|
|
View previous topic :: View next topic |
Author |
Message |
nurquhar
Joined: 05 Aug 2006 Posts: 149 Location: Redditch, UK
|
How can I use large const struct arrays with CCS ??? |
Posted: Sun Jul 15, 2007 5:53 am |
|
|
PIC 16F876A
Compliler PCM 249
I am trying to use some large lookup tables in my program. Unfortunatly with CCS once the size of const array is bigger than 256 bytes then the indexes nolonger work correctly.
for example if you have something like this :
Code: | const int val[] = { 1, 2, 3, ........., 254,255,256 } ;
int16 i ;
i = 255 ;
printf("val[%ld] = %d", i, val[i]) ; |
you will probably see val[255] = 1 on the screen and not val[255] = 256.
The way I have got round this in the past has been to split a large table in half and use a function to access it, like this :
Code: |
const int table1 = {1,2,3 .......,126,127} ;
const int table2 = {128,129,130 .......,255,256} ;
int GetVal(int16 idx)
{
if(idx >= 128) return table2[idx - 128] ;
else return table1[idx] ;
} |
This sort of works.
However !!
I now want to use a typdef struct in an array, something like this :
Code: | typedef struct _sFrame {
uint16 time ; uint8 output[MAX_UNITS] ;
} sFrame ;
const sFrame film1[] = {
// 1111111 11122222 22222333
// Time 12345678 90123456 78901234 56789012
// ----- -------- -------- -------- --------
{50, 0b00000000, 0b00000000, 0b00000000, 0b00000000 },
{50, 0b10000000, 0b00000000, 0b00000000, 0b00000000 },
{50, 0b00000001, 0b00000000,
..... etc ....................
0b00000001, 0b00000000 },
} ;
// Function to access one element of the struct array
sFrame *GetFrame(uint16 idx)
{
sFrame *f ;
f = &film1[idx] ;
return f ;
}
|
The problem is I can't get the syntax correct to force GetFrame() to return a pointer to an element in the struct array. Once I can do this I can implement a large table fix as per normal const arrarys. Whats the correct syntax that keeps the CCS compiler happy ? |
|
|
Ttelmah Guest
|
|
Posted: Sun Jul 15, 2007 7:12 am |
|
|
What you are trying to do, won't work.
The array of structures, will still be a single memory element, and as such will have the original problem. Also, CCS, in v3 compilers (I guess your 'version', is 3.249, since you say '249'), does not support pointers to constants.
Your original solution is the only one that is going to work with normal array accesses. In the past, some functions have been published here to 'automate' the handling of multiple arrays like this, so that a int16 address is passed to the function, and then automatically select the sub-array, anthe required element in this.
The best solution though (only applicable on the 16 chips that support reading from program memory - the 676 is one that does), is to declare the large array, using the #ROM statement at a particular address, and then just access the elements using the 'read_program_memory' function (element number+start address of the array).
This isn't the default behaviour, because the ability only exists on a limited number of PICs.
Best Wishes |
|
|
Pret
Joined: 18 Jul 2006 Posts: 92 Location: Iasi, Romania
|
|
Posted: Mon Jul 16, 2007 12:45 am |
|
|
Ttelmah wrote: | Also, CCS, in v3 compilers (I guess your 'version', is 3.249, since you say '249'), does not support pointers to constants.
| But v4.x supports? As far as i know... it doesnt support either. |
|
|
nurquhar
Joined: 05 Aug 2006 Posts: 149 Location: Redditch, UK
|
|
Posted: Mon Jul 16, 2007 2:53 am |
|
|
My soloution has been to do a copy into ram of the element of required from the const struct with a function. The function handles getting the index to one of several tables, to avoid using a table bigger than 256 bytes that CCS can't handle. I would have thought the overhead of using a function instead of "read_program_memory" would not be much in either code size or execution time. However the function is perhaps it bit more obvious when it comes to code maintenance.
Code: |
typedef struct _sFrame {
uint16 time ; // Time for this output frame to endure, hunderths
uint8 output[MAX_UNITS] ; // The units output values
} sFrame ;
const sFrame film1[] = {
// 1111111 11122222 22222333
// Time 12345678 90123456 78901234 56789012
// ----- -------- -------- -------- --------
{150, 0b00000000, 0b00000000, 0b00000000, 0b00000000 },
{150, 0b10000000, 0b00000000, 0b00000000, 0b00000000 },
.....................
{750, 0b11111111, 0b11111111, 0b11111111, 0b00000000 },
} ;
#if sizeof(film1) > 256
#error film1 table is too big
#endif
const uint16 maxframes1 = sizeof(film1) / sizeof(sFrame) ;
const sFrame film2[] = {
// 1111111 11122222 22222333
// Time 12345678 90123456 78901234 56789012
// ----- -------- -------- -------- --------
{150, 0b11111111, 0b11111111, 0b11111110, 0b00000000 },
{150, 0b11111111, 0b11111111, 0b11111100, 0b00000000 },
{150, 0b11111111, 0b11111111, 0b11111000, 0b00000000 },
................
{150, 0b10000000, 0b00000000, 0b00000000, 0b00000000 },
} ;
#if sizeof(film2) > 256
#error film2 table is too big
#endif
const uint16 maxframes2 = sizeof(film2) / sizeof(sFrame) ;
const sFrame film3[] = {
// 1111111 11122222 22222333
// Time 12345678 90123456 78901234 56789012
// ----- -------- -------- -------- --------
} ;
#if sizeof(film3) > 256
#error film3 table is too big
#endif
const uint16 maxframes3 = sizeof(film3) / sizeof(sFrame) ;
const uint16 maxframes = maxframes1 + maxframes2 + maxframes3;
// Function to access the frames
void GetFrame(uint16 idx, sFrame *f)
{
int i ;
if(idx < maxframes1) {
f->time = film1[idx].time ;
for(i = 0 ; i < MAX_UNITS ; i++) {
f->output[i] = film1[idx].output[i] ;
}
return ;
}
if(idx < (maxframes1 + maxframes2)) {
idx -= maxframes1 ;
f->time = film2[idx].time ;
for(i = 0 ; i < MAX_UNITS ; i++) {
f->output[i] = film2[idx].output[i] ;
}
return ;
}
if(idx < (maxframes1 + maxframes2 + maxframes3)) {
idx -= (maxframes1 + maxframes2) ;
f->time = film3[idx].time ;
for(i = 0 ; i < MAX_UNITS ; i++) {
f->output[i] = film3[idx].output[i] ;
}
return ;
}
}
#endif
|
|
|
|
Ttelmah Guest
|
|
Posted: Mon Jul 16, 2007 3:05 am |
|
|
Yes, V4 allows pointers to constants, in certain specific cases. They started to work in the mid 4.03x releases. However in some cases it generates a lot of code in use, and the syntaxes that work, bear little relationship to those in the manual!.
However the limit on block size in the 16 chips still exists, so the array as shown would still not work.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|