| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| adcor 
 
 
 Joined: 21 Feb 2008
 Posts: 31
 
 
 
			    
 
 | 
			
				| Handling big data array in ROM |  
				|  Posted: Wed Dec 30, 2020 6:52 pm |   |  
				| 
 |  
				| I am using a dspic33ch128mp505 with 128k flash to display on a ST7735 GLCD 128x160 resolution (compiler 5.097) On full resolution the data takes 20.5k pixels x 16bit space.It is declared as ROM unsigned int16 array[] , it compiles fine but the uP is resetting in a loop. (some memory violation probably).
 If I drop the resolution to 70x110 (~8k pixels), everything is ok.
 I tried to place the data array use the #org 0x1000 after the IVT  but  no matter the size is the array I have compiler errors:
 
 Fonts.c:163:6:  Info#300  More info:   Segment at 00000-0FFFE (0000 used)
 Fonts.c:163:6:  Info#300  More info:   Segment at 10000-15EFE (0000 used)
 Fonts.c:163:6:  Info#300  More info:   Attempted to create: 01000-00000  for #org
 Fonts.c:163:6:  Error#126  Invalid ORG range
 
 Is any way I can fit this amount of data in the rom space?
 thanks
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu Dec 31, 2020 2:38 am |   |  
				| 
 |  
				| The way I have done a large data block, is to directly import it, and not access it as a 'variable', but access it directly.
 
 So:
 
  	  | Code: |  	  | #IMPORT(FILE=.\Logo.bin, RAW, LOCATION=where_stored, BPI=3)
 //This physically imports the file, and sets 'where_stored' as the
 //address where it is stored.
 
 //Then I read the data from this with:
 //routine to give access to ROM stored data - used for bitmap
 union access {
 unsigned int32 whole;
 unsigned int8 bytes[4];
 };
 
 BYTE getval(unsigned int32 locn, unsigned int32 index)
 {
 unsigned int32 calc;
 union access rdg;
 unsigned int8 bval;
 //Now I need to calculate the actual cell I need to read, fetch this
 //then extract the byte
 calc=(index/3)*2;
 //This gives the actual cell offset from locn.
 read_program_memory(locn+calc, &rdg, 4);
 //Gives the 32bit value containing the byte required.
 bval=index % 3;
 //Now gives the byte number required
 return rdg.bytes[bval];
 //return the physical byte
 }
 
 | 
 
 This is called with 'where_stored', and the index of the byte required.
 
 This is efficient since it stored 3 bytes per instruction (BPI=3).
 
 This merrily handles over a 100K data array for me.
 
 There is a very large 'caveat' in what you were doing. It may be taking
 much more ROM than you expect. A 16bit value stored into the ROM space
 has to be 'word aligned'. So each 16bit value will be using a whole 3byte
 instruction word. A chip with 128K of program memory only has about
 44000 words of memory. Using over 20000 of these up on a single
 array may well give problems.... Using byte alignment as I show, uses
 only 66% of the space.
 |  |  
		|  |  
		| adcor 
 
 
 Joined: 21 Feb 2008
 Posts: 31
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 01, 2021 3:40 am |   |  
				| 
 |  
				| Thanks for your solution, I'll try it. So, index variable is total number of bytes from the raw file and basically in 8 bytes used in ROM I can retrieve 3 x int16 data.
 I could also try to boost the ROM to 512k chip, or to split the big bitmap file into smaller ones to see if the compiler maps them differently.
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 01, 2021 3:56 am |   |  
				| 
 |  
				| getval automatically handles the indexing. If you look it calculates the physical ROM address by taking the 'offset' it is given and dividing this
 by three and multiplying by 2 (to give a 'byte' based address. It then
 extracts the needed byte from this address.
 
 So if you call getval(where_stored,0) it returns the first stored byte
 setval)where_stored,1), the second byte, getval(where_stored,2), the third
 byte, and getval(where_stored,3) gets the third byte. Since the index and
 address are int32, it can handle any number of bytes that can be stored.
 |  |  
		|  |  
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 01, 2021 6:28 am |   |  
				| 
 |  
				| Assuming the bitmaps are 'fonts for alphabets', you could split the array into 'uppercase' and 'lowercase' arrays. I did this decades ago for a 'kbd code converter' project in order to fit everything into a 16C84. Whenever I see 'fonts and bitmaps... I just see a LOT of typing involved and even more misstyping.....
  |  |  
		|  |  
		| adcor 
 
 
 Joined: 21 Feb 2008
 Posts: 31
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 01, 2021 9:29 pm |   |  
				| 
 |  
				| Thanks, it is a picture in my case 128w x 151h pixels. I tried the #import way but it draws some garbage, sort of horizontal
 bands.
 Since I have an int16 for each pixel, it means I have 256 bytes per row, or 38656 bytes in the raw file (bmp file was stripped from its header).
 Below is how I declared the function to map the pixels. Am I doing something wrong?
 
 
  	  | Code: |  	  | #IMPORT(FILE=.\test_16.raw, RAW, LOCATION=0x1000, BPI=3) //This physically imports the file, and sets 'where_stored' as the
 //address where it is stored.
 
 //Then I read the data from this with:
 //routine to give access to ROM stored data - used for bitmap
 union access {
 unsigned int32 whole;
 unsigned int8 bytes[4];
 };
 
 BYTE getval(unsigned int32 locn, unsigned int32 index)  //max index = (128x151x2)=38656 bytes
 {
 unsigned int32 calc;
 union access rdg;
 unsigned int8 bval;
 //Now I need to calculate the actual cell I need to read, fetch this
 //then extract the byte
 calc=(index/3)*2;
 //This gives the actual cell offset from locn.
 read_program_memory(locn+calc, &rdg, 4);
 //Gives the 32bit value containing the byte required.
 bval=index % 3;
 //Now gives the byte number required
 return rdg.bytes[bval];
 //return the physical byte
 }
 
 void display_import() {
 unsigned int8 hi,lo,buff,col,row;
 unsigned int16 color;
 unsigned int32 pos;
 for (pos=0;pos<38656;pos++) {
 buff=getval(0x1000,pos);
 if (pos%2 == 0) lo=buff;
 else {
 hi=buff;color=make16(hi,lo);
 row=pos/256;
 col=pos%256;
 drawPixel(col, row, color);}
 }
 }
 
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun Jan 03, 2021 9:19 am |   |  
				| 
 |  
				| Right, first question. Are you sure your 'raw' file format is right. This needs to be basic binary data containing the array contents LSBMSBLSBMSBetc.. 
 I'd test first, by doing a basic read of a few elements and comparing with
 what the int16 array was returning.
 
 Also use where_stored as I show rather than trying to force an address.
 This allows more flexibility on where the compiler places the data. Better
 for memory usage.
 
 Now honestly, I'd encapsulate a array_read function. So, something like:
 
  	  | Code: |  	  | #IMPORT(FILE=.\test_16.raw, RAW, LOCATION=where_stored, BPI=3)
 //This physically imports the file, and sets 'where_stored' as the
 //address where it is stored.
 
 //Then I read the data from this with:
 //routine to give access to ROM stored data - used for bitmap
 union access {
 unsigned int32 whole;
 unsigned int8 bytes[4];
 };
 
 BYTE getval(unsigned int32 locn, unsigned int32 index)  //max index = (128x151x2)=38656 bytes
 {
 unsigned int32 calc;
 union access rdg;
 unsigned int8 bval;
 //Now I need to calculate the actual cell I need to read, fetch this
 //then extract the byte
 calc=(index/3)*2;
 //This gives the actual cell offset from locn.
 read_program_memory(locn+calc, &rdg, 4);
 //Gives the 32bit value containing the byte required.
 bval=index % 3;
 //Now gives the byte number required
 return rdg.bytes[bval];
 //return the physical byte
 }
 
 #define ROW_SIZE 256
 
 unsigned int16 read_from(int32 row, int col)
 {
 //Using int32, for the row, so I can do the maths in this variable
 unsigned int16 rval;
 row*=ROW_SIZE;
 row+=col;
 //Now have index required/2 in 'row'
 row*=2;
 rval=make16(getval(where_stored,row+1), getval(where_stored,row));
 return rval;
 }
 
 void display_import() {
 unsigned int8 col,row;
 unsigned int16 color;
 for (row=0;row<151;row++)
 {
 for (col=0;col<128;col++)
 {
 color=read_from(row,col);
 drawPixel(col, row, color);
 }
 }
 }
 
 | 
 |  |  
		|  |  
		| adcor 
 
 
 Joined: 21 Feb 2008
 Posts: 31
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jan 04, 2021 3:47 pm |   |  
				| 
 |  
				| Thanks Mr TT, I made some progress with your math. For a full screen resolution I do have some sort of image showing somewhere in the middle and squeezed... However I wanted to get some grasp on this issue and create a small 4 rows hex data F8 00 ( blue color). Import address is 0x1000, but it proves it does not matter where I set it, the lst result is the same, it starts at 015C54 for some reason. Could be a compiler issue?
 
 
  	  | Code: |  	  | 015C54: F800 0000 00F8 00F8 F800 0000 00F8 00F8    ................ 015C5C: F800 0000 00F8 00F8 F800 0000 00F8 00F8    ................
 015C64: F800 0000 00F8 00F8 F800 0000 00F8 00F8    ................
 015C6C: F800 0000 00F8 00F8 F800 0000 00F8 00F8    ................
 015C74: F800 0000 00F8 00F8 F800 0000 00F8 00F8    ................
 015C7C: F800 0000 00F8 00F8 F800 0000 00F8 00F8    ................
 | 
 |  |  
		|  |  
		| PCM programmer 
 
 
 Joined: 06 Sep 2003
 Posts: 21708
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jan 04, 2021 5:45 pm |   |  
				| 
 |  
				| Why not try importing at 0x16000 ? |  |  
		|  |  
		| adcor 
 
 
 Joined: 21 Feb 2008
 Posts: 31
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jan 04, 2021 6:10 pm |   |  
				| 
 |  
				| At 0x16000 I think there is some memory violation...the chip is resetting in a loop. |  |  
		|  |  
		| temtronic 
 
 
 Joined: 01 Jul 2010
 Posts: 9589
 Location: Greensville,Ontario
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jan 04, 2021 6:37 pm |   |  
				| 
 |  
				| Hmmm...maybe 'something' has protected banks of memory and 15c54 is the first available address ?? Try a very, very small program (org and store, main() loops forever) and see what happens ??
 |  |  
		|  |  
		| adcor 
 
 
 Joined: 21 Feb 2008
 Posts: 31
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Mon Jan 04, 2021 9:18 pm |   |  
				| 
 |  
				| No luck, I compiled this program where "test1_16.raw" was either 1kB or 16 bytes size and the compiler puts the data in the #015xxx address area for some reason. However I changed the processor to 33CH512MP505 version and the ROM address moved to # 057EF4. 
 
  	  | Code: |  	  | #include <33CH128MP505.h> #device ADC=12
 #IMPORT(FILE=.\test1_16.raw,RAW,LOCATION=0x1000,BPI=3)
 
 #use delay(internal=180000000)
 
 #FUSES NOWDT                    //No Watch Dog Timer
 #FUSES CKSFSM                   //Clock Switching is enabled, fail Safe clock monitor is enabled
 #FUSES S1_CKSFSM                //Slave core Clock Switching is enabled, fail Safe clock monitor is enabled
 
 union access {
 unsigned int32 whole;
 unsigned int8 bytes[4];
 };
 
 BYTE getval(unsigned int32 locn,unsigned int32 index)
 {
 unsigned int32 calc;
 union access rdg;
 unsigned int8 bval;
 //Now I need to calculate the actual cell I need to read, fetch this
 //then extract the byte
 calc=(index/3)*2;
 //This gives the actual cell offset from locn.
 read_program_memory(locn+calc,&rdg,4);
 //Gives the 32bit value containing the byte required.
 bval=index%3;
 //Now gives the byte number required
 return rdg.bytes[bval];
 //return the physical byte
 }
 
 #define ROW_SIZE 256
 
 unsigned int16 read_from(unsigned int32 row,unsigned int8 col)
 {
 //Using int32, for the row, so I can do the maths in this variable
 unsigned int16 rval;
 row*=ROW_SIZE;
 row+=col;
 //Now have index required/2 in 'row'
 row*=2;
 rval=make16(getval(0x1000,row+1), getval(0x1000,row));
 return rval;
 }
 
 void test_import() {
 unsigned int8 col,row;
 unsigned int16 color;
 for (row=0;row<4;row++)
 {
 for (col=0;col<128;col++)
 {
 color=read_from(row,col);
 }
 }
 }
 void main()
 {
 setup_timer1(TMR_INTERNAL | TMR_DIV_BY_256, 0);
 setup_adc_ports(sAN0);
 setup_adc(ADC_CLOCK_SYSTEM | ADC_CLOCK_DIV_1 | ADC_WARMTIME_16 | ADC_SHARED_CLOCK_DIV_2 | ADC_SHARED_TAD_MUL_2);
 
 while (1) {
 test_import();
 }
 }
 
 
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19967
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue Jan 05, 2021 3:18 am |   |  
				| 
 |  
				| I don't see anywhere where #import says you can use a location as you are trying to do.
 From the manual:
 
  	  | Quote: |  	  | LOCATION=id - The identifier is made a constant with the start address of the imported data.
 
 | 
 No mention of putting the data at a location with this....
 
 You could put it at a specified location, by having the data at 0x1000 in
 the file, and using RANGE for the import, or probably by using a #ORG
 for the import. By default the compiler places imported data at the top
 of the available memory, to leave as much uninterrupted space as possible.
 This is what you are seeing happen.
 
 Use #import the way I do it.
 |  |  
		|  |  
		| adcor 
 
 
 Joined: 21 Feb 2008
 Posts: 31
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Fri Jan 08, 2021 4:27 pm |   |  
				| 
 |  
				| Thanks MrTT, the only way I could make it work is to look in the lst file to see where the compiler put the ROM data and use that address as starting range as in "locn". There is no correlation between LOCATION=id or RANGE=start:end in import directive and locn from getval(unsigned int32 locn,unsigned int32 index), the compiler is lost in translation.
 |  |  
		|  |  
		| adcor 
 
 
 Joined: 21 Feb 2008
 Posts: 31
 
 
 
			    
 
 | 
			
				| SOLVED -Handling big data array in ROM |  
				|  Posted: Fri Jan 08, 2021 5:46 pm |   |  
				| 
 |  
				| I got it working by not using LOCATION=0x4000 as a physical address interpretation rather as a label  id e.g. LOCATION=ph1 and then use this label into the function retrieving the data from the ROM. Maybe the compiler was confused somehow. Thanks all for support.
 |  |  
		|  |  
		|  |  
  
	| 
 
 | 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
 
 |