#include "header.h" // ALTERNATE FUNCTIONS : // Table 14-9 : port D alternate functions // BUTTON1 SW1 PD2 : // -> INT0 (External Interrupt 0 Input) // -> PCINT18 (Pin Change Interrupt 18) // BUTTON2 SW2 PD4 : // -> XCK (USART External Clock Input/Output) // -> T0 (Timer/Counter 0 External Counter Input) // -> PCINT20 (Pin Change Interrupt 20) // EXTERNAL INTERRUPTS GROUP : // 13.2.4 : pin change interrupt controle register (PCICR) // -> bit PCIE2 for PCINT[23:16] (PCI2 Interrupt Vector) // PCMSK2 to enable each pin // INTERRUPT VECTORS NAME : // Table 12-6 : interrupts vectors // -> PCINT2_vect // ENABLE PIN CHANGE INTERRUPT : // 13.2.6 : PCMSK2 – Pin Change Mask Register 2 // -> (1 << PCINT20) | (1 << PCINT18) volatile uint8_t prevPIND; // Store previous state of PIND volatile uint8_t value = 0; void print_binary(int value) { int mask_3 = 0b1000; int bit_at_3 = value & mask_3; int bit_at_4 = bit_at_3 << 1; PORTB = (value & 0b111) + bit_at_4; } void increment_int() { // int *value = params->value; // int max = params->max; value = (value >= MAX) ? MAX : ++value; } void decrement_int() { // int *value = params->value; // int min = params->min; value = (value <= MIN) ? MIN : --value; } void increment_led() { // IncrementParams *params = (IncrementParams *)param; increment_int(); print_binary(value); } void decrement_led() { // IncrementParams *params = (IncrementParams *)param; decrement_int(); print_binary(value); } void on_press(int bit, void (*action)(void)) { if ((TEST(PIND, bit)) == 0) { action(); _delay_ms(20); while ((TEST(PIND, bit)) == 0) { continue; } _delay_ms(20); } } // write a program that incr/decr-ements a number with the buttons, using interrupts, empty infinite loop, and displays the result on LEDs in binary int main() { MODE_OUTPUT(LED1); MODE_OUTPUT(LED2); MODE_OUTPUT(LED3); MODE_OUTPUT(LED4); MODE_INPUT(BUTTON1); MODE_INPUT(BUTTON2); PULLUP_ON(BUTTON1); PULLUP_ON(BUTTON2); SREG |= ENABLE_GLOBAL_INTERRUPT; PCICR = (1 << PCIE2); // 13.2.4 : enable pin change interrupt, bit PCIE2 for PCINT[23:16], (Table 14-9 : alternates : PD2 - PCINT18, PD4 - PCINT20) PCMSK2 = (1 << PCINT20) | (1 << PCINT18); // 13.2.6 : enable individual pin chang interrupt prevPIND = PIND; while(1); } ISR(PCINT2_vect) { uint8_t currentPIND = PIND; // Read the current state of Port D uint8_t changedPins = currentPIND ^ prevPIND; // Find changed bits if (!TEST(changedPins, SW1)) { on_press(SW1, increment_led); } if (!TEST(changedPins, SW1)) { on_press(SW2, decrement_led); } prevPIND = currentPIND; }