Compare commits
	
		
			7 Commits
		
	
	
		
			1.0.0
			...
			feature/en
		
	
	| Author | SHA256 | Date | |
|---|---|---|---|
| a9f342b45b | |||
| 042d38b0f5 | |||
| 7e8165e7a2 | |||
| e0781257a6 | |||
| 35c66787de | |||
| c9d30ef44e | |||
| 74a0780219 | 
| @ -76,7 +76,7 @@ Hardware: FT232 USB-UART adapter connected to UPDI with a 4.7 kΩ resistor. | ||||
|    ``` | ||||
| 4. Flash using pymcuprog: | ||||
|    ```bash | ||||
|     pymcuprog -t uart -u /dev/ttyUSB0 -d attiny202 write -f build/main.hex | ||||
|     pymcuprog -t uart -u /dev/ttyUSB0 -d attiny202 erase && pymcuprog -t uart -u /dev/ttyUSB0 -d attiny202 write -f build/main.hex | ||||
|    ``` | ||||
| ## Hardware Setup (FT232 → ATtiny202 UPDI) | ||||
|    ```bash | ||||
|  | ||||
							
								
								
									
										99
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										99
									
								
								main.c
									
									
									
									
									
								
							| @ -1,26 +1,28 @@ | ||||
| /** | ||||
|  * @file main.c | ||||
|  * @brief Bike rear light implementation for ATTINY202. | ||||
|  * | ||||
|  * @brief Bike rear light implementation for ATTINY202 with low-power standby. | ||||
|  */ | ||||
|  | ||||
| #include <stdint.h> | ||||
| #include <stdbool.h> | ||||
| #include <avr/io.h> | ||||
| #include <util/delay.h> | ||||
| #include <avr/sleep.h> | ||||
| #include <avr/interrupt.h> | ||||
|  | ||||
| #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 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 MAIN_LOOP_SLEEP 10U                 // Main loop delay in ms | ||||
| #define MAIN_LOOP_SLEEP 50U                 // Loop period in ms | ||||
| #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 */ | ||||
| #define MS_TO_TICKS(ms) ((ms) / MAIN_LOOP_SLEEP) | ||||
|  | ||||
| /** Global flags */ | ||||
| @ -33,10 +35,28 @@ 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); | ||||
|  | ||||
| /** | ||||
|  * @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 | ||||
| @ -52,7 +72,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 | ||||
|  | ||||
| @ -66,19 +92,32 @@ 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_IGNORE_DURATION_MS / 10); | ||||
|                 _delay_ms(BUTTON_CONFIRMATION_BLINK_DURATION_MS); | ||||
|                 leds_on(); | ||||
|             _delay_ms(BUTTON_IGNORE_DURATION_MS / 10); | ||||
|                 _delay_ms(BUTTON_CONFIRMATION_BLINK_DURATION_MS); | ||||
|                 leds_off(); | ||||
|             } | ||||
|  | ||||
|             // Give time until button is released | ||||
|             _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 | ||||
|         { | ||||
| @ -88,7 +127,9 @@ int main(void) | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         _delay_ms(MAIN_LOOP_SLEEP); | ||||
|         sleep_enable(); | ||||
|         sleep_cpu(); // Sleep until PIT wakes | ||||
|         sleep_disable(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @ -149,6 +190,32 @@ 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) | ||||
|  * | ||||
| @ -279,7 +346,7 @@ void blinkLed(bool resetCounters) | ||||
|         if (counter >= T250) | ||||
|         { | ||||
|             counter = 0; | ||||
|             state = 0; // restart normal sequence | ||||
|             state = 0; | ||||
|         } | ||||
|         break; | ||||
|     } | ||||
|  | ||||
		Reference in New Issue
	
	Block a user