144 lines
3.7 KiB
C
144 lines
3.7 KiB
C
#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)
|
||
|
||
#define TIMER_TOP_MS 20
|
||
|
||
volatile uint8_t value = 0;
|
||
volatile Boolean pressed = FALSE;
|
||
volatile Boolean timer_0_init = FALSE;
|
||
volatile Boolean timer_delay_enabled = FALSE;
|
||
volatile uint16_t timer_delay = 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 timer0_init_1_ms() {
|
||
TCCR0A |= (1 << WGM01); // CTC mode
|
||
OCR0A = 249; // Compare match every 1ms (F_CPU / Prescaler = 16,000,000 / 64 = 250,000 ticks/sec)
|
||
TIMSK0 |= (1 << OCIE0A); // Enable Compare Match A interrupt
|
||
TCCR0B |= (1 << CS01) | (1 << CS00); // Prescaler 64
|
||
sei(); // Enable global interrupts
|
||
timer_0_init = TRUE;
|
||
}
|
||
|
||
void launch_delay_ms(void) {
|
||
if (!timer_0_init) {
|
||
timer0_init_1_ms();
|
||
}
|
||
CLEAR(PCICR, PCIE2); // disable interupt PCINT2
|
||
CLEAR(PCMSK2, PCINT20);
|
||
CLEAR(PCMSK2, PCINT18);
|
||
timer_delay = 0;
|
||
timer_delay_enabled = TRUE;
|
||
SET(PCIFR, PCIF2); // reset flag interrupt PCINT2
|
||
}
|
||
|
||
ISR(TIMER0_COMPA_vect) {
|
||
if (!timer_delay_enabled) {
|
||
return;
|
||
}
|
||
timer_delay++;
|
||
if (timer_delay >= TIMER_TOP_MS) {
|
||
// TOGGLE_ELEM(LED1);
|
||
timer_delay_enabled = FALSE;
|
||
SET(PCICR, PCIE2); // re-enable interupt PCINT2
|
||
SET(PCMSK2, PCINT20);
|
||
SET(PCMSK2, PCINT18);
|
||
}
|
||
}
|
||
|
||
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);
|
||
// }
|
||
launch_delay_ms();
|
||
if (!pressed) {
|
||
// if ((TEST(PIND, bit)) == 0) {
|
||
// }
|
||
pressed = TRUE;
|
||
action();
|
||
} else {
|
||
pressed = FALSE;
|
||
}
|
||
}
|
||
|
||
// 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) {
|
||
if (!TEST_PIN(BUTTON1)) {
|
||
on_press(SW1, increment_led);
|
||
}
|
||
if (!TEST_PIN(BUTTON2)) {
|
||
on_press(SW2, decrement_led);
|
||
}
|
||
}
|