//
// Timer Compare Interrupt
// By PEK '2006
//
// MCU: AT91SAM7S256
// Experiment board: AT91SAM7S-EK
//

#include "Board.h"

// Macros
#define SET_LED(x)  AT91C_BASE_PIOA->PIO_ODSR = (x)

// Definitions
#define INT_LEVEL_TIMER     4           // Priority of interrupt
#define TIME_PERIOD         MCK/1024/5   // Period of 200 ms

void compare_isr(void)
{
    static unsigned char ucCntr = 0;
    volatile unsigned int uiStat;

    uiStat = AT91C_BASE_TC0->TC_SR;    // Interrupt Acknowledge

    SET_LED(~ucCntr);
    ucCntr++;
}

int main()
{
    // Setup PIO
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA;  // Enable clock to PIO
    AT91C_BASE_PIOA->PIO_OER = LED_MASK;    // Output on PA0-PA3
    AT91C_BASE_PIOA->PIO_OWER = LED_MASK;   // Enable to set/clear PA0-PA3 with status register
    SET_LED(0xF); // Clear leds

    // Setup TC0
    AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC0;   // Enable clock to TC0
    AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV5_CLOCK | AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO;    // Prescaler set to 1024, Compare mode on RC
    AT91C_BASE_TC0->TC_RC = TIME_PERIOD;   // Compare value of RC
    AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; // Enable timer

    // Setup interrupts
    AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0, INT_LEVEL_TIMER, AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE, compare_isr);
    AT91C_BASE_TC0->TC_IER  = AT91C_TC_CPCS;  //  IRQ enable CPC
    AT91C_BASE_AIC->AIC_IECR = 1 << AT91C_ID_TC0;   // Enable interrupt in AIC

    AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;    // Start timer

    while(1);
}
