Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 72 additions & 84 deletions AriesRGB_32x16.cpp
Original file line number Diff line number Diff line change
@@ -1,57 +1,62 @@

#include "AriesRGB_32x16.h"

// DIRECT HARDWARE MEMORY MAP (Derived from VEGA gpio.c)
#define VEGA_GPIO_0_BASE 0x10080000UL
#define VEGA_GPIO_1_BASE 0x10180000UL

volatile unsigned short* fastPort[32];
unsigned short fastMask[32];

inline void fastDigitalWrite(uint8_t pin, bool val)
{
if (val) *(fastPort[pin]) = fastMask[pin];
else *(fastPort[pin]) = 0;

// Crucial RISC-V instruction to force the memory out to the physical pins
__asm__ __volatile__ ("fence");
}

AriesRGB_32x16::AriesRGB_32x16(
uint8_t r1, uint8_t g1, uint8_t b1,
uint8_t r2, uint8_t g2, uint8_t b2,
uint8_t clk, uint8_t lat, uint8_t oe,
uint8_t a, uint8_t b, uint8_t c,
uint8_t pw,
uint8_t ph)
uint8_t pw, uint8_t ph)
{
panelsWide = constrain(pw, 1, MAX_PANELS_X);
panelsHigh = constrain(ph, 1, MAX_PANELS_Y);

totalWidth = panelsWide * PANEL_WIDTH;
totalHeight = panelsHigh * PANEL_HEIGHT;

PIN_R1 = r1;
PIN_G1 = g1;
PIN_B1 = b1;

PIN_R2 = r2;
PIN_G2 = g2;
PIN_B2 = b2;

PIN_CLK = clk;
PIN_LAT = lat;
PIN_OE = oe;

PIN_A = a;
PIN_B = b;
PIN_C = c;
PIN_R1 = r1; PIN_G1 = g1; PIN_B1 = b1;
PIN_R2 = r2; PIN_G2 = g2; PIN_B2 = b2;
PIN_CLK = clk; PIN_LAT = lat; PIN_OE = oe;
PIN_A = a; PIN_B = b; PIN_C = c;

scanRow = 0;

clear();
}

void AriesRGB_32x16::begin()
{
pinMode(PIN_R1, OUTPUT);
pinMode(PIN_G1, OUTPUT);
pinMode(PIN_B1, OUTPUT);

pinMode(PIN_R2, OUTPUT);
pinMode(PIN_G2, OUTPUT);
pinMode(PIN_B2, OUTPUT);

pinMode(PIN_CLK, OUTPUT);
pinMode(PIN_LAT, OUTPUT);
pinMode(PIN_OE, OUTPUT);
pinMode(PIN_R1, OUTPUT); pinMode(PIN_G1, OUTPUT); pinMode(PIN_B1, OUTPUT);
pinMode(PIN_R2, OUTPUT); pinMode(PIN_G2, OUTPUT); pinMode(PIN_B2, OUTPUT);
pinMode(PIN_CLK, OUTPUT); pinMode(PIN_LAT, OUTPUT); pinMode(PIN_OE, OUTPUT);
pinMode(PIN_A, OUTPUT); pinMode(PIN_B, OUTPUT); pinMode(PIN_C, OUTPUT);

pinMode(PIN_A, OUTPUT);
pinMode(PIN_B, OUTPUT);
pinMode(PIN_C, OUTPUT);
for(int p = 0; p < 32; p++)
{
if (p <= 15) {
uint32_t bit_pos = (1 << p);
fastPort[p] = (volatile unsigned short*)(VEGA_GPIO_0_BASE + (bit_pos << 2));
fastMask[p] = bit_pos;
} else {
uint32_t bit_pos = (1 << (p - 16));
fastPort[p] = (volatile unsigned short*)(VEGA_GPIO_1_BASE + (bit_pos << 2));
fastMask[p] = bit_pos;
}
}

clear();
}
Expand All @@ -61,12 +66,7 @@ void AriesRGB_32x16::clear()
memset(framebuffer, 0, sizeof(framebuffer));
}

void AriesRGB_32x16::drawPixel(
int x,
int y,
bool r,
bool g,
bool b)
void AriesRGB_32x16::drawPixel(int x, int y, bool r, bool g, bool b)
{
if(x < 0 || x >= totalWidth) return;
if(y < 0 || y >= totalHeight) return;
Expand All @@ -78,67 +78,55 @@ void AriesRGB_32x16::drawPixel(

void AriesRGB_32x16::refresh()
{
digitalWrite(PIN_OE, HIGH);
fastDigitalWrite(PIN_OE, HIGH);

// Set ABC scan address
digitalWrite(PIN_A, (scanRow >> 0) & 1);
digitalWrite(PIN_B, (scanRow >> 1) & 1);
digitalWrite(PIN_C, (scanRow >> 2) & 1);
fastDigitalWrite(PIN_A, (scanRow >> 0) & 1);
fastDigitalWrite(PIN_B, (scanRow >> 1) & 1);
fastDigitalWrite(PIN_C, (scanRow >> 2) & 1);

// Vertical stacked panels
for(int py = 0; py < panelsHigh; py++)
for(int pCol = panelsWide - 1; pCol >= 0; pCol--)
{
int panelBaseY = py * PANEL_HEIGHT;
int panelBaseX = pCol * PANEL_WIDTH;

for(int pRow = panelsHigh - 1; pRow >= 0; pRow--)
{
int panelBaseY = pRow * PANEL_HEIGHT;

// 1/8 scan rows
int y1 = panelBaseY + scanRow;
int y2 = panelBaseY + scanRow + 8;
int y1 = panelBaseY + scanRow;
int y2 = panelBaseY + scanRow + 8;

// Horizontal panels
for(int px = 0; px < panelsWide; px++)
{
int panelBaseX = px * PANEL_WIDTH;
bool* row1_ptr = &framebuffer[y1][panelBaseX][0];
bool* row2_ptr = &framebuffer[y2][panelBaseX][0];

for(int col = 0; col < PANEL_WIDTH; col++)
{
int x = panelBaseX + col;

digitalWrite(PIN_R1, framebuffer[y1][x][0]);
digitalWrite(PIN_G1, framebuffer[y1][x][1]);
digitalWrite(PIN_B1, framebuffer[y1][x][2]);
fastDigitalWrite(PIN_R1, *(row1_ptr++));
fastDigitalWrite(PIN_G1, *(row1_ptr++));
fastDigitalWrite(PIN_B1, *(row1_ptr++));

digitalWrite(PIN_R2, framebuffer[y2][x][0]);
digitalWrite(PIN_G2, framebuffer[y2][x][1]);
digitalWrite(PIN_B2, framebuffer[y2][x][2]);
fastDigitalWrite(PIN_R2, *(row2_ptr++));
fastDigitalWrite(PIN_G2, *(row2_ptr++));
fastDigitalWrite(PIN_B2, *(row2_ptr++));

digitalWrite(PIN_CLK, HIGH);
digitalWrite(PIN_CLK, LOW);
fastDigitalWrite(PIN_CLK, HIGH);
fastDigitalWrite(PIN_CLK, LOW);
}
}
}

// Latch
digitalWrite(PIN_LAT, HIGH);
digitalWrite(PIN_LAT, LOW);
fastDigitalWrite(PIN_LAT, HIGH);
fastDigitalWrite(PIN_LAT, LOW);

// Enable output
digitalWrite(PIN_OE, LOW);
delayMicroseconds(50);
digitalWrite(PIN_OE, HIGH);
fastDigitalWrite(PIN_OE, LOW);

// If the screen is dim, increase this to 500 or 800
delayMicroseconds(300);

fastDigitalWrite(PIN_OE, HIGH);

// Next scan row
scanRow++;

if(scanRow >= 8)
scanRow = 0;
}

uint16_t AriesRGB_32x16::width()
{
return totalWidth;
if(scanRow >= 8) scanRow = 0;
}

uint16_t AriesRGB_32x16::height()
{
return totalHeight;
}
uint16_t AriesRGB_32x16::width() { return totalWidth; }
uint16_t AriesRGB_32x16::height() { return totalHeight; }
100 changes: 64 additions & 36 deletions AriesRGB_Font5x7_Vert.cpp
Original file line number Diff line number Diff line change
@@ -1,45 +1,73 @@
#include <Arduino.h>

// Vertical-panel text rendering for AriesRGB_32x16.
//
// PHYSICAL MOUNTING
// ─────────────────
// Rotate the 32×16 panel 90° COUNTER-CLOCKWISE so that:
// • The long (32-pixel) edge becomes the vertical axis → logical HEIGHT = 32
// • The short (16-pixel) edge becomes the horizontal axis → logical WIDTH = 16
// • The DATA connector (normally at the bottom) now faces to the RIGHT.
//
// Coordinate transform used internally (logical → physical):
// phys_x = logical_y
// phys_y = (PANEL_HEIGHT - 1) - logical_x = 15 - logical_x
//
// LOGICAL SPACE for a single 32×16 panel mounted vertically:
// x : 0 … 15 (left → right as you look at it)
// y : 0 … 31 (top → bottom)
//
// For multi-panel arrays (panelsWide > 1 etc.) scale accordingly.
// ─────────────────────────────────────────────────────────────────────────────

#define ARIES_VERT_LOG_WIDTH 16
#define ARIES_VERT_LOG_HEIGHT 32

class AriesRGB_32x16;
#include "AriesRGB_Font5x7_Vert.h"
#include "AriesRGB_32x16.h"
#include "AriesRGB_Font5x7.h"
#include <avr/pgmspace.h>

void AriesDrawPixelVert(
AriesRGB_32x16& display,
int lx, int ly,
bool r, bool g, bool b
);
bool r, bool g, bool b)
{
int logWidth = (display.width() / 32) * 16;
int logHeight = (display.height() / 16) * 32;

while(lx < 0) lx += logWidth;
lx = lx % logWidth;

if (ly < 0 || ly >= logHeight) return;

int maxCol = (logWidth / 16) - 1;
int panelCol = maxCol - (lx / 16);

int panelRow = ly / 32;

int localX = lx % 16;
int localY = ly % 32;

int px = (panelCol * 32) + (31 - localY);
int py = (panelRow * 16) + (15 - localX);

display.drawPixel(px, py, r, g, b);
}

#define FONT_HEADER_SIZE 6

void AriesDrawCharVert(
AriesRGB_32x16& display,
int x, int y,
char c,
bool r, bool g, bool b
);
int x, int y, char c,
bool r, bool g, bool b)
{
if (c < ARIES_FONT_FIRST || c >= (ARIES_FONT_FIRST + 96)) return;

uint16_t charIndex = (uint16_t)(c - ARIES_FONT_FIRST);
uint16_t glyphIndex = FONT_HEADER_SIZE + (charIndex * ARIES_FONT_WIDTH);

for(uint8_t col = 0; col < ARIES_FONT_WIDTH; col++)
{
uint8_t line = pgm_read_byte(&System5x7[glyphIndex + col]);
for(uint8_t row = 0; row < ARIES_FONT_HEIGHT; row++)
{
if(line & (1 << row))
{
// UN-MIRROR X, KEEP Y UPRIGHT
int drawX = x + col;
int drawY = y + (ARIES_FONT_HEIGHT - 1 - row);

AriesDrawPixelVert(display, drawX, drawY, r, g, b);
}
}
}
}

void AriesDrawStringVert(
AriesRGB_32x16& display,
int x, int y,
const char* str,
bool r, bool g, bool b
);
int x, int y, const char* str,
bool r, bool g, bool b)
{
while(*str)
{
AriesDrawCharVert(display, x, y, *str, r, g, b);
x += (ARIES_FONT_WIDTH + 1);
str++;
}
}
Loading