3

I have the following array:

PROGMEM prog_uint16_t show_hide_info[] = { 4216, 8900, 4380, 580, 500, 600, 500, 580, 1620, 580, 500, 600, 500, 580, 500, 600, 480, 600, 500, 580, 1620, 580, 1620, 600, 500, 580, 1620, 580, 1620, 600, 1600, 600, 1620, 580, 1620, 600, 500, 580, 1620, 580, 500, 600, 1600, 600, 500, 580, 1620, 580, 500, 600, 1620, 580, 1620, 600, 480, 600, 1620, 580, 500, 600, 1600, 600, 500, 580, 1620, 580, 500, 600, 39300, 8860, 2160, 580, 0 };

I'd like to be able to loop through this array and execute the following methods accordingly:

pulseIR(4216);
delayMicroseconds(8900);
pulseIR(4380);
delayMicroseconds(580);
...

This is what I have so far, which is obviously way off track:

unsigned int* get(prog_uint16_t code[]) {
  unsigned int c;

  while ((c = pgm_read_word(code++))) {
    //pulseIR(c); ??
    //delayMicroseconds(c+1); ??
  }
}

Not quite sure what I'm meant to be doing with c to be honest.

Due to lack of sleep, I can't for the life of me make sense of the following documentation on PROGMEM:

http://arduino.cc/en/Reference/PROGMEM

3 Answers 3

1

First you'll need some short hand to find the end of the array. If its a fixed number of values, then the compiler can calculate it this way to find the count of int16 values:

PROGMEM prog_uint16_t show_hide_info[] = { 4216, 8900, 4380, 580, ....etc
int arraySize = sizeof(show_hide_info) / sizeof(prog_uint16_t);

Then if you want to have a function that goes thru your array just once, the function can be declared this way:

void cycleThruArrayOnce(prog_uint16_t *pInArray, int nLimit) {
 for (int i=0;i<nLimit;i=i+2) {
   pulseIR(pgm_read_word(pInArray++));
   delayMicroseconds(pgm_read_word(pInArray+));
 }
}

And it can be called from your main program this way:

cycleThruArrayOnce(show_hide_info, arraySize);
Sign up to request clarification or add additional context in comments.

5 Comments

Concur. Another way to signal the end of an array is to use a value that you'll never actually use to act as the signal that you've reached the end. But that requires an if each time you go through the loop.
Shouldn't it be: void sendCode(prog_uint16_t inArray[], int nLimit); instead of void sendCode(int inArray[], int nLimit);? Otherwise I get the following errors: error: invalid conversion from 'prog_uint16_t*' to 'int*' and error: initializing argument 1 of 'void sendCode(int*, int)'
Yes, you are correct, the type prog_uint16_t needs to match the array. Updated now. (I hadn't compiled the snippet previously.)
Ok, I've updated it to minimize the code and fix the incorrect syntax to pgm_read_word (it expects a ptr, not the value of the array, that's why it was giving you those same incorrect values). I see that you added a 0 at the end of the array to signal its size. In general, thats a bad practice because it relies on someone correctly entering values at a specific place (someone in the future might want the 42nd value to be 0, which would break the loop). Better to let the compiler figure it out ahead of time to generate the smallest code footprint.
@jdh Using this code as it generates a smaller code footprint and works exactly the same way.
1

I ended up using the following code. Does what I need it to do. Not sure if it's the most efficient way however. I'm open to any suggestions and am willing to accept answers over my final one.

void sendCode(prog_uint16_t inArray[], int nLimit) {

  unsigned int arr[nLimit];
  unsigned int c;
  int index = 0;

  while ((c = pgm_read_word(inArray++))) {
    arr[index] = c;
    index++;
  }

  for (int i = 0; i < nLimit; i=i+2) {
    delayMicroseconds(arr[i]);
    pulseIR(arr[i+1]);
  }

}

5 Comments

This looks like it could write beyond the end of arr. It assumes that there is a 0 at the end of the inArray. In your example show_hide_info doesn't have this. It may seem to work correctly but there are no guarantees about its behavior without this.
@MatthewMurdoch I've ensured all my arrays end in 0. If there's a better way of replicating what's happening in my final code then feel free to add it as an answer and I'd be willing to accept it.
My answer to your other question (stackoverflow.com/a/8978128/4023) shows a more efficient way to perform these operations.
I've corrected a syntax error in my previous answer below. In your solution, the code is duplicating the work of the commpiler at runtime in attempting to find the end of the array. You've also imposed that the array can't contain 0 values this way (might later want no delay). This tiny duplicate loop is also taking some minor unnecessary code space.
@jdh will give it a try when I get home tonight.
1

Would this bit be a little faster

    for (int i = 0; i < nLimit; i=i+2) {
    delayMicroseconds(arr[i]);
    pulseIR(arr[i+1]);
  }

if

for (int i = 0; i < nLimit; i++) {
    delayMicroseconds(arr[i]);
    i++;
    pulseIR(arr[i]);
  }

1 Comment

Not sure whether I'm after performance. I'd prefer to keep sketch size low as a priority.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.