(solved)Again matrix problem, 8x32 , scrolling.....

Right, I decided to make bugger display now and mistakenly thought that wouldn't make code much harder; obviously I was wrong.
I managed to make scrolling text, varying speed with potentiometer, look specified portion of text (variable scroll you could say) and make 9999 seconds counter (I like my eggs bit harder....)
But, to make even 8x16 screen that scrolls smoothly, that seems hard, or then I'm just looking in wrong direction. Most schemes I looked either had separate drivers for columns/rows, or then that MAX's ic (Don't have single one of those.....).
But, my circuit has daisy-chained shift registers, I know they're not cause of trouble as I have same setup, only bigger in 8' cube, and it works well. Rows are controlled with one shift register, and columns with darlingtons paired with shift registers
Now, I'm asking again help here, what would be best approach with issue?
This code scrolls numbers from 0-9, but on all matrises same time (well, that's what is intented too in code) Please don't give code right away, I learned so much recently and 'I'd like to keep that way,
surely you'll understand. Interrupt or 2d-array needed? And ask if you need more info.

//scrolls text with variable speed, or with set speed
int dataPin = 2;        //IC 14       //Define which pins will be used for the Shift Register control
int latchPin = 3;       //IC 12
int clockPin = 4;       //IC 11
//OE-GND
//MR-VCC
int delaytime = 1, timer, timerPrev = 0;
int shift = 0;
int len = 80;
int m;
static uint8_t  x [80] =    //numbers stored here
{
  0x00, 0x7c, 0xa2, 0x92, 0x8a, 0x7c, 0x00, 0x00, // 0
  0x00, 0x42, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, // 1
  0x00, 0x42, 0x86, 0x8a, 0x92, 0x62, 0x00, 0x00, // 2
  0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 3
  0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 4
  0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 5
  0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 6
  0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 7
  0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 8
  0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 9
};


void setup()   //runs once
{
  DDRD = DDRD | B00011100;                                  //set pins as output
}

void loop()
{
  //int val = analogRead(A0);     //if set speed, comment this out perhaps some better way for this too, but i'll let this be commented for now, was just test
  timer = millis ();            //set timer from current millis value
  if (timer - timerPrev > 200)    //change val to set value for set speed
  {
    shift++;
    if (shift == len)shift = 0;
    timerPrev = timer;
  }
  for (int i = 0; i < 8; i++)
  {
    PORTD = B00000000;                                  //turn latch low
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);          //Send the data #2        (what columns to power)
                                          //if bigger > smaller    true               false, smaller way for if/else
    shiftOut(dataPin, clockPin, LSBFIRST, x[i + shift > len - 1 ? i + shift - len : i + shift]); //Send the data #1       ( what data to draw)
    /*
if (i+ shift > len -1)
{
m=i+shift-len;    //equilavent way for ?
}
else
{
m=i+shift;
}
*/
    PORTD = B00001000;                                  //turn latch on->show screen
  }

}

I'm curious!

Why is the array, named x[], declared global static?

Are you familiar with the % (modulo) operator and how it could be used to keep 'shift' within boundary?

Perhaps you could describe your project and hardware here so we don't have to hunt down whatever other thread your original was discussed in?

It'd make more sense of ...

shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);
shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);
shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);
shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);

... to me if I understood your hardware and project better/

declaring

static uint8_t x[] =

followed late by ...

const size_t len = COUNT_ENTRIES(x);

... with ...

#define COUNT_ENTRIES(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))

... would keep you from having to manually specify some values yourself as this way has the compiler do it based on the arrays actual size.

Glad you're having fun.

Sorry, forgot to name those things better like x; really doesn't mean anything, still I read from time to time variables and other names should be something else than x-something....
But,

lloyddean:
Why is the array, named x[], declared global static?

Are you familiar with the % (modulo) operator and how it could be used to keep 'shift' within boundary?

Perhaps you could describe your project and hardware here so we don't have to hunt down whatever other thread your original was discussed in?

It'd make more sense of ...

shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);

shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);
shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);
shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);




... to me if I understood your hardware and project better/

I opted that static would be fine for x-array since it's variables doesn't change, like book, I don't change what there reads, but I'll change that x for font in future to make more sense

shiftOut(dataPin, clockPin, MSBFIRST, 1 << i);

This was just so I could control single screens scanned at same time to see they work like intended so there are no lurking solder-bridges or such (at least few found)

About Modulo, I've tried to understand It's function but I tend to confuse it with percent-ratio. Probadly because it is percent-mark. I do have modulo in that 9999 counter thought, but that code I found online and only suited it for matrix so I didn't need to think of modulos function.

About project, hardware and such, here's circuit:
This issue I haven't discussed in this forum yet.

Thanks for putting some code together, I don't quite understand meaning for these as I only created array where to store font, or am I looking this wrong way?

Thanks for reply, sort of nervous of asking help, 'prolly because of nature
BTW, found typo on starting message; I meant bigger display, NOT bugger....

const size_t len = COUNT_ENTRIES(x);

#define COUNT_ENTRIES(ARRAY) (sizeof(ARRAY) / sizeof(ARRAY[0]))

Made few changes to code to make it better readable, no more random x's (seems static for x-array wasn't needed, uint8_t was enough:
Sadly I don't understand how % can be used to keep shift within bounds, I really don't understand it's operation when;

x = 4 % 5;   // x now contains 4

Still quite new for arduino

//scrolls text with variable speed, or with set speed
int dataPin = 2;        //IC 14       //Define which pins will be used for the Shift Register control
int latchPin = 3;       //IC 12
int clockPin = 4;       //IC 11
//OE-GND
//MR-VCC
int timer, timerPrev = 0;
int shift;  
int length = 80;  //length of shifts
uint8_t  text [] =    //numbers stored here
{
  0x00, 0x7c, 0xa2, 0x92, 0x8a, 0x7c, 0x00, 0x00, // 0
  0x00, 0x42, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, // 1
  0x00, 0x42, 0x86, 0x8a, 0x92, 0x62, 0x00, 0x00, // 2
  0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 3
  0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 4
  0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 5
  0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 6
  0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 7
  0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 8
  0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 9
};


void setup()   //runs once
{
  DDRD = DDRD | B00011100;                                  //set pins as output
}

void loop()
{
  timer = millis ();            //set timer from current millis value
  if (timer - timerPrev > 200)    //chech whether it is time
  {
    shift++;    //shift by one
    if (shift == length)shift = 0; //if it has shifted same amount as lenght, reset shift
    timerPrev = timer;    //set previous time from current timer (millis)
  }
  for (int columns = 0; columns < 8; columns++)   //scan columns
  {
    PORTD = B00000000;                                  //turn latch low
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << columns);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << columns);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << columns);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << columns);          //Send the data #2        (what columns to power)
                                          //show text determined whether shifts has happened enough many times
    shiftOut(dataPin, clockPin, LSBFIRST, text[columns + shift > length - 1 ? columns + shift - length : columns + shift]); //Send the data #1       ( what data to draw)
    PORTD = B00001000;                                  //turn latch on->show screen
  }

}

An example of 'i % 3' over the range of 0 ... 10

//    i:  result
      0:  0
      1:  1
      2:  2
      3:  0
      4:  1
      5:  2
      6:  0
      7:  1
      8:  2
      9:  0
     10:  1

The result will be in the range 0 to 2, 1 less than 3 for all positive values of i, even if i = 1000000UL.

As it relates to yoour code -

shift++;
if (shift == length)shift = 0;

... can be stated as ...

shift++;
shift %= len;

Ah, I see there you used compound, just yesterday noticed this when looking for codes and trying to understand what they were doing (some were PIC-codes, but codes still)
Thanks again!

Your timer variables should be unsigned longs. Other sizes will mess up the timing calculations after the code runs awhile.

Ah, because maxinum millis() is 4 294 967 296 and only unsigned long can hold such value? whereas int holds only 32,767, oops. I really gotta write the diiferent storage types up, this Isn't first time this happens.....
Thanks! Rookie mistake

fezder:
Ah, because maxinum millis() is 4 294 967 296 and only unsigned long can hold such value? whereas int holds only 32,767, oops. I really gotta write the diiferent storage types up, this Isn't first time this happens.....
Thanks! Rookie mistake

Nah. Your mistake was not reading the millis() reference page.

aarg:
Nah. Your mistake was not reading the millis() reference page.

Ahem, now that you mention it, it is clearly said there....
Oh, and i found this while browsing, to my eye it looks there might be some help here, I mean perhaps this could be used with column control:
http://forum.arduino.cc/index.php?topic=56660.0

    currentRow = (currentRow+1) % 8;

And there too was used shift registers
But, current code:

//scrolls text with variable speed, or with set speed
int dataPin = 2;        //IC 14       //Define which pins will be used for the Shift Register control
int latchPin = 3;       //IC 12
int clockPin = 4;       //IC 11
//OE-GND
//MR-VCC
unsigned long timer;                      //now time variables are better storage type....
unsigned long timerPrev = 0;
int shift;      //store number of shifts
int length = 80;  //lenght of maxinum text string
uint8_t  text [] =    //numbers stored here
{
  0x00, 0x7c, 0xa2, 0x92, 0x8a, 0x7c, 0x00, 0x00, // 0
  0x00, 0x42, 0xfe, 0x02, 0x00, 0x00, 0x00, 0x00, // 1
  0x00, 0x42, 0x86, 0x8a, 0x92, 0x62, 0x00, 0x00, // 2
  0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 3
  0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 4
  0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 5
  0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 6
  0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 7
  0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 8
  0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 9
};


void setup()   //runs once
{
  DDRD = DDRD | B00011100;                                  //set pins as output
}

void loop()
{
  timer = millis ();            //set timer from current millis value
  if (timer - timerPrev > 200)    //chech whether it is time
  {
   shift++;
shift %= length;    //keeps shift within bounds
    timerPrev = timer;    //set previous time from current timer (millis)
  }
  for (int columns = 0; columns < 8; columns++)   //scan columns
  {
    PORTD = B00000000;                                  //turn latch low
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << columns);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << columns);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << columns);          //Send the data #2        (what columns to power)
    shiftOut(dataPin, clockPin, MSBFIRST, 1 << columns);          //Send the data #2        (what columns to power)
                                          //show text determined whether shifts has happened enough many times
    shiftOut(dataPin, clockPin, LSBFIRST, text[columns + shift > length - 1 ? columns + shift - length : columns + shift]); //Send the data #1       ( what data to draw)
    PORTD = B00001000;                                  //turn latch on->show screen
  }

}

Is that 32 pixel in width by 8 pixels in height?

You've 4, 8 x 8 pixels images side by side, or one above the other?

What orientation does the display take when displaying the contents of 'text' during the first frame -

0123

or

3 2 1 0

or

0
1
2
3

They're side by side, like this:

RTC Isn't connected yet, it is idea to implement it to this afterwards, once control stuff is clear, how to control this screen (I of course try it first myself, if possible. I do have RTC hooked to LCD so not that big issue, automatic time was screwed and hda to set it manually on-time)

lloyd, I noticed you asked earlier (edited, couldn't reply then) whether this would be POV-style, I made POV-clock/display earlier, aarg and riva here in forums helped out with it (still under ''construction'', only enclosure needed and suitable application, perhaps vu-meter, not sure yet)

Soyour code variable columns refers to. The screen not the data in the text array correct?

Yeah, columns variable refers indeed columns in real life matrix, not array columns in code. True, it could mean array columns too, caused slight confusion I see, sorry about that!

Figured to share progress so far what we've done with friend of mine, started off PIC-code but didn't have better at hand, font is external file.

#include "FontMap.h"

int dataPin = 2; // ic: 14, ser_in Define which pins will be used for the Shift Register control
int latchPin = 3; // ic:12 silkscreen numbers!
int clockPin = 4;


unsigned char displayPointer=0; // for interrupt use...
unsigned char buffer1[32]; // buffer for screen
unsigned char backbuffer[32]; // Spare screen for drawing on
unsigned char power[8]={128,64,32,16,8,4,2,1};

ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
if(TIFR2) // Make sure its the timer interrupt.
{
setcolumn(displayPointer);
setdata(buffer1[displayPointer]);
digitalWrite(latchPin ,HIGH);digitalWrite(latchPin , LOW ); // STORECLOCK
if(++displayPointer==32) { displayPointer = 0; } // 32 LED row sections in total
}
TIFR2 = 0; // Clear timer 2 interrupt flag


}

void setcolumn(unsigned char col){
signed char pos;
for (pos = 32;pos>-1;pos--){
if (col == pos){digitalWrite(dataPin ,HIGH);}else {digitalWrite(dataPin ,LOW);} // PIN1 DATA pin
digitalWrite(clockPin ,HIGH);digitalWrite(clockPin ,LOW);
}}

void setdata(unsigned char dat){
unsigned char pos;
for (pos = 0;pos<8;pos++){
if (dat & 128){dat-=128;digitalWrite(dataPin ,HIGH);}else { digitalWrite(dataPin ,LOW);} // PIN1 DATA pin
dat = dat * 2;
digitalWrite(clockPin ,HIGH);digitalWrite(clockPin ,LOW);
}}
void clr() //clear
{
int addr;
for(addr=0;addr<32;addr++) // Empty display buffer
backbuffer[addr]= 0;
}

void Blit() //transfers data between display buffer to screen buffer
{
int addr=0;
noInterrupts(); // disable all interrupts during setup
for(addr=0;addr < 32;addr ++)
{
buffer1[addr] = backbuffer[addr]; // put all data from display buffer
} // to screen buffer
interrupts(); // enable all interrupts
}

void pixel(signed char x,signed char y,int cond)
{
unsigned char pix,msk;
if(x<0 || y<0) return; // outside drawing limits negative
if(x>31 || y>7) return; // outside drawing limits positive
pix = power[y];
msk = backbuffer[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
backbuffer[x] = pix; // apply changes
}

void charput(unsigned char ch, signed char x,signed char y)
{
signed char x1, y1;
unsigned char disp;
unsigned char disp2;
for( x1=0;x1<8;x1++) // eight rows
{
disp = font[x1+(ch * 8)];
for (y1 = 0; y1<8; y1++) // eight pixels
{
disp2 = disp & power[y1];
if(disp2 > 0)
{
pixel(x+x1,y+y1,0); // OR the pixel to the display buffer
}
}

}
}

void strput(const char* ch, signed char x,signed char y)
{
int addr;
while (*ch )
{
charput(*ch++,x,y); // write a string to the display buffer
x+=7;
}
}

void setup() //setup runs once
{
noInterrupts(); // disable all interrupts during setup
DDRD = DDRD | B11111100; //port registers used to set pin directions
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 5; // compare match register 16MHz/256/2Hz
TCCR1B |= (1 << WGM12); // CTC mode, free-running, clear on match
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts
} // End main

void loop() //just sitting here
{
clr();

pixel(0,0,0);
pixel(31,8,0);

charput( 0,1,0);

charput( 1,7,0);



Blit();
delay(500);
}

and font (external file, same folder as main sketch)

static unsigned char font [1000] =              //numbers stored here
{                                               //Position, Character
0x00, 0x00, 0x7E, 0x81, 0x81, 0x81, 0x7E, 0x00, // 0            0
0x00, 0x00, 0x80, 0x82, 0xFF, 0x80, 0x80, 0x00, // 1            1

0x00, 0x8E, 0x91, 0xA1, 0xC1, 0x82, 0x00, 0x00, // 2            2   
0x00, 0x80, 0x81, 0x91, 0x91, 0x91, 0x6E, 0x00, // 3            3
0x00, 0x08, 0x18, 0x28, 0x48, 0xFF, 0x08, 0x00, // 4            4 
0x00, 0x00, 0xF2, 0x89, 0x89, 0x89, 0x86, 0x00, // 5            5
0x00, 0x00, 0x76, 0x89, 0x89, 0x89, 0x86, 0x00, // 6            6
0x00, 0x00, 0x80, 0x03, 0x8C, 0xB0, 0xC0, 0x00, // 7            7
0x00, 0x00, 0x6E, 0x91, 0x91, 0x91, 0x6E, 0x00, // 8            8   
0x00, 0x00, 0x70, 0x89, 0x89, 0x89, 0x76, 0x00, // 9            9

0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 10            
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // 11            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 12               
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 13            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 14               
0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 15            
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 16            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 17            
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 18               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 19  
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 20            
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // 21            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 22               
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 23            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 24               
0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 25            
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 26            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 27            
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 28               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 29  
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 30     
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, // 31            


0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 32         "space"        
0x00, 0x00, 0x00, 0xFB, 0xFB, 0x00, 0x00, 0x00, // 33           !       
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 34               
0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 35            
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 36            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 37            
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 38               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 39            


0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 40            
0x00, 0x81, 0x21, 0xC1, 0xFF, 0x01, 0x01, 0x00, // 41            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 42               
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 43            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 44               
0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 45            
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 46            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 47  

0x00, 0x00, 0x7E, 0x81, 0x81, 0x81, 0x7E, 0x00, // 0            0
0x00, 0x00, 0x80, 0x82, 0xFF, 0x80, 0x80, 0x00, // 1            1
0x00, 0x80, 0x41, 0x83, 0x85, 0x89, 0x71, 0x00, // 2            2   
0x00, 0x80, 0x81, 0x91, 0x91, 0x91, 0x6E, 0x00, // 3            3
0x00, 0x08, 0x18, 0x28, 0x48, 0xFF, 0x08, 0x00, // 4            4 
0x00, 0x00, 0xF2, 0x89, 0x89, 0x89, 0x86, 0x00, // 5            5
0x00, 0x00, 0x76, 0x89, 0x89, 0x89, 0x86, 0x00, // 6            6
0x00, 0x00, 0x80, 0x03, 0x8C, 0xB0, 0xC0, 0x00, // 7            7
0x00, 0x00, 0x6E, 0x91, 0x91, 0x91, 0x6E, 0x00, // 8            8   
0x00, 0x00, 0x70, 0x89, 0x89, 0x89, 0x76, 0x00, // 9            9

0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 58               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 59            
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 60            
0x00, 0x81, 0x21, 0xC1, 0xFF, 0x01, 0x01, 0x00, // 61            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 62               
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 63            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 64               
0x00, 0x80, 0x3F, 0x48, 0x48, 0x48, 0x3F, 0x00, // 65            A
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 66            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 67            
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 68               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 69            

0x00, 0x80, 0xFF, 0x08, 0x88, 0x88, 0x80, 0x00, // 70            F
0x00, 0x81, 0x21, 0xC1, 0xFF, 0x01, 0x01, 0x00, // 71            
0x00, 0x80, 0xFF, 0x18, 0x08, 0x08, 0xFF, 0x00, // 72            H
0x00, 0x80, 0x81, 0x81, 0xFF, 0x81, 0x81, 0x00, // 73            I
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 74               
0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 75            
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 76            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 77            
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 78               
0x00, 0x00, 0x7E, 0x81, 0x81, 0x81, 0x7E, 0x00, // 79            O

0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 80            
0x00, 0x81, 0x21, 0xC1, 0xFF, 0x01, 0x01, 0x00, // 81            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 82               
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 83            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 84               
0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 85            
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 86            
0x00, 0x00, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x00, // 87            W
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 88               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 89            

0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 90            
0x00, 0x81, 0x21, 0xC1, 0xFF, 0x01, 0x01, 0x00, // 91            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 92               
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 93            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 94               
0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 95            
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 96            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 97            
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 98               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 99            

0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 100            
0x00, 0x81, 0x21, 0xC1, 0xFF, 0x01, 0x01, 0x00, // 101            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 102               
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 103            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 104              
0x00, 0x00, 0x00, 0x91, 0xBF, 0x01, 0x00, 0x00, // 105            i
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 106            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 107            
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 108               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 109            


0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 110            
0x00, 0x81, 0x21, 0xC1, 0xFF, 0x01, 0x01, 0x00, // 111            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 112               
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 113            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00, // 114               
0x00, 0xe4, 0xa2, 0xa2, 0xa2, 0x9c, 0x00, 0x00, // 115            
0x00, 0x3c, 0x52, 0x92, 0x92, 0x0c, 0x00, 0x00, // 116            
0x00, 0x80, 0x8e, 0x90, 0xa0, 0xc0, 0x00, 0x00, // 117            
0x00, 0x6c, 0x92, 0x92, 0x92, 0x6c, 0x00, 0x00, // 118               
0x00, 0x60, 0x92, 0x92, 0x94, 0x78, 0x00, 0x00, // 119            

0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, // 120            
0x00, 0x81, 0x21, 0xC1, 0xFF, 0x01, 0x01, 0x00, // 121            
0x81, 0x42, 0x00, 0x18, 0x18, 0x00, 0x42, 0x01, // 122              
0x00, 0x84, 0x82, 0xa2, 0xd2, 0x8c, 0x00, 0x00, // 123            
0x00, 0x18, 0x28, 0x48, 0xfe, 0x08, 0x00, 0x00  // 124               



};

At this point what are you looking for?

I've made suggestions earlier that you seemed to have ignored.

You've still hardcoded a lot of numerical constants, such as 32, which if reimplemented as named constants would make the code more readable, changeable and maintainable in general.

A suggestion -

Your font, glyph, data could be expressed in a more visual way for easier editing.

Additionally it may be of benifit to specify it as a 2D array.

uint8_t glyphs[][8] =
{
    ...
    ...
    ...
    ,
    {
          0b00000000
        , 0b00111100
        , 0b01100110
        , 0b01101110
        , 0b01110110
        , 0b01100110
        , 0b00111100
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b00011000
        , 0b00111000
        , 0b00011000
        , 0b00011000
        , 0b00011000
        , 0b01111110
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b00111100
        , 0b01100110
        , 0b00001100
        , 0b00011000
        , 0b00110000
        , 0b01111110
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b01111110
        , 0b00001100
        , 0b00011000
        , 0b00001100
        , 0b01100110
        , 0b00111100
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b00001100
        , 0b00011100
        , 0b00111100
        , 0b01101100
        , 0b01111110
        , 0b00001100
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b01111110
        , 0b01100000
        , 0b01111100
        , 0b00000110
        , 0b01100110
        , 0b00111100
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b00111100
        , 0b01100000
        , 0b01111100
        , 0b01100110
        , 0b01100110
        , 0b00111100
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b01111110
        , 0b00000110
        , 0b00001100
        , 0b00011000
        , 0b00110000
        , 0b00110000
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b00111100
        , 0b01100110
        , 0b00111100
        , 0b01100110
        , 0b01100110
        , 0b00111100
        , 0b00000000
    }
    ,
    {
          0b00000000
        , 0b00111100
        , 0b01100110
        , 0b00111110
        , 0b00000110
        , 0b00001100
        , 0b00111000
        , 0b00000000
    }
    ,
    ...
    ...
    ...
};

What suggestions? :o I've must have missed them totally, I don't usually ignore anything suggested, unless they are way over my head (which is highly possible....) I suppose you meant by that suggestion modulo operator?

We got it working but code is somewhat ugly and not arduino-language, but best we got...(word woof scrolls through matrix)
Thanks for pointing out making better visualized array!

 #include "FontMap.h"

int dataPin = 2; // ic: 14, ser_in Define which pins will be used for the Shift Register control
int latchPin = 3; // ic:12 silkscreen numbers!
int clockPin = 4;


unsigned char displayPointer=0; // for interrupt use...
unsigned char buffer1[32]; // buffer for screen
unsigned char backbuffer[32]; // Spare screen for drawing on
unsigned char power[8]={128,64,32,16,8,4,2,1};

ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine
{
if(TIFR2) // Make sure its the timer interrupt.
{
setcolumn(displayPointer);
setdata(buffer1[displayPointer]);
digitalWrite(latchPin ,HIGH);digitalWrite(latchPin , LOW ); // STORECLOCK
if(++displayPointer==32) { displayPointer = 0; } // 32 LED row sections in total
}
TIFR2 = 0; // Clear timer 2 interrupt flag


}

void setcolumn(unsigned char col){
signed char pos;
for (pos = 32;pos>-1;pos--){
if (col == pos){digitalWrite(dataPin ,HIGH);}else {digitalWrite(dataPin ,LOW);} // PIN1 DATA pin
digitalWrite(clockPin ,HIGH);digitalWrite(clockPin ,LOW);
}}

void setdata(unsigned char dat){
unsigned char pos;
for (pos = 0;pos<8;pos++){
if (dat & 128){dat-=128;digitalWrite(dataPin ,HIGH);}else { digitalWrite(dataPin ,LOW);} // PIN1 DATA pin
dat = dat * 2;
digitalWrite(clockPin ,HIGH);digitalWrite(clockPin ,LOW);
}}
void clr() //clear
{
int addr;
for(addr=0;addr<32;addr++) // Empty display buffer
backbuffer[addr]= 0;
}

void Blit() //transfers data between display buffer to screen buffer
{
int addr=0;
noInterrupts(); // disable all interrupts during setup
for(addr=0;addr < 32;addr ++)
{
buffer1[addr] = backbuffer[addr]; // put all data from display buffer
} // to screen buffer
interrupts(); // enable all interrupts
}

void pixel(signed char x,signed char y,int cond)
{
unsigned char pix,msk;
if(x<0 || y<0) return; // outside drawing limits negative
if(x>31 || y>7) return; // outside drawing limits positive
pix = power[y];
msk = backbuffer[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
backbuffer[x] = pix; // apply changes
}

void charput(unsigned char ch, signed char x,signed char y)
{
signed char x1, y1;
unsigned char disp;
unsigned char disp2;
for( x1=0;x1<8;x1++) // eight rows
{
disp = font[x1+(ch * 8)];
for (y1 = 0; y1<8; y1++) // eight pixels
{
disp2 = disp & power[y1];
if(disp2 > 0)
{
pixel(x+x1,y+y1,0); // OR the pixel to the display buffer
}
}

}
}

void strput(const char* ch, signed char x,signed char y)
{
int addr;
while (*ch )
{
charput(*ch++,x,y); // write a string to the display buffer
x+=7;
}
}



void setup() //setup runs once
{
signed char cntr;
noInterrupts(); // disable all interrupts during setup
DDRD = DDRD | B11111100; //port registers used to set pin directions
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 1; // compare match register 16MHz/256/2Hz -----------------------------------> delay time (lcd flicker/brightness)
TCCR1B |= (1 << WGM12); // CTC mode, free-running, clear on match
TCCR1B |= (1 << CS12); // 256 prescaler
TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt
interrupts(); // enable all interrupts

} // End main

void loop() //just sitting here
{
signed char scrollctr;
unsigned char numCTR;

clr();
strput("WOOF",0,0);
Blit();
delay(5);

for (scrollctr=-8;scrollctr<9;scrollctr++)
{
clr();
strput("WOOF",0,scrollctr);
Blit();
delay(5);
}

for (scrollctr=-32;scrollctr<33;scrollctr++)
{
clr();
strput("WOOF",scrollctr,0);
Blit();
delay(5);
}

for (numCTR=0;numCTR<10;numCTR++){
for (scrollctr=-8;scrollctr<9;scrollctr++)
{
clr();
charput(numCTR,24,scrollctr);
Blit();
delay(5);
}
}



}

You opened this discussion with a request for helps sans code.

Since then you've indicated success with your own implementation and I assume your looking for some comments on improving it in some, as yet, unspecified manner.

I'm choosing to post my quick reinterpretation of you code.

It is of course untested as I don't have your hardware so I can't be sure it works but do so in the hopes that you'll find it at least somewhat educational.

The code as written should be adaptable to your expanding and duplicating the existing hardware in a compatible manner by simply changing the constants 'dxPIXELS' and 'dyPIXELS'.

If I've done it correctly the frame and draw buffers shall automatically adapt to the correct sizes and all existing functions should continue to work correctly.

With the known exception of your 'charput' function which I didn't bother with.

No offense was intended by posting this modification of your code, I simply hoped you'd find it educational.

// <https://forum.arduino.cc/index.php?topic=369981.0>

#include <limits.h>
#include <string.h>

#include "FontMap.h"

#define COUNT_ENTRIES(ARRAY)    (sizeof(ARRAY) / sizeof(ARRAY[0]))

#define COLUMNS_COUNT(DX)       (DX)
#define ROWS_COUNT(DY)          ((((DY) - 1) / (sizeof(uint8_t) * CHAR_BIT)) + 1)

#define X_TO_COLUMN(X)          (X)
#define Y_TO_ROW(Y)             ((Y) / CHAR_BIT)
#define Y_TO_BIT(Y)             ((1 << (CHAR_BIT - 1)) >> ((Y) % CHAR_BIT))

const uint8_t   pinDATA         = 2;    // ic: 14, ser_in Define which pins will be used for the Shift Register control
const uint8_t   pinLATCH        = 3;    // ic:12 silkscreen numbers!
const uint8_t   pinCLOCK        = 4;

const uint8_t   dxPIXELS        = 32;
const uint8_t   dyPIXELS        =  8;

const size_t    BUFFER_COLUMNS  = COLUMNS_COUNT(dxPIXELS);
const size_t    BUFFER_ROWS     = ROWS_COUNT(dyPIXELS);

uint8_t         bufferFrame[BUFFER_ROWS][BUFFER_COLUMNS];
uint8_t         bufferDraw[BUFFER_ROWS][BUFFER_COLUMNS];

void setdata(uint8_t data)
{
    for ( size_t mask = ((sizeof(data) * CHAR_BIT) -  1); mask; mask >>= 1 )
    {
        digitalWrite(pinDATA, ((data & mask) ? HIGH : LOW));

        digitalWrite(pinCLOCK, HIGH);
        digitalWrite(pinCLOCK, LOW);
    }
}

void setcolumn(uint8_t col)
{
    for ( size_t pos = BUFFER_COLUMNS; pos--; )
    {
        digitalWrite(pinDATA, ((col == pos) ? HIGH : LOW));

        digitalWrite(pinCLOCK, HIGH);
        digitalWrite(pinCLOCK, LOW);
    }
}

// TIMER COMPARE INTERRUPT SERVICE ROUTINE
ISR(TIMER1_COMPA_vect)
{
    static uint8_t  indexFrame  = 0;

    // MAKE SURE ITS THE TIMER INTERRUPT.
    if ( TIFR2 )
    {
        // TRANSFER NEXT COLUMN TO SHIFT-REGISTER FOR OUTPUT
        const uint8_t*  pbuffer = (uint8_t*)bufferFrame;
        const size_t    cb      = sizeof(bufferFrame);

        setcolumn(indexFrame);
        setdata(pbuffer[indexFrame]);

        // STORECLOCK
        digitalWrite(pinLATCH, HIGH);
        digitalWrite(pinLATCH, LOW);

        indexFrame = ((indexFrame + 1) % cb);
    }

    // CLEAR TIMER 2 INTERRUPT FLAG
    TIFR2 = 0;
}

void clr()
{
    memset(bufferDraw, 0, sizeof(bufferDraw));
}

// TRANSFERS DATA BETWEEN DRAW BUFFER TO FRAME BUFFER
void Blit()
{
    // DISABLE ALL INTERRUPTS DURING SETUP
    noInterrupts();

        memcpy(bufferFrame, bufferDraw, sizeof(bufferFrame));

    // ENABLE ALL INTERRUPTS
    interrupts();
}

void pixel(uint8_t x, uint8_t y, uint8_t mode)
{
    // ... CLIPPING ...
    if ( (x < 0)         || (y < 0) )           { return; }
    if ( (x >= dxPIXELS) || (y >= dyPIXELS) )   { return; }

    uint8_t&        data    = bufferDraw[Y_TO_ROW(y)][X_TO_COLUMN(x)];
    const uint8_t   bit     = Y_TO_BIT(y);

    switch ( mode )
    {
        case 0: data |=  bit;   break;  // SET, OR data to screen
        case 1: data &= ~bit;   break;  // CLEAR, AND data to screen
        case 2: data ^=  bit;   break;  // INVERT, XOR data to screen
    }
}

// ... DIDN'T TOUCH THIS ONE ...
void charput(uint8_t ch, uint8_t x, uint8_t y)
{
    int8_t  x1, y1;
    uint8_t disp;
    uint8_t disp2;

    for ( x1 = 0; x1 < 8; x1++ )    // eight rows
    {
        disp = font[x1 + (ch * 8)];
        for ( y1 = 0; y1 < 8; y1++ )    // eight pixels
        {
            disp2 = disp & power[y1];
            if ( disp2 > 0 )
            {
                pixel(x + x1, y + y1, 0);   // OR the pixel to the display buffer
            }
        }
    }
}

void strput(const char* pch, uint8_t x, uint8_t y)
{
    // write a string to the display buffer
    char    ch;
    while ( ch = *pch++ )
    {
        charput(ch, x, y);
        x += 7;
    }
}

void loop()
{
    clr();

    pixel( 0, 0, 0);
    pixel(31, 8, 0);

    charput(0, 1, 0);

    charput(1, 7, 0);

    Blit();
    delay(500);
}

void setup()
{
    noInterrupts(); // disable all interrupts during setup

    DDRD    = DDRD | B11111100;     //port registers used to set pin directions
    TCCR1A  = 0;
    TCCR1B  = 0;
    TCNT1   = 0;
    OCR1A   = 5;                    // compare match register 16MHz/256/2Hz
    TCCR1B |= (1 << WGM12);         // CTC mode, free-running, clear on match
    TCCR1B |= (1 << CS12);          // 256 prescaler
    TIMSK1 |= (1 << OCIE1A);        // enable timer compare interrupt

    interrupts();                   // enable all interrupts
}

No offence taken if someone is just helping out!
Bit different code, but there's many ways to skin a cat! :slight_smile:
Was that the full code? It gave an error while comiling saying power wasn't declared, copied power from previous code. Now it didn't gave errors, but nothing sensible appears on screen. Can post a photo if needed, this I added to declaration's place:

 unsigned char power[8]={128,64,32,16,8,4,2,1};