Help to reduce recursive code

Hello all you wonderful Arduino'ers!

Once again I dusted off my Arduino to tinker on a new ever evolving project and whilst I have had some challenges in getting the project to where oit is now .. I am quite happy I have it working...

I am undersure how I might pass some data and work on the variables iwth varying types ..

At the moment, I define some ASCII characters in binary "bitmaps"

const uint8_t PROGMEM char_M[8] = {   // store in program memory to save RAM
  B11111111,  B11111110,  B00001100,  B00111000,  B00111000,  B00001100,  B11111110,  B11111111};

I then call a function to use this data and write it to some an LED strip:

void chrM() {

  for (byte x = 0; x < 8; ++x) {
    int i = 0;
    byte data = pgm_read_byte (&char_M[x]);   // fetch data from program memory
    for (byte y = 0; y < 8; ++y) {
      if (data & (1 << y)) {
        writeColour(i);
        i++;

      } else {
        colors[i] = (rgb_color) {
          0, 0, 0
        };
        i++;
      }

      // repeat for 8 bits
    }
    writeDisplay();
  }

}

But here in lies the problem .. I have over 70 functions with just the variable changing meaning my program is becoming bloatware :frowning:

Could someone show or guide me to how I might do bitwise operations on the passed variable .. It's the & which is confusing me!

Essentially, I would like to use one function and change the &char_M[x] variable.

Thanks in advance

Essentially, I would like to use one function and change the &char_M

[/b] variable.

So, why don't you? What is the problem?

By the way, your problem has nothing to do with recursion.

you need something like this

void displayChar(byte data) 
{
  for (byte x = 0; x < 8; ++x) 
  {
    int i = 0;
    for (byte y = 0; y < 8; ++y) 
    {
      if (data & (1 << y)) {
        writeColour(i);
        i++;
      } else {
        colors[i] = (rgb_color) {
          0, 0, 0
        };
        i++;
      }
    }
    writeDisplay();
  }
}

That doesn't work, the outer loop is supposed to address 8 consecutive bytes from PRGOMEM

Put your character map in a two dimensional array.

Recursion is when a function calls itself. It's only for grown-ups.

...R

Robin2:
Recursion is when a function calls itself. It's only for grown-ups.

...R

To iterate is human, to recurse, divine.

AWOL:
To iterate is human, to recurse, divine.

LOL

...R

Sorry for my incorrect use of recursive :slight_smile:

And thanks for the advice...

I guess I just got a little confused trying to pass the whole part of the char array as a byte when I should pass a character array as a copy of the data in:

const uint8_t PROGMEM char_M[8] = { // store in program memory to save RAM
B11111111, B11111110, B00001100, B00111000, B00111000, B00001100, B11111110, B11111111};

I'll try it again today

I just got a little confused trying to pass the whole part of the char array as a byte

No wonder you are confused. Whole or part? Why would you (try to) pass a char array as a byte? Passing it as a char * makes sense. Passing it as a byte array makes (some) sense. Passing it as a char array makes sense. Passing it as a byte does not.

you mean a function like this ?:

void chrM(const uint8_t PROGMEM *data, byte dataLength ) {
...
}

Something like:

const uint8_t PROGMEM char_AZ[][8] = {  
  { ... }, // letter A
  { ... }, // letter B
  ...
  { B11111111,  B11111110,  B00001100,  B00111000,  B00111000,  B00001100,  B11111110,  B11111111}, // letter M
  ...
  { ...}, //letter Y
  { ...} //letter Z
};

void chrAZ(char ch) {

  uint8 *thechar = char_AZ[ch - 'A'];

  for (byte x = 0; x < 8; ++x) {
    int i = 0;
    byte data = pgm_read_byte (&thechar[x]);   // fetch data from program memory
    for (byte y = 0; y < 8; ++y) {
      if (data & (1 << y)) {
        writeColour(i);
        i++;

      } else {
        colors[i] = (rgb_color) {
          0, 0, 0
        };
        i++;
      }

      // repeat for 8 bits
    }
    writeDisplay();
  }
}

PaulMurrayCbr:
Something like:

const uint8_t PROGMEM char_AZ[][8] = {  

{ ... }, // letter A
  { ... }, // letter B
  ...
  { B11111111,  B11111110,  B00001100,  B00111000,  B00111000,  B00001100,  B11111110,  B11111111}, // letter M
  ...
  { ...}, //letter Y
  { ...} //letter Z
};

void chrAZ(char ch) {

uint8 *thechar = char_AZ[ch - 'A'];

for (byte x = 0; x < 8; ++x) {
    int i = 0;
    byte data = pgm_read_byte (&thechar[x]);  // fetch data from program memory
    for (byte y = 0; y < 8; ++y) {
      if (data & (1 << y)) {
        writeColour(i);
        i++;

} else {
        colors[i] = (rgb_color) {
          0, 0, 0
        };
        i++;
      }

// repeat for 8 bits
    }
    writeDisplay();
  }
}

Firstly, thank you everyone who has posted so far - this help is awesome and whilst I feel I am now in the deep end of my knowledge - the help is greatly appreciated.

I tried to implemet your example Paul but I am getting an error:

'unit8' was not declared in this scope.

So I thought it might be uint8_t but I dont think so as that gives another error. Maybe it's how I'm calling the function ..

chrAZ('A');

Suffice to say, when I started this project I was using integer arrays to define the 8x8 square of a character and I've managed to save RAM but defining them as binary. The challenges can be overcome as I have learned on this project but I do feel like my awareness of datatypes, passing variables and bitwise functions / pointers etc are letting me down...

Thanks all for the wonderful community help thus far!

Wow - thanks people - I think I might have it working using a bits from you all :smiley:

I will just iron out a few bugs and post back here shortly

WOW! Thank you all for some excellent help

I have managed to cut down on all of the explicitly defined functions and reduce them to this:

const uint8_t PROGMEM char_1[8] = {   // store in program memory to save RAM
  B00000000,  B10001100,  B10000110,  B11111111,  B11111111,  B10000000,  B10000000,  B00000000};

const uint8_t PROGMEM char_2[8] = {   // store in program memory to save RAM
  B00000000,  B11000010,  B11100011,  B11100001,  B10110011,  B10011011,  B10001110,  B00000000};

const uint8_t PROGMEM char_3[8] = {   // store in program memory to save RAM
  B00000000,  B01000010,  B10001001,  B10001001,  B10001001,  B11001011,  B01110110,  B00000000};

...

And with each variable as they were (they don't take up much space) I call the function with:

print_Char(char_A, 8);

Function:

void print_Char(const uint8_t PROGMEM *char_Print, byte dataLength ) {
  for (byte x = 0; x < 8; ++x) {
    int i = 0;
    byte data = pgm_read_byte (&char_Print[x]);   // fetch data from program memory
    for (byte y = 0; y < 8; ++y) {
      if (data & (1 << y)) {
        writeColour(i);
        i++;

      } else {
        colors[i] = (rgb_color) {
          0, 0, 0
        };
        i++;
      }

      // repeat for 8 bits
    }
    writeDisplay();
  }
  for (int numSep = 0 ; numSep < maxSeperators ; numSep++) {
    seperator();
  }
}

I call the function as follows:

The size of the code has gone from:
-----------------------------------------------------
Sketch uses 13,910 bytes (45%) of program storage space.
Global variables use 114 bytes (5%) of dynamic memory

To:
-----------------------------------------------------
Sketch uses 4,662 bytes (15%) of program storage space.
Global variables use 114 bytes (5%) of dynamic memory

You don't use the dataLength parameter at all, so you should either use it or remove it.

arduinodlb:
You don't use the dataLength parameter at all, so you should either use it or remove it.

some of the characters are wider than others so having the datalenth might work later... I prefer that I can change it later