check program for EPSON RX-8025NB and STM M41T62 external RTC library

Dependencies:   RX8025NB M41T62

main.cpp

Committer:
kenjiArai
Date:
2020-08-07
Revision:
1:0fd657a82160
Parent:
0:564965644ed2

File content as of revision 1:0fd657a82160:

/*
 * mbed Application program
 *      External RTC test program for EPSON RX-8025NB and STM M41T62
 *
 * Copyright (c) 2020 Kenji Arai / JH1PJL
 *  http://www7b.biglobe.ne.jp/~kenjia/
 *  https://os.mbed.com/users/kenjiArai/
 *      Created: August     7th, 2020
 *      Revised: August     7th, 2020
 */

// tested on Nucleo-L476RG board

//  Select target RTC ----------------------------------------------------------
//#define CHECK_RX8025
#define CHECK_M41T62

//  Include --------------------------------------------------------------------
#include "mbed.h"
#include "redirect_stdio.h"
#if defined(CHECK_RX8025)
#   include    "RX8025NB.h"
#   define      RTC_NO  0
#elif  defined(CHECK_M41T62)
#   include    "m41t62_rtc.h"
#   define      RTC_NO  1
#endif


//  Definition -----------------------------------------------------------------
#define PUSHED_SW       0           // Active low

#define SLEEP_TIME      2           // 2 minuts(minimum setting)

//  Object ---------------------------------------------------------------------
DigitalIn userSW(USER_BUTTON);
DigitalOut myled(LED1);             // Indicate the sampling period
I2C i2c(D14, D15);
#if defined(CHECK_RX8025)
RX8025  ex_rtc(i2c);                // EPSON RX-8025NB
DigitalIn rtc_irq(A5, PullUp);      // will change to InterruptIn
#elif  defined(CHECK_M41T62)
M41T62  ex_rtc(i2c);                // STMicro M41T62
DigitalIn rtc_irq(A4, PullUp);      // will change to InterruptIn
#endif

//  RAM ------------------------------------------------------------------------

//  ROM / Constant data --------------------------------------------------------
const char *const msg0 = "Is a time correct? If no, please hit any key. ";
const char *const msg1 = "<Push USER SW then enter the Deep Sleep mode> ";
const char *const rtc_name[2]  = {"RX-8025NB", "M41T62"};

//  Function prototypes --------------------------------------------------------
static void w_check_rtc_time(void);
static void time_enter_mode(void);
static void chk_and_set_time(char *ptr);
static int32_t xatoi(char **str, int32_t *res);
static void get_line(char *buff, int32_t len);
static void rtc_interrut(void);

extern void print_revision(void);

//------------------------------------------------------------------------------
//  Control Program
//------------------------------------------------------------------------------
int main()
{
    char buf[64];
    time_t seconds;
    uint8_t wait_counter = 0;

    puts("\r\n\r\nTest Nucleo RTC Function.");
    printf("External RTC is %s\r\n", rtc_name[RTC_NO]);
    print_revision();
    myled = !myled;
    ThisThread::sleep_for(100ms);
    myled = !myled;
    ThisThread::sleep_for(100ms);
    // RTC related preparation
    //ex_rtc.set_sq_wave(RTC_SQW_NONE);
    ex_rtc.clear_IRQ();
    w_check_rtc_time();
    while(true) {
        seconds = time(NULL);
        strftime(buf, 50, " %B %d,'%y, %H:%M:%S\r\n", localtime(&seconds));
        printf("[Time] %s", buf);
        printf("%s", msg0);
        printf("%s", msg1);
        puts("\r");
        wait_counter = 0;
        while (seconds == time(NULL)) {
            if (readable() == 1) {      // Enter time from PC console
                getc(); // dummy read
                time_enter_mode();
            }
            if (userSW == PUSHED_SW) {  // goto sleep and wake up by RTC timer
                while (userSW == PUSHED_SW) {
                    ThisThread::sleep_for(10ms);
                }
                printf("Please wait %d minutes to wake-up(Reset).", SLEEP_TIME);
                puts(" Entered the deep sleep mode. ");
                ThisThread::sleep_for(1s);
                myled = 0;
#if defined(CHECK_RX8025)
                InterruptIn rtc_irq(A5, PullUp);
#elif  defined(CHECK_M41T62)
                InterruptIn rtc_irq(A4, PullUp);
#endif
                rtc_irq.fall(&rtc_interrut);
                ex_rtc.set_next_IRQ(SLEEP_TIME);
                ThisThread::sleep_for(1s);
                DigitalIn dmy0(LED1);
                DigitalIn dmy1(USBTX);
                DigitalIn dmy2(USBRX);
                ThisThread::sleep_for(10000s);  // sleep long time
            }
            ThisThread::sleep_for(50ms);
            if (++wait_counter > (2000 / 50)) {
                break;
            }
        }
        // delete previous strings
        printf("\033[2A");
        puts("");   // null
        uint8_t n = strlen(msg0) + strlen(msg1);
        memset(buf, ' ', 64);
        if (n > 64) {
            n -= 64;
            puts_wo_cr(buf, 64);
        }
        if (n > 64) {
            puts_wo_cr(buf, 64);
        } else {
            puts_wo_cr(buf, n);
        }
        printf("\033[G");
        myled = !myled;
    }
}

//  Check External RTC data
static void w_check_rtc_time(void)
{
    time_t seconds_1st, seconds_2nd, diff;
    struct tm t;

    for (uint32_t i = 0; i < 5; i++) {
        ex_rtc.read_rtc_std(&t);   // read External RTC data
        printf("Year:%d ",t.tm_year);
        printf("Month:%d ",t.tm_mon);
        printf("Day:%d ",t.tm_mday);
        printf("Hour:%d ",t.tm_hour);
        printf("Min:%d ",t.tm_min);
        printf("Sec: %d \r\n",t.tm_sec);
        seconds_1st = mktime(&t);
        ex_rtc.read_rtc_std(&t);   // read External RTC data again (make sure)
        seconds_2nd = mktime(&t);
        diff = seconds_2nd - seconds_1st;
        if ((diff == 0) || (diff == 1)) {
            break;
        }
    }
    set_time(seconds_2nd);
}

//  Interrupt for wake up
static void rtc_interrut(void)
{
    system_reset(); // restart from RESET condition
}

//  Time adjustment
static void time_enter_mode(void)
{
    char *ptr;
    char linebuf[64];

    puts("Set time into RTC.");
    puts(" e.g. >20 8 1 12 34 56 -> August 01,'20, 12:34:56");
    puts(" If time is fine, just hit enter key.");
    putc('>');
    ptr = linebuf;
    get_line(ptr, sizeof(linebuf));
    puts("\r");
    chk_and_set_time(ptr);
}

//  Change string -> integer
static int32_t xatoi(char **str, int32_t *res)
{
    uint32_t val;
    uint8_t c, radix, s = 0;

    while ((c = **str) == ' ') (*str)++;
    if (c == '-') {
        s = 1;
        c = *(++(*str));
    }
    if (c == '0') {
        c = *(++(*str));
        if (c <= ' ') {
            *res = 0;
            return 1;
        }
        if (c == 'x') {
            radix = 16;
            c = *(++(*str));
        } else {
            if (c == 'b') {
                radix = 2;
                c = *(++(*str));
            } else {
                if ((c >= '0')&&(c <= '9')) {
                    radix = 8;
                }   else {
                    return 0;
                }
            }
        }
    } else {
        if ((c < '1')||(c > '9')) {
            return 0;
        }
        radix = 10;
    }
    val = 0;
    while (c > ' ') {
        if (c >= 'a') c -= 0x20;
        c -= '0';
        if (c >= 17) {
            c -= 7;
            if (c <= 9) return 0;
        }
        if (c >= radix) return 0;
        val = val * radix + c;
        c = *(++(*str));
    }
    if (s) val = -val;
    *res = val;
    return 1;
}

//  Get key input data
static void get_line(char *buff, int32_t len)
{
    char c;
    int32_t idx = 0;

    for (;;) {
        c = getc();
        //printf("0x%x \r\n", c);
        if ((c == '\r') || (c == '\n')) {
            buff[idx++] = '\r';
            break;
        }
        if ((c == '\b') && idx) {
            idx--;
            const char bf_bs[] =
            {0x1b, '[', '1', 'D', ' ', 0x1b, '[', '1', 'D',0};
            for(uint32_t i = 0; bf_bs[i] != 0; i++) {
                putc(bf_bs[i]);
            }
        }
        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
            buff[idx++] = c;
            putc(c);
        }
    }
    buff[idx] = 0;
    putc('\n');
}

//  Check key input strings and set time
static void chk_and_set_time(char *ptr)
{
    int32_t p1;
    struct tm t;
    time_t seconds;

    if (xatoi(&ptr, &p1)) {
        t.tm_year       = (uint8_t)p1 + 100;
        printf("Year:%d ",p1);
        xatoi( &ptr, &p1 );
        t.tm_mon        = (uint8_t)p1 - 1;
        printf("Month:%d ",p1);
        xatoi( &ptr, &p1 );
        t.tm_mday       = (uint8_t)p1;
        printf("Day:%d ",p1);
        xatoi( &ptr, &p1 );
        t.tm_hour       = (uint8_t)p1;
        printf("Hour:%d ",p1);
        xatoi( &ptr, &p1 );
        t.tm_min        = (uint8_t)p1;
        printf("Min:%d ",p1);
        xatoi( &ptr, &p1 );
        t.tm_sec        = (uint8_t)p1;
        printf("Sec: %d \r\n",p1);
        seconds = mktime(&t);
        set_time(seconds);
    } else {
        seconds = time(NULL);
    }
    seconds = time(NULL);
    struct tm *time_ajd = localtime(&seconds);
    ex_rtc.write_rtc_std(time_ajd);
    // Show Time with several example
    // ex.1
    printf(
        "Date: %04d/%02d/%02d, %02d:%02d:%02d\r\n",
        t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec
    );
    char buf[64];
    // ex.2
    strftime(buf, 40, "%x %X", localtime(&seconds));
    printf("Date: %s\r\n", buf);
    // ex.3
    strftime(buf, 40, "%I:%M:%S %p (%Y/%m/%d)", localtime(&seconds));
    printf("Date: %s\r\n", buf);
    // ex.4
    strftime(buf, 40, "%B %d,'%y, %H:%M:%S", localtime(&seconds));
    printf("Date: %s\r\n", buf);
}