I've just gotten into PIC development using a 16F690. All of my development
is
in assembler. I'm putting together a bit-map table for character
generation.
I use the character that I want generated to look up it's bit-map info in
the table.
Since I store the table in program memory, I need a method to index into
the table. App note an556 (see below) recommends using an "retlw K"
instruction
to return the table value. This does work, however, it requires two bytes
per
table entry. Since my table is close to 1k bytes, this consumes an
additional 1k bytes
of program memory.
Has anyone found a better solution?
Thanks,
Mike
Example 1:
.
.
movlw offest
call Table
.
.
Table:
addwf PCL,F ;add offset to pc to generate a computed goto
retlw 'A' ;return the ASCII char A
retlw 'B' ;return the ASCII char B
retlw 'C' ;return the ASCII char C
.
.
The 16F690 has the capability of reading and storing tables as 14-bit
values in PGM memory, rather
than in retlw tables. In that case, your 1K table would require 1K
14-bit words. If your table values will
fit into 14 bits, this is very efficient. To do this in RETLW xx mathod
will require 2K + some overhead.
I'm not sure what your application is , but I have built strain-guage
sensors based on the F876 calibrated
in exactly this way. In this application, pgm space was tight, but the
width of the data needed was only
10 bits, whereas I had 14 bits to work with. What I did was to squeeze
the table length to 5/7 of its size.
Here's how:
Write an algorithm that will read in 5 14-bit words, and pump out 7
10-bit table values. This is because
5 * 14 = 70, and 7 * 10 = 70, so there will be no losses. This algorithm
will be called in order to obtain
the correct 10-bit table value in real time.
When you have decided what needs to be loaded into the table (the
sensor/PIC PCB is subjected to
tests at critical points so a table can be created) then create an
algorithm that takes 7 10-bit values
and squeezes then into 5 14-bit values. When the "1K Table" is done, it
only took 5/7*1024 bytes or
about 732 words
>I've just gotten into PIC development using a 16F690. All of my development
>is
>in assembler. I'm putting together a bit-map table for character
>generation.
>I use the character that I want generated to look up it's bit-map info in
>the table.
>Since I store the table in program memory, I need a method to index into
>the table. App note an556 (see below) recommends using an "retlw K"
>instruction
>to return the table value. This does work, however, it requires two bytes
>per
>table entry. Since my table is close to 1k bytes, this consumes an
>additional 1k bytes
>of program memory.
>Has anyone found a better solution?
>
>Thanks,
>Mike
>
>Example 1:
> .
> .
> movlw offest
> call Table
> .
> .
>Table:
> addwf PCL,F ;add offset to pc to generate a computed goto
>
> retlw 'A' ;return the ASCII char A
> retlw 'B' ;return the ASCII char B
> retlw 'C' ;return the ASCII char C
> .
> .
>
>
>
>
Mike Ervin wrote:
> App note an556 (see below) recommends using an "retlw K"
> instruction to return the table value. This does work,
> however, it requires two bytes per table entry.
No, it requires 1 *word*, which is not = 2 bytes.
Then Bob Axtell wrote :
> The 16F690 has the capability of reading and storing tables
> as 14-bit values in PGM memory, rather than in retlw tables.
> In that case, your 1K table would require 1K 14-bit words.
> If your table values will fit into 14 bits, this is very efficient.
OK, 1 byte in each word of flash.
> To do this in RETLW xx mathod
> will require 2K + some overhead.
This I don't understand. 2K of what ? Words or bytes ?
A RETLW table *also* stores 1 byte in each word of flash...
Now, maybe the table value actualy a 7-bit value ?
As when using 5x7 dot displays ?
In that case you might store 2 table entries in each
14-bit flash word.
Yes, you're right, it does use 1 "word" (14-bits) and not
two bytes (8-bit bytes). I was wondering why I kept losing
the high-order two bits when I used the following
statements in code section:
db 0x80
kept showing up as 0x00. My mistake :-)
I can probably get by with 7x8 characters, so I'll try
squeezing two of those in each program "word" :-)
db 0x7F,...
But I am still not clear on how to access the table data in program
memory without using the "retlw K" instruction.
>From: Jan-Erik Soderholm <.....jan-erik.soderholmKILLspam@spam@telia.com>
>Reply-To: "Microcontroller discussion list - Public." <piclistKILLspammit.edu>
>To: .....piclistKILLspam.....mit.edu
>Subject: RE: [PIC] Better 16F690 Table Lookup Algrorithms?
>Date: Thu, 23 Mar 2006 22:27:26 +0100 (MET)
>
>
>Mike Ervin wrote:
> > App note an556 (see below) recommends using an "retlw K"
> > instruction to return the table value. This does work,
> > however, it requires two bytes per table entry.
>
>No, it requires 1 *word*, which is not = 2 bytes.
>
>
>Then Bob Axtell wrote :
>
> > The 16F690 has the capability of reading and storing tables
> > as 14-bit values in PGM memory, rather than in retlw tables.
> > In that case, your 1K table would require 1K 14-bit words.
> > If your table values will fit into 14 bits, this is very efficient.
>
>OK, 1 byte in each word of flash.
>
> > To do this in RETLW xx mathod
> > will require 2K + some overhead.
>
>This I don't understand. 2K of what ? Words or bytes ?
>A RETLW table *also* stores 1 byte in each word of flash...
>
>
>Now, maybe the table value actualy a 7-bit value ?
>As when using 5x7 dot displays ?
>In that case you might store 2 table entries in each
>14-bit flash word.
>
>Regards,
>Jan-Erik.
>
>
>
>Mike Ervin wrote:
>
>
>>App note an556 (see below) recommends using an "retlw K"
>>instruction to return the table value. This does work,
>>however, it requires two bytes per table entry.
>>
>>
>
>No, it requires 1 *word*, which is not = 2 bytes.
>
>
>Then Bob Axtell wrote :
>
>
>
>>The 16F690 has the capability of reading and storing tables
>>as 14-bit values in PGM memory, rather than in retlw tables.
>>In that case, your 1K table would require 1K 14-bit words.
>>If your table values will fit into 14 bits, this is very efficient.
>>
>>
>
>OK, 1 byte in each word of flash.
>
>
>
>>To do this in RETLW xx mathod
>>will require 2K + some overhead.
>>
>>
>
>This I don't understand. 2K of what ? Words or bytes ?
>A RETLW table *also* stores 1 byte in each word of flash...
>
>
>
2K of code words. a " RETLW XX" is a full code word. He said that
he needed two bytes for each table entry. If he did it using RETLW XX
he would need 2K code words, plus the overhead of "addwf pcl,f". Right?
>Now, maybe the table value actualy a 7-bit value ?
>As when using 5x7 dot displays ?
>In that case you might store 2 table entries in each
>14-bit flash word.
>
>
er, well it was never made clear how wide his table entry was. So
by example, I showed him how to compress 10bit table entries so
that less code space could be taken.
Ok,
I've concluded that there is no "easy" way to set up a bit-map table using
"program memory".
So, I've done what the app note an556 suggests. Here's a snippet of the
code that I've
put together for a table lookup. It requires twice the memory necessary,
but it does get
the job done :-) And there's a LOT of processing necessary to extract each
data byte
from "program memory".
Are there any other PIC processors that would be better suited for this
application?
It would be interesting to see how a "c" program handles this :-)
WorkW res 2 ; work variable
ASCIIch res 1 ; ASCII character to process
ASCIImo res 1 ; ASCII bit map offset
ASCIIbm res 8 ; 8x8 bit ASCII character bit map
PROG CODE ; Set the start of code from 16f690.lkr script
; ASCII Character table processing. This routine determines the progam
; memory address and offset from that address to extract the 8-byte bit
; map definition of the ASCII character.
;
; Inputs: ASCIIch = the character to process
;
; Outputs: ASCIIbm[0]...ASCIIbm[7] contains the character map
ASCIIbitMap
clrf ASCIImo ; set bit map offset to zero
call bitMapWork
movwf ASCIIbm+0
On Mar 23, 2006, at 11:44 PM, Michael L. Ervin wrote:
> Are there any other PIC processors that would be better
> suited for this application?
The PIC18 family has byte-addressable program memory and the TBLRD
(table read) instruction, which should help quite a bit
> It would be interesting to see how a "c" program handles this :-)
>
A C program can handle the algorithms fine. C handles multiple
memory spaces less well. Whether the compiler can produce
useful code out of something readable is another matter!
I think your code has quite a bit of room for improvement.
Have you looked here:
char bitMapWork(char asciichar, char row)
{
char * (bitmapentry)(void); /* pointer to a function */
bitmapentry = 8 * asciichar; /* compute offset to start */
bitmapentry += row; /* Add in the row offset */
bitmapentry += TABLESTART; /* table beginning */
return *(bitmapentry)(); /* call code via computed pointer. */
}
This being an 8bit micro, the multiplication and math on the "bigger
than 8 bit" pointer is a bit painful.
I think you should "refactor" the code more like:
asciibitmap(char ASCIIch)
{
char *(bitmapentry)(void); /* pointer to function */
bitmapentry = bitMapTop(ASCIIch);
for (i=0; i < 8; i++)
asciibm[i] = *(bitmapentry++)();
}
<mumble> bitMapTop(asciichar)
{
/* return pointer to first row for a character */
return TABLESTART + (8 * asciichar);
}
THat is; only compute the pointer to the start of the bitmap for
your character once, rather than 8 times. If you arrange your
bitmap table a bit carefully, an single character's bitmap data
will never span a page (or even 256 byte) boundry, and the increment
of the pointer for each "row" becomes easy.
OTOH, many applications that use bitmaps will end up needing row 0
of multiple characters before they're ready for row 1 of the first
character, which is what your existing bitMapWork function does
reasonably well (assuming it's correct; I didn't really check),
so optimizing the retrieval of the entire bitmap may not be useful.
If you can use a 8x7 bitmap instead of 8x8, you can use the
special flash read instructions and cut your table size in half,
and the code will be basically similar. The flash read is described
in section 10 of the 690 manual...
Sounds like you are writing code to display the complete ASCII character set
on a dot matrix display. What does the display require in regards to data?
More than one line of characters? Do you send it the blank pixels between
characters and above' lines?
Are you receiving characters from outside that you will display?
And the big question, do you really need the ability to display the complete
ASCII character set? If you are getting characters from outside, you may
want to translate them to your own internal character set so that you will
not have any invalid characters characters in and being acted upon.
For displaying, your character set could have hex 0 to 9 an characters 0 to
9. and to display a 3 would consist of
And the character A could be translated to decimal 10, BE to decimal 11.
And if you have a few words and phrases you wish to display , "VOLTS",
"HIGH" and "DANGER WILL ROBERTSON!" could be treated as one character with a
lot of bits to display.
The computed 'goto' could go to (another goto) the character , word or
phrase you desired to display.
; W contains character code of character, word or phrase
addwf PCL,F ;add offset to pc to generate a computed goto
goto dspzero
goto dspone
--------------
goto dspvolts
goto dspdangerwr
The trick is to isolate the way the data is physically stored from the way
the application accesses it. For example, you could access the data, up to
16 bits at a time, using a function like:
Where:
base_address is a code address of the area containing the code. The
funny syntax lets "C" think of it as a function pointer so that it is
relative to code memory.
bitpos is a bit position within the code memory, starting at bit 0.
numbits is the number of bits to return.
Then the 'get_pgm_data' routine would handle the job of actually grabbing
the data from code memory regardless of its alignment.
An application would then just have to do things like:
charstart = charcode * PIXELSPERCHAR; // determine starting location
of character
for (i = 0; i < ROWSPERCHAR; i++)
{
x = get_pgm_data( pixel_data, charstart, PIXELSPERROW);
<process x>
charstart += PIXELSPERROW;
}
And, as I mentioned before, getting the data into the correct bit-packed
form can be done by using Excel to create the assembly language source code.
I have also done this by using rather elaborate macros in MPASM, and in a
few cases by writing custom conversion programs to create the MPASM source.
Thanks for the feedback! I think the "flash read" you mentioned below will
help
a lot. I can get by with 8x7 bitmap which will reduce the table size
considerably.