This commit is contained in:
2025-10-25 14:47:08 +02:00
parent e0781257a6
commit 7e8165e7a2

86
main.c
View File

@ -10,10 +10,8 @@
#include <util/delay.h> #include <util/delay.h>
#include <avr/sleep.h> #include <avr/sleep.h>
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/wdt.h>
#include <avr/cpufunc.h> // for CCP
#define BUTTON_PIN_MASK 0x01 // PA0 TODO: using RESET/UPDI pin #define BUTTON_PIN_MASK 0x01 // PA0 used as RESET/UPDI pin
#define PA1_SET_MASK 0x02 ///< LED 12 #define PA1_SET_MASK 0x02 ///< LED 12
#define PA2_SET_MASK 0x04 ///< LED 36 #define PA2_SET_MASK 0x04 ///< LED 36
#define PA3_SET_MASK 0x08 ///< LED 78 #define PA3_SET_MASK 0x08 ///< LED 78
@ -22,7 +20,9 @@
#define MAIN_LOOP_SLEEP 10U // Main loop delay in ms #define MAIN_LOOP_SLEEP 10U // Main loop delay in ms
#define BUTTON_LONG_PRESS_DURATION_MS 1000U // Long press threshold #define BUTTON_LONG_PRESS_DURATION_MS 1000U // Long press threshold
#define BUTTON_IGNORE_DURATION_MS 1000U // Time button ignored after long press #define BUTTON_IGNORE_DURATION_MS 2000U // Time button ignored after long press
#define BUTTON_CONFIRMATION_BLINK_LOOPS 10U // Blink animation for confirmation
#define BUTTON_CONFIRMATION_BLINK_DURATION_MS 50U
/** Convert milliseconds to system ticks */ /** Convert milliseconds to system ticks */
#define MS_TO_TICKS(ms) ((ms) / MAIN_LOOP_SLEEP) #define MS_TO_TICKS(ms) ((ms) / MAIN_LOOP_SLEEP)
@ -37,43 +37,19 @@ static inline void leds_off(void);
static inline void leds_on(void); static inline void leds_on(void);
static void battery_level_indicator(void); static void battery_level_indicator(void);
static void handleSwitch(void); static void handleSwitch(void);
int main(void); static void software_reset(void);
ISR(PORTA_PORT_vect);
void software_reset(void)
{
CCP = CCP_IOREG_gc; // unlock protected registers
RSTCTRL.SWRR = 1; // trigger software reset
while (1)
; // wait for reset
}
ISR(PORTA_PORT_vect)
{
// Clear interrupt flags for PA0
PORTA.INTFLAGS = BUTTON_PIN_MASK;
if (!(VPORTA.IN & BUTTON_PIN_MASK)) // check PA0 low
{
// Turn off all LEDs
leds_off();
software_reset();
}
}
/** /**
* @brief Main entry point * @brief Main entry point
*/ */
int main(void) int main(void)
{ {
// MCU resumes execution here after reset
sleep_disable(); // Disable sleep
// Configure LED pins as outputs // Configure LED pins as outputs
VPORTA.DIR = (PA1_SET_MASK | PA2_SET_MASK | PA3_SET_MASK | PA6_SET_MASK | PA7_SET_MASK); VPORTA.DIR = (PA1_SET_MASK | PA2_SET_MASK | PA3_SET_MASK | PA6_SET_MASK | PA7_SET_MASK);
// Configure PA0 as input with pull-up // Configure PA0 as input with pull-up
VPORTA.DIR &= ~BUTTON_PIN_MASK; // Input VPORTA.DIR &= ~BUTTON_PIN_MASK; // Input
// register8_t backup_ctl = PORTA.PIN0CTRL;
PORTA.PIN0CTRL = PORT_PULLUPEN_bm; // Pull-up enabled PORTA.PIN0CTRL = PORT_PULLUPEN_bm; // Pull-up enabled
// Ensure all LEDs off at startup // Ensure all LEDs off at startup
@ -96,24 +72,24 @@ int main(void)
leds_off(); leds_off();
} }
// Long press detected show confirmation blink // Long press detected --> show confirmation blink
if (bLedEnabledOld != bLedEnabled) if (bLedEnabledOld != bLedEnabled)
{ {
bLedEnabledOld = bLedEnabled; bLedEnabledOld = bLedEnabled;
leds_off(); for (uint8_t i = 0U; i < BUTTON_CONFIRMATION_BLINK_LOOPS; i++)
_delay_ms(BUTTON_IGNORE_DURATION_MS / 10); {
leds_on(); leds_off();
_delay_ms(BUTTON_IGNORE_DURATION_MS / 10); _delay_ms(BUTTON_CONFIRMATION_BLINK_DURATION_MS);
leds_off(); leds_on();
_delay_ms(BUTTON_CONFIRMATION_BLINK_DURATION_MS);
leds_off();
}
// Give time until button is released
_delay_ms(BUTTON_IGNORE_DURATION_MS); _delay_ms(BUTTON_IGNORE_DURATION_MS);
blinkLed(true); // reset blink state machine // Activate the interrupt for PA0
leds_off();
_delay_ms(BUTTON_IGNORE_DURATION_MS * 2);
// TODO: activate the interrupt for PA0
PORTA.PIN0CTRL = PORT_PULLUPEN_bm | PORT_ISC_FALLING_gc; PORTA.PIN0CTRL = PORT_PULLUPEN_bm | PORT_ISC_FALLING_gc;
set_sleep_mode(SLEEP_MODE_STANDBY); // Deepest sleep mode (standby) set_sleep_mode(SLEEP_MODE_STANDBY); // Deepest sleep mode (standby)
@ -192,6 +168,32 @@ static void handleSwitch(void)
prevPressed = pressed; prevPressed = pressed;
} }
/**
* @brief Perform software reset
*/
static void software_reset(void)
{
CCP = CCP_IOREG_gc; // unlock protected registers
RSTCTRL.SWRR = 1; // trigger software reset
while (1)
; // wait for reset
}
/**
* @brief Interrupt service routine
*/
ISR(PORTA_PORT_vect)
{
// Clear interrupt flags for PA0
PORTA.INTFLAGS = BUTTON_PIN_MASK;
if (!(VPORTA.IN & BUTTON_PIN_MASK)) // check PA0 low
{
// Turn off all LEDs
software_reset();
}
}
/** /**
* @brief LED blink state machine (bike rear light style) * @brief LED blink state machine (bike rear light style)
* *