View previous topic :: View next topic |
Author |
Message |
gaugeguy
Joined: 05 Apr 2011 Posts: 301
|
Large Array |
Posted: Tue Aug 07, 2018 1:50 pm |
|
|
So I am using a PIC24FJ1024GA606 to drive a 240x320 display and things are working well. I am now trying to add an image to display on boot up and having problems.
The image array is 16 bit data at 240 x 106 pixel size as a one dimensional array.
I created a test program that does little more than include the header file and the compiler locks up. I have tried versions 5.075 and 5.080.
Code: |
#include <IMAGE-TEST.h>
#include <stdint.h>
#include <splash_240x106.h>
#ZERO_RAM
void main()
{
output_b(0);
output_b(splash_240x106[0]);
while(TRUE)
{
//TODO: User Code
}
|
The array is defined as
Code: |
const uint16_t splash_240x106[] = {0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,
...
0x0000,0x0000,0x0000,0x0000,0x0000};
|
If I delete out the center of the array so it is a very small size then it will compile.
Any ideas? |
|
|
elcrcp
Joined: 11 Mar 2016 Posts: 62 Location: izmir / Turkey
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19457
|
|
Posted: Wed Aug 08, 2018 12:55 am |
|
|
The basic size limit in the thread pointed to above, disappeared with later compilers. Still exists to some extent with PIC16's, but doesn't really apply to the PIC24.
Build it as a ROM array, not a const array.
ROM uint16_t array[] = {
This is basically exactly the same (still an array built in the ROM), but adds a tiny bit of code to allow pointers to be constructed. However key is that it removes the compiler having to scan the array at build time, to see if it may contain strings (with a const array these can be passed in RAM using #device PASS_STRINGS=IN_RAM). The extra compiler testing for this causes problems when arrays get over a few thousand elements. Yours is going to be 25440 elements!...
Will use 5% of your ROM. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 301
|
|
Posted: Wed Aug 08, 2018 8:02 am |
|
|
Thanks. That got me almost there.
Using ROM did get my example to compile and quit locking up. The next problem was my actual program has a bootloader in the top page of ROM and that is where the compiler was insisting on putting this large array.
I am trying to force it to use a lower ROM segment but I do not know quite how to get it structured properly.
Code: |
#ROM int16 0x70000 = { ... }
|
puts the data where I want, but is not setting up as an array to get accessed by code.
I am playing around with
Code: |
uint16_t splash_240x106[];
#locate splash_240x106 = 0x70000
|
but that is not right since it does not have the extra code needed to access the array.
I will keep trying some other ideas and report back. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19457
|
|
Posted: Wed Aug 08, 2018 10:44 am |
|
|
Two routes:
First, Just reserve where the bootloader is.
If you tell it the area is used by a code block, it won't put the rom constants there.
So if the top of the memory was 0x7FFFF
#ORG 0x78000, 0x7FFFF {}
Would say that the top 0x8000 bytes was unavailable.
Or build your main code with the end defined. So if you have (in front of loading the code):
#org 0, 0x77FFF
The code will be built not using the same area.
The second is really the 'correct' way to do this. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 301
|
|
Posted: Wed Aug 08, 2018 12:44 pm |
|
|
CCS sent me a new pcd.dll file that fixed the problem with const hanging up the complier. Got my splash image showing up nicely.
The new issue is the time it takes. A lot of data to get sent out.
I am working on using Program Space Visibility to try and speed up the process. I don't think CCS has any routines for using PSV but I should be able to get some register access and assembly routines working.
Thanks for the help and support. I will report back how things turn out and I will monitor this thread for any other clever ideas. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19457
|
|
Posted: Wed Aug 08, 2018 1:19 pm |
|
|
#device PSV=16
However there is a big caveat. Only the low 16bits of each instruction appears. The line above makes rom and const reformat the data to be compatible with this.
Quote: |
PSV support for 16-bit PICs has been added:
#device PSV=16
When used, all 'rom' and 'const' keywords are fit into a PSV page of the
program memory, and the contents of the 'rom and 'const' structure/array
are made PSV friendly. 'const' or 'rom' pointers can be assigned to RAM
pointers and still allow access to the data in the program memory.
Example:
#device PSV=16
const char constString[] = "Hello";
const char *constPtr = constString; //constPtr points to program memory in PSV
char *ramPtr = constString; //ramPtr points to program memory in PSV
printf("%s", constPtr);
printf("%s", ramPtr);
|
Key thing throughout (using ROM or RAM) will be the design of your code. Depending on the interface involved you may well be able to have the hardware transmitting while you are fetching the next byte. This will be down to what interface is used and how you layout the code. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9205 Location: Greensville,Ontario
|
|
Posted: Thu Aug 09, 2018 5:35 am |
|
|
re:
The new issue is the time it takes. A lot of data to get sent out.
Have to ask is it 25K or 50K long? Either way it IS a lot of data
I'm assuming this is some kind of LCD screen? If so, they are slow BUT if the driver /module is smart, it should be buffered and have feedback to max out the data transfer.
A clue may be found in the display datasheet...gotta be a chart about speed, refresh rate, etc. It'll be the one we ALL glance at, never read but has the IMPORTANT details in......
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19457
|
|
Posted: Thu Aug 09, 2018 6:27 am |
|
|
Also just worth adding you can't use PSV for this. PSV supports just 32KB. Your array is 50KB (25000 16 bit entries). |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 301
|
|
Posted: Thu Aug 09, 2018 8:12 am |
|
|
320x240 color TFT with 16bit parallel interface
The CCS PSV=16 only works if every const declaration totals to less than 32k bytes so it can fit in one segment.
I am going to try getting PSV to work by handling the page transition and if that does not work then use program memory read in assembly to optimize the speed. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19457
|
|
Posted: Thu Aug 09, 2018 9:09 am |
|
|
Seriously you should be able to write 50KB in a small fraction of a second using a parallel interface.
On PSV, you need to do more than handling the transition yourself. Everything you declare you want to use with PSV, has to be declared as 16bits to the instruction to word. So you are going to have to change the whole array declaration to be this format. However it is going to save 'peanuts' on time. If it is taking any noticeable time, then something is badly wrong with the write logic. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 301
|
|
Posted: Thu Aug 09, 2018 2:43 pm |
|
|
I certainly can, and I do have things working well now using table reads. I am splitting up the image send into small time slices to coincide with other time sensitive loops I have going on at the same time.
One of the challenges of using this PIC is that a 16 bit color image does not fit into the RAM on the chip. My full project is currently only using about 20% of the ROM and less than half of the RAM.
We have also used both the PIC24FJ256DA206 and PIC32MZ2048EFG064 to drive this TFT but this project was more cost sensitive and the PIC24FJ1024GA606 costs much less than either of them.
Thanks for all of the assistance. |
|
|
gaugeguy
Joined: 05 Apr 2011 Posts: 301
|
|
Posted: Fri Aug 10, 2018 8:10 am |
|
|
Ok, another question related to the image file.
Currently CCS packs the 16 bit table with the first 2/3 of it in the low 16 bits of each 24 bit ROM location and the top 1/3 of it split into the top 8 bits of the 24 bit ROM. I would like the entire table to be put into memory using only the low 16 bits of each 24 bit ROM location.
I don't know if there are any compile commands that could for this. I tried just making the table longer, appending zeroes to the end so that these extra zeroes would get packed into the top 8 bits but I get a segment or the program is too large.
My original array is 25440 16bit words which gets packed into 16960 24 bit words. When I increase the array with zero padding to 38160 16 bit words I expect it to get packed into 25440 24 bit words, which should fit into a single segment, which I believe is 32768 24 bit words. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9205 Location: Greensville,Ontario
|
|
Posted: Fri Aug 10, 2018 9:37 am |
|
|
Hmm.. what happens if you declare your data as 24 bit words where the first 8 bits are all zeros, then your 16 bit data. That way the array should be 25440 in length.
There would be no 'packing' of data.. each 24bit ROM location would be ONE entry of your table.
just thinking out loud here.
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19457
|
|
Posted: Sun Aug 12, 2018 12:53 am |
|
|
#ROM allows you to do this.
Code: |
#ROM 0xxxxxx = {
0x00345678, 0x00456789, 0x00567890, 0x00678901, 0x00345678, 0x00456789, 0x00567890, 0x00678901,
0x00345678, 0x00456789, 0x00567890, 0x00678901, 0x00345678, 0x00456789, 0x00567890, 0x00678901,
0x00345678, 0x00456789, 0x00567890, 0x00678901, 0x00345678, 0x00456789, 0x00567890, 0x00678901,
0x00345678, 0x00456789, 0x00567890, 0x00678901, 0x00345678, 0x00456789, 0x00567890, 0x00678901
}
|
Puts 24bit values into each word at the specified address.
The fastest way to read this is to use a RAM buffer. If (for instance), you used a 256 entry (1KB) RAM buffer and then use 'read_program_memory' to get the 256 word 'page' you require into this, it codes this as a block read.
Reading 25K entries 'block by block' like this, and retrieving the values from RAM takes less than 1/4 second. |
|
|
|