Just finished the font render part of my spreadsheet. It renders directly from the unpacked 5-byte 'input' table. Change a byte in there and you'll see the changes immediately. Mind if I show it off, guys (see below)?
Cheerful regards, Mike, K8LH
Just finished the font render part of my spreadsheet. It renders directly from the unpacked 5-byte 'input' table. Change a byte in there and you'll see the changes immediately. Mind if I show it off, guys (see below)?
Cheerful regards, Mike, K8LH
Last edited by Mike, K8LH; - 20th May 2018 at 20:03.
Richard... Would you be interested in seeing my driver code for font tables with 2.5 word-per-character packing instead of 3 word-per-character packing? The new '2.5' font tables use 240 words of memory (down from 288 words) and my little single file ~225 line (non-PBP) demo program now weighs in at ~406 words total memory...
Cheerful regards, Mike
Last edited by Mike, K8LH; - 24th May 2018 at 09:35.
yes please, I had considered doing that but could not find a method that preserved the gainRichard... Would you be interested in seeing my driver code for font tables
my attempts used half the saved space up doing the unpacking
Warning I'm not a teacher
First, here's how I'm packing font pattern data into 2-1/2 words within groups of 5 words;
In the first part of my WrChar() routine I calculate the table address by first subtracting the font table offset (32) from the ASCII character value (32..127). Then I multiply the resulting font table index (0..95) by 2.5 and add the integer result (0..237) to the font table base address. In my case, I'm using a fixed 0x0400 address for the font table so I don't need to perform the addition. I simply stuff the 0..237 value directly into EEADRL and the hi byte of the font table address into EEADRH.
In the other half of my WrChar() routine, if the font table index is even I print the 1st word hi & lo bytes, the 2nd word hi & lo bytes, and the 3rd word hi byte. If the font table index is odd I print the 1st word lo byte, the 2nd word hi & lo bytes, and the 3rd word hi & lo bytes. You'll notice the logic is relatively simple and unrolling the print loop to accommodate the logic doesn't seem to have incurred additional program overhead.
The new demo program (attached below) is 50 words smaller than the old (3-word-per-character) program (406 words total) so it seems I've realized the full 48 word savings from the new packed font table format.
I hope this example provides some useful ideas and I'm sorry I can't help with PBP...
Have fun... Cheerful regards, Mike
Code:/******************************************************************** * * * Project: Nokia 5110 16F1823 Demo * * Source: Nokia_5110_Packed_v2.c * * Author: Mike McLaren, K8LH * * (C)2013: Micro Application Consultants * * Date: 23-May-2018 * * * * Experimental Nokia 5110 LCD display driver demo using a 96 * * character packed 2.5-word-per-character 5x7 font table. * * * * IDE: MPLAB 8.92 (tabs = 4) * * Lang: SourceBoost BoostC v7.30, Lite/Free version * * * ********************************************************************/ #include <system.h> #pragma DATA _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _MCLRE_ON #pragma DATA _CONFIG2, _PLLEN_OFF & _LVP_OFF #pragma CLOCK_FREQ 8000000 // 8 MHz INTOSC /******************************************************************** * function prototypes * ********************************************************************/ /******************************************************************** * typedef, defines, and macros * ********************************************************************/ #define rst porta.0 // RA0 = 5110 'reset' #define dat porta.1 // RA1 = 5110 'din' #define clk porta.2 // RA2 = 5110 'clk' #define ce portc.0 // RC0 = 5110 'ce' #define dc portc.1 // RC1 = 5110 'dc' #define putlcd(x) asm movlw x \ asm call putwreg() #define putcmd(x) dc = 0; \ asm movlw x \ asm call putwreg() /******************************************************************** * variables & packed 2.5-word-per-character 5x7 font table/array * ********************************************************************/ #pragma DATA 1024, 0x0000, 0x0000, 0x0000, 0x005F, 0x0000, // 32 ' ' '!' 0x0007, 0x0007, 0x0014, 0x3F94, 0x3F94, // 34 '"' '#' 0x122A, 0x3FAA, 0x0923, 0x0988, 0x3262, // 36 '$' '%' 0x1B49, 0x2AA2, 0x2800, 0x0283, 0x0000, // 38 '&' ''' 0x001C, 0x1141, 0x0000, 0x20A2, 0x0E00, // 40 '(' ')' 0x0A08, 0x1F08, 0x0A08, 0x043E, 0x0408, // 42 '*' '+' 0x0050, 0x1800, 0x0008, 0x0408, 0x0408, // 44 ',' '-' 0x0060, 0x3000, 0x0020, 0x0808, 0x0202, // 46 '.' '/' 0x1F51, 0x24C5, 0x1F00, 0x217F, 0x2000, // 48 '0' '1' 0x2161, 0x28C9, 0x2321, 0x20C5, 0x25B1, // 50 '2' '3' 0x0C14, 0x097F, 0x0827, 0x22C5, 0x22B9, // 52 '4' '5' 0x1E4A, 0x24C9, 0x1801, 0x3889, 0x0283, // 54 '6' '7' 0x1B49, 0x24C9, 0x1B06, 0x24C9, 0x149E, // 56 '8' '9' 0x0036, 0x1B00, 0x0000, 0x2B36, 0x0000, // 58 ':' ';' 0x0414, 0x1141, 0x0014, 0x0A14, 0x0A14, // 60 '<' '=' 0x0041, 0x1114, 0x0402, 0x00D1, 0x0486, // 62 '>' '?' 0x1949, 0x3CC1, 0x1F7E, 0x0891, 0x08FE, // 64 '@' 'A' 0x3FC9, 0x24C9, 0x1B3E, 0x20C1, 0x20A2, // 66 'B' 'C' 0x3FC1, 0x20A2, 0x0E7F, 0x24C9, 0x24C1, // 68 'D' 'E' 0x3F89, 0x0489, 0x00BE, 0x20C9, 0x24FA, // 70 'F' 'G' 0x3F88, 0x0408, 0x3F80, 0x20FF, 0x2080, // 72 'H' 'I' 0x1040, 0x20BF, 0x00FF, 0x0414, 0x1141, // 74 'J' 'K' 0x3FC0, 0x2040, 0x207F, 0x010C, 0x017F, // 76 'L' 'M' 0x3F84, 0x0410, 0x3FBE, 0x20C1, 0x20BE, // 78 'N' 'O' 0x3F89, 0x0489, 0x033E, 0x20D1, 0x10DE, // 80 'P' 'Q' 0x3F89, 0x0CA9, 0x2346, 0x24C9, 0x24B1, // 82 'R' 'S' 0x0081, 0x3F81, 0x00BF, 0x2040, 0x203F, // 84 'T' 'U' 0x0FA0, 0x2020, 0x0FBF, 0x2038, 0x203F, // 86 'V' 'W' 0x3194, 0x0414, 0x3187, 0x0470, 0x0407, // 88 'X' 'Y' 0x30D1, 0x24C5, 0x2180, 0x3FC1, 0x2080, // 90 'Z' '[' 0x0104, 0x0410, 0x1000, 0x20C1, 0x3F80, // 92 '\' ']' 0x0202, 0x0082, 0x0240, 0x2040, 0x2040, // 94 '^' '_' 0x0001, 0x0104, 0x0020, 0x2A54, 0x2A78, // 96 '`' 'a' 0x3FC8, 0x2244, 0x1C38, 0x2244, 0x2220, // 98 'b' 'c' 0x1C44, 0x2248, 0x3FB8, 0x2A54, 0x2A18, // 100 'd' 'e' 0x047E, 0x0481, 0x010C, 0x2952, 0x293E, // 102 'f' 'g' 0x3F88, 0x0204, 0x3C00, 0x227D, 0x2000, // 104 'h' 'i' 0x1040, 0x223D, 0x007F, 0x0828, 0x2200, // 106 'j' 'k' 0x0041, 0x3FC0, 0x007C, 0x0218, 0x0278, // 108 'l' 'm' 0x3E08, 0x0204, 0x3C38, 0x2244, 0x2238, // 110 'n' 'o' 0x3E14, 0x0A14, 0x0408, 0x0A14, 0x0C7C, // 112 'p' 'q' 0x3E08, 0x0204, 0x0448, 0x2A54, 0x2A20, // 114 'r' 's' 0x023F, 0x2240, 0x103C, 0x2040, 0x107C, // 116 't' 'u' 0x0E20, 0x2020, 0x0E3C, 0x2030, 0x203C, // 118 'v' 'w' 0x2228, 0x0828, 0x220C, 0x2850, 0x283C, // 120 'x' 'y' 0x2264, 0x2A4C, 0x2200, 0x0436, 0x2080, // 122 'z' '{' 0x0000, 0x3F80, 0x0000, 0x20B6, 0x0400, // 124 '|' '}' 0x0808, 0x0410, 0x0478, 0x2341, 0x2378 // 126 '~' '' /******************************************************************** * * ********************************************************************/ void putwreg() // send byte, msb first (15 words) { char work; // asm movwf _work // char n = 0; ce = 0; // spi enable on do // send 8 bits { clk = 0; dat = 0; // " if(work.7) dat = 1; // " clk = 1; work <<= 1; // " n++; // " } while(n.3 == 0); // " ce = 1; // spi enable off } // /******************************************************************** * * ********************************************************************/ void RdFlash() // bank 3 (inserted by compiler) { asm bcf _eecon1,CFGS // not 'config' memory |03 asm bsf _eecon1,EEPGD // select 'program' memory |03 asm bsf _eecon1,RD // initiate read operation |03 asm nop // required nop |03 asm nop // " |03 asm incf _eeadrl,F // bump EEADR |03 asm rlf _eedatl,W // move b7 into Carry |03 asm rlf _eedath,W // wreg = the 7 bit hi byte |03 asm bcf _eedatl,7 // eedatl = the 7 bit lo byte |03 } // /******************************************************************** * * ********************************************************************/ void WrChar(char ascii) // for packed 2.5 word 5x7 font { dc = 1; // set lcd 'data' mode asm movlw -32 // ascii 32..127 minus offset |00 asm addwf _ascii,F // font array index, 0..95 |00 asm lsrf _ascii,W // int(ascii *= 2.5) -> 0..237 |00 asm addwf _ascii,W // " |00 asm addwf _ascii,W // " |00 // asm movlb 3 // bank 3 (inserted by compiler) |03 asm movwf _eeadrl // flash address lo, 0..237 |03 asm movlw 1024/256 // table address hi |03 asm movwf _eeadrh // flash address hi |03 /* * * Extract five bytes of pattern data from three memory words. * * Odd characters use word 0 lo, 1 hi + lo, and 2 hi + lo while * * even characters use word 0 hi + lo, 1 hi + lo, and 2 hi. A * * sixth blank (zero) byte is sent for inter-character spacing. * * */ asm call RdFlash() // read 1st word |03 // asm movlb 0 // bank 0 (inserted by compiler) |00 asm btfss _ascii,0 // odd char? yes, skip, else |00 asm call putwreg() // send hi byte (even character) |00 // asm movlb 3 // bank 3 |03 asm movf _eedatl,W // |03 asm call putwreg() // send lo byte |00 asm call RdFlash() // read 2nd word |03 asm call putwreg() // send hi byte |00 // asm movlb 3 // bank 3 |03 asm movf _eedatl,W // |03 asm call putwreg() // send lo byte |00 asm call RdFlash() // read 3rd word |03 asm call putwreg() // send hi byte |00 // asm movlb 3 // bank 3 |03 asm movf _eedatl,W // |03 // asm movlb 0 // bank 0 |00 asm btfsc _ascii,0 // even char? yes, skip, else |00 asm call putwreg() // send lo byte (odd characters) |00 asm movlw 0 // |00 asm call putwreg() // send blank 6th column |00 } // /******************************************************************** * * ********************************************************************/ void WrChar(rom char *data) // overload function for strings { char ndx = 0; // while(data[ndx++]) // while not end-of-string WrChar(wreg); // } // /******************************************************************** * main setup * ********************************************************************/ void main() { ansela = 0; // adc off for digital I/O anselc = 0; // " trisa = 0; // porta all outputs except RA3/MCLR trisc = 0; // portc all outputs ce = 1; // 5110 'ce' off rst = 1; // 5110 'rst' off osccon = 0b01110000; // set INTOSC to 8 MHz /* * * initialize Nokia 5110 LCD display * * */ delay_ms(30); // rst = 0; rst = 1; // 5110 'reset' pulse putcmd(0x20+0x01); // function set: extended instructions putcmd(0x80+0x30); // set Vop (contrast), 0..127 putcmd(0x04+0x02); // set temperature coefficient, 0..3 putcmd(0x10+0x03); // Set bias system, 0..7 putcmd(0x20+0x00); // function set: standard instructions putcmd(0x08+0x04); // display control: normal mode /* * * test the LCD and the print string overload function. * * */ putcmd(0x80+0x20); // set DDRAM X address, 0..83 putcmd(0x40+0x02); // set DDRAM Y address, 0..5 WrChar('H'); // write ascii character WrChar("ello"); // write ascii string /******************************************************************** * main loop * ********************************************************************/ while(1) // { // } // } //
Last edited by Mike, K8LH; - 25th May 2018 at 02:26.
thanks mike , the concept works nicely
xc8 version (393)+240 words , uses mssp1
Code:#include "mcc_generated_files/mcc.h" #include "FONT.c" void putwreg(char work); void putcmd(char x); void WrChar(char ascii); void WrStr(char *); void main(void) { // initialize the device SYSTEM_Initialize(); /* * * initialize Nokia 5110 LCD display * * */ __delay_ms(30); // LCD_RST_SetLow(); // 5110 'reset' pulse __delay_ms(1); LCD_RST_SetHigh(); // 5110 'reset' pulse __delay_ms(1); putcmd(0x20 + 0x01); // function set: extended instructions putcmd(0xc8); // set Vop (contrast), 0..127 putcmd(0x04 + 0x02); // set temperature coefficient, 0..3 putcmd(0x10 + 0x03); // Set bias system, 0..7 putcmd(0x20 + 0x00); // function set: standard instructions putcmd(0x08 + 0x04); // display control: normal mode putcmd(0x80 + 0x20); // set DDRAM X address, 0..83 putcmd(0x40 + 0x02); // set DDRAM Y address, 0..5 WrChar('R'); // write ascii character WrStr("eady"); while (1) { } } /** End of File */ void putwreg(char work) // send byte, msb first (15 words) { LCD_CE_LAT = 0; // spi enable on SPI1_Exchange8bit(work); while (!PIR1bits.SSP1IF); LCD_CE_LAT = 1; // spi enable off } // void WrChar(char ascii) // for packed 2.5 word 5x7 font { unsigned int dat, inx = 0x1f00; char i = 5; // char fd[6],i=5,*pt; //pt=fd; inx += ((ascii - 32)*5) >> 1; dat = FLASH_ReadWord(inx++); if (!(ascii & 1))putwreg(dat >> 7); // *pt++=dat>>7; putwreg(dat & 0x7f); //*pt++ =(char)dat&0x7f; dat = FLASH_ReadWord(inx++); putwreg(dat >> 7); putwreg(dat & 0x7f); //*pt++=dat>>7; //*pt++=(char)dat&0x7f; dat = FLASH_ReadWord(inx); //*pt++=dat>>7; putwreg(dat >> 7); if (ascii & 1) putwreg(dat & 0x7f); //*pt++=(char)dat&0x7f; //pt=fd; // while(i--){ // putwreg(*pt++); // } putwreg(0); } void putcmd(char x) { LCD_DC_SetLow(); putwreg(x); LCD_DC_SetHigh(); } void WrStr(char *buff) { { // while (*buff) // while not end-of-string WrChar(*buff++); // } }
font
Code:#include <xc.h> #asm PSECT strings,class=CODE,abs,delta=2 ORG 0x1f00 DW 0x0000, 0x0000, 0x0000, 0x005F, 0x0000 // 32 ' ' '!' DW 0x0007, 0x0007, 0x0014, 0x3F94, 0x3F94 // 34 '"' '#' DW 0x122A, 0x3FAA, 0x0923, 0x0988, 0x3262 // 36 '$' '%' DW 0x1B49, 0x2AA2, 0x2800, 0x0283, 0x0000 // 38 '&' ''' DW 0x001C, 0x1141, 0x0000, 0x20A2, 0x0E00 // 40 '(' ')' DW 0x0A08, 0x1F08, 0x0A08, 0x043E, 0x0408 // 42 '*' '+' DW 0x0050, 0x1800, 0x0008, 0x0408, 0x0408 // 44 ',' '-' DW 0x0060, 0x3000, 0x0020, 0x0808, 0x0202 // 46 '.' '/' DW 0x1F51, 0x24C5, 0x1F00, 0x217F, 0x2000 // 48 '0' '1' DW 0x2161, 0x28C9, 0x2321, 0x20C5, 0x25B1 // 50 '2' '3' DW 0x0C14, 0x097F, 0x0827, 0x22C5, 0x22B9 // 52 '4' '5' DW 0x1E4A, 0x24C9, 0x1801, 0x3889, 0x0283 // 54 '6' '7' DW 0x1B49, 0x24C9, 0x1B06, 0x24C9, 0x149E // 56 '8' '9' DW 0x0036, 0x1B00, 0x0000, 0x2B36, 0x0000 // 58 ':' ';' DW 0x0414, 0x1141, 0x0014, 0x0A14, 0x0A14 // 60 '<' '=' DW 0x0041, 0x1114, 0x0402, 0x00D1, 0x0486 // 62 '>' '?' DW 0x1949, 0x3CC1, 0x1F7E, 0x0891, 0x08FE // 64 '@' 'A' DW 0x3FC9, 0x24C9, 0x1B3E, 0x20C1, 0x20A2 // 66 'B' 'C' DW 0x3FC1, 0x20A2, 0x0E7F, 0x24C9, 0x24C1 // 68 'D' 'E' DW 0x3F89, 0x0489, 0x00BE, 0x20C9, 0x24FA // 70 'F' 'G' DW 0x3F88, 0x0408, 0x3F80, 0x20FF, 0x2080 // 72 'H' 'I' DW 0x1040, 0x20BF, 0x00FF, 0x0414, 0x1141 // 74 'J' 'K' DW 0x3FC0, 0x2040, 0x207F, 0x010C, 0x017F // 76 'L' 'M' DW 0x3F84, 0x0410, 0x3FBE, 0x20C1, 0x20BE // 78 'N' 'O' DW 0x3F89, 0x0489, 0x033E, 0x20D1, 0x10DE // 80 'P' 'Q' DW 0x3F89, 0x0CA9, 0x2346, 0x24C9, 0x24B1 // 82 'R' 'S' DW 0x0081, 0x3F81, 0x00BF, 0x2040, 0x203F // 84 'T' 'U' DW 0x0FA0, 0x2020, 0x0FBF, 0x2038, 0x203F // 86 'V' 'W' DW 0x3194, 0x0414, 0x3187, 0x0470, 0x0407 // 88 'X' 'Y' DW 0x30D1, 0x24C5, 0x2180, 0x3FC1, 0x2080 // 90 'Z' '[' DW 0x0104, 0x0410, 0x1000, 0x20C1, 0x3F80 // 92 '\' ']' DW 0x0202, 0x0082, 0x0240, 0x2040, 0x2040 // 94 '^' '_' DW 0x0001, 0x0104, 0x0020, 0x2A54, 0x2A78 // 96 '`' 'a' DW 0x3FC8, 0x2244, 0x1C38, 0x2244, 0x2220 // 98 'b' 'c' DW 0x1C44, 0x2248, 0x3FB8, 0x2A54, 0x2A18 // 100 'd' 'e' DW 0x047E, 0x0481, 0x010C, 0x2952, 0x293E // 102 'f' 'g' DW 0x3F88, 0x0204, 0x3C00, 0x227D, 0x2000 // 104 'h' 'i' DW 0x1040, 0x223D, 0x007F, 0x0828, 0x2200 // 106 'j' 'k' DW 0x0041, 0x3FC0, 0x007C, 0x0218, 0x0278 // 108 'l' 'm' DW 0x3E08, 0x0204, 0x3C38, 0x2244, 0x2238 // 110 'n' 'o' DW 0x3E14, 0x0A14, 0x0408, 0x0A14, 0x0C7C // 112 'p' 'q' DW 0x3E08, 0x0204, 0x0448, 0x2A54, 0x2A20 // 114 'r' 's' DW 0x023F, 0x2240, 0x103C, 0x2040, 0x107C // 116 't' 'u' DW 0x0E20, 0x2020, 0x0E3C, 0x2030, 0x203C // 118 'v' 'w' DW 0x2228, 0x0828, 0x220C, 0x2850, 0x283C // 120 'x' 'y' DW 0x2264, 0x2A4C, 0x2200, 0x0436, 0x2080 // 122 'z' '{' DW 0x0000, 0x3F80, 0x0000, 0x20B6, 0x0400 // 124 '|' '}' DW 0x0808, 0x0410, 0x0478, 0x2341, 0x2378 // 126 '~' '' #endasm
Last edited by richard; - 25th May 2018 at 10:42.
Warning I'm not a teacher
Nice to see an XC8 example excerpt...
May I ask where I can find information for placing DW data in XC8 at an absolute address, please? I haven't found it so far, nor can I get your example working in a 16F1823 XC8 project...
I'm also struggling with MCC (Microsoft Code Configurator)...
all my knowledge came from google" xc8 psect" , i have not found a good reference yetMay I ask where I can find information for placing DW data in XC8 at an absolute address
the xc8 use rguide/manual is severely lacking in that respect
key elements
PSECT strings,class=CODE,abs,delta=2
ORG 0x1f00
my example uses an asm segment in a c include file, it may be better to place the data in an asm file and include that instead
because i have terrible trouble getting "labels" to work properly my way. [ still learning]
mcc is a splendid thing once you get the hang of it, for the chips it supports.
once i have created the standalone project i use mcc to set the osc and create the main.c and mcc files
then you can add the pins/hw modules
Bookmarks