#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 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

	while(1);
}

ISR(PCINT2_vect) {
	on_press(SW1, increment_led);
	on_press(SW2, decrement_led);
}
