/** @(#)main.c Created on: <30-Nov-2003 06:52:44 Z4303>
* Last Time-stamp: <30-Nov-2003 10:27:20 Z4303>
*
* \file main.c
* \ingroup Esterel Automation
* \brief main() for Esterel Reflex Game Demonstration.
*
*/
/*lint -save */
#include "includes.h"
#define DEFINE_SPACE_MAIN_H (1)
#include "main.h"
#include "hardware.h"
#include "debounce.h"
#include "led_digits.h"
#include "reflex_game.h"
static uint8_t isr_ms_tick_u8; /* Incremented every 1 mS by IRQ */
static uint8_t isr_coin_u8; /* Incremented by press of the 'coin' button */
/*
* This Timer ISR get called every 1 mS.
* It is the system base 'tick'.
*/
#pragma interrupt
void isr_timer0(void)
{
DISABLE_INTERRUPTS();
IRQ0ENH &= (uint8_t) ~T0ENH; /* Disable Timer0 Interrupts */
IRQ0ENL &= (uint8_t) ~T0ENL;
ENABLE_INTERRUPTS();
++isr_ms_tick_u8; /* Use counter instead of flag, so ticks will not be missed */
++random_number_u16; /* Used to generate a random number of mS for pseudo-random delay */
DISABLE_INTERRUPTS();
IRQ0ENL |= T0ENL; /* IRQ0 Enable; Timer0 is programed to Level-1/Low priority */
ENABLE_INTERRUPTS();
}
/*
* Initialize Timer-0 for continuous mode,
* and for interrupts to occur every 1ms.
*
* FREQ18432 18,432,000 Hz
* Time-Out Period (s) = (Reload Value * Prescale)/ System Clock (Hz)
*
*/
#define TIMER0_RELOAD (144) /* = (18,432,000/(1/1mS))/128 */
#define TIMER0_RELOAD_HIGH (TIMER0_RELOAD>>8)
#define TIMER0_RELOAD_LOW (TIMER0_RELOAD & 0xFF)
void init_timer0(void);
void init_timer0(void)
{
SET_VECTOR(TIMER0, isr_timer0); /* Pass the vector number and the ISR
* address to be placed into the interrupt
* table
*/
T0H = 0x00; /* Timer High */
T0L = 0x00; /* Timer Low */
T0CPH = TIMER0_RELOAD_HIGH; /* Reload Compare High and Low */
T0CPL = TIMER0_RELOAD_LOW; /* To get 1ms time period */
IRQ0ENH &= (uint8_t) ~T0ENH; /* Set Timer0 for Level-1/Low priority */
IRQ0ENL |= T0ENL;
T0CTL = (TEN|TPRESCALE128|TMODE_CONTINUOUS); /* Timer Enable */
}
/*
* Timer1 ISR called to update LED Display.
*/
#pragma interrupt
void isr_timer1(void)
{
DISABLE_INTERRUPTS();
IRQ0ENH &= (uint8_t) ~T1ENH; /* Disable Timer1 Interrupts */
IRQ0ENL &= (uint8_t) ~T1ENL;
ENABLE_INTERRUPTS();
isr_led_digits_timer();
DISABLE_INTERRUPTS();
IRQ0ENH |= T1ENH; /* IRQ Enable; Timer1 is programed to Level-2/Medium priority */
ENABLE_INTERRUPTS();
}
#define TIMER1_RELOAD (4608)
#define TIMER1_RELOAD_HIGH (TIMER0_RELOAD>>8)
#define TIMER1_RELOAD_LOW (TIMER0_RELOAD & 0xFF)
void init_timer1(void);
void init_timer1(void)
{
SET_VECTOR(TIMER1, isr_timer1); /* Pass the vector number and the ISR
* address to be placed into the interrupt
* table
*/
T1H = 0x00; /* Timer High */
T1L = 0x00; /* Timer Low */
T1CPH = TIMER1_RELOAD_HIGH; /* Reload Compare High and Low */
T1CPL = TIMER1_RELOAD_LOW; /* To get 1ms time period */
IRQ0ENH |= T1ENH; /* Set Timer1 for Level-2/Medium priority */
IRQ0ENL &= (uint8_t) ~T1ENL;
T1CTL = (TEN|TPRESCALE64|TMODE_CONTINUOUS); /* Timer Enable */
}
#pragma interrupt
void isr_coin_button(void) /* Restart game at any time if 'coin is inserted' */
{
++isr_coin_u8;
}
void init_coin_button(void);
void init_coin_button(void)
{
IRQPS |= PAD3S; /* Interrupt Port Select Register (IRQPS), Select PD3 as IRQ */
SET_VECTOR(P3AD, isr_coin_button);
IRQ1ENH |= PAD3EN; /* Set Interrupt Level-3/High priority*/
IRQ1ENL |= PAD3EN;
}
int main()
{
uint8_t buttons_u8;
DISABLE_INTERRUPTS();
/* Setup I/O ports: */
PFDD = (PF7|PF6); /* Data Direction, 0 = Output Direction, PF6&5 are inputs */
PFAF = 0x00; /* Alternate Function, 0 = Normal/Follow DDx bit */
PFOC = 0x00; /* Output Control, 1 = Open Drain */
PFHDE = 0xFF; /* High Drive Enable, 1 = High Current Drive */
PFSMRE = 0x00; /* Stop Mode Recovery Enable, 1 = Stop Mode Recovery Source */
PFOUT = 0x00; /* Output, 1 = Logical High Output, PF6&5 are inputs */
isr_ms_tick_u8 =
isr_coin_u8 = 0;
init_timer0();
init_timer1();
init_timer2();
init_coin_button();
led_digits_all_off();
REFLEX_GAME_reset(); /* Reset the Esterel code */
/*
* Programs often contain instantaneous initial statements, such
* as signal emissions or variable initializations, to be performed
* during the first reaction. To perform them, it is often useful
* (but not mandatory) to generate a blank initial event by calling
* the reaction function before calling any input C function. (This
* boot transition is different from the automaton reset).
*/
REFLEX_GAME(); /* Iniz the Esterel code */
/* Interrupts will be enabled in the main()line code, no need to do here. */
for(;;)/*ever*/
{
/*
* Interrupts are disabled briefly because the Esterel Automation code
* expects all inputs to be stable for the duration of its execution.
* Counters that are incremented by interrupts are decremented here
* in the main()line code.
*
* By using counters instead of flags, multiple IRQs will not be
* missed, because they might have been preempted by a higher
* priority interrupt. Doing a tick a bit late is better than
* missing the tick for this project.
*
*/
DISABLE_INTERRUPTS();
if( isr_coin_u8 > 0 )
{
--isr_coin_u8;
REFLEX_GAME_I_COIN();
}
if( isr_ms_tick_u8 > 0 )
{
--isr_ms_tick_u8;
REFLEX_GAME_I_MS();
}
ENABLE_INTERRUPTS();
buttons_u8 = debounce_buttons( BUTTONS_IN );/* Register buttons as edge
* sensitive rather than level sensitive.
* Using level sensing
* rather than edge sensing can cause
* race conditions in the
* Esterel Automation code.
*/
if( BUTTON_READY & buttons_u8 )/* Is the button asserted? */
{/* Yes */
display_rdy(); /* Let the human know the button 'took' when it was pressed */
REFLEX_GAME_I_READY(); /* Let the Esterel code know that SW2/READY has been asserted */
}
if( BUTTON_STOP & buttons_u8 )/* Is the button asserted? */
{/* Yes */
REFLEX_GAME_I_STOP(); /* Let the Esterel code know that SW1/STOP has been asserted */
}
REFLEX_GAME(); /* Call the Esterel Automation code.
* It must be called at least as often as the 'system
* tick() happens, 1 mS in this example.
*/
}
}
/*lint -restore */