// Copyright (c) 2001-2004 Rowley Associates Limited.
//
// This file may be distributed under the terms of the License Agreement
// provided with this software.
//
// THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
////////////////////////////////////////////////////////////////////////////////
//
//                  Atmel AT91RM9200 Timer Interrupt Example
//
// Description
// -----------
// This example demonstrates a simple interrupt handler and setting up a timer.
//
////////////////////////////////////////////////////////////////////////////////

#include <targets/AT91RM9200.h>

#define LED (1 << 2)

// Interrupt definitions
#define AIC_SMR(n) (*(&AIC_SMR0 + n))
#define AIC_SVR(n) (*(&AIC_SVR0 + n))

#define AIC_SRCTYPE_INT_LEVEL_SENSITIVE 0x00    /* Level Sensitive */
#define AIC_SRCTYPE_INT_EDGE_TRIGGERED  0x20    /* Edge Triggered */

#define TC0_ID 17

static int count;

static void
ledInit(void)
{
  PIOB_PER = LED;
  PIOB_OER = LED;
}

static void
ledOn(void)
{
  PIOB_CODR = LED;
}

static void
ledOff(void)
{
  PIOB_SODR = LED;
}

void timer_irq_handler(void) __attribute__ ((interrupt ("IRQ")));

void
timer_irq_handler(void)
{
  TC0_SR;
  if (count++ & 1)
    ledOn();
  else
    ledOff();

  // Signal end of interrupt
  AIC_EOICR = 0;
}

int
main(void)
{
  // Setup LEDs
  ledInit();

  // Set up timer interrupt
  __ARMLIB_enableIRQ();
  AIC_IDCR = 1 << TC0_ID;
  AIC_SVR(TC0_ID) = (unsigned)timer_irq_handler;
  AIC_SMR(TC0_ID) = AIC_SRCTYPE_INT_LEVEL_SENSITIVE;
  AIC_ICCR = 1 << TC0_ID;
  AIC_IECR = 1 << TC0_ID;

  // Set up timer
  PMC_PCER = 1 << TC0_ID; // Enable T0 peripheral clock
  TC0_CCR = TC0_CCR_CLKDIS_MASK;
  TC0_IDR = 0xFFFFFFFF;
  TC0_CMR = 3; /* Timer clock 4  */
  TC0_IER = TC0_IER_COVFS_MASK;
  TC0_CCR = TC0_CCR_CLKEN | TC0_CCR_SWTRG;

  while (count < 5);

  return 0; 
}

