diff --git a/firmware/Application/ButtonManager.cpp b/firmware/Application/ButtonManager.cpp index d0866c3..7377b87 100644 --- a/firmware/Application/ButtonManager.cpp +++ b/firmware/Application/ButtonManager.cpp @@ -161,7 +161,7 @@ void ButtonManager::irq() static BSP::time_t systime; // TODO: is this call too expensive for an interrupt handler? - //BSP::SystemTimer::get_time(systime); + BSP::SystemTimer::get_time(systime); if (!m_instance) { return; diff --git a/firmware/Bsp/Drivers/LowPower.cpp b/firmware/Bsp/Drivers/LowPower.cpp index 45622c1..f13e20e 100644 --- a/firmware/Bsp/Drivers/LowPower.cpp +++ b/firmware/Bsp/Drivers/LowPower.cpp @@ -50,12 +50,13 @@ ReturnCode LowPower::init(GpioPin &timing_pin) ReturnCode LowPower::enable_debug() { /* Enable Clocks */ + // FIXME for all boards // SET(RCC->APB2ENR, RCC_APB2ENR_DBGEN); // SET(RCC->APB2SMENR, RCC_APB2SMENR_DBGSMEN); - // SET(DBGMCU->CR, DBGMCU_CR_DBG_STOP); - // SET(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); - // SET(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); + SET(DBGMCU->CR, DBGMCU_CR_DBG_STOP); + SET(DBGMCU->CR, DBGMCU_CR_DBG_SLEEP); + SET(DBGMCU->CR, DBGMCU_CR_DBG_STANDBY); return ReturnCode::OK; } diff --git a/firmware/Test/Apps/button_lowpower.cpp b/firmware/Test/Apps/button_lowpower.cpp new file mode 100644 index 0000000..339da1e --- /dev/null +++ b/firmware/Test/Apps/button_lowpower.cpp @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2020 Max Regan + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "Bsp/Drivers/GpioDriver.h" + +#include "Application/ButtonManager.h" + +#include "TestBoard.h" + +#include "printf.h" +#include "test.h" + +using namespace BSP; + +using Button = ButtonManager::Button; +using ButtonState = ButtonManager::ButtonState; + +static GpioPin g_btn_down(g_gpioa, 0); +static GpioPin g_btn_mid(g_gpioa, 1); +static GpioPin g_btn_up(g_gpioa, 2); + +static ButtonManager g_btn_mgr(g_sched, + g_btn_down, + g_btn_mid, + g_btn_up, + Time::millis(50)); + +[[noreturn]] void main() { + + board_init(); + g_debug0_pin.configure_output(GpioDriver::output_mode_t::PUSH_PULL, GpioDriver::output_speed_t::LOW); + BSP::LowPower::init(g_debug0_pin); + + g_test_uart.tx_blocking(test_start_text); + + g_btn_down.configure_input(GpioDriver::input_pull_t::PULL_UP); + g_btn_mid.configure_input(GpioDriver::input_pull_t::PULL_UP); + g_btn_up.configure_input(GpioDriver::input_pull_t::PULL_UP); + + g_btn_mgr.init(); + + ButtonManager::ChangeCallback callback = + [&](ButtonState state) { + g_test_uart.tx_blocking("up:"); + if (state == ButtonState::PRESSED) { + g_test_uart.tx_blocking("pressed\r\n"); + } else { + g_test_uart.tx_blocking("released\r\n"); + } + }; + + g_btn_mgr.set_callback(Button::UP, callback); + + Schedule::NextTime asap = Schedule::NextTime::asap(); + g_sched.add_task(g_test_uart, asap); + g_sched.add_task(g_btn_mgr, asap); + + g_test_uart.tx_blocking("Waiting for button press...\r\n"); + g_sched.run(); + + TEST_SPIN(); +} diff --git a/test/src/tr_test/test.py b/test/src/tr_test/test.py index 26108c7..f4599dc 100755 --- a/test/src/tr_test/test.py +++ b/test/src/tr_test/test.py @@ -244,6 +244,24 @@ def test_button_fast(context_factory, logger): assert serial_dev.readline() == b"" +def test_button_lowpower(context_factory, logger): + serial_dev, jlink = context_factory("Test/Apps/button_lowpower.bin") + serial_dev.timeout = 0.3 + ASSERTED = True + + serial_dev.dtr = not ASSERTED + while (line := serial_dev.readline()) is not None and len(line) > 0: + pass + + for _ in range(5): + serial_dev.dtr = ASSERTED + press_line = serial_dev.readline() + serial_dev.dtr = not ASSERTED + release_line = serial_dev.readline() + assert press_line == b"up:pressed\r\n" + assert release_line == b"up:released\r\n" + + def test_clock(context_factory, logger): serial_dev, jlink = context_factory("Test/Apps/clock.bin") EXPECTED_RUNTIME = 10 @@ -325,7 +343,7 @@ def test_lptim(context_factory, logger): def test_app_lowpower(context_factory, logger): serial_dev, jlink = context_factory("Application/main.bin", leave_halted=True) jlink.reset(halt=False) - state0_periods, state1_periods = measure_frequency(10, "D1") + state0_periods, state1_periods = measure_frequency(10, "D0") num_periods = min(len(state0_periods), len(state1_periods)) periods = [state0_periods[i] + state1_periods[i] for i in range(num_periods)] freqs = list(map(lambda x: 1 / x, periods))