Entire demo is 872 words ,its less than 1/3 size of other attempts and has same features and a full alpha-numeric font
Printable View
Entire demo is 872 words ,its less than 1/3 size of other attempts and has same features and a full alpha-numeric font
Amazing work Richard.
5*
Ioannis
Well done Richard, Ioannis almost got it right - put a star up against your name and let's call it 6*.
Regards,
Bill
I agree... nicely done, Richard. I can't tell you how much I enjoy studying and learning from your code.
I was inspired by how you compressed a 96 character 5x7 font table down to something like 288 words and I spent most of the day implementing something similar on an old 5110 demo program written in C for a 16F1823. With just basic INIT, CMD, DAT, and STR functions, the program now uses less than 500 words of program memory. I'm pretty geeked about it! Thank you...
Take care. Have fun. Cheerful regards, Mike
if you really want to geek it up
changing the output routine to use the mssp module shaves another 10% off the code size
and speeds the thing up by a factor of 10x
din and clk need to be on sdo and sck
this
PAUSEUS 150
SHiftOUT LCD_DIN,LCD_CLK,1,[LcdData]
becomes
PIR1.3=0
SSP1BUF = LcdData
WHILE !PIR1.3 : wend
and this is added to init routine
SSP1CON1=$21 ;$22,21,20 all work @32mhz 20 is fastest
SSP1STAT=$40
Yes, I already thought about using the SPI module. The current bit-bang driver uses 14 words of memory and runs at ~190-kb/s (with 8-MHz clock). An SPI driver and its init code shouldn't be any bigger. I hope to work on an SPI driver later today. I just need to refresh my memory on the SPI modes. Looks like you're using CKE = 1 and CKP = 0, yes?
Attachment 8650
Implementing the 'packed' font table and extracting data was surprisingly simple, though I'm coding pretty close to the metal and the results are nothing as agile or elegant as your use of the 'readcode' function. Here's an excerpt, if you're interested;
Code:/********************************************************************
* *
********************************************************************/
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 btfsc _status,Z // " |03
asm incf _eeadrh,F // " |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) // WrChar() for packed 5x7 font
{ asm movf _ascii,W // ascii char value, 32..127 |00
asm addlw -32 // minus table offset |00
asm movwf _ascii // font array index, 0..95 |00
/* *
* multiply index by 3 (0..95 -> 0..285), add table base address, *
* and stuff the result in the EEADR register pair. *
* */
asm lslf _wreg,W // wreg = (ascii-32)*2 |00
asm addwf _ascii,W // wreg = (ascii-32)*3 |00
// asm movlb 3 // bank 3 (inserted by compiler) |03
asm movwf _eeadrl // flash address lo |03
asm movlw 1024/256 // table address hi |03
asm btfsc _status,C // overflow? no, skip, else |03
asm addlw 1 // bump value |03
asm movwf _eeadrh // flash address hi |03
/* *
* read 3 words (6 bytes) of font pattern data from the 5x7 font *
* array and write them to the Nokia 5110 LCD. *
* */
for(char i=0; i<3; i++) //
{ RdFlash(); // read one word (2 bytes)
putlcd(wreg); // send hi byte
putlcd(eedatl); // send lo byte
} //
} //
/********************************************************************
* *
********************************************************************/
void WrChar(rom char *data) // overload function for strings
{ char ndx = 0; //
while(data[ndx++]) // while not end-of-string
WrChar(wreg); //
} //
Thank you again for sharing your work. MikeCode:/* *
* initialize Nokia 5110 LCD display *
* */
delay_ms(30); //
rst = 0; // 5110 'reset' pulse
rst = 1; //
dc = 0; // command mode
putlcd(0x20+0x01); // function set: extended instructions
putlcd(0x80+0x30); // set Vop (contrast), 0..127
putlcd(0x04+0x02); // set temperature coefficient, 0..3
putlcd(0x10+0x03); // Set bias system, 0..7
putlcd(0x20+0x00); // function set: standard instructions
putlcd(0x08+0x04); // display control: normal mode
putlcd(0x80+0x20); // set DDRAM X address, 0..83
putlcd(0x40+0x02); // set DDRAM Y address, 0..5
dc = 1; // data mode
WrChar("Hello"); // test string overload function
Hi Richard,
Just taking a quick look at your Include demo and I can only write 13 characters per line successfully... if 14 then the result is a wrap around and overwriting of the first char. Example below:
I'll test more later today and let you know if I find anything else needing a tweak. Again, great job.Code:looper:
LCDCLR
; LCDSTR 6,0,"-Nokia-Demo-" ; Line 0, position 6.
LCDSTR 0,0,"I wonder what happens if the string is large?" ; = Rubbish on first line and "missing quote" error message.
; LCDSTR 0,0,"I wonder what?" ; = "? wonder what" [14 chars]
LCDSTR 0,0,"I wonder what" ; = "I wonder what" [13 chars only]
LCDC 0,4,"'" ; Line 4, position 0.
LCDC 25,5,"8" ; Line 5, position 25.
PAUSE 1000
GOTO looper
Regards,
Bill
yes probably, but here is a new version with double size chr capability and mssp and font unpacking in asm [like in my ks0108 code]
its not been texted on a pic18 , but its blisteringly fast on the 16f1847, and will fill screen fully
thanks go to blll [wjsmarine] for donation of hardware for this project, enjoy
That's impressive, Richard.
Can you explain how your font table works and how you derived those values in each column please? What limits the size of the table one can create?
I'd like to learn from it and maybe if I can get my head around the process find a way to smooth out the double size characters (particularly 0-9, the degree symbol and C) - I'm guessing you are working your magic to achieve double size by math so it probably means making a larger table to accommodate these.
An indication of smooth characters is shown in the pic attached, made with the previous lookup table style, which consumed 4 normal sized chars' area per big one and 2 lines (as does yours) and also noting the degree C was formed as one big character. Apologies for the blurry image, not helped with the scratchy plastic over the LCD to protect the glass...
Thanks for your patience and help.
Regards,
Bill
I replace the _ chr with @ dw 642 , 9266 ,72 in my fonts to get a deg C chr
correct , I know of no realistic way to smooth the result , it has been tried.Quote:
achieve double size by math so it probably means making a larger table to accommodate these
table size is only limited by the memory available.
if you create a large font say 14x10 for digits it would not be an unreasonable size, but would need its own routines to unpack and display
if you plot my font on graph paper its pretty obvious how it works, the pic 18 version is easier to disassemble
some 8x8 graphpaper
AND an old spread sheet that did the number crunching
I used a spreadsheet to convert my old 5 byte per character tables, too. Works a treat...
Cheerful regards, Mike
Attachment 8669
I came up with the same solution , the freely available font creators [like the mikronta one] don't really
convert the font to the most efficient format for pic's when codespace is an issue.
although they can be a good starting point
Nice job on the spreadsheet, Richard. I just finished modifying mine to format the packed font table output for either C or asm. Here's a sample;
Code:0x0000, 0x0000, 0x0000, // 32 ' '
0x0000, 0x2F80, 0x0000, // 33 '!'
0x0007, 0x0007, 0x0000, // 34 '"'
0x0A7F, 0x0A7F, 0x0A00, // 35 '#'
0x122A, 0x3FAA, 0x0900, // 36 '$'
0x1193, 0x0464, 0x3100, // 37 '%'
0x1B49, 0x2AA2, 0x2800, // 38 '&'
0x0005, 0x0180, 0x0000, // 39 '''
0x001C, 0x1141, 0x0000, // 40 '('
0x0041, 0x111C, 0x0000, // 41 ')'
0x0A08, 0x1F08, 0x0A00, // 42 '*'
0x0408, 0x1F08, 0x0400, // 43 '+'
I also decided to render all 96 characters directly from the input table so that I can see at-a-glance which characters might need tweaking...Code:dw 0x0000, 0x0000, 0x0000 ; 32 ' '
dw 0x0000, 0x2F80, 0x0000 ; 33 '!'
dw 0x0007, 0x0007, 0x0000 ; 34 '"'
dw 0x0A7F, 0x0A7F, 0x0A00 ; 35 '#'
dw 0x122A, 0x3FAA, 0x0900 ; 36 '$'
dw 0x1193, 0x0464, 0x3100 ; 37 '%'
dw 0x1B49, 0x2AA2, 0x2800 ; 38 '&'
dw 0x0005, 0x0180, 0x0000 ; 39 '''
dw 0x001C, 0x1141, 0x0000 ; 40 '('
dw 0x0041, 0x111C, 0x0000 ; 41 ')'
dw 0x0A08, 0x1F08, 0x0A00 ; 42 '*'
dw 0x0408, 0x1F08, 0x0400 ; 43 '+'
Attachment 8670
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
Attachment 8672
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
yes please, I had considered doing that but could not find a method that preserved the gainQuote:
Richard... Would you be interested in seeing my driver code for font tables
my attempts used half the saved space up doing the unpacking
First, here's how I'm packing font pattern data into 2-1/2 words within groups of 5 words;
Attachment 8679
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) //
{ //
} //
} //
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
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 yetQuote:
May 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
a saner way is, and let the linker locate the font for you
font .c file
in main.cCode:#include <xc.h>
#asm
psect FONT_table,class=CODE,local,delta=2
GLOBAL _FNT
_FNT
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 '&' '''
................
extern const char FNT;
int addr=&FNT;
in wrChar()
unsigned int dat, inx = addr;
char i = 5;
Hi Richard,
Well done to you and Mike for continuing the thread, even though what you are documenting is so far above my head I'm dizzy...
If I can jump in here I'd like to bring your attention to an undocumented feature of your Inc file I've just discovered when converting my previous code to run it. For various reasons, but mainly leading zero suppression, I insert a space but with your Inc file I get error messages e.g.
resulting inCode:looper:
LCDCLR
bigtxt = 1 ; double size chrs
LCDSTR 0,0,"Noki+12"
LCDSTR 0,2,"345678@"
bigtxt = 0 ; normal size chrs
' LCDSTR 52,3,"Demo"
LCDSTR 0,4,"With@MSSP xfer"
' LCDSTR 0,5,"Dble Size Chrs"
LCDSTR 0,5," " ; this doesn't compile - causes errors and warnings wherever used.
' LCDSTR 0,5,32 ; same result as above (worth a try).
PAUSE 1000
GOTO looper
[ASM ERROR] NOKIA_DEMO PPS.ASM (1701) : Illegal character (0)
[ASM WARNING] NOKIA_DEMO PPS.ASM (1701) : Found label after column 1. (LCDSTR?CCC)
When you have the time may I ask for this to be corrected?
Kind regards,
Bill
its a pbp problemQuote:
LCDSTR 0,5," "
" " is not a String pbp interprets a single chr as a byte , regardless of the quotes . and its not possible to fix it
you can simply use
LCDC " "
or
LCDC 0,5," "
to print a single character
have a look at this
http://support.melabs.com/forum/picb...strtok-usercmd
it has a rightjustify user command in it,
eg to display a 3 digit field
Code:arraywrite buff,[dec h,0]
RJUSTBUFF buff,3
LCDSTR 36,0,BUFF
Ah... Thank you for the PSECT search term. Got it. I also discovered that I could use a label in the font table and access that address in my code... Very exciting stuff (grin)...
I still need to double-check and simulate my XC8 version but so far it uses 381 words (141 code + 240 font). I didn't use MCC (Microchip Code Configurator) so it's a single file, about 235 lines, including the font table (see below).
MCC doesn't seem to support the MSSP module on my 16F1823 so I still need to consult the datasheet before I can implement the SPI driver.
Cheerful regards, Mike, K8LH
Code:/************************************************************************
* *
* Project: Nokia_Fonts *
* Source: Nokia_Main.c *
* Author: Mike McLaren, K8LH *
* (C)2013: Micro Application Consultants *
* Date: 25-May-2018 *
* *
* Experimental Nokia 5110 LCD display driver demo using a 96 *
* character packed 2.5-word-per-character 5x7 font table on a *
* PIC16F1823. *
* *
* IDE: MPLABX v4.05 *
* Lang: XC8 v1.45, Lite/Free version *
* *
************************************************************************/
/* CONFIG1 */
#pragma config FOSC = INTOSC // INTOSC oscillator: I/O on CLKIN pin
#pragma config WDTE = OFF // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = OFF // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = ON // MCLR/VPP pin function is MCLR
#pragma config CP = OFF // Code protection is disabled
#pragma config CPD = OFF // Data memory code protection disabled
#pragma config BOREN = ON // Brown-out Reset Enable
#pragma config CLKOUTEN = OFF // Clock Out Enable (off)
#pragma config IESO = OFF // Internal/External Switchover (off)
#pragma config FCMEN = OFF // Fail-Safe Clock Monitor Enable (off)
/* CONFIG2 */
#pragma config WRT = OFF // Write protection off
#pragma config PLLEN = OFF // PLL Enable (4x PLL disabled)
#pragma config STVREN = ON // Stack Overflow/Underflow Reset Enable
#pragma config BORV = LO // Brown-out Reset Low Trip Point
#pragma config LVP = ON // Low-Voltage Programming Enable
#include <xc.h>
#define _XTAL_FREQ 8000000
/************************************************************************
* *
************************************************************************/
#define rst RA0 // 5110 'reset'
#define dat RA1 // 5110 'din'
#define clk RA2 // 5110 'clk'
#define ce RC0 // 5110 'ce'
#define dc RC1 // 5110 'dc'
/************************************************************************
* *
************************************************************************/
void putwreg() // send byte, msb first
{ char work; //
asm("movwf putwreg@work "); //
ce = 0; // spi enable on
for(char n=0; n<8; n++) //
{ clk = 0; dat = 0; // "
if(work & 128) dat = 1; // "
clk = 1; work <<= 1; // "
} //
ce = 1; // spi enable off
} //
/************************************************************************
* *
************************************************************************/
void putcmd(char cmd) // bank 0 (inserted by compiler) |00
{ dc = 0; // command mode |00
asm("call _putwreg "); // |00
}
/************************************************************************
* *
************************************************************************/
void rdflash() //
{ asm("banksel EECON1 "); // bank 3 |03
asm("bcf EECON1,6 "); // CFGS = 0 (not config) |03
asm("bsf EECON1,7 "); // EEPGD = 1 (program memory) |03
asm("bsf EECON1,0 "); // RD = 1 (initiate read) |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) //
{ dc = 1; // set lcd 'data' mode |00
asm("movlw -32 "); // ascii 32..127 minus offset |00
asm("addwf wrchar@ascii,F "); // font array index, 0..95 |00
asm("lsrf wrchar@ascii,W "); // int(ascii *= 2.5) -> 0..237 |00
asm("addwf wrchar@ascii,W "); // " |00
asm("addwf wrchar@ascii,W "); // " |00
asm("movlb 3 "); // bank 3 |00
asm("movwf EEADRL "); // flash address lo |00
asm("movlw Font5x7/256 "); // |00
asm("movwf EEADRH "); // flash address hi |00
/* *
* Extract five bytes of pattern data from three memory words. An *
* even character uses word 0 hi + lo, 1 hi + lo, and 2 hi while *
* odd characters use word 0 lo, 1 hi + lo, and 2 hi + lo. A 6th *
* blank (zero) byte is sent for inter-character spacing. *
* */
asm("call _rdflash "); // read 1st word (2 bytes) |03
asm("banksel wrchar@ascii "); // bank 0 |00
asm("btfss wrchar@ascii,0 "); // odd char? yes, skip, else |00
asm("call _putwreg "); // send hi byte (even character) |00
asm("banksel EEDATL "); // bank 3 |03
asm("movf EEDATL,W "); // |03
asm("call _putwreg "); // send lo byte |00
asm("call _rdflash "); // read 2nd word (2 bytes) |03
asm("call _putwreg "); // send hi byte |00
asm("banksel EEDATL "); // bank 3 |03
asm("movf EEDATL,W "); // |03
asm("call _putwreg "); // send lo byte |00
asm("call _rdflash "); // read 3rd word (2 bytes) |03
asm("call _putwreg "); // send hi byte |00
asm("banksel EEDATL "); // bank 3 |03
asm("movf EEDATL,W "); // |03
asm("banksel wrchar@ascii "); // bank 0 |00
asm("btfsc wrchar@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 putstr(const char *str) // put 'ROM' strings
{ char n = 0; //
while(str[n++]) //
{ asm("call _putwreg "); //
}
}
/************************************************************************
* main setup *
************************************************************************/
void main(void)
{ ANSELA = 0; // Analog off (digital I/O)
ANSELC = 0; // "
TRISA = 0; //
TRISC = 0; //
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: ext 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: std instructions
putcmd(0x08+0x04); // display control: normal mode
/* *
* test the lcd print functions *
* */
putcmd(0x80+0x20); // set DDRAM X address, 0..83
putcmd(0x40+0x02); // set DDRAM Y address, 0..5
wrchar('R'); //
putstr("eady"); //
/************************************************************************
* main loop *
************************************************************************/
while(1)
{ //
} //
} //
/************************************************************************
* Packed 96 character 5x7 Font, 2.5-words-per-character, 240 words *
************************************************************************/
#asm
PSECT myFonts, class=CODE, abs, space=0, delta=2
ORG 700h
Font5x7:
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
/************************************************************************/
mike
mssp is pretty easy
SSP1CON1=0x21 ;$22,21,20 all work @32mhz 20 is fastest
SSP1STAT=0x40
sdo and sck pins set to dig o/p
to transfer data
PIR1.3=0
SSP1BUF = data
WHILE (!PIR1.3) ;
tried your code on 16f1847 ,its not working
It seems XC8 is placing my program code on top of my font table in the 0700h area of memory. More detective work (sigh)...
Thanks for the MSSP/SPI info, Richard. I will get to that after tracking down the current problem...
Mike
<added>
If you get a chance, add the "ovrld" param' to the following line and tell me if that fixes the problem, please?
Code:PSECT myFonts, class=CODE, abs, ovrld, space=0, delta=2
^^^^^
ovrld,
does not fix it
even local too
there is more wrong than just that , the putwreg function is getting called six times for the wrchar
and only 5 times for the entire putstr call
its a total bitch to debug with all that inline asm , the debugger just
goes stupid
putcmd looks fine on the logic analyser , it all goes pear shaped from then on
Sorry, Richard (and gang). A bug at the very top of the putchar() routine was messing up the font table address. And yes, I know assembler is a PITA... I wish I could get a gratis copy of PBP...
Corrected version attached (375 words total). I still need to dig out my old Nokia 5110 display and test this on real hardware. I also have a tiny 128x32 I2C OLED display and a tiny 128x64 SPI OLED display to play with sometime soon.
Cheerful regards, Mike
Attachment 8684
putstr still not working
I think it should look like this, but it only works for the first call
so I get "Re and then garbage
Code:void putstr(const char *str) // put 'ROM' strings
{ //
while(*str)
wrchar(*str++);
} //
more oddly
strcpy(buff,"eady");
putstr(buff);
works with my modified routine
putstr("eady");
crashes the show
fixed it, compiler optimised ascii var outCode:void wrchar(char d) //
{
volatile char ascii=d;
Yes, your putstr() routine is better...
While debugging I've found XC8 is using the same memory location for local variables in both the wrchar() and putstr() functions. The wrchar@ascii variable is using 70h and the putstr@str pointer is using 70h and 71h. Is this a result of my heavy use of assembly code? That is, XC8 doesn't realize those local variables need to be unique? How do I get XC8 to use unique memory locations for those local variables?
make them static
I think I prefer my take on this
since:-
the font is automatically located
the pin/hw defines are in mcc ,therefore its simple to port to any chip that can read its own flash
its easy to debug
bigtext and inverted text are easily implemented
its only 100 or so words bigger
font.cCode:/**
Product Revision : PIC10 / PIC12 / PIC16 / PIC18 MCUs - 1.65.2
Device : PIC16F1847
Driver Version : 2.00
* font.c included via ide source files
*/
#include "mcc_generated_files/mcc.h"
void putwreg(char work);
void putcmd(char x);
void WrChar(char );
void WrStr(const char *);
extern const char FNT;
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 d) { // for packed 2.5 word 5x7 font
uint16_t tmp, inx = (uint16_t) & FNT;
char fd[6], j = 0, k = 3, *pt;
inx += ((uint16_t) (d - 32)*5) >> 1;
while (k--) {
tmp = FLASH_ReadWord(inx++);
fd[j + 1] = tmp & 0x7f;
tmp <<= 1;
fd[j] = tmp >> 8;
j += 2;
}
pt = fd;
if ((d & 1))pt++;
k = 5;
// with font now stored in bufer fd its easy to have large and/or inverted text
while (k--) {
putwreg(*pt++);
}
putwreg(0);
}
void putcmd(char x) {
LCD_DC_SetLow();
putwreg(x);
LCD_DC_SetHigh();
}
void WrStr(const char *buff) {
{ //
while (*buff)
WrChar(*buff++); //
}
}
Code:#include <xc.h>
#asm
psect FONT_table,class=CODE,local,delta=2
GLOBAL _FNT
_FNT
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
tried a pbp version for the 5 byte compressed packed font, the unpacking done without asm
takes more code space than the compressing saves :frown:
inc file
Code:'****************************************************************
'* Name : NOKIA_ds5.INC *
'* Author : richard *
'* Notice : *
'* : *
'* Date : 26/05/2018 *
'* Version : 1.0b mssp1 version bigtxt *
'* Notes : inverse text mike 5 byte font version *
'* :FOR pic 16/18 NOKIA LCD *
'****************************************************************
goto overglcd
;##################################################################
; adjust these definitions to suit and place in main prg
'#DEFINE PIC16 1 ;IF PIC18 NOT USED
'#define use_mssp 1 ;if mssp used DON'T FORGET to set sdo and sck pins as o/p's
' lcdheight con 5 ; 6 PAGES
' lcdwidth con 84 ; 84 PIXELS WIDE
;--------------ONLY IF MSSP NOT USED---------------
' LCD_CLK var Portb.4 ' Clock
' LCD_DIN var Portb.2 ' Data
;-----------------------------------------
' LCD_RST var PortA.4
' LCD_DC var PortA.3
' LCD_CE var LATA.6
' LCD_LIGHT var PortA.0
;##################################################################
USERCOMMAND "LCDC" ;X,Y,CHR 0 < X < 84 , 0 < Y < 7 31 < CHR > 127
USERCOMMAND "LCDCLR" ;clear LCD
USERCOMMAND "LCDSTR" ;STRING @ X,Y or Constant String
USERCOMMAND "LCDCMD" ;cmd BYTE TO LCD
USERCOMMAND "LCDDAT" ;DATA BYTE TO LCD
ASM
;----[const String]---------------------------------------------------------------
LCDSTR?CCS macro Xin ,Yin,Cin
IFNDEF TBLPTRL
local TheString, OverStr ; define local labels so you can call macro multiple times
goto OverStr ; goto over string stored in FLASH, so processor can't execute that
TheString ;label to get address of your string
da Cin, 0 ;add string to flash at TheString address and end string with 0
OverStr
MOVE?CW TheString, _glcd_bigaddress
MOVE?CB Xin , _POSX
MOVE?CB Yin , _POSY
L?CALL _GlcdUnpackStr
ELSE
local TheString, OverStr ; define local labels so you can call macro multiple times
goto OverStr ; goto over string stored in FLASH, so processor can't execute that
TheString ;label to get address of your string
data Cin, 0 ;add string to flash at TheString address and end string with 0
OverStr
movlw UPPER TheString
movwf TBLPTRU
movlw HIGH TheString
movwf TBLPTRH
movlw LOW TheString
movwf TBLPTRL
MOVE?CB Xin , _POSX
MOVE?CB Yin , _POSY
L?CALL GLCD_Cstr_out
ENDIF
endm
;----------------------Strings------------------------------------
LCDSTR?CBB macro Xin ,Yin ,Bin
MOVE?CB Xin , _POSX
MOVE?BB Yin , _POSY
MOVE?CB high Bin, FSR1H ;load highbyte
MOVE?CB low Bin, FSR1L ;load low byte
L?CALL GLCD_str_out
endm
LCDSTR?CCB macro Xin ,Yin ,Bin
MOVE?CB Xin , _POSX
MOVE?CB Yin ,_POSY
MOVE?CB high (Bin), FSR1H ;load highbyte
MOVE?CB low (Bin), FSR1L ;load low byte
L?CALL GLCD_str_out
endm
LCDSTR?BBB macro Xin ,Yin ,Bin
MOVE?B Xin, _POSX
MOVE?B Yin, _POSY
MOVE?CB high Bin, FSR1H ;load highbyte
MOVE?CB low Bin, FSR1L ;load low byte
L?CALL GLCD_str_out
endm
LCDSTR?WBB macro Xin ,Yin ,Bin
MOVE?WB Xin, _POSX
MOVE?BB Yin, _POSY
MOVE?CB high Bin, FSR1H ;load highbyte
MOVE?CB low Bin, FSR1L ;load low byte
L?CALL GLCD_str_out
endm
LCDSTR?WWB macro Xin ,Yin ,Bin
MOVE?WB Xin, _POSX
MOVE?WB Yin, _POSY
MOVE?CB high Bin, FSR1H ;load highbyte
MOVE?CB low Bin, FSR1L ;load low byte
L?CALL GLCD_str_out
endm
LCDCMD?C macro Cin
MOVE?CT 0,_LCD_DC
MOVE?CB Cin , _lcdData
L?CALL _lcd_byte
endm
LCDCMD?B macro Cin
MOVE?CT 0,_LCD_DC
MOVE?BB Cin , _lcdData
L?CALL _lcd_byte
endm
LCDCMD?W macro Cin
MOVE?CT 0,_LCD_DC
MOVE?WB Cin , _lcdData
L?CALL _lcd_byte
endm
LCDDAT?C macro Cin
MOVE?CT 1,_LCD_DC
MOVE?CB Cin , _lcdData
L?CALL _lcd_byte
endm
LCDDAT?B macro Cin
MOVE?CT 1,_LCD_DC
MOVE?BB Cin , _lcdData
L?CALL _lcd_byte
endm
LCDDAT?W macro Cin
MOVE?CT 1,_LCD_DC
MOVE?WB Cin , _lcdData
L?CALL _lcd_byte
endm
LCDCLR? macro
L?CALL _lcd_clr
endm
;----------------------Character @ X,Y ------------------------------------
LCDC?BBB macro Xin ,Yin , Bin
MOVE?BB Xin, _POSX
MOVE?BB Yin, _POSY
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
LCDC?WBB macro Xin ,Yin , Bin
MOVE?WB Xin, _POSX
MOVE?BB Yin, _POSY
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
LCDC?WWB macro Xin ,Yin , Bin
MOVE?WB Xin, _POSX
MOVE?WB Yin, _POSY
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
LCDC?BBC macro Xin ,Yin , Cin
MOVE?BB Xin, _POSX
MOVE?BB Yin, _POSY
MOVE?CB Cin ,_glcdCh
L?CALL _gcga
endm
LCDC?WBC macro Xin ,Yin , Cin
MOVE?WB Xin, _POSX
MOVE?BB Yin, _POSY
MOVE?CB Cin ,_glcdCh
L?CALL _gcga
endm
LCDC?CCC macro Xin ,Yin ,Cin
MOVE?CB Xin , _POSX
MOVE?CB Yin, _POSY
MOVE?CB Cin, _glcdCh
L?CALL _gcga
endm
LCDC?CCB macro Xin ,Yin ,Bin
MOVE?CB Xin , _POSX
MOVE?CB Yin, _POSY
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
LCDC?B macro Bin
MOVE?BB Bin, _glcdCh
L?CALL _gcga
endm
GLetAddress macro Label, Wout
CHK?RP Wout
movlw low Label ; get low byte
movwf Wout
movlw High Label ; get high byte
movwf Wout + 1
BANKSEL 0
endm
IFDEF TBLPTRL
GLCD_Cstr_out
tblrd *+
movf TABLAT,w
bz GLCD_exit_Cstr_out ; EXIT ON Null char
CHK?RP _glcdCh
MOVWF _glcdCh
CHK?RP _glcd_bigaddress
movff TBLPTRU,_glcd_bigaddress
movff TBLPTRH,_glcd_bigaddress+1
movff TBLPTRL,_glcd_bigaddress+2
L?CALL _gcga
CHK?RP _glcd_bigaddress
movff _glcd_bigaddress ,TBLPTRU
movff _glcd_bigaddress+1 ,TBLPTRH
movff _glcd_bigaddress+2 ,TBLPTRL
bra GLCD_Cstr_out
GLCD_exit_Cstr_out
BANKSEL 0
return
GLCD_str_out
movf POSTINC1, W ; Get a character
bz GLCD_exit_strout ; EXIT ON Null char
CHK?RP _glcdCh
MOVWF _glcdCh
BANKSEL 0
L?CALL _gcga
bra GLCD_str_out
GLCD_exit_strout
BANKSEL 0
return
ELSE
GLCD_str_out
IFDEF BSR
MOVIW FSR1++ ; Get a character
BTFSC STATUS,Z
BRA GLCD_exit_strout ; EXIT ON Null char
ELSE
movf INDF, W ; Get a character
BTFSC STATUS,Z
GOTO GLCD_exit_strout ; EXIT ON Null char
INCF FSR,F
ENDIF
CHK?RP _glcdCh
MOVWF _glcdCh
MOVE?BB FSR1L,_glcd_bigaddress
MOVE?BB FSR1H,_glcd_bigaddress+1
BANKSEL 0
L?CALL _gcga
MOVE?BB _glcd_bigaddress,FSR1L
MOVE?BB _glcd_bigaddress+1,FSR1H
GOTO GLCD_str_out
GLCD_exit_strout
BANKSEL 0
return
ENDIF
endasm
glcd_bigaddress VAR BYTE[3]
glcdCh var byte 'chr DATA
lcdData VAR byte 'DATA
glcdDC VAR BYTE 'gca var
glcdFont var word 'font address
glcdOffset VAR word 'font offset
dsfbuff var byte[26]
ctemp1 var word
gl var byte
glcdBc var byte
POSY var byte 'gca pg address
gy_ var byte 'gca pg address
POSX var byte 'gca row address
gx_ var byte 'gca row address
ctemp var word
glcdStrAddr var word ext
bigtxt var bit
inverted var bit
@glcdStrAddr = _glcd_bigaddress
GlcdUnpackStr:
readcode glcdStrAddr,CTEMP
glcd_bigaddress[2] = CTEMP&$7f
ctemp=ctemp<<1
glcdCh = CTEMP.HIGHBYTE
glcdStrAddr=glcdStrAddr+1
if glcdCh then
gosub gcga
glcdCh = glcd_bigaddress[2]
else
return
endif
if glcdCh then
gosub gcga
else
return
endif
goto GlcdUnpackStr:
return
lcd_init:
@ GLetAddress _font7x5,_glcdFont
bigtxt = 0
inverted =0
#ifdef use_mssp
SSP1CON1=$21 ;$22,21,20 all work @32mhz 20 is fastest
SSP1STAT=$40
#endif
LCD_CE=1
pause 30
Lcd_RST = 0 ' Reset LCD (HW reset)
pause 1
Lcd_RST = 1 ' Release Reset
' lcd_dc=0
LCDCMD $21 ' LCD EXTENDED COMMANDS
LCDCMD $c8 ' SET LCD Vop (CONTRAST) initial value $C8 = 200.
LCDCMD $06 ' SET TEMP COEFFICIENT
LCDCMD $13 ' LCD BIAS MODE
LCDCMD $20 ' LCD STANDARD COMMANDS
LCDCMD $08 ' LCD blank
LCDCMD $0c ' LCD IN NORMAL MODE
return
lcd_clr: ' clear
FOR gy_ =0 TO 5
FOR GX_=0 TO 83
LCDDAT 0
NEXT
NEXT
return
lcd_byte: 'send command sequence "glcdData "
LCD_CE=0
#ifdef use_mssp
PIR1.3=0
SSP1BUF = LcdData
WHILE !PIR1.3 : wend
#else
PAUSEUS 150
SHiftOUT LCD_DIN,LCD_CLK,1,[LcdData]
#endif
LCD_CE=1
return
LCDxy: ;set LCD XY
POSY = POSY MIN lcdheight
POSX = POSX MIN lcdwidth
LCDCMD POSY|$40
LCDCMD POSX|$80
return
gcga: ;unpack font from flash and display it
#ifdef PIC16
glcdOffset = (glcdch-32)*5/2 + glcdFont ; point to cga data
#ELSE
glcdOffset = (glcdch-32)*6 + glcdFont ; point to cga data
#ENDIF
gosub LCDxy
#ifdef PIC16
' ; COMMENT OUT THIS ASM SECTION IF CHIP HAS NO EEDAT REG
' ASM
' MOVE?CB high _dsfbuff, FSR1H ;load highbyte
' MOVE?CB low _dsfbuff, FSR1L ;load low byte
' MOVE?WW _glcdOffset,EEADRL
' MOVE?CB 3,_glcdDC
'nxtf
' BANKSEL EECON1
' BSF EECON1, EEPGD ;Point to PROGRAM memory
' BSF EECON1, RD ;EE Read
' NOP
' NOP
' RLF EEDAT, W
' RLF EEDATH, W
' MOVE?AB _glcdBc
' BANKSEL EEDAT
' BCF EEDAT,7
' MOVF EEDAT,W
' MOVWI FSR1++
' MOVE?BA _glcdBc
' MOVWI FSR1++
' BANKSEL EEADRL
' incf EEADRL,F
' btfsc STATUS,Z
' incf EEADRH,F
' BANKSEL _glcdDC
' DECFSZ _glcdDC,F ;dec count
' GOTO nxtf
' BANKSEL 0
' ENDASM
; UNCOMMENT IF CHIP HAS NO EEDAT REG
glcdBc=0
gosub getflash
if !glcdch.0 then
dsfbuff[glcdBc] = CTEMP.HIGHBYTE
glcdBc=glcdBc+1
endif
dsfbuff[glcdBc] = glcdDC
glcdBc=glcdBc+1
gosub getflash
dsfbuff[glcdBc] = CTEMP.HIGHBYTE
glcdBc=glcdBc+1
dsfbuff[glcdBc] = glcdDC
glcdBc=glcdBc+1
gosub getflash
dsfbuff[glcdBc] = CTEMP.HIGHBYTE
if glcdch.0 then
glcdBc=glcdBc+1
dsfbuff[glcdBc] = glcdDC
endif
dsfbuff[5] = 0
#else
for glcddc = 0 to 2
dsfbuff[glcddc*2] = CTEMP
dsfbuff[glcddc*2+1] = CTEMP.HIGHBYTE
glcdOffset = glcdOffset + 2
NEXT
#endif
if inverted then
for glcddc = 5 to 0 STEP -1
dsfbuff[glcddc]=~dsfbuff[glcddc]
next
endif
if bigtxt then ;create a big chr from a small one
DSFBUFF[24] = POSX
DSFBUFF[25] = POSy
for glcddc = 5 to 0 STEP -1
ctemp = 0
ctemp1 = 3
gL = dsfbuff[glcddc]
for glcdBc = 0 to 7
IF GL & 1 THEN ctemp = ctemp|ctemp1
ctemp1 = ctemp1<<2
GL = GL>>1
NEXT
gL = glcddc*2
dsfbuff[GL] =ctemp.LOWBYTE
dsfbuff[GL+1] =ctemp.LOWBYTE
dsfbuff[GL+12]=ctemp.HIGHBYTE
dsfbuff[GL+13]=ctemp.HIGHBYTE
NEXT
for glcddc = 0 to 11
LCDDAT dsfbuff[GLCDDC]
NEXT
POSY=POSY+1
POSX=DSFBUFF[24]
gosub LCDxy
for glcddc = 12 to 23
LCDDAT dsfbuff[GLCDDC]
NEXT
POSx = POSX + 12
IF POSX > 72 THEN POSX=0 ;wrap
posy=DSFBUFF[25]
else
for glcddc = 0 to 5
LCDDAT dsfbuff[GLCDDC]
NEXT
POSx = POSX + 6
IF POSX > 78 THEN POSX=0 ;wrap
endif
RETURN
getflash:
readcode glcdOffset,CTEMP
glcdDC= CTEMP&$7f
ctemp = ctemp << 1
glcdOffset = glcdOffset + 1
return
overglcd :
demo file
Code:'****************************************************************
'* Name : NOKIA_DEMO.PBP *
'* Author : richard *
'* Notice : *
'* : *
'* Date : 16/5/2018 *
'* Version : mssp1 version with bigtxt ,inverse txt *
'* Notes : used mikes compressed packed 5 byte font *
'* :FOR pic 16F1847@32MHZ NOKIA *
'****************************************************************
#CONFIG ; 16FF1847.
__config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _BOREN_OFF
__config _CONFIG2, _PLLEN_OFF & _LVP_OFF
#ENDCONFIG
define OSC 32
; --- *** Oscillator *** ---------------------------------------------------
OSCCON = %11110000 ;32 MHz,
ANSELb = 0
ANSELA = 0
TRISA=%10010000
TRISB=%11101011
;DEFINES FOR DISPLAY use font7x5_16.bas or font7x5_18.bas for pic18
#DEFINE PIC16 1
#define use_mssp 1
lcdheight con 5 ; 6 PAGES
lcdwidth con 83 ; 84 PIXELS WIDE
' LCD_CLK var LATB.4 ' SCK1 pin needs to be set as dig o/p
' LCD_DIN var LATB.2 ' SDO1 pin needs to be set as dig o/p
LCD_RST var LATA.4
LCD_DC var LATA.3
LCD_CE var LATA.6
LCD_LIGHT var LATA.0
BUFF VAR BYTE [16]
char VAR BYTE
Include "nokia_ds5.inc" ' bring it in
include "font7x5_16_5.bas"
'========================== MAIN Routine ==============================
gosub lcd_init
LCDCLR
ARRAYWRITE BUFF,["READY",0]
inverted=1
LCDSTR 5,2,BUFF
PAUSE 1000
LCDCLR
inverted=0
bigtxt = 1
LCDSTR 5,2,BUFF
PAUSE 1000
LCDCLR
bigtxt = 0
posx=0
posy=0
gosub LCDxy
char=32
looper:
lcdc char
while posx
char=char+1
if char>127 then char=32
lcdc char
PAUSE 100
wend
posy=posy+1
if posy>5 then
posy=0
gosub LCDxy
PAUSE 1000
endif
GOTO LOOPER
'
END
font
Code:'****************************************************************
'* Name : font7x5_16_5.BAS *
'* Author : mike *
'* Notice : *
'* : *
'* Date : *
'* Version : 1.0 *
'* Notes : *
'* : *
'****************************************************************
goto overfont
font7x5: ;14BIT PACKED FORMAT [2X7BITS] CHR32-126 [SP TO ~ ]
asm
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
overfont:
dittoQuote:
Thank you very much for the pointers and help. It's been a fun experiment and I've learned a lot.
and I finally figured out what I was doing wrong with asm psect labels
whats next
a ttf
a double size font for digits (0 to 9 +- : )
Hi Richard,
Thanks for the fix on the single char problem, it works well but I've found another problem...
When I add DT Ints the big characters don't work, I tried with and without using mssp but same result.
Also there's something strange taking place with the led backlight insomuch as I need to sprinkle port pin enable code immediately following any lcd write (with or without DT Ints). I tried changing LCD_LIGHT from A.0 to A.1 (while leaving it connected to A.0) with no difference - does the Inc file employ any commands for the light?
Here's the edited code:
Is the Inc file compatible with DT Ints?Code:#CONFIG ; 16F1847.
__config _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_ON & _CP_OFF & _BOREN_OFF
__config _CONFIG2, _PLLEN_OFF & _LVP_OFF
#ENDCONFIG
@ ERRORLEVEL -306 ; turn off crossing page boundary message
; --- *** Oscillator *** ---------------------------------------------------
define OSC 32
OSCCON = %11110000 ; 32 MHz,
ANSELA = 0 ; all digital
ANSELB = 0 ; all digital
TRISA=%00000000
'TRISB=%00000000
TRISB=%11101011 ; Encoder inputs on B5-7
ch var byte
BUFF VAR BYTE [10]
;DEFINES FOR DISPLAY use font7x5_16.bas or font7x5_18.bas for pic18
#DEFINE PIC16 1
#define use_mssp 1 ; much faster and less words (1027 vs 1106).
lcdheight con 5 ; 6 PAGES
lcdwidth con 83 ; 84 PIXELS WIDE
LCD_RST var LATA.4
LCD_DC var LATA.3
LCD_CE var LATA.6
LCD_LIGHT var LATA.0
LCD_CLK var LATB.4 ' SCK1 pin needs to be set as dig o/p
LCD_DIN var LATB.2 ' SDO1 pin needs to be set as dig o/p
;--------------ONLY IF MSSP NOT USED---------------
' LCD_CLK var Portb.4 ' Clock
' LCD_DIN var Portb.2 ' Data
Include "Modedefs.bas"
INCLUDE "DT_INTS-14.bas" ' Base Interrupt System
INCLUDE "ReEnterPBP.bas" ' Include if using PBP type interrupts
Include "nokia_ds.INC" ' bring it in
include "font7x5_16.bas"
'include "font7x5_16 edit degC.BAS" ; use @ to access degC symbol.
ASM
INT_LIST macro ; IntSource, Label, Type, ResetFlag?
INT_Handler IOC_INT, _Rot_Encoder, PBP, yes
endm
INT_CREATE ; Creates the interrupt processor
ENDASM
@ INT_ENABLE IOC_INT ; Port Change Interrupt
'========================== MAIN Routine ==============================
gosub lcd_init
LCDCLR
ARRAYWRITE BUFF,["READY",0]
LCDSTR 5,0,BUFF
PortA.0 = 0 ' turn on backlight.
PAUSE 1000
LCDCLR
PAUSE 1000
looper:
LCDCLR
PortA.0 = 0 ' turn on backlight.
bigtxt = 1 ; double size chrs
LCDSTR 0,0,"Noki+12"
LCDSTR 0,2,"345678@"
bigtxt = 0 ; normal size chrs
' LCDSTR 52,3,"Demo"
' LCDSTR 0,4,"With@MSSP xfer"
LCDSTR 0,4,"Hi"
PortA.0 = 0 ' turn on backlight.
' LCDSTR 0,5,"Dble Size Chrs"
' LCDSTR 0,5," " ; this doesn't compile - causes errors and warnings wherever used.
LCDC 0,5,"a" ; use LCDC for single chars.
PortA.0 = 0 ' turn on backlight.
PAUSE 1000
GOTO looper
Rot_Encoder:
' if PortB.7 = 0 then ' Check if Encoder pushbutton was pushed.
' ButtPush = 1 ' Set the flag for a quick exit.
' Old_Bits = New_Bits ' Equalize the disturbance the pushbutton caused.
@ INT_RETURN ; Exit accordingly.
' endif
END
Regards,
Bill