Skip to content

Commit

Permalink
added arduino uni r4 minima
Browse files Browse the repository at this point in the history
  • Loading branch information
CamelCaseName committed Dec 1, 2023
1 parent 69b2ebb commit 881111e
Show file tree
Hide file tree
Showing 8 changed files with 438 additions and 20 deletions.
19 changes: 10 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
name=HUB75nano
version=2.3.0
version=2.3.1
author=Leonhard Seidel
maintainer=Leonhard Seidel <leonhardseidel@gmx.de>
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/
Expand Down
4 changes: 4 additions & 0 deletions src/boards/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -33,6 +36,7 @@
#endif
#endif
#endif
#endif

#ifndef PANEL_X
#error "Panel size needs to be defined"
Expand Down
4 changes: 4 additions & 0 deletions src/boards/board_methods.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -46,5 +49,6 @@
#endif
#endif
#endif
#endif

#endif // HUB75NANO_BOARD_METHODS
18 changes: 9 additions & 9 deletions src/boards/iot/iot_methods.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
76 changes: 76 additions & 0 deletions src/boards/uno_r4/uno_r4.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#ifndef HUB75NANO_UNO_R4_H
#define HUB75NANO_UNO_R4_H

#include <Arduino.h>
#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
109 changes: 109 additions & 0 deletions src/boards/uno_r4/uno_r4_methods.h
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 881111e

Please sign in to comment.