View previous topic :: View next topic |
Author |
Message |
curt2go
Joined: 21 Nov 2003 Posts: 200
|
Pointers...... and LCD driver |
Posted: Thu Jul 16, 2020 5:42 pm |
|
|
I am attempting to clean up some rotten code for a few years ago. I had originally used a function for each font type to draw the letters on the screen.
I am not trying to make a "generic driver" that will take a pointer to the chars and also let me know where to start of the font array I would like to use this time.
The font array is built with a const unsigned int8 array.
An example of how it works:
Code: | const unsigned int8 timesNewRoman[] {
0x00,0x00..................
};
const unsigned int8 anotherFont[] {
0x00,0x00..................
};
sprintf(someCharArray,"Hello World");
buildTheLCD(someCharArray,timesNewRoman);
void buildTheLCD(char *inChar, unsigned int8 *fontInt){
}
|
I am building the font arrays with the same structure, first 2 bytes will be height and width, then each char row will be the same length after that. I am looking at using pointers because I want to pass the different locations of the different fonts into the function. This will make it so I don't have to use different functions that just use the different font arrays directly.
I am having trouble with moving the pointer to the appropriate char start location in the font array. So lets say I want to display the char '!' , so the start of the timesNewRoman array is location [74] . Each char is made of [72] bytes. My pointer math is no good so i thought I would ask. But maybe it's just cause it can't be done this way.
I will also point out I am using the 24EP256GU206 chip and 5.083 compiler. I am trying to save space by using the const for the font arrays. I have a few fonts and they can get pretty large. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 16, 2020 6:41 pm |
|
|
It worked for me. I made a test program with CCS vs.5.094 and ran it.
It displayed 0x12, just like it should. The output window of the MPLAB 8.92
simulator shows this result:
Test program:
Code: |
#include <18F46K22.h>
#device PASS_STRINGS=IN_RAM
#fuses NOWDT
#use delay(internal=4M)
#use rs232(UART1, baud=9600, ERRORS)
void buildTheLCD(char *ptr)
{
printf("%x \r", *ptr);
}
//--------------------------------
const unsigned int8 timesNewRoman[] = {0x12, 0x34};
const unsigned int8 anotherFont[] = {0x56, 0x78};
//=================================
void main()
{
buildTheLCD(timesNewRoman);
while(TRUE);
}
|
|
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Thu Jul 16, 2020 6:56 pm |
|
|
Yes, i do agree. I can get the first line of chars as well. But after that , things go haywire.
Each char has 72 bytes, chars are from 32 to 128. At least for the first font that I am rebuilding. The bytes per char will obviously vary based on a few things.
Or even let's say I want to start the pointer at timerNewRoman[0] + 346; that's what is not working properly. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 16, 2020 7:09 pm |
|
|
In that case I think you have to use rom pointers. Declare the data as 'rom'
not 'const'. |
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Thu Jul 16, 2020 7:26 pm |
|
|
I did try that as well. Unless I am doing something really dumb, which probably is the case. I will give it another shot.
Gave it another shot. Found that I was not using the rom in the function as well.
Why does it not work with const? Its weird. |
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Thu Jul 16, 2020 8:04 pm |
|
|
It also takes a very long time , instruction wise to run it in ROM. like 20 times longer. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Jul 16, 2020 10:19 pm |
|
|
Quote: | Why does it not work with const? Its weird. |
Const data has overhead bytes at the start of the data.
I made two test programs. Printf ran slow, so I changed it to putc() in
each case. I ran both in MPLAB vs. 8.92 simulator with the simulator
frequency set to 4 MHz to match the #use delay() statement in each case.
I put a breakpoint on the while(TRUE) statement in each program.
Then I clicked on the "Run" arrow toolbar button in MPLAB.
The 'const' program ran in 55 usec, and the 'rom' program ran in 73 usec.
const program:
Code: | #include <18F46K22.h>
#device PASS_STRINGS=IN_RAM
#fuses NOWDT
#use delay(internal=4M)
#use rs232(UART1, baud=9600, ERRORS)
void buildTheLCD(char *ptr)
{
putc(*ptr);
}
//--------------------------------
const unsigned int8 timesNewRoman[] = {0x41, 0x42};
//const unsigned int8 anotherFont[] = {0x56, 0x78};
//=================================
void main()
{
buildTheLCD(timesNewRoman); // Will display the letter 'A' (0x41)
while(TRUE);
}
|
rom program:
Code: | #include <18F46K22.h>
#use delay(internal=4M)
#use rs232(baud=9600, UART1, ERRORS)
void buildTheLCD(rom *ptr)
{
putc(*ptr);
}
//--------------------------------
rom unsigned int8 timesNewRoman[] = {0x41, 0x42, 0x43, 0x44, 0x45, 0x46};
//=====================
void main()
{
buildTheLCD(timesNewRoman + 4); // Will display the letter 'E' (0x45)
while(TRUE);
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19535
|
|
Posted: Fri Jul 17, 2020 1:29 am |
|
|
The key thing here really is TANSTAAFL.....
If you access a variable at a fixed location in RAM, the code can read it in a
single instruction. Do it via a 'pointer', and suddenly perhaps a dozen
instructions are needed for the same access. Even worse, put it in ROM,
and the instructions needed for access 'shoot up' (the PIC is one of the
very few processors where the ROM and RAM are in separate memory
spaces, and there is a relatively high overhead involved in reading a byte
from the program memory...).
PCM is showing you how to do this with rom pointers (note the rom *),
and this can be made to work well, but it does come at a cost in performance.
That the pointers have to change is because of the two memories being
in difference spaces. So there is an 'address 0' in ROM, and a second
'address 0' in RAM. The code has to be told to switch to the second memory
space. The exceptions to this on the PIC are:
1) String arrays stored in ROM. The option 'PASS_STRINGS=IN_RAM',
allows the compiler to automatically 'virtualise' such ROM access into
RAM, using a small buffer. If your font declarations could be changed to
character arrays, this could be used.
2) PIC24/30/33's where the option 'PSV' can be used, to create a
'window' space between the ROM and the RAM. Downside is is costs
storage space (only stores 2 bytes per instruction in this mode). However
a powerful feature of these more complex chips....
So having a pointer based ROM font array is going to cost performance.
You will have to make the decision whether this is acceptable. |
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Fri Jul 17, 2020 7:29 am |
|
|
You guys are awesome. I have been working with PICs for over 20 years now and still don't know a fraction of you guys. Thank you and keep up the good work.
I am going to look into the 'PSV' mode.
Because this is a 480x320 lcd driver, each char is a lot of pixels, so speed is a big issue.
*** edit****
Code: | void buildTheLCD(char *ptr)
{
putc(*ptr);
}
//--------------------------------
const unsigned int8 timesNewRoman[] = {0x41, 0x42};
//const unsigned int8 anotherFont[] = {0x56, 0x78};
//=================================
void main()
{
buildTheLCD(timesNewRoman); // Will display the letter 'A' (0x41)
while(TRUE);
} |
In this scenario, I increment through timesNewRoman in the buildTheLCD(char *ptr) function. That was where I was getting hung up with longer arrays. It seemed as though the pointer would only increment to around 48.
I originally was trying to pass the buildTheLCD function the location of the timesNewRoman start, so then I could just increment through it to find the bytes i needed in the timesNewRoman array. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9240 Location: Greensville,Ontario
|
|
Posted: Fri Jul 17, 2020 5:37 pm |
|
|
Silly comment
you've got an array of 96 characters, each needing 72 bytes which is an array 6912 bytes long
..so to get to the 'bit pattern' of the 4th character, you'd be 4 * 72 or 288 bytes offset from the start ?
Shouldn't you be using unsigned int16 for the 'position' or actual 'element' to access the bit pattern data ? 'char' is 0-255.
Maybe I'm looking at this all wrong, it's hot up here, I'm 67 and win7 taskbar 'magically' changed the colour of the taskbar....grrrrrrr |
|
|
curt2go
Joined: 21 Nov 2003 Posts: 200
|
|
Posted: Wed Jul 22, 2020 6:01 pm |
|
|
Yes for sure an INT16 is needed. |
|
|
|