# (Solved)Again problem with matrix, this time 8x32

Discussion in 'Arduino' started by fezder, Jan 4, 2016.

1. ### Dr_DoggyWell-Known Member

Joined:
Aug 11, 2007
Messages:
1,718
Likes:
37
yes, the mirror is example of another potential rotation axis , this structure will work for basic 90/180/270 degree rotations, more may be required depending on the level of complexity you want, how you want to issue rotation instruction, and how often you want to rotate.... by putting it here in charput, we are rotating per character...

Code (text):

void charput(int  ch, int x, int y, int z, int simple_axis)  //relies on pixel!
{
int x1, y1;
int disp;
int disp2;
for ( x1 = 0; x1 < 8; x1++) // eight rows
{
disp = cubefont[x1 + (ch * 8)]; //look data from fontmap,
for (y1 = 0; y1 < 8; y1++) // eight pixels
{
disp2 = disp & 1 << y1;
if (disp2 > 0)
{

if (simple_axis==1){   pixel(z, x + x1, y + y1, 0); // OR the pixel to the display buffer}
else if (simple_axis==2){   pixel(y + y1, z, x + x1, 0); // OR the pixel to the display buffer}
else if (simple_axis==3){   pixel(x + x1, y + y1, z, 0); // OR the pixel to the display buffer}

else if (simple_axis==4){   pixel(x + x1, y + y1, (7-z), 0); // OR the pixel to the display buffer}

}
}
}
}

2. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
Doggy, thanks for those. They're bit off however, took photos how they look (generally, it draws characters correctly, but see for yourself very close!:
first, code if you don't mind, I tidied it so starts from 0 : also, I dunno if if....if.....if array is better or worse than if....else if....
Code (c):

void charput(int ch, int x, int y, int z, int simple_axis)  //relies on pixel!
{
int x1, y1;
int disp;
int disp2;
for ( x1 = 0; x1 < 8; x1++) // eight rows
{
disp = cubefont[x1 + (ch * 8)]; //look data from fontmap,
for (y1 = 0; y1 < 8; y1++) // eight pixels
{
disp2 = disp & 1 << y1;
if (disp2 > 0)
{
if (simple_axis == 0) //bottom, normal, so ok!
{
pixel(x + x1, y + y1, z, 0); // OR the pixel to the display buffer}
}

if (simple_axis == 1) // left wall, but inverted vertically
{
pixel(z, x + x1, y + y1, 0); // OR the pixel to the display buffer}
}

if (simple_axis == 2) //face wall, opposite of cable-in
{
pixel(y + y1, z, x + x1, 0); // OR the pixel to the display buffer}
}
if (simple_axis == 3)  //top wall, ceiling, ok. So as numver #0 but counts from up->down
{
pixel(x + x1, y + y1, (7 - z), 0); // OR the pixel to the display buffer}
}
}
}
}
}

Now then, results (number in picture represents if() situation in pixel() for clarity!. In each picture, cable input is upwards^)
0, pulled it to z=7 to take better picture:

1, left wall, vertically mirrored

2, face, but in z=0, draws in back, not big deal! Only character is 90' CCW, if looked from front face.

and 3, draws as 0, but counts from top->bottom

finally, 0-2pulled to frontal faces

These prove handy still!

3. ### Dr_DoggyWell-Known Member

Joined:
Aug 11, 2007
Messages:
1,718
Likes:
37
iififif will check each one, else if wont check the others after one "if" is true, so else if is a bit faster, for this example switch(select)case would be good too since it only checks once, i just posted example few, by using the pixel function as such we can set up all the walls, and call rotation as we want, also that backwards 2 is not backwards, its just on the wrong wall... we can also adjust this by changing the z value to something like (7 - z)

or the upside down 1 can be corrected like this: (7 - y + y1) , and if it backwards to 7 - x + x1 , its difficult to see exactly whats going on, so feel free to setup the if s how you want, this method can be used to flip along the surfaces how ever you choose, but its looking good!

Joined:
Jan 12, 1997
Messages:
-
Likes:
0

5. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland

Lol, again, I tested and 7-(x+x1) were one of those I didn't test.....I even tested it in z-axis and I was pleased to see that character was drawn inside cube I like this cube more and more! And, I didn't know that speed improvement between if/else and if/if. Any bit of improvement is always welcome! The more time micro has to do something, they all add up. And I've learnt SO much to squeeze power out of this chip, still using arduino btw

6. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
Here we go, pretty much all covered with this, only needs bit of optimization perhaps since I used ton of if/if/if structures....I'll take video later!
Code (c):

void charput(byte ch, signed char x, signed char y, signed char z, byte plane, byte rotation)  //relies on pixel!
{
signed char x1, y1;
byte disp;
byte disp2;
for ( x1 = 0; x1 < 8; x1++) // eight rows
{
disp = cubefont[x1 + (ch * 8)]; //look data from fontmap,
for (y1 = 0; y1 < 8; y1++) // eight pixels
{
disp2 = disp & 1 << y1;
if (disp2 > 0)
{
if (plane == 0) //layer walls
{
if (rotation == 0)
{
pixel(x + x1, y + y1, 7 - z, 0); //0 degrees, readable from front
}
if (rotation == 1)
{
pixel((y + y1), 7 - (x + x1), 7 - z, 0); //90 degrees CCW, readable from right
}
if (rotation == 2)
{
pixel(7 - (x + x1), 7 - (y + y1), 7 - z, 0); //180 degrees CCW, readable from back
}
if (rotation == 3)
{
pixel(7 - (y + y1), (x + x1), 7 - z, 0); //90 degrees CW, readable from left
}
}

if (plane == 1) //face wall
{
if (rotation == 0)
{
pixel((x + x1), 7 - z, 7 - (y + y1), 0); //0 degrees, readable from front
}
if (rotation == 1 )
{
pixel(y + y1, 7 - z, x + x1, 0); //90 degrees CCW, readable from front, flipped to left
}
if (rotation == 2)
{
pixel(7 - (x + x1), 7 - z, y + y1, 0); //180 degrees CCW,readable from front
}
if (rotation == 3)
{
pixel(7 - (y + y1), 7 - z, 7 - (x + x1), 0); //90 degrees CW, readable from front, flipped to right
}
}

if (plane == 2) //back wall
{
if (rotation == 0)
{
pixel(7 - (x + x1), z, 7 - (y + y1), 0); //0 degrees, readable rom back
}
if (rotation == 1)
{
pixel(7 - (y + y1), z, x + x1, 0); //90 degrees cCW, readable from back, flipped to left
}
if (rotation == 2)
{
pixel((x + x1), z, (y + y1), 0); //180 degrees CCW, readable rom back
}
if (rotation == 3)
{
pixel((y + y1), z, 7 - (x + x1), 0); //90 degrees cCW, readable from back, flipped to right
}
}

if (plane == 3) // left wall
{
if (rotation == 0)
{
pixel(z, x + x1, 7 - (y + y1), 0); //0 degrees, readable from left wall
}
if (rotation == 1)
{
pixel(z, y + y1, x + x1, 0);//90 degrees CCW, readable from left wall, flipped to left
}
if (rotation == 2)
{
pixel(z, 7 - (x + x1), y + y1, 0); //180 degrees CCW, readable from left wall
}
if (rotation == 3)
{
pixel(z, 7 - (y + y1), 7 - (x + x1), 0); //90 degrees CW, readable from left wall, flipped to right
}
}

if (plane == 4)  //right wall
{
if (rotation == 0)
{
pixel(7 - z, 7 - (x + x1), 7 - (y + y1), 0); //0 degrees, readable from right-wall
}
if (rotation == 1)
{
pixel(7 - z, 7 - (y + y1), (x + x1), 0); //90 degrees CW, readable from right wall, flipped to left
}
if (rotation == 2)
{
pixel(7 - z, x + x1, y + y1, 0); //  180 degrees CCW, readable right-wall
}
if (rotation == 3)
{
pixel(7 - z, (y + y1), 7 - (x + x1), 0); //90 degrees CW, readable from right wall, flipped to right
}
}
}
}
}
}

7. ### Dr_DoggyWell-Known Member

Joined:
Aug 11, 2007
Messages:
1,718
Likes:
37
Another thing i learned the hard way was about what a stack overflow is(besides the website), and every time you go if(){if(){if(){}}} or while or anything, you use a "layer of stack", the pic uC I had was very small and only supported 10 layers, not sure about arduino...
Speed improvement a good coder will always say is #1, i say its more important on the "lower levels" of the code since those are the ones that get called the most,.
I always start my code like that if,if,if but one thing i have noticed is that when done patterns emerge across the differences. sometimes you can size it down with an equation or less if's just by grouping properly, or maybe some of those rotations will never be called so they can be cut out too, If you are good with the math I would recommend reading about Bedmas, Boolean Algebra, and K-maps.

for example, Im not too sure yet that we can compress the "plane" variable too much, but we can compress rotation buy doing something like this:

Code (text):

if (disp2 <= 0)  { return;}  // saves one stack

if (rotation ==0){x =7-x;}
if (rotation ==2){y =7-y;}
if (rotation ==3){z =7-z;}

if (plane == 0) //layer walls
{
pixel(x + x1, y + y1,  z, 0); //0 degrees, readable from front
}

if (plane == 1) //face wall
{
pixel((x + x1), 7 - z,  (y + y1), 0); //0 degrees, readable from front
}

if (plane == 2) //back wall
{
pixel( (x + x1), z,  (y + y1), 0); //0 degrees, readable rom back
}

if (plane == 3) // left wall
{
pixel(z, x + x1,  (y + y1), 0); //0 degrees, readable from left wall
}

if (plane == 4)
{
pixel( z,  (x + x1),  (y + y1), 0);
}

This is only example though, since it is all subjective to how you want it, ie,
1)do you want rotation=0 to always mean that the letter is straight and right side up at front and back of cube when you are looking from front?
2) or does rotation = 0 mean that the letter is straight and right side up, only if you are looking at the surface closest to you?
3) or does rotation = 0 mean there is no rotation, 1 = upside down, 3=flipped

again all subjective , are you just rotating to correct the alignment , or will you use it down the road and if so how do you want it to work?

Last edited: Aug 15, 2016
8. ### djsfantasiMember

Joined:
Mar 15, 2011
Messages:
161
Likes:
21
Location:
Metro Boston
Umm, (7-x+x1) is not the same
as 7-(x+x1)...

• Agree x 2
9. ### Dr_DoggyWell-Known Member

Joined:
Aug 11, 2007
Messages:
1,718
Likes:
37
ah good eye!, this is also wrong then too, it should be:
if (rotation ==0){x =7-x;}
if (rotation ==2){y =7-y;}
if (rotation ==3){z =7-z;}

10. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
Doggy, again I could use help. I'm trying to show Serial data, as text, but problem Is I can't neither use String, as text() function excpects chars, so I can't null-terminate char array either since that makes char array to string, correct?
I've managed to make this far, but now trouble is, I can't empty char array. Any clues?
Code (c):

//this sketch allows to scroll text and data on 8x8 matrises. When changing matrix size, change matrises value and OCR1A in setup. However, OCR1A is initially se-up for bigger displays, and it works in smaller too so no need change unless screen doesn't update fast enought; increase value then.
/*
to display text = text("text here",x-pos,y-pos, rot(optional));
to display values in numbers= value(value, x-pos,y-pos, rot(optional));
to display pixels=pixel(x-pos,y-pos,mode);  (useful for drawing lines and graphs, use for() loop to create lines better

BIG thanks for dr.doggy from ETO (electro tech online)

signed char/char= 1 byte(8 bits), -127->127
unsigned char/byte= 1 byte(8 bits), 0->255
int= 2 byte(16 bits), -32768->32767
unsigned int= 2 byte(16 bits), 0-> 65535
long = 4 byte(32 bits), -2,147,483,648->2,147,483,647
unsigned long= 4 byte (32 bits), 4,294,967,295

*/

#include "FontMap.h"  //font is in external file
#define matrises 4  //define number of matrises, 4-22
#define columns matrises*8  //calculate columns based how many matrises are in use
byte displayPointer = 0;  //for interrupt use...
byte buffer1[columns];  // buffer for screen,4x8=32
const byte power[8] = {128, 64, 32, 16, 8, 4, 2, 1}; //for each column B10000000->B00000001
char data[20];
byte index = 0;
char c;
byte Length = 0;

void draw()
{
setcolumn(displayPointer);  //column scanning
setdata(buffer1[displayPointer]);  //bit banging shift registers
bitSet(PORTD, 3); //blit latch, high->low
bitClear(PORTD, 3);
if (++displayPointer == columns)  //32 LED row sections in total
{ displayPointer = 0;
}
}

void setcolumn(byte col)  //loop that takes care of column scanning
{
int pos;
for (pos = columns; pos > -1; pos--)
{
if (col == pos)
{
bitSet(PORTD, 2);  //data high
}
else
{
bitClear(PORTD, 2); //data low
}
bitSet(PORTD, 4);  //blit clock high->low
bitClear(PORTD, 4);
}
}

void setdata(byte dat)
{
byte pos;
for (pos = 0; pos < 8; pos++)
{
if (dat & 128)
{
dat -= 128;
bitSet(PORTD, 2);  //data high
}
else
{
bitClear(PORTD, 2); //data low
}
dat = dat << 1;  //dat <<1==dat *2;
bitSet(PORTD, 4);  //blit clock
bitClear(PORTD, 4);

}
}

void clr()  //clear display buffer
{
}

void pixel(signed char x, signed char y, byte cond)
{
byte pix, msk;
if (x < 0 || y < 0)
{
return; // outside drawing limits negative
}
if (x > (columns - 1) || y > 7)
{
return; // outside drawing limits positive, x=32, y=8
}
pix = power[y];
msk = buffer1[x]; // get exsisting data

if (cond == 2)
pix ^= msk; //XOR data to screen
if (cond == 1)
{
pix = ~pix;
pix &= msk; // AND data to screen
}
if (cond == 0)
pix |= msk; // OR data to screen
buffer1[x] = pix; // apply changes
}

void value(char ch, signed char x, signed char y, byte rotation)
{
byte x1, y1;
byte disp, disp2;
for ( x1 = 0; x1 < 8; x1++) // eight rows
{
disp = font[x1 + (ch << 3)]; //look data from fontmap, (ch<<3)==(ch *8)
for (y1 = 0; y1 < 8; y1++) // eight pixels
{
disp2 = disp & power[y1];
if (disp2 > 0)
{
if (rotation == 0)
{
pixel(x + x1, y + y1, 0); //0 degrees
}
if (rotation == 1)
{
pixel(7 - (y + y1), (x + x1), 0); //90 degrees, flip to left
}
if (rotation == 2)
{
pixel(7 - (x + x1), 7 - (y + y1), 0);
}
if (rotation == 3)
{
pixel(y + y1, 7 - (x + x1), 0); //90 degrees, flip to right
}
}
}
}
}

void text(char* ch, signed char x, signed char y, byte rotation)  //strput relies on charput
{
while (*ch )
{
value(*ch++, x, y, rotation); //write a string to the display buffer
x += 7;
}
}

void setup() //setup runs once
{
DDRD = DDRD | B11111100; //port registers used to set pin directions
Serial.begin(9600);
}

void loop() //just sitting here
{

do
{
if (Serial.available() > 0)
{

if (c != '\n' && c != '\r')
{
data[index++] = c;
}
}
}
while (c != '\n');
index = 0;
clr();
text(data, 0, 0, 0);
draw();
}

11. ### Dr_DoggyWell-Known Member

Joined:
Aug 11, 2007
Messages:
1,718
Likes:
37
\r\n = char 13 & char 10 ,, from the ascii table.

have you included <strings.h> ?

I recently just did code similar , will post when i get home

12. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
13. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
Thanks doggy, I stumbled upon this handy command:
Code (c):

String.toCharArray(array, size);

And that allowed using strings and converting them to char array! Thanks!

14. ### Dr_DoggyWell-Known Member

Joined:
Aug 11, 2007
Messages:
1,718
Likes:
37
this was some code i just wrote few weeks ago to read data from an internal array block called sensorbuffer, lol but i forget exactly how its encoded, as you can see it will eventually be able to write to the sensorbuffer array too, but not there yet!
From what i can tell, it looks for the command string , checks for get instruction, checks for the element number wanted, then returns said block... still need a few lines for the set instruction to work, i think its something like this:
#AQUA GET 3 \r\n

this line is looking for the command string and the "Line Feed" terminator "\n", in string form it looks like "\n" but really its only 1 byte long, so only 1 char, and as you can see from ascii table it is char 10:
if (readString1.startsWith(command_string) & c == 10)
.... when you hit the enter on your keyboard you are sending \r\n which is "Carriage Return" & "Line Feed"
(sorry if i was confusing, \n is how PC uses operators and terminaors inside strings, idk, dont think it works for arduino strings)

Code (text):

void loop(){serialListener();doStuff();}

void serialListener(void)
{
String dir, command_string = "#AQUA";
while (Serial.available())
{
if (readString1.startsWith(command_string) & c == 10)
{
for (int i = 0; i < readString1.length(); i++) {
if (readString1.substring(i, i + 1) == " ") {
break;
}
}

// for debugging
Serial.print((String)dir + "," + headPos + "\r\n");
Serial.print("\r\n");
// for debugging

if (dir == "get" || dir == "GET") { Serial.print((String)SensorBuffer[headPos] + "\r\n"); }
// not coded yet!!
// if (dir == "set" || dir == "SET") { Serial.print((String)SensorBuffer[headPos] + "\r\n"); }
}
delay(10);
}
}

15. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
I managed to ditch Strings and use array of chars now, this allows to change text AND rotation form serial. Only need to make code that allows text, rotation, and plane for 8-cube...
Code (c):

//this sketch allows to scroll text and data on 8x8 matrises. When changing matrix size, change matrises value and OCR1A in setup. However, OCR1A is initially se-up for bigger displays, and it works in smaller too so no need change unless screen doesn't update fast enought; increase value then.
/*
SERIAL INPUT!
to display text = text("text here",x-pos,y-pos, rot(optional));
to display values in numbers= value(value, x-pos,y-pos, rot(optional));
to display pixels=pixel(x-pos,y-pos,mode);   (useful for drawing lines and graphs, use for() loop to create lines better

BIG thanks for dr.doggy from ETO (electro tech online)

signed char/char= 1 byte(8 bits), -127->127
unsigned char/byte= 1 byte(8 bits), 0->255
int= 2 byte(16 bits), -32768->32767
unsigned int= 2 byte(16 bits), 0-> 65535
long = 4 byte(32 bits), -2,147,483,648->2,147,483,647
unsigned long= 4 byte (32 bits), 4,294,967,295
*/

#include "FontMap.h"  //font is in external file
#define matrises 4          //define number of matrises, 4-22
#define columns matrises*8  //calculate columns based how many matrises are in use
byte displayPointer = 0;                       //for interrupt use...
byte buffer1[columns];                              // buffer for screen,4x8=32
const byte power[8] = {128, 64, 32, 16, 8, 4, 2, 1}; //for each column B10000000->B00000001

char string[40]; //array to store incoming data
char c;
byte index;
byte textlength; //for dynaminc scroll length
char * vout; //used with strtok()
byte Rotation; //optional rotation command, not needed for normal scrolling

void draw()
{
setcolumn(displayPointer);            //column scanning
setdata(buffer1[displayPointer]);    //bit banging shift registers
bitSet(PORTD, 3); //blit latch, high->low
bitClear(PORTD, 3);
if (++displayPointer == columns)          //32 LED row sections in total
{ displayPointer = 0;
}
}

void setcolumn(byte col)         //loop that takes care of column scanning
{
int pos;
for (pos = columns; pos > -1; pos--)
{
if (col == pos)
{
bitSet(PORTD, 2);  //data high
}
else
{
bitClear(PORTD, 2); //data low
}
bitSet(PORTD, 4);      //blit clock high->low
bitClear(PORTD, 4);
}
}

void setdata(byte dat)
{
byte pos;
for (pos = 0; pos < 8; pos++)
{
if (dat & 128)
{
dat -= 128;
bitSet(PORTD, 2);  //data high
}
else
{
bitClear(PORTD, 2); //data low
}
dat = dat << 1;  //dat <<1==dat *2;
bitSet(PORTD, 4);     //blit clock
bitClear(PORTD, 4);

}
}

void clr()                          //clear display buffer
{
}

void pixel(signed char x, signed char y, byte cond)
{
byte pix, msk;
if (x < 0 || y < 0)
{
return; // outside drawing limits negative
}
if (x > (columns - 1) || y > 7)
{
return; // outside drawing limits positive, x=32, y=8
}
pix = power[y];
msk = buffer1[x]; // get exsisting data

if (cond == 2)
pix ^= msk; //XOR data to screen
if (cond == 1)
{
pix = ~pix;
pix &= msk; // AND data to screen
}
if (cond == 0)
pix |= msk; // OR data to screen
buffer1[x] = pix; // apply changes
}

void value(char ch, signed char x, signed char y, byte rotation)
{
byte x1, y1;
byte disp, disp2;
for ( x1 = 0; x1 < 8; x1++) // eight rows
{
disp = font[x1 + (ch << 3)]; //look data from fontmap, (ch<<3)==(ch *8)
for (y1 = 0; y1 < 8; y1++) // eight pixels
{
disp2 = disp & power[y1];
if (disp2 > 0)
{
if (rotation == 0)
{
pixel(x + x1, y + y1, 0); //0 degrees
}
if (rotation == 1)
{
pixel(7 - (y + y1), (x + x1), 0); //90 degrees, flip to left
}
if (rotation == 2)
{
pixel(7 - (x + x1), 7 - (y + y1), 0);
}
if (rotation == 3)
{
pixel(y + y1, 7 - (x + x1), 0); //90 degrees, flip to right
}
}
}
}
}

void text(char* ch, signed char x, signed char y, byte rotation)  //strput relies on charput
{
while (*ch )
{
value(*ch++, x, y, rotation); //write a string to the display buffer
x += 7;
}
}

void setup() //setup runs once
{
DDRD = DDRD | B11111100; //port registers used to set pin directions
Serial.begin(115200);
}

void loop() //just sitting here
{

if (Serial.available() > 0)
{

if ((c != '\r') && (c != '\n')) //Keep these out of our buffer
{
}

else
{
textlength = index * 8 + 32;  // *8, since matrises are 8-wide, and 32 to scroll whole screen.
string[index++] = '\0';//Converts the array into a string
index = 0; //next time we start from beginning index
vout = strtok(string, ",");   //array is ready, time to parse

while (vout != NULL)
{
Rotation = atoi(vout);
vout = strtok(NULL, " .");
}
}
}
clr();
text(string, 31 - millis() / 100 % textlength, 0, Rotation);
draw();
}

16. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
wee, got it too working! I didn't know that strtok() destroys string while reading, will post even further improved code soonish!

17. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
Code (c):

//this sketch allows to scroll text and data on 8x8 matrises. When changing matrix size, change matrises value and OCR1A in setup. However, OCR1A is initially se-up for bigger displays, and it works in smaller too so no need change unless screen doesn't update fast enought; increase value then.
/*
SERIAL INPUT!
to display text = text("text here",x-pos,y-pos, rot(optional));
to display values in numbers= value(value, x-pos,y-pos, rot(optional));
to display pixels=pixel(x-pos,y-pos,mode);   (useful for drawing lines and graphs, use for() loop to create lines better

BIG thanks for dr.doggy from ETO (electro tech online)

signed char/char= 1 byte(8 bits), -127->127
unsigned char/byte= 1 byte(8 bits), 0->255
int= 2 byte(16 bits), -32768->32767
unsigned int= 2 byte(16 bits), 0-> 65535
long = 4 byte(32 bits), -2,147,483,648->2,147,483,647
unsigned long= 4 byte (32 bits), 4,294,967,295
*/

#include "FontMap.h"  //font is in external file
#define matrises 4          //define number of matrises, 4-22
#define columns matrises*8  //calculate columns based how many matrises are in use
byte displayPointer = 0;                       //for interrupt use...
byte buffer1[columns];                              // buffer for screen,4x8=32
const byte power[8] = {128, 64, 32, 16, 8, 4, 2, 1}; //for each column B10000000->B00000001

char string[40]; //array to store incoming data
char textFromPc[40]; //array to store actual text to show on matrix

char c;
byte index;
byte textlength; //for dynaminc scroll length
char * strtokIndx; // this is used by strtok() as an index

byte Yoffset = 0;
byte Rotation = 0;

void draw() //draw loop,DON'T TOUCH!
{
setcolumn(displayPointer);            //column scanning
setdata(buffer1[displayPointer]);    //bit banging shift registers
bitSet(PORTD, 3); //blit latch, high->low
bitClear(PORTD, 3);
if (++displayPointer == columns)          //32 LED row sections in total
{ displayPointer = 0;
}
}

void setcolumn(byte col)         //loop that takes care of column scanning DON'T TOUCH!
{
int pos;
for (pos = columns; pos > -1; pos--)
{
if (col == pos)
{
bitSet(PORTD, 2);  //data high
}
else
{
bitClear(PORTD, 2); //data low
}
bitSet(PORTD, 4);      //blit clock high->low
bitClear(PORTD, 4);
}
}

void setdata(byte dat)
{
byte pos;
for (pos = 0; pos < 8; pos++)
{
if (dat & 128)
{
dat -= 128;
bitSet(PORTD, 2);  //data high
}
else
{
bitClear(PORTD, 2); //data low
}
dat = dat << 1;  //dat <<1==dat *2;
bitSet(PORTD, 4);     //blit clock
bitClear(PORTD, 4);

}
}

void clr()                          //clear display buffer
{
}

void pixel(signed char x, signed char y, byte cond)
{
byte pix, msk;
if (x < 0 || y < 0)
{
return; // outside drawing limits negative
}
if (x > (columns - 1) || y > 7)
{
return; // outside drawing limits positive, x=32, y=8
}
pix = power[y];
msk = buffer1[x]; // get exsisting data

if (cond == 2)
pix ^= msk; //XOR data to screen
if (cond == 1)
{
pix = ~pix;
pix &= msk; // AND data to screen
}
if (cond == 0)
pix |= msk; // OR data to screen
buffer1[x] = pix; // apply changes
}

void value(char ch, signed char x, signed char y, byte rotation)
{
byte x1, y1;
byte disp, disp2;
for ( x1 = 0; x1 < 8; x1++) // eight rows
{
disp = font[x1 + (ch << 3)]; //look data from fontmap, (ch<<3)==(ch *8)
for (y1 = 0; y1 < 8; y1++) // eight pixels
{
disp2 = disp & power[y1];
if (disp2 > 0)
{
if (rotation == 0)
{
pixel(x + x1, y + y1, 0); //0 degrees
}
if (rotation == 1)
{
pixel(7 - (y + y1), (x + x1), 0); //90 degrees, flip to left
}
if (rotation == 2)
{
pixel(7 - (x + x1), 7 - (y + y1), 0);
}
if (rotation == 3)
{
pixel(y + y1, 7 - (x + x1), 0); //90 degrees, flip to right
}
}
}
}
}

void text(char* ch, signed char x, signed char y, byte rotation)  //strput relies on charput
{
while (*ch )
{
value(*ch++, x, y, rotation); //write a string to the display buffer
x += 7;
}
}

void setup() //setup runs once
{
DDRD = DDRD | B11111100; //port registers used to set pin directions
Serial.begin(115200);
}

void loop() //just sitting here
{

if (Serial.available() > 0)
{

if ((c != '\r') && (c != '\n')) //Keep these out of our buffer
{
}

else
{
textlength = index * 8 + 32;  // *8, since matrises are 8-wide, and 32 to scroll whole screen.
string[index++] = '\0';//Converts the array into a string
index = 0; //next time we start from beginning index
parseData(); //time to parse data received
//showParsedData(); //for debugging!

}
}
clr();
text(textFromPc, 31 - millis() / 100 % textlength, Yoffset, Rotation);
draw();
}

void parseData()  //function for splitting the array
{

strtokIndx = strtok(string, ",");     // get the first part - the TEXT PART
strcpy(textFromPc, strtokIndx); // copy it to messageFromPC

strtokIndx = strtok(NULL, ",");
Yoffset = atoi(strtokIndx);

strtokIndx = strtok(NULL, ",");
Rotation = atoi(strtokIndx);

}

/*
void showParsedData()
{
Serial.print("text ");
Serial.println(textFromPc);
Serial.print("plane ");
Serial.println(Yoffset);
Serial.print("rotation ");
Serial.println(Rotation);
}
*/

18. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
Again I must keep this thread alive, since I ran to problem when I try to feed data from ESP8266 via server....I really have no idea, why. I just copy my topic from arduino forum...I posted this alsoi in ESP-forums but no help yet. Moderator still has my post lol...
Arduino part of code processes serial data, works in wired serial as well as bluetooth. But, now when I try to add ESP-01 to control from browser, something odd is happening.

But, when I try to use ESP-01, text only "blinks" very quickly when shot from browser, and MDNS-part of code is shown on screen once, before sending any data. It looks like extra line feed is fed.
But, according to serial monitor, no extra LN is received on arduino part.
I have feeling esp-part of code is culprit, since bluetooth serial and wired serial works fine
First, ESP:code (program using arduino IDE)
http://embedded-lab.com/blog/wifi-enabled-scrolling-led-matrix-display/
I hope I didn't forgot any relevant information.
Code (c):

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>

MDNSResponder mdns;

// Replace with your network credentials
const char* ssid = "KONIG_WS01";

ESP8266WebServer server(80);

String webPage = "";

void setup(void) {

webPage += "<h1>ESP8266 Web Server</h1>";
webPage +=   "<form action='msg'><p>Type your message <input type='text' name='msg' size=100 autofocus> <input type='submit' value='Submit'></form>";

delay(1000);
Serial.begin(115200);
Serial.println("");

// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.println(WiFi.localIP());

if (mdns.begin("esp8266", WiFi.localIP())) {
Serial.println("MDNS responder started");
}

server.on("/", []() {
server.send(200, "text/html", webPage);
});

server.on("/msg", []() {
server.send(200, "text/html", webPage);
String msg = server.arg("msg");
Serial.println(msg);    delay(1000);
});

server.begin();
Serial.println("HTTP server started");
}

void loop(void) {
server.handleClient();
}

And then the pro-mini part
Code (c):

//this sketch allows to scroll text and data on 8x8 matrises. When changing matrix size, change matrises value and OCR1A in setup. However, OCR1A is initially se-up for bigger displays, and it works in smaller too so no need change unless screen doesn't update fast enought; increase value then.
/*
SERIAL INPUT!
to display text = text("text here",x-pos,y-pos, rot(optional));
to display values in numbers= value(value, x-pos,y-pos, rot(optional));
to display pixels=pixel(x-pos,y-pos,mode);   (useful for drawing lines and graphs, use for() loop to create lines better

BIG thanks for dr.doggy from ETO (electro tech online)

signed char/char= 1 byte(8 bits), -127->127
unsigned char/byte= 1 byte(8 bits), 0->255
int= 2 byte(16 bits), -32768->32767
unsigned int= 2 byte(16 bits), 0-> 65535
long = 4 byte(32 bits), -2,147,483,648->2,147,483,647
unsigned long= 4 byte (32 bits), 4,294,967,295
*/

#include "FontMap.h"  //font is in external file
#define matrises 4          //define number of matrises, 4-22
#define columns matrises*8  //calculate columns based how many matrises are in use
byte displayPointer = 0;                       //for interrupt use...
byte buffer1[columns];                              // buffer for screen,4x8=32
const byte power[8] = {128, 64, 32, 16, 8, 4, 2, 1}; //for each column B10000000->B00000001

char string[40]; //array to store incoming data
char textFromPc[40]; //array to store actual text to show on matrix

char c;
byte index;
byte textlength; //for dynaminc scroll length
char * strtokIndx; // this is used by strtok() as an index

byte Yoffset = 0;
byte Rotation = 0;

void draw() //draw loop,DON'T TOUCH!
{
setcolumn(displayPointer);            //column scanning
setdata(buffer1[displayPointer]);    //bit banging shift registers
bitSet(PORTD, 3); //blit latch, high->low
bitClear(PORTD, 3);
if (++displayPointer == columns)          //32 LED row sections in total
{ displayPointer = 0;
}
}

void setcolumn(byte col)         //loop that takes care of column scanning DON'T TOUCH!
{
int pos;
for (pos = columns; pos > -1; pos--)
{
if (col == pos)
{
bitSet(PORTD, 2);  //data high
}
else
{
bitClear(PORTD, 2); //data low
}
bitSet(PORTD, 4);      //blit clock high->low
bitClear(PORTD, 4);
}
}

void setdata(byte dat)
{
byte pos;
for (pos = 0; pos < 8; pos++)
{
if (dat & 128)
{
dat -= 128;
bitSet(PORTD, 2);  //data high
}
else
{
bitClear(PORTD, 2); //data low
}
dat = dat << 1;  //dat <<1==dat *2;
bitSet(PORTD, 4);     //blit clock
bitClear(PORTD, 4);

}
}

void clr()                          //clear display buffer
{
}

void pixel(signed char x, signed char y, byte cond)
{
byte pix, msk;
if (x < 0 || y < 0)
{
return; // outside drawing limits negative
}
if (x > (columns - 1) || y > 7)
{
return; // outside drawing limits positive, x=32, y=8
}
pix = power[y];
msk = buffer1[x]; // get exsisting data

if (cond == 2)
pix ^= msk; //XOR data to screen
if (cond == 1)
{
pix = ~pix;
pix &= msk; // AND data to screen
}
if (cond == 0)
pix |= msk; // OR data to screen
buffer1[x] = pix; // apply changes
}

void value(char ch, signed char x, signed char y, byte rotation)
{
byte x1, y1;
byte disp, disp2;
for ( x1 = 0; x1 < 8; x1++) // eight rows
{
disp = font[x1 + (ch << 3)]; //look data from fontmap, (ch<<3)==(ch *8)
for (y1 = 0; y1 < 8; y1++) // eight pixels
{
disp2 = disp & power[y1];
if (disp2 > 0)
{
if (rotation == 0)
{
pixel(x + x1, y + y1, 0); //0 degrees
}
if (rotation == 1)
{
pixel(7 - (y + y1), (x + x1), 0); //90 degrees, flip to left
}
if (rotation == 2)
{
pixel(7 - (x + x1), 7 - (y + y1), 0);
}
if (rotation == 3)
{
pixel(y + y1, 7 - (x + x1), 0); //90 degrees, flip to right
}
}
}
}
}

void text(char* ch, signed char x, signed char y, byte rotation)  //strput relies on charput
{
while (*ch )
{
value(*ch++, x, y, rotation); //write a string to the display buffer
x += 7;
}
}

void setup() //setup runs once
{
DDRD = DDRD | B11111100; //port registers used to set pin directions
Serial.begin(115200);
}

void loop() //just sitting here
{

if (Serial.available() > 0)
{

if ((c != '\r') && (c != '\n')) //Keep these out of our buffer
{
}

else
{
textlength = index * 8 + 32;  // *8, since matrises are 8-wide, and 32 to scroll whole screen.
string[index++] = '\0';//Converts the array into a string
index = 0; //next time we start from beginning index
parseData(); //time to parse data received
//showParsedData(); //for debugging!

}
}
clr();
text(textFromPc, 31 - millis() / 100 % textlength, Yoffset, Rotation);
draw();
}

void parseData()  //function for splitting the array
{

strtokIndx = strtok(string, ",");     // get the first part - the TEXT PART
strcpy(textFromPc, strtokIndx); // copy it to messageFromPC

strtokIndx = strtok(NULL, ",");
Yoffset = atoi(strtokIndx);

strtokIndx = strtok(NULL, ",");
Rotation = atoi(strtokIndx);

}

/*
void showParsedData()
{
Serial.print("text ");
Serial.println(textFromPc);
Serial.print("plane ");
Serial.println(Yoffset);
Serial.print("rotation ");
Serial.println(Rotation);
}
*/

19. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
Aha! Seems I have bug In my code, since I debugged bit with serial monitor.
This is code I used to debug, arriving data, what is going to buffer, and what is in buffer:
Code (c):

char string[40]; //array to store incoming data
char textFromPc[40]; //array to store actual text to show on matrix

char c;
byte index;
byte textlength; //for dynaminc scroll length

void setup() //setup runs once
{
Serial.begin(9600);
}

void loop() //just sitting here
{

if (Serial.available() > 0)
{
Serial.print("before buffer:  ");
Serial.println(c, DEC);

if ((c != '\r') && (c != '\n')) //Keep these out of our buffer
{
//Serial.print("going to buffer:  ");
//Serial.println(c, DEC);
}
else
{
textlength = index * 8 + 32;  // *8, since matrises are 8-wide, and 32 to scroll whole screen.
string[index++] = '\0';//Converts the array into a string
//Serial.print("at buffer, received in ASCII:  ");
//Serial.println(string);
index = 0; //next time we start from beginning index
}
}
}

Normal, written straight from monitor,when pressed enter:
Code (c):

before buffer:  10 //line feed!
at buffer, received in ASCII:    //nothing, since, LN is ignored

and, with esp:
Code (c):

before buffer: 13    //hmm, carrion return?
before buffer :10

and same test, with character "h":
normal:
Code (c):

before buffer:  104
going to buffer:  104
before buffer:  10
at buffer, received in ASCII:  h

esp:
Code (c):

before buffer: 104
going to buffer:104
before buffer: 13
at buffer , received in ASCII: h
before buffer: 10

WHILE writing this, I found bug in my arduino part, so this fixed: (LN wasn't terminator in my code!)
Code (c):

if(c=='\n')
{
textlength = index * 8 + 32;  // *8, since matrises are 8-wide, and 32 to scroll whole screen.
string[index++] = '\0';//Converts the array into a string
//Serial.print("at buffer, received in ASCII:  ");
//Serial.println(string);
index = 0; //next time we start from beginning index

parseData(); //time to parse data received
//showParsedData(); //for debugging!

}

Last edited: Dec 7, 2016
20. ### fezderWell-Known Member

Joined:
Dec 11, 2011
Messages:
1,665
Likes:
100
Location:
Mikkeli, Finland
Here, wrapped matrix to handy library!
Had to use slow digitalWrite since I don't knot how to allocate pins for portmanipulation on the fly.
Also, array is not set dynamically etiher, but It works on some degree!

Also attatched version for 7-segment

#### Attached Files:

File size:
5.1 KB
Views:
49
• ###### _74595_sevenSegment.zip
File size:
4.5 KB
Views:
47
Last edited: Dec 18, 2016
• Like x 1