//-----------------------------------
// File:          timer0.c
// Function:      Timing measurement using TIMER0
// Supported chip(s):
//    - AT91SAM7XC128
//    - AT91SAM7XC256
// Supported toolchain(s):
//    - IAR Embedded Workbench
// Date created:  05 June 2006
// Created by:    JJo
//-----------------------------------

//-----------------------------------
// Includes

#include "timer0.h"

#ifdef USE_TIMER0

//-----------------------------------
// Global variables

volatile unsigned int timestamp;
unsigned int measurement;
unsigned int start;

//-----------------------------------
// Interrupts

/**
 * Name:      timer0_handler
 * Purpose:   IRQ handler for timer 0 interrupt
 */
void timer0_handler() {

  TIMER->TC_SR;
  timestamp++;
}

//-----------------------------------
// Functions

/**
 * Name:      timer0_init
 * Purpose:   Initializes timer 0
 */
void timer0_init() {

  debug_printf("Timer0: Initializing ...\n");

  // Configure PMC and PIO
  AT91F_TC0_CfgPMC();
  AT91F_TC0_CfgPIO();

  // Configure timer
  TIMER->TC_CMR = AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO;
  TIMER->TC_RC = COUNTER_VALUE;

  AT91F_TC_InterruptEnable(TIMER, AT91C_TC_CPCS);
  // Interrupt
  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC,
                        AT91C_ID_TC0,
                        AT91C_AIC_PRIOR_HIGHEST,
                        AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL,
                        timer0_handler);
  AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_TC0);

  // Reset timestamp
  timestamp = 0;
  measurement = 0;

  // Start timer
  TIMER->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;

  debug_printf("Timer0: Initialization done.\n");
}

/**
 * Name:      timer0_cleanup
 * Purpose:   Cleanup of timer 0
 */
void timer0_cleanup() {

  debug_printf("Timer0: Cleaning up ...\n");

  TIMER->TC_CCR = AT91C_TC_CLKDIS;
  TIMER->TC_CMR = 0;
  TIMER->TC_IDR = 0x000000FF;
  TIMER->TC_RC = 0;
  AT91F_AIC_DisableIt(AT91C_BASE_AIC, AT91C_ID_TC0);
  AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_TC0, 0, 0, 0);
  AT91F_PMC_DisablePeriphClock(AT91C_BASE_PMC, 1 << AT91C_ID_TC0);
  AT91F_PIO_CfgOutput(AT91C_BASE_PIOB, AT91C_PB23_TIOA0 | AT91C_PB24_TIOB0 | AT91C_PB12_TCLK0);

  debug_printf("Timer0: Cleanup done.\n");
}

/**
 * Name:      timer0_start
 * Purpose:   Starts a timing measurement
 */
void timer0_start() {

  measurement = 0;
  start = timestamp;
}

/**
 * Name:      timer0_resume
 * Purpose:   Resumes a timing measurement
 */
void timer0_resume() {

  start = timestamp;
}

/**
 * Name:      timer0_stop
 * Purpose:   Stops or ends a timing measurement
 */
void timer0_stop() {

  measurement += timestamp - start;
}

/**
 * Name:      timer0_get
 * Purpose:   Retrieve the current timing measurement
 * Output:    Current timing measurement
 */
unsigned int timer0_get() {
  
  return measurement;
}

#endif // USE_TIMER0
