luni
Well-known member
The last days I had a lot of fun exploring the std::chrono namespace which provides a new (well, >=c++11) abstraction of durations, time points and clocks.
As an outcome of all this I implemented a std::chrono compliant teensy_clock with the following features:
Here a quick example showing what one can do with it. Basically it uses the teensy_clock to time a random delayMicroseconds() and displays the actual delay measured by the clock. After that it pretty prints the actual time/date.
Printout:
Of course all of this can be done the usual way with ARM_DW_DYCNT and the C-API time functions. But I like the clean and flexible way std::chrono is handling this.
In case anyone is interested in some modern c++ gimmicks: Here the code: https://github.com/luni64/TeensyHelpers
I also did a more detailed description of the new concepts and the working of the clock in the User WIKI: https://github.com/TeensyUser/doc/wiki/fun-with-modern-cpp
As an outcome of all this I implemented a std::chrono compliant teensy_clock with the following features:
- Internally, the clock tracks time as the number of clock cycles since the usual epoch (0::00h, 1970-01-01).
- To get reasonable rollover times it extends the cycle counter ARM_DW_CYCNT a 64bit extend cycle counter
- To correct for rollovers it uses the periodic timer from the SNVS_HPCR module (T=1s)
- It can be synced to the on board RTC at startup or at any later time
Here a quick example showing what one can do with it. Basically it uses the teensy_clock to time a random delayMicroseconds() and displays the actual delay measured by the clock. After that it pretty prints the actual time/date.
Code:
#include "teensy_clock.h"
using namespace std::chrono;
typedef teensy_clock::time_point timePoint; // just for the sake of less typing
typedef duration<float, std::micro> micros_f; // float based microseconds (predefined type 'microseconds' is integer based)
void setup()
{
teensy_clock::begin(); // starts the 64bit cycle counter, and syncs the clock to the rtc (works with and without battery)
}
void loop()
{
// demonstrate clock resolution --------------------------------------------------
unsigned delay_us = random(10, 5000);
Serial.printf("delayMicroseconds(%u)\n", delay_us);
timePoint t_0 = teensy_clock::now(); // get two timepoints 'delay_us' apart
delayMicroseconds(delay_us);
timePoint t_1 = teensy_clock::now();
auto dt = duration_cast<micros_f>(t_1 - t_0); // cast delta to microseconds (float)
Serial.printf("dt = t_1-t_0: %7.2f µs\n", dt.count());
// convert to C-API ---------------------------------------------------------------
timePoint currentTime = teensy_clock::now(); // get current time
time_t ct = teensy_clock::to_time_t(currentTime); // convert C-API time_t
Serial.printf("Current Time: %s\n", ctime(&ct)); // pretty print date/time
delay(1000);
}
Code:
delayMicroseconds(3099)
dt = t_1-t_0: 3099.08 µs
Current Time: Fri Oct 23 17:02:34 2020
delayMicroseconds(4945)
dt = t_1-t_0: 4945.08 µs
Current Time: Fri Oct 23 17:02:35 2020
delayMicroseconds(4714)
dt = t_1-t_0: 4714.08 µs
Current Time: Fri Oct 23 17:02:36 2020
delayMicroseconds(4384)
dt = t_1-t_0: 4384.08 µs
Current Time: Fri Oct 23 17:02:37 2020
delayMicroseconds(806)
dt = t_1-t_0: 806.08 µs
Current Time: Fri Oct 23 17:02:38 2020
...
Of course all of this can be done the usual way with ARM_DW_DYCNT and the C-API time functions. But I like the clean and flexible way std::chrono is handling this.
In case anyone is interested in some modern c++ gimmicks: Here the code: https://github.com/luni64/TeensyHelpers
I also did a more detailed description of the new concepts and the working of the clock in the User WIKI: https://github.com/TeensyUser/doc/wiki/fun-with-modern-cpp