/* SPDX-License-Identifier: MIT Copyright (c) 2023 John Watts and the LuminaSensum contributors */ #include "ButtonThread.h" #include "mbed.h" EventFlags buttonFlags; #define PUSH_FLAG 0b01 void button_onrise(void) { buttonFlags.set(PUSH_FLAG); } int readButtonPresses(void) { int pressed_count = 0; // Wait and track an initial press without timing out buttonFlags.wait_any(PUSH_FLAG); pressed_count++; while (true) { uint32_t flags = buttonFlags.wait_any(PUSH_FLAG, 1000); bool timed_out = flags == osFlagsErrorTimeout; bool had_any_error = flags & osFlagsError; if (timed_out) { break; } else if (had_any_error) { error("Unable to wait for push button flag?\n"); } else { pressed_count++; } } return pressed_count; } int buttonPressCount; Mutex buttonPressMutex; ConditionVariable cv(buttonPressMutex); void buttonTask(void) { InterruptIn buttonIRQ(BUTTON1); buttonIRQ.rise(button_onrise); while (true) { int presses = readButtonPresses(); buttonPressMutex.lock(); buttonPressCount = presses; cv.notify_one(); buttonPressMutex.unlock(); } } bool waitPressCondition(Kernel::Clock::time_point timeout) { // buttonPressCount is 0 if we have already read the current value while (buttonPressCount == 0) { if (cv.wait_until(timeout) == cv_status::timeout) { return false; } } return true; } // returns presses or -1 on timeout int waitForPresses(std::chrono::milliseconds wait_time) { Kernel::Clock::time_point timeout = Kernel::Clock::now() + wait_time; int presses = -1; buttonPressMutex.lock(); if (waitPressCondition(timeout)) { presses = buttonPressCount; buttonPressCount = 0; } buttonPressMutex.unlock(); return presses; }