// CrossWorks Tasking Library.
//
// Copyright (c) 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.

#include <targets/AX07CF192.h>
#include "ctl_api.h"

#define INTERRUPT_SOURCE_COUNT 21
  
static CTL_ISR_FN_t vectors[INTERRUPT_SOURCE_COUNT];
static unsigned int currentVector;

void irq_handler(void) __attribute__((naked));

void
irq_handler(void)
{
  asm("stmfd sp!, {r0-r12, lr}"); 
  asm("mrs r0, spsr");
  asm("stmfd sp!, {r0}");
  ctl_interrupt_count++;
  for (currentVector = 0; currentVector < INTERRUPT_SOURCE_COUNT; ++currentVector)
    if (ISR & 1 << currentVector)
      {
        ISCR = 1 << currentVector;
        IMR |= 1 << currentVector;
        vectors[currentVector]();
        IMR &= ~(1 << currentVector);
        break;
      }
  asm("mov r0, sp");
  asm("ldr r1, =ctl_exit_isr");
  asm("bx r1");
}

int
ctl_set_isr(unsigned int vector, unsigned int priority, CTL_ISR_TRIGGER_t trigger, CTL_ISR_FN_t isr, CTL_ISR_FN_t *oldisr)
{
  if (oldisr)
    *oldisr = vectors[vector];
  vectors[vector] = isr;
  switch (trigger)
    {
      case CTL_ISR_TRIGGER_LOW_LEVEL:
        TMR |= 1 << vector;
        TPR &= ~(1 << vector);
        break;
      case CTL_ISR_TRIGGER_HIGH_LEVEL:
        TMR |= 1 << vector;
        TPR |= 1 << vector;
        break;
      case CTL_ISR_TRIGGER_POSITIVE_EDGE:
        TMR &= ~(1 << vector);
        TPR |= 1 << vector;
        break;
      case CTL_ISR_TRIGGER_NEGATIVE_EDGE:
      default:
        TMR &= ~(1 << vector);
        TPR &= ~(1 << vector);
        break;
    }
  IDR &= ~(1 << vector); /* IRQ Interrupt */
  return 1;
}

int
ctl_unmask_isr(unsigned int vector)
{
  GMR &= ~(1 << vector);
  IMR &= ~(1 << vector);
  return 1;
}

int
ctl_mask_isr(unsigned int vector)
{
  GMR |= 1 << vector;
  return 1;
}
