#include "includes.h" 

#include "hardware.h" 
#include "example3.h" 

static uint8_t isr_second_tick_u8; /* Incremented every 1 mS by IRQ */

/*
 * ZDS-II Board comes up with Light Up The World attitude.  74HC273 should have
 * been used.  Turn all of them off.
 */
void turn_off_digit_leds(void);
void turn_off_digit_leds(void)
{
    PEDD   = 0x00;  /* Data Direction,            0 = Output Direction */
    PEAF   = 0x00;  /* Alternate Function,        0 = Normal/Follow DDx bit */
    PEOC   = 0x00;  /* Output Control,            1 = Open Drain */
    PEHDE  = 0x00;  /* High Drive Enable,         1 = High Current Drive */
    PESMRE = 0x00;  /* Stop Mode Recovery Enable, 1 = Stop Mode Recovery Source */
    PEOUT  = 0x1F;  /* Output,                    1 = Logical High Output */

    PGDD   = 0x00;  /* Data Direction,            0 = Output Direction */
    PGAF   = 0x00;  /* Alternate Function,        0 = Normal/Follow DDx bit */
    PGOC   = 0x00;  /* Output Control,            1 = Open Drain */
    PGHDE  = 0x00;  /* High Drive Enable,         1 = High Current Drive */
    PGSMRE = 0x00;  /* Stop Mode Recovery Enable, 1 = Stop Mode Recovery Source */
    PGOUT  = 0x00;  /* Output,                    1 = Logical High Output */

    LED_D1_CLOCK();
    LED_D2_CLOCK();
    LED_D3_CLOCK();
    LED_D4_CLOCK();
}

/*
 * This Timer ISR get called every 250 mS.
 * It is the system base 'tick'.
 * It is divided by two to get a one second square wave.
 */
#define SECOND_PRESCALE (2) 
#pragma interrupt 
void isr_timer0(void)
{
    static uint8_t second_prescale_u8 = 0;

    DISABLE_INTERRUPTS();
    IRQ0ENH &= (uint8_t) ~T0ENH;     /* Disable Timer0 Interrupts */
    IRQ0ENL &= (uint8_t) ~T0ENL;
    ENABLE_INTERRUPTS();

    if( 0 == second_prescale_u8-- )
	{
	    second_prescale_u8 = SECOND_PRESCALE;
	    ++isr_second_tick_u8;		     /* Use counter instead of flag, so ticks will not be missed */
	}

    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 250 mS.
 *
 * FREQ18432 18,432,000 Hz
 * Time-Out Period (s) = (Reload Value * Prescale)/ System Clock (Hz)
 *
 */
#define TIMER0_RELOAD (36000)	      /* = (18,432,000/(1/250mS))/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 */
}

int main()
{

    DISABLE_INTERRUPTS();

    /* Setup I/O ports: */
    turn_off_digit_leds();

    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_second_tick_u8 = 0; /* Not really needed but keeps Lint happy */
    init_timer0();

    Example3_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).
    */
    Example3(); /* Iniz the Esterel code */

    /* Interrupts will be enabled in the main()line code, no need to do here. */

    for(;;)/*ever*/
    {
	DISABLE_INTERRUPTS();
	if( TRUE == SW1_ASSERTED() )
	    Example3_I_SW1_ASSERTED(); /* Let the Esterel code know that SW1 has been asserted */

	if( TRUE == SW2_ASSERTED() )
	    Example3_I_SW2_ASSERTED(); /* Let the Esterel code know that SW2 has been asserted */

	if( isr_second_tick_u8 > 0 )
	{
	    --isr_second_tick_u8;

	    Example3_I_Second_Tick();
	}
	ENABLE_INTERRUPTS();

	Example3();    /* Call the Esterel Automation code.
			* It must be called at least as often as the 'system
			* tick() [1 mS] happens.
			*/
    }
}