Compare commits
	
		
			1 Commits
		
	
	
		
			1.1.0
			...
			74a0780219
		
	
	| Author | SHA256 | Date | |
|---|---|---|---|
| 74a0780219 | 
| @ -76,7 +76,7 @@ Hardware: FT232 USB-UART adapter connected to UPDI with a 4.7 kΩ resistor. | |||||||
|    ``` |    ``` | ||||||
| 4. Flash using pymcuprog: | 4. Flash using pymcuprog: | ||||||
|    ```bash |    ```bash | ||||||
|     pymcuprog -t uart -u /dev/ttyUSB0 -d attiny202 erase && pymcuprog -t uart -u /dev/ttyUSB0 -d attiny202 write -f build/main.hex |     pymcuprog -t uart -u /dev/ttyUSB0 -d attiny202 write -f build/main.hex | ||||||
|    ``` |    ``` | ||||||
| ## Hardware Setup (FT232 → ATtiny202 UPDI) | ## Hardware Setup (FT232 → ATtiny202 UPDI) | ||||||
|    ```bash |    ```bash | ||||||
|  | |||||||
							
								
								
									
										119
									
								
								main.c
									
									
									
									
									
								
							
							
						
						
									
										119
									
								
								main.c
									
									
									
									
									
								
							| @ -1,7 +1,6 @@ | |||||||
| /** | /** | ||||||
|  * @file main.c |  * @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 <stdint.h> | ||||||
| @ -11,38 +10,47 @@ | |||||||
| #include <avr/sleep.h> | #include <avr/sleep.h> | ||||||
| #include <avr/interrupt.h> | #include <avr/interrupt.h> | ||||||
|  |  | ||||||
| #define BUTTON_PIN_MASK 0x01 // PA0 used as RESET/UPDI pin | #define BUTTON_PIN_MASK 0x01 // PA0 | ||||||
| #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 pin | #define PA6_SET_MASK 0x40    // Green LED | ||||||
| #define PA7_SET_MASK 0x80    ///< Red LED | #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_LONG_PRESS_DURATION_MS 1000U // Long press threshold | ||||||
| #define BUTTON_IGNORE_DURATION_MS 2000U     // Time button ignored after long press | #define BUTTON_IGNORE_DURATION_MS 1000U     // Ignore 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) | #define MS_TO_TICKS(ms) ((ms) / MAIN_LOOP_SLEEP) | ||||||
|  |  | ||||||
| /** Global flags */ | volatile bool bLedEnabled = false; | ||||||
| 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); | ||||||
| static void software_reset(void); | void blinkLed(bool resetCounters); | ||||||
| ISR(PORTA_PORT_vect); |  | ||||||
|  |  | ||||||
| /** | /* --- Timer init: Use RTC PIT for periodic wake-up --- */ | ||||||
|  * @brief Main entry point | 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) | int main(void) | ||||||
| { | { | ||||||
|     // Configure LED pins as outputs |     // Configure LED pins as outputs | ||||||
| @ -58,7 +66,13 @@ int main(void) | |||||||
|  |  | ||||||
|     bool bLedEnabledOld = bLedEnabled; |     bool bLedEnabledOld = bLedEnabled; | ||||||
|  |  | ||||||
|     while (true) |     cli(); | ||||||
|  |     init_timer(); | ||||||
|  |     sei(); | ||||||
|  |  | ||||||
|  |     set_sleep_mode(SLEEP_MODE_STANDBY); | ||||||
|  |  | ||||||
|  |     while (1) | ||||||
|     { |     { | ||||||
|         handleSwitch(); // Check switch state |         handleSwitch(); // Check switch state | ||||||
|  |  | ||||||
| @ -72,32 +86,19 @@ 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; | ||||||
|  |  | ||||||
|             for (uint8_t i = 0U; i < BUTTON_CONFIRMATION_BLINK_LOOPS; i++) |             leds_off(); | ||||||
|             { |             _delay_ms(BUTTON_IGNORE_DURATION_MS / 10); | ||||||
|                 leds_off(); |             leds_on(); | ||||||
|                 _delay_ms(BUTTON_CONFIRMATION_BLINK_DURATION_MS); |             _delay_ms(BUTTON_IGNORE_DURATION_MS / 10); | ||||||
|                 leds_on(); |             leds_off(); | ||||||
|                 _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); | ||||||
|  |  | ||||||
|             // Activate the interrupt for PA0 |             blinkLed(true); // reset blink state machine | ||||||
|             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 | ||||||
|         { |         { | ||||||
| @ -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; |     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) | ||||||
|  * |  * | ||||||
| @ -324,7 +301,7 @@ void blinkLed(bool resetCounters) | |||||||
|         if (counter >= T250) |         if (counter >= T250) | ||||||
|         { |         { | ||||||
|             counter = 0; |             counter = 0; | ||||||
|             state = 0; // restart normal sequence |             state = 0; | ||||||
|         } |         } | ||||||
|         break; |         break; | ||||||
|     } |     } | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user