Important changes to forums and questions
All forums and questions are now archived. To start a new conversation or read the latest updates go to forums.mbed.com.
12 years, 1 month ago.
Dereferencing an array of pointers to arrays
I'm stumped again. In a prior post (http://mbed.org/questions/1581/Array-of-pointers-to-byte-arrays/), the kind people of this forum help me out. Now, I'm trying to take it to the next level and running into problems again. My project uses an 8-position DIP switch to select one of 256 patterns for blinking LEDs. I am trying to understand why the patterns don't appear as expected. If I remove the sequence pointer dereferencing attempt and simply point to a sequence, the sequence runs. Can any of you see what I am missing?
Many thanks.
main program
#include "mbed.h"
#include "bits.h"
#include "types.h"
#include "sequences.h"
/* Determines the fastest and slowest sequence step timing. Times are in
1/60th of a second (one clock).*/
#define FASTEST_TIME 12.0 /* about 100ms */
#define SLOWEST_TIME 360.0 /* about 3000ms */
/* The AnalogIn function scales the voltage input to a float 0.0-1.0. */
#define SLOPE (SLOWEST_TIME - FASTEST_TIME)
/* Setup a serial debug port on the USB interface. */
//Serial pc(USBTX, USBRX); // tx, rx
/* Setup the dipswitch input port. */
BusIn dipswitch(P0_7, P0_8, P0_9, P0_10, P0_11, P0_12, P0_13, P0_14);
/* Setup the pattern output port. */
//BusOut lights(P0_16, P0_17, P0_18, P0_19, P0_20, P0_21, P0_22, P0_23);
BusOut lights(P0_20, P0_22);
/* The potentiometer input port to select the speed of the sequence steps. */
AnalogIn potentiometer(P0_15);
Ticker heartbeat; /* Simulates the 1/60th of a second clock from the future ZCD. */
DigitalOut led1(P0_21); /* For debugging inside the interrupt routine. */
byte *ptrSequence; /* A pointer to the desired sequence. */
word sequenceLength; /* The length of the desired sequence. */
byte pattern; /* The current output pattern. */
word sequence; /* The current sequence. */
float speed; /* The selected speed. */
int speed_clks; /* speed in clocks (1/60th sec). */
word clocks; /* Incremented everytime the 1/60th sec interrupt is called. */
int i;
void HB() {
clocks++;
if((clocks % speed_clks) == 0) {
i++;
if(i >= sequenceLength) {
i = 0;
}
led1 = !led1;
pattern = ptrSequence[i];
lights = pattern;
}
}
int main() {
/* Basic initialization. */
led1 = 1;
clocks = 0;
speed_clks = 100;
i = 0;
/* Simulate the 1/60th sec interrupt from the zero crossing detector. */
heartbeat.attach(&HB, 0.0083333);
/* Loop through the sequence forever. */
while(1) {
/* Obtain the inputs. */
/* Read the dipswitch */
//sequence = dipswitch;
sequence = 0;
/* Read the potentiometer. */
speed = potentiometer;
/* Use the inputs to determine internal values. */
/* Set the sequence number and length. */
__disable_irq(); // Disable Interrupts
/* This line doesn't work. */
//ptrSequence = (byte *) ptrSequences[sequence];
/* This line does. */
ptrSequence = (byte *) sequence0;
sequenceLength = sequenceLengths[sequence];
/* Changes the analog speed voltage to a time in clocks. */
speed_clks = SLOPE * speed + FASTEST_TIME;
__enable_irq(); // Enable Interrupts
//pc.printf("sequence: %i, Length: %i\r\n", sequence, sequenceLength);
// pc.printf("clocks: %i, speed_clks: %i\r\n", clocks, speed_clks);
// pc.printf("i: %i, pattern = %d\r\n", i, pattern);
wait(0.4);
}
}
types.h
typedef unsigned char byte; typedef unsigned int word; typedef unsigned long dword; typedef int sword; typedef long sdword; #define TRUE 1 #define FALSE 0
sequences.h
const byte sequence0[] = {
B10000000,
B01000000,
B00100000,
B00010000,
B00001000,
B00000100,
B00000010,
B00000001
};
const byte sequence1[] = {
B10000001,
B10000001,
B11000001,
B10100001,
B10010001,
B10001001,
B10000101,
...
bits.h
#define B00000000 0x00 #define B00000001 0x01 #define B00000010 0x02 #define B00000011 0x03 #define B00000100 0x04 ...
4 Answers
12 years, 1 month ago.
Hello Kevin Callan,
the next time please highlight code which works and not, I almost overlooked it in your pasted code
/* This line doesn't work. */
1. //ptrSequence = (byte *) ptrSequences[sequence];
/* This line does. */
2. ptrSequence = (byte *) sequence0;
What does 1. do? Cast a value which is designated by the address ptrSequences[sequence] to a pointer to byte. This pointer will point to the address which is equal to the value stored at the address (ptrSequences + sequence). An example
ptrSequences[sequence] = 10; ptrSequence = (byte *) ptrSequences[sequence]; /* ptrSequence points to the 10 */
What does 2. do? Stores an address of the sequence0 beginning (&sequcence[0])
I believe if you want to point to an address of an item inside an array, use this syntax &ptrSequences[index]
Regards,
0xc0170
12 years, 1 month ago.
What you apparently like to have is an array of sequences. When all sequences have the same length you can use a two-dimensional array. When not you can use an array of pointers to sequences (arrays of bytes). for instance:
byte seq1[] = {1,2,3};
byte seq2[] = {1,2,3,4};
byte seq3[] = {1,2,3,4,5};
int sizes[] = {sizeof(seq1), sizeof(seq2), sizeof(seq3)};
byte* seqs[] = {seq1, seq2, seq3}; //make sure that seqs and sizes have the same number of elements
for (int s = 0; s < sizeof(seqs)/sizeof(byte*); s++)
{ if (s < sizeof(sizes)/sizeof(int)) //paranoid precaution in case sizes has less elements than seqs
for (int i = 0; i < sizes[s]; i++)
{ byte val = seqs[s][i];
}
}
Don't try to be clever and circumvent the use of the sizes array
byte seq1[] = {1,2,3};
byte seq2[] = {1,2,3,4};
byte seq3[] = {1,2,3,4,5};
byte* seqs[] = {seq1, seq2, seq3};
for (int s = 0; s < sizeof(seqs)/sizeof(byte*); s++)
{ int size = sizeof(seqs[s]); //will give the size of a byte* (4)
int size = sizeof(*seqs[s]); //will give the size of a byte (1)
for (int i = 0; i < size; i++)
{ byte val = seqs[s][i];
}
}
12 years, 1 month ago.
I think Kevin is trying to say that the code lines 1 and 2 are supposed to do the same thing. Line 1 doesn't work, line 2 does. I don't see why line 1 shouldn't work.
/* This line doesn't work. */
1. //ptrSequence = (byte *) ptrSequences[sequence];
/* This line does. */
2. ptrSequence = (byte *) sequence0;
12 years, 1 month ago.
Thank you all for your help. I still don't have it working. I'm afraid that I'll have to do something ugly for now just to get it working. Like this:
ugly code
switch(dipswitch) {
case 0: {
ptrSequence = (byte *) sequence0;
break;
}
case 1: {
ptrSequence = (byte *) sequence1;
break;
}
case 2: {
ptrSequence = (byte *) sequence2;
break;
}
...