@@ -10,27 +10,33 @@
# include <avr/sleep.h>
# include <avr/sleep.h>
# include <avr/interrupt.h>
# include <avr/interrupt.h>
# define BUTTON_PIN_MASK 0x01 // PA0
# define BUTTON_PIN_MASK 0x01 // PA0 used as RESET/UPDI pin
# define PA1_SET_MASK 0x02 // LED 1– 2
# define PA1_SET_MASK 0x02 ///< LED 1– 2
# define PA2_SET_MASK 0x04 // LED 3– 6
# define PA2_SET_MASK 0x04 ///< LED 3– 6
# define PA3_SET_MASK 0x08 // LED 7– 8
# define PA3_SET_MASK 0x08 ///< LED 7– 8
# define PA6_SET_MASK 0x40 // Green LED
# define PA6_SET_MASK 0x40 ///< Green LED pin
# define PA7_SET_MASK 0x80 // Red LED
# define PA7_SET_MASK 0x80 ///< Red LED
# define MAIN_LOOP_SLEEP 50U // Loop period in ms
# define MAIN_LOOP_SLEEP 50U // Loop period 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 1 000U // I gnore after long press
# define BUTTON_IGNORE_DURATION_MS 2 000U // Time button i gnored after long press
# define BUTTON_CONFIRMATION_BLINK_LOOPS 10U // Blink animation for confirmation
# define BUTTON_CONFIRMATION_BLINK_DURATION_MS 50U
# define MS_TO_TICKS(ms) ((ms) / MAIN_LOOP_SLEEP)
# define MS_TO_TICKS(ms) ((ms) / MAIN_LOOP_SLEEP)
volatile bool bLedEnabled = false ;
/** Global flags */
volatile bool bLedEnabled = true ;
volatile bool bBtnPressed = false ;
volatile bool bBtnPressed = false ;
// Forward declarations
void blinkLed ( bool resetCounters ) ;
static inline void leds_off ( void ) ;
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 ) ;
void blinkLed ( bool resetCounters ) ;
static void software_reset ( void ) ;
ISR ( PORTA_PORT_vect ) ;
/* --- Timer init: Use RTC PIT for periodic wake-up --- */
/* --- Timer init: Use RTC PIT for periodic wake-up --- */
void init_timer ( void )
void init_timer ( void )
@@ -86,19 +92,32 @@ 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
PORTA . PIN0CTRL = PORT_PULLUPEN_bm | PORT_ISC_FALLING_gc ;
set_sleep_mode ( SLEEP_MODE_STANDBY ) ; // Deepest sleep mode (standby)
sleep_enable ( ) ; // Enable sleep
cli ( ) ; // Disable global interrupts
sei ( ) ; // Re-enable interrupts
sleep_cpu ( ) ; // MCU sleeps here
}
}
else
else
{
{
@@ -171,6 +190,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)
*
*