diff --git a/examples/avr/adc/oversample/main.cpp b/examples/avr/adc/oversample/main.cpp index ad91a499da..a2588a1388 100644 --- a/examples/avr/adc/oversample/main.cpp +++ b/examples/avr/adc/oversample/main.cpp @@ -15,6 +15,7 @@ using namespace modm::platform; using namespace modm::literals; +using namespace std::chrono_literals; // Create a new UART object @@ -32,7 +33,7 @@ typedef modm::AdcSampler< AdcInterrupt, 3, 32 > sensors; // the results are up to 16 bit wide sensors::DataType sensorData[3]; -modm::ShortTimeout timeout(100); +modm::ShortTimeout timeout(100ms); int main() @@ -67,7 +68,7 @@ main() // start another readout sensors::startReadout(); - timeout.restart(200); + timeout.restart(200ms); } } } diff --git a/examples/avr/block_device_mirror/main.cpp b/examples/avr/block_device_mirror/main.cpp index 9b9302e546..f2a209a9e6 100644 --- a/examples/avr/block_device_mirror/main.cpp +++ b/examples/avr/block_device_mirror/main.cpp @@ -17,7 +17,6 @@ #include using namespace modm::platform; -typedef modm::platform::SystemClock clock; // Create a new UART object and configure it to a baudrate of 115200 Uart0 uart; diff --git a/examples/avr/can/mcp2515_uart/main.cpp b/examples/avr/can/mcp2515_uart/main.cpp index d8760b0072..5d899d07de 100644 --- a/examples/avr/can/mcp2515_uart/main.cpp +++ b/examples/avr/can/mcp2515_uart/main.cpp @@ -12,13 +12,12 @@ // ---------------------------------------------------------------------------- #include -#include - #include #include using namespace modm::platform; using namespace modm::literals; +using namespace std::chrono_literals; typedef GpioOutputB0 LedGreen; typedef GpioOutputB1 LedRed; @@ -49,25 +48,13 @@ FLASH_STORAGE(uint8_t canFilter[]) = MCP2515_FILTER_EXTENDED(0), // Mask 1 }; -// timer interrupt routine -MODM_ISR(TIMER2_COMPA) -{ - modm::Clock::increment(); -} - int main() { + SystemClock::enable(); LedGreen::setOutput(modm::Gpio::High); LedRed::setOutput(modm::Gpio::Low); - // timer initialization - // compare-match-interrupt every 1 ms at 14.7456 MHz - TCCR2A = (1 << WGM21); - TCCR2B = (1 << CS22); - TIMSK2 = (1 << OCIE2A); - OCR2A = 230; - Uart0::connect(); Uart0::initialize(); @@ -99,7 +86,7 @@ main() mcp2515.sendMessage(message); - modm::ShortPeriodicTimer timer(200); + modm::ShortPeriodicTimer timer(200ms); while (true) { if (mcp2515.isMessageAvailable()) diff --git a/examples/avr/display/dogm128/benchmark/main.cpp b/examples/avr/display/dogm128/benchmark/main.cpp index d15e39e450..1e1666a4e6 100644 --- a/examples/avr/display/dogm128/benchmark/main.cpp +++ b/examples/avr/display/dogm128/benchmark/main.cpp @@ -47,15 +47,11 @@ modm::DogM128< lcd::SPI, lcd::Cs, lcd::A0, lcd::Reset, true > display; using namespace modm::glcd; -// timer interrupt routine -MODM_ISR(TIMER2_COMPA) -{ - modm::Clock::increment(); -} - void setup() { + SystemClock::enable(); + led::R::set(); led::G::set(); led::B::reset(); @@ -67,13 +63,6 @@ setup() lcd::SPI::connect(); lcd::SPI::initialize(); - // timer initialization - // compare-match-interrupt every 1 ms at 14.7456 MHz - TCCR2A = (1 << WGM21); - TCCR2B = (1 << CS22); - TIMSK2 = (1 << OCIE2A); - OCR2A = 230; - // enable interrupts enableInterrupts(); @@ -165,7 +154,7 @@ main() display.setFont(modm::font::FixedWidth5x8); - modm::ShortPeriodicTimer timer(1000); + modm::ShortPeriodicTimer timer(1s); while (true) { uint8_t iter = 0; diff --git a/examples/avr/protothread/main.cpp b/examples/avr/protothread/main.cpp index 3009ca64fd..cff2977046 100644 --- a/examples/avr/protothread/main.cpp +++ b/examples/avr/protothread/main.cpp @@ -17,6 +17,7 @@ #include using namespace modm::platform; +using namespace std::chrono_literals; typedef GpioOutputB0 LedGreen; typedef GpioOutputB1 LedRed; @@ -37,13 +38,13 @@ class BlinkingLightGreen : public modm::pt::Protothread { LedGreen::set(); - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); LedGreen::reset(); - this->timeout.restart(600); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(600ms); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); @@ -69,23 +70,23 @@ class BlinkingLightRed : public modm::pt::Protothread { LedRed::set(); - this->timeout.restart(200); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(200ms); + PT_WAIT_UNTIL(timeout.isExpired()); LedRed::reset(); - this->timeout.restart(300); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(300ms); + PT_WAIT_UNTIL(timeout.isExpired()); LedRed::set(); - this->timeout.restart(200); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(200ms); + PT_WAIT_UNTIL(timeout.isExpired()); LedRed::reset(); - this->timeout.restart(1000); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(1s); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); @@ -95,22 +96,10 @@ class BlinkingLightRed : public modm::pt::Protothread modm::ShortTimeout timeout; }; -// timer interrupt routine -MODM_ISR(TIMER2_COMPA) -{ - modm::Clock::increment(); -} - int main() { - // timeout initialization - // compare-match-interrupt every 1 ms at 14.7456 MHz - TCCR2A = (1 << WGM21); - TCCR2B = (1 << CS22); - TIMSK2 = (1 << OCIE2A); - OCR2A = 230; - + SystemClock::enable(); enableInterrupts(); BlinkingLightGreen greenLight; diff --git a/examples/avr/protothread/project.xml b/examples/avr/protothread/project.xml index 0af38df366..c66ce4433f 100644 --- a/examples/avr/protothread/project.xml +++ b/examples/avr/protothread/project.xml @@ -6,6 +6,7 @@ modm:platform:core + modm:platform:clock modm:platform:gpio modm:processing:protothread modm:processing:timer diff --git a/examples/avr/timeout/main.cpp b/examples/avr/timeout/main.cpp index 60eb1e7147..c595ca05d1 100644 --- a/examples/avr/timeout/main.cpp +++ b/examples/avr/timeout/main.cpp @@ -12,42 +12,31 @@ // ---------------------------------------------------------------------------- #include -#include #include using namespace modm::platform; +using namespace std::chrono_literals; // create a output device for the led typedef GpioOutputB0 Led; -// timer interrupt routine -MODM_ISR(TIMER2_COMPA) -{ - modm::Clock::increment(); -} int main() { + SystemClock::enable(); Led::setOutput(); Led::reset(); - // timer initialization - // compare-match-interrupt every 1 ms at 14.7456 MHz - TCCR2A = (1 << WGM21); - TCCR2B = (1 << CS22); - TIMSK2 = (1 << OCIE2A); - OCR2A = 230; - // enable interrupts enableInterrupts(); - modm::ShortTimeout timeout(200); + modm::ShortTimeout timeout(200ms); while (true) { if (timeout.isExpired()) { - timeout.restart(200); + timeout.restart(200ms); Led::toggle(); } } diff --git a/examples/avr/timeout/project.xml b/examples/avr/timeout/project.xml index d229d0f793..823919c202 100644 --- a/examples/avr/timeout/project.xml +++ b/examples/avr/timeout/project.xml @@ -7,6 +7,7 @@ modm:architecture:interrupt modm:platform:core + modm:platform:clock modm:platform:gpio modm:processing:timer modm:build:scons diff --git a/examples/avr/timer/main.cpp b/examples/avr/timer/main.cpp new file mode 100644 index 0000000000..6847a848b3 --- /dev/null +++ b/examples/avr/timer/main.cpp @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020, Niklas Hauser + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#include +#include + +int main() +{ + Board::initialize(); + + uint32_t counter(0); + modm::PrecisePeriodicTimer ptmr(0.500990s); + modm::PeriodicTimer tmr(0.500990s); + + for (int ii=0; ii<20; ii++) + { + LedD13::toggle(); + modm::delay(std::chrono::milliseconds(10*ii)); + } + + uint32_t ms_counter{0}; + uint32_t us_counter{0}; + + while (true) + { + { + uint32_t ms = modm::Clock::now().time_since_epoch().count(); + if (ms < ms_counter) { + MODM_LOG_ERROR << ms << " < " << ms_counter << modm::endl; + } + ms_counter = ms; + }{ + uint32_t us = modm::PreciseClock::now().time_since_epoch().count(); + if (us < us_counter) { + MODM_LOG_ERROR << us << " < " << us_counter << modm::endl; + } + us_counter = us; + } + + if (ptmr.execute()) + { + LedD13::set(); + MODM_LOG_INFO << "loop: " << counter++ << modm::endl; + } + if (tmr.execute()) + { + LedD13::reset(); + } + } +} diff --git a/examples/avr/timer/project.xml b/examples/avr/timer/project.xml new file mode 100644 index 0000000000..cc098bd659 --- /dev/null +++ b/examples/avr/timer/project.xml @@ -0,0 +1,12 @@ + + modm:arduino-nano + + + + + modm:architecture:delay + modm:processing:timer + modm:build:scons + modm:build:cmake + + diff --git a/examples/avr/uart/basic_mega8/main.cpp b/examples/avr/uart/basic_mega8/main.cpp deleted file mode 100644 index 0da8340438..0000000000 --- a/examples/avr/uart/basic_mega8/main.cpp +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2010-2013, Fabian Greif - * Copyright (c) 2012-2013, 2017, Niklas Hauser - * Copyright (c) 2014, Sascha Schade - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include - -using namespace modm::literals; -using namespace modm::platform; - -int -main() -{ - Uart::connect(); - Uart::initialize(); - - // Enable interrupts, this is needed for every buffered UART - enableInterrupts(); - - // Write some characters - Uart::write('H'); - Uart::write('e'); - Uart::write('l'); - Uart::write('l'); - Uart::write('o'); - Uart::write('\n'); - - while (true) - { - } -} diff --git a/examples/avr/uart/basic_mega8/project.xml b/examples/avr/uart/basic_mega8/project.xml deleted file mode 100644 index 181161d056..0000000000 --- a/examples/avr/uart/basic_mega8/project.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - modm:platform:clock - modm:platform:core - modm:platform:gpio - modm:platform:uart - modm:build:scons - - diff --git a/examples/avr/xpcc/sender/component_sender/sender.cpp b/examples/avr/xpcc/sender/component_sender/sender.cpp index c2d81423c8..a60acb6f17 100644 --- a/examples/avr/xpcc/sender/component_sender/sender.cpp +++ b/examples/avr/xpcc/sender/component_sender/sender.cpp @@ -21,12 +21,13 @@ #include #include "sender.hpp" +using namespace std::chrono_literals; // ---------------------------------------------------------------------------- component::Sender::Sender(uint8_t id, xpcc::Dispatcher &communication) : xpcc::AbstractComponent(id, communication), positionCallback(this, &Sender::getPositionCallback), - timer(2000) + timer(2s) { } diff --git a/examples/generic/i2c_multiplex/main.cpp b/examples/generic/i2c_multiplex/main.cpp index 3c65040800..a85df030f0 100644 --- a/examples/generic/i2c_multiplex/main.cpp +++ b/examples/generic/i2c_multiplex/main.cpp @@ -94,8 +94,8 @@ DeviceThread::update() MODM_LOG_DEBUG.printf("[dev ] ping3\n"); MODM_LOG_DEBUG.printf("[dev ] ping3 res: %d\n", PT_CALL(dev3.ping())); // Do again in 1s - this->timeout.restart(1000); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(1s); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); diff --git a/examples/generic/ros/can_bridge/main.cpp b/examples/generic/ros/can_bridge/main.cpp index fec7520747..8525cd2717 100644 --- a/examples/generic/ros/can_bridge/main.cpp +++ b/examples/generic/ros/can_bridge/main.cpp @@ -122,7 +122,7 @@ main() nh.subscribe(sub_can); nh.advertise(pub_can); - modm::ShortPeriodicTimer heartbeat(1000); + modm::ShortPeriodicTimer heartbeat(1s); while (true) { if (Can::isMessageAvailable()) diff --git a/examples/generic/ros/environment/main.cpp b/examples/generic/ros/environment/main.cpp index bae93e28f2..d259d87275 100644 --- a/examples/generic/ros/environment/main.cpp +++ b/examples/generic/ros/environment/main.cpp @@ -78,7 +78,7 @@ main() Bme280Thread bme280thread; DisplayThread display_thread; - modm::ShortPeriodicTimer timer(1000); + modm::ShortPeriodicTimer timer(1s); bool bme_sampling(false); while (true) diff --git a/examples/generic/ros/environment/thread_bme280.cpp b/examples/generic/ros/environment/thread_bme280.cpp index dffb1c82ae..ea26af3086 100644 --- a/examples/generic/ros/environment/thread_bme280.cpp +++ b/examples/generic/ros/environment/thread_bme280.cpp @@ -49,8 +49,8 @@ Bme280Thread::update() if (PT_CALL(barometer.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } // Configure the device until it responds @@ -60,8 +60,8 @@ Bme280Thread::update() if (PT_CALL(barometer.initialize())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << MODM_FILE_INFO; diff --git a/examples/generic/ros/environment/thread_display.cpp b/examples/generic/ros/environment/thread_display.cpp index 6ecf05c9b4..1ebd624621 100644 --- a/examples/generic/ros/environment/thread_display.cpp +++ b/examples/generic/ros/environment/thread_display.cpp @@ -31,7 +31,7 @@ DisplayThread::update() PT_BEGIN(); // Wait for 100 msec unitl display powered up. - boot_timeout.restart(100); + boot_timeout.restart(100ms); PT_WAIT_UNTIL(boot_timeout.isExpired()); display.initializeBlocking(); diff --git a/examples/generic/ros/sub_pub/main.cpp b/examples/generic/ros/sub_pub/main.cpp index 8bd608bf3f..620e27d419 100644 --- a/examples/generic/ros/sub_pub/main.cpp +++ b/examples/generic/ros/sub_pub/main.cpp @@ -97,7 +97,7 @@ main() // Make sure to publish on boot bool button_state = not Board::Button::read(); - modm::ShortPeriodicTimer heartbeat(1000); + modm::ShortPeriodicTimer heartbeat(1s); while(true) { bool button_read = Board::Button::read(); diff --git a/examples/generic/rtc_ds1302/main.cpp b/examples/generic/rtc_ds1302/main.cpp index 0cc5cf7cd7..2fdc1ea193 100644 --- a/examples/generic/rtc_ds1302/main.cpp +++ b/examples/generic/rtc_ds1302/main.cpp @@ -79,10 +79,10 @@ main() uint16_t tt = 9995; // Milliseconds modm::Timeout timeout; - timeout.restart(tt); + timeout.restart(std::chrono::milliseconds(tt)); // Periodically report progress - modm::PeriodicTimer blinkTimer(250); + modm::PeriodicTimer blinkTimer(250ms); MODM_LOG_DEBUG.printf("CPU frequency is %ld Hz\n", Board::SystemClock::Frequency); diff --git a/examples/linux/xpcc/basic/component_sender/sender.cpp b/examples/linux/xpcc/basic/component_sender/sender.cpp index 59fa24db95..9300be9f8a 100644 --- a/examples/linux/xpcc/basic/component_sender/sender.cpp +++ b/examples/linux/xpcc/basic/component_sender/sender.cpp @@ -20,12 +20,13 @@ #include #include "sender.hpp" +using namespace std::chrono_literals; // ---------------------------------------------------------------------------- component::Sender::Sender(uint8_t id, xpcc::Dispatcher &communication) : xpcc::AbstractComponent(id, communication), positionCallback(this, &Sender::getPositionCallback), - timer(2000) + timer(2s) { } diff --git a/examples/nucleo_f031k6/blink/main.cpp b/examples/nucleo_f031k6/blink/main.cpp index fe99a871bc..27b5693d5a 100644 --- a/examples/nucleo_f031k6/blink/main.cpp +++ b/examples/nucleo_f031k6/blink/main.cpp @@ -31,7 +31,7 @@ main() while (true) { LedD13::toggle(); - modm::delayMilliseconds(Button::read() ? 100 : 500); + modm::delay(Button::read() ? 100ms : 500ms); MODM_LOG_INFO << "loop: " << counter++ << modm::endl; } diff --git a/examples/nucleo_f031k6/sk6812/main.cpp b/examples/nucleo_f031k6/sk6812/main.cpp index aa2537b36f..a1285b7db3 100644 --- a/examples/nucleo_f031k6/sk6812/main.cpp +++ b/examples/nucleo_f031k6/sk6812/main.cpp @@ -18,7 +18,7 @@ using namespace Board; using Output = Board::D11; modm::Sk6812w leds; -modm::ShortPeriodicTimer tmr{33}; +modm::ShortPeriodicTimer tmr{33ms}; int main() diff --git a/examples/nucleo_f103rb/blink/main.cpp b/examples/nucleo_f103rb/blink/main.cpp index 467df82f17..53ea9b38b8 100644 --- a/examples/nucleo_f103rb/blink/main.cpp +++ b/examples/nucleo_f103rb/blink/main.cpp @@ -10,6 +10,7 @@ // ---------------------------------------------------------------------------- #include +#include using namespace Board; @@ -27,13 +28,16 @@ main() MODM_LOG_ERROR << "error" << modm::endl; uint32_t counter(0); + modm::PrecisePeriodicTimer tmr(1.23456789s); while (true) { - LedD13::toggle(); - modm::delayMilliseconds(Button::read() ? 100 : 500); + if (tmr.execute()) + { + LedD13::toggle(); - MODM_LOG_INFO << "loop: " << counter++ << modm::endl; + MODM_LOG_INFO << "loop: " << counter++ << modm::endl; + } } return 0; diff --git a/examples/nucleo_f103rb/blink/project.xml b/examples/nucleo_f103rb/blink/project.xml index 991cd6a8c7..e1ae885214 100644 --- a/examples/nucleo_f103rb/blink/project.xml +++ b/examples/nucleo_f103rb/blink/project.xml @@ -5,5 +5,6 @@ modm:build:scons + modm:processing:timer diff --git a/examples/nucleo_f103rb/itm/main.cpp b/examples/nucleo_f103rb/itm/main.cpp index 1dacbadc86..5de5f00a6c 100644 --- a/examples/nucleo_f103rb/itm/main.cpp +++ b/examples/nucleo_f103rb/itm/main.cpp @@ -36,10 +36,10 @@ main() while (true) { - static modm::PeriodicTimer tmr{500}; + static modm::PeriodicTimer tmr{500ms}; if (tmr.execute()) { - tmr.restart(Button::read() ? 100 : 500); + tmr.restart(Button::read() ? 100ms : 500ms); LedD13::toggle(); static uint32_t counter{0}; diff --git a/examples/nucleo_f103rb/itm/project.xml b/examples/nucleo_f103rb/itm/project.xml index b34b7319e2..c7cacff49c 100644 --- a/examples/nucleo_f103rb/itm/project.xml +++ b/examples/nucleo_f103rb/itm/project.xml @@ -7,5 +7,6 @@ modm:build:scons modm:platform:itm + modm:processing:timer diff --git a/examples/nucleo_f401re/distance_vl53l0/main.cpp b/examples/nucleo_f401re/distance_vl53l0/main.cpp index 6f7a93288c..17505791d7 100644 --- a/examples/nucleo_f401re/distance_vl53l0/main.cpp +++ b/examples/nucleo_f401re/distance_vl53l0/main.cpp @@ -13,6 +13,7 @@ #include +#include #include #include #include @@ -63,8 +64,8 @@ class ThreadOne : public modm::pt::Protothread } // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << "Device responded" << modm::endl; @@ -76,8 +77,8 @@ class ThreadOne : public modm::pt::Protothread } // otherwise, try again in 200ms - this->timeout.restart(200); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(200ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << "Device initialized" << modm::endl; @@ -89,7 +90,7 @@ class ThreadOne : public modm::pt::Protothread this->highAccuracyMode = true; } - this->timeout.restart(1000); + timeout.restart(1s); while (true) { @@ -110,8 +111,8 @@ class ThreadOne : public modm::pt::Protothread } MODM_LOG_DEBUG << ", t = " << (modm::Clock::now() - stamp) << "ms" << modm::endl; - // query button state every 1000ms - if(this->timeout.isExpired()) + // query button state every 1s + if(timeout.isExpired()) { // toggle between fast and high accuracy mode when button is pressed if(Button::read()) @@ -136,7 +137,7 @@ class ThreadOne : public modm::pt::Protothread } } - this->timeout.restart(1000); + timeout.restart(1s); } } @@ -163,7 +164,7 @@ main() MODM_LOG_INFO << "\n\nWelcome to VL53L0X demo!\n\n"; - modm::ShortPeriodicTimer tmr(500); + modm::ShortPeriodicTimer tmr(500ms); while (true) { diff --git a/examples/nucleo_f411re/imu_bno055/main.cpp b/examples/nucleo_f411re/imu_bno055/main.cpp index af7da50679..57a74788e9 100644 --- a/examples/nucleo_f411re/imu_bno055/main.cpp +++ b/examples/nucleo_f411re/imu_bno055/main.cpp @@ -83,7 +83,7 @@ class ThreadOne : public modm::pt::Protothread } private: - modm::ShortPeriodicTimer timer{100}; + modm::ShortPeriodicTimer timer{100ms}; }; ThreadOne one; @@ -101,7 +101,7 @@ main() MODM_LOG_INFO << "\n\nWelcome to BNO055 demo!\n\n" << modm::endl; - modm::ShortPeriodicTimer tmr(500); + modm::ShortPeriodicTimer tmr(500ms); // Board::D15::setOutput(); diff --git a/examples/nucleo_f411re/radio/nrf24-basic-comm/main.cpp b/examples/nucleo_f411re/radio/nrf24-basic-comm/main.cpp index 9dbf009f73..bcc1b7c6cc 100644 --- a/examples/nucleo_f411re/radio/nrf24-basic-comm/main.cpp +++ b/examples/nucleo_f411re/radio/nrf24-basic-comm/main.cpp @@ -86,8 +86,8 @@ int main() Nrf2Phy::setBits(Register::CONFIG, Config::PWR_UP); - /* Timer to send packets every 1000ms */ - modm::ShortPeriodicTimer sendPacket(1000); + /* Timer to send packets every 1s */ + modm::ShortPeriodicTimer sendPacket(1s); /* Buffer for received payload */ uint8_t received_data[payload_length]; @@ -96,7 +96,7 @@ int main() { // ------------------------- Primary sender --------------------------- - /* Send packet every 1000ms */ + /* Send packet every 1s */ if(sendPacket.execute()) { /* Copy packet into ptx device. Because CE is always high here, the diff --git a/examples/nucleo_f411re/radio/nrf24-data/main.cpp b/examples/nucleo_f411re/radio/nrf24-data/main.cpp index 07856b4fda..956e314eb2 100644 --- a/examples/nucleo_f411re/radio/nrf24-data/main.cpp +++ b/examples/nucleo_f411re/radio/nrf24-data/main.cpp @@ -28,7 +28,7 @@ int main() Nrf1Data::update(); Nrf2Data::update(); - static modm::PeriodicTimer sendTimer{1000}; + static modm::PeriodicTimer sendTimer{1s}; if (Nrf1Data::Packet packet; sendTimer.execute()) { static uint8_t counter{0}; diff --git a/examples/nucleo_f411re/radio/nrf24-scanner/main.cpp b/examples/nucleo_f411re/radio/nrf24-scanner/main.cpp index e990d53d8f..9bc8cb49a7 100644 --- a/examples/nucleo_f411re/radio/nrf24-scanner/main.cpp +++ b/examples/nucleo_f411re/radio/nrf24-scanner/main.cpp @@ -59,8 +59,8 @@ int main() } // modm::ShortPeriodicTimer divide_timer((max_channel*rx_settle)/1000 * divider); - modm::ShortPeriodicTimer divide_timer(500); - modm::ShortPeriodicTimer refreshTerminal(500); + modm::ShortPeriodicTimer divide_timer(500ms); + modm::ShortPeriodicTimer refreshTerminal(500ms); bool divide_now = false; diff --git a/examples/nucleo_f411re/ws2812b/main.cpp b/examples/nucleo_f411re/ws2812b/main.cpp index 50bdf67af9..6ee411a8a1 100644 --- a/examples/nucleo_f411re/ws2812b/main.cpp +++ b/examples/nucleo_f411re/ws2812b/main.cpp @@ -18,7 +18,7 @@ using namespace Board; using Output = Board::D11; modm::Ws2812b leds; -modm::ShortPeriodicTimer tmr{33}; +modm::ShortPeriodicTimer tmr{33ms}; int main() diff --git a/examples/nucleo_f429zi/pat9125el/main.cpp b/examples/nucleo_f429zi/pat9125el/main.cpp index 25afe6abaa..7a4ea3ea36 100644 --- a/examples/nucleo_f429zi/pat9125el/main.cpp +++ b/examples/nucleo_f429zi/pat9125el/main.cpp @@ -42,8 +42,8 @@ class Thread : public modm::pt::Protothread break; } // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_INFO << "Ping successful" << modm::endl; diff --git a/examples/nucleo_f429zi/pat9125el/project.xml b/examples/nucleo_f429zi/pat9125el/project.xml index d5fcb3bb8a..e0cc9fc9f0 100644 --- a/examples/nucleo_f429zi/pat9125el/project.xml +++ b/examples/nucleo_f429zi/pat9125el/project.xml @@ -8,6 +8,7 @@ modm:io modm:platform:i2c:1 modm:processing:protothread + modm:processing:timer modm:build:scons diff --git a/examples/nucleo_g071rb/apa102/main.cpp b/examples/nucleo_g071rb/apa102/main.cpp index faec621207..76dd75a215 100644 --- a/examples/nucleo_g071rb/apa102/main.cpp +++ b/examples/nucleo_g071rb/apa102/main.cpp @@ -17,7 +17,7 @@ using namespace Board; modm::Apa102 leds; -modm::ShortPeriodicTimer tmr{33}; +modm::ShortPeriodicTimer tmr{33ms}; int main() diff --git a/examples/nucleo_g071rb/blink/main.cpp b/examples/nucleo_g071rb/blink/main.cpp index 7b18c00195..da89431903 100644 --- a/examples/nucleo_g071rb/blink/main.cpp +++ b/examples/nucleo_g071rb/blink/main.cpp @@ -9,6 +9,7 @@ */ #include +#include using namespace Board; @@ -17,6 +18,7 @@ int main() { Board::initialize(); + LedD13::setOutput(modm::Gpio::Low); // Use the logging streams to print some messages. // Change MODM_LOG_LEVEL above to enable or disable these messages @@ -25,15 +27,40 @@ main() MODM_LOG_WARNING << "warning" << modm::endl; MODM_LOG_ERROR << "error" << modm::endl; - LedD13::setOutput(); - static uint8_t counter{0}; + uint32_t counter(0); + modm::PrecisePeriodicTimer tmr(0.500990s); + modm::PeriodicTimer tmrS(0.500990s); + + uint32_t ms_counter{0}; + uint32_t us_counter{0}; while (true) { - LedD13::toggle(); - modm::delay(Button::read() ? 500ms : 1s); + { + uint32_t ms = modm::Clock::now().time_since_epoch().count(); + if (ms < ms_counter) { + MODM_LOG_ERROR << ms << " < " << ms_counter << modm::endl; + } + ms_counter = ms; + }{ + uint32_t us = modm::PreciseClock::now().time_since_epoch().count(); + if (us < us_counter) { + MODM_LOG_ERROR << us << " < " << us_counter << modm::endl; + } + us_counter = us; + } + + if (tmr.execute()) + { + LedD13::toggle(); + + MODM_LOG_INFO << "loop: " << counter++ << modm::endl; + } - MODM_LOG_INFO << "loop: " << counter++ << modm::endl; + if (tmrS.execute()) + { + LedD13::toggle(); + } } return 0; diff --git a/examples/nucleo_g071rb/blink/project.xml b/examples/nucleo_g071rb/blink/project.xml index b44c5e95a6..989fdf8b60 100644 --- a/examples/nucleo_g071rb/blink/project.xml +++ b/examples/nucleo_g071rb/blink/project.xml @@ -5,6 +5,7 @@ modm:platform:gpio + modm:processing:timer modm:build:scons diff --git a/examples/nucleo_l432kc/gyroscope/main.cpp b/examples/nucleo_l432kc/gyroscope/main.cpp index 4a084042b8..5180cc25dd 100644 --- a/examples/nucleo_l432kc/gyroscope/main.cpp +++ b/examples/nucleo_l432kc/gyroscope/main.cpp @@ -52,9 +52,9 @@ class ReaderThread : public modm::pt::Protothread if (PT_CALL(gyro.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); + timeout.restart(100ms); Board::LedD13::set(); - PT_WAIT_UNTIL(this->timeout.isExpired()); + PT_WAIT_UNTIL(timeout.isExpired()); Board::LedD13::reset(); } @@ -73,8 +73,8 @@ class ReaderThread : public modm::pt::Protothread double(averageY.getValue()), double(averageZ.getValue())); - this->timeout.restart(50); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(50ms); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); diff --git a/examples/stm32f072_discovery/can/main.cpp b/examples/stm32f072_discovery/can/main.cpp index 2e62179ab7..a1f518c472 100644 --- a/examples/stm32f072_discovery/can/main.cpp +++ b/examples/stm32f072_discovery/can/main.cpp @@ -97,7 +97,7 @@ main() msg1.data[0] = 0x11; Can::sendMessage(msg1); - modm::ShortPeriodicTimer pTimer(1000); + modm::ShortPeriodicTimer pTimer(1s); const auto silent = static_cast(CAN->BTR & CAN_BTR_SILM); const auto loop_back = static_cast(CAN->BTR & CAN_BTR_LBKM); diff --git a/examples/stm32f072_discovery/rotation/main.cpp b/examples/stm32f072_discovery/rotation/main.cpp index a8d9ba238e..a7b7a6905a 100644 --- a/examples/stm32f072_discovery/rotation/main.cpp +++ b/examples/stm32f072_discovery/rotation/main.cpp @@ -60,8 +60,8 @@ class ReaderThread : public modm::pt::Protothread } // repeat every 5 ms - this->timeout.restart(5); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(5ms); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); diff --git a/examples/stm32f072_discovery/tmp102/main.cpp b/examples/stm32f072_discovery/tmp102/main.cpp index 4dc55da4b2..35dbbcc4be 100644 --- a/examples/stm32f072_discovery/tmp102/main.cpp +++ b/examples/stm32f072_discovery/tmp102/main.cpp @@ -46,8 +46,8 @@ class ThreadOne : public modm::pt::Protothread if (PT_CALL(temp.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } @@ -84,8 +84,8 @@ class ThreadOne : public modm::pt::Protothread stream << modm::endl; if (result) stream << "Heat me up!" << modm::endl; } - this->timeout.restart(200); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(200ms); + PT_WAIT_UNTIL(timeout.isExpired()); Board::LedDown::toggle(); } diff --git a/examples/stm32f072_discovery/tmp102/project.xml b/examples/stm32f072_discovery/tmp102/project.xml index 990eacc9bf..93f529b3e6 100644 --- a/examples/stm32f072_discovery/tmp102/project.xml +++ b/examples/stm32f072_discovery/tmp102/project.xml @@ -10,6 +10,7 @@ modm:platform:i2c:1 modm:platform:uart:1 modm:processing:protothread + modm:processing:timer modm:build:scons diff --git a/examples/stm32f0_discovery/logger/main.cpp b/examples/stm32f0_discovery/logger/main.cpp index aa841d0112..c2cf5c65aa 100644 --- a/examples/stm32f0_discovery/logger/main.cpp +++ b/examples/stm32f0_discovery/logger/main.cpp @@ -49,12 +49,12 @@ main() while (true) { Board::LedBlue::set(); - timeout.restart(100); + timeout.restart(100ms); while(not timeout.isExpired()) {}; Board::LedBlue::reset(); - timeout.restart(900); + timeout.restart(900ms); while(not timeout.isExpired()) {}; diff --git a/examples/stm32f103c8t6_blue_pill/adns_9800/main.cpp b/examples/stm32f103c8t6_blue_pill/adns_9800/main.cpp index 423d6c3b0c..91a7ef4530 100644 --- a/examples/stm32f103c8t6_blue_pill/adns_9800/main.cpp +++ b/examples/stm32f103c8t6_blue_pill/adns_9800/main.cpp @@ -40,7 +40,7 @@ class BlinkThread : public modm::pt::Protothread public: BlinkThread() { - timeout.restart(100); + timeout.restart(100ms); } bool @@ -53,12 +53,12 @@ class BlinkThread : public modm::pt::Protothread Board::LedGreen::reset(); PT_WAIT_UNTIL(timeout.isExpired()); - timeout.restart(100); + timeout.restart(100ms); Board::LedGreen::set(); PT_WAIT_UNTIL(timeout.isExpired()) ; - timeout.restart(4900); + timeout.restart(4.9s); MODM_LOG_INFO << "Seconds since reboot: " << uptime << modm::endl; @@ -76,7 +76,7 @@ class BlinkThread : public modm::pt::Protothread class Adns9800Thread : public modm::pt::Protothread { public: - Adns9800Thread() : timer(10), x(0), y(0) + Adns9800Thread() : timer(10ms), x(0), y(0) { } diff --git a/examples/stm32f103c8t6_blue_pill/environment/thread_blink.cpp b/examples/stm32f103c8t6_blue_pill/environment/thread_blink.cpp index 06ee91218f..4607ac0f37 100644 --- a/examples/stm32f103c8t6_blue_pill/environment/thread_blink.cpp +++ b/examples/stm32f103c8t6_blue_pill/environment/thread_blink.cpp @@ -23,7 +23,7 @@ // ---------------------------------------------------------------------------- BlinkThread::BlinkThread() : - timer(5000), + timer(5s), uptime(0) { } @@ -36,7 +36,7 @@ BlinkThread::update() while (true) { PT_WAIT_UNTIL(timer.execute()); - timeout.restart(100); + timeout.restart(100ms); Board::LedGreen::set(); bmp180Thread.startMeasurement(); diff --git a/examples/stm32f103c8t6_blue_pill/environment/thread_bme280.cpp b/examples/stm32f103c8t6_blue_pill/environment/thread_bme280.cpp index 63079ee718..a9d46443fd 100644 --- a/examples/stm32f103c8t6_blue_pill/environment/thread_bme280.cpp +++ b/examples/stm32f103c8t6_blue_pill/environment/thread_bme280.cpp @@ -53,8 +53,8 @@ Bme280Thread::update() if (PT_CALL(barometerA.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } while(true) @@ -63,8 +63,8 @@ Bme280Thread::update() if (PT_CALL(barometerB.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } // stream << "Barometer BME280 responded" << modm::endl; @@ -76,8 +76,8 @@ Bme280Thread::update() if (PT_CALL(barometerA.initialize())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } while(true) @@ -86,8 +86,8 @@ Bme280Thread::update() if (PT_CALL(barometerB.initialize())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << MODM_FILE_INFO; diff --git a/examples/stm32f103c8t6_blue_pill/environment/thread_bmp180.cpp b/examples/stm32f103c8t6_blue_pill/environment/thread_bmp180.cpp index 17a38c2f71..e9c30fb50b 100644 --- a/examples/stm32f103c8t6_blue_pill/environment/thread_bmp180.cpp +++ b/examples/stm32f103c8t6_blue_pill/environment/thread_bmp180.cpp @@ -53,8 +53,8 @@ Bmp180Thread::update() if (PT_CALL(barometerA.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } while(true) @@ -63,8 +63,8 @@ Bmp180Thread::update() if (PT_CALL(barometerB.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << MODM_FILE_INFO; @@ -77,8 +77,8 @@ Bmp180Thread::update() if (PT_CALL(barometerA.initialize())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } while(true) @@ -87,8 +87,8 @@ Bmp180Thread::update() if (PT_CALL(barometerB.initialize())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << MODM_FILE_INFO; diff --git a/examples/stm32f103c8t6_blue_pill/logger/main.cpp b/examples/stm32f103c8t6_blue_pill/logger/main.cpp index a44f5e3fdc..ab1492b79f 100644 --- a/examples/stm32f103c8t6_blue_pill/logger/main.cpp +++ b/examples/stm32f103c8t6_blue_pill/logger/main.cpp @@ -37,7 +37,7 @@ class BlinkThread : public modm::pt::Protothread public: BlinkThread() { - timeout.restart(100); + timeout.restart(100ms); } bool @@ -50,12 +50,12 @@ class BlinkThread : public modm::pt::Protothread Board::LedGreen::reset(); PT_WAIT_UNTIL(timeout.isExpired()); - timeout.restart(100); + timeout.restart(100ms); Board::LedGreen::set(); PT_WAIT_UNTIL(timeout.isExpired()) ; - timeout.restart(900); + timeout.restart(900ms); MODM_LOG_INFO << "Seconds since reboot: " << ++uptime << modm::endl; } diff --git a/examples/stm32f103c8t6_blue_pill/weight_scale_hx711/main.cpp b/examples/stm32f103c8t6_blue_pill/weight_scale_hx711/main.cpp index 6d950a92df..afb225dcb0 100644 --- a/examples/stm32f103c8t6_blue_pill/weight_scale_hx711/main.cpp +++ b/examples/stm32f103c8t6_blue_pill/weight_scale_hx711/main.cpp @@ -82,7 +82,7 @@ class BlinkThread : public modm::pt::Protothread } protected: - modm::ShortPeriodicTimer timer{1'000}; + modm::ShortPeriodicTimer timer{1s}; }; BlinkThread blink_thread; diff --git a/examples/stm32f1_discovery/logger/main.cpp b/examples/stm32f1_discovery/logger/main.cpp index bfb5dbfef5..4363c77c62 100644 --- a/examples/stm32f1_discovery/logger/main.cpp +++ b/examples/stm32f1_discovery/logger/main.cpp @@ -53,11 +53,11 @@ main() while (true) { Board::LedBlue::set(); - timeout.restart(100); + timeout.restart(100ms); while(not timeout.isExpired()) ; Board::LedBlue::reset(); - timeout.restart(900); + timeout.restart(900ms); while(not timeout.isExpired()) ; MODM_LOG_INFO << "Seconds since reboot: " << ii++ << modm::endl; } diff --git a/examples/stm32f3_discovery/accelerometer/main.cpp b/examples/stm32f3_discovery/accelerometer/main.cpp index 95b0496ad0..dec621cdcd 100644 --- a/examples/stm32f3_discovery/accelerometer/main.cpp +++ b/examples/stm32f3_discovery/accelerometer/main.cpp @@ -61,8 +61,8 @@ class ReaderThread : public modm::pt::Protothread } // repeat every 5 ms - this->timeout.restart(5); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(5ms); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); diff --git a/examples/stm32f3_discovery/can/main.cpp b/examples/stm32f3_discovery/can/main.cpp index 2700f543b8..513c8bd721 100644 --- a/examples/stm32f3_discovery/can/main.cpp +++ b/examples/stm32f3_discovery/can/main.cpp @@ -98,7 +98,7 @@ main() msg1.data[0] = 0x11; Can::sendMessage(msg1); - modm::ShortPeriodicTimer pTimer(100); + modm::ShortPeriodicTimer pTimer(100ms); while (true) { diff --git a/examples/stm32f3_discovery/rotation/main.cpp b/examples/stm32f3_discovery/rotation/main.cpp index 2893c447fa..99771e8e27 100644 --- a/examples/stm32f3_discovery/rotation/main.cpp +++ b/examples/stm32f3_discovery/rotation/main.cpp @@ -76,8 +76,8 @@ class ReaderThread : public modm::pt::Protothread } // repeat every 5 ms - this->timeout.restart(5); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(5ms); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); diff --git a/examples/stm32f469_discovery/blink/main.cpp b/examples/stm32f469_discovery/blink/main.cpp index f0710f23ca..8aad0e1025 100644 --- a/examples/stm32f469_discovery/blink/main.cpp +++ b/examples/stm32f469_discovery/blink/main.cpp @@ -13,6 +13,7 @@ // ---------------------------------------------------------------------------- #include +#include using namespace Board; @@ -21,7 +22,6 @@ int main() { Board::initialize(); - LedD13::setOutput(modm::Gpio::Low); // Use the logging streams to print some messages. // Change MODM_LOG_LEVEL above to enable or disable these messages @@ -31,23 +31,39 @@ main() MODM_LOG_ERROR << "error" << modm::endl; uint32_t counter(0); + modm::PrecisePeriodicTimer tmr(0.500990s); + modm::PeriodicTimer tmrS(0.500990s); + + uint32_t ms_counter{0}; + uint32_t us_counter{0}; while (true) { - LedGreen::toggle(); - modm::delayMilliseconds(Button::read() ? 125 : 500); - - LedOrange::toggle(); - modm::delayMilliseconds(Button::read() ? 125 : 500); + { + uint32_t ms = modm::Clock::now().time_since_epoch().count(); + if (ms < ms_counter) { + MODM_LOG_ERROR << ms << " < " << ms_counter << modm::endl; + } + ms_counter = ms; + }{ + uint32_t us = modm::PreciseClock::now().time_since_epoch().count(); + if (us < us_counter) { + MODM_LOG_ERROR << us << " < " << us_counter << modm::endl; + } + us_counter = us; + } - LedRed::toggle(); - modm::delayMilliseconds(Button::read() ? 125 : 500); + if (tmr.execute()) + { + LedBlue::toggle(); - LedBlue::toggle(); - modm::delayMilliseconds(Button::read() ? 125 : 500); - LedD13::toggle(); + MODM_LOG_INFO << "loop: " << counter++ << modm::endl; + } - MODM_LOG_INFO << "loop: " << counter++ << modm::endl; + if (tmrS.execute()) + { + LedGreen::toggle(); + } } return 0; diff --git a/examples/stm32f469_discovery/blink/project.xml b/examples/stm32f469_discovery/blink/project.xml index 8f43e3a528..96fac5c54b 100644 --- a/examples/stm32f469_discovery/blink/project.xml +++ b/examples/stm32f469_discovery/blink/project.xml @@ -5,6 +5,7 @@ modm:platform:gpio + modm:processing:timer modm:build:scons diff --git a/examples/stm32f469_discovery/can/main.cpp b/examples/stm32f469_discovery/can/main.cpp index 3c5f1385f2..ba51682ea0 100644 --- a/examples/stm32f469_discovery/can/main.cpp +++ b/examples/stm32f469_discovery/can/main.cpp @@ -90,7 +90,7 @@ main() msg1.data[0] = 0x11; Can2::sendMessage(msg1); - modm::ShortPeriodicTimer pTimer(100); + modm::ShortPeriodicTimer pTimer(100ms); while (true) { diff --git a/examples/stm32f469_discovery/can/project.xml b/examples/stm32f469_discovery/can/project.xml index 1ea514d89a..4612114e79 100644 --- a/examples/stm32f469_discovery/can/project.xml +++ b/examples/stm32f469_discovery/can/project.xml @@ -9,6 +9,7 @@ modm:platform:can:2 modm:platform:gpio modm:platform:uart:3 + modm:processing:timer modm:build:scons diff --git a/examples/stm32f469_discovery/game_of_life/main.cpp b/examples/stm32f469_discovery/game_of_life/main.cpp index ad07094c9b..b8e01feef6 100644 --- a/examples/stm32f469_discovery/game_of_life/main.cpp +++ b/examples/stm32f469_discovery/game_of_life/main.cpp @@ -280,9 +280,9 @@ void game_of_life() framebuffers[1] = framebuffer_t(uint32_t(framebuffers[1]) + bw+1); // 30 Hz max refresh rate, or lower - modm::PeriodicTimer timer(33); + modm::PeriodicTimer timer(33ms); // Reseed after a few minutes - modm::PeriodicTimer reseed(60'000 * 3); + modm::PeriodicTimer reseed(180s); bool touch_read = false; init(framebuffers); diff --git a/examples/stm32f4_discovery/accelerometer/main.cpp b/examples/stm32f4_discovery/accelerometer/main.cpp index dc77ad73a2..84067debc0 100644 --- a/examples/stm32f4_discovery/accelerometer/main.cpp +++ b/examples/stm32f4_discovery/accelerometer/main.cpp @@ -66,9 +66,9 @@ class ReaderThread : public modm::pt::Protothread if (PT_CALL(accel.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); + timeout.restart(100ms); Board::LedOrange::set(); - PT_WAIT_UNTIL(this->timeout.isExpired()); + PT_WAIT_UNTIL(timeout.isExpired()); Board::LedOrange::reset(); } @@ -92,8 +92,8 @@ class ReaderThread : public modm::pt::Protothread Board::LedGreen::set(averageY.getValue() < -0.2); Board::LedRed::set(averageY.getValue() > 0.2); - this->timeout.restart(5); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(5ms); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); diff --git a/examples/stm32f4_discovery/adc/oversample/main.cpp b/examples/stm32f4_discovery/adc/oversample/main.cpp index 8889f71354..8692ad5d76 100644 --- a/examples/stm32f4_discovery/adc/oversample/main.cpp +++ b/examples/stm32f4_discovery/adc/oversample/main.cpp @@ -36,7 +36,7 @@ Adc2::Channel sensorMapping[3] = { uint32_t sensorData[3]; // 3 channels and averages of 100 oversamples typedef modm::AdcSampler< AdcInterrupt2, 3, 100 > sensors; -modm::ShortTimeout timeout(100); +modm::ShortTimeout timeout(100ms); // ---------------------------------------------------------------------------- int @@ -70,7 +70,7 @@ main() // start another readout sensors::startReadout(); - timeout.restart(200); + timeout.restart(200ms); } } diff --git a/examples/stm32f4_discovery/app_uart_sniffer/main.cpp b/examples/stm32f4_discovery/app_uart_sniffer/main.cpp index 036959a5bb..3befe5ca98 100644 --- a/examples/stm32f4_discovery/app_uart_sniffer/main.cpp +++ b/examples/stm32f4_discovery/app_uart_sniffer/main.cpp @@ -46,16 +46,16 @@ setDirection(Direction dir) } else { direction = dir; static uint16_t counter = 0; - static modm::Timestamp lastTimestamp = modm::Clock::now(); + static modm::Duration lastTimestamp = modm::Clock::now().time_since_epoch(); - modm::Timestamp timestamp = modm::Clock::now(); + modm::Duration timestamp = modm::Clock::now().time_since_epoch(); MODM_LOG_INFO.printf("\e[39m\n%04" PRId16 " %02" PRId32 ":%03" PRId32 " +%01" PRId32 ":%03" PRId32 " ", counter, - timestamp.getTime() / 1000, - timestamp.getTime() % 1000, - (timestamp.getTime() - lastTimestamp.getTime()) / 1000, - (timestamp.getTime() - lastTimestamp.getTime()) % 1000); + timestamp.count() / 1000, + timestamp.count() % 1000, + (timestamp.count() - lastTimestamp.count()) / 1000, + (timestamp.count() - lastTimestamp.count()) % 1000); switch (direction) { diff --git a/examples/stm32f4_discovery/barometer_bmp085_bmp180/main.cpp b/examples/stm32f4_discovery/barometer_bmp085_bmp180/main.cpp index 7a4bcfca5d..36e23072db 100644 --- a/examples/stm32f4_discovery/barometer_bmp085_bmp180/main.cpp +++ b/examples/stm32f4_discovery/barometer_bmp085_bmp180/main.cpp @@ -55,8 +55,8 @@ class ThreadOne : public modm::pt::Protothread if (PT_CALL(barometer.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } stream << "Device responded" << modm::endl; @@ -68,8 +68,8 @@ class ThreadOne : public modm::pt::Protothread if (PT_CALL(barometer.initialize())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } stream << "Device configured" << modm::endl; @@ -91,7 +91,7 @@ class ThreadOne : public modm::pt::Protothread while (true) { - static modm::ShortPeriodicTimer timer(250); + static modm::ShortPeriodicTimer timer(250ms); PT_WAIT_UNTIL(timer.execute()); diff --git a/examples/stm32f4_discovery/can2/main.cpp b/examples/stm32f4_discovery/can2/main.cpp index 1f2d7f5c5e..c8fc1d9538 100644 --- a/examples/stm32f4_discovery/can2/main.cpp +++ b/examples/stm32f4_discovery/can2/main.cpp @@ -99,7 +99,7 @@ main() msg1.data[0] = 0x11; Can1::sendMessage(msg1); - modm::ShortPeriodicTimer pTimer(100); + modm::ShortPeriodicTimer pTimer(100ms); while (true) { diff --git a/examples/stm32f4_discovery/can2/project.xml b/examples/stm32f4_discovery/can2/project.xml index 2190d514d1..9abdb3be4d 100644 --- a/examples/stm32f4_discovery/can2/project.xml +++ b/examples/stm32f4_discovery/can2/project.xml @@ -9,6 +9,7 @@ modm:platform:can:2 modm:platform:gpio modm:platform:uart:2 + modm:processing:timer modm:build:scons diff --git a/examples/stm32f4_discovery/colour_tcs3414/main.cpp b/examples/stm32f4_discovery/colour_tcs3414/main.cpp index ac31443f07..368a8b5e2d 100644 --- a/examples/stm32f4_discovery/colour_tcs3414/main.cpp +++ b/examples/stm32f4_discovery/colour_tcs3414/main.cpp @@ -61,8 +61,8 @@ class ThreadOne : public modm::pt::Protothread break; } // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } stream << "Device responded" << modm::endl; @@ -73,8 +73,8 @@ class ThreadOne : public modm::pt::Protothread break; } // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } stream << "Device initialized" << modm::endl; @@ -89,8 +89,8 @@ class ThreadOne : public modm::pt::Protothread break; } // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } stream << "Device configured" << modm::endl; @@ -104,8 +104,8 @@ class ThreadOne : public modm::pt::Protothread colors.toHsv(&hsv); stream.printf(" %5d\n", hsv.hue); } - this->timeout.restart(500); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(500ms); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); @@ -132,7 +132,7 @@ main() stream << "\n\nWelcome to TCS3414 demo!\n\n"; - modm::ShortPeriodicTimer tmr(500); + modm::ShortPeriodicTimer tmr(500ms); while (true) { diff --git a/examples/stm32f4_discovery/display/hd44780/main.cpp b/examples/stm32f4_discovery/display/hd44780/main.cpp index ce2d39a5a0..7bd7194fa0 100644 --- a/examples/stm32f4_discovery/display/hd44780/main.cpp +++ b/examples/stm32f4_discovery/display/hd44780/main.cpp @@ -122,8 +122,8 @@ class ThreadOne : public modm::pt::Protothread MODM_LOG_DEBUG << "Device did not respond" << modm::endl; // otherwise, try again in 100ms - this->timeout.restart(1000); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(1s); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << "Device responded" << modm::endl; @@ -167,8 +167,8 @@ class ThreadOne : public modm::pt::Protothread counter++; - this->timeout.restart(1000); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(1s); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); @@ -198,7 +198,7 @@ main() MyI2cMaster::connect(MyI2cMaster::PullUps::Internal); MyI2cMaster::initialize(); - modm::ShortPeriodicTimer tmr(500); + modm::ShortPeriodicTimer tmr(500ms); while(true) { diff --git a/examples/stm32f4_discovery/display/nokia_5110/main.cpp b/examples/stm32f4_discovery/display/nokia_5110/main.cpp index 54c8cf4943..bc1df959b2 100644 --- a/examples/stm32f4_discovery/display/nokia_5110/main.cpp +++ b/examples/stm32f4_discovery/display/nokia_5110/main.cpp @@ -94,8 +94,8 @@ class ThreadOne : public modm::pt::Protothread counter++; - this->timeout.restart(1000); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(1s); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); @@ -126,7 +126,7 @@ main() SpiMaster2::connect(); mySpiMaster::initialize(); - modm::ShortPeriodicTimer tmr(500); + modm::ShortPeriodicTimer tmr(500ms); while(true) { diff --git a/examples/stm32f4_discovery/display/ssd1306/main.cpp b/examples/stm32f4_discovery/display/ssd1306/main.cpp index 900c621ab8..aeea40c8a4 100644 --- a/examples/stm32f4_discovery/display/ssd1306/main.cpp +++ b/examples/stm32f4_discovery/display/ssd1306/main.cpp @@ -40,7 +40,7 @@ main() display << "Hello World!"; display.update(); - modm::ShortPeriodicTimer timer(1000); + modm::ShortPeriodicTimer timer(1s); uint16_t counter(0); while (true) diff --git a/examples/stm32f4_discovery/distance_vl6180/main.cpp b/examples/stm32f4_discovery/distance_vl6180/main.cpp index ea6f0cd2b6..ba1c5851cc 100644 --- a/examples/stm32f4_discovery/distance_vl6180/main.cpp +++ b/examples/stm32f4_discovery/distance_vl6180/main.cpp @@ -64,8 +64,8 @@ class ThreadOne : public modm::pt::Protothread break; } // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << "Device responded" << modm::endl; @@ -75,12 +75,12 @@ class ThreadOne : public modm::pt::Protothread if (PT_CALL(distance.initialize())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << "Device initialized" << modm::endl; - this->timeout.restart(1); + timeout.restart(1ms); PT_CALL(distance.setIntegrationTime(10)); @@ -125,8 +125,8 @@ class ThreadOne : public modm::pt::Protothread MODM_LOG_DEBUG << " \tt=" << (modm::Clock::now() - stamp) << modm::endl; - PT_WAIT_UNTIL(this->timeout.isExpired()); - this->timeout.restart(40); + PT_WAIT_UNTIL(timeout.isExpired()); + timeout.restart(40ms); } PT_END(); @@ -153,7 +153,7 @@ main() MODM_LOG_INFO << "\n\nWelcome to VL6180X demo!\n\n"; - modm::ShortPeriodicTimer tmr(500); + modm::ShortPeriodicTimer tmr(500ms); while (true) { diff --git a/examples/stm32f4_discovery/led_matrix_display/main.cpp b/examples/stm32f4_discovery/led_matrix_display/main.cpp index 3b53d1bfe7..8f0ebf8e73 100644 --- a/examples/stm32f4_discovery/led_matrix_display/main.cpp +++ b/examples/stm32f4_discovery/led_matrix_display/main.cpp @@ -64,7 +64,7 @@ main() ledMatrixDisplay.setFont(modm::font::FixedWidth5x8); ledMatrixDisplay.setCursor(0, 0); - modm::ShortPeriodicTimer countdownTimer(100); + modm::ShortPeriodicTimer countdownTimer(100ms); while (true) { diff --git a/examples/stm32f4_discovery/pressure_ams5915/main.cpp b/examples/stm32f4_discovery/pressure_ams5915/main.cpp index bdd47f7764..f231ee7c43 100644 --- a/examples/stm32f4_discovery/pressure_ams5915/main.cpp +++ b/examples/stm32f4_discovery/pressure_ams5915/main.cpp @@ -64,8 +64,8 @@ class ThreadOne : public modm::pt::Protothread break; } // otherwise, try again in 10ms - this->timeout.restart(10); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(10ms); + PT_WAIT_UNTIL(timeout.isExpired()); } MODM_LOG_DEBUG << "Device responded" << modm::endl; @@ -81,8 +81,8 @@ class ThreadOne : public modm::pt::Protothread MODM_LOG_INFO << "Temperature [degree centigrade]: " << data.getTemperature() << modm::endl; // read next pressure measurement in 1ms - this->timeout.restart(1); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(1ms); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); @@ -107,7 +107,7 @@ main() MODM_LOG_INFO << "\n\nWelcome to AMSYS 5915 pressure sensor demo!\n\n"; - modm::ShortPeriodicTimer tmr(500); + modm::ShortPeriodicTimer tmr(500ms); while (true) { diff --git a/examples/stm32f4_discovery/protothreads/main.cpp b/examples/stm32f4_discovery/protothreads/main.cpp index d196cdaa9e..7e6be3c182 100644 --- a/examples/stm32f4_discovery/protothreads/main.cpp +++ b/examples/stm32f4_discovery/protothreads/main.cpp @@ -46,8 +46,8 @@ class ThreadOne : public modm::pt::Protothread if (PT_CALL(temp.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } @@ -84,8 +84,8 @@ class ThreadOne : public modm::pt::Protothread stream << modm::endl; if (result) stream << "Heat me up!" << modm::endl; } - this->timeout.restart(200); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(200ms); + PT_WAIT_UNTIL(timeout.isExpired()); Board::LedRed::toggle(); } diff --git a/examples/stm32f4_discovery/protothreads/project.xml b/examples/stm32f4_discovery/protothreads/project.xml index 567eb5ab22..6a2aa88f46 100644 --- a/examples/stm32f4_discovery/protothreads/project.xml +++ b/examples/stm32f4_discovery/protothreads/project.xml @@ -10,6 +10,7 @@ modm:platform:i2c:1 modm:platform:uart:2 modm:processing:protothread + modm:processing:timer modm:build:scons diff --git a/examples/stm32f4_discovery/temperature_ltc2984/main.cpp b/examples/stm32f4_discovery/temperature_ltc2984/main.cpp index b154b96afd..9a3214b1fe 100644 --- a/examples/stm32f4_discovery/temperature_ltc2984/main.cpp +++ b/examples/stm32f4_discovery/temperature_ltc2984/main.cpp @@ -81,8 +81,8 @@ class ThreadOne : public modm::pt::Protothread while(!PT_CALL(tempSensor.ping())) { logger << "Device not reachable" << modm::endl; - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } @@ -121,8 +121,8 @@ class ThreadOne : public modm::pt::Protothread logger << "Time: " << (modm::Clock::now() - stamp) << modm::endl; - this->timeout.restart(1000); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(1s); + PT_WAIT_UNTIL(timeout.isExpired()); } PT_END(); diff --git a/examples/stm32f746g_discovery/adc_ad7928/main.cpp b/examples/stm32f746g_discovery/adc_ad7928/main.cpp index d7b83335ae..85c1a754db 100644 --- a/examples/stm32f746g_discovery/adc_ad7928/main.cpp +++ b/examples/stm32f746g_discovery/adc_ad7928/main.cpp @@ -87,7 +87,7 @@ class ThreadOne : public modm::pt::Protothread { MODM_LOG_INFO << PT_CALL(adc.nextSequenceConversion()) << modm::endl; - timeout.restart(500); + timeout.restart(500ms); PT_WAIT_UNTIL(timeout.isExpired()); } diff --git a/examples/stm32f746g_discovery/tmp102/main.cpp b/examples/stm32f746g_discovery/tmp102/main.cpp index 97e894e10e..7921edb050 100644 --- a/examples/stm32f746g_discovery/tmp102/main.cpp +++ b/examples/stm32f746g_discovery/tmp102/main.cpp @@ -41,8 +41,8 @@ class ThreadOne : public modm::pt::Protothread if (PT_CALL(temp.ping())) break; // otherwise, try again in 100ms - this->timeout.restart(100); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); } @@ -79,8 +79,8 @@ class ThreadOne : public modm::pt::Protothread if (result) { MODM_LOG_INFO << " Heat me up!"; } MODM_LOG_INFO << modm::endl; } - this->timeout.restart(200); - PT_WAIT_UNTIL(this->timeout.isExpired()); + timeout.restart(200ms); + PT_WAIT_UNTIL(timeout.isExpired()); Board::LedD13::toggle(); } diff --git a/examples/stm32f746g_discovery/tmp102/project.xml b/examples/stm32f746g_discovery/tmp102/project.xml index 2088e250eb..1b940c166a 100644 --- a/examples/stm32f746g_discovery/tmp102/project.xml +++ b/examples/stm32f746g_discovery/tmp102/project.xml @@ -8,6 +8,7 @@ modm:io modm:platform:i2c:1 modm:processing:protothread + modm:processing:timer modm:build:scons diff --git a/examples/zmq/1_stm32/component_odometry/odometry.cpp b/examples/zmq/1_stm32/component_odometry/odometry.cpp index bc0d4a5246..90b6bf78d7 100644 --- a/examples/zmq/1_stm32/component_odometry/odometry.cpp +++ b/examples/zmq/1_stm32/component_odometry/odometry.cpp @@ -27,7 +27,7 @@ // ---------------------------------------------------------------------------- component::Odometry::Odometry(uint8_t id, xpcc::Dispatcher &communication) : xpcc::AbstractComponent(id, communication), - timer(50) + timer(50ms) { } diff --git a/examples/zmq/1_stm32/main.cpp b/examples/zmq/1_stm32/main.cpp index ec5fde0089..7f1478fb22 100644 --- a/examples/zmq/1_stm32/main.cpp +++ b/examples/zmq/1_stm32/main.cpp @@ -66,7 +66,7 @@ namespace component Odometry odometry(robot::component::ODOMETRY, dispatcher); } -modm::ShortPeriodicTimer tmr(50); +modm::ShortPeriodicTimer tmr(50ms); int main() diff --git a/examples/zmq/4_zmq_backtoback/main.cpp b/examples/zmq/4_zmq_backtoback/main.cpp index 7790b45c08..251e9cb568 100644 --- a/examples/zmq/4_zmq_backtoback/main.cpp +++ b/examples/zmq/4_zmq_backtoback/main.cpp @@ -17,7 +17,7 @@ #include using namespace std::chrono_literals; -modm::PeriodicTimer pt(2000); +modm::PeriodicTimer pt(2s); int main() diff --git a/src/modm/architecture/interface/clock.hpp b/src/modm/architecture/interface/clock.hpp deleted file mode 100644 index 0f7e02143c..0000000000 --- a/src/modm/architecture/interface/clock.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2009-2010, Martin Rosekeit - * Copyright (c) 2009-2011, 2013, 2015, Fabian Greif - * Copyright (c) 2011-2018, Niklas Hauser - * Copyright (c) 2013, Kevin Läufer - * Copyright (c) 2015-2016, Sascha Schade - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#ifndef MODM_INTERFACE_CLOCK_HPP -#define MODM_INTERFACE_CLOCK_HPP - -#include -#include - -namespace modm -{ - -/** - * Interface to the system wide tick timer. - * - * This class maintains a 32-bit counter which is incremented every 1ms. - * - * Example: - * @code - * // Interrupt every 1ms - * ISR(TIMER) - * { - * modm::Clock::increment(); - * } - * @endcode - * @ingroup modm_architecture_clock - */ -class Clock -{ -public: - using Type = uint32_t; - -public: - /// Get the current time, either as `Timestamp` or `LongTimestamp`. - /// Provides an atomic access to the current time - template< typename TimestampType = Timestamp > - static TimestampType - now(); - - static inline ShortTimestamp - nowShort() - { - return now(); - } - -public: - /// Update the current time - static void - increment(uint_fast16_t step = 1); - -protected: - static Type time; -}; - -} // namespace modm - -#endif // MODM_INTERFACE_CLOCK_HPP diff --git a/src/modm/architecture/interface/clock.hpp.in b/src/modm/architecture/interface/clock.hpp.in new file mode 100644 index 0000000000..4bbe4cfd2e --- /dev/null +++ b/src/modm/architecture/interface/clock.hpp.in @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2009-2010, Martin Rosekeit + * Copyright (c) 2009-2011, 2013, 2015, Fabian Greif + * Copyright (c) 2011-2019, Niklas Hauser + * Copyright (c) 2013, Kevin Läufer + * Copyright (c) 2015-2016, Sascha Schade + * Copyright (c) 2019, Raphael Lehmann + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#pragma once + +#include +#include +#include + +namespace modm +{ + +namespace chrono +{ + +/** + * Returns a time_point in milliseconds. + * + * This clock is meant for measuring durations (time differences), not time + * since reboot. You must not depend on this clock for timekeeping, especially + * not over long periods of time, since: + * + * 1. the clock is NOT STEADY! The 32-bit millisecond counter will wrap around + * after ~49 days! + * 2. the clock may have quite some drift and is not synchable to an external + * reference. You must therefore not rely on this clock for very long + * durations that need to be *accurate*. + * + * You must use an actual calendar implementation for proper time keeping! + * + * @ingroup modm_architecture_clock + */ +struct milli_clock +{ + using duration = std::chrono::duration; + using rep = duration::rep; + using period = duration::period; + using time_point = std::chrono::time_point; + + static constexpr bool is_steady = false; + + static time_point + now() noexcept; +}; + +/** + * Returns a time_point in microseconds. + * + * This clock is meant for measuring durations (time differences), not time + * since reboot. You must not depend on this clock for timekeeping, especially + * not over long periods of time, since: + * + * 1. the clock is NOT STEADY! The 32-bit microsecond counter will wrap around + * after 71 minutes! + * 2. the clock may have quite some drift and is not synchable to an external + * reference. You must therefore not rely on this clock for very long + * durations that need to be *accurate*. + * + * You must use an actual calendar implementation for proper time keeping! + * + * @ingroup modm_architecture_clock + */ +struct micro_clock +{ + using duration = std::chrono::duration; + using rep = duration::rep; + using period = duration::period; + using time_point = std::chrono::time_point; + + static constexpr bool is_steady = false; + + static time_point + now() noexcept; +}; + +} // namespace chrono + +using Clock = chrono::milli_clock; +using PreciseClock = chrono::micro_clock; +using namespace ::std::chrono_literals; + +} // namespace modm + +%% if with_io +#include + +template +modm::IOStream& +operator << (modm::IOStream& s, const std::chrono::time_point& m) +{ + s << m.time_since_epoch(); + return s; +} +template +modm::IOStream& +operator << (modm::IOStream& s, const std::chrono::duration& m) +{ + s << m.count(); + if constexpr (std::is_same_v) s << "ns"; + if constexpr (std::is_same_v) s << "us"; + if constexpr (std::is_same_v) s << "ms"; + if constexpr (std::is_same_v>) s << "min"; + if constexpr (std::is_same_v>) s << 'h'; + return s; +} +%% endif + diff --git a/src/modm/architecture/interface/clock.md b/src/modm/architecture/interface/clock.md new file mode 100644 index 0000000000..fd88b0b8f2 --- /dev/null +++ b/src/modm/architecture/interface/clock.md @@ -0,0 +1,45 @@ +# System Clock + +To provide a system-wide time base this module provides two clocks: + +- `modm::Clock`: a 32-bit unsigned millisecond clock running for approx. 49 days + until wrap around, as an optimized replacement of `std::chrono::system_clock`. +- `modm::PreciseClock`: a 32-bit unsigned microsecond clock running for approx. + 71 minutes until wrap around, as an optimized replacement of + `std::chrono::high_resolution_clock`. + +These clocks are intended to measure time intervals: + +```cpp +const auto start = modm::PreciseClock::now(); +how_long_does_this_function_take(); +const auto duration = modm::PreciseClock::now() - start; +MODM_LOG_DEBUG << "Function took " << duration << modm::endl; +``` + +For additional common timeout and periodic timer use-cases also check out the +`modm:processing:timer` module which uses these clocks. + + +## Limitations + +The clocks intended to be very lightweight to use, however, a few interface +tradeoffs had to be made to achieve this goal. + +1. The clocks are **not steady** with their 32-bit counters overflowing after a + relatively short time. They must therefore only be used for measuring + intervals, not absolute time. +2. The clocks have *unsigned* durations to make it easy to work with intervals + since the addition/subtraction of intervals works just fine on clocks + wrapping around, on the important condition that the interval is shorter than + the clocks wrap around time. + +!!! warning "Use a RTC-backed calendar for timekeeping!" + These clocks are definitely not accurate over long periods of time, since + they are based on the internal clock supplies, which may have significant + drift and thus are no replacement for a Real-Time Clock! + +Also check the `modm:platform:clock` module descriptions for additional +limitations on clock resolution and clock drift depending on target. + + diff --git a/src/modm/architecture/interface/delay.hpp b/src/modm/architecture/interface/delay.hpp index 8c1af3c9d9..557a5c1199 100644 --- a/src/modm/architecture/interface/delay.hpp +++ b/src/modm/architecture/interface/delay.hpp @@ -97,6 +97,8 @@ inline void delayMicroseconds(uint32_t us) { delay_us(us); } [[deprecated("Use `modm::delay_ms(uint32_t ms)` instead!")]] inline void delayMilliseconds(uint32_t ms) { delay_ms(ms); } +using namespace ::std::chrono_literals; + } // namespace modm #endif diff --git a/src/modm/architecture/module.lb b/src/modm/architecture/module.lb index f39c81d062..17eea11103 100644 --- a/src/modm/architecture/module.lb +++ b/src/modm/architecture/module.lb @@ -136,15 +136,16 @@ class Can(Module): class Clock(Module): def init(self, module): module.name = "clock" - module.description = "System Tick" + module.description = FileReader("interface/clock.md") def prepare(self, module, options): - module.depends(":processing:timer") + module.depends(":stdc++") return True def build(self, env): + env.substitutions = {"with_io": env.has_module(":io")} env.outbasepath = "modm/src/modm/architecture" - env.copy("interface/clock.hpp") + env.template("interface/clock.hpp.in") # ----------------------------------------------------------------------------- class Delay(Module): diff --git a/src/modm/board/al_avreb_can/board.hpp b/src/modm/board/al_avreb_can/board.hpp index f23f51172e..093e87a0f6 100644 --- a/src/modm/board/al_avreb_can/board.hpp +++ b/src/modm/board/al_avreb_can/board.hpp @@ -46,27 +46,6 @@ initialize() Uart1::connect(); Uart1::initialize(); - // modm::Clock initialization - // Clear Timer on Compare Match Mode - TCCR0A = (1 << WGM01); - TIMSK0 = (1 << OCIE0A); -#if F_CPU > 16'000'000 - // Set and enable output compare A - OCR0A = F_CPU / (1'000ul * 256); - // Set prescaler 256 and enable timer - TCCR0A = (1 << CS02); -#elif F_CPU > 2'000'000 - // Set and enable output compare A - OCR0A = F_CPU / (1'000ul * 64); - // Set prescaler 64 and enable timer - TCCR0A = (1 << CS01) | (1 << CS00); -#elif F_CPU > 1'000'000 - // Set and enable output compare A - OCR0A = F_CPU / (1'000ul * 8); - // Set prescaler 8 and enable timer - TCCR0A = (1 << CS01); -#endif - enableInterrupts(); } diff --git a/src/modm/board/al_avreb_can/board_clock.cpp b/src/modm/board/al_avreb_can/board_clock.cpp deleted file mode 100644 index 49290e7520..0000000000 --- a/src/modm/board/al_avreb_can/board_clock.cpp +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (c) 2016, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include "board.hpp" -#include - -ISR(TIMER0_COMP_vect) -{ - modm::Clock::increment(); -} diff --git a/src/modm/board/arduino_uno/board.hpp b/src/modm/board/arduino_uno/board.hpp index 769cdfa5b7..b5f59bda57 100644 --- a/src/modm/board/arduino_uno/board.hpp +++ b/src/modm/board/arduino_uno/board.hpp @@ -64,27 +64,6 @@ initialize() Uart0::connect(); Uart0::initialize(); - // modm::Clock initialization - // Clear Timer on Compare Match Mode - TCCR0A = (1 << WGM01); - TIMSK0 = (1 << OCIE0A); -#if F_CPU > 16'000'000 - // Set and enable output compare A - OCR0A = F_CPU / (1'000ul * 256); - // Set prescaler 256 and enable timer - TCCR0B = (1 << CS02); -#elif F_CPU > 2'000'000 - // Set and enable output compare A - OCR0A = F_CPU / (1'000ul * 64); - // Set prescaler 64 and enable timer - TCCR0B = (1 << CS01) | (1 << CS00); -#elif F_CPU > 1'000'000 - // Set and enable output compare A - OCR0A = F_CPU / (1'000ul * 8); - // Set prescaler 8 and enable timer - TCCR0B = (1 << CS01); -#endif - enableInterrupts(); } diff --git a/src/modm/board/arduino_uno/board_clock.cpp b/src/modm/board/arduino_uno/board_clock.cpp deleted file mode 100644 index dd204aadfa..0000000000 --- a/src/modm/board/arduino_uno/board_clock.cpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (c) 2016, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include "board.hpp" -#include -#include - -MODM_ISR(TIMER0_COMPA) -{ - modm::Clock::increment(); -} diff --git a/src/modm/communication/amnb/interface.hpp b/src/modm/communication/amnb/interface.hpp index 15bd9e34ef..56b69c9c03 100644 --- a/src/modm/communication/amnb/interface.hpp +++ b/src/modm/communication/amnb/interface.hpp @@ -32,30 +32,6 @@ namespace modm { namespace amnb { - /** - * This clock should run at 10kHz. It is used to provide the back-off - * timer with finer control over timing, which enabled much higher - * throughput. - * When using a very high datarate and short message length this clock - * can be run at higher speeds than the recommended 10kHz. - */ - class Clock - { - public: - static Timestamp - now(); - - /// \brief Set the current time - static inline void - increment(uint_fast16_t step = 1) - { - time += step; - } - - protected: - static uint_fast16_t time; - }; - /** * \internal * \brief Universal base class for the AMNB interface @@ -74,7 +50,7 @@ namespace modm * * \ingroup amnb */ - template + template class Interface { public: @@ -191,7 +167,7 @@ namespace modm update(); #if AMNB_TIMING_DEBUG - static modm::Timestamp latency; + static modm::ShortDuration latency; static uint8_t collisions; #endif @@ -220,7 +196,7 @@ namespace modm static bool hasMessageToSend; static bool messageSent; static bool transmitting; - static modm::Timeout rescheduleTimer; + static modm::PreciseTimeout rescheduleTimer; static uint8_t rescheduleTimeout; static State state; diff --git a/src/modm/communication/amnb/interface_impl.hpp b/src/modm/communication/amnb/interface_impl.hpp index 6e44f06662..320344d7db 100644 --- a/src/modm/communication/amnb/interface_impl.hpp +++ b/src/modm/communication/amnb/interface_impl.hpp @@ -18,20 +18,6 @@ #include -uint_fast16_t modm::amnb::Clock::time = 0; - -modm::Timestamp -modm::amnb::Clock::now() -{ - uint_fast16_t tempTime; - { - atomic::Lock lock; - tempTime = time; - } - - return Timestamp(tempTime); -} - // ---------------------------------------------------------------------------- #ifdef __AVR__ # include @@ -105,7 +91,7 @@ bool modm::amnb::Interface::messageSent = false; #if AMNB_TIMING_DEBUG template -modm::Timestamp modm::amnb::Interface::latency; +modm::ShortDuration modm::amnb::Interface::latency; template uint8_t modm::amnb::Interface::collisions; @@ -118,7 +104,7 @@ void modm::amnb::Interface::initialize(int seed) { srand(seed); - rescheduleTimeout = static_cast(rand()); + rescheduleTimeout = static_cast(rand()) % TIMEOUT; state = SYNC; } @@ -146,7 +132,7 @@ modm::amnb::Interface::writeMessage() rescheduleTransmit = true; Device::resetErrorFlags(); // and wait for a random amount of time before sending again - rescheduleTimer.restart(rescheduleTimeout % TIMEOUT); + rescheduleTimer.restart(std::chrono::microseconds(rescheduleTimeout)); #if AMNB_TIMING_DEBUG ++collisions; #endif @@ -338,8 +324,8 @@ modm::amnb::Interface::update() Device::flushReceiveBuffer(); // and wait for a random amount of time before sending again - rescheduleTimeout = static_cast(rand()); - rescheduleTimer.restart(rescheduleTimeout % TIMEOUT); + rescheduleTimeout = static_cast(rand()) % TIMEOUT; + rescheduleTimer.restart(std::chrono::microseconds(rescheduleTimeout)); state = SYNC; #if AMNB_TIMING_DEBUG ++collisions; @@ -381,7 +367,7 @@ modm::amnb::Interface::update() break; } - resetTimer.restart(resetTimeout); + resetTimer.restart(std::chrono::microseconds(resetTimeout)); } if ((state != SYNC) && resetTimer.isExpired()) state = SYNC; @@ -396,7 +382,7 @@ modm::amnb::Interface::update() // otherwise reschedule else { rescheduleTransmit = true; - rescheduleTimer.restart(rescheduleTimeout % TIMEOUT); + rescheduleTimer.restart(std::chrono::microseconds(rescheduleTimeout % TIMEOUT)); } rescheduleTimeout = static_cast(rand()); } diff --git a/src/modm/communication/amnb/node.hpp b/src/modm/communication/amnb/node.hpp index 1a063975cd..7f9e790c63 100644 --- a/src/modm/communication/amnb/node.hpp +++ b/src/modm/communication/amnb/node.hpp @@ -399,8 +399,8 @@ namespace modm uint8_t expectedAddress; uint8_t expectedResponseLength; modm::ShortTimeout timer; - - static const uint8_t timeout = 10; ///< timeout value in milliseconds + /// timeout value in milliseconds + static constexpr std::chrono::milliseconds timeout{10}; }; } } diff --git a/src/modm/communication/ros/ros_modm_hardware.hpp b/src/modm/communication/ros/ros_modm_hardware.hpp index 6ba0ab99b4..659bb7b945 100644 --- a/src/modm/communication/ros/ros_modm_hardware.hpp +++ b/src/modm/communication/ros/ros_modm_hardware.hpp @@ -64,8 +64,7 @@ class ModmHardware unsigned long time() { - modm::Timestamp ts = modm::Clock::now<>(); - return ts.getTime(); + return modm::Clock::now().time_since_epoch().count(); } }; diff --git a/src/modm/communication/sab/master.hpp b/src/modm/communication/sab/master.hpp index aacfb53890..3341cdd70b 100644 --- a/src/modm/communication/sab/master.hpp +++ b/src/modm/communication/sab/master.hpp @@ -118,8 +118,8 @@ namespace modm static QueryStatus queryStatus; static uint8_t expectedResponseLength; static modm::ShortTimeout timer; - - static const uint8_t timeout = 10; ///< timeout value in milliseconds + /// timeout value in milliseconds + static constexpr std::chrono::milliseconds timeout{10}; }; } } diff --git a/src/modm/communication/xpcc/dispatcher.hpp.in b/src/modm/communication/xpcc/dispatcher.hpp.in index a61318a81b..c495ffc4d2 100644 --- a/src/modm/communication/xpcc/dispatcher.hpp.in +++ b/src/modm/communication/xpcc/dispatcher.hpp.in @@ -39,8 +39,8 @@ namespace xpcc class Dispatcher { public: - static const uint16_t acknowledgeTimeout = {{ options["timeout.acknowledge"] }}; - static const uint16_t responseTimeout = {{ options["timeout.response"] }}; + static constexpr std::chrono::milliseconds acknowledgeTimeout{ {{ options["timeout.acknowledge"] }} }; + static constexpr std::chrono::milliseconds responseTimeout{ {{ options["timeout.response"] }} }; public: Dispatcher(BackendInterface *backend, Postman* postman); diff --git a/src/modm/driver/inertial/hmc6343_impl.hpp b/src/modm/driver/inertial/hmc6343_impl.hpp index f623fec700..bc2269604f 100644 --- a/src/modm/driver/inertial/hmc6343_impl.hpp +++ b/src/modm/driver/inertial/hmc6343_impl.hpp @@ -17,7 +17,7 @@ // ---------------------------------------------------------------------------- template < class I2cMaster > modm::Hmc6343::Hmc6343(Data &data, uint8_t address) -: I2cDevice(address), data(data), timeout(500) +: I2cDevice(address), data(data), timeout(500ms) { } @@ -33,7 +33,7 @@ modm::Hmc6343::writeCommand(Command command, uint16_t timeout) buffer[0] = i(command); RF_WAIT_UNTIL( this->timeout.isExpired() and this->startWrite(buffer, 1) ); - this->timeout.restart(timeout); + this->timeout.restart(std::chrono::milliseconds(timeout)); RF_WAIT_WHILE( this->isTransactionRunning() ); RF_END_RETURN( this->wasTransactionSuccessful() ); @@ -52,7 +52,7 @@ modm::Hmc6343::writeRegister(Register reg, uint8_t value) RF_WAIT_UNTIL( timeout.isExpired() and this->startWrite(buffer, 3) ); - timeout.restart(10); + timeout.restart(10ms); RF_WAIT_WHILE( this->isTransactionRunning() ); RF_END_RETURN( this->wasTransactionSuccessful() ); @@ -91,7 +91,7 @@ modm::Hmc6343::readRegister(Register reg, uint8_t &value) buffer[1] = i(reg); RF_WAIT_UNTIL( timeout.isExpired() and this->startWrite(buffer, 2) ); - timeout.restart(10); + timeout.restart(10ms); RF_WAIT_WHILE( this->isTransactionRunning() ); if( this->wasTransactionSuccessful() ) diff --git a/src/modm/driver/position/vl53l0_impl.hpp b/src/modm/driver/position/vl53l0_impl.hpp index c5e9fec478..2c7b8050fc 100644 --- a/src/modm/driver/position/vl53l0_impl.hpp +++ b/src/modm/driver/position/vl53l0_impl.hpp @@ -60,7 +60,7 @@ modm::Vl53l0::reset() // Wait until the device responds again // After releasing reset it does not accept any I2C transactions // for some time and will respond with NACKs - timeout.restart(500); + timeout.restart(500ms); RF_WAIT_UNTIL(RF_CALL(ping()) or timeout.isExpired()); RF_END_RETURN(not timeout.isExpired()); @@ -659,7 +659,7 @@ modm::Vl53l0::poll(Register reg, Predicate pred, const uint16_t timeo break; } - timeout.restart(stepMs); + timeout.restart(std::chrono::milliseconds(stepMs)); RF_WAIT_UNTIL(timeout.isExpired()); if(index >= stepMs) { diff --git a/src/modm/driver/position/vl6180_impl.hpp b/src/modm/driver/position/vl6180_impl.hpp index 51db483a5d..a5417b444a 100644 --- a/src/modm/driver/position/vl6180_impl.hpp +++ b/src/modm/driver/position/vl6180_impl.hpp @@ -65,6 +65,7 @@ template < typename I2cMaster > modm::ResumableResult modm::Vl6180::readSensor(bool isDistance) { + using namespace std::chrono; // for this relatively complicated sequence, see the datasheet page 17 RF_BEGIN(); @@ -75,7 +76,7 @@ modm::Vl6180::readSensor(bool isDistance) { // Measurement will take 7.5ms + convergence time (< ~10ms) for ranging // or the analog integration time for ALS - timeout.restart(isDistance ? 10 : data.time); + timeout.restart(milliseconds(isDistance ? 10 : data.time)); RF_WAIT_UNTIL(timeout.isExpired()); // When the measurement is completed, the interrupt source of ALS or range @@ -98,7 +99,7 @@ modm::Vl6180::readSensor(bool isDistance) } // otherwise wait 2ms longer on every try - timeout.restart(logicBuffer.byte[0]); + timeout.restart(milliseconds(logicBuffer.byte[0])); logicBuffer.byte[0] += 2; // 168ms timeout @@ -140,7 +141,7 @@ modm::Vl6180::readSensor(bool isDistance) } // otherwise wait 4ms and try again - timeout.restart(4); + timeout.restart(4ms); RF_WAIT_UNTIL(timeout.isExpired()); if (i2cBuffer[3]++ > 15) diff --git a/src/modm/driver/pressure/bmp085_impl.hpp b/src/modm/driver/pressure/bmp085_impl.hpp index 845d75a4dc..0cbf40992c 100644 --- a/src/modm/driver/pressure/bmp085_impl.hpp +++ b/src/modm/driver/pressure/bmp085_impl.hpp @@ -76,7 +76,7 @@ modm::Bmp085::readout() RF_RETURN(false); // Wait until temperature reading is succeeded - timeout.restart(5); + timeout.restart(5ms); RF_WAIT_UNTIL(timeout.isExpired()); // Get the temperature from sensor @@ -101,7 +101,7 @@ modm::Bmp085::readout() RF_RETURN(false); // Wait until sensor has converted the pressure - timeout.restart(conversionDelay[bufferedMode >> 6]); + timeout.restart(std::chrono::milliseconds(conversionDelay[bufferedMode >> 6])); RF_WAIT_UNTIL(timeout.isExpired()); // Get the pressure from sensor diff --git a/src/modm/driver/radio/nrf24/nrf24_data.hpp b/src/modm/driver/radio/nrf24/nrf24_data.hpp index 5ab7be5afd..9e88fe150b 100644 --- a/src/modm/driver/radio/nrf24/nrf24_data.hpp +++ b/src/modm/driver/radio/nrf24/nrf24_data.hpp @@ -241,7 +241,7 @@ class Nrf24Data : modm::Nrf24Register /// Depending on the amount of retransmissions and the auto retransmit delay /// this timeout can become quite large. Worst case is 4000us * 15 = 60ms /// plus some processing times. We consider the worst case here. - static constexpr int sendingInterruptTimeoutMs = 65; + static constexpr std::chrono::milliseconds sendingInterruptTimeoutMs{65}; }; } // namespace modm diff --git a/src/modm/driver/radio/nrf24/nrf24_data_impl.hpp b/src/modm/driver/radio/nrf24/nrf24_data_impl.hpp index 8bf91a0203..f5520a32aa 100644 --- a/src/modm/driver/radio/nrf24/nrf24_data_impl.hpp +++ b/src/modm/driver/radio/nrf24/nrf24_data_impl.hpp @@ -192,8 +192,8 @@ modm::Nrf24Data::getPacket(Packet& packet) // Best effort approach: return average between now and last timestamp, // divide individually to avoid overflow feedbackLastPacket.timestamp = Timestamp( - (feedbackCurrentPacket.timestamp.getTime() / 2) + - (modm::Clock::now().getTime() / 2)); + (feedbackCurrentPacket.timestamp.time_since_epoch() / 2) + + (modm::Clock::now().time_since_epoch() / 2)); } // `currentFeedback` has now been migrated to `feedbackLastPacket` so we diff --git a/src/modm/driver/temperature/ds1631.hpp b/src/modm/driver/temperature/ds1631.hpp index 4ef609c41b..bb4fd7864a 100644 --- a/src/modm/driver/temperature/ds1631.hpp +++ b/src/modm/driver/temperature/ds1631.hpp @@ -186,10 +186,10 @@ class Ds1631 : public ds1631, public I2cDevice< I2cMaster, 2 >, uint8_t buffer[3]; Config_t config; + modm::ShortDuration updateTime; + modm::ShortDuration conversionTime; modm::ShortTimeout periodTimeout; modm::ShortTimeout conversionTimeout; - uint16_t updateTime; - uint8_t conversionTime; }; } // namespace modm diff --git a/src/modm/driver/temperature/ds1631_impl.hpp b/src/modm/driver/temperature/ds1631_impl.hpp index ac259a1a31..3145b4eeea 100644 --- a/src/modm/driver/temperature/ds1631_impl.hpp +++ b/src/modm/driver/temperature/ds1631_impl.hpp @@ -20,7 +20,8 @@ template modm::Ds1631::Ds1631(Data &data, uint8_t address) : I2cDevice(address), data(data), config(0), - periodTimeout(250), conversionTimeout(250), updateTime(250), conversionTime(232) + updateTime(250), conversionTime(232), + periodTimeout(updateTime), conversionTimeout(conversionTime) { this->stop(); } @@ -79,7 +80,7 @@ modm::Ds1631::setUpdateRate(uint8_t rate) RF_RETURN(false); } - updateTime = (1000/rate - 29); + updateTime = modm::ShortDuration(1000/rate - 29); periodTimeout.restart(updateTime); this->restart(); diff --git a/src/modm/driver/temperature/tmp102.hpp b/src/modm/driver/temperature/tmp102.hpp index 0011ec8df8..c53f44b5bf 100644 --- a/src/modm/driver/temperature/tmp102.hpp +++ b/src/modm/driver/temperature/tmp102.hpp @@ -162,8 +162,8 @@ class Tmp102 : public tmp102, public Lm75< I2cMaster >, modm::ResumableResult setLimitRegister(Register reg, float temperature); - modm::ShortTimeout timeout; uint16_t updateTime; + modm::ShortTimeout timeout; Config2_t config_lsb; }; diff --git a/src/modm/driver/temperature/tmp102_impl.hpp b/src/modm/driver/temperature/tmp102_impl.hpp index 0e8e87016c..8c033669e2 100644 --- a/src/modm/driver/temperature/tmp102_impl.hpp +++ b/src/modm/driver/temperature/tmp102_impl.hpp @@ -19,7 +19,7 @@ template < typename I2cMaster > modm::Tmp102::Tmp102(Data &data, uint8_t address) : Lm75(reinterpret_cast(data), address), - timeout(250), updateTime(250), + updateTime(250), timeout(modm::ShortDuration(updateTime)), config_lsb(ConversionRate_t(ConversionRate::Hz4)) { this->stop(); @@ -38,11 +38,11 @@ modm::Tmp102::run() if (updateTime & (1 << 15)) { PT_CALL(startConversion()); - timeout.restart(29); + timeout.restart(29ms); } PT_WAIT_UNTIL(timeout.isExpired()); - timeout.restart(updateTime & ~(1 << 15)); + timeout.restart(std::chrono::milliseconds(updateTime & ~(1 << 15))); PT_CALL(this->readTemperature()); } @@ -86,14 +86,14 @@ modm::Tmp102::setUpdateRate(uint8_t rate) { if (rate == 0) updateTime = 4000; else updateTime = 1000/rate; - timeout.restart(updateTime & ~(1 << 15)); + timeout.restart(std::chrono::milliseconds(updateTime & ~(1 << 15))); RF_RETURN(true); } } else { updateTime = (1000/rate - 29) | (1 << 15); - timeout.restart(updateTime & ~(1 << 15)); + timeout.restart(std::chrono::milliseconds(updateTime & ~(1 << 15))); RF_RETURN(true); } diff --git a/src/modm/driver/temperature/tmp175.hpp b/src/modm/driver/temperature/tmp175.hpp index 83bc4fe9e2..e115556835 100644 --- a/src/modm/driver/temperature/tmp175.hpp +++ b/src/modm/driver/temperature/tmp175.hpp @@ -112,10 +112,10 @@ class Tmp175 : public tmp175, public Lm75< I2cMaster >, modm::ResumableResult setLimitRegister(Register reg, float temperature); + modm::ShortDuration updateTime; + modm::ShortDuration conversionTime; modm::ShortTimeout periodTimeout; modm::ShortTimeout conversionTimeout; - uint16_t updateTime; - uint8_t conversionTime; }; } // namespace modm diff --git a/src/modm/driver/temperature/tmp175_impl.hpp b/src/modm/driver/temperature/tmp175_impl.hpp index 0f8c593bb0..2bdf678d5a 100644 --- a/src/modm/driver/temperature/tmp175_impl.hpp +++ b/src/modm/driver/temperature/tmp175_impl.hpp @@ -19,7 +19,8 @@ template < typename I2cMaster > modm::Tmp175::Tmp175(Data &data, uint8_t address) : Lm75(reinterpret_cast(data), address), - periodTimeout(250), conversionTimeout(250), updateTime(250), conversionTime(232) + updateTime(250), conversionTime(232), + periodTimeout(updateTime), conversionTimeout(conversionTime) { this->stop(); } @@ -62,7 +63,7 @@ modm::Tmp175::setUpdateRate(uint8_t rate) if (rate == 0) rate = 1; if (rate > 33) rate = 33; - updateTime = (1000/rate - 29); + updateTime = modm::ShortDuration(1000/rate - 29); periodTimeout.restart(updateTime); this->restart(); @@ -76,7 +77,7 @@ modm::Tmp175::setResolution(Resolution resolution) Resolution_t::set(reinterpret_cast(this->config_msb), resolution); - conversionTime = (uint8_t(resolution) + 1) * 29; + conversionTime = modm::ShortDuration((uint8_t(resolution) + 1) * 29); RF_END_RETURN_CALL( writeConfiguration() ); } diff --git a/src/modm/platform/can/canusb/canusb_impl.hpp b/src/modm/platform/can/canusb/canusb_impl.hpp index 637a12a7ff..11b22b6569 100644 --- a/src/modm/platform/can/canusb/canusb_impl.hpp +++ b/src/modm/platform/can/canusb/canusb_impl.hpp @@ -53,7 +53,6 @@ template bool modm::platform::CanUsb::open(bitrate_t canBitrate) { - using namespace literals; if (this->serialPort.open()) { MODM_LOG_DEBUG << MODM_FILE_INFO << "SerialPort opened in canusb" << modm::endl; @@ -61,7 +60,7 @@ modm::platform::CanUsb::open(bitrate_t canBitrate) this->serialPort.write("C\r"); modm::ShortTimeout timeout; - timeout.restart(500); + timeout.restart(500ms); while (not timeout.isExpired()) { } @@ -102,7 +101,7 @@ modm::platform::CanUsb::open(bitrate_t canBitrate) - timeout.restart(500); + timeout.restart(500ms); while (not this->serialPort.read(a)) { if (timeout.isExpired()) @@ -120,7 +119,7 @@ modm::platform::CanUsb::open(bitrate_t canBitrate) // Open CAN channel this->serialPort.write("O\r"); MODM_LOG_DEBUG << MODM_FILE_INFO << "written 'O'" << modm::endl; - timeout.restart(500); + timeout.restart(500ms); while (not this->serialPort.read(a)) { if (timeout.isExpired()) diff --git a/src/modm/platform/clock/avr/clock.cpp.in b/src/modm/platform/clock/avr/clock.cpp.in new file mode 100644 index 0000000000..4bab623fa8 --- /dev/null +++ b/src/modm/platform/clock/avr/clock.cpp.in @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2016, Niklas Hauser + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#include "clock.hpp" +#include +#include +#include + +#ifndef TCCR0B +# define TCCR0B TCCR0A +#endif + +#ifndef OCR0A +# define OCR0A OCR0 +#endif + +#ifndef TCCR0A +# define TCCR0A TCCR0 +#endif + +#ifndef TIMER0_COMPA_vect +# define TIMER0_COMPA_vect TIMER0_COMP_vect +#endif + +#ifndef TIMSK0 +# define TIMSK0 TIMSK +#endif + +bool +modm::platform::SystemClock::enable() +{ + // modm::Clock initialization + // Clear Timer on Compare Match Mode + TCCR0B = 0; + TCCR0A = (1 << WGM01); + TIMSK0 = (1 << OCIE0A); + // Set and enable output compare A + OCR0A = {{overflow}}; + +%% if div == 256 + // Set prescaler 256 and enable timer + TCCR0B |= (1 << CS02); +%% elif div == 64 + // Set prescaler 64 and enable timer + TCCR0B |= (1 << CS01) | (1 << CS00); +%% elif div == 8 + // Set prescaler 8 and enable timer + TCCR0B |= (1 << CS01); +%% else + // Set prescaler 1 and enable timer + TCCR0B |= (1 << CS00); +%% endif + return true; +} + +static volatile uint32_t milli_time{0}; +static volatile uint32_t micro_time{0}; +static volatile uint8_t interrupt{false}; + +MODM_ISR(TIMER0_COMPA) +{ + milli_time++; + micro_time += 1000ul; + interrupt = true; +} + +modm::chrono::milli_clock::time_point modm_weak +modm::chrono::milli_clock::now() noexcept +{ + uint32_t time; + do + { // load opportunistically instead of with an atomic lock + interrupt = false; + time = milli_time; + } + while(interrupt); + return time_point{duration{time}}; +} + +modm::chrono::micro_clock::time_point modm_weak +modm::chrono::micro_clock::now() noexcept +{ + uint32_t time; + uint8_t val; + do // We cannot use an atomic lock here, the counter still overflows even + { // if the interrupt hasn't happened yet. And then micro_time is 1000us + // behind thus giving a wrong time. + interrupt = false; + val = TCNT0; + time = micro_time; + } + while(interrupt); + + time += uint16_t(val * uint16_t({{scaler}})) >> {{shift}}; + + return time_point{duration{time}}; +} diff --git a/src/modm/platform/clock/common/static.hpp b/src/modm/platform/clock/avr/clock.hpp similarity index 94% rename from src/modm/platform/clock/common/static.hpp rename to src/modm/platform/clock/avr/clock.hpp index 8eacb13f3a..ba88e9ce9d 100644 --- a/src/modm/platform/clock/common/static.hpp +++ b/src/modm/platform/clock/avr/clock.hpp @@ -45,13 +45,7 @@ SystemClock static constexpr uint32_t Adc = Frequency; - static bool - enable() - { - // do nothing - return true; - } - + static bool enable(); }; } // namespace platform diff --git a/src/modm/platform/clock/avr/module.lb b/src/modm/platform/clock/avr/module.lb new file mode 100644 index 0000000000..07168216d8 --- /dev/null +++ b/src/modm/platform/clock/avr/module.lb @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# +# Copyright (c) 2020, Niklas Hauser +# +# This file is part of the modm project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# ----------------------------------------------------------------------------- + +def init(module): + module.name = ":platform:clock" + module.description = """ +# System Clock via Timer/Counter 0 + +The TC0 timer is used to provide a time point at milli- and microsecond +resolution to implement the `modm::Clock::now()` and `modm::PreciseClock::now()` +interfaces defined in the `modm:architecture:clock` module. + +For this, the timer is configured to trigger a 1ms interrupt to increment the +millisecond counter. To compute the microsecond counter, the 8-bit timer counter +is used to interpolate between milliseconds via a 16x16=16-bit multiplication +and shift to avoid a division. This is very fast, however, the resolution of the +`modm::PreciseClock` is limited to *at best* ~4us (1000us/8-bit) and *at worst* +~32us ((2MHz/64)/1000us). +""" + +def prepare(module, options): + if not options[":target"].has_driver("tc:tc8"): + return False + + # FIXME: Clock is only implemented for a specific version of TC0 + target = options[":target"].identifier + if target.family in {"tiny"} and target.name in {"861", "88"}: + return False + if target.family in {"mega"} and target.name in {"8", "16", "32", "64", "128"}: + return False + + module.depends(":architecture:atomic", ":architecture:clock") + return True + +def build(env): + env.outbasepath = "modm/src/modm/platform/clock" + env.copy("clock.hpp") + + f_cpu = env.get(":platform:core:f_cpu", 8e6) + # Max out the 8-bit counter: F_CPU / div < 256 + if f_cpu <= 250e3: + div = 1 + elif f_cpu <= 2e6: + div = 8 + elif f_cpu <= 16e6: + div = 64 + else: + div = 256 + overflow = int(f_cpu // (div * 1e3)) + shift = 6 # the result is <100us, so <10-bit => 16-bit >> 6 = 10-bit + scaler = int((div * 1e6 * 2**shift) // f_cpu) + + # Never an issue in range 1e3 to 32e6! + # if not (scaler < 2**16 and overflow * scaler < 2**16): + # env.log.error("`modm::PreciseClock` scalar overflowed!") + + env.substitutions = { + "div": div, + "overflow": overflow, + "shift": shift, + "scaler": scaler, + } + env.template("clock.cpp.in") diff --git a/src/modm/platform/clock/common/module.lb b/src/modm/platform/clock/common/module.lb deleted file mode 100644 index 8f799467b9..0000000000 --- a/src/modm/platform/clock/common/module.lb +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# Copyright (c) 2016-2018, Niklas Hauser -# Copyright (c) 2017, Fabian Greif -# -# This file is part of the modm project. -# -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. -# ----------------------------------------------------------------------------- - -def init(module): - module.name = ":platform:clock" - module.description = "System Clock" - -def prepare(module, options): - if options[":target"].has_driver("clock:avr"): - module.depends( - ":architecture:atomic", - ":architecture:clock") - return True - -def build(env): - env.outbasepath = "modm/src/modm/platform/clock" - - if env[":target"].has_driver("clock:avr"): - env.copy("static.hpp") diff --git a/src/modm/platform/clock/stm32/rcc.cpp.in b/src/modm/platform/clock/stm32/rcc.cpp.in index 5e1e6a7481..8e611b1e04 100644 --- a/src/modm/platform/clock/stm32/rcc.cpp.in +++ b/src/modm/platform/clock/stm32/rcc.cpp.in @@ -17,11 +17,13 @@ #include "rcc.hpp" +/// @cond namespace modm::platform { uint16_t modm_fastdata delay_fcpu_MHz({{ hsi_frequency }}); uint16_t modm_fastdata delay_ns_per_loop({{ "{0:,}".format((loops * 1000.0 / hsi_frequency)|int).replace(',', "'") }}); } +/// @endcond // ---------------------------------------------------------------------------- %% if target["family"] == "f0" diff --git a/src/modm/platform/clock/stm32/rcc_impl.hpp.in b/src/modm/platform/clock/stm32/rcc_impl.hpp.in index 6ffdafd33a..b534d4505e 100644 --- a/src/modm/platform/clock/stm32/rcc_impl.hpp.in +++ b/src/modm/platform/clock/stm32/rcc_impl.hpp.in @@ -13,9 +13,10 @@ namespace modm::platform { - +/// @cond extern uint16_t delay_fcpu_MHz; extern uint16_t delay_ns_per_loop; +/// @endcond constexpr Rcc::flash_latency Rcc::computeFlashLatency(uint32_t Core_Hz, uint16_t Core_mV) diff --git a/src/modm/platform/clock/systick/module.lb b/src/modm/platform/clock/systick/module.lb index b6b0fa4470..2c5ee0c389 100644 --- a/src/modm/platform/clock/systick/module.lb +++ b/src/modm/platform/clock/systick/module.lb @@ -1,7 +1,7 @@ #!/usr/bin/env python3 # -*- coding: utf-8 -*- # -# Copyright (c) 2016-2018, Niklas Hauser +# Copyright (c) 2016-2018, 2020, Niklas Hauser # Copyright (c) 2017, Fabian Greif # # This file is part of the modm project. @@ -14,8 +14,8 @@ import os def init(module): - module.name = ":platform:systick" - module.description = "ARM Cortex-M SysTick" + module.name = ":platform:clock" + module.description = FileReader("module.md") def prepare(module, options): if not options[":target"].has_driver("core:cortex-m*"): @@ -34,19 +34,12 @@ def validate(env): raise ValidateException("FreeRTOS frequency must cleanly divide 1kHz for modm::Clock!") def build(env): - device = env[":target"] - driver = device.get_driver("core") - - properties = device.properties - properties["target"] = target = device.identifier - properties["driver"] = driver - properties["core"] = driver["type"] - properties["systick_frequency"] = env.get(":freertos:frequency", 1000) - properties["has_freertos"] = env.has_module(":freertos") - - env.substitutions = properties + core = env[":target"].get_driver("core")["type"] + default = 1000 if "m0" in core else 4 + env.substitutions = { + "systick_frequency": env.get(":freertos:frequency", default), + "has_freertos": env.has_module(":freertos"), + } env.outbasepath = "modm/src/modm/platform/clock" - - # Systick Timer env.template("systick_timer.hpp.in") env.template("systick_timer.cpp.in") diff --git a/src/modm/platform/clock/systick/module.md b/src/modm/platform/clock/systick/module.md new file mode 100644 index 0000000000..2dae3a8d89 --- /dev/null +++ b/src/modm/platform/clock/systick/module.md @@ -0,0 +1,40 @@ +# System Clock via Cortex-M SysTick + +The SysTick timer is used to provide a time point at milli- and microsecond +resolution to implement the `modm::Clock::now()` and `modm::PreciseClock::now()` +interfaces defined in the `modm:architecture:clock` module. + +For this, the timer is configured to run at 1/8th HCLK frequency +and the 24-bit counter is loaded for an interrupt every 250ms (on ARMv7-M) or +every 1ms (ARMv6-M). The interrupt increments the 32-bit counters by 250ms and +250'000us (or 1ms and 1000us) respectively. + +Since this comes nowhere near the 1us resolution we want, the `SysTick->VAL` +counter is used to interpolate the time between interrupts with this algorithm: + +```cpp +uint32_t milli_time{0}; +uint32_t micro_time{0}; +void SysTick_Handler() +{ + milli_time += 250; + micro_time += 250'000; +} + +modm::{Precise}Clock::now() +{ + float cycles_per_ms = (SystemClock::Frequency / 8) / 1e3; + float cycles_per_us = (SystemClock::Frequency / 8) / 1e6; + uint32_t val = SysTick->LOAD - SysTick->VAL; // SysTick->VAL counts down + milliseconds = milli_time + val / cycles_per_ms; + microseconds = micro_time + val / cycles_per_us; +} +``` + +The actual algorithm avoids the floating point division and is instead +approximated with a 32x32=64-bit multiplication and a bit shift without loosing +accuracy. This computation is very, very fast on ARMv7-M. + +However, since ARMv6-M only has a 32x32=32-bit multiplication, the interrupt +runs at 1ms, thus eliminating the multiplication for the millisecond clock, +and allowing to fit into a 32-bit multiplication for the microsecond clock. diff --git a/src/modm/platform/clock/systick/systick_timer.cpp.in b/src/modm/platform/clock/systick/systick_timer.cpp.in index 53c0f2a8ff..734d101473 100644 --- a/src/modm/platform/clock/systick/systick_timer.cpp.in +++ b/src/modm/platform/clock/systick/systick_timer.cpp.in @@ -12,12 +12,14 @@ // ---------------------------------------------------------------------------- #include -#include #include #include "systick_timer.hpp" -static modm::platform::InterruptHandler sysTickHandler(nullptr); +static constexpr auto systick_step({{ 1000 // systick_frequency }}); +static volatile uint32_t milli_time{0}; +static volatile uint32_t micro_time{0}; +static volatile uint8_t interrupt{false}; extern "C" void %% if has_freertos @@ -26,26 +28,29 @@ vApplicationTickHook() SysTick_Handler(void) %% endif { - modm::Clock::increment({{ 1000 // systick_frequency }}); - if (sysTickHandler) sysTickHandler(); + milli_time += systick_step; + micro_time += systick_step * 1'000ul; + interrupt = true; } +// pick the lowest possible priority for the SysTick interrupt +static constexpr uint8_t systick_priority{(1ul << __NVIC_PRIO_BITS) - 1ul}; + // ---------------------------------------------------------------------------- void -modm::platform::SysTickTimer::enable(uint32_t reload) +modm::platform::SysTickTimer::enable(uint32_t modm_unused reload, bool modm_unused prescaler8) { %% if not has_freertos - SysTick->LOAD = reload; // Lower systick interrupt priority to lowest level - NVIC_SetPriority(SysTick_IRQn, 0xf); + NVIC_SetPriority(SysTick_IRQn, systick_priority); - SysTick->VAL = 0; - SysTick->CTRL = - SysTick_CTRL_CLKSOURCE_Msk | - SysTick_CTRL_ENABLE_Msk | - SysTick_CTRL_TICKINT_Msk; -%% else - static_cast(reload); + SysTick->LOAD = reload; + SysTick->VAL = reload; + if (prescaler8) { + SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk; + } else { + SysTick->CTRL = SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_CLKSOURCE_Msk; + } %% endif } @@ -53,21 +58,57 @@ void modm::platform::SysTickTimer::disable() { %% if not has_freertos - SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk; + SysTick->CTRL = 0; %% endif } // ---------------------------------------------------------------------------- -void -modm::platform::SysTickTimer::attachInterruptHandler(InterruptHandler handler) +modm::chrono::milli_clock::time_point modm_weak +modm::chrono::milli_clock::now() noexcept { - atomic::Lock lock; - sysTickHandler = handler; +%% if systick_frequency == 1000 + return time_point{duration{milli_time}}; +%% else + uint32_t val; + uint32_t ms; + do // We cannot use an atomic lock here, the counter still overflows even + { // if the interrupt hasn't happened yet. + interrupt = false; + val = SysTick->VAL; + ms = milli_time; + } + while(interrupt); + const auto diff = SysTick->LOAD - val; + const auto ms_per_Ncycles = platform::SysTickTimer::ms_per_Ncycles; + constexpr auto Ncycles = platform::SysTickTimer::Ncycles; + + ms += (uint64_t(diff) * uint64_t(ms_per_Ncycles)) >> Ncycles; + return time_point{duration{ms}}; +%% endif } -void -modm::platform::SysTickTimer::detachInterruptHandler() +modm::chrono::micro_clock::time_point modm_weak +modm::chrono::micro_clock::now() noexcept { - atomic::Lock lock; - sysTickHandler = nullptr; + uint32_t val; + uint32_t us; + do // We cannot use an atomic lock here, the counter still overflows even + { // if the interrupt hasn't happened yet. + interrupt = false; + val = SysTick->VAL; + us = micro_time; + } + while(interrupt); + const auto diff = SysTick->LOAD - val; + const auto us_per_Ncycles = platform::SysTickTimer::us_per_Ncycles; + constexpr auto Ncycles = platform::SysTickTimer::Ncycles; + +%% if systick_frequency == 1000 + // use a 32x32=32bit multiplication + us += uint32_t(diff * us_per_Ncycles) >> Ncycles; +%% else + // use a 32x32=64bit multiplication + us += (uint64_t(diff) * uint64_t(us_per_Ncycles)) >> Ncycles; +%% endif + return time_point{duration{us}}; } diff --git a/src/modm/platform/clock/systick/systick_timer.hpp.in b/src/modm/platform/clock/systick/systick_timer.hpp.in index cf05978059..db47e7b4bf 100644 --- a/src/modm/platform/clock/systick/systick_timer.hpp.in +++ b/src/modm/platform/clock/systick/systick_timer.hpp.in @@ -13,9 +13,8 @@ #ifndef MODM_CORTEX_SYSTICK_TIMER_HPP #define MODM_CORTEX_SYSTICK_TIMER_HPP -#include -#include #include +#include #include namespace modm::platform @@ -51,11 +50,30 @@ public: static void initialize() { - constexpr auto result = Prescaler::from_range( - SystemClock::Frequency, {{ systick_frequency }}, 1, (1ul << 24)-1); - PeripheralDriver::assertBaudrateInTolerance< result.frequency, {{ systick_frequency }}, tolerance >(); + static_assert(SystemClock::Frequency < (2ull << 24)*8*{{systick_frequency}}, + "HLCK is too fast for the SysTick to run at {{systick_frequency}}Hz!"); + if constexpr (SystemClock::Frequency < 8'000'000) { + constexpr auto result = Prescaler::from_range( + SystemClock::Frequency, {{ systick_frequency }}, 1, (1ul << 24)-1); + PeripheralDriver::assertBaudrateInTolerance< result.frequency, {{ systick_frequency }}, tolerance >(); - enable(result.index); + us_per_Ncycles = ((1ull << Ncycles) * 1'000'000ull) / SystemClock::Frequency; +%% if systick_frequency != 1000 + ms_per_Ncycles = ((1ull << Ncycles) * 1'000ull) / SystemClock::Frequency; +%% endif + enable(result.index, false); + } + else { + constexpr auto result = Prescaler::from_range( + SystemClock::Frequency/8, {{ systick_frequency }}, 1, (1ul << 24)-1); + PeripheralDriver::assertBaudrateInTolerance< result.frequency, {{ systick_frequency }}, tolerance >(); + + us_per_Ncycles = ((1ull << Ncycles) * 8'000'000ull) / SystemClock::Frequency; +%% if systick_frequency != 1000 + ms_per_Ncycles = ((1ull << Ncycles) * 8'000ull) / SystemClock::Frequency; +%% endif + enable(result.index, true); + } } /** @@ -69,28 +87,37 @@ public: static void disable(); - /** - * Passed method will be called periodically on each event. - * Previously passed interrupt handler will be detached. - */ - static void - attachInterruptHandler(InterruptHandler handler); - - /** - * Detaches previously attached interrupt handler. - */ - static void - detachInterruptHandler(); - private: static void - enable(uint32_t reload); + enable(uint32_t reload, bool prescaler8); + +%% if systick_frequency != 1000 + // FCPU < 8MHz + // 536e6/4 < 27-bit, 8e6/4 < 21-bit + // 2^32*1e6/536e6 < 23-bit, 2^32*1e6/8e6 = 29-bit + // FCPU >= 8MHz + // 536e6/8/4 < 24-bit, 8e6/8/4 < 18-bit + // 2^32*8e6/536e6 < 26-bit, 2^32*8e6/8e6 = 32-bit + static constexpr uint8_t Ncycles{32}; + static inline uint32_t ms_per_Ncycles{0}; +%% else + // FCPU < 8MHz + // 536e6/1000 < 20-bit, 8e6/1000 < 13-bit + // 2^20*1e6/536e6 < 11-bit, 2^20*1e6/8e6 = 17-bit + // FCPU >= 8MHz + // 536e6/8/1000 < 17-bit, 8e6/8/1000 < 10-bit + // 2^20*8e6/536e6 < 14-bit, 2^20*8e6/8e6 = 20-bit + static constexpr uint8_t Ncycles{20}; +%% endif + static inline uint32_t us_per_Ncycles{0}; + friend class modm::chrono::milli_clock; + friend class modm::chrono::micro_clock; }; } namespace modm::cortex { - using SysTickTimer [[deprecated("Please use `modm::platform:SysTickTimer` instead")]] = + using SysTickTimer [[deprecated("Use `modm::platform:SysTickTimer` instead!")]] = ::modm::platform::SysTickTimer; } diff --git a/src/modm/platform/core/avr/clock.cpp b/src/modm/platform/core/avr/clock.cpp deleted file mode 100644 index 8f968cfb10..0000000000 --- a/src/modm/platform/core/avr/clock.cpp +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2017-2018, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include -#include - -modm::Clock::Type modm::Clock::time; - -template< typename TimestampType > -TimestampType -modm::Clock::now() -{ - typename TimestampType::Type tempTime; - { - atomic::Lock lock; - tempTime = typename TimestampType::Type(time); - } - return TimestampType(tempTime); -} - -void -modm::Clock::increment(uint_fast16_t step) -{ - time += step; -} - -// explicit declaration of what member function templates we need to generate -template modm::ShortTimestamp modm::Clock::now(); -template modm::Timestamp modm::Clock::now(); diff --git a/src/modm/platform/core/avr/module.lb b/src/modm/platform/core/avr/module.lb index 5ef8400d75..0bce179f2b 100644 --- a/src/modm/platform/core/avr/module.lb +++ b/src/modm/platform/core/avr/module.lb @@ -64,11 +64,6 @@ def build(env): if env.has_module(":architecture:delay"): env.template("delay_impl.hpp.in") - if env.has_module(":architecture:clock"): - # modm-test implements the clock methods itself - if not env.has_module(":test:architecture"): - env.copy("clock.cpp") - env.template("interrupts.hpp.in") if is_xmega: diff --git a/src/modm/platform/core/cortex/atomic_lock_impl.hpp b/src/modm/platform/core/cortex/atomic_lock_impl.hpp.in similarity index 67% rename from src/modm/platform/core/cortex/atomic_lock_impl.hpp rename to src/modm/platform/core/cortex/atomic_lock_impl.hpp.in index 9038a1869e..453a9ed70c 100644 --- a/src/modm/platform/core/cortex/atomic_lock_impl.hpp +++ b/src/modm/platform/core/cortex/atomic_lock_impl.hpp.in @@ -12,17 +12,13 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_PLATFORM_ATOMIC_LOCK_HPP -#define MODM_PLATFORM_ATOMIC_LOCK_HPP +#pragma once -/// @cond #include "../device.hpp" #include -namespace modm -{ - -namespace atomic +/// @cond +namespace modm::atomic { class Lock @@ -63,9 +59,34 @@ class Unlock uint32_t cpsr; }; -} // namespace atomic +%% if "m0" in core +class LockPriority : Lock +{ +public: + modm_always_inline + LockPriority(uint32_t) : Lock() {} +}; +%% else +class LockPriority +{ +public: + modm_always_inline + LockPriority(uint32_t priority) : basepri(__get_BASEPRI()) + { + __set_BASEPRI_MAX(priority << (8u - __NVIC_PRIO_BITS)); + } + + modm_always_inline + ~LockPriority() + { + __set_BASEPRI(basepri); + } -} // namespace modm +private: + uint32_t basepri; +}; +%% endif +} // namespace modm::atomic /// @endcond -#endif // MODM_PLATFORM_ATOMIC_LOCK_HPP + diff --git a/src/modm/platform/core/cortex/clock.cpp b/src/modm/platform/core/cortex/clock.cpp deleted file mode 100644 index 01892bd0bf..0000000000 --- a/src/modm/platform/core/cortex/clock.cpp +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (c) 2017-2018, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include - -modm::Clock::Type modm::Clock::time = 0; - -template< typename TimestampType > -TimestampType -modm::Clock::now() -{ - return typename TimestampType::Type(time); -} - -void -modm::Clock::increment(uint_fast16_t step) -{ - time += step; -} - -// explicit declaration of what member function templates we need to generate -template modm::ShortTimestamp modm::Clock::now(); -template modm::Timestamp modm::Clock::now(); diff --git a/src/modm/platform/core/cortex/module.lb b/src/modm/platform/core/cortex/module.lb index 776d283da8..12df97a3b3 100644 --- a/src/modm/platform/core/cortex/module.lb +++ b/src/modm/platform/core/cortex/module.lb @@ -155,7 +155,6 @@ def prepare(module, options): module.depends( ":architecture:interrupt", - ":platform:clock", ":cmsis:device", ":stdc++") @@ -298,11 +297,6 @@ def build(env): if env.has_module(":architecture:build_id"): env.copy("build_id.cpp") - if env.has_module(":architecture:clock"): - # modm-test implements the clock methods itself - if not env.has_module(":test:architecture"): - env.copy("clock.cpp") - # Heap table from linkerscript if env.has_module(":architecture:memory"): env.template("heap_table.cpp.in") @@ -313,7 +307,7 @@ def build(env): env.template("../../heap/cortex/no_heap.c.in", "no_heap.c") if env.has_module(":architecture:atomic"): - env.copy("atomic_lock_impl.hpp") + env.template("atomic_lock_impl.hpp.in") if env.has_module(":architecture:accessor"): env.copy("flash_reader_impl.hpp") diff --git a/src/modm/platform/core/hosted/clock.cpp b/src/modm/platform/core/hosted/clock.cpp new file mode 100644 index 0000000000..6c24c8a485 --- /dev/null +++ b/src/modm/platform/core/hosted/clock.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Niklas Hauser + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#include + +modm::chrono::milli_clock::time_point modm_weak +modm::chrono::milli_clock::now() noexcept +{ + const auto time = std::chrono::steady_clock::now().time_since_epoch(); + return time_point{std::chrono::duration_cast(time)}; +} + +modm::chrono::micro_clock::time_point modm_weak +modm::chrono::micro_clock::now() noexcept +{ + const auto time = std::chrono::high_resolution_clock::now().time_since_epoch(); + return time_point{std::chrono::duration_cast(time)}; +} diff --git a/src/modm/platform/core/hosted/clock.cpp.in b/src/modm/platform/core/hosted/clock.cpp.in deleted file mode 100644 index fb5a221ee9..0000000000 --- a/src/modm/platform/core/hosted/clock.cpp.in +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2017-2018, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include - -modm::Clock::Type modm::Clock::time = 0; - -%% if target.family in ["darwin", "linux"] -#include - -template< typename TimestampType > -TimestampType -modm::Clock::now() -{ - struct timeval now; - gettimeofday(&now, 0); - - time = typename TimestampType::Type( (now.tv_sec * 1'000) + (now.tv_usec / 1'000) ); - return time; -} - -%% elif target.family == "windows" -#include - -template< typename TimestampType > -TimestampType -modm::Clock::now() -{ - SYSTEMTIME now; - GetSystemTime(&now); - - time = typename TimestampType::Type( now.wMilliseconds + (now.wSecond * 1'000) + (now.wMinute * 1'000 * 60) ); - return time; -} -%% endif - -void -modm::Clock::increment(uint_fast16_t step) -{ - time += step; -} - -// explicit declaration of what member function templates we need to generate -template modm::ShortTimestamp modm::Clock::now(); -template modm::Timestamp modm::Clock::now(); diff --git a/src/modm/platform/core/hosted/module.lb b/src/modm/platform/core/hosted/module.lb index 80180cd89f..8189591c3b 100644 --- a/src/modm/platform/core/hosted/module.lb +++ b/src/modm/platform/core/hosted/module.lb @@ -43,9 +43,7 @@ def build(env): env.copy("../cortex/flash_reader_impl.hpp", "flash_reader_impl.hpp") if env.has_module(":architecture:clock"): - # modm-test implements the clock methods itself - if not env.has_module(":test:architecture"): - env.template("clock.cpp.in") + env.copy("clock.cpp") if target.family == "windows": if env.has_module(":architecture:assert"): diff --git a/src/modm/platform/core/stm32/module.lb b/src/modm/platform/core/stm32/module.lb index ced951aec6..1420827166 100644 --- a/src/modm/platform/core/stm32/module.lb +++ b/src/modm/platform/core/stm32/module.lb @@ -22,7 +22,7 @@ def prepare(module, options): if options[":target"].identifier.platform != "stm32": return False - module.depends(":platform:cortex-m", ":platform:systick") + module.depends(":platform:cortex-m") return True diff --git a/src/modm/processing/protothread/module.md b/src/modm/processing/protothread/module.md index a5a9c89b6e..abda8ceb07 100644 --- a/src/modm/processing/protothread/module.md +++ b/src/modm/processing/protothread/module.md @@ -51,11 +51,11 @@ public: while (true) { - timeout.restart(100); + timeout.restart(100ms); Led::set(); PT_WAIT_UNTIL(timeout.isExpired()); - timeout.restart(200); + timeout.restart(200ms); Led::reset(); PT_WAIT_UNTIL(timeout.isExpired()); } diff --git a/src/modm/processing/resumable/module.md b/src/modm/processing/resumable/module.md index 63528bf8cb..d9a1451303 100644 --- a/src/modm/processing/resumable/module.md +++ b/src/modm/processing/resumable/module.md @@ -138,7 +138,7 @@ public: { RF_BEGIN(); - timeout.restart(new_timeout); + timeout.restart(std::chrono::milliseconds(new_timeout)); if(timeout.isArmed()) { RF_RETURN(true); diff --git a/src/modm/processing/timer/module.lb b/src/modm/processing/timer/module.lb index 8c017df32c..5b165d54f3 100644 --- a/src/modm/processing/timer/module.lb +++ b/src/modm/processing/timer/module.lb @@ -18,6 +18,7 @@ def init(module): def prepare(module, options): module.depends( ":architecture:clock", + ":architecture:assert", ":io", ":math:utils") return True diff --git a/src/modm/processing/timer/module.md b/src/modm/processing/timer/module.md index 52fb320632..c90ad1afac 100644 --- a/src/modm/processing/timer/module.md +++ b/src/modm/processing/timer/module.md @@ -1,141 +1,178 @@ # Software Timers -An implementation of lightweight software timeouts and periodic timers. +This module provides polling based software timers for executing code after a +delay or periodically in millisecond resolution via `modm::Clock` and in +microsecond resolution via `modm::PreciseClock`. -- `modm::Timestamp` containing a time in millisecond resolution up to 49 days. -- `modm::Timeout` for timeouts up to 24 days. -- `modm::PeriodicTimer` for periodic timeouts up to 24 days periods. +To delay or delegate execution to the future, you can use `modm::Timeout` to set +a duration after which the timeout expires and executes your code: -There are also 16-bit versions of these, in case you need to preserve memory: - -- `modm::ShortTimestamp` containing a time in millisecond resolution up to 65 seconds. -- `modm::ShortTimeout` for timeouts up to 32 seconds. -- `modm::ShortPeriodicTimer` for periodic timeouts up to 32 second periods. - -These classes default to using `modm::Clock`, which must be implemented on your -system to return a time with millisecond resolution. - -You may also create your own timers with custom time bases and resolutions -using these classes: +```cpp +modm::Timeout timeout{100ms}; +while (not timeout.isExpired()) ; +// your code after a delay +``` -- `modm::GenericTimestamp`. -- `modm::GenericTimeout`. -- `modm::GenericPeriodicTimer`. +However, this construct is not very useful, particularly since you could also +simply use `modm::delay(100ms)` for this, so instead use the `execute()` +method to poll non-blockingly for expiration: -!!! warning - Never use these classes when a precise timebase is needed! +```cpp +modm::Timeout timeout{100ms}; -## Timeouts +void update() +{ + if (timeout.execute()) + { + // your code after a expiration + } +} +// You must call the update() function in your main loop now! +int main() +{ + while(1) + { + update(); + } +} +``` -The `modm::GenericTimeout` classes allow for a signal to be generated after a -period of time, which can also be used to execute code once after timeout -expiration. +The `execute()` method returns true only once after expiration, so it can be +continuously polled somewhere in your code. A more comfortable use-case is to +use a `modm::Timeout` inside a class that needs to provide some asynchronous +method for timekeeping: -Its behavior can be described by the following annotated waveform: +```cpp +class DelayEvents +{ + modm::Timeout timeout; +public: + void event() { timeout.restart(100ms); } + void update() + { + if (timeout.execute()) { + // delegated code here + } + } +} +``` -- C: Default Constructor -- S: (Re-)Start timeout -- E: Timeout Expired -- H: Code handler (`execute()` returned `true`) -- P: Stop timeout +However, for more complex use-cases, these classes are intended to be used with +Protothreads (from module `modm:processing:protothread`) or Resumable Functions +(from module `modm:processing:resumable`) to implement non-blocking delays. +```cpp +class FancyDelayEvents : public modm::pt::Protothread +{ + modm::Timeout timeout; +public: + void event() + { + this->restart(); // restart entire protothread + } + bool update() + { + PT_BEGIN(); + + // pre-delay computation + timeout.restart(100ms); + PT_WAIT_UNTIL(timeout.isExpired()); + // post-delay computation + + PT_END(); + } +} ``` -Event: C S E H P S E H - _____________ ______________ -Expired: ______________/ \_______________________/ ... - ______ __________ -Armed: _______/ \__________________________/ \______________... - _______ ____________ -Stopped: \____________________/ \_________________________... - _ _ -Handle: ___________________/ \_______________________________/ \___________... +For periodic timeouts, you could simply restart the timeout, however, the +`restart()` method schedules a timeout from the *current* time onwards: -Remaining: 0 | + | - | 0 | + | - +```cpp +void update() +{ + if (timeout.execute()) + { + // delayed code + timeout.restart(); // restarts but with *current* time!!! + } +} - time ——————> ``` -The default constructor initializes the timeout in the `Stopped` state, -in which `isExpired()` and `execute()` never return `true`. -If you need a timeout to expire immidiately after construction, you need -to explicitly initialize the constructor with time `0`, which has the -same behavior as `restart(0)`. - -If you want to execute code once after the timeout expired, poll the -`execute()` method, which returns `true` exactly once after expiration. +This can lead to longer period than required, particularly in a system that has +a lot to do and cannot service every timeout immediately. The solution is to use +a `modm::PeriodicTimer`, which only reimplements the `execute()` method to +automatically restart the timer, by adding the interval to the *old* time, thus +keeping the period accurate: ```cpp -if (timeout.execute()) +modm::PeriodicTimer timer{100ms}; +void update() { - // called once after timeout - Led::toggle(); + if (timer.execute()) // automatically restarts + { + // blink an LED or something + } } ``` -Be aware, however, that since this method is polled, it cannot execute -exactly at the time of expiration, but some time after expiration, as -indicated in the above waveform graph. - -The `remaining()` time until expiration is signed positive before, and -negative after expiration. This means `Clock::now() + Timeout::remaining()` -will yield the timestamp of the expiration. -If the timeout is stopped, `remaining()` returns zero. +The `execute()` method actually returns the number of missed periods, so that in +a heavily congested system you do not need to keep track of time yourself. This +can be particularly useful when dealing with soft-time physical systems like LED +animations or control loops: +```cpp +modm::PeriodicTimer timer{1ms}; // render at 1kHz ideally +void update() +{ + // call only once regarless of the number of periods + if (const size_t periods = timer.execute(); periods) + { + animation.step(periods); // still compute the missing steps + animation.render(); // but only render once please + } + // or alternatively to call the code the number of missed periods + for (auto periods{timer.execute()}; periods; periods--) + { + // periods is decreasing! + } + // This is fine, since execute() is evaluated only once! + for (auto periods : modm::range(timer.execute())) + { + // periods is increasing! + } + // THIS WILL NOT WORK, since execute() reschedules itself immediately! + for (auto periods{0}; periods < timer.execute(); periods++) + { + // called at most only once!!! periods == 0 always! + } +} +``` -## Periodic Timers - -The `modm::GenericPeriodicTimer` class allows for periodic code execution. - -Its behavior can be described by the following annotated waveform: +!!! warning "DO NOT use for hard real time systems!" + You are responsible for polling these timers `execute()` methods as often as + required. If you need to meed hard real time deadlines these are not the + timers you are looking for! -- C: Constructor -- S: (Re-)Start timer -- I: Period interval -- H: Code handler (`execute()` returned `true`) -- P: Stop timer +!!! note "Timers are stopped by default!" + If you want to start a timer at construction time, give the constructor a + duration. Duration Zero will expire the timer immediately -``` -Event: C IH I I H I S IH I IH P - _ _____________ __ _ ______ -Expired: __________/ \_______/ \_____/ \____/ \__/ \____... - __________ _______ _____ ____ __ _ -Armed: \_/ \_____________/ \__/ \_/ \______/ \__... - __ -Stopped: ______________________________________________________________/ ... +## Resolution - _ _ _ _ -Handle: __________/ \___________________/ \_____________/ \_______/ \____... +Two timer resolutions are available, using `modm::Clock` for milliseconds and +`modm::PreciseClock` for microseconds. They follow the same naming scheme: -Remaining: + |0| + | - |0| + | -| + |0| +| - |0|+| 0 +- `modm::Timeout`, `modm::PeriodicTimer`: 49 days in milliseconds and 8 bytes. +- `modm::PreciseTimeout`, `modm::PrecisePeriodicTimer`: 71 mins in microseconds + and 8 bytes. - time ——————> -``` +If you deal with short time periods, you can save a little memory by using the +16-bit versions of the same timers: -If you want to execute code once per period interval, poll the -`execute()` method, which returns `true` exactly once after expiration. +- `modm::ShortTimeout`, `modm::ShortPeriodicTimer`: 65 seconds in milliseconds + and 4 bytes. +- `modm::ShortPreciseTimeout`, `modm::ShortPrecisePeriodicTimer`: 65 + milliseconds in microseconds and 4 bytes. -```cpp -if (timer.execute()) -{ - // periodically called once - Led::toggle(); -} -``` -Be aware, however, that since this method is polled, it cannot execute -exactly at the time of expiration, but some time after expiration, as -indicated in the above waveform graph. -If one or several periods are missed when polling `execute()`, these -code executions are discarded and will not be caught up. -Instead, `execute()` returns `true` once and then reschedules itself -for the next period, without any period skewing. - -Notice, that the `PeriodicTimerState::Expired` is reset to -`PeriodicTimerState::Armed` only after `execute()` has returned `true`. -This is different to the behavior of GenericTimeout, where calls to -`GenericTimeout::execute()` have no impact on class state. - -The `remaining()` time until period expiration is signed positive before, -and negative after period expiration until `execute()` is called. -If the timer is stopped, `remaining()` returns zero. diff --git a/src/modm/processing/timer/periodic_timer.hpp b/src/modm/processing/timer/periodic_timer.hpp index 729cde1164..2f841ead13 100644 --- a/src/modm/processing/timer/periodic_timer.hpp +++ b/src/modm/processing/timer/periodic_timer.hpp @@ -1,9 +1,10 @@ /* * Copyright (c) 2009-2011, 2015, Fabian Greif * Copyright (c) 2010-2011, Georgi Grinshpun - * Copyright (c) 2012, 2015, 2017, Niklas Hauser + * Copyright (c) 2012, 2015, 2017, 2020, Niklas Hauser * Copyright (c) 2013-2014, Kevin Läufer * Copyright (c) 2017, Sascha Schade + * Copyright (c) 2019, Raphael Lehmann * * This file is part of the modm project. * @@ -13,24 +14,12 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_PERIODIC_TIMER_HPP -#define MODM_PERIODIC_TIMER_HPP - +#pragma once #include "timeout.hpp" namespace modm { -/// Possible states of a timer -/// @ingroup modm_processing_timer -enum class -PeriodicTimerState : uint8_t -{ - Stopped = 0, - Expired = 0b010, - Armed = 0b100, -}; - /** * Generic periodic software timeout class for variable timebase and timestamp width. * @@ -38,85 +27,82 @@ PeriodicTimerState : uint8_t * * @tparam Clock * Used clock which inherits from modm::Clock, may have a variable timebase. - * @tparam TimestampType + * @tparam Duration * Used timestamp which is compatible with the chosen Clock. * * @author Fabian Greif * @author Niklas Hauser * @ingroup modm_processing_timer */ -template< class Clock, typename TimestampType = modm::Timestamp > -class GenericPeriodicTimer +template< class Clock, class Duration > +class GenericPeriodicTimer : public GenericTimeout { public: - /// Create a stopped timer - GenericPeriodicTimer(); - - /// Create and start the timer - GenericPeriodicTimer(TimestampType period); - - /// Restart the timer with the current period. - void - restart(); - - /// Restart the timer with a new period value. - void - restart(TimestampType period); - - /// Stops the timer and sets isStopped() to `true`, and isExpired() to `false`. - void - stop(); - - - /// @return `true` exactly once during each period - bool - execute(); - - - /// @return the time until (positive time) or since (negative time) expiration, or 0 if stopped - typename TimestampType::SignedType - remaining() const; - - /// @return the set time period or zero if unset - TimestampType - getPeriod() const; - - - /// @return the current state of the timer - PeriodicTimerState - getState() const; - - /// @return `true` if the timer has been stopped, `false` otherwise - bool - isStopped() const; - -private: - TimestampType period; - GenericTimeout timeout; + // Inherit all constructors + using GenericTimeout::GenericTimeout; + + /** + * For a duration of 0, this function will always expire, but only return 1. + * + * @return the number of missed periods, or zero if not expired yet + */ + size_t + execute() + { + if (GenericTimeout::execute()) + { + size_t count{0}; + if (this->_interval.count()) + { + const typename Clock::time_point now = Clock::now(); + while(1) + { + this->_start += this->_interval; + const auto diff{now - this->_start}; + if (diff != this->_interval) count++; + if (diff < this->_interval) break; + } + } + else { + this->_start = Clock::now(); + count = 1; + } + this->_state = this->ARMED; + return count; + } + return 0; + } }; /** - * Periodic software timer for up to 32 seconds with millisecond resolution. + * Periodic software timer for up to 65 seconds with millisecond resolution. * - * Extra care must be taken when not calling the isExpired() method - * for more than 32 seconds. Due to an overflow in the implementation - * this might add an additional delay of up to 32s ticks in the worst + * Extra care must be taken when not calling the `execute()` method + * for more than 65 seconds. Due to an overflow in the implementation + * this might add an additional delay of up to 65s ticks in the worst * case. - * Always call restart() or restart(time) before reusing the timer - * to avoid this behaviour. + * Always call `restart()` before reusing the timer to avoid this behaviour. * * If you need a longer time period, use PeriodicTimer. * * @ingroup modm_processing_timer */ -using ShortPeriodicTimer = GenericPeriodicTimer< ::modm::Clock, ShortTimestamp>; +using ShortPeriodicTimer = GenericPeriodicTimer< Clock, ShortDuration >; -/// Periodic software timer for up to 24 days with millisecond resolution. +/// Periodic software timer for up to 49 days with millisecond resolution. /// @ingroup modm_processing_timer -using PeriodicTimer = GenericPeriodicTimer< ::modm::Clock, Timestamp>; +using PeriodicTimer = GenericPeriodicTimer< Clock, Duration >; -} // namespace +/// Periodic software timer for up to 65 milliseconds with microsecond resolution. +/// @ingroup modm_processing_timer +using ShortPrecisePeriodicTimer = GenericPeriodicTimer< PreciseClock, ShortPreciseDuration >; -#include "periodic_timer_impl.hpp" +/// Periodic software timer for up to 71 minutes with microsecond resolution. +/// @ingroup modm_processing_timer +using PrecisePeriodicTimer = GenericPeriodicTimer< PreciseClock, PreciseDuration >; -#endif // MODM_PERIODIC_TIMER_HPP +/// @cond +using PeriodicTimerState [[deprecated("Use `modm::TimerState` instead!")]] = TimerState; +/// @endcond + +} // namespace diff --git a/src/modm/processing/timer/periodic_timer_impl.hpp b/src/modm/processing/timer/periodic_timer_impl.hpp deleted file mode 100644 index c39490037d..0000000000 --- a/src/modm/processing/timer/periodic_timer_impl.hpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2009, Martin Rosekeit - * Copyright (c) 2009-2010, Fabian Greif - * Copyright (c) 2010-2011, Georgi Grinshpun - * Copyright (c) 2012, 2015, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#ifndef MODM_PERIODIC_TIMER_HPP -# error "Don't include this file directly, use 'periodic_timeout.hpp' instead!" -#endif - -template< class Clock , typename TimestampType > -modm::GenericPeriodicTimer::GenericPeriodicTimer() : - period(0) -{ -} - -template< class Clock , typename TimestampType > -modm::GenericPeriodicTimer::GenericPeriodicTimer(TimestampType period) : - period(period), timeout(period) -{ -} - -template< class Clock , typename TimestampType > -void -modm::GenericPeriodicTimer::restart() -{ - timeout.restart(period); -} - -template< class Clock , typename TimestampType > -void -modm::GenericPeriodicTimer::restart(TimestampType period) -{ - this->period = period; - restart(); -} - -template< class Clock , typename TimestampType > -void -modm::GenericPeriodicTimer::stop() -{ - timeout.stop(); -} - -template< class Clock, class TimestampType > -modm::PeriodicTimerState -modm::GenericPeriodicTimer::getState() const -{ - return PeriodicTimerState(timeout.getState()); -} - -template< class Clock , typename TimestampType > -bool -modm::GenericPeriodicTimer::isStopped() const -{ - return timeout.isStopped(); -} - -template< class Clock , typename TimestampType > -bool -modm::GenericPeriodicTimer::execute() -{ - if (timeout.execute()) - { - TimestampType now = Clock::template now(); - - do - { - timeout.endTime = timeout.endTime + period; - } - while(timeout.endTime <= now); - - timeout.state = timeout.ARMED; - return true; - } - return false; -} - -template< class Clock, class TimestampType > -typename TimestampType::SignedType -modm::GenericPeriodicTimer::remaining() const -{ - return timeout.remaining(); -} - -template< class Clock, class TimestampType > -TimestampType -modm::GenericPeriodicTimer::getPeriod() const -{ - return period; -} - diff --git a/src/modm/processing/timer/timeout.hpp b/src/modm/processing/timer/timeout.hpp index 9653b7baee..0d959e98c0 100644 --- a/src/modm/processing/timer/timeout.hpp +++ b/src/modm/processing/timer/timeout.hpp @@ -2,8 +2,9 @@ * Copyright (c) 2009-2011, 2015, Fabian Greif * Copyright (c) 2011, Martin Rosekeit * Copyright (c) 2012, Sascha Schade - * Copyright (c) 2012, 2015, Niklas Hauser + * Copyright (c) 2012, 2015, 2020, Niklas Hauser * Copyright (c) 2013, Kevin Läufer + * Copyright (c) 2019, Raphael Lehmann * * This file is part of the modm project. * @@ -13,12 +14,11 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_TIMEOUT_HPP -#define MODM_TIMEOUT_HPP - -#include - +#pragma once #include "timestamp.hpp" +#include +#include +#include namespace modm { @@ -26,15 +26,15 @@ namespace modm /// Possible states of a timeout /// @ingroup modm_processing_timer enum class -TimeoutState : uint8_t +TimerState : uint8_t { - Stopped = 0, + Stopped = 0b001, Expired = 0b010, - Armed = 0b100, + Armed = 0b100, }; // forward declaration for friending -template< class Clock, class TimestampType > +template< class Clock, class Duration > class GenericPeriodicTimer; /** @@ -44,101 +44,134 @@ class GenericPeriodicTimer; * * @tparam Clock * Used clock which inherits from modm::Clock, may have a variable timebase. - * @tparam TimestampType + * @tparam DurationType * Used timestamp which is compatible with the chosen Clock. * * @author Fabian Greif * @author Niklas Hauser * @ingroup modm_processing_timer */ -template< class Clock, class TimestampType = modm::Timestamp > +template< class Clock, class Duration > class GenericTimeout { public: - /// Creates a stopped timeout - GenericTimeout(); + using clock = Clock; + using period = typename Duration::period; + using rep = typename Duration::rep; + using time_point = std::chrono::time_point; + using duration = Duration; + using wide_signed_duration = std::chrono::duration< + modm::WideType>, period>; + + /// Create a stopped timeout + GenericTimeout() = default; /// Create and start the timeout - GenericTimeout(const TimestampType time); + template< typename Rep, typename Period > + GenericTimeout(std::chrono::duration interval); + /// Restart the timer with the current timeout. + void restart(); /// Set a new timeout value. - void - restart(TimestampType time); + template< typename Rep, typename Period > + void restart(std::chrono::duration interval); /// Stops the timer and sets isStopped() to `true`, and isExpired() to `false`. - inline void + void stop(); - - /// @return `true` exactly once, after the timeout expired - bool - execute(); - - /// @return the time until (positive time) or since (negative time) expiration, or 0 if stopped - inline typename TimestampType::SignedType + wide_signed_duration remaining() const; + /// @return the currently set interval + duration + interval() const; /// @return the current state of the timeout - TimeoutState - getState() const; + TimerState + state() const; /// @return `true` if the timeout is stopped, `false` otherwise - inline bool + bool isStopped() const; /// @return `true` if the timeout has expired, `false` otherwise - inline bool + bool isExpired() const; /// @return `true` if the timeout is armed (not stopped and not expired), `false` otherwise - inline bool + bool isArmed() const; -private: - inline bool + /// @return `true` exactly once, after the timeout expired + bool + execute(); + + /// @cond + [[deprecated("Use `std::chrono::{milli,micro}seconds` for interval instead!")]] + GenericTimeout(rep interval) : + GenericTimeout(duration(interval)) {} + [[deprecated("Use `std::chrono::{milli,micro}seconds` for interval instead!")]] + void restart(rep interval) + { restart(duration(interval)); } + [[deprecated("Use `Timeout.state()` instead!")]] + TimerState getState() const { return state(); } + /// @endcond + +protected: + bool checkExpiration() const; -private: enum InternalState : uint8_t { - STOPPED = 0b000, - EXECUTED = 0b001, - EXPIRED = 0b010, - ARMED = 0b100, - STATUS_MASK = 0b110 + STOPPED = int(TimerState::Stopped), + EXPIRED = int(TimerState::Expired), + ARMED = int(TimerState::Armed), + EXECUTED = 0b1000, + STATUS_MASK = (EXPIRED | ARMED | STOPPED) }; - TimestampType endTime; - mutable uint8_t state; + time_point _start{duration{0}}; + duration _interval{0}; + mutable uint8_t _state{STOPPED}; friend class - GenericPeriodicTimer; + GenericPeriodicTimer; }; /** - * Software timeout for up to 32 seconds with millisecond resolution. + * Software timeout for up to 65 seconds with millisecond resolution. * * Extra care must be taken when not calling the isExpired() method - * for more than 32 seconds. Due to an overflow in the implementation - * this might add an additional delay of up to 32s ticks in the worst + * for more than 65 seconds. Due to an overflow in the implementation + * this might add an additional delay of up to 65s ticks in the worst * case. - * Always call restart(time) before reusing the timer to avoid this behaviour. + * Always call restart() before reusing the timer to avoid this behaviour. * * If you need a longer time period, use Timeout. * * @ingroup modm_processing_timer */ -using ShortTimeout = GenericTimeout< ::modm::Clock, ShortTimestamp>; +using ShortTimeout = GenericTimeout< Clock, ShortDuration >; -/// Software timeout for up to 24 days with millisecond resolution. +/// Software timeout for up to 49 days with millisecond resolution. /// @ingroup modm_processing_timer -using Timeout = GenericTimeout< ::modm::Clock, Timestamp>; +using Timeout = GenericTimeout< Clock, Duration >; + +/// Software timeout for up to 65 milliseconds with microsecond resolution. +/// @ingroup modm_processing_timer +using ShortPreciseTimeout = GenericTimeout< PreciseClock, ShortPreciseDuration >; + +/// Software timeout for up to 71 minutes with microsecond resolution. +/// @ingroup modm_processing_timer +using PreciseTimeout = GenericTimeout< PreciseClock, PreciseDuration >; + +/// @cond +using TimeoutState [[deprecated("Use `modm::TimerState` instead!")]] = TimerState; +/// @endcond } // namespace modm #include "timeout_impl.hpp" - -#endif // MODM_TIMEOUT_HPP diff --git a/src/modm/processing/timer/timeout_impl.hpp b/src/modm/processing/timer/timeout_impl.hpp index 70e57a1d30..b1758cec7e 100644 --- a/src/modm/processing/timer/timeout_impl.hpp +++ b/src/modm/processing/timer/timeout_impl.hpp @@ -2,7 +2,8 @@ * Copyright (c) 2009-2010, Fabian Greif * Copyright (c) 2009, 2011, Martin Rosekeit * Copyright (c) 2012, Sascha Schade - * Copyright (c) 2012, 2015, Niklas Hauser + * Copyright (c) 2012, 2015, 2020, Niklas Hauser + * Copyright (c) 2019, Raphael Lehmann * * This file is part of the modm project. * @@ -12,48 +13,61 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_TIMEOUT_HPP -# error "Don't include this file directly, use 'timeout.hpp' instead!" -#endif - -template< class Clock, class TimestampType > -modm::GenericTimeout::GenericTimeout() : - endTime(0), state(STOPPED) +template< class Clock, class Duration > +template< typename Rep, typename Period > +modm::GenericTimeout::GenericTimeout(std::chrono::duration interval) { + restart(interval); } -template< class Clock, class TimestampType > -modm::GenericTimeout::GenericTimeout(const TimestampType time) +template< class Clock, class Duration > +void +modm::GenericTimeout::restart() { - restart(time); + restart(_interval); } -template< class Clock, class TimestampType > +template< class Clock, class Duration > +template< typename Rep, typename Period > void -modm::GenericTimeout::restart(TimestampType time) +modm::GenericTimeout::restart(std::chrono::duration interval) { - endTime = Clock::template now() + time; - state = ARMED; + if (0 <= interval.count()) + { + const auto cast_interval = std::chrono::duration_cast(interval); + modm_assert_continue_fail_debug(interval.count() <= duration::max().count(), "tmr.size", + "Timer interval must be smaller than the maximal duration!", interval.count()); + + _start = std::chrono::time_point_cast(Clock::now()); + _interval = cast_interval; + _state = ARMED; + } + else { + modm_assert_continue_fail_debug(false, "tmr.neg", + "Timer interval must be larger than zero!", interval.count()); + stop(); + } } -template< class Clock, class TimestampType > +template< class Clock, class Duration > void -modm::GenericTimeout::stop() +modm::GenericTimeout::stop() { - state = STOPPED; + _state = STOPPED; + _interval = duration{0}; } // ---------------------------------------------------------------------------- -template< class Clock, class TimestampType > +template< class Clock, class Duration > bool -modm::GenericTimeout::execute() +modm::GenericTimeout::execute() { - if (state & EXECUTED) + if (_state & (EXECUTED | STOPPED)) return false; - if (state == EXPIRED || checkExpiration()) + if ((_state == EXPIRED) or checkExpiration()) { - state = EXPIRED | EXECUTED; + _state = (EXPIRED | EXECUTED); return true; } @@ -61,56 +75,54 @@ modm::GenericTimeout::execute() return false; } -template< class Clock, class TimestampType > -typename TimestampType::SignedType -modm::GenericTimeout::remaining() const +template< class Clock, class Duration > +typename modm::GenericTimeout::wide_signed_duration +modm::GenericTimeout::remaining() const { - if (state != STOPPED) - return (endTime - Clock::template now()).getTime(); - - return 0; + if (_state == STOPPED) + return wide_signed_duration{0}; + return std::chrono::duration_cast(_interval) + + std::chrono::time_point_cast(_start) - + std::chrono::time_point_cast(Clock::now()); } // ---------------------------------------------------------------------------- -template< class Clock, class TimestampType > -modm::TimeoutState -modm::GenericTimeout::getState() const +template< class Clock, class Duration > +modm::TimerState +modm::GenericTimeout::state() const { if (checkExpiration()) - { - state &= ~ARMED; - state |= EXPIRED; - } - return TimeoutState(state & STATUS_MASK); + _state = (_state & ~ARMED) | EXPIRED; + return TimerState(_state & STATUS_MASK); } -template< class Clock, class TimestampType > +template< class Clock, class Duration > bool -modm::GenericTimeout::isStopped() const +modm::GenericTimeout::isStopped() const { // we do not need to use `getState()` here, since stopping a timeout // has to be done by the user, it will not stop itself. - return state == STOPPED; + return _state == STOPPED; } -template< class Clock, class TimestampType > +template< class Clock, class Duration > bool -modm::GenericTimeout::isArmed() const +modm::GenericTimeout::isArmed() const { - return getState() == TimeoutState::Armed; + return state() == TimerState::Armed; } -template< class Clock, class TimestampType > +template< class Clock, class Duration > bool -modm::GenericTimeout::isExpired() const +modm::GenericTimeout::isExpired() const { - return getState() == TimeoutState::Expired; + return state() == TimerState::Expired; } // ---------------------------------------------------------------------------- -template< class Clock, class TimestampType > +template< class Clock, class Duration > bool -modm::GenericTimeout::checkExpiration() const +modm::GenericTimeout::checkExpiration() const { - return (state & ARMED) and (Clock::template now() >= endTime); + return (_state & ARMED) and (Clock::now() - _start) >= _interval; } diff --git a/src/modm/processing/timer/timestamp.hpp b/src/modm/processing/timer/timestamp.hpp index 98122dbd59..88bac0e49d 100644 --- a/src/modm/processing/timer/timestamp.hpp +++ b/src/modm/processing/timer/timestamp.hpp @@ -1,10 +1,6 @@ /* - * Copyright (c) 2009, Georgi Grinshpun - * Copyright (c) 2009-2012, Fabian Greif - * Copyright (c) 2010-2011, Martin Rosekeit - * Copyright (c) 2012-2013, Sascha Schade - * Copyright (c) 2012, 2015, Niklas Hauser - * Copyright (c) 2013, Kevin Läufer + * Copyright (c) 2019, Raphael Lehmann + * Copyright (c) 2020, Niklas Hauser * * This file is part of the modm project. * @@ -14,113 +10,43 @@ */ // ---------------------------------------------------------------------------- -#ifndef MODM_TIMESTAMP_HPP -#define MODM_TIMESTAMP_HPP - -#include - -#include -#include +#pragma once +#include namespace modm { -/** - * Generic timestamp for 16bit and 32bit timestamps of variable timebase. - * - * @author Fabian Greif - * @author Niklas Hauser - * @ingroup modm_processing_timer - */ -template< typename T > -class GenericTimestamp -{ -public: - typedef T Type; - typedef modm::SignedType SignedType; - -public: - /// @param initialTime in ms - GenericTimestamp(const Type initialTime = 0) : - time(initialTime) - { - } - - inline Type - getTime() const - { - return time; - } - - inline GenericTimestamp - operator + (const GenericTimestamp& other) const - { - return GenericTimestamp(time + other.time); - } - - inline GenericTimestamp - operator - (const GenericTimestamp& other) const - { - return GenericTimestamp(time - other.time); - } - - inline bool - operator == (const GenericTimestamp& other) const - { - return (time == other.time); - } - - inline bool - operator != (const GenericTimestamp& other) const - { - return (time != other.time); - } +/// 16bit duration, which can hold up to 65 seconds at millisecond resolution. +/// @ingroup modm_processing_timer +using ShortDuration = std::chrono::duration; - inline bool - operator < (const GenericTimestamp& other) const - { - return SignedType(time - other.time) < 0; - } +/// 32bit duration, which can hold up to 49 days at millisecond resolution. +/// @ingroup modm_processing_timer +using Duration = std::chrono::duration; - inline bool - operator > (const GenericTimestamp& other) const - { - return SignedType(time - other.time) > 0; - } +/// 16bit precise duration, which can hold up to 65 milliseconds at microsecond resolution. +/// @ingroup modm_processing_timer +using ShortPreciseDuration = std::chrono::duration; - inline bool - operator <= (const GenericTimestamp& other) const - { - return SignedType(time - other.time) <= 0; - } +/// 32bit precise duration, which can hold up to 71 minutes at microsecond resolution. +/// @ingroup modm_processing_timer +using PreciseDuration = std::chrono::duration; - inline bool - operator >= (const GenericTimestamp& other) const - { - return SignedType(time - other.time) >= 0; - } -private: - Type time; -}; +/// 16bit time point, which can hold up to 65 seconds at millisecond resolution. +/// @ingroup modm_processing_timer +using ShortTimestamp = std::chrono::time_point; -/// 16bit timestamp, which can hold up to 65 seconds at millisecond resolution. +/// 32bit time point, which can hold up to 49 days at millisecond resolution. /// @ingroup modm_processing_timer -using ShortTimestamp = GenericTimestamp; +using Timestamp = modm::chrono::milli_clock::time_point; -/// 32bit timestamp, which can hold up to 49 days at millisecond resolution. +/// 16bit precise time point, which can hold up to 65 milliseconds at microsecond resolution. /// @ingroup modm_processing_timer -using Timestamp = GenericTimestamp; +using ShortPreciseTimestamp = std::chrono::time_point; -// ------------------------------------------------------------------------ -template< typename T > -inline IOStream& -operator << (IOStream& os, const GenericTimestamp& t) -{ - os << t.getTime(); - return os; -} +/// 32bit precise time point, which can hold up to 71 minutes at microsecond resolution. +/// @ingroup modm_processing_timer +using PreciseTimestamp = modm::chrono::micro_clock::time_point; } // namespace modm - -#endif // MODM_TIMESTAMP_HPP diff --git a/src/modm/ui/animation/base.hpp b/src/modm/ui/animation/base.hpp index b074b45b77..3160498534 100644 --- a/src/modm/ui/animation/base.hpp +++ b/src/modm/ui/animation/base.hpp @@ -45,12 +45,9 @@ class Animation using Handler = void(*)(T); public: - /// @param value a reference to the value to be animated - Animation(T &value); - /// @param value a reference to the value to be animated /// @param handler this function will be called whenever the value has been changed - Animation(T &value, Handler handler); + Animation(T &value, Handler handler=nullptr); /// @param handler this function will be called whenever the value has been changed void @@ -89,8 +86,8 @@ class Animation private: Handler handler; T ¤tValue; - T endValue; - TimeType animationTime; + T endValue{0}; + TimeType animationTime{0}; modm::ShortTimestamp previous; FastRamp interpolation; }; diff --git a/src/modm/ui/animation/base_impl.hpp b/src/modm/ui/animation/base_impl.hpp index d0f77765de..ba5fc7e4a4 100644 --- a/src/modm/ui/animation/base_impl.hpp +++ b/src/modm/ui/animation/base_impl.hpp @@ -14,16 +14,9 @@ #endif // ---------------------------------------------------------------------------- -template< typename T > -modm::ui::Animation::Animation(T &value) -: Animation(value, nullptr) -{ -} - template< typename T > modm::ui::Animation::Animation(T &value, Handler handler) -: handler(handler), currentValue(value), endValue(0), - animationTime(0), previous(0) +: handler(handler), currentValue(value) { } @@ -85,7 +78,7 @@ modm::ui::Animation::animateTo(T value, TimeType time) endValue = value; animationTime = time; interpolation.initialize(currentValue, endValue, animationTime); - previous = modm::Clock::nowShort(); + previous = modm::Clock::now(); return true; } @@ -101,11 +94,11 @@ modm::ui::Animation::update() if (animationTime > 0) { // buffer the delta time - modm::ShortTimestamp now = modm::Clock::nowShort(); + const modm::ShortTimestamp now = modm::Clock::now(); // this cast requires us to be updates once at least every 255ms // If this method is not called every few ms, the animation does // not look good anyways, so this limitation is okay. - uint_fast8_t delta = (now - previous).getTime(); + uint_fast8_t delta = (now - previous).count(); // check if at least 1ms has passed if (delta) diff --git a/src/modm/ui/gui/types.hpp b/src/modm/ui/gui/types.hpp index 04280d0341..0179ef3c2f 100644 --- a/src/modm/ui/gui/types.hpp +++ b/src/modm/ui/gui/types.hpp @@ -99,7 +99,7 @@ class AsyncEvent AsyncEvent(uint16_t delayMilliseconds, genericCallback cb, void* cb_data) : cb(cb), cb_data(cb_data), - timeout(delayMilliseconds), + timeout(std::chrono::milliseconds(delayMilliseconds)), already_run(false) { } diff --git a/src/modm/ui/menu/choice_menu.hpp b/src/modm/ui/menu/choice_menu.hpp index f63b8e4401..b1ab6e73f5 100644 --- a/src/modm/ui/menu/choice_menu.hpp +++ b/src/modm/ui/menu/choice_menu.hpp @@ -93,7 +93,7 @@ namespace modm{ openNextScreen() = 0; private: - uint16_t display_update_time; + modm::ShortDuration display_update_time; modm::ShortPeriodicTimer timer; bool buttonAction; diff --git a/src/modm/ui/menu/standard_menu.cpp b/src/modm/ui/menu/standard_menu.cpp index 779acb4f4c..2e606597e3 100644 --- a/src/modm/ui/menu/standard_menu.cpp +++ b/src/modm/ui/menu/standard_menu.cpp @@ -22,7 +22,7 @@ modm::MenuEntry::MenuEntry(const char* text, uint16_t space, MenuEntryCallback f modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier) : modm::AbstractMenu(stack, identifier), display_update_time(500), - timer(display_update_time), + timer(std::chrono::milliseconds(display_update_time)), buttonAction(false), title(""), homePosition(0), @@ -34,7 +34,7 @@ modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier) : modm::StandardMenu::StandardMenu(modm::ViewStack* stack, uint8_t identifier, const char* title) : modm::AbstractMenu(stack, identifier), display_update_time(500), - timer(display_update_time), + timer(std::chrono::milliseconds(display_update_time)), buttonAction(false), title(title), homePosition(0), diff --git a/src/modm/ui/menu/standard_menu.hpp b/src/modm/ui/menu/standard_menu.hpp index de90a31852..c7c9e92e40 100644 --- a/src/modm/ui/menu/standard_menu.hpp +++ b/src/modm/ui/menu/standard_menu.hpp @@ -116,7 +116,7 @@ namespace modm inline void setUpdateTime(uint16_t ms) { this->display_update_time = ms; - this->timer.restart(ms); + this->timer.restart(std::chrono::milliseconds(ms)); } private: diff --git a/test/modm/architecture/driver/clock_test.cpp b/test/modm/architecture/driver/clock_test.cpp index 7e9b4d2fd3..8014553efa 100644 --- a/test/modm/architecture/driver/clock_test.cpp +++ b/test/modm/architecture/driver/clock_test.cpp @@ -13,43 +13,29 @@ // ---------------------------------------------------------------------------- #include "clock_test.hpp" -#include +#include +#include +using test_clock = modm_test::chrono::milli_clock; void ClockTest::testClock() { - // test 16bit timestamp "ShortTimestamp" - TestingClock::time = 0; - TEST_ASSERT_EQUALS(modm::Clock::nowShort(), modm::ShortTimestamp(0)); - - TestingClock::time = 10; - TEST_ASSERT_EQUALS(modm::Clock::nowShort(), modm::ShortTimestamp(10)); - - TestingClock::time = 65'000; - TEST_ASSERT_EQUALS(modm::Clock::nowShort(), modm::ShortTimestamp(65'000)); - - TestingClock::time = 65'535; - TEST_ASSERT_EQUALS(modm::Clock::nowShort(), modm::ShortTimestamp(65'535)); - - // overflow in timestamp, but not the Clock! - TestingClock::time = 65'536; - TEST_ASSERT_EQUALS(modm::Clock::nowShort(), modm::ShortTimestamp(0)); - - + using time_point = modm::Clock::time_point; + using duration = modm::Clock::duration; // test 32bit timestamp "Timestamp" - TestingClock::time = 0; - TEST_ASSERT_EQUALS(modm::Clock::now(), modm::Timestamp(0)); + test_clock::setTime(0); + TEST_ASSERT_EQUALS(modm::Clock::now(), time_point(duration(0))); - TestingClock::time = 10; - TEST_ASSERT_EQUALS(modm::Clock::now(), modm::Timestamp(10)); + test_clock::setTime(10); + TEST_ASSERT_EQUALS(modm::Clock::now(), time_point(duration(10))); - TestingClock::time = 65'536; - TEST_ASSERT_EQUALS(modm::Clock::now(), modm::Timestamp(65'536)); + test_clock::setTime(65'536); + TEST_ASSERT_EQUALS(modm::Clock::now(), time_point(duration(65'536))); - TestingClock::time = 4'294'967'295; - TEST_ASSERT_EQUALS(modm::Clock::now(), modm::Timestamp(4'294'967'295)); + test_clock::setTime(4'294'967'295); + TEST_ASSERT_EQUALS(modm::Clock::now(), time_point(duration(4'294'967'295))); // overflow in both timestamp and Clock! - TestingClock::time = uint32_t(4'294'967'296); - TEST_ASSERT_EQUALS(modm::Clock::now(), modm::Timestamp(0)); + test_clock::setTime(uint32_t(4'294'967'296)); + TEST_ASSERT_EQUALS(modm::Clock::now(), time_point(duration(0))); } diff --git a/test/modm/architecture/module.lb b/test/modm/architecture/module.lb index 2e1c5feb2b..9e6dc5c366 100644 --- a/test/modm/architecture/module.lb +++ b/test/modm/architecture/module.lb @@ -17,7 +17,7 @@ def init(module): def prepare(module, options): module.depends( - ":mock:clock.testing", + ":mock:clock", "modm:architecture:accessor", "modm:architecture:atomic", "modm:architecture:can", @@ -28,11 +28,5 @@ def prepare(module, options): def build(env): env.outbasepath = "modm-test/src/modm-test/architecture" + env.copy('.') - ignore_patterns = [] - target = env[":target"].identifier - if target["platform"] == "hosted": - # Test does not work on hosted - ignore_patterns.append("*driver/clock_test.*") - - env.copy('.', ignore=env.ignore_patterns(*ignore_patterns)) diff --git a/test/modm/communication/module.lb b/test/modm/communication/module.lb index 7433c43450..93175ceb51 100644 --- a/test/modm/communication/module.lb +++ b/test/modm/communication/module.lb @@ -28,7 +28,7 @@ class Xpcc(Module): module.name = "xpcc" def prepare(self, module, options): - module.depends("modm:communication:xpcc", ":mock:clock.testing") + module.depends("modm:communication:xpcc", ":mock:clock") return True def build(self, env): diff --git a/test/modm/communication/xpcc/dispatcher_test.cpp b/test/modm/communication/xpcc/dispatcher_test.cpp index c41317c0e1..0d900d4791 100644 --- a/test/modm/communication/xpcc/dispatcher_test.cpp +++ b/test/modm/communication/xpcc/dispatcher_test.cpp @@ -14,7 +14,8 @@ #define UNITTEST_RETURN_ON_FAIL #include "dispatcher_test.hpp" -#include +#include +using test_clock = modm_test::chrono::milli_clock; // ---------------------------------------------------------------------------- void @@ -399,7 +400,7 @@ DispatcherTest::testActionRetransmissionWithAbort() backend->messagesSend.removeAll(); // reset time so that the timeout is expired - TestingClock::time += 500; + test_clock::increment(500); dispatcher->update(); } @@ -427,7 +428,7 @@ DispatcherTest::testActionRetransmission() if (i == 0) { // reset time so that the timeout is expired - TestingClock::time += 500; + test_clock::increment(500); } dispatcher->update(); @@ -439,7 +440,7 @@ DispatcherTest::testActionRetransmission() modm::SmartPointer())); // reset time so that the timeout is expired - TestingClock::time += 500; + test_clock::increment(500); dispatcher->update(); @@ -477,7 +478,7 @@ DispatcherTest::testResponseRetransmissionWithAbort() backend->messagesSend.removeFront(); // reset time so that the timeout is expired - TestingClock::time += 500; + test_clock::increment(500); dispatcher->update(); } @@ -509,7 +510,7 @@ DispatcherTest::testResponseRetransmission() if (i == 0) { // reset time so that the timeout is expired - TestingClock::time += 500; + test_clock::increment(500); } dispatcher->update(); @@ -521,7 +522,7 @@ DispatcherTest::testResponseRetransmission() modm::SmartPointer())); // reset time so that the timeout is expired if still active - TestingClock::time += 100; + test_clock::increment(100); dispatcher->update(); diff --git a/test/modm/mock/clock.cpp b/test/modm/mock/clock.cpp new file mode 100644 index 0000000000..c44dad1119 --- /dev/null +++ b/test/modm/mock/clock.cpp @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2018, Niklas Hauser + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#include +#include "clock.hpp" + +// ---------------------------------------------------------------------------- +static uint32_t milli_time{0}; + +modm::chrono::milli_clock::time_point +modm::chrono::milli_clock::now() noexcept +{ + return time_point{duration{milli_time}}; +} + +void +modm_test::chrono::milli_clock::setTime(uint32_t milliseconds) +{ + milli_time = milliseconds; +} + +void +modm_test::chrono::milli_clock::increment(uint32_t milliseconds) +{ + milli_time += milliseconds; +} + +// ---------------------------------------------------------------------------- +static uint32_t micro_time{0}; + +modm::chrono::micro_clock::time_point +modm::chrono::micro_clock::now() noexcept +{ + return time_point{duration{micro_time}}; +} + +void +modm_test::chrono::micro_clock::setTime(uint32_t microseconds) +{ + micro_time = microseconds; +} + +void +modm_test::chrono::micro_clock::increment(uint32_t microseconds) +{ + micro_time += microseconds; +} diff --git a/test/modm/mock/clock.hpp b/test/modm/mock/clock.hpp new file mode 100644 index 0000000000..df8e883591 --- /dev/null +++ b/test/modm/mock/clock.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020, Niklas Hauser + * + * This file is part of the modm project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +// ---------------------------------------------------------------------------- + +#pragma once +#include +#include + +/// @ingroup modm_test_mock_clock +namespace modm_test::chrono +{ + +class milli_clock : modm::chrono::milli_clock +{ +public: + static inline void setTime(std::chrono::milliseconds time) + { setTime(time.count()); } + static void setTime(uint32_t milliseconds); + + static inline void increment(std::chrono::milliseconds time) + { increment(time.count()); } + static void increment(uint32_t milliseconds); +}; + +class micro_clock : modm::chrono::micro_clock +{ +public: + static inline void setTime(std::chrono::microseconds time) + { setTime(time.count()); } + static void setTime(uint32_t microseconds); + + static inline void increment(std::chrono::microseconds time) + { increment(time.count()); } + static void increment(uint32_t microseconds); +}; + +} // namespace modm_test diff --git a/test/modm/mock/clock_dummy.cpp b/test/modm/mock/clock_dummy.cpp deleted file mode 100644 index 824393277a..0000000000 --- a/test/modm/mock/clock_dummy.cpp +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (c) 2017, Fabian Greif - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include "clock_dummy.hpp" - -modm::Timestamp modm::ClockDummy::time; diff --git a/test/modm/mock/clock_dummy.hpp b/test/modm/mock/clock_dummy.hpp deleted file mode 100644 index b5eda3d032..0000000000 --- a/test/modm/mock/clock_dummy.hpp +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright (c) 2017, Fabian Greif - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#ifndef MODM_CLOCK_DUMMY_HPP -#define MODM_CLOCK_DUMMY_HPP - -#include -#include - -namespace modm -{ - -/** - * Dummy clock implementation for testing. - * - * @ingroup modm_test_mock_clock_dummy - */ -class ClockDummy -{ -public: - /// Get the current time, either as `Timestamp` or `LongTimestamp`. - /// Provides an atomic access to the current time - template< typename TimestampType = Timestamp > - static inline TimestampType - now() - { - return TimestampType(time.getTime()); - } - - static inline ShortTimestamp - nowShort() - { - return now(); - } - - /// Update the current time - static inline void - increment(uint_fast16_t step = 1) - { - time = time + Timestamp(step); - } - - static inline void - setTime(Timestamp timestamp) - { - time = timestamp; - } - -protected: - static Timestamp time; -}; - -} // namespace modm - -#endif diff --git a/test/modm/mock/module.lb b/test/modm/mock/module.lb index a7c157f2c5..1c6af50d9d 100644 --- a/test/modm/mock/module.lb +++ b/test/modm/mock/module.lb @@ -10,9 +10,10 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. -class ClockDummy(Module): +class Clock(Module): def init(self, module): - module.name = "clock.dummy" + module.name = "clock" + module.description = "System Tick Mockup" def prepare(self, module, options): module.depends(":architecture:clock") @@ -20,21 +21,8 @@ class ClockDummy(Module): def build(self, env): env.outbasepath = "modm-test/src/modm-test/mock" - env.copy("clock_dummy.hpp") - env.copy("clock_dummy.cpp") - -class ClockTesting(Module): - def init(self, module): - module.name = "clock.testing" - - def prepare(self, module, options): - module.depends(":architecture:clock") - return True - - def build(self, env): - env.outbasepath = "modm-test/src/modm-test/mock" - env.copy("testing_clock.hpp") - env.copy("testing_clock.cpp") + env.copy("clock.hpp") + env.copy("clock.cpp") class SpiDevice(Module): def init(self, module): @@ -79,8 +67,7 @@ def init(module): module.name = ":mock" def prepare(module, options): - module.add_submodule(ClockDummy()) - module.add_submodule(ClockTesting()) + module.add_submodule(Clock()) module.add_submodule(SpiDevice()) module.add_submodule(SpiMaster()) module.add_submodule(IoDevice()) diff --git a/test/modm/mock/testing_clock.cpp b/test/modm/mock/testing_clock.cpp deleted file mode 100644 index 35dc4acb9c..0000000000 --- a/test/modm/mock/testing_clock.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (c) 2017-2018, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#include - -// This class is only generated on hosted targets! -modm::Clock::Type modm::Clock::time = 0; - -template< typename TimestampType > -TimestampType -modm::Clock::now() -{ - return TimestampType(time); -} - -void -modm::Clock::increment(uint_fast16_t /* step */) -{ - /* tumbleweed */ -} - -// explicit declaration of what member function templates we need to generate -template modm::ShortTimestamp modm::Clock::now(); -template modm::Timestamp modm::Clock::now(); - diff --git a/test/modm/mock/testing_clock.hpp b/test/modm/mock/testing_clock.hpp deleted file mode 100644 index 40558a1af2..0000000000 --- a/test/modm/mock/testing_clock.hpp +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2009, Martin Rosekeit - * Copyright (c) 2009-2011, Fabian Greif - * Copyright (c) 2012, 2015, 2017-2018, Niklas Hauser - * - * This file is part of the modm project. - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -// ---------------------------------------------------------------------------- - -#ifndef TESTING_CLOCK_HPP -#define TESTING_CLOCK_HPP - -#include - -/** - * Gain full access to modm::Clock::time. - */ -/// @ingroup modm_test_mock_testing_clock -class TestingClock : public modm::Clock -{ -public: - // expose protected members - using modm::Clock::time; -}; - -#endif diff --git a/test/modm/processing/module.lb b/test/modm/processing/module.lb index 3f9d0d089a..9bd4b318b5 100644 --- a/test/modm/processing/module.lb +++ b/test/modm/processing/module.lb @@ -24,7 +24,7 @@ def prepare(module, options): "modm:processing:resumable", "modm:processing:timer", "modm:processing:scheduler", - ":mock:clock.dummy") + ":mock:clock") return True diff --git a/test/modm/processing/timer/periodic_timer_test.cpp b/test/modm/processing/timer/periodic_timer_test.cpp index 20da29154c..9d9b837903 100644 --- a/test/modm/processing/timer/periodic_timer_test.cpp +++ b/test/modm/processing/timer/periodic_timer_test.cpp @@ -12,183 +12,191 @@ */ // ---------------------------------------------------------------------------- +#include "periodic_timer_test.hpp" #include -#include +#include -#include "periodic_timer_test.hpp" +using namespace std::chrono_literals; +using test_clock = modm_test::chrono::milli_clock; void PeriodicTimerTest::setUp() { - modm::ClockDummy::setTime(0); + test_clock::setTime(0); } void PeriodicTimerTest::testConstructor() { - modm::GenericPeriodicTimer timerShort(10); - modm::GenericPeriodicTimer timer(10); + modm::ShortPeriodicTimer timerShort(10ms); + modm::PeriodicTimer timer(10ms); - TEST_ASSERT_EQUALS(timerShort.remaining(), 10l); - TEST_ASSERT_EQUALS(timer.remaining(), 10l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 10ms); + TEST_ASSERT_EQUALS(timer.remaining(), 10ms); TEST_ASSERT_FALSE(timerShort.isStopped()); TEST_ASSERT_FALSE(timer.isStopped()); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Armed); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Armed); TEST_ASSERT_FALSE(timerShort.execute()); TEST_ASSERT_FALSE(timer.execute()); + + timerShort.restart(0ms); + timer.restart(0ms); + + TEST_ASSERT_EQUALS(timerShort.execute(), 1u); + TEST_ASSERT_EQUALS(timer.execute(), 1u); } void PeriodicTimerTest::testTimer() { - modm::GenericPeriodicTimer timerShort(10); - modm::GenericPeriodicTimer timer(10); + modm::ShortPeriodicTimer timerShort(10ms); + modm::PeriodicTimer timer(10ms); - TEST_ASSERT_EQUALS(timerShort.remaining(), 10l); - TEST_ASSERT_EQUALS(timer.remaining(), 10l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 10ms); + TEST_ASSERT_EQUALS(timer.remaining(), 10ms); - TEST_ASSERT_FALSE(timerShort.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); int i; for (i = 0; i < 9; ++i) { - modm::ClockDummy::setTime(i); + test_clock::setTime(i); - TEST_ASSERT_FALSE(timerShort.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); - TEST_ASSERT_EQUALS(timerShort.remaining(), (10l-i)); - TEST_ASSERT_EQUALS(timer.remaining(), (10l-i)); + TEST_ASSERT_EQUALS(timerShort.remaining(), std::chrono::milliseconds(10-i)); + TEST_ASSERT_EQUALS(timer.remaining(), std::chrono::milliseconds(10-i)); } - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Armed); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Armed); - modm::ClockDummy::setTime(10); + test_clock::setTime(10); - TEST_ASSERT_EQUALS(timerShort.remaining(), 0l); - TEST_ASSERT_EQUALS(timer.remaining(), 0l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timer.remaining(), 0ms); - TEST_ASSERT_TRUE(timerShort.execute()); - TEST_ASSERT_FALSE(timerShort.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 1u); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); - TEST_ASSERT_TRUE(timer.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timer.execute(), 1u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); - TEST_ASSERT_EQUALS(timerShort.remaining(), 10l); - TEST_ASSERT_EQUALS(timer.remaining(), 10l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 10ms); + TEST_ASSERT_EQUALS(timer.remaining(), 10ms); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Armed); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Armed); - modm::ClockDummy::setTime(20); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Expired); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Expired); + test_clock::setTime(20); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Expired); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Expired); - TEST_ASSERT_TRUE(timerShort.execute()); - TEST_ASSERT_FALSE(timerShort.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 1u); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); - TEST_ASSERT_TRUE(timer.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timer.execute(), 1u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Armed); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Armed); // we are going to miss the 30, 40, 50, 60, 70, 80, 90 periods // however, execute() should still only return exactly once - modm::ClockDummy::setTime(100); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Expired); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Expired); + test_clock::setTime(100); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Expired); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Expired); - TEST_ASSERT_EQUALS(timerShort.remaining(), -70l); - TEST_ASSERT_EQUALS(timer.remaining(), -70l); + TEST_ASSERT_EQUALS(timerShort.remaining(), -70ms); + TEST_ASSERT_EQUALS(timer.remaining(), -70ms); - TEST_ASSERT_TRUE(timerShort.execute()); - TEST_ASSERT_FALSE(timerShort.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 7u); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); - TEST_ASSERT_TRUE(timer.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timer.execute(), 7u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); - TEST_ASSERT_EQUALS(timerShort.remaining(), 10l); - TEST_ASSERT_EQUALS(timer.remaining(), 10l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 10ms); + TEST_ASSERT_EQUALS(timer.remaining(), 10ms); // we are going to miss a couple of periods more - modm::ClockDummy::setTime(150); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Expired); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Expired); + test_clock::setTime(150); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Expired); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Expired); - TEST_ASSERT_EQUALS(timerShort.remaining(), -40l); - TEST_ASSERT_EQUALS(timer.remaining(), -40l); + TEST_ASSERT_EQUALS(timerShort.remaining(), -40ms); + TEST_ASSERT_EQUALS(timer.remaining(), -40ms); // lets call execute() with a delay of 5ms after period expiration. // it should expired once, and then reschedule for 160ms, not 165ms!! - modm::ClockDummy::setTime(155); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Expired); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Expired); + test_clock::setTime(155); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Expired); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Expired); - TEST_ASSERT_EQUALS(timerShort.remaining(), -45l); - TEST_ASSERT_EQUALS(timer.remaining(), -45l); + TEST_ASSERT_EQUALS(timerShort.remaining(), -45ms); + TEST_ASSERT_EQUALS(timer.remaining(), -45ms); - TEST_ASSERT_TRUE(timerShort.execute()); - TEST_ASSERT_FALSE(timerShort.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 5u); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); - TEST_ASSERT_TRUE(timer.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timer.execute(), 5u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); - TEST_ASSERT_EQUALS(timerShort.remaining(), 5l); - TEST_ASSERT_EQUALS(timer.remaining(), 5l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 5ms); + TEST_ASSERT_EQUALS(timer.remaining(), 5ms); // not yet - modm::ClockDummy::setTime(159); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Armed); + test_clock::setTime(159); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Armed); - TEST_ASSERT_EQUALS(timerShort.remaining(), 1l); - TEST_ASSERT_EQUALS(timer.remaining(), 1l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 1ms); + TEST_ASSERT_EQUALS(timer.remaining(), 1ms); // now it should expire - modm::ClockDummy::setTime(160); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Expired); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Expired); + test_clock::setTime(160); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Expired); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Expired); - TEST_ASSERT_EQUALS(timerShort.remaining(), 0l); - TEST_ASSERT_EQUALS(timer.remaining(), 0l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timer.remaining(), 0ms); - TEST_ASSERT_TRUE(timerShort.execute()); - TEST_ASSERT_FALSE(timerShort.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 1u); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); - TEST_ASSERT_TRUE(timer.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timer.execute(), 1u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); - TEST_ASSERT_EQUALS(timerShort.remaining(), 10l); - TEST_ASSERT_EQUALS(timer.remaining(), 10l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 10ms); + TEST_ASSERT_EQUALS(timer.remaining(), 10ms); // it should not fire at 165ms - modm::ClockDummy::setTime(165); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Armed); + test_clock::setTime(165); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Armed); - TEST_ASSERT_FALSE(timerShort.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); - TEST_ASSERT_EQUALS(timerShort.remaining(), 5l); - TEST_ASSERT_EQUALS(timer.remaining(), 5l); + TEST_ASSERT_EQUALS(timerShort.remaining(), 5ms); + TEST_ASSERT_EQUALS(timer.remaining(), 5ms); } void PeriodicTimerTest::testRestart() { - modm::GenericPeriodicTimer timerShort(10); - modm::GenericPeriodicTimer timer(10); + modm::ShortPeriodicTimer timerShort(10ms); + modm::PeriodicTimer timer(10ms); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Armed); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Armed); TEST_ASSERT_FALSE(timerShort.isStopped()); TEST_ASSERT_FALSE(timer.isStopped()); @@ -200,30 +208,30 @@ PeriodicTimerTest::testRestart() timerShort.stop(); timer.stop(); - TEST_ASSERT_FALSE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_FALSE(timer.getState() == modm::PeriodicTimerState::Armed); + TEST_ASSERT_FALSE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_FALSE(timer.state() == modm::TimerState::Armed); TEST_ASSERT_TRUE(timerShort.isStopped()); TEST_ASSERT_TRUE(timer.isStopped()); - timerShort.restart(5); - timer.restart(5); + timerShort.restart(5ms); + timer.restart(5ms); TEST_ASSERT_FALSE(timerShort.isStopped()); TEST_ASSERT_FALSE(timer.isStopped()); - TEST_ASSERT_TRUE(timerShort.getState() == modm::PeriodicTimerState::Armed); - TEST_ASSERT_TRUE(timer.getState() == modm::PeriodicTimerState::Armed); + TEST_ASSERT_TRUE(timerShort.state() == modm::TimerState::Armed); + TEST_ASSERT_TRUE(timer.state() == modm::TimerState::Armed); - TEST_ASSERT_FALSE(timerShort.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); - modm::ClockDummy::setTime(5); - TEST_ASSERT_TRUE(timerShort.execute()); - TEST_ASSERT_FALSE(timerShort.execute()); + test_clock::setTime(5); + TEST_ASSERT_EQUALS(timerShort.execute(), 1u); + TEST_ASSERT_EQUALS(timerShort.execute(), 0u); - TEST_ASSERT_TRUE(timer.execute()); - TEST_ASSERT_FALSE(timer.execute()); + TEST_ASSERT_EQUALS(timer.execute(), 1u); + TEST_ASSERT_EQUALS(timer.execute(), 0u); } diff --git a/test/modm/processing/timer/timeout_test.cpp b/test/modm/processing/timer/timeout_test.cpp index 3a9d0adc86..f9b939c7c6 100644 --- a/test/modm/processing/timer/timeout_test.cpp +++ b/test/modm/processing/timer/timeout_test.cpp @@ -1,7 +1,7 @@ /* * Copyright (c) 2009, Martin Rosekeit * Copyright (c) 2009-2010, 2012, 2018, Fabian Greif - * Copyright (c) 2012, 2014-2015, 2017, Niklas Hauser + * Copyright (c) 2012, 2014-2015, 2017, 2020, Niklas Hauser * Copyright (c) 2013, 2016, Sascha Schade * * This file is part of the modm project. @@ -12,27 +12,30 @@ */ // ---------------------------------------------------------------------------- -#include +#include "timeout_test.hpp" #include -#include +#include +#include +#include -#include "timeout_test.hpp" +using namespace std::chrono_literals; +using test_clock = modm_test::chrono::milli_clock; // ---------------------------------------------------------------------------- void TimeoutTest::setUp() { - modm::ClockDummy::setTime(0); + test_clock::setTime(0); } void TimeoutTest::testDefaultConstructor() { - modm::GenericTimeout timeoutShort; - modm::GenericTimeout timeout; + modm::ShortTimeout timeoutShort; + modm::Timeout timeout; - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0l); - TEST_ASSERT_EQUALS(timeout.remaining(), 0l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); TEST_ASSERT_TRUE(timeoutShort.isStopped()); TEST_ASSERT_TRUE(timeout.isStopped()); @@ -49,18 +52,78 @@ TimeoutTest::testDefaultConstructor() TEST_ASSERT_FALSE(timeoutShort.isExpired()); TEST_ASSERT_FALSE(timeout.isExpired()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0l); - TEST_ASSERT_EQUALS(timeout.remaining(), 0l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); +} + +void +TimeoutTest::testZeroConstructor() +{ + modm::ShortTimeout timeoutShort{0ms}; + modm::Timeout timeout{0ms}; + + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); + + TEST_ASSERT_FALSE(timeoutShort.isStopped()); + TEST_ASSERT_FALSE(timeout.isStopped()); + + // immediately expires! + TEST_ASSERT_FALSE(timeoutShort.isArmed()); + TEST_ASSERT_FALSE(timeout.isArmed()); + + TEST_ASSERT_TRUE(timeoutShort.isExpired()); + TEST_ASSERT_TRUE(timeout.isExpired()); + + TEST_ASSERT_TRUE(timeoutShort.execute()); + TEST_ASSERT_TRUE(timeout.execute()); + + TEST_ASSERT_TRUE(timeoutShort.isExpired()); + TEST_ASSERT_TRUE(timeout.isExpired()); + + TEST_ASSERT_FALSE(timeoutShort.execute()); + TEST_ASSERT_FALSE(timeout.execute()); + + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); +} + +void +TimeoutTest::testNegativeConstructor() +{ + modm::ShortTimeout timeoutShort{-1ms}; + modm::Timeout timeout{-10ms}; + + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); + + TEST_ASSERT_TRUE(timeoutShort.isStopped()); + TEST_ASSERT_TRUE(timeout.isStopped()); + + TEST_ASSERT_FALSE(timeoutShort.isArmed()); + TEST_ASSERT_FALSE(timeout.isArmed()); + + TEST_ASSERT_FALSE(timeoutShort.isExpired()); + TEST_ASSERT_FALSE(timeout.isExpired()); + + TEST_ASSERT_FALSE(timeoutShort.execute()); + TEST_ASSERT_FALSE(timeout.execute()); + + TEST_ASSERT_FALSE(timeoutShort.isExpired()); + TEST_ASSERT_FALSE(timeout.isExpired()); + + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); } void TimeoutTest::testBasics() { - modm::GenericTimeout timeoutShort(10); - modm::GenericTimeout timeout(10); + modm::ShortTimeout timeoutShort(10ms); + modm::Timeout timeout(10ms); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 10l); - TEST_ASSERT_EQUALS(timeout.remaining(), 10l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 10ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 10ms); TEST_ASSERT_FALSE(timeoutShort.execute()); TEST_ASSERT_FALSE(timeout.execute()); @@ -71,28 +134,27 @@ TimeoutTest::testBasics() TEST_ASSERT_FALSE(timeoutShort.isExpired()); TEST_ASSERT_FALSE(timeout.isExpired()); - int i; - for (i = 0; i < 9; ++i) { - modm::ClockDummy::setTime(i); + for (int i = 0; i < 9; ++i) { + test_clock::setTime(i); TEST_ASSERT_FALSE(timeoutShort.execute()); TEST_ASSERT_FALSE(timeout.execute()); TEST_ASSERT_FALSE(timeoutShort.isExpired()); TEST_ASSERT_FALSE(timeout.isExpired()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), (10l-i)); - TEST_ASSERT_EQUALS(timeout.remaining(), (10l-i)); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), std::chrono::milliseconds(10-i)); + TEST_ASSERT_EQUALS(timeout.remaining(), std::chrono::milliseconds(10-i)); } - modm::ClockDummy::setTime(10); + test_clock::setTime(10); TEST_ASSERT_TRUE(timeoutShort.isExpired()); TEST_ASSERT_TRUE(timeout.isExpired()); TEST_ASSERT_FALSE(timeoutShort.isArmed()); TEST_ASSERT_FALSE(timeout.isArmed()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0l); - TEST_ASSERT_EQUALS(timeout.remaining(), 0l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); TEST_ASSERT_TRUE(timeoutShort.execute()); TEST_ASSERT_TRUE(timeout.execute()); @@ -106,12 +168,12 @@ TimeoutTest::testBasics() TEST_ASSERT_FALSE(timeoutShort.isArmed()); TEST_ASSERT_FALSE(timeout.isArmed()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0l); - TEST_ASSERT_EQUALS(timeout.remaining(), 0l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); // check that the class does not hold the state - modm::ClockDummy::setTime(11); + test_clock::setTime(11); TEST_ASSERT_FALSE(timeoutShort.execute()); TEST_ASSERT_FALSE(timeout.execute()); @@ -121,8 +183,8 @@ TimeoutTest::testBasics() TEST_ASSERT_FALSE(timeoutShort.isArmed()); TEST_ASSERT_FALSE(timeout.isArmed()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), -1l); - TEST_ASSERT_EQUALS(timeout.remaining(), -1l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), -1ms); + TEST_ASSERT_EQUALS(timeout.remaining(), -1ms); timeoutShort.stop(); timeout.stop(); @@ -136,41 +198,51 @@ TimeoutTest::testBasics() TEST_ASSERT_FALSE(timeoutShort.isArmed()); TEST_ASSERT_FALSE(timeout.isArmed()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0l); - TEST_ASSERT_EQUALS(timeout.remaining(), 0l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); } void TimeoutTest::testTimeOverflow() { - modm::ShortTimestamp::Type time = std::numeric_limits::max(); - TEST_ASSERT_EQUALS(time, 65535); + modm::ShortTimeout timeoutShort; + modm::ShortDuration time{modm::ShortDuration::max()}; + TEST_ASSERT_EQUALS(time, 65535ms); + + // overflow after 65535 for uint16_t => 65535+100 = 99 + test_clock::setTime(time.count() + 100); + TEST_ASSERT_EQUALS(time + modm::ShortDuration(100ms), 99ms); - // overflow after 65535 for uint16_t => 32767+100 = 32867 - modm::ClockDummy::setTime(time / 2 + 100); - TEST_ASSERT_EQUALS((time / 2 + 100), 32867); - modm::GenericTimeout timeoutShort(time / 2 - 1); //=> 32867 + 32766 = 97 - TEST_ASSERT_EQUALS(((signed)(time / 2) - 1), 32766); + test_clock::setTime(0); + timeoutShort.restart(time); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 65535ms); + TEST_ASSERT_FALSE(timeoutShort.execute()); + test_clock::setTime(100); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 65435ms); TEST_ASSERT_FALSE(timeoutShort.execute()); - modm::ClockDummy::setTime(time); + timeoutShort.restart(time); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 65535ms); TEST_ASSERT_FALSE(timeoutShort.execute()); - modm::ClockDummy::setTime(0); + test_clock::setTime(65535); + timeoutShort.restart(time-1ms); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 65534ms); TEST_ASSERT_FALSE(timeoutShort.execute()); - // Overflow happened. This needs to be avoided by the user! - modm::ClockDummy::setTime(100); + test_clock::setTime(65534); + timeoutShort.restart(time+1ms); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); TEST_ASSERT_TRUE(timeoutShort.execute()); } void TimeoutTest::testRestart() { - modm::GenericTimeout timeoutShort; - modm::GenericTimeout timeout; + modm::ShortTimeout timeoutShort; + modm::Timeout timeout; TEST_ASSERT_FALSE(timeoutShort.execute()); TEST_ASSERT_FALSE(timeout.execute()); @@ -181,15 +253,15 @@ TimeoutTest::testRestart() TEST_ASSERT_FALSE(timeoutShort.isExpired()); TEST_ASSERT_FALSE(timeout.isExpired()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0l); - TEST_ASSERT_EQUALS(timeout.remaining(), 0l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 0ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 0ms); - timeoutShort.restart(42); - timeout.restart(42); + timeoutShort.restart(42ms); + timeout.restart(42ms); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 42l); - TEST_ASSERT_EQUALS(timeout.remaining(), 42l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 42ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 42ms); TEST_ASSERT_FALSE(timeoutShort.execute()); TEST_ASSERT_FALSE(timeout.execute()); @@ -201,7 +273,7 @@ TimeoutTest::testRestart() TEST_ASSERT_FALSE(timeout.isExpired()); - modm::ClockDummy::setTime(10); + test_clock::setTime(10); TEST_ASSERT_FALSE(timeoutShort.execute()); TEST_ASSERT_FALSE(timeout.execute()); @@ -211,10 +283,10 @@ TimeoutTest::testRestart() TEST_ASSERT_FALSE(timeoutShort.isExpired()); TEST_ASSERT_FALSE(timeout.isExpired()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 32l); - TEST_ASSERT_EQUALS(timeout.remaining(), 32l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 32ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 32ms); - modm::ClockDummy::setTime(50); + test_clock::setTime(50); TEST_ASSERT_FALSE(timeoutShort.isArmed()); TEST_ASSERT_FALSE(timeout.isArmed()); @@ -233,12 +305,12 @@ TimeoutTest::testRestart() TEST_ASSERT_TRUE(timeoutShort.isExpired()); TEST_ASSERT_TRUE(timeout.isExpired()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), -8l); - TEST_ASSERT_EQUALS(timeout.remaining(), -8l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), -8ms); + TEST_ASSERT_EQUALS(timeout.remaining(), -8ms); - timeoutShort.restart(60); - timeout.restart(60); + timeoutShort.restart(60ms); + timeout.restart(60ms); TEST_ASSERT_TRUE(timeoutShort.isArmed()); TEST_ASSERT_TRUE(timeout.isArmed()); @@ -249,11 +321,11 @@ TimeoutTest::testRestart() TEST_ASSERT_FALSE(timeoutShort.isExpired()); TEST_ASSERT_FALSE(timeout.isExpired()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), 60l); - TEST_ASSERT_EQUALS(timeout.remaining(), 60l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), 60ms); + TEST_ASSERT_EQUALS(timeout.remaining(), 60ms); - modm::ClockDummy::setTime(150); + test_clock::setTime(150); TEST_ASSERT_TRUE(timeoutShort.execute()); TEST_ASSERT_TRUE(timeout.execute()); @@ -264,6 +336,6 @@ TimeoutTest::testRestart() TEST_ASSERT_TRUE(timeoutShort.isExpired()); TEST_ASSERT_TRUE(timeout.isExpired()); - TEST_ASSERT_EQUALS(timeoutShort.remaining(), -40l); - TEST_ASSERT_EQUALS(timeout.remaining(), -40l); + TEST_ASSERT_EQUALS(timeoutShort.remaining(), -40ms); + TEST_ASSERT_EQUALS(timeout.remaining(), -40ms); } diff --git a/test/modm/processing/timer/timeout_test.hpp b/test/modm/processing/timer/timeout_test.hpp index 53f044bf1e..a65e60819d 100644 --- a/test/modm/processing/timer/timeout_test.hpp +++ b/test/modm/processing/timer/timeout_test.hpp @@ -20,12 +20,17 @@ class TimeoutTest : public unittest::TestSuite virtual void setUp(); + void + testDefaultConstructor(); void - testBasics(); + testZeroConstructor(); void - testDefaultConstructor(); + testNegativeConstructor(); + + void + testBasics(); void testTimeOverflow(); diff --git a/test/modm/processing/timer/timestamp_test.cpp b/test/modm/processing/timer/timestamp_test.cpp index 35662810cb..a84b1a5284 100644 --- a/test/modm/processing/timer/timestamp_test.cpp +++ b/test/modm/processing/timer/timestamp_test.cpp @@ -15,63 +15,64 @@ #include #include "timestamp_test.hpp" +using namespace std::chrono_literals; // ---------------------------------------------------------------------------- void -TimestampTest::testConstructors() +DurationTest::testConstructors() { - modm::ShortTimestamp t1Short; - TEST_ASSERT_TRUE(t1Short == 0); + modm::ShortDuration t1Short; + TEST_ASSERT_TRUE(t1Short == 0ms); - modm::Timestamp t1; - TEST_ASSERT_TRUE(t1 == 0); + modm::Duration t1; + TEST_ASSERT_TRUE(t1 == 0ms); - modm::ShortTimestamp t2Short(1000); - TEST_ASSERT_TRUE(t2Short == 1000); + modm::ShortDuration t2Short(1s); + TEST_ASSERT_TRUE(t2Short == 1000ms); - modm::Timestamp t2(1000); - TEST_ASSERT_TRUE(t2 == 1000); + modm::Duration t2(1s); + TEST_ASSERT_TRUE(t2 == 1000ms); - t1Short = 500; - TEST_ASSERT_TRUE(t1Short == 500); + t1Short = modm::ShortDuration(500ms); + TEST_ASSERT_TRUE(t1Short == 500ms); - t1 = 500; - TEST_ASSERT_TRUE(t1 == 500); + t1 = modm::Duration(500ms); + TEST_ASSERT_TRUE(t1 == 500ms); } void -TimestampTest::testArithmetics() +DurationTest::testArithmetics() { - modm::ShortTimestamp t1Short(200); - modm::ShortTimestamp t2Short(500); - modm::ShortTimestamp t3Short; + modm::ShortDuration t1Short(200ms); + modm::ShortDuration t2Short(500ms); + modm::ShortDuration t3Short; t3Short = t1Short + t2Short; - TEST_ASSERT_TRUE(t3Short == 700); + TEST_ASSERT_TRUE(t3Short == 700ms); - modm::Timestamp t1(200); - modm::Timestamp t2(500); - modm::Timestamp t3; + modm::Duration t1(200ms); + modm::Duration t2(500ms); + modm::Duration t3; t3 = t1 + t2; - TEST_ASSERT_TRUE(t3 == 700); + TEST_ASSERT_TRUE(t3 == 0.7s); } void -TimestampTest::testComparisons() +DurationTest::testComparisons() { - modm::ShortTimestamp t1Short; - modm::ShortTimestamp t2Short; - modm::Timestamp t1; - modm::Timestamp t2; + modm::ShortDuration t1Short{}; + modm::ShortDuration t2Short{}; + modm::Duration t1{}; + modm::Duration t2{}; TEST_ASSERT_TRUE(t1Short == t2Short); TEST_ASSERT_FALSE(t1Short != t2Short); TEST_ASSERT_TRUE(t1 == t2); TEST_ASSERT_FALSE(t1 != t2); - t1Short = std::numeric_limits::max() / 2; - t1 = std::numeric_limits::max() / 2; + t1Short = modm::ShortDuration::max(); + t1 = modm::Duration::max(); TEST_ASSERT_FALSE(t1Short == t2Short); TEST_ASSERT_TRUE(t1Short != t2Short); @@ -83,11 +84,11 @@ TimestampTest::testComparisons() TEST_ASSERT_TRUE(t1 > t2); TEST_ASSERT_TRUE(t1 >= t2); - t1Short = std::numeric_limits::max() / 2 + 1; - t1 = std::numeric_limits::max() / 2 + 1; + t1Short = std::chrono::milliseconds(modm::ShortDuration::max() + 1ms); + t1 = std::chrono::milliseconds(modm::Duration::max() + 1ms); - TEST_ASSERT_TRUE(t1Short < t2Short); - TEST_ASSERT_TRUE(t1Short <= t2Short); - TEST_ASSERT_TRUE(t1 < t2); - TEST_ASSERT_TRUE(t1 <= t2); + TEST_ASSERT_TRUE(t1Short == t2Short); + TEST_ASSERT_FALSE(t1Short != t2Short); + TEST_ASSERT_TRUE(t1 == t2); + TEST_ASSERT_FALSE(t1 != t2); } diff --git a/test/modm/processing/timer/timestamp_test.hpp b/test/modm/processing/timer/timestamp_test.hpp index d09bf4ff51..b45d078075 100644 --- a/test/modm/processing/timer/timestamp_test.hpp +++ b/test/modm/processing/timer/timestamp_test.hpp @@ -14,7 +14,7 @@ #include /// @ingroup modm_test_test_processing -class TimestampTest : public unittest::TestSuite +class DurationTest : public unittest::TestSuite { public: void diff --git a/tools/build_script_generator/module.lb b/tools/build_script_generator/module.lb index 0d713acc05..946a921eec 100644 --- a/tools/build_script_generator/module.lb +++ b/tools/build_script_generator/module.lb @@ -61,8 +61,6 @@ def prepare(module, options): description=descr_build_path)) if platform in ["avr"]: - # we need the clock:f_cpu option! - module.depends(":platform:clock") module.add_option( StringOption(name="avrdude.programmer", default="", description="AvrDude programmer"))