[SOLVED] Strange problem with simple loop

Hi all,

This code:

void send_cmd (const uint16_t *cmd, uint16_t bytes, uint16_t repeat, uint16_t delay)
{
    uint16_t data; // read data
    uint16_t idx; // data block index

    // command repeat count, if any
    while (repeat--) {
        for (idx = 0; idx < bytes; idx++) {
            sei (); // interrupts on
            while (busy); // wait if busy
            cli (); // interrupts off
            data = pgm_read_word ((const uint16_t *)(cmd + idx));
            enable = (data >> 15); // bit 15 is emitter on/off
            count = (data << 1); // count * 2 for full cycle
            busy = 1; // flag ISR busy
        }
        enable = 0; // insure emitter off
        delay_msec (delay); // inter-command delay, if any
    }
}

… is driving me crazy. Specifically, this part:

        for (idx = 0; idx < bytes; idx++) {
            // .......
        }

If “bytes” is 3 (three), then the loop should run 3 times, giving me an index (idx) of 0, 1 and 2… right?

However, it seems to be only going to 0 and 1. In order to make it do all 3, I have to say “[b]idx <= bytes[/b]” which is, as far as I know, wrong!

How I can tell what’s happening is this: I put in some test data into the PROGMEM array that this code reads which should produce one pulse, then two, then three pulses… looking like this on the 'scope:

[b][tt]      _          _    _          _    _    _
      | |        | |  | |        | |  | |  | |
______| |________| |__| |________| |__| |__| |____

___[/b][/tt]

…but with “[b]idx < bytes[/b]” (where “bytes” == 3), I only get the first two sets (i.e. 1 pulse then 2 pulses).

Anyone have any ideas? I am completely stumped.

It would help if you posted a complete program that exhibits the problem.

Probably not your issue but I'm confused with the use of the variable name bytes given you read words not bytes. So when you do cmd + idx given the type of the pointer you skip 2 bytes every time. Is that intended and is this how you stored things in memory for your test?

My guess - bytes is 2, not 3 as you think it should be. This is usually caused by calculating things in floating-point and then converting back to int without adding a fudge factor, but I can't tell for sure because you have not posted your entire sketch, [u]like the sticky says to do[/u]. So I have to guess, and I could be wrong. There's no way for me to know.

enable is zero if the MSB of a PROGMEM data word is zero, which per the comment(s) means “emitter off”
what might be the effect of that?

If "bytes" really is three (and not two because of some rounding error for example) then that loop gets executed three times, exactly as you thought.

So if you are only seeing two pulses I would suspect that you're not "warming up the loop" properly and the first pass is not doing what you're expecting.

We can't see because the code to output the pulses is not shown (nor is the initialization code), so we can only guess. I suspect that the pulses are somehow generated in an ISR during the "while(busy)" statement, but that's just a guess. Could it be for example that "busy" (or "enable") is not initialized correctly prior to the first pass of the loop and so the first pulse is not generated?

Is busy volatile?

When that snippet ends, interrupts will be disabled. Is that a good idea? Not in my opinion.

wg0z: enable is zero if the MSB of a PROGMEM data word is zero, which per the comment(s) means "emitter off" what might be the effect of that?

THAT was the problem. I had "enable = 0" in the wrong part of the loop and disabled the emitter (an LED) after the first pass.