Build and upload tool (arduino-build.sh): - Compile, upload, and monitor via arduino-cli - Device discovery with USB ID identification (--devices) - Persistent reconnecting serial monitor (--watch) - Split compile/upload workflow (--verify, --upload-only) - First-time setup wizard (--setup) - Comprehensive --help with troubleshooting and RedBoard specs Testable application architecture: - Hardware abstraction layer (lib/hal/) decouples logic from Arduino API - Google Mock HAL for unit tests (exact call verification) - Simulated HAL for system tests (GPIO state, virtual clock, I2C devices) - Example I2C temperature sensor simulator (TMP102) - Host-side test suite via CMake + Google Test (21 tests) Example sketch: - blink/ -- LED blink with button-controlled speed, wired through HAL
89 lines
2.6 KiB
C++
89 lines
2.6 KiB
C++
#ifndef BLINK_APP_H
|
|
#define BLINK_APP_H
|
|
|
|
#include <hal.h>
|
|
|
|
/*
|
|
* BlinkApp -- Testable blink logic, decoupled from hardware.
|
|
*
|
|
* Blinks an LED and reads a button. When the button is pressed,
|
|
* the blink rate doubles (toggles between normal and fast mode).
|
|
*
|
|
* All hardware access goes through the injected Hal pointer. This
|
|
* class has no dependency on Arduino.h and compiles on any host.
|
|
*/
|
|
class BlinkApp {
|
|
public:
|
|
static constexpr uint8_t DEFAULT_LED_PIN = LED_BUILTIN; // pin 13
|
|
static constexpr uint8_t DEFAULT_BUTTON_PIN = 2;
|
|
static constexpr unsigned long SLOW_INTERVAL_MS = 500;
|
|
static constexpr unsigned long FAST_INTERVAL_MS = 125;
|
|
|
|
BlinkApp(Hal* hal,
|
|
uint8_t led_pin = DEFAULT_LED_PIN,
|
|
uint8_t button_pin = DEFAULT_BUTTON_PIN)
|
|
: hal_(hal)
|
|
, led_pin_(led_pin)
|
|
, button_pin_(button_pin)
|
|
, led_state_(LOW)
|
|
, fast_mode_(false)
|
|
, last_toggle_ms_(0)
|
|
, last_button_state_(HIGH) // pulled up, so HIGH = not pressed
|
|
{}
|
|
|
|
// Call once from setup()
|
|
void begin() {
|
|
hal_->pinMode(led_pin_, OUTPUT);
|
|
hal_->pinMode(button_pin_, INPUT_PULLUP);
|
|
hal_->serialBegin(115200);
|
|
hal_->serialPrintln("BlinkApp started");
|
|
last_toggle_ms_ = hal_->millis();
|
|
}
|
|
|
|
// Call repeatedly from loop()
|
|
void update() {
|
|
handleButton();
|
|
handleBlink();
|
|
}
|
|
|
|
// -- Accessors for testing ----------------------------------------------
|
|
bool ledState() const { return led_state_ == HIGH; }
|
|
bool fastMode() const { return fast_mode_; }
|
|
unsigned long interval() const {
|
|
return fast_mode_ ? FAST_INTERVAL_MS : SLOW_INTERVAL_MS;
|
|
}
|
|
|
|
private:
|
|
void handleButton() {
|
|
uint8_t reading = hal_->digitalRead(button_pin_);
|
|
|
|
// Detect falling edge (HIGH -> LOW = button press with INPUT_PULLUP)
|
|
if (last_button_state_ == HIGH && reading == LOW) {
|
|
fast_mode_ = !fast_mode_;
|
|
hal_->serialPrintln(fast_mode_ ? "FAST" : "SLOW");
|
|
}
|
|
last_button_state_ = reading;
|
|
}
|
|
|
|
void handleBlink() {
|
|
unsigned long now = hal_->millis();
|
|
unsigned long target = fast_mode_ ? FAST_INTERVAL_MS : SLOW_INTERVAL_MS;
|
|
|
|
if (now - last_toggle_ms_ >= target) {
|
|
led_state_ = (led_state_ == HIGH) ? LOW : HIGH;
|
|
hal_->digitalWrite(led_pin_, led_state_);
|
|
last_toggle_ms_ = now;
|
|
}
|
|
}
|
|
|
|
Hal* hal_;
|
|
uint8_t led_pin_;
|
|
uint8_t button_pin_;
|
|
uint8_t led_state_;
|
|
bool fast_mode_;
|
|
unsigned long last_toggle_ms_;
|
|
uint8_t last_button_state_;
|
|
};
|
|
|
|
#endif // BLINK_APP_H
|