Text to RGB LED Strip - 32 LED/m Addressable 10312

Hello this is my first post so I hope I’ve come to the right place.

I have purchased 8 Addressable RGB LED Strips from Sparkfun and they are a blast! I have connected them in a chain from 0-255 and wrapped them around to make a matrix. I only use 2 pins to send the data and every second strip has a 5V 3A supply and a common ground connected to the Arduino.

0, 1, 2, —>— 29, 30, 31 STRIP #1

63, 62, 61, —<— 34, 33, 32 STRIP #2

64, 65, 66, —>— 93, 94, 95 STRIP #3

127,126,125,—<— 98, 97, 96 STRIP #4

… STRIP #5

… STRIP #6

… STRIP #7

… STRIP #8

… you get the point

I am able to control them without any issues and the brightness is impressive. The next idea I have is to use this 32x8 “matrix” and make a stock market like text ticker. I can write text now but it is a very tedious process. I turn on each LED individually then post the frame to get the text I want.

Does anyone know a simple way to convert text into a matrix so that I can display it on my strips?

Is there a library that could help me out?

Is there a SMART approach to this problem?

Anything that could point me in the right direction?

How are you storing the bitmaps for the character font? I assume you have some 3D array of either bits, greyscale or RGB data.

-----> X axis

|

|

v

y-axis

You could try something like this:

#include <avr\pgmspace.h>

struct RGB {

uint8_t r;

uint8_t g;

uint8_t b;

RGB() { };

RGB(uint8_t cr, uint8_t cg, uint8_t cb) { r = cr; g = cg; b = cb; };

};

// the capital letter N

#define SPRITE_N 0

#define SPRITE_WIDTH 5

#define SPRITE_HEIGHT 5

// 5x5 greyscale font

static const uint8_t sprites[25] PROGMEM = {

{ 0x00, 0x00, 0xFF, 0x00, 0x00,

0x00, 0xFF, 0x00, 0xFF, 0x00,

0xFF, 0xFF, 0xFF, 0xFF, 0x00,

0xFF, 0x00, 0x00, 0x00, 0xFF,

0xFF, 0x00, 0x00, 0x00, 0xFF

}

};

#define FRAME_WIDTH 32

#define FRAME_HEIGHT 8

void draw_sprite(void* frame_start, uint8_t x, uint8_t y, void* sprite, RGB color) {

register uint8_t *p;

register uint8_t *s;

for (uint8_t i = 0; i < SPRITE_HEIGHT; i++) {

if ((y + i) >= FRAME_HEIGHT) {

break;

}

if ((y+i) % 2 == 0) { // even rows are left to right

s = (uint8_t *)sprite + i * SPRITE_HEIGHT;

p = (uint8_t *)frame_start + ((y + i) * FRAME_WIDTH + x) * 3;

for (uint8_t j = 0; j < SPRITE_WIDTH; j++) {

if ((j + x) >= FRAME_WIDTH) {

break;

}

*p++ = (uint8_t)((*s * color.b) >> 8);

*p++ = (uint8_t)((*s * color.g) >> 8);

*p++ = (uint8_t)((*s++ * color.r) >> 8);

}

} else { // odd rows are right to left

s = (uint8_t *)sprite + i * SPRITE_HEIGHT;

p = (uint8_t *)frame_start + ((y + i + 1) * FRAME_WIDTH - x) * 3;

for (uint8_t j = 0; j < SPRITE_WIDTH; j++) {

if ((j + x) >= FRAME_WIDTH) {

break;

}

*–p = (uint8_t)((*s * color.b) >> 8);

*–p = (uint8_t)((*s * color.g) >> 8);

*–p = (uint8_t)((*s++ * color.r) >> 8);

}

}

}

};

/*

Based on code from http://code.google.com/p/fastspi/

*/

void frame_out(void *frame_start) {

register uint8_t *p = (uint8_t *)frame_start;

register const uint8_t *e = p + FRAME_WIDTH * FRAME_HEIGHT * 3;

SPDR = *p;

while (p < e) {

while (!(SPSR & _BV(SPIF)));

SPDR = *++p;

while (!(SPSR & _BV(SPIF)));

SPDR = *++p;

while (!(SPSR & _BV(SPIF)));

SPDR = *++p;

}

while (!(SPSR & _BV(SPIF)));

};

To “print” the letter N at (x, y) position (10, 2) in 1/2 brightness green color:

RGB frame_buffer[FRAME_HEIGHT][FRAME_WIDTH];

uint8_t sprite[25];

memcpy_P(sprite, &sprites[SPRITE_N][0], 25);

draw_sprite(&frame_buffer[0][0], 10, 2, sprite, RGB(0, 127, 0));

frame_out(&frame_buffer[0][0], FRAME_WIDTH * FRAME_HEIGHT * 3);

I haven’t debugged the draw_sprite code. It looks good on paper, but I could have an error in there.

I made some edits to fix the draw_sprite loop (I think I shouldn’t have written it just before bedtime)

Sorry for thread-jacking, but this is a similar issue I’m having.

void frame_row(void *frame_start, byte layer) 
{
register uint8_t *p = (uint8_t *)frame_start;
register const uint8_t *e = p + 128;

SPDR = *p & layer; //bitmask to only draw current layer
while (p < e) {
while (!(SPSR & _BV(SPIF)));  //pixel 1
SPDR = *++p & layer; while (!(SPSR & _BV(SPIF))); //pixel 2 
SPDR = *++p & layer; while (!(SPSR & _BV(SPIF))); //pixel 3
SPDR = *++p & layer; while (!(SPSR & _BV(SPIF))); //pixel 4
....
SPDR = *++p & layer; 
}
while (!(SPSR & _BV(SPIF))); //pixel 128
};

byte frame[32][128];

void loop()
{
for (byte n=1; n < number_of_shades; n++)
{
  for (byte i=0; i < 32; i++)
  {
      frame_row(&frame[i][0], n);
     //do row pulsing etc .. 
  }
}
};

Would this also be a speed increase over using direct port manipulation to toggle the pin on/off?

also -

It seems wasteful to send a full byte when only a bit is needed.

Would there be further speed increase if I preprocessed the frame and stored it in a new array, like so:

Pseudo:

byte someframe[32][16];
register uint8_t *p = (uint8_t *)someframe;

for all rows
for (all pixels in row, per 8 bit)
   if (pixel is lit in this layer) *p |= B00000001; else *p &=  ~B00000001;
   if (pixel is lit in this layer) *p |= B00000010; else *p &=  ~B00000010;
   ...
    if (pixel is lit in this layer) *p++ |= B10000000; else *p++ &= ~B10000000;

then simply:
frame_out(p);  <- should send 32*16 bytes instead of 32*128 bytes (of which 7/8 is wasted space)?

I figure I could use << to insert the last high/low value instead of bitmasking. But I’ll have to read up on bitmath first. :slight_smile:

Maybe something like this?

*p = ((*p << 1) | (pixelvalue | layer)?1:0);

Today I’m using direct port manipulation, but it doesn’t seem to fast (170 us per row), like so:

for all rows
   for all pixels in row
        if (pixel is lit in this layer) bitSet(PORTF, 0); else bitClear(PORTF,0); // pin "0" = data pin.
        //pulse column clock

Hello again!

I’ve continued my own discussion in a separate thread here → viewtopic.php?f=32&t=29442.