Last active
August 26, 2021 10:40
-
-
Save imax9000/574fe8e83a2e7ae3bf67de1d742c3a08 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
SECTIONS { | |
__vector_20 = __vector_20_override; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <Arduino.h> | |
#define BS_B _BV(0) | |
#define BS_START _BV(1) | |
#define BS_SELECT _BV(2) | |
#define BS_A _BV(3) | |
#define BS_LEFT _BV(0) | |
#define BS_DOWN _BV(1) | |
#define BS_UP _BV(2) | |
#define BS_RIGHT _BV(3) | |
namespace pin { | |
const int up = 4; | |
const int down = 3; | |
const int left = 2; | |
const int right = 5; | |
const int A = 9; | |
const int B = 8; | |
const int select = 6; | |
const int start = 7; | |
// These are fixed: port manipulation code assumes that they have specific | |
// values and won't adjust automatically if these constants are chagned. | |
const int left_b = 17; | |
const int down_start = 16; | |
const int up_select = 15; | |
const int right_a = 14; | |
// ISR assumes that these are on PORTD. | |
const int ab_scan = 21; | |
const int dpad_scan = 20; | |
}; // namespace pin | |
volatile uint8_t buttons_state = 0xF; | |
volatile uint8_t dpad_state = 0xF; | |
void updateButtonState(int pin, uint8_t button, volatile uint8_t *state) { | |
if (digitalRead(pin)) { | |
*state |= button; | |
Serial.print("Button "); | |
Serial.print(pin); | |
Serial.println(" released"); | |
} else { | |
*state &= ~button; | |
Serial.print("Button "); | |
Serial.print(pin); | |
Serial.println(" pressed"); | |
} | |
} | |
// Custom linker script replaces PORTD ISR with this. | |
ISR(__vector_20_override) { | |
PORT_t *portStruct = portToPortStruct(PD); | |
uint8_t int_flags = portStruct->INTFLAGS; | |
if (digitalPinToBitMask(pin::ab_scan) & int_flags) { | |
PORTD.OUT = (PORTD.OUT & (~0xF)) | (buttons_state & 0xF); | |
portStruct->INTFLAGS = digitalPinToBitMask(pin::ab_scan); | |
} | |
if (digitalPinToBitMask(pin::dpad_scan) & int_flags) { | |
PORTD.OUT = (PORTD.OUT & (~0xF)) | (dpad_state & 0xF); | |
portStruct->INTFLAGS = digitalPinToBitMask(pin::dpad_scan); | |
} | |
} | |
void setup() { | |
Serial.begin(9600); | |
pinMode(pin::left_b, OUTPUT); | |
pinMode(pin::down_start, OUTPUT); | |
pinMode(pin::up_select, OUTPUT); | |
pinMode(pin::right_a, OUTPUT); | |
pinMode(pin::ab_scan, INPUT_PULLUP); | |
pinMode(pin::dpad_scan, INPUT_PULLUP); | |
digitalWrite(pin::left_b, HIGH); | |
digitalWrite(pin::down_start, HIGH); | |
digitalWrite(pin::up_select, HIGH); | |
digitalWrite(pin::right_a, HIGH); | |
// Configure the port to receive interrupts. No handler specified, since we | |
// override the handler for the whole port. | |
attachInterrupt(digitalPinToInterrupt(pin::ab_scan), nullptr, FALLING); | |
attachInterrupt(digitalPinToInterrupt(pin::dpad_scan), nullptr, FALLING); | |
// Input button pins | |
for (int pin = 2; pin <= 9; pin++) { | |
pinMode(pin, INPUT_PULLUP); | |
} | |
attachInterrupt( | |
pin::A, []() { updateButtonState(pin::A, BS_A, &buttons_state); }, | |
CHANGE); | |
attachInterrupt( | |
pin::B, []() { updateButtonState(pin::B, BS_B, &buttons_state); }, | |
CHANGE); | |
attachInterrupt( | |
pin::select, | |
[]() { updateButtonState(pin::select, BS_SELECT, &buttons_state); }, | |
CHANGE); | |
attachInterrupt( | |
pin::start, | |
[]() { updateButtonState(pin::start, BS_START, &buttons_state); }, | |
CHANGE); | |
attachInterrupt( | |
pin::up, []() { updateButtonState(pin::up, BS_UP, &dpad_state); }, | |
CHANGE); | |
attachInterrupt( | |
pin::down, []() { updateButtonState(pin::down, BS_DOWN, &dpad_state); }, | |
CHANGE); | |
attachInterrupt( | |
pin::left, []() { updateButtonState(pin::left, BS_LEFT, &dpad_state); }, | |
CHANGE); | |
attachInterrupt( | |
pin::right, | |
[]() { updateButtonState(pin::right, BS_RIGHT, &dpad_state); }, CHANGE); | |
} | |
void loop() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
BOARD := arduino:megaavr:nona4809:mode=off | |
PORT ?= $(wildcard /dev/cu.usbmodem*) | |
.PHONY: all upload build format | |
all: build | |
format: | |
clang-format -i $$(find . -name \*.cpp -o -name \*.ino -o -name \*.h) | |
build: format | |
arduino-cli compile --fqbn $(BOARD) --build-property compiler.c.elf.extra_flags=isr_override.ld . | |
upload: format | |
arduino-cli compile --fqbn $(BOARD) --build-property compiler.c.elf.extra_flags=isr_override.ld --upload --port $(PORT) . |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment