diff --git a/Makefile b/Makefile index 8e16276..408a122 100644 --- a/Makefile +++ b/Makefile @@ -8,10 +8,15 @@ flash: build build: gympal.hex -gympal.hex: src/gympal.c bin - avr-gcc -Wall -Os -DF_CPU=16000000UL -mmcu=atmega328p -c src/gympal.c -o bin/gympal.o - avr-gcc -Os -mmcu=atmega328p -o bin/gympal.elf bin/gympal.o +gympal.hex: gympal.o control.o + avr-gcc -Os -mmcu=atmega328p -o bin/gympal.elf bin/gympal.o bin/control.o avr-objcopy -O ihex -R .eeprom bin/gympal.elf bin/gympal.hex +gympal.o: src/gympal.c bin + avr-gcc -Wall -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o bin/gympal.o src/gympal.c + +control.o: src/control.c bin + avr-gcc -Wall -Os -DF_CPU=16000000UL -mmcu=atmega328p -c -o bin/control.o src/control.c + bin: mkdir bin \ No newline at end of file diff --git a/src/control.c b/src/control.c new file mode 100644 index 0000000..0a829fd --- /dev/null +++ b/src/control.c @@ -0,0 +1,47 @@ +#include "control.h" + +volatile uint8_t CTL_INPUT_FLAGS = 0; + +uint8_t readPin(uint8_t inputRegister, uint8_t inputPin) { + return (inputRegister & (1 << inputPin)) >> inputPin; +} + +ISR(PCINT2_vect) { + cli(); + uint8_t rotDt = readPin(PIND, CTL_ROTARY_ENCODER_DT_IN); + uint8_t rotClk = readPin(PIND, CTL_ROTARY_ENCODER_CLK_IN); + uint8_t buttonA = readPin(PIND, CTL_BUTTON_A_IN); + uint8_t buttonB = readPin(PIND, CTL_BUTTON_B_IN); + uint8_t buttonC = readPin(PIND, CTL_BUTTON_C_IN); + CTL_INPUT_FLAGS = ( + (rotDt << CTL_ROTARY_ENCODER_DT_FLAG) | + (rotClk << CTL_ROTARY_ENCODER_CLK_FLAG) | + (buttonA << CTL_BUTTON_A_FLAG) | + (buttonB << CTL_BUTTON_B_FLAG) | + (buttonC << CTL_BUTTON_C_FLAG) + ); + sei(); +} + +void ctl_init() { + // Set all control pins as input (0). + DDRD &= ~( + (1 << CTL_ROTARY_ENCODER_DT) | + (1 << CTL_ROTARY_ENCODER_CLK) | + (1 << CTL_BUTTON_A) | + (1 << CTL_BUTTON_B) | + (1 << CTL_BUTTON_C) + ); + // Set up interrupts for handling control pin state changes. + // Luckily, all interrupts happen on PCINT[16..23] so we only need one interrupt to handle them all. + PCICR |= 1 << PCIE2; // Enable PCINT2_vector interrupts. + PCMSK2 |= (// Enable the flag for each input we want to cause interrupts on state change. + (1 << CTL_ROTARY_ENCODER_DT_INT) | + (1 << CTL_ROTARY_ENCODER_CLK_INT) | + (1 << CTL_BUTTON_A_INT) | + (1 << CTL_BUTTON_B_INT) | + (1 << CTL_BUTTON_C_INT) + ); + // Enable the global interrupt flag. + sei(); +} \ No newline at end of file diff --git a/src/control.h b/src/control.h new file mode 100644 index 0000000..d88db2d --- /dev/null +++ b/src/control.h @@ -0,0 +1,39 @@ +#ifndef CONTROL_H +#define CONTROL_H + +#include +#include + +#define CTL_ROTARY_ENCODER_DT PORTD2 +#define CTL_ROTARY_ENCODER_DT_IN PIND2 +#define CTL_ROTARY_ENCODER_DT_INT PCINT18 +#define CTL_ROTARY_ENCODER_DT_FLAG 0 + +#define CTL_ROTARY_ENCODER_CLK PORTD3 +#define CTL_ROTARY_ENCODER_CLK_IN PIND3 +#define CTL_ROTARY_ENCODER_CLK_INT PCINT19 +#define CTL_ROTARY_ENCODER_CLK_FLAG 1 + +#define CTL_BUTTON_A PORTD5 +#define CTL_BUTTON_A_IN PIND5 +#define CTL_BUTTON_A_INT PCINT21 +#define CTL_BUTTON_A_FLAG 2 + +#define CTL_BUTTON_B PORTD6 +#define CTL_BUTTON_B_IN PIND6 +#define CTL_BUTTON_B_INT PCINT22 +#define CTL_BUTTON_B_FLAG 3 + +#define CTL_BUTTON_C PORTD7 +#define CTL_BUTTON_C_IN PIND7 +#define CTL_BUTTON_C_INT PCINT23 +#define CTL_BUTTON_C_FLAG 4 + +extern volatile uint8_t CTL_INPUT_FLAGS; + +/** + * @brief Initializes the user control inputs and interrupts. + */ +void ctl_init(); + +#endif \ No newline at end of file diff --git a/src/gympal.c b/src/gympal.c index 634dba8..dd25570 100644 --- a/src/gympal.c +++ b/src/gympal.c @@ -1,33 +1,24 @@ #include -#include #include -volatile uint8_t a = 0; - -void updatePin12(uint8_t status) { - PORTB = status << PORTB4; -} - -ISR(PCINT2_vect) { - uint8_t value = (PIND & (1 << PIND5)) >> PIND5; - PORTB = value << PORTB4; -} +#include "control.h" int main() { - PCICR |= 1 << PCIE2; - PCMSK2 |= 1 << PCINT21; - sei(); - // Pin 12 == Port B4, aka 4th bit on the B register. - // Set pin 12 as output. + ctl_init(); + // Just for testing the interrupts, we're setting up B4 as an indicator LED. DDRB |= 1 << PORTB4; - // Set pin 5 as input. - DDRD &= ~(1 << PORTD5); PORTB &= ~(1 << PORTB4); - while (1) { - // updatePin12(ledOn); - // ledOn = !ledOn; - // _delay_ms(1000.0); - // DO NOTHING! rely on interrupt. + uint8_t led = 0; + while(1) { + uint8_t v = (CTL_INPUT_FLAGS & (1 << CTL_BUTTON_B_FLAG)) >> CTL_BUTTON_A_FLAG; + if (led != v) { + led = v; + if (led) { + PORTB |= 1 << PORTB4; + } else { + PORTB &= ~(1 << PORTB4); + } + } } return 0; } \ No newline at end of file