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.
11 years, 2 months 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
11 years, 2 months 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
11 years, 2 months 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]; } }
11 years, 2 months 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;
11 years, 2 months 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; } ...