Support KL25z requirements

Dependents:   kl25z_Usb_Logger

Fork of RTC by Erik -

RTC.cpp

Committer:
Sissors
Date:
2012-12-05
Revision:
0:39767ffe05e6
Child:
1:be9d058ee5c7

File content as of revision 0:39767ffe05e6:

#include "RTC.h"

FunctionPointer RTC::attachCB[6];
FunctionPointer RTC::alarmCB;

bool RTC::initialRun = true;

void RTC::attach(void (*function)(void), TimeUnit interval)
{
    //Disable IRQs, dont want them to happen while busy here
    NVIC_DisableIRQ(RTC_IRQn);

    //Set the IRQ vector
    NVIC_SetVector(RTC_IRQn, (uint32_t)&RTC::IRQHandler);

    //If this is the first time it is called, delete all interrupt sources
    //We need to do this because RTC unit isnt affected by system resets apparently
    if (initialRun) {
        LPC_RTC->CIIR = 0;
        LPC_RTC->AMR = 255;
        initialRun = false;
        LPC_RTC->ILR = 0x03;
    }

    //Set the function pointer
    attachCB[interval].attach(function);


    //Set/reset correct interrupt source
    if (function == NULL) {
        switch (interval) {
            case Second:
                LPC_RTC->CIIR &= ~1;
                break;
            case Minute:
                LPC_RTC->CIIR &= ~2;
                break;
            case Hour:
                LPC_RTC->CIIR &= ~4;
                break;
            case Day:
                LPC_RTC->CIIR &= ~56;
                break;
            case Month:
                LPC_RTC->CIIR &= ~64;
                break;
            case Year:
                LPC_RTC->CIIR &= ~128;
                break;
        }
    } else {
        switch (interval) {
            case Second:
                LPC_RTC->CIIR |= 1;
                break;
            case Minute:
                LPC_RTC->CIIR |= 2;
                break;
            case Hour:
                LPC_RTC->CIIR |= 4;
                break;
            case Day:
                LPC_RTC->CIIR |= 56;
                break;
            case Month:
                LPC_RTC->CIIR |= 64;
                break;
            case Year:
                LPC_RTC->CIIR |= 128;
                break;
        }
    }

    //We can always enable IRQs, since if all IRQs are disabled by the user the RTC hardware will never raise its IRQ flag anyway
    NVIC_EnableIRQ(RTC_IRQn);
}


void RTC::alarm(void (*function)(void), tm time)
{
    //Disable IRQs, dont want them to happen while busy here
    NVIC_DisableIRQ(RTC_IRQn);

    //Set the IRQ vector
    NVIC_SetVector(RTC_IRQn, (uint32_t)&RTC::IRQHandler);

    //If this is the first time it is called, delete all interrupt sources
    //We need to do this because RTC unit isnt affected by system resets apparently
    if (initialRun) {
        LPC_RTC->CIIR = 0;
        LPC_RTC->AMR = 255;
        initialRun = false;
        LPC_RTC->ILR = 0x03;
    }

    //Set the function pointer
    alarmCB.attach(function);
    
    //Set the alarm register
    if ((time.tm_sec>=0) && (time.tm_sec<60)) {
        LPC_RTC->ALSEC = time.tm_sec;
        LPC_RTC->AMR &= ~1;
    } else
        LPC_RTC->AMR |= 1;

    if ((time.tm_min>=0) && (time.tm_min<60)) {
        LPC_RTC->ALMIN = time.tm_min;
        LPC_RTC->AMR &= ~2;
    } else
        LPC_RTC->AMR |= 2;

    if ((time.tm_hour>=0) && (time.tm_hour<24)) {
        LPC_RTC->ALHOUR = time.tm_hour;
        LPC_RTC->AMR &= ~4;
    } else
        LPC_RTC->AMR |= 4;

    if ((time.tm_mday>=1) && (time.tm_mday<32)) {
        LPC_RTC->ALDOM = time.tm_mday;
        LPC_RTC->AMR &= ~8;
    } else
        LPC_RTC->AMR |= 8;        
        
    if ((time.tm_mon>=0) && (time.tm_mon<12)) {
        LPC_RTC->ALMON = time.tm_mon + 1;   //Different definitions
        LPC_RTC->AMR &= ~64;
    } else
        LPC_RTC->AMR |= 64;    

    if ((time.tm_year>=0) && (time.tm_year<1000)) {
        LPC_RTC->ALYEAR = time.tm_year + 1900;   //Different definitions
        LPC_RTC->AMR &= ~128;
    } else
        LPC_RTC->AMR |= 128;
        
    //We can always enable IRQs, since if all IRQs are disabled by the user the RTC hardware will never raise its IRQ flag anyway
    NVIC_EnableIRQ(RTC_IRQn);
}

void RTC::alarmOff( void ) {
    LPC_RTC->AMR = 255;
    }


void RTC::IRQHandler( void )
{
    if ((LPC_RTC->ILR & 0x01) == 0x01) {
        //Attach interrupt
        attachCB[0].call();

        //If seconds zero
        if (LPC_RTC->SEC == 0) {
            attachCB[1].call();

            //If minutes zero
            if (LPC_RTC->MIN == 0) {
                attachCB[2].call();

                //If hours zero
                if (LPC_RTC->HOUR == 0) {
                    attachCB[3].call();

                    //If days zero
                    if (LPC_RTC->DOM == 0) {
                        attachCB[4].call();

                        //If month zero
                        if (LPC_RTC->MONTH == 0)
                            attachCB[5].call();
                    }
                }
            }
        }
    }

    if ((LPC_RTC->ILR & 0x02) == 0x02)
        alarmCB.call();



    //Reset interrupt status
    LPC_RTC->ILR = 0x03;
}