/** @(#)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 */