Thats great that you managed to get your code working. If you are agreeable I would like to post your code on our website in case others can benefit from working code for this type of CPU (credit posted accordingly of course). If you agree, please advise name to use for credits.
Here is a conversion routine for generating suitable bitmaps from ASCII characters.
Font/character set definition:
BYTE code g_lpCharLU[128][5] = {
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 000
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 001
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 002
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 003
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 004
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 005
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 006
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 007
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 008
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 009
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 010
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 011
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 012
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 013
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 014
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 015
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 016
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 017
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 018
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 019
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 020
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 021
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 022
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 023
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 024
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 025
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 026
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 027
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 028
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 029
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 030
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 031
{ 0x0, 0x0, 0x0, 0x0, 0x0, }, // 032 Space
{ 0x0, 0x0, 0x79,0x0, 0x0, }, // 033 !
{ 0x0, 0x70,0x0, 0x70,0x0, }, // 034 "
{ 0x14,0x7F,0x14,0x7F,0x14,}, // 035 Hash mark
{ 0x24,0x2A,0x7F,0x2A,0x12,}, // 036 $
{ 0x23,0x13,0x08,0x64,0x62,}, // 037 %
{ 0x05,0x22,0x55,0x49,0x36,}, // 038 &
{ 0x0, 0x0, 0x60,0x50,0x0, }, // 039 '
{ 0x0, 0x41,0x22,0x1c,0x0, }, // 040 (
{ 0x0, 0x1c,0x22,0x41,0x0, }, // 041 )
{ 0x14,0x08,0x3E,0x08,0x14,}, // 042 *
{ 0x08,0x08,0x3E,0x08,0x08,}, // 043 +
{ 0x0, 0x0, 0x06,0x05,0x0, }, // 044 ,
{ 0x08,0x08,0x08,0x08,0x08,}, // 045 -
{ 0x0, 0x0, 0x03,0x03,0x0, }, // 046 .
{ 0x20,0x10,0x08,0x04,0x02,}, // 047 forward slash
{ 0x3E,0x51,0x49,0x45,0x3E,}, // 048 0
{ 0x0, 0x01,0x7f,0x21,0x0, }, // 049 1
{ 0x31,0x49,0x45,0x43,0x21,}, // 050 2
{ 0x46,0x69,0x51,0x41,0x42,}, // 051 3
{ 0x04,0x7F,0x24,0x14,0x0C,}, // 052 4
{ 0x4E,0x51,0x51,0x51,0x72,}, // 053 5
{ 0x06,0x49,0x49,0x29,0x1E,}, // 054 6
{ 0x60,0x50,0x48,0x47,0x40,}, // 055 7
{ 0x36,0x49,0x49,0x49,0x36,}, // 056 8
{ 0x3C,0x4A,0x49,0x49,0x30,}, // 057 9
{ 0x0, 0x0, 0x36,0x36,0x0, }, // 058 :
{ 0x0, 0x0, 0x36,0x35,0x0, }, // 059 ;
{ 0x0, 0x41,0x22,0x14,0x08,}, // 060 <
{ 0x14,0x14,0x14,0x14,0x14,}, // 061 =
{ 0x08,0x14,0x22,0x41,0x0, }, // 062 >
{ 0x30,0x48,0x45,0x40,0x20,}, // 063 ?
{ 0x3C,0x55,0x5D,0x41,0x3E,}, // 064 @
{ 0x3F,0x48,0x48,0x48,0x3F,}, // 065 A
{ 0x36,0x49,0x49,0x49,0x7F,}, // 066 B
{ 0x22,0x41,0x41,0x41,0x3E,}, // 067 C
{ 0x1C,0x22,0x41,0x41,0x7F,}, // 068 D
{ 0x41,0x49,0x49,0x49,0x7F,}, // 069 E
{ 0x40,0x48,0x48,0x48,0x7F,}, // 070 F
{ 0x2F,0x49,0x49,0x41,0x3E,}, // 071 G
{ 0x7F,0x08,0x08,0x08,0x7F,}, // 072 H
{ 0x0, 0x41,0x7f,0x41,0x0, }, // 073 I
{ 0x40,0x7E,0x41,0x01,0x02,}, // 074 J
{ 0x41,0x22,0x14,0x08,0x7F,}, // 075 K
{ 0x01,0x01,0x01,0x01,0x7F,}, // 076 L
{ 0x7F,0x20,0x18,0x20,0x7F,}, // 077 M
{ 0x7F,0x04,0x08,0x10,0x7F,}, // 078 N
{ 0x3E,0x41,0x41,0x41,0x3E,}, // 079 O
{ 0x30,0x48,0x48,0x48,0x7F,}, // 080 P
{ 0x3D,0x42,0x45,0x41,0x3E,}, // 081 Q
{ 0x31,0x4A,0x4C,0x48,0x7F,}, // 082 R
{ 0x26,0x49,0x49,0x49,0x32,}, // 083 S
{ 0x40,0x40,0x7F,0x40,0x40,}, // 084 T
{ 0x7F,0x01,0x01,0x01,0x7F,}, // 085 U
{ 0x7C,0x02,0x01,0x02,0x7C,}, // 086 V
{ 0x7E,0x01,0x0E,0x01,0x7E,}, // 087 W
{ 0x63,0x14,0x08,0x14,0x63,}, // 088 X
{ 0x70,0x08,0x07,0x08,0x70,}, // 089 Y
{ 0x61,0x51,0x49,0x45,0x43,}, // 090 Z
{ 0x0, 0x44,0x41,0x7f,0x0, }, // 091 [
{ 0x02,0x04,0x08,0x10,0x20,}, // 092 back slash
{ 0x0, 0x7f,0x41,0x41,0x0, }, // 093 ]
{ 0x10,0x20,0x40,0x20,0x10,}, // 094 ^
{ 0x01,0x01,0x01,0x01,0x01,}, // 095 _
{ 0x0, 0x50,0x60,0x0, 0x0, }, // 096 `
{ 0x0F,0x15,0x15,0x15,0x02,}, // 097 a
{ 0x0E,0x11,0x11,0x11,0x7F,}, // 098 b
{ 0x11,0x11,0x11,0x11,0x0E,}, // 099 c
{ 0x7F,0x11,0x11,0x11,0x0E,}, // 100 d
{ 0x0C,0x15,0x15,0x15,0x0E,}, // 101 e
{ 0x50,0x50,0x3F,0x10,0x10,}, // 102 f
{ 0x1E,0x15,0x15,0x15,0x08,}, // 103 g
{ 0x0F,0x10,0x10,0x08,0x7F,}, // 104 h
{ 0x0, 0x01,0x5f,0x11,0x0, }, // 105 i
{ 0x0, 0x5e,0x11,0x01,0x02,}, // 106 j
{ 0x0, 0x11,0x0a,0x04,0x7f,}, // 107 k
{ 0x0, 0x01,0x7f,0x41,0x0, }, // 108 l
{ 0x0F,0x10,0x1F,0x10,0x1F,}, // 109 m
{ 0x0F,0x10,0x10,0x08,0x1F,}, // 110 n
{ 0x0E,0x11,0x11,0x11,0x0E,}, // 111 o
{ 0x08,0x14,0x14,0x14,0x1F,}, // 112 p
{ 0x1F,0x14,0x14,0x14,0x08,}, // 113 q
{ 0x0, 0x10,0x10,0x08,0x1f,}, // 114 r
{ 0x12,0x15,0x15,0x15,0x09,}, // 115 s
{ 0x11,0x11,0x7E,0x10,0x10,}, // 116 t
{ 0x1F,0x02,0x01,0x01,0x1E,}, // 117 u
{ 0x1C,0x02,0x01,0x02,0x1C,}, // 118 v
{ 0x1E,0x01,0x06,0x01,0x1E,}, // 119 w
{ 0x11,0x0A,0x04,0x0A,0x11,}, // 120 x
{ 0x1E,0x05,0x05,0x05,0x18,}, // 121 y
{ 0x11,0x19,0x15,0x13,0x11,}, // 122 z
{ 0x0, 0x41,0x41,0x36,0x08,}, // 123 {
{ 0x0, 0x0, 0x77,0x0, 0x0, }, // 124 |
{ 0x08,0x36,0x41,0x41,0x0, }, // 125 }
{ 0x08,0x1C,0x2A,0x08,0x08,}, // 126 ~
{ 0x08,0x08,0x2A,0x1C,0x08,}, // 127
};
BYTE code pixels[56] = //This array is used in the LC24 algorithm
{ //for the character set
4,3,3,2,2,
1,1,0,0,40,
39,39,38,38,
37,37,36,36,
76,75,75,74,
74,73,73,72,72,36,36,
37,37,38,38,39,39,40,
22,22,21,21,20,20,19,19,18,18,
58,58,57,57,56,56,55,55,54,54,
};
Conversion routine:
//***************************************************************
//***************************************************************
//
// FUNCTION NAME : DisplayText
//
// INPUTS : byKeyNum - Key 'display' number.
// StringSize - Number of characters in the string.
// *Text - Pointer to the buffer where the bitmap is.
// Centered - Indicates if the string should
// be centered.
// LC16 - LC16 data bytes must be bit reversed
//
//
// OUTPUTS : None
//
//
// DESCRIPTION : Display text on a specifed screen key.
//
//
//***************************************************************
//***************************************************************
void DisplayText(BYTE byKeyNum, \
PSTR Text, \
BYTE StringSize, \
BIT Centered, \
BIT LC16)
{
xdata BYTE Bitmap[108];
TextToBitMap(StringSize, Text, Bitmap, Centered, LC16);
SKPict(byKeyNum, Bitmap, LC16);
}
//***************************************************************
//***************************************************************
//
// FUNCTION NAME : TextToBitMap
//
// INPUTS : byStrSize - the lenght of the string passed.
// *pStr - pointer to the string being processed.
// *pLcdData - pointer to the buffer that will
// store the data.
// bCentered - A boolean value which indicates if
// the string should be centered.
// LC16 - Set if data intended for LC16
//
// OUTPUTS : None
//
//
// DESCRIPTION : Convert the string to a bitmap for displaying on a LCD key.
// We assume all parameters have been verified.
//
// We convert the string to a "true" bitmap. Before displaying
// this bitmap on a lcd key each byte will need to be bit
// reversed (if LC16).
//
// An LC16 bitmap consists of 64 bytes laid out as a
// 4*16 array.
//
// Byte0 Byte1 Byte2 Byte3
// R0 0 1 2 3
// R1 4 5 6 7
// : : : : :
// : : : : :
// R15 60 61 62 63
//
// A character cell consists of 40 bits laid out as a
// 5*8 grid. We use a hard coded character set lookup table
// to generate each cell. Eg For character 'P' our lookup
// table has the following five byte entry:
// 0x30,0x48,0x48,0x48,0x7F
// which translates into:
//
// ..XX....
// .X..X...
// .X..X...
// .X..X...
// .XXXXXXX
//
// Thus each character cell needs to be rotated by 90 degrees
// before being placed in the lcd buffer.
//
// A one pixel vertical/vertical space is placed between
// characters.
//
//
//***************************************************************
//***************************************************************
void TextToBitMap(BYTE byStrSize, \
PSTR pStr, \
NPBYTE pLcdData, \
BIT bCentered, \
BIT LC16)
{
BYTE xdata x = 0; //Increment
BYTE xdata y = 0; //Increment
BYTE xdata z = 0; //Increment
BYTE xdata SKMtmp = 0; //stores the byte taken from the character set
BYTE xdata byChr = 0; //byte from a string passed
BYTE xdata byOrg = 0; //where the text will start on an LC16 key
BYTE xdata byColCnt = 0; //tracks next column (pixel) position to write in image array
BYTE xdata byMask = 0x80; //the mask points to position within byte in image array
BYTE xdata byLineCnt = 0; //points to current line in image array being populated
BYTE xdata byLineTmp; //used to inc from current LineCnt to next line
BYTE *pBuf = 0; //used to access the actual pixel image
BOOL bOdd = 1; //used to indicate what pattern the byte run vertically in LC24
memset(pLcdData,0,108);
if(LC16)
{
//Determine starting position if less than full line (<5 chars)
if((byStrSize <= 5) && (bCentered)) //if centered and 5 or less characters
{
byOrg = (64 / 4); //The origin of the characters is byte 16
if(byStrSize < 5)
{
byColCnt = (5 - byStrSize) * 6; //These are calculation used to say where the
byColCnt >>= 1; //text should start for a given number of characters
byMask = (0x80 >> (byColCnt % 8));
}
}
//Create image from passed string
for(x = 0; x < byStrSize; x++)
{
//take the next byte from the string passed
byChr = *pStr++;
//move to the next line if the top line has been filled
if(x == 5)
{
byOrg = 32; //Start at beginning of next line
byMask = 0x80;
byColCnt = 0; //First column in this row
}
//Every char pattern has bit 0x80 blank
byMask = ( (byMask>>1) | (byMask<<7) );
byColCnt++ ;
//Loop through each byte of character set for this display char
for(y = 0; y < BYTESPERCELL; y++)
{
pBuf = pLcdData + byOrg + (byColCnt / 8); //The byte about to be processed will be placed
//in pLcdData at a certain location
SKMtmp = g_lpCharLU[byChr][(BYTESPERCELL - 1) - y];//Use the character set stored in prom
for(z=0;z<8;z++)
{
if(SKMtmp & 0x80) //if the bit is a one process it
*pBuf |= byMask;
SKMtmp <<= 1; //otherwise move on
pBuf += 4;
}
byColCnt++;
byMask = ( (byMask>>1) | (byMask<<7) );
}
}
}
else
{
//Initialise counters
byColCnt = 35; //Start in left most colum
byLineCnt = 0; //Start on first (top) line
bOdd = 1; //First line is "Odd" => last byte only has lower nibble
byMask = 0x08; //First pixels are in low nibble of byte 4
//Determine starting position if less than full line (<6 chars)
if((byStrSize <= 6) && (bCentered))
{
//Text centred on vertical - always line num 8 which is always odd
byLineCnt = 8;
//Centred on horiz - find num free spaces, alloc half (3 pixels) to each side
byColCnt = 35 - ((6 - byStrSize)*3);
//Set mask start to match first position
if(byColCnt < 32)
//In first 4 normal bytes (not shifted)
byMask = (0x80 >> ((31-byColCnt) % 8));
else
//In last byte (=4) then mask is shifted across nibble only
byMask = (0x80 >> ((39-byColCnt) % 8));
}
//Create image from passed string
for(x = 0; x < byStrSize; x++)
{
//Take next byte from string passed
byChr = *pStr++;
//move to the next line if current line has been filled
//need 5 pixels (columns) to fit next char
//if all 6 chars written to end then byColCnt wraps around to 255
if(byColCnt < 4 || byColCnt > 250) {
byLineCnt += 8;
byColCnt = 35;
bOdd = 1;
byMask = 0x08;
}
//Loop through each byte of character set for this display char
for(y = 0; y < BYTESPERCELL; y++)
{
SKMtmp = g_lpCharLU[byChr][(BYTESPERCELL - 1) - y];//Get next char pattern byte
byLineTmp = byLineCnt;
//Loop through every pixel in char pattern byte
for(z=0;z<8;z++)
{
if(SKMtmp & 0x80) { //if the bit is a one process it
pBuf = pLcdData + ((byLineTmp/2)*9) + ((byColCnt+(bOdd?0:4))/8) + (bOdd?0:4);
//The byte about to be processed will be placed
//in pLcdData at a certain location
if(bOdd)
//Use mask as normal
*pBuf |= byMask;
else
//Next line has bytes shifted left x 4 bits
//Need to move mask up/down depending on position (nibble)
if(byMask > 0x08)
*pBuf |= (byMask>>4);
else
*pBuf |= (byMask<<4);
}
//move to next bit in char pattern byte (next line in image)
SKMtmp <<= 1;
bOdd = !bOdd;
byLineTmp++;
}
//Go to next column to fill
byColCnt--;
byMask = ( (byMask>>1) | (byMask<<7) );
}
//Skip one pixel column to create gap between chars
byMask = ( (byMask>>1) | (byMask<<7) );
byColCnt-- ;
}
}
}
Output to ScreenKey:
//***************************************************************
//***************************************************************
//
// FUNCTION NAME : SKPict
//
// INPUTS : KeyNr - The key to display the picture on.
// *PictData - A Pointer the an array containing
// the picture to be displayed.
// LCTpye - 1 = LC16, 0 = LC24
//
// OUTPUTS : None
//
//
// DESCRIPTION : Called when a key display is to be updated.
//
//
//***************************************************************
//***************************************************************
void SKPict(BYTE KeyNr, NPBYTE PictData, BIT LCType)
{
BYTE i = 0;
BYTE lcd_size;
SwSelect(KeyNr); // select the key to display the image on.
SKDataOut(0x00, 0 ); // Start Byte
SKDataOut(LC_PIXREG, 1); // Cmd Byte
//Set max size to transmit to key
lcd_size = LCType ? 64 : 108;
for (i = 0; i < lcd_size; i++)
if(LCType == 0)
SKDataOut(PictData[i], 1); // LC24
else
SKDataOut(BitReverse(PictData[i]),1); // LC16
SKDataOut(0xAA, 0); // End Byte
}
Obviously you would have to work on this to translate it for your specific compiler and MCU type. It is possible to reduce its footprint by only using part of the character set and removing the LC16 or LC24 sections that you do not want.
Good luck with it!