@@ -1,7 +1,6 @@
/**
* @file main.c
* @brief Bike rear light implementation for ATTINY202.
*
* @brief Bike rear light implementation for ATTINY202 with low-power standby .
*/
# include <stdint.h>
@@ -11,38 +10,47 @@
# include <avr/sleep.h>
# include <avr/interrupt.h>
# define BUTTON_PIN_MASK 0x01 // PA0 used as RESET/UPDI pin
# define PA1_SET_MASK 0x02 ///< LED 1– 2
# define PA2_SET_MASK 0x04 ///< LED 3– 6
# define PA3_SET_MASK 0x08 ///< LED 7– 8
# define PA6_SET_MASK 0x40 ///< Green LED pin
# define PA7_SET_MASK 0x80 ///< Red LED
# define BUTTON_PIN_MASK 0x01 // PA0
# define PA1_SET_MASK 0x02 // LED 1– 2
# define PA2_SET_MASK 0x04 // LED 3– 6
# define PA3_SET_MASK 0x08 // LED 7– 8
# define PA6_SET_MASK 0x40 // Green LED
# define PA7_SET_MASK 0x80 // Red LED
# define MAIN_LOOP_SLEEP 1 0U // Main loop delay in ms
# define MAIN_LOOP_SLEEP 5 0U // Loop period in ms
# define BUTTON_LONG_PRESS_DURATION_MS 1000U // Long press threshold
# 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 BUTTON_IGNORE_DURATION_MS 1 000U // I gnore after long press
/** Convert milliseconds to system ticks */
# define MS_TO_TICKS(ms) ((ms) / MAIN_LOOP_SLEEP)
/** Global flags */
volatile bool bLedEnabled = true ;
volatile bool bLedEnabled = false ;
volatile bool bBtnPressed = false ;
// Forward declarations
void blinkLed ( bool resetCounters ) ;
static inline void leds_off ( void ) ;
static inline void leds_on ( void ) ;
static void battery_level_indicator ( void ) ;
static void handleSwitch ( void ) ;
static void software_reset ( void ) ;
ISR ( PORTA_PORT_vect ) ;
void blinkLed ( bool resetCounters ) ;
/**
* @brief Main entry point
*/
/* --- Timer init: Use RTC PIT for periodic wake-up --- */
void init_timer ( void )
{
RTC . CLKSEL = RTC_CLKSEL_INT1K_gc ; // 1 kHz ULP clock for RTC
while ( RTC . STATUS > 0 )
{
} // Wait for sync
RTC . PITINTCTRL = RTC_PI_bm ; // Enable PIT interrupt
RTC . PITCTRLA = RTC_PERIOD_CYC64_gc // ≈64 ms wake-up (~50 ms)
| RTC_PITEN_bm ; // Enable PIT
}
ISR ( RTC_PIT_vect )
{
RTC . PITINTFLAGS = RTC_PI_bm ; // Clear interrupt flag
}
/* --- MAIN --- */
int main ( void )
{
// Configure LED pins as outputs
@@ -58,7 +66,13 @@ int main(void)
bool bLedEnabledOld = bLedEnabled ;
while ( true )
cli ( ) ;
init_timer ( ) ;
sei ( ) ;
set_sleep_mode ( SLEEP_MODE_STANDBY ) ;
while ( 1 )
{
handleSwitch ( ) ; // Check switch state
@@ -72,32 +86,19 @@ int main(void)
leds_off ( ) ;
}
// Long press detected --> show confirmation blink
// Long press detected → show confirmation blink
if ( bLedEnabledOld ! = bLedEnabled )
{
bLedEnabledOld = bLedEnabled ;
for ( uint8_t i = 0U ; i < BUTTON_CONFIRMATION_BLINK_LOOPS ; i + + )
{
leds_off ( ) ;
_delay_ms ( BUTTON_CONFIRMATION_BLINK_DURATION_MS ) ;
_delay_ms ( BUTTON_IGNORE_DURATION_MS / 10 ) ;
leds_on ( ) ;
_delay_ms ( BUTTON_CONFIRMATION_BLINK_DURATION_MS ) ;
_delay_ms ( BUTTON_IGNORE_DURATION_MS / 10 ) ;
leds_off ( ) ;
}
// Give time until button is released
_delay_ms ( BUTTON_IGNORE_DURATION_MS ) ;
// 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
blinkLed ( true ) ; // reset blink state machine
}
else
{
@@ -107,7 +108,9 @@ int main(void)
}
}
_delay_ms ( MAIN_LOOP_SLEEP ) ;
sleep_enable ( ) ;
sleep_cpu ( ) ; // Sleep until PIT wakes
sleep_disable ( ) ;
}
}
@@ -168,32 +171,6 @@ static void handleSwitch(void)
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)
*
@@ -324,7 +301,7 @@ void blinkLed(bool resetCounters)
if ( counter > = T250 )
{
counter = 0 ;
state = 0 ; // restart normal sequence
state = 0 ;
}
break ;
}