Main Page   Modules   Data Structures   File List   Data Fields   Globals   Related Pages  

Software Real Time Clock.

// Built with BFTC Rev. 1.0.0, ven 20 marzo 2015 16:28:27
/*
    Copyright 2014-2015 Digital Technology Art SRL
    This file is part of Blackfin Toolchain (BFTC) project.

    BFTC is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    BFTC is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Nome-Programma.  If not, see <http://www.gnu.org/licenses/>.
*/

// Simple implementation of a software RTC (Real Time Clock)
// Inspired by Leonardo Miliani work swRTC
//

#include "main.h"

typedef struct RTCdata {
    unsigned char   hours;
    unsigned char   minutes;
    unsigned char   seconds;
    unsigned char   day;
    unsigned char   month;
    int             year;
    unsigned char   daysPerMonth[12];
}RTCdata;

RTCdata rtc;

bool isLeapYear(int yearT) 
{
    if(((yearT % 4) == 0) && ((yearT % 100) != 0) || ((yearT % 400) == 0)) 
        return true;
    return false;
}

void rtcInit(RTCdata * t)
{
    t->daysPerMonth[0]  = 31;    // January
    t->daysPerMonth[1]  = 28;    // February
    t->daysPerMonth[2]  = 31;    // March
    t->daysPerMonth[3]  = 30;    // April
    t->daysPerMonth[4]  = 31;    // May
    t->daysPerMonth[5]  = 30;    // June
    t->daysPerMonth[6]  = 31;    // July
    t->daysPerMonth[7]  = 31;    // August
    t->daysPerMonth[8]  = 30;    // September
    t->daysPerMonth[9]  = 31;    // October
    t->daysPerMonth[10] = 30;    // November
    t->daysPerMonth[11] = 31;    // December
    
    t->hours = 0;
    t->minutes = 0;
    t->seconds = 0;
    t->day = 1;
    t->month = 1;
    t->year = 2000;
}

bool setTime(unsigned char hourT, unsigned char minuteT, unsigned char secondT, RTCdata * t) 
{
    //check if the params are correct
    if(hourT > 23)      return false;
    if(minuteT > 59)    return false;
    if(secondT > 59)    return false;

    t->hours = hourT;
    t->minutes = minuteT;
    t->seconds = secondT;
    return true;
}

bool setDate(unsigned char dayT, unsigned char monthT, int yearT, RTCdata * t) 
{
    //check if the params are correct
    if((dayT < 1) || (dayT > 31))       return false;
    if((monthT < 1) || (monthT > 12))   return false;
    if(yearT < 0)                       return false;

    t->day = dayT;
    t->month = monthT;
    t->year = yearT;
    return true;
}

unsigned long getTimestamp(int yearT, RTCdata * t)
{
    int     i;
    unsigned long time = 0;

    //check the epoch
    if(yearT == 0)
        yearT = 1970;
        else 
            if(yearT < 1900)
                yearT = 1900;
            else 
                if(yearT > 1970)
                    yearT = 1970;
                else 
                    if((yearT != 1900) && (yearT != 1970))
                        yearT = 1970;

    //One revolution of the Earth is not 365 days but accurately 365.2422 days.
    //It is leap year that adjusts this decimal fraction. But...
    time += (t->year - yearT) * 365.2422;
    for(i = 0; i < t->month - 1; i++)
        time += t->daysPerMonth[i];     // find day from month

    time = (time + t->day) * 24UL;      // find hours from day
    time = (time + t->hours) * 60UL;    // find minutes from hours
    time = (time + t->minutes) * 60UL;  // find seconds from minute
    time += t->seconds;                // add seconds
    if(time > 951847199UL)
        time += 86400UL;                // year 2000 is a special leap year, so 1 day must be added if date is greater than 29/02/2000
    return (time - 86400UL);            // because years start at day 0.0, not day 1.
}

// Set the internal clock using a timestamp using the epoch passed as argument
unsigned char setClockWithTimestamp(unsigned long timeT, int yearRef, RTCdata * t) 
{
    int             yearT, monthT, hoursT, minutesT;
    unsigned long   dayT;
    float           remaining, dayRemaining;

    if(timeT > 951847199UL) 
        timeT -= 86400UL;   // year 2000 is a special leap year, so 1 day must be added if date is greater than 29/02/2000
    timeT += 86400UL;       // days in the calendar start from Jan., 1 not from Jan., 0
    dayT = timeT / (60UL * 60UL * 24UL);
    remaining = timeT - dayT * (60UL * 60UL * 24UL);
    yearT = (dayT / 365.2422);
    dayRemaining = dayT - yearT * 365.2422;

    if(yearRef == 0)
        yearRef = 1970;
    else 
        if(yearRef < 1900)
            yearRef = 1900;
        else 
            if(yearRef > 1970)
                yearRef = 1970;
            else 
                if((yearRef != 1900) && (yearRef != 1970))
                    yearRef = 1970;

    yearT += yearRef;
    if(dayRemaining >= 365.2422)
        return 1;   // my math is wrong!

    if(yearT < yearRef)
        return 2;   // year not supported!

    monthT = 0;
    while(dayRemaining > t->daysPerMonth[monthT])
    {
        dayRemaining -= t->daysPerMonth[monthT];
        if(monthT == 1 && isLeapYear(yearT))
            dayRemaining--;
        monthT++;
    }

    monthT++;       // because month 0 doesn't exist
    if(monthT > 12)
        return 3;   // my math is wrong!

    if(dayRemaining >= (60UL * 60UL * 24UL))
        return 4;   // my math is wrong!

    dayT = dayRemaining;
    if(dayRemaining - dayT > 0)
        // add partial day!
        dayT++;
    
    hoursT = remaining / (60UL * 60UL);
    remaining = remaining - hoursT * (60UL * 60UL);
    if(remaining >= (60UL * 60UL))
        return 5;   // my math is wrong!

    minutesT = remaining / 60UL;
    remaining = remaining - minutesT * 60UL;
    if(remaining >= 60)
        return 6;   // my math is wrong!

    t->year = yearT;
    t->month = monthT;
    t->day = dayT;
    t->hours = hoursT;
    t->minutes = minutesT;
    t->seconds = remaining;
    return 0;
}

unsigned char weekDay(unsigned long timestamp) 
{
    return ((timestamp / 86400UL) + 4 ) % 7;
}

unsigned char getWeekDay(RTCdata * t) 
{
    return (weekDay(getTimestamp(0, t)));
}

// RTC handler
void RTC(RTCdata * t)
{
    unsigned char dayT;
    t->seconds++;
    if(rtc.seconds > 59) 
    {
        t->seconds = 0;
        t->minutes++;
        if(t->minutes > 59) 
        {
            t->minutes = 0;
            t->hours++;
            if(t->hours > 23) 
            {
                t->hours = 0;
                t->day++;
                if(t->month == 2) 
                { 
                    //february?
                    if(isLeapYear(t->year)) 
                        dayT = 29;
                    else 
                        dayT = 28;
                } 
                else 
                    dayT = t->daysPerMonth[t->month - 1];
                if(t->day > dayT) 
                {
                    t->day = 1;
                    t->month++;
                    if(t->month > 12) 
                    {
                        t->month = 1;
                        t->year++;
                    }
                }
            }
        }
    }
}

void BackgroundProcess()
{
    RTC(&rtc);
    printf("%4d/%02d/%02d - %02d:%02d:%02d: TS = %d\n", rtc.year, rtc.month, rtc.day, rtc.hours, rtc.minutes, rtc.seconds, getTimestamp(0, &rtc));
}

int main(void)
{
    Set_PLL(16, 4);             // CORE: 25MHz * 16 = 400MHz, SCLK: 400MHz / 4 = 100MHz
    Set_Port();                 // Set the port according to project set
    Set_Uart0(115200);  // printf is redirected to UART0
    
    Set_TimerInterruptService(TIMER_0, &BackgroundProcess, 1000000);
    Set_TimerEnable(TIMER_0, true);
    
    rtcInit(&rtc);
    
    rtc.year = 2015;
    rtc.month = 3;
    rtc.day = 20;
    rtc.hours = 19;
    rtc.minutes = 35;
    rtc.seconds = 23;
    
    while(1)                    // Main loop
    {
        // What can I do?
    }
    return 0;
}

Generated on Tue Apr 7 20:07:44 2015 for BF592A Library by doxygen 1.3.1