diff --git a/README.md b/README.md index 5bf5313..5ea2475 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # HUB75nano -This Arduino library adds the basic functionality needed to drive a HUB 75 protocol LED Panel up to 64x32 Pixels RGB (only tested with 64x32). +This Arduino library can be used to drive a HUB 75 protocol LED Panel up to 64x32 Pixels RGB (tested with 64x32 and 32x16). It can display colors up to 8 bit colors for a full screen, a 1 or 2 bit rgb image buffer (dynamic) or 4 bit rgb buffers (static). It was originally written for the Arduino Nano (It should also work with the Arduino Uno), but is now being ported to a number of other chips in the nano formfactor (or with similar architecture). Refer to the [list below](#Supported-Arduino-boards) for the current state of support. @@ -62,14 +62,15 @@ Example: `#define RA 12` This puts the first row bit on D12 instead of A0. Ⓜ️ : Maybe works, should in theory (probably needs a custom pin assignment) ### 5V boards, work just like that -| board | chip | operating voltage | supported | -| -------------------------- | ------------- | ----------------- | --------- | -| Arduino Nano | ATmega328(p) | 5V | ✅ | -| Arduino Uno R3 | Atmega328p | 5V | Ⓜ️ | -| Arduino Uno WiFi Rev2 | ATmega4809 | 5V | Ⓜ️ | -| Arduino Uno R4 Minima/WiFi | Renesas RA4M1 | 5V | ❌ | -| Arduino Nano Every | ATMega4809 | 5V | ✅ | -| Arduino Mega | ATmega2560 | 5V | ✅ | +| board | chip | operating voltage | supported | +| --------------------- | ------------- | ----------------- | ------------------------------- | +| Arduino Nano | ATmega328(p) | 5V | ✅ | +| Arduino Uno R3 | Atmega328p | 5V | Ⓜ️ | +| Arduino Uno WiFi Rev2 | ATmega4809 | 5V | Ⓜ️ | +| Arduino Uno R4 Minima | Renesas RA4M1 | 5V | ✅ | +| Arduino Uno R4 WiFi | Renesas RA4M1 | 5V | Ⓜ️(pinout different than minima) | +| Arduino Nano Every | ATMega4809 | 5V | ✅ | +| Arduino Mega | ATmega2560 | 5V | ✅ | ### 3.3V boards, usually need level shifters diff --git a/library.properties b/library.properties index eecec45..4a6d060 100644 --- a/library.properties +++ b/library.properties @@ -1,8 +1,8 @@ name=HUB75nano -version=2.3.0 +version=2.3.1 author=Leonhard Seidel maintainer=Leonhard Seidel -sentence=This Library makes the Arduino Nano/Uno/Nano Every/Mega drive a HUB75 panel from 8x16 up to 32x64 +sentence=This Library makes the Arduino Nano/Uno/Uno R4 Minima/Nano Every/Mega drive a HUB75 panel from 8x16 up to 32x64 paragraph=You can use a 1 or 2 bit buffer to store the images which you want to display, or display 4 bit from FLASH. category=Display url=https://github.com/CamelCaseName/HUB75nano/ diff --git a/src/boards/board.h b/src/boards/board.h index acce83a..ed0393b 100644 --- a/src/boards/board.h +++ b/src/boards/board.h @@ -25,6 +25,9 @@ #ifdef ARDUINO_AVR_MEGA2560 #include "boards/mega/mega.h" #else +#ifdef ARDUINO_MINIMA +#include "boards/uno_r4/uno_r4.h" +#else #error "This library currently only supports the Arduino Nano or Uno with Atmega328(p), Nano Every, Nano 33 IOT, Nano 33 BLE, Nano RP2040" #endif #endif @@ -33,6 +36,7 @@ #endif #endif #endif +#endif #ifndef PANEL_X #error "Panel size needs to be defined" diff --git a/src/boards/board_methods.h b/src/boards/board_methods.h index c47919a..4a955f7 100644 --- a/src/boards/board_methods.h +++ b/src/boards/board_methods.h @@ -38,6 +38,9 @@ #ifdef ARDUINO_AVR_MEGA2560 #include "boards/mega/mega_methods.h" #else +#ifdef ARDUINO_MINIMA +#include "boards/uno_r4/uno_r4_methods.h" +#else #error "This library currently only supports the Arduino Nano or Uno with Atmega328(p), Nano Every, Nano 33 IOT, Nano 33 BLE, Nano RP2040" #endif #endif @@ -46,5 +49,6 @@ #endif #endif #endif +#endif #endif // HUB75NANO_BOARD_METHODS \ No newline at end of file diff --git a/src/boards/iot/iot_methods.h b/src/boards/iot/iot_methods.h index 243b7b9..eb7885b 100644 --- a/src/boards/iot/iot_methods.h +++ b/src/boards/iot/iot_methods.h @@ -94,22 +94,22 @@ _stepRow() #endif #endif #ifdef PANEL_ROW_PINS_OOO - uint8_t invertedRow = (~PANEL_ROW_VAR) & 15; + uint8_t invertedRow = (~PANEL_ROW_VAR) & ((PANEL_Y / 2) - 1); PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RA))].OUTSET.reg = (PANEL_ROW_VAR & 1) << bit_from_pin(arduino_pin_to_avr_pin(RA)); PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RA))].OUTCLR.reg = (invertedRow & 1) << bit_from_pin(arduino_pin_to_avr_pin(RA)); - PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RB))].OUTSET.reg = (PANEL_ROW_VAR & 1) << bit_from_pin(arduino_pin_to_avr_pin(RB)); - PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RB))].OUTCLR.reg = (invertedRow & 1) << bit_from_pin(arduino_pin_to_avr_pin(RB)); + PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RB))].OUTSET.reg = ((PANEL_ROW_VAR >> 1) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RB)); + PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RB))].OUTCLR.reg = ((invertedRow >> 1) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RB)); #if PANEL_Y > 8 - PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RC))].OUTSET.reg = (PANEL_ROW_VAR & 1) << bit_from_pin(arduino_pin_to_avr_pin(RC)); - PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RC))].OUTCLR.reg = (invertedRow & 1) << bit_from_pin(arduino_pin_to_avr_pin(RC)); + PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RC))].OUTSET.reg = ((PANEL_ROW_VAR >> 2) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RC)); + PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RC))].OUTCLR.reg = ((invertedRow >> 2) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RC)); #endif #if PANEL_Y > 16 - PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RD))].OUTSET.reg = (PANEL_ROW_VAR & 1) << bit_from_pin(arduino_pin_to_avr_pin(RD)); - PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RD))].OUTCLR.reg = (invertedRow & 1) << bit_from_pin(arduino_pin_to_avr_pin(RD)); + PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RD))].OUTSET.reg = ((PANEL_ROW_VAR >> 3) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RD)); + PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RD))].OUTCLR.reg = ((invertedRow >> 3) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RD)); #endif #if PANEL_Y > 32 - PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RE))].OUTSET.reg = (PANEL_ROW_VAR & 1) << bit_from_pin(arduino_pin_to_avr_pin(RE)); - PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RE))].OUTCLR.reg = (invertedRow & 1) << bit_from_pin(arduino_pin_to_avr_pin(RE)); + PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RE))].OUTSET.reg = ((PANEL_ROW_VAR >> 4) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RE)); + PORT->Group[port_from_pin(arduino_pin_to_avr_pin(RE))].OUTCLR.reg = ((invertedRow >> 4) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RE)); #endif #endif PANEL_ADVANCE_ROW; diff --git a/src/boards/uno_r4/uno_r4.h b/src/boards/uno_r4/uno_r4.h new file mode 100644 index 0000000..78fae27 --- /dev/null +++ b/src/boards/uno_r4/uno_r4.h @@ -0,0 +1,76 @@ +#ifndef HUB75NANO_UNO_R4_H +#define HUB75NANO_UNO_R4_H + +#include +#include "uno_r4_pin_helpers.h" + +// actual pin numbers like in the arduino digitalwrite, can be changed here or in your project +#ifndef RA +#define RA 11 // row selector a +#endif +#ifndef RB +#define RB 12 // row selector b +#endif +#ifndef RC +#define RC 10 // row selector c +#endif +#ifndef RD +#define RD 13 // row selector d +#endif +// currently unused +#ifndef RE +// port3, but rightbit position (304!) +#define RE 8 // row selector e +#endif +#ifndef RF +#define RF A5 // red first byte +#endif +#ifndef GF +#define GF A4 // green first byte +#endif +#ifndef BF +#define BF 5 // blue first byte +#endif +#ifndef RS +#define RS 4 // red second byte +#endif +#ifndef GS +#define GS 3 // green second byte +#endif +#ifndef BS +#define BS 2 // blue second byte +#endif +#ifndef CLK +#define CLK A1 // clock signal +#endif +#ifndef LAT +#define LAT A2 // data latch +#endif +#ifndef OE +#define OE A3 // output enable +#endif + +// helper definitions for setting/clearing +#define high_pin(pin) ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(pin))].PCNTR3.POSR = 1 << bit_from_pin(arduino_pin_to_avr_pin(pin)) +#define clear_pin(pin) ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(pin))].PCNTR3.PORR = 1 << bit_from_pin(arduino_pin_to_avr_pin(pin)) + +// Set pin to output mode +#define set_pin_output(pin) pinMode(pin, OUTPUT); + +#define HIGH_CLK high_pin(CLK) +#define CLEAR_CLK clear_pin(CLK) +#define HIGH_LAT high_pin(LAT) +#define CLEAR_LAT clear_pin(LAT) +#define HIGH_OE high_pin(OE) +#define CLEAR_OE clear_pin(OE) +#define Clock \ + HIGH_CLK; \ + CLEAR_CLK +#define LATCH \ + HIGH_LAT; \ + CLEAR_LAT + +// todo, no idea how +#define OVERFLOW 0 + +#endif // HUB75NANO_UNO_R4_H \ No newline at end of file diff --git a/src/boards/uno_r4/uno_r4_methods.h b/src/boards/uno_r4/uno_r4_methods.h new file mode 100644 index 0000000..9a877b8 --- /dev/null +++ b/src/boards/uno_r4/uno_r4_methods.h @@ -0,0 +1,109 @@ +#ifndef HUB75NANO_UNO_R4_METHODS_H +#define HUB75NANO_UNO_R4_METHODS_H + +#include "uno_r4.h" +#include "uno_r4_pin_helpers.h" +#include "../method_helper.h" +#include "../../Settings.h" + +// bulk pin access color, only good if pins are in right order +#ifdef PANEL_MAX_SPEED +__attribute__((always_inline)) +#endif +inline void +_set_color(uint8_t value) +{ +#if RF == A5 and GF == A4 and BF == 5 and RS == 4 and GS == 3 and BS == 2 + // set 6 color pins and keep the rx tx pins as are + // we need to shift two as the reads are optimized for nano and expect the 0 and 1 to be rx/tx + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RF))].PCNTR3.POSR = value >> 2; + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RF))].PCNTR3.PORR = (~(value >> 2)) & 63; +#else + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RF))].PCNTR3.POSR = (value & 1) << bit_from_pin(arduino_pin_to_avr_pin(RF)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RF))].PCNTR3.PORR = ((~value) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RF)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(GF))].PCNTR3.POSR = ((value >> 1) & 1) << bit_from_pin(arduino_pin_to_avr_pin(GF)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(GF))].PCNTR3.PORR = ((~(value >> 1)) & 1) << bit_from_pin(arduino_pin_to_avr_pin(GF)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(BF))].PCNTR3.POSR = ((value >> 2) & 1) << bit_from_pin(arduino_pin_to_avr_pin(BF)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(BF))].PCNTR3.PORR = ((~(value >> 2)) & 1) << bit_from_pin(arduino_pin_to_avr_pin(BF)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RS))].PCNTR3.POSR = ((value >> 3) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RS)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RS))].PCNTR3.PORR = ((~(value >> 3)) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RS)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(GS))].PCNTR3.POSR = ((value >> 4) & 1) << bit_from_pin(arduino_pin_to_avr_pin(GS)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(GS))].PCNTR3.PORR = ((~(value >> 4)) & 1) << bit_from_pin(arduino_pin_to_avr_pin(GS)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(BS))].PCNTR3.POSR = ((value >> 5) & 1) << bit_from_pin(arduino_pin_to_avr_pin(BS)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(BS))].PCNTR3.PORR = ((~(value >> 5)) & 1) << bit_from_pin(arduino_pin_to_avr_pin(BS)); +#endif +} + +#ifndef PANEL_ROW_VAR +uint8_t _row = 0; +#define PANEL_ROW_VAR _row +#endif + +// we can only set the _row fast when the pins are in order +#ifdef PANEL_MAX_SPEED +__attribute__((always_inline)) +#endif +inline void +_stepRow() +{ +// row pin check +#if PANEL_Y > 32 +#if RA == 11 and RB == 12 and RC == 10 and RD == 13 and RE == 8 + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.POSR = (PANEL_ROW_VAR & 15) << bit_from_pin(arduino_pin_to_avr_pin(RA)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.PORR = ((~PANEL_ROW_VAR) & 15) << bit_from_pin(arduino_pin_to_avr_pin(RA)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RE))].PCNTR3.POSR = ((PANEL_ROW_VAR >> 4) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RE)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RE))].PCNTR3.PORR = (((~PANEL_ROW_VAR) >> 4) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RE)); +#else +#define PANEL_ROW_PINS_OOO +#endif +#else +#if PANEL_Y > 16 +#if RA == 11 and RB == 12 and RC == 10 and RD == 13 + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.POSR = PANEL_ROW_VAR << bit_from_pin(arduino_pin_to_avr_pin(RA)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.PORR = ((~PANEL_ROW_VAR) & 15) << bit_from_pin(arduino_pin_to_avr_pin(RA)); +#else +#define PANEL_ROW_PINS_OOO +#endif +#else +#if PANEL_Y > 8 +#if RA == 11 and RB == 12 and RC == 10 + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.POSR = PANEL_ROW_VAR << bit_from_pin(arduino_pin_to_avr_pin(RA)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.PORR = ((~PANEL_ROW_VAR) & 7) << bit_from_pin(arduino_pin_to_avr_pin(RA)); +#else +#define PANEL_ROW_PINS_OOO +#endif +#else +#if PANEL_Y > 4 +#if RA == 11 and RB == 12 + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.POSR = PANEL_ROW_VAR << bit_from_pin(arduino_pin_to_avr_pin(RA)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.PORR = ((~PANEL_ROW_VAR) & 3) << bit_from_pin(arduino_pin_to_avr_pin(RA)); +#else +#define PANEL_ROW_PINS_OOO +#endif +#endif +#endif +#endif +#endif +#ifdef PANEL_ROW_PINS_OOO + uint8_t invertedRow = (~PANEL_ROW_VAR) & ((PANEL_Y / 2) - 1); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.POSR = (PANEL_ROW_VAR & 1) << bit_from_pin(arduino_pin_to_avr_pin(RA)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RA))].PCNTR3.PORR = (invertedRow & 1) << bit_from_pin(arduino_pin_to_avr_pin(RA)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RB))].PCNTR3.POSR = ((PANEL_ROW_VAR >> 1) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RB)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RB))].PCNTR3.PORR = ((invertedRow >> 1) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RB)); +#if PANEL_Y > 8 + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RC))].PCNTR3.POSR = ((PANEL_ROW_VAR >> 2) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RC)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RC))].PCNTR3.PORR = ((invertedRow >> 2) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RC)); +#endif +#if PANEL_Y > 16 + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RD))].PCNTR3.POSR = ((PANEL_ROW_VAR >> 3) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RD)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RD))].PCNTR3.PORR = ((invertedRow >> 3) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RD)); +#endif +#if PANEL_Y > 32 + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RE))].PCNTR3.POSR = ((PANEL_ROW_VAR >> 4) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RE)); + ((PORTS *)IO_PORT_START)->port[port_from_pin(arduino_pin_to_avr_pin(RE))].PCNTR3.PORR = ((invertedRow >> 4) & 1) << bit_from_pin(arduino_pin_to_avr_pin(RE)); +#endif +#endif + PANEL_ADVANCE_ROW; +} + +#endif // HUB75NANO_UNO_R4_METHODS_H diff --git a/src/boards/uno_r4/uno_r4_pin_helpers.h b/src/boards/uno_r4/uno_r4_pin_helpers.h new file mode 100644 index 0000000..426fae9 --- /dev/null +++ b/src/boards/uno_r4/uno_r4_pin_helpers.h @@ -0,0 +1,224 @@ +#ifndef HUB75NANO_UNO_R4_PIN_HELPER_H +#define HUB75NANO_UNO_R4_PIN_HELPER_H + +#define P000 0 +#define P001 1 +#define P002 2 +#define P003 3 +#define P004 4 +#define P005 5 +#define P006 6 +#define P007 7 +#define P008 8 +#define P010 10 +#define P011 11 +#define P012 12 +#define P013 13 +#define P014 14 +#define P015 15 + +#define P100 100 +#define P101 101 +#define P102 102 +#define P103 103 +#define P104 104 +#define P105 105 +#define P106 106 +#define P107 107 +#define P108 108 +#define P109 109 +#define P110 110 +#define P111 111 +#define P112 112 +#define P113 113 +#define P114 114 +#define P115 115 + +#define P201 201 +#define P202 202 +#define P203 203 +#define P204 204 +#define P205 205 +#define P206 206 +#define P212 212 +#define P213 213 + +#define P300 300 +#define P301 301 +#define P302 302 +#define P303 303 +#define P304 304 +#define P305 305 +#define P306 306 +#define P307 307 + +#define P400 400 +#define P401 401 +#define P402 402 +#define P403 403 +#define P404 404 +#define P405 405 +#define P406 406 +#define P407 407 +#define P408 408 +#define P409 409 +#define P410 410 +#define P411 411 +#define P412 412 +#define P413 413 +#define P414 414 +#define P415 415 + +#define P500 500 +#define P501 501 +#define P502 502 +#define P503 503 +#define P504 504 +#define P505 505 + +#define P600 600 +#define P601 601 +#define P602 602 +#define P603 603 +#define P608 608 +#define P609 609 +#define P610 610 + +#define P708 708 + +#define P808 808 +#define P809 809 + +#define P914 914 +#define P915 915 + +#define NOT_A_PORT 255 +#define NOT_A_PIN 255 + +// todo fix +#define IO_PORT_START 0x40040000 + +#define PORT0_OFFSET 0 +#define PORT1_OFFSET 1 +#define PORT2_OFFSET 2 +#define PORT3_OFFSET 3 +#define PORT4_OFFSET 4 +#define PORT5_OFFSET 5 +#define PORT6_OFFSET 6 +#define PORT7_OFFSET 7 +#define PORT8_OFFSET 8 +#define PORT9_OFFSET 9 + +constexpr uint8_t +port_from_pin(uint16_t pin) +{ + return (uint8_t)(pin < 100 ? PORT0_OFFSET + : pin < 200 ? PORT1_OFFSET + : pin < 300 ? PORT2_OFFSET + : pin < 400 ? PORT3_OFFSET + : pin < 500 ? PORT4_OFFSET + : pin < 600 ? PORT5_OFFSET + : pin < 700 ? PORT6_OFFSET + : pin < 800 ? PORT7_OFFSET + : pin < 900 ? PORT8_OFFSET + : pin < 1000 ? PORT9_OFFSET + : NOT_A_PORT); +} + +constexpr uint8_t bit_from_pin(uint8_t pin) +{ + return (uint8_t)(pin < 100 ? pin + : pin < 200 ? pin - 100 + : pin < 300 ? pin - 200 + : pin < 400 ? pin - 300 + : pin < 500 ? pin - 400 + : pin < 600 ? pin - 500 + : pin < 700 ? pin - 600 + : pin < 800 ? pin - 700 + : pin < 900 ? pin - 800 + : pin < 1000 ? pin - 900 + : NOT_A_PORT); +} + +constexpr uint8_t arduino_pin_to_avr_pin(uint8_t pin) +{ + return (uint8_t)(pin == 0 ? P301 + : pin == 1 ? P302 + : pin == 2 ? P105 + : pin == 3 ? P104 + : pin == 4 ? P103 + : pin == 5 ? P102 + : pin == 6 ? P106 + : pin == 7 ? P107 + : pin == 8 ? P304 + : pin == 9 ? P303 + : pin == 10 ? P112 + : pin == 11 ? P109 + : pin == 12 ? P110 + : pin == 13 ? P111 + : pin == 14 ? P014 + : pin == 15 ? P000 + : pin == 16 ? P001 + : pin == 17 ? P002 + : pin == 18 ? P101 + : pin == 19 ? P100 + : NOT_A_PIN); +} + +#pragma pack(push, 1) +typedef struct IOPORT +{ + union PCNTR1 + { + struct + { + // 1 is output high + uint16_t PDR; + // data direction, 1 is output + uint16_t PODR; + }; + uint32_t reg; + } PCNTR1; + union PCNTR2 + { + struct + { + // pin state + uint16_t PIDR; + // event input data, 1 is high + uint16_t EIDR; + }; + uint32_t reg; + } PCNTR2; + union PCNTR3 + { + struct + { + // pin output set, 1 is high + uint16_t POSR; + // pin output clear, 1 is low + uint16_t PORR; + }; + uint32_t reg; + } PCNTR3; + union PCNTR4 + { + struct + { + // pin event ouput set + uint16_t EOSR; + // pin event output clear + uint16_t EORR; + }; + uint32_t reg; + } PCNTR4; + uint8_t padding[16]; +} IOPORT; + +typedef struct PORTS +{ + IOPORT port[10]; +} PORTS; +#pragma pack(pop) + +#endif // HUB75NANO_UNO_R4_PIN_HELPER_H \ No newline at end of file