RTC library

What could be included in further releases, or for the forum.
User avatar
GrumpyOldPizza
Posts: 174
Joined: Fri Apr 15, 2016 4:15 pm
Location: Denver, CO

RTC library

Post by GrumpyOldPizza » Tue May 24, 2016 9:27 pm

Quickly would love to ask for input about the design of an RTC library. The goal is to be RTCZero compatible API wise.

I am wondering whether all the necessary addon functionality is there, or whether something was overlooked. N.b there is only 1 alarm exposed. The 2nd in hardware is reserved for internal purposes.

Thanx for looking.

Code: Select all

class RTClock {
public:
    enum RTCAlarmMatch
    {
        MATCH_OFF,           // Never                                                                                                                                                         
        MATCH_SS,            // Every Minute                                                                                                                                                  
        MATCH_MMSS,          // Every Hour                                                                                                                                                    
        MATCH_HHMMSS,        // Every Day                                                                                                                                                     
        MATCH_DDHHMMSS,      // Every Month                                                                                                                                                   
        MATCH_MMDDHHMMSS,    // Every Year                                                                                                                                                    
        MATCH_YYMMDDHHMMSS,  // Once, on a specific date and a specific time                                                                                                                  
    };

    RTClock();
    void begin(bool resetTime = false);

    void enableAlarm(RTCAlarmMatch match);
    void disableAlarm();

    void attachInterrupt(void(*callback)(void));
    void detachInterrupt();

    void standbyMode();

    // Get Functions                                                                                                                                                                          
    uint8_t getSeconds();
    uint8_t getMinutes();
    uint8_t getHours();

    uint8_t getDay();
    uint8_t getMonth();
    uint8_t getYear();

    uint8_t getAlarmSeconds();
    uint8_t getAlarmMinutes();
    uint8_t getAlarmHours();

    uint8_t getAlarmDay();
    uint8_t getAlarmMonth();
    uint8_t getAlarmYear();

    // Set Functions                                                                                                                                                                          
    void setSeconds(uint8_t seconds);
    void setMinutes(uint8_t minutes);
    void setHours(uint8_t hours);
    void setTime(uint8_t hours, uint8_t minutes, uint8_t seconds);

    void setDay(uint8_t day);
    void setMonth(uint8_t month);
    void setYear(uint8_t year);
    void setDate(uint8_t day, uint8_t month, uint8_t year);

    void setAlarmSeconds(uint8_t seconds);
    void setAlarmMinutes(uint8_t minutes);
    void setAlarmHours(uint8_t hours);
    void setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds);

    void setAlarmDay(uint8_t day);
    void setAlarmMonth(uint8_t month);
    void setAlarmYear(uint8_t year);
    void setAlarmDate(uint8_t day, uint8_t month, uint8_t year);

    // Epoch Functions                                                                                                                                                                        
    uint32_t getEpoch();
    uint32_t getY2kEpoch();
    void setEpoch(uint32_t ts);
    void setY2kEpoch(uint32_t ts);
    
    // EXTENSTION: subsecond handling for timer synchronisation                                                                                                                       
    uint32_t getSubSeconds();
    void shiftSubSeconds(int32_t micros);

    // EXTENSTION: clock calibration [-511..512]                                                                                                                                      
    int32_t getCalibration();
    void setCalibration(int32_t calibration);

    // EXTENSTION: periodic wakeup                                                                                                                                                    
    void wakeup(uint32_t millis, void(*callback)(void));
};

extern RTClock RTC;


User avatar
martinayotte
Posts: 1171
Joined: Mon Apr 27, 2015 1:45 pm

Re: RTC library

Post by martinayotte » Wed May 25, 2016 12:09 am

Hi @GrumpyOldPizza,

Why would you not expose the second Alarm ?

On F1, if I remember, there is only 1, but on F4, I've implemented the lib with both available.

User avatar
GrumpyOldPizza
Posts: 174
Joined: Fri Apr 15, 2016 4:15 pm
Location: Denver, CO

Re: RTC library

Post by GrumpyOldPizza » Wed May 25, 2016 12:59 am

martinayotte wrote:Hi @GrumpyOldPizza,

Why would you not expose the second Alarm ?

On F1, if I remember, there is only 1, but on F4, I've implemented the lib with both available.
EDITED ANSWER.

Suppose you want to add a future "Alarm" class that allows an unlimited number of alarms by keeping a sorted list by expiration. This could be using the 2nd hardware alarm without compatibility problems with a simpler RTC class. It seemed to be important keep compatibility with the original RTCZero class as much as possible on the other hand. So this looks like a nice compromise.

User avatar
ahull
Posts: 1510
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: RTC library

Post by ahull » Wed May 25, 2016 3:13 pm

Are you sure there is only one on the F1, the only info I could find suggests that there may be two.
Overview of the STM32 advanced RTC
AN3371
8/42
Doc ID 018624 Rev 2
1.2 RTC alarms
1.2.1
RTC Alarm configuration
STM32 RTC embeds two alarms, Alarm A and Alarm B, which are similar. An alarm can be
generated at a given time or/and date programmed by the user.
The STM32 RTC provides a rich combination of alarms settings, and offers many features to
make it easy to configure and display these alarms settings.
I cannot find anything specific to the F10x that says there is only one, however you may well be correct.On the other hand, even if the STM documentation claims only one for the F10x, this may be marketing spec rather than anything to do with the silicon, and the 2nd alarm may actually work any way.
- Andy Hull -

User avatar
martinayotte
Posts: 1171
Joined: Mon Apr 27, 2015 1:45 pm

Re: RTC library

Post by martinayotte » Wed May 25, 2016 3:35 pm

The document STM32F1xxx-RM0008-CD00171190.pdf is stating in chapter 18 that only 1 RTCAlarm is present for the F1xx.
For the F4xx, the document STM32F4xxx-RM0090-DM00031020.pdf (chap.26) is showing that there are 2 Alarms, A and B, and also WakeUp timer, which I've implemented in RTClock for F4 as setPeriodicWakeup() awhile ago.

EDIT : Also, on a side note, the RTC of F1 is "epoch" based while the F4 is BCD based.

User avatar
GrumpyOldPizza
Posts: 174
Joined: Fri Apr 15, 2016 4:15 pm
Location: Denver, CO

Re: RTC library

Post by GrumpyOldPizza » Wed May 25, 2016 3:52 pm

martinayotte wrote:The document STM32F1xxx-RM0008-CD00171190.pdf is stating in chapter 18 that only 1 RTCAlarm is present for the F1xx.
For the F4xx, the document STM32F4xxx-RM0090-DM00031020.pdf (chap.26) is showing that there are 2 Alarms, A and B, and also WakeUp timer, which I've implemented in RTClock for F4 as setPeriodicWakeup() awhile ago.

EDIT : Also, on a side note, the RTC of F1 is "epoch" based while the F4 is BCD based.
Yep. Like your library a lot, BTW. Less useless cruft, fewer methods than the RTCZero I started working off.

Is there any advantage splitting the attach/detach of the wakeup callback from the configuration of the wakeup timeout ? The normal usage of the wakeup (given it's low precision) seems to be more to wakeup from STOP mode periodically. In that case a callback would be rather pointless ...

User avatar
ahull
Posts: 1510
Joined: Mon Apr 27, 2015 11:04 pm
Location: Sunny Scotland
Contact:

Re: RTC library

Post by ahull » Wed May 25, 2016 4:44 pm

martinayotte wrote:The document STM32F1xxx-RM0008-CD00171190.pdf is stating in chapter 18 that only 1 RTCAlarm is present for the F1xx.
For the F4xx, the document STM32F4xxx-RM0090-DM00031020.pdf (chap.26) is showing that there are 2 Alarms, A and B, and also WakeUp timer, which I've implemented in RTClock for F4 as setPeriodicWakeup() awhile ago.

EDIT : Also, on a side note, the RTC of F1 is "epoch" based while the F4 is BCD based.
Good to know. Particularly the fact that one is epoch and one BCD, this suggests some differences at the silicon level.
- Andy Hull -

User avatar
martinayotte
Posts: 1171
Joined: Mon Apr 27, 2015 1:45 pm

Re: RTC library

Post by martinayotte » Wed May 25, 2016 6:30 pm

Yes, it is down to silicon level, but the main goal is that BCD Alarms can be triggered in lot of different ways, such "per minute", "per hour", "per days", etc., things that can not be achieve in hardware with "epoch" based.

User avatar
martinayotte
Posts: 1171
Joined: Mon Apr 27, 2015 1:45 pm

Re: RTC library

Post by martinayotte » Wed May 25, 2016 6:32 pm

GrumpyOldPizza wrote:Is there any advantage splitting the attach/detach of the wakeup callback from the configuration of the wakeup timeout ? The normal usage of the wakeup (given it's low precision) seems to be more to wakeup from STOP mode periodically. In that case a callback would be rather pointless ...
I think I've done that simply by mimic the mechanism found in F1.

User avatar
GrumpyOldPizza
Posts: 174
Joined: Fri Apr 15, 2016 4:15 pm
Location: Denver, CO

Re: RTC library

Post by GrumpyOldPizza » Sun Oct 23, 2016 2:01 pm

Ok, finally got around implementing all of this for the STM32L4 core. Could somebody review && || provide feedback whether I got the API and functionality correct ?

The API is compatible with RTCZero (the code on github has a "RTCZero.h" wrapper). Couple of caveats. The wakeup timer is not exposed. This is reserved for "STM32.sleep(timeout)" and "STM32.deepsleep(timeout)". The 2nd alarm for L0 and L4 is not exposed at the moment to support a future "RTCAlarm" class.

Some notes. RTC.getCalibration/setCalibration allows to speed-up/slow-down the clock. One uses RTC.pinMode(OUTPUT_1HZ) for example to output a 1Hz signal on PC13 which can be compared to a more precise reference clock. RTC.adjustTicks() can be used together with RTC.pinMode(INPUT_SYNC) to aligned the RTC with an external clock. Say one connects the PPS of a GPS to PC13, and uses RTC.onSync(). Each time there is a rising edge on PPS, the onSync() callback will be called, and with RTC.getSyncTicks() the offset (or adjustment factor) can be determinted. The sync facility itself can be used also to measure the exact time of an external event, say a button press (which is the default for Dragonfly).

N.b that "ticks" are similar to "subseconds" in the STM documentation, except that they are always scaled to [0..32767].

Thanx for looking.

Code: Select all

class RTCClass {
public:

    enum AlarmMatch: uint8_t {
        MATCH_ANY          = 0,      // Every Second
        MATCH_SS           = 1,      // Every Minute
        MATCH_MMSS         = 3,      // Every Hour
        MATCH_HHMMSS       = 7,      // Every Day
        MATCH_DHHMMSS      = 15,     // Every Month
        MATCH_MMDDHHMMSS   = 31,     // Every Year
        MATCH_YYMMDDHHMMSS = 64      // Once, on a specific date and a specific time
    };

    enum PinMode: uint8_t {
        NONE               = 0,
        INPUT_SYNC         = 1,
        OUTPUT_512HZ       = 2,
        OUTPUT_1HZ         = 3,
    };

    void enableAlarm(AlarmMatch match);
    void disableAlarm();

    void attachInterrupt(void(*callback)(void));
    void detachInterrupt();
  
    // Get Functions
    uint8_t getSeconds();
    uint8_t getMinutes();
    uint8_t getHours();
  
    uint8_t getDay();
    uint8_t getMonth();
    uint8_t getYear();
  
    uint8_t getAlarmSeconds();
    uint8_t getAlarmMinutes();
    uint8_t getAlarmHours();

    uint8_t getAlarmDay();
    uint8_t getAlarmMonth();
    uint8_t getAlarmYear();

    // Set Functions
    void setSeconds(uint8_t seconds);
    void setMinutes(uint8_t minutes);
    void setHours(uint8_t hours);
    void setTime(uint8_t hours, uint8_t minutes, uint8_t seconds);

    void setDay(uint8_t day);
    void setMonth(uint8_t month);
    void setYear(uint8_t year);
    void setDate(uint8_t day, uint8_t month, uint8_t year);

    void setAlarmSeconds(uint8_t seconds);
    void setAlarmMinutes(uint8_t minutes);
    void setAlarmHours(uint8_t hours);
    void setAlarmTime(uint8_t hours, uint8_t minutes, uint8_t seconds);

    void setAlarmDay(uint8_t day);
    void setAlarmMonth(uint8_t month);
    void setAlarmYear(uint8_t year);
    void setAlarmDate(uint8_t day, uint8_t month, uint8_t year);

    // Epoch Functions
    uint32_t getEpoch();
    uint32_t getY2kEpoch();
    void setEpoch(uint32_t ts);
    void setY2kEpoch(uint32_t ts);

    // STM32L4 EXTENSION: atomic set time/date
    void setCalendar(uint8_t hours, uint8_t minutes, uint8_t seconds, uint8_t day, uint8_t month, uint8_t year);

    // STM32L4 EXTENSION: ticks [0..32767]
    uint16_t getTicks();

    // STM32L4 EXTENSION: clock calibration [-511..512]
    int32_t getCalibration();
    void setCalibration(int32_t calibration);

    // STM32L4 EXTENSION: clock fine tuning [-32767..32768]
    void adjustTicks(int32_t ticks);

    // STM32L4 EXTENSION: external sync pulse
    bool syncOccured();
    uint16_t getSyncTicks();
    uint8_t getSyncSeconds();
    uint8_t getSyncMinutes();
    uint8_t getSyncHours();
    uint8_t getSyncDay();
    uint8_t getSyncMonth();
    void onSync(void(*callback)(void));

    // STM32L4 EXTENSION: PC13 control
    void pinMode(PinMode mode);
};

extern RTCClass RTC;


Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest