Kevin Braun / Mbed 2 deprecated ds3232m_HelloWorld

Dependencies:   ds3232m mbed mbed-rtos

main.cpp

Committer:
loopsva
Date:
2014-12-23
Revision:
2:958004aa28a4
Parent:
1:c891c3930f4e
Child:
3:f0eb506d4add

File content as of revision 2:958004aa28a4:

#include "mbed.h"
//#include "rtos.h"                           //mbed rtos - uncomment to make RTOS available
#include "ds3232m.h"                        //Maxim RTC

RawSerial pc(USBTX, USBRX);                 //onsole interface

#ifdef RTOS_H
Mutex MutexI2C0;                            //lock/unlock I2C requests
#endif  //RTOS_H

#define SDA0        PTE25
#define SCL0        PTE24
ds3232m rtc(SDA0, SCL0, 400000);            //Maxim real time clock

//--------------------------------------------------------------------------------------------------------------------------------------//
// Time variables

time_t ctTime;                              //time structure
int DST = 1;                                //Daylight Saving Time (or as defined in .ini file)
int TZone = -8;                             //Time Zone from UTC (or as defined in .ini file)
char timebuf_hms[10];                       //local time format buffer - 21:16:43
char timebuf_dMyy[14];                      //local time format buffer - 01-Apr-2014
char timebuf_dow[1];                        //local time format buffer - 5
int StartTime = 0;                          //time we powered up
bool allowDisplayTime = false;              //used to stop displaying date/time when entering data from the console

//--------------------------------------------------------------------------------------------------------------------------------------//
//Variables for USB Serial Port RX

uint32_t pcRxQty = 0;                       //RX data counter/pointer
char pcRxBuffer[128];                       //RX data buffer
bool pcRxLine = false;                      //CR or LF detected (end of line)
bool pcRxEOB = false;                       //RX buffer is full!!! cannot accept any more characters
char inchar = 0;                            //RX input character

//--------------------------------------------------------------------------------------------------------------------------------------//
// This function is called when a character goes into the RX buffer.

#define DOUPONELINE "\033[1A"
#define BS          0x08                    //ascii backspace
#define CR          0x0d                    //ascii CR
#define LF          0x0a                    //ascii LF
#define ticC        0x03                    //ascii control C
#define DEGC_DEGF_FLOAT         9.0 / 5.0 + 32.0

void PcRxChar(char inchar) {
    if(inchar == CR) pc.printf(" %c %c", BS, BS);   //NOTE: Bug in K64F has issue with CR and/or LF, these 2 lines are needed
    if(inchar == LF) pc.printf(" %c %c", BS, BS);
    if(inchar == BS) { 
        if(pcRxQty == 0) {
            pcRxBuffer[pcRxQty] = 0;
        } else {
            pc.printf("%c %c", BS, BS);
            pcRxQty--;
            pcRxBuffer[pcRxQty] = 0;
        }
    } else if((inchar == CR) || (inchar == LF)) { 
        pcRxLine = true;
        pc.printf("\r\n");
    } else if(inchar == ticC) {
        NVIC_SystemReset();
    } else {
        if(pcRxQty < (sizeof(pcRxBuffer) - 2)) {
            pcRxBuffer[pcRxQty] = inchar;
            pcRxQty++;
            pcRxBuffer[pcRxQty] = 0;
            pc.printf("%c", pcRxBuffer[pcRxQty - 1]);
        } else {
            pc.printf ("\r\n*** pcRxBuffer is full!!\r\n");
            pcRxEOB = true;
        }
    }
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Read received chars from USB UART interrupt

void PcRxIRQ(void){
#if defined(TARGET_KL25Z)
    NVIC_DisableIRQ(UART0_IRQn);        // n=0, 1 or 2  Disable Rx interrupt on kl25z
#endif
#if defined(TARGET_K64F)
    NVIC_DisableIRQ(UART0_RX_TX_IRQn);  // n=0, 1 or 2  Disable Rx interrupt on k64f
#endif
#if defined(TARGET_LPC1768)
    LPC_UART0->IER = 0;                 //Disable Rx interrupt on mbed1768
#endif
    while (pc.readable()) {
        inchar = pc.getc();             //<<<<< broken here!!!!     //read data from USB
        PcRxChar(inchar);               //go process char
    }
#if defined(TARGET_KL25Z)
    NVIC_EnableIRQ(UART0_IRQn);         // n=0, 1 or 2  Re-enable Rx interrupt on kl25z
#endif
#if defined(TARGET_K64F)
    NVIC_EnableIRQ(UART0_RX_TX_IRQn);   // n=0, 1 or 2  Re-enable Rx interrupt on k64f
#endif
#if defined(TARGET_LPC1768)
    LPC_UART0->IER = 1;                 //RE-enable Rx interrupt on mbed1768
#endif
}

//--------------------------------------------------------------------------------------------------------------------------------------//
//clear RxData buffer with all 00's and clear flags

void pcClrLineBuf() {
    pcRxQty = 0;                                                            // data counter/pointer
    for(int i = 0; i < (sizeof(pcRxBuffer) - 1); i++) pcRxBuffer[i] = 0;    // clear out rx buffer
    pcRxLine = false;
    pcRxEOB = false;
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Update time display values

void UpdateTimeRegs() {
    strftime(timebuf_dMyy, 14, "%d-%b-%Y", localtime(&ctTime));
    strftime(timebuf_hms, 10, "%H:%M:%S", localtime(&ctTime));
    strftime(timebuf_dow, 1, "%u", localtime(&ctTime));
}

void UpdateTime() {
    ctTime = time(NULL) + ((TZone + DST) * 3600);   //timezone and dst offsets
    UpdateTimeRegs();
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// display current local date and time

void PrintDateTime() {
    pc.printf("%sDate: %s   ",  DOUPONELINE, timebuf_dMyy);
    pc.printf("Time: %s \r\n", timebuf_hms);
}

//--------------------------------------------------------------------------------------------------------------------------------------//
//Manually set the date and time

ds3232m::Time_rtc rtc_m = {};
struct tm t;

bool SetRTC() {
    pc.printf("Enter current date and time:\n");
    pc.printf("MM DD YY HH MM SS[enter]\n");  
    pcClrLineBuf(); 
     
    //wait for string above
    do{
#ifdef RTOS_H
        Thread::wait(10);
#else
        wait_ms(10);
#endif
    } while((pcRxLine == false) && (pcRxEOB == false));
    
    //load up the time structure
    t.tm_year = (2000 + ((pcRxBuffer[6] - '0') * 10) + pcRxBuffer[7] - '0');
    t.tm_mon =  (((pcRxBuffer[0] - '0') * 10) + pcRxBuffer[1] - '0');
    t.tm_mday = (((pcRxBuffer[3] - '0') * 10) + pcRxBuffer[4] - '0');
    t.tm_hour = (((pcRxBuffer[9] - '0') * 10) + pcRxBuffer[10] - '0');
    t.tm_min = (((pcRxBuffer[12] - '0') * 10) + pcRxBuffer[13] - '0');
    t.tm_sec = (((pcRxBuffer[15] - '0') * 10) + pcRxBuffer[16] - '0');
    
    //adjust for tm structure required values
    t.tm_year = t.tm_year - 1900;
    t.tm_mon = t.tm_mon - 1;  
    t.tm_wday = t.tm_wday & 7;
    
    //if error exists, exit without changing time
    if(t.tm_year < 113) return(32);
    if(t.tm_mon > 12) return(16); 
    if(t.tm_mday > 31) return(8);  
    if(t.tm_hour > 23) return(4); 
    if(t.tm_min > 59) return(2); 
    if(t.tm_sec > 59) return(1); 
    
    //set up the DS3232's RTC
    rtc_m.sec = t.tm_sec;
    rtc_m.min = t.tm_min;
    rtc_m.hour = t.tm_hour;
    rtc_m.wday = t.tm_wday;
    rtc_m.date = t.tm_mday;
    rtc_m.mon = t.tm_mon + 1;
    rtc_m.year = t.tm_year + 1900;
    rtc.setTime(rtc_m);    //(time structure)

    //set the mbed's time
    time_t ctTime = mktime(&t);
    //reset system up time since it will be out of whack once the time is updated
    StartTime = ctTime;                         //have to change sysuptime now
    ctTime = ctTime - (TZone + DST) * 3600;     //take out local time
    set_time(ctTime);
    UpdateTime();
    return(0);
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Load the local mbed-RTC from that external DS3232 RTC

void loadRTC() {
    //get data from DS3232
    rtc.getTime(rtc_m);
    t.tm_sec = rtc_m.sec;
    t.tm_min = rtc_m.min;
    t.tm_hour = rtc_m.hour;
    t.tm_mday = rtc_m.date;
    t.tm_mon = rtc_m.mon - 1;
    t.tm_year = rtc_m.year - 1900;
            
    //set the mbed's time
    time_t ctTime = mktime(&t);
    ctTime = ctTime - (TZone + DST) * 3600;     //take out local time
    set_time(ctTime);
    UpdateTime(); 
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Pull the temperature out of the DS3232 RTC

void Get3232Temp() {
    pc.printf("%c", BS);
    if(rtc.startTempCycle() == true) {
        pc.printf(" - DS3232M start converstion ok \r\n");
    } else {
        pc.printf(" - DS3232M start converstion BUSY!!! \r\n");
    }
        
    //wait for DS3232 temperature conversion to finish
    int i = 80;
    for(i = 80; i > 0; i--) {
#ifdef RTOS_H
        Thread::wait(20);
#else
        wait_ms(20);
#endif
        if((rtc.checkTempBusy()) == true) break;
    }
        
    //timed out or display temperature
    if(i > 0) {
        float ds3232tempC = rtc.getTemperature();
        pc.printf(" - DS3232M Temperature: %.2fC  %.1fF\r\n", ds3232tempC, ds3232tempC * DEGC_DEGF_FLOAT);
    } else {
        pc.printf("*** DS3232M Temperature timeout!!!!\r\n");
    }
}

//--------------------------------------------------------------------------------------------------------------------------------------//
// Checking for characters to execute commands from.  It's a thread if RTOS is used.

#ifdef RTOS_H
void cli_thread(void const *argument) {
    pc.printf(" - Starting CLI RTOS thread\r\n");
    while (true) {      //while loop only for RTOS
        Thread::wait(73);
#else
void cli_thread() {
#endif
        if(pcRxQty != 0) {
            pc.printf("\r\n");
            if(pcRxBuffer[0] == 'A') rtc.set32KhzOutput(true, false);   //turn on 32KHz output
            if(pcRxBuffer[0] == 'a') rtc.set32KhzOutput(false, false);  //turn off 32KHz output
            if(pcRxBuffer[0] == 'B') rtc.set1hzOutput(true, false);   //turn on 1Hz output
            if(pcRxBuffer[0] == 'b') rtc.set1hzOutput(false, false);  //turn off 1Hz output
            if(pcRxBuffer[0] == 'c') {
                allowDisplayTime = true;
                SetRTC();  //change DS3232 time
                allowDisplayTime = false;
                pcRxBuffer[0] = 'c';
            }
            uint16_t errorValue = 0;
            if(pcRxBuffer[0] == 'g') {  //get and display stored data string
                errorValue = rtc.getUserRAM(pcRxBuffer, 128, 126);
                if(errorValue) {
                    pc.printf("'Get' user RAM error: %d\r\n", errorValue);
                } else if(pcRxBuffer[0] == NULL) {
                    pc.printf("User RAM empty!!\r\n");
                } else {
                    //pcRxBuffer[31] = NULL;    //guarantee that the string max length is 32 bytes
                    pc.printf("%s\r\n", pcRxBuffer);
                }
                pcRxBuffer[0] = 'g';
                errorValue = 0;
            }
            if(pcRxBuffer[0] == 's') {  //save data string
                allowDisplayTime = true;
                pc.printf("Enter text string to save: ");
                pcClrLineBuf();
                do {
#ifdef RTOS_H
                    Thread::wait(20);
#else
                    wait_ms(20);
#endif
                } while((pcRxLine == false) && (pcRxEOB == false));
                errorValue = rtc.putUserRAM(pcRxBuffer, 128, pcRxQty + 2);
                if(errorValue) pc.printf("'Put' user RAM error: %d\r\n", errorValue);
                allowDisplayTime = false;
                pcRxBuffer[0] = 's';
                errorValue = 0;
            }
            if(pcRxBuffer[0] == 't') Get3232Temp();  //display the DS3232's temperature
            if(pcRxBuffer[0] == 'z') {  
                rtc.LoadRTCRam();
                pc.printf("CRC16 value: 0x%04X\r\n", rtc.calculateCRC16(rtc.RTCbuffer, 0x14, 0xea));
            }
            if((pcRxBuffer[0] != 'a') && (pcRxBuffer[0] != 'A') && (pcRxBuffer[0] != 'b') 
                && (pcRxBuffer[0] != 'B') && (pcRxBuffer[0] != 'c') && (pcRxBuffer[0] != 'g') 
                && (pcRxBuffer[0] != 's') && (pcRxBuffer[0] != 't') && (pcRxBuffer[0] != 'z')) pc.printf("Entry Error!!\r\n");
            pc.printf("\r\n");
            pcClrLineBuf();
        }
#ifdef RTOS_H
    }   //RTOS while loop
#endif
}

//--------------------------------------------------------------------------------------------------------------------------------------//

int main() {
    pc.baud(230400);
    ctTime = time(NULL);
    StartTime = ctTime;                     //get time we started up
    pc.printf("\r\n\r\nDS3232M demo  23-DEC-2014  K. Braun\r\n");
    
    //check for RTOS operation
#ifdef RTOS_H
    pc.printf("RTOS installed...\r\n");
#else
    pc.printf("not using RTOS...\r\n");
#endif

    //pc RX character callback interrupt
    pc.printf("Initializing Serial Port Rx Interrupt...   \r\n");
    pc.attach(&PcRxIRQ, pc.RxIrq);
    
    pc.printf("Checking the mbed's RTC...\r\n");
#ifdef RTOS_H
    Thread::wait(1500);
#else
    wait_ms(1500);
#endif

    ctTime = time(NULL);
    
    //first, see if K64F's RTC already running
    if((StartTime == ctTime) || (ctTime <= 1000000000)) {
        pc.printf("*** mbed's local RTC is not initialized\r\n");
        loadRTC();
        StartTime = ctTime;
        
        //now see if DS3232's clock needs to be set
        if(ctTime <= 1000000000) {
            pc.printf("*** Local RTC stopped, initializing the RTC.  !!CHECK BATTERY!!\r\n");
            pc.printf("*** Note: Time is incorrect, needs to be updated!!!\r\n");
            
            //set up the DS3232's clock
            if(SetRTC() != 0) pc.printf("Entry Error!!");
            pcClrLineBuf();
        }
    } 
    
    //sync up the mbed's time with the DS3232's time    
    loadRTC();
    StartTime = ctTime;
    pc.printf(" - RTC Start Time:   ");
    PrintDateTime();
    pc.printf(" - Day of Week: %s\r\n", timebuf_dow);  //day of the week
        
    //get the DS3232's temperature
    Get3232Temp();
    
#ifdef RTOS_H
    //turn on the rest of the os threads
    pc.printf("Initializing os threads...\r\n");
    Thread th3(cli_thread, NULL, osPriorityNormal);
    Thread::wait(300);
#endif
    
    int CheckTime = ctTime;
    pc.printf("Hit 'A' or 'a' - turn on/off the 32KHz output\r\n");
    pc.printf("Hit 'B' or 'b' - turn on/off the 1Hz output (1Hz pin needs pull-up)\r\n");
    pc.printf("Hit 'c' - change the date & time\r\n");
    pc.printf("Hit 'g' - get data string from DS3232 user RAM\r\n");
    pc.printf("Hit 's' - store data string in the DS3232 user RAM\r\n");
    pc.printf("Hit 't' - get DS3232's temperature\r\n");
    pc.printf("Hit 'z' - get user RAM CRC data\r\n");
    pc.printf("Hit '^C' - reboot\r\n");
    pc.printf("\r\n");
    
    //Ready!!
    while (true) {
#ifdef RTOS_H
        Thread::wait(50);
#else
        wait_ms(50);
#endif
        UpdateTime();
        if(CheckTime != ctTime) {
            CheckTime = ctTime;
            if(allowDisplayTime == false) PrintDateTime();
        }
#ifndef RTOS_H
        cli_thread();
#endif      
    }
}