My C skills in casting, pointers, referencing & dereferencing are hiding somewhere in my brain after many years of neglect. So far, programming of Arduinos has not needed them until today.
I am using the TVout library. I have the demo working on a Nano 3, so I know my hardware is fine. I have also successfully manipulated the screen data directly rather than via the various dot, line, text, bitmap functions provided by the library.
What I want to do is allow my sketch to access the screen data using an alternative view. Allow me to explain:
The screen data in the TVout library is declared:
uint8_t * screen;
i.e. a pointer to a single dimension array of bytes. It uses the malloc() function to get memory allocated based on the requested screen resolution.
I want my sketch to view this same memory as a 2 dimensional array of unsigned long, e.g.:
unsigned long * myScreen[4][96]
I will ensure that these two structures are the same size.
How do I point myScreen to the same data as screen. Is it simply?:
unsigned long (* myScreen)[4][96];
myScreen = (long unsigned int (*)[4][96]) TV.screen;
I think your original definition of myScreen was a 4 by 96 array of pointers to unsigned long. What you wanted was a pointer to a 4 by 96 array of unsigned long. That's what the additional parentheses do.
//Set up initial cells in matrix
for (int r = 0; r < matHeight; r++) {
for (int c = 0; c < matWidth; c++) {
(*myScreen)[r][c] = random(0xffff) << 16 | random(0xffff);
}
}
}
Note: I also had to change PAL to _PAL to get it to compile.
for (int r = 0; r < matHeight; r++) {
for (int c = 0; c < matWidth; c++) {
(*myScreen)[r][c] = random(0xffff) << 16 | random(0xffff);
}
}
}
Thanks John. Again, I think I understand that now I see it, but not convinced I could figure out a similar problem for myself in the future!
I fixed the code myself in the end by making a compromise. I managed to convince the sketch to treat the screen data as a one-dimensional array of unsigned long, as opposed to 2-dimensional. This required some code changes, but the move from 8-bit data chunks to 32-bit data chunks gave me the performance boost I was hoping/expecting.
I expected to see an improvement in performance because my code used to use unsigned long before I adapted it to work with TVout. Initially, I adapted it by changing it to process bytes, to fit in with the screen data format that TVout uses. I was hoping that the performance would not be affected, because an ATmega328 has an 8-bit architecture, and has to process unsigned long in 4 instructions at least. But I did see an immediate performance drop, which was reversed when (with your help) I managed to change the code back to using unsigned long. So even though the same number of bytes have to be processed either way, its more efficient to work with unsigned long vs byte for this application. Here is the link to the final version of the code.
johnwasser:
Note: I also had to change PAL to _PAL to get it to compile.
You can take a pointer to the base of an array and add offsets into any part of the array, iterate with ++ or --.
You can cast that pointer to access array members as whatever you want and iterate those too.
Don't forget memset(), memcpy() and the rest of the mem functions in string.h!