/* * ATmega8A Pin Cycling Test * Version 1: Array in Flash (PROGMEM) * * Cycles through PB0–PB5, PC0–PC5, PD0–PD7. * Every 200 ms: one pin is driven low, then returned to input with pull-up, * then the next pin is selected. * * Same as version 2, but lookup table stored in program memory. * Uses pgm_read_word() to fetch DDR/PORT addresses and mask. */ #include #include #include #include #include typedef struct { uint16_t ddrAddr; uint16_t portAddr; uint8_t mask; } PinDesc; // --- Array of test pins in flash (PROGMEM) --- // Use addresses cast to uint16_t const PinDesc PROGMEM testPins[] = { { (uint16_t)&DDRB, (uint16_t)&PORTB, _BV(PB0) }, { (uint16_t)&DDRB, (uint16_t)&PORTB, _BV(PB1) }, { (uint16_t)&DDRB, (uint16_t)&PORTB, _BV(PB2) }, { (uint16_t)&DDRB, (uint16_t)&PORTB, _BV(PB3) }, { (uint16_t)&DDRB, (uint16_t)&PORTB, _BV(PB4) }, { (uint16_t)&DDRB, (uint16_t)&PORTB, _BV(PB5) }, { (uint16_t)&DDRC, (uint16_t)&PORTC, _BV(PC0) }, { (uint16_t)&DDRC, (uint16_t)&PORTC, _BV(PC1) }, { (uint16_t)&DDRC, (uint16_t)&PORTC, _BV(PC2) }, { (uint16_t)&DDRC, (uint16_t)&PORTC, _BV(PC3) }, { (uint16_t)&DDRC, (uint16_t)&PORTC, _BV(PC4) }, { (uint16_t)&DDRC, (uint16_t)&PORTC, _BV(PC5) }, { (uint16_t)&DDRD, (uint16_t)&PORTD, _BV(PD0) }, { (uint16_t)&DDRD, (uint16_t)&PORTD, _BV(PD1) }, { (uint16_t)&DDRD, (uint16_t)&PORTD, _BV(PD2) }, { (uint16_t)&DDRD, (uint16_t)&PORTD, _BV(PD3) }, { (uint16_t)&DDRD, (uint16_t)&PORTD, _BV(PD4) }, { (uint16_t)&DDRD, (uint16_t)&PORTD, _BV(PD5) }, { (uint16_t)&DDRD, (uint16_t)&PORTD, _BV(PD6) }, { (uint16_t)&DDRD, (uint16_t)&PORTD, _BV(PD7) } }; #define NUM_PINS (sizeof(testPins)/sizeof(testPins[0])) volatile uint8_t currentPin = 0; volatile uint8_t toggleState = 0; ISR(TIMER1_COMPA_vect) { //PORTB ^= _BV(PB0); // toggle PB0 // Fetch PinDesc from flash uint16_t ddrAddr = pgm_read_word(&testPins[currentPin].ddrAddr); uint16_t portAddr = pgm_read_word(&testPins[currentPin].portAddr); uint8_t mask = pgm_read_byte(&testPins[currentPin].mask); volatile uint8_t *ddr = (volatile uint8_t*)ddrAddr; volatile uint8_t *port = (volatile uint8_t*)portAddr; if (toggleState == 0) { *ddr |= mask; // output *port &= ~mask; // drive low toggleState = 1; } else { *ddr &= ~mask; // input *port |= mask; // pull-up currentPin++; if (currentPin >= NUM_PINS) currentPin = 0; toggleState = 0; } } static void pins_init(void) { DDRB = 0x00; DDRC = 0x00; DDRD = 0x00; PORTB = 0xFF; PORTC = 0xFF; PORTD = 0xFF; /*DDRB |= _BV(PB0); // PB0 output PORTB &= ~_BV(PB0);*/ } static void timer1_init(void) { //TCCR1A = 0; TCCR1B = (1 << WGM12) | (1 << CS12); //TCNT1 = 0; OCR1A = 12500 - 1; TIMSK |= (1 << OCIE1A); } int main(void) { pins_init(); timer1_init(); sei(); set_sleep_mode(SLEEP_MODE_IDLE); for (;;) sleep_mode(); }