Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
arcadien committed Nov 23, 2023
1 parent b146299 commit 2dba2f7
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 28 deletions.
18 changes: 8 additions & 10 deletions lib/Cross/Gun/Atmega328pHal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,21 @@
#define VIBRATOR_PIN 6
#define BATTERY_VOLTAGE_PIN A3
#define CHARGING_STATE_PIN A2
#define BUTTON2_PIN 3
#define BUTTON_PIN 3
#define TRIGGER_PIN 2

#define MIN_BAT_VOLTAGE 3000
#define MAX_BAT_VOLTAGE 4120

Atmega328pHal::Atmega328pHal() {

pinMode(VIBRATOR_PIN, OUTPUT);
pinMode(LASER_PIN, OUTPUT);
pinMode(TRIGGER_PIN, INPUT_PULLUP);
pinMode(BUTTON_PIN, INPUT_PULLUP);
}

bool Atmega328pHal::triggerIsUp() { return bit_is_set(PIND, PD2); }
bool Atmega328pHal::buttonIsUp() { return bit_is_set(PIND, PD3); }
bool Atmega328pHal::buttonIsUp() { return bit_is_clear(PIND, PD3); }

/*
* the 'loop' method shall be called each 10ms
Expand Down Expand Up @@ -89,17 +90,14 @@ void Atmega328pHal::sleep() {
USART0_OFF, TWI_OFF);
}

void Atmega328pHal::setGun(Gun *gun) { gun = gun; }
void Atmega328pHal::setGun(Gun *gun) { this->gun = gun; }

extern void buttonInterruptHandler();
void Atmega328pHal::configureInputCallbacks() {
extern void triggerInterruptHandler();

pinMode(BUTTON2_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON2_PIN), buttonInterruptHandler,
void Atmega328pHal::configureInputCallbacks() {
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), buttonInterruptHandler,
CHANGE);

extern void triggerInterruptHandler();
pinMode(TRIGGER_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(TRIGGER_PIN), triggerInterruptHandler,
CHANGE);
}
4 changes: 2 additions & 2 deletions lib/Cross/Gun/SSD1306Ui.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@ class SSD1306Ui : public IGunUi {
}

void clearCalibration() override {
display.fillRect(2, 10, 126, 14, 0); // clear
display.fillRect(2, 10, 126, 22, 0); // clear
}

void displayCalibration() override {
display.clearDisplay();
display.setCursor(2, 25);
display.setFont(&FreeMonoOblique9pt7b);
display.setCursor(2, 25);
display.print("Calibration");
display.display();
}
Expand Down
39 changes: 23 additions & 16 deletions src/GunApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,27 +23,31 @@ SSD1306Ui ui;
Atmega328pHal hal;
Gun gun(&hal, &ui);

volatile bool tick = false;
ISR(TIMER2_COMPA_vect) { tick = true; }
volatile bool applicativeEvent = false;
ISR(TIMER2_COMPA_vect) { applicativeEvent = true; }

volatile Contactor::Event pendingTriggerEvent;
void triggerInterruptHandler() {
if (hal.triggerIsUp()) {
pendingTriggerEvent = Contactor::Event::Released;
} else {
pendingTriggerEvent = Contactor::Event::Pressed;
if (Contactor::Event::NoEvent == pendingTriggerEvent) {
if (hal.triggerIsUp()) {
pendingTriggerEvent = Contactor::Event::Released;
} else {
pendingTriggerEvent = Contactor::Event::Pressed;
}
applicativeEvent = true;
}
tick = true;
}

volatile Contactor::Event pendingButtonEvent;
void buttonInterruptHandler() {
if (hal.buttonIsUp()) {
pendingButtonEvent = Contactor::Event::Released;
} else {
pendingButtonEvent = Contactor::Event::Pressed;
if (Contactor::Event::NoEvent == pendingButtonEvent) {
if (hal.buttonIsUp()) {
pendingButtonEvent = Contactor::Event::Released;
} else {
pendingButtonEvent = Contactor::Event::Pressed;
}
applicativeEvent = true;
}
tick = true;
}

void loop(void) {
Expand All @@ -53,16 +57,19 @@ void loop(void) {
// and counter1, used internally by the Arduino
// framework. Avoid processing these wakeups as
// applicative events using 'tick' control variable.

if (tick) {

if (applicativeEvent) {
applicativeEvent = false;

// wire interrupt-based events with main code
gun.trigger.pendingEvent = pendingTriggerEvent;
gun.button.pendingEvent = pendingButtonEvent;

gun.loop();

pendingTriggerEvent = Contactor::Event::NoEvent;
pendingButtonEvent = Contactor::Event::NoEvent;

gun.loop();
tick = false;
hal.sleep();
}
}
Expand Down
31 changes: 31 additions & 0 deletions test/native/test_gun/gun.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,12 +191,43 @@ void expect_trigger_to_have_no_effect_in_calibration_mode() {
Verify(Method(mockHal, laserOff)).Exactly(0);
}

void expect_long_press_to_trigger_only_if_button_is_down() {
Mock<IGunUi> mockUi;
Mock<IGunHal> mockHal;

MOCK_ALL();

IGunUi &ui = mockUi.get();
IGunHal &hal = mockHal.get();

Gun gun(&hal, &ui);

gun.button.pendingEvent = Contactor::Event::Pressed;
gun.loop();

gun.button.pendingEvent = Contactor::Event::Released;
gun.loop();

for (uint8_t tickCounter = 0; tickCounter <= 200; tickCounter++) {
// long press shall be accounted after 2s, 200 ticks
gun.loop();
}

// No long press, no switch to calibration
Verify(Method(mockHal, laserOn)).Exactly(0);
Verify(Method(mockUi, displayCalibration)).Exactly(0);
Verify(Method(mockHal, laserOff)).Exactly(0);
Verify(Method(mockUi, clearCalibration)).Exactly(0);
Verify(Method(mockUi, displayShootCount)).Exactly(1);
}

int main(int, char **) {
UNITY_BEGIN();
RUN_TEST(expect_gun_to_loop);
RUN_TEST(expect_gun_to_shoot_50ms_on_trigger_down);
RUN_TEST(expect_ui_to_display_battery_state_at_boot_and_each_1s);
RUN_TEST(expect_switch_to_maintenance_after_2s_button_continuous_press);
RUN_TEST(expect_long_press_to_trigger_only_if_button_is_down);
RUN_TEST(expect_button_press_to_reset_shoot_count_and_redisplay);
RUN_TEST(expect_trigger_to_have_no_effect_in_calibration_mode);

Expand Down

0 comments on commit 2dba2f7

Please sign in to comment.