// CrossWorks Tasking Library.
//
// CTL support for the ATMEL AT91SAM9XE-EK evaluation board
//
// Copyright (c) 2009 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.

#include <ctl_api.h>
#include <targets/AT91SAM9XE512.h>

#define LEDS (1<<6)
#define BUTTONS (1<<30)|(1<<31)

void
ctl_board_init(void)
{
  PMC_PCER |= PMC_PCER_PIOA; // enable PIOA peripheral clock
  PIOA_PER = LEDS; // Set in PIO mode
  PIOA_OER = LEDS; // Configure in Output
}

static CTL_ISR_FN_t userButtonISR;
void
buttonISR(void)
{
  unsigned long isr = PIOA_ISR;
  unsigned long pdsr = PIOA_PDSR;
  userButtonISR();  
}

void 
ctl_board_on_button_pressed(CTL_ISR_FN_t buttonFn)
{
  userButtonISR = buttonFn;

  // Setup PIO
  PIOA_ODR = BUTTONS;
  PIOA_PER = BUTTONS;
  PIOA_MDDR = ~BUTTONS;
  PIOA_MDER = BUTTONS;
  PIOA_IER = BUTTONS;
  ctl_set_isr(2, 0, CTL_ISR_TRIGGER_LOW_LEVEL, buttonISR, 0);
  ctl_unmask_isr(2);
}

void
ctl_board_set_leds(unsigned v)
{
  if (v)
    PIOA_SODR = LEDS;
  else
    PIOA_CODR = LEDS;
}

void
delay(volatile unsigned int d)
{
  d *= 10;
  for (;d ;--d);
}

static CTL_ISR_FN_t timerFn;

static void
timerISR(void)
{
  timerFn();
  PIT_PIVR; // clear PITS
}

#define MCLK_KHz 99328 // 198.656/2

void
ctl_start_timer(CTL_ISR_FN_t t)
{
  timerFn = t;
  PIT_MR = ((MCLK_KHz/16)*10) | PIT_MR_PITEN | PIT_MR_PITIEN; // interrupt every 10 ms
  PIT_PIVR; // clear PITS
#ifdef CTL_TASKING
  ctl_time_increment = 10; // so increment the counter by 10 to get the ms counter
#endif    
  ctl_set_isr(1, 1, CTL_ISR_TRIGGER_HIGH_LEVEL, timerISR, 0);
  ctl_unmask_isr(1);
}

unsigned long
ctl_get_ticks_per_second(void)
{
#ifdef CTL_TASKING
  return 1000;
#else
  return 100;
#endif
}

#define AT91C_SDRAM (*(volatile unsigned int *)0x20000000)

void
init_sdram_pll()
{
  unsigned i;

  // Enable the main oscillator
  CKGR_MOR = 0x801;
  while (!(CKGR_MCFR & CKGR_MCFR_MAINRDY));
  PMC_MCKR = 1;

  // Set Flash wait states
  EEFC_FMR = 0x200;

  // Set up PLL A
  CKGR_PLLAR = 0x20603F09; // MULA=97, DIVA=9 - 18.432*97/9 = 198.656
  while (!(PMC_SR & PMC_SR_LOCKA));
  // Use PLL A as processor clock and master clock divided by 2
  PMC_MCKR = 0x00000102;

  // select 32 bit data bus
  PIOC_PDR = 0xFFFF0000; 
  PIOC_ASR = 0xFFFF0000;

  // assign EBI CSA1 to SDRAM
  EBI_CSA |= EBI_CSA_EBI_CS1A;

  // SDRAM timings and configuration
  SDRAMC_CR = 0x85227259;

  for (i =0; i< 1000;i++);
  
  // "All Banks Precharge"
  SDRAMC_MR = 2;
  AT91C_SDRAM = 0;          

  for (i =0; i< 1000;i++);

  // 8 "Auto Refresh Commands"
  for (i=0;i<8;i++)
    {
      SDRAMC_MR = 4;
      AT91C_SDRAM = 0;
    }
  // "Load Mode Register"
  SDRAMC_MR = 3;
  AT91C_SDRAM = 0;  
  // Set Refresh Rate to 7.8 us
  SDRAMC_TR = 780;
  // Switch to normal mode
  SDRAMC_MR = 0;
  AT91C_SDRAM = 0;

  // map SRAM to address zero
  MATRIX_MRCR = 0x3;
}

