Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
arcadien committed Nov 20, 2023
1 parent 8255b5b commit 83a63c8
Show file tree
Hide file tree
Showing 11 changed files with 482 additions and 322 deletions.
86 changes: 86 additions & 0 deletions lib/Domain/Gun/Atmega328pHal.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
/*
*
* Copyright (c) 2023 Aurélien Labrosse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once

#include <Gun/IGunHal.hpp>
#include <avr/io.h>

#define BSP_TICKS_PER_SEC 100
#define F_CPU 16000000L

#define LASER_PIN 10
#define VIBRATOR_PIN 6
#define BATTERY_VOLTAGE_PIN A3
#define CHARGING_STATE_PIN A2

#define MIN_BAT_VOLTAGE 3000
#define MAX_BAT_VOLTAGE 4120

ISR(TIMER2_COMPA_vect) {}

class Atmega328pHal : public IGunHal {
public:
~Atmega328pHal() {}

Atmega328pHal() {

pinMode(VIBRATOR_PIN, OUTPUT);
pinMode(LASER_PIN, OUTPUT);
}
/*
* the 'loop' method shall be called each 10ms
*
* Configure timer2 so that an interrupt occurs each 10ms
* and wake up the MCU if it is in sleep mode.
*/
void setupHeartbeat() override {
TCCR2A = (1U << WGM21) | (0U << WGM20); // set Timer2 in CTC mode
TCCR2B = (1U << CS22) | (1U << CS21) | (1U << CS20); // 1/1024 prescaler
ASSR &= ~(1U << AS2);
TIMSK2 = (1U << OCIE2A); // enable TIMER2 compare Interrupt
TCNT2 = 0U;

// set the output-compare register based on the desired tick frequency
OCR2A = (F_CPU / BSP_TICKS_PER_SEC / 1024U) - 1U;
}

void laserOn() override { PORTB |= (1 << PB2); }
void laserOff() override { PORTB &= ~(1 << PB2); }
void vibrationOn() override { PORTD |= (1 << PD6); }
void vibrationOff() override { PORTD &= ~(1 << PD6); }

uint16_t getBatteryVoltageMv() override {

analogRead(BATTERY_VOLTAGE_PIN);
float rawBatt = analogRead(BATTERY_VOLTAGE_PIN);
rawBatt += analogRead(BATTERY_VOLTAGE_PIN);
rawBatt += analogRead(BATTERY_VOLTAGE_PIN);
rawBatt += analogRead(BATTERY_VOLTAGE_PIN);
rawBatt /= 4;
uint16_t battMv = (5000 / 1023.f) * rawBatt;

return battMv;
};

uint8_t getBatteryVoltagePercent() override {
return map(getBatteryVoltageMv(), MIN_BAT_VOLTAGE, MAX_BAT_VOLTAGE, 0, 100);
}

virtual bool isCharging() override {
return (digitalRead(CHARGING_STATE_PIN) == HIGH);
}
};
18 changes: 18 additions & 0 deletions lib/Domain/Gun/Button.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
*
* Copyright (c) 2023 Aurélien Labrosse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include <Gun/Button.hpp>
67 changes: 28 additions & 39 deletions lib/Domain/Gun.cpp → lib/Domain/Gun/Button.hpp
Original file line number Diff line number Diff line change
@@ -1,39 +1,28 @@
/*
*
* Copyright (c) 2023 Aurélien Labrosse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Gun.hpp>

static const uint8_t SHOTS_PER_REARM = 5;

void Gun::onButton1ShortPress() {
if (availableShots > 0) {
_hal.laserOn();
_hal.vibrationOn();
_hal.shortDelay();
_hal.laserOff();
_hal.vibrationOff();
availableShots--;
}

}

void Gun::onButton1LongPress() {
_hal.deepSleep();
}
void Gun::onButton2ShortPress() { availableShots = SHOTS_PER_REARM; }
void Gun::onButton2LongPress() {
_hal.laserOn();
}
/*
*
* Copyright (c) 2023 Aurélien Labrosse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <Contactor.hpp>

class Button : public Contactor {

public:
Button() : Contactor(), calibrationMode(false) {}

bool calibrationMode;
void onShortPress() override { shootCount = 0; }
void onLongPress() override { calibrationMode = !calibrationMode; }
};
143 changes: 143 additions & 0 deletions lib/Domain/Gun/Gun.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
/*
*
* Copyright (c) 2023 Aurélien Labrosse
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <Contactor.hpp>
#include <Gun.hpp>
#include <LowPower.h>

volatile uint16_t hitcount;
uint16_t previoushitcout;
volatile uint16_t shootCount;

#define TICKS_BETWEEN_UI_UPDATE 10

// display API
static void displayBatteryStatus();
static void displayShootCount();

void setup();
static void setupHeartbeat();

// counter for ticks between battery display update
uint16_t updateBatteryDisplayCycleCount;

Trigger trigger;
Button button;

volatile Contactor::Event pendingTriggerEvent;
void triggerInterruptHandler() {
if (bit_is_set(PIND, PD2)) {
pendingTriggerEvent = Contactor::Event::Released;
} else {
pendingTriggerEvent = Contactor::Event::Pressed;
}
}

volatile Contactor::Event pendingButtonEvent;
void buttonInterruptHandler() {
if (bit_is_set(PIND, PD3)) {
pendingButtonEvent = Contactor::Event::Released;
} else {
pendingButtonEvent = Contactor::Event::Pressed;
}
}

long now = 0;

void Gun::loop(void) {

now += 10; // 10ms per loop thanks to timer2

trigger.decreaseCycleCount();

cli();
trigger.pendingEvent = pendingTriggerEvent;
button.pendingEvent = pendingButtonEvent;
pendingTriggerEvent = Contactor::Event::NoEvent;
pendingButtonEvent = Contactor::Event::NoEvent;
sei();

trigger.processPendingEvent(now);
button.processPendingEvent(now);

button.checkForLongPress(now);

if (button.calibrationMode) {
hal->laserOn();
hal->vibrationOff();

} else {
if (trigger.shootCycleCountdown == 0) {
hal->laserOff();
hal->vibrationOff();
ui->displayShootCount(shootCount);
}

if (updateBatteryDisplayCycleCount > 0) {
updateBatteryDisplayCycleCount--;
}
if (updateBatteryDisplayCycleCount == 0) {
displayBatteryStatus();
updateBatteryDisplayCycleCount = TICKS_BETWEEN_UI_UPDATE;
}
}

LowPower.idle(SLEEP_15MS, ADC_OFF, TIMER2_ON, TIMER1_ON, TIMER0_ON, SPI_OFF,
USART0_OFF, TWI_OFF);
}


void Gun::setup(void) {

#if defined(SERIAL_OUTPUT)
Serial.begin(115200);
while (!Serial) {
}

shootCount = 0;
updateBatteryDisplayCycleCount = TICKS_BETWEEN_UI_UPDATE;

pinMode(LASER_PIN, OUTPUT);
digitalWrite(LASER_PIN, LOW);

pinMode(OUT2_PIN, OUTPUT);
digitalWrite(OUT2_PIN, LOW);

pinMode(BATTERY_VOLTAGE_PIN, INPUT);
pinMode(CHARGING_STATE_PIN, INPUT);

pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);

#if defined(SERIAL_OUTPUT)
Serial.println("Ready!");
#endif

ui->displaySplash();
ui->displayBatteryStatus();
ui->displayShootCount();

pinMode(BUTTON2_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON2_PIN), buttonInterruptHandler,
CHANGE);

pinMode(TRIGGER_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(TRIGGER_PIN), triggerInterruptHandler,
CHANGE);
cli();
setupHeartbeat();
sei();
}
17 changes: 8 additions & 9 deletions lib/Domain/Gun.hpp → lib/Domain/Gun/Gun.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,17 @@
*/
#pragma once

#include <IGunHal.hpp>
#include <stdint.h>
#include <Gun/IGunHal.hpp>
#include <Gun/IGunUi.hpp>

class Gun {

IGunHal &_hal;
IGunHal *hal;
IGunUi *ui;

public:
uint8_t availableShots;
Gun(IGunHal &hal) : _hal(hal) {}
void onButton1ShortPress();
void onButton1LongPress();
void onButton2ShortPress();
void onButton2LongPress();
Gun(IGunHal *hal, IGunUi *ui) : hal(hal), ui(ui) {}

void loop();
void setup();
};
18 changes: 11 additions & 7 deletions lib/Domain/IGunHal.hpp → lib/Domain/Gun/IGunHal.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,22 @@
*/
#pragma once

#include <stdint.h>

class IGunHal {
public:
virtual ~IGunHal() {}
virtual bool isTriggerDown() = 0;
virtual bool isButtonDown() = 0;
virtual void shortDelay() = 0;
virtual void longDelay() = 0;
virtual void ledOn() = 0;
virtual void ledOff() = 0;

/*
* the 'loop' method shall be called each 10ms
*/
virtual void setupHeartbeat() = 0;

virtual void laserOn() = 0;
virtual void laserOff() = 0;
virtual void vibrationOn() = 0;
virtual void vibrationOff() = 0;
virtual void deepSleep() = 0;
virtual uint16_t getBatteryVoltageMv() = 0;
virtual bool isCharging() = 0;

};
Loading

0 comments on commit 83a63c8

Please sign in to comment.