|
|
View previous topic :: View next topic |
Author |
Message |
thgood
Joined: 14 Oct 2003 Posts: 1
|
Phrase Strings stored in rom |
Posted: Tue Oct 14, 2003 10:30 am |
|
|
Hello,
I want to index into a large number strings stored in ROM. Each string will be 32 characters long. There will be about 50 strings.
I have run into problems using the built in CCS arrays. What is the best alternative for coding this up and accessing the strings randomly?
Thanks
Tom |
|
|
Ttelmah Guest
|
Re: Phrase Strings stored in rom |
Posted: Tue Oct 14, 2003 10:45 am |
|
|
thgood wrote: | Hello,
I want to index into a large number strings stored in ROM. Each string will be 32 characters long. There will be about 50 strings.
I have run into problems using the built in CCS arrays. What is the best alternative for coding this up and accessing the strings randomly?
Thanks
Tom |
What chip?.
The answer does differ massively (especially since the latter/larger chips will allow two characters to be stored in each ROM location).
Are the strings genuinely fixed length, or is the 32 character figure a maximum?.
Best Wishes |
|
|
Guest
|
Re: Phrase Strings stored in rom |
Posted: Tue Oct 14, 2003 11:45 pm |
|
|
Ttelmah wrote: |
What chip?.
The answer does differ massively (especially since the latter/larger chips will allow two characters to be stored in each ROM location).
Are the strings genuinely fixed length, or is the 32 character figure a maximum?.
Best Wishes |
I am using a 16F877
The strings are actually variable length and will be displayed on an lcd screen... I would like to display a different message each day.
Thanks
Tom |
|
|
Ttelmah Guest
|
Re: Phrase Strings stored in rom |
Posted: Wed Oct 15, 2003 3:02 am |
|
|
Anonymous wrote: | Ttelmah wrote: |
What chip?.
The answer does differ massively (especially since the latter/larger chips will allow two characters to be stored in each ROM location).
Are the strings genuinely fixed length, or is the 32 character figure a maximum?.
Best Wishes |
I am using a 16F877
The strings are actually variable length and will be displayed on an lcd screen... I would like to display a different message each day.
Thanks
Tom |
Um.
Realistically, it'd be much easier, using the 18F452...
You might want to consider making the messages 'fixed length', since otherwise the overhead of knowing where the messages start/end, becomes significant.
If you do a search back in the archives, you will find a number of posts about how to store two characters into each location in the 18F, (basically the storage locations in ROM, are 14bit, and so if the characters are only 7bit ASCII, you can combine two characters into each locations).
If you have a conversion routine like this, then you can simply rely on each message starting 16 locations from the last.
Then you can use a simple 'identifier' for the messages.
Hence:
#define M_HELLO (0)
#define M_WORLD (1)
etc...
#define MESSAGE_LOCN (0x1CE0)
#ROM MESSAGE_LOCN = {
"H"+"e"<<7,"l"+"l"<<7,"o",0,0,0,0,0,0,0,0,0,0,0,0,0,
"W"+"o"<<7,"r"+"l"<<7,"d",0,0,0,0,0,0,0,0,0,0,0,0,0
}
static char buffer[33];
char * get_message(int message_num) {
int16 location;
int8 count=0;
int16 value;
location=MESSAGE_LOCN+((int16)message_num*16);
do {
value=read_program_eeprom(location);
buffer[count++]=value & 0x7F;
buffer[count++]=value >> 7;
} while (count<32 && value!=0);
}
Now, I wouldn't want to guarantee the syntax of what I have typed (I haven't tested it...), but basically every message is stored in just 16 bytes, and can be up to 32 characters in length. Each storage location is holding two characters, by shifting the second one left seven bits. The remainder of each 16 character block, is filled with zeros (as is the top 'half' of a location if it only holds one character. The 'message fetcher', is called with the symbolic 'name' of the message to fetch, and returns a null terminated string containing the message (basically the routine will copy every character, till it gets a 'word' which is zero, or it hits the end of the 16 bytes. Since nothing is ever written to location 33 in the buffer array, it will remain initialised as zero (the 'static' definition ensures this is done).
Then the 'fetcher' can be called as:
printf("%s %s",get_message(M_HELLO),get_message(M_WORLD));
Now the advantage of this, is that fifty messages, would fit in just 800 words of storage (0x320), and you don't have any overhead involved in storing 'locations' to find the messages (which would happen if the lengths are variable).
It is (of course), a 'trade_off' between the waste of ROM, by using 16 characters for each, versus the efficiency of storing the codes this way.
There are other compromises that can be used to improve this. I have used a similar approach in the past, using a message table in 8 character 'lumps'. The declarations remain basically the same, except I use the top 'bit' of the message number declaration to signify that the message is a 'long message'.
#define M_HELLO (0)
#define M_WORLD (1)
#define M_LONGMESSAGE (2+0x80)
#define M_NEXTSHORT (4) //Note two 'slots' used by the long message.
Then the 'fetcher' tests the high bit of the incoming message number, and if it is zero, starts as shown, but only counts up to 16, and the declarations for the messages in this table are only justified to 8 words long, but if the top bit is set, counts to 32 bytes, and uses two message 'slots' for the long message. The declaraction in the ROM, then becomes:
#ROM MESSAGE_LOCN = {
"H"+"e"<<7,"l"+"l"<<7,"o",0,0,0,0,0,
"W"+"o"<<7,"r"+"l"<<7,"d",0,0,0,0,0,
"T"+"h"<<7,"i"+"s"<<7," "+"i"<<7,"s"+" "<<7,"a"+" "<<7,"l"+"o"<<7,
"n"+"g"<<7," "+"m"<<7,"e"+"s"<<7,"s"+"a"<<7,"g"+"e"<<7,0,
0,0,0,0,
"N"+"e"<<7,"x"+"t"<<7,0,0,0,0,0,0
}
Also remember with this method that the message 'slots' are only 8 characters long, so this becomes the multiplier in the position calculation, instead of 16.
This has the advantage of making really quite efficient use of the ROM, and still being quick.
In the past, when needing to input a lot of messages like this, I wrote a simple VB application to take ordinary strings, and generate the definitions from them. I can't find this at the moment, but it is a fairly simple thing to code.
Best Wishes |
|
|
burnsy
Joined: 18 Oct 2003 Posts: 35 Location: Brisbane, Australia
|
StringToRom14.exe |
Posted: Sat Oct 18, 2003 6:21 pm |
|
|
here's a copy of my reply in a similar discussion....
/*
This might help. I will try and remember how it works....
I needed to to store strings to display on an lcd. All my strings were of fixed length (16 bytes).. If each character was only 7bits long, you fit two in each word. I would store them like this..
// Note Exchange2
#define LCDMSG_PWRUPMSG0 0x00
#rom 0x0100={0x104E,0x37F4,0x32A0,0x22F8,0x31E8,0x30EE,0x33E5,0x1920}
// V1.58
#define LCDMSG_PWRUPMSG1 0x01
#rom 0x0108={0x1020,0x1020,0x1056,0x18AE,0x1AB8,0x1020,0x1020,0x1020}
// INSERT NOTES
#define LCDMSG_INSERTN 0x02
#rom 0x0110={0x1020,0x24CE,0x29C5,0x2954,0x104E,0x27D4,0x22D3,0x1020}
Each msg would have a number, and a fixed starting address. All you do is calc the starting address to retrieve the string.
eg
void
wr_line2lcd(uchar x)
{
uchar u;
uint t;
/* wr lcd direct with byte, with bytes stored in flash */
/* calc offset to msg (16 bytes per msg) */
t = x;
t <<= 3;
t += LCD_MSGS; /* offset to table in rom */
/* copy each byte to lcd_putchar() */
for (u = 0 ; u < 0x10 ; u++ )
{
/* first byte */
x = read_flash(t + u,0);
lcd_putchar(x);
/* second byte */
x = read_flash(t + u,1);
lcd_putchar(x);
}
}
if you want fixed string lenghts or not, here is a handy VB utility I wrote that will allow you to type in a string and it will convert the string into ROM = (xxxxh,xxxxxh....) code for you. Follow the link.
http://home.iprimus.com.au/jtek/pic/stringtorom14.exe
hope this helps
*/ _________________ This is the last code change until its ready.... |
|
|
|
|
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
|