// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // LCD display driver // // This is the basic driver for LCD-graphic Display Modules. At // the moment works but still needs some more work, it is included // here so that useres may get an idea of how to drive one of these // 128 x 64 pixel arrays, see also the LCD-Graphic-T.fth in the // examples folder. // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // HISTORY: // ******************************************************* // // ******************************************************* // // REQUIRES: // #URL-lib "http://pin1.org/forthlib/flb/General/pinsel.flb" // LCD Pin // 1 0V // 2 + // 3 contrast GND // 4 RS - H=data, L=instruction // 5 R/W h=read // 6 E enable // 7 D0 // 8 D1 // 9 D2 // 10 D3 // 11 D4 // 12 D5 // 13 D6 // 14 D7 // 15 CS1 // 16 CS2 // 17 /RST // CONSTANTS: // ========= change this section to match the display =============== // constants used for different display types, the value is // the command + &80 to return the cursor to the start of // the row. This can be found by trial and error using LCDDD 0 constant row0 64 constant row1 20 constant row2 84 constant row3 // constants relate pin numbers to function, note they do not // relate the port, this is done in the actual code -27 constant RS -28 constant RW 23 constant E -29 constant D0 20 constant D1 19 constant D2 18 constant D3 -30 constant D4 -20 constant D5 17 constant D6 16 constant D7 // 14 constant CS1 -22 constant CS2 13 constant /RST // // Variables variable LCDpen // used for pen up/ doen in graphics section // ================ Basic elements section =============== // set up ports, this relates the port and pin numbers as // port 0 and port 1 can be used, set to all o/p for now : LCDctrl RS io-out RW io-out E io-out CS1 io-out CS2 io-out /RST io-out ; // data separate because this could be read or write : LCDdin D0 io-in D1 io-in D2 io-in D3 io-in D4 io-in D5 io-in D6 io-in D7 io-in ; // : LCDdout D0 io-out D1 io-out D2 io-out D3 io-out D4 io-out D5 io-out D6 io-out D7 io-out ; // // set controls CHECK and CHANGE if PORT 0 or 1 // ( 1|0 --- ) : LCDrs RS p! ; : LCDrw RW p! ; : LCDe E p! ; : LCDcs1 CS1 p! ; : LCDcs2 CS2 p! ; : LCDrst /RST p! ; // sends a byte to the lcd display // ( 8 bit value ---) : LCDout 1 LCDe // place data on bus dup 1 and D0 p! // D0 1 rshift // next bit dup 1 and D1 p! // D5 1 rshift // next bit dup 1 and D2 p! // D6 1 rshift // next bit dup 1 and D3 p! // D4 1 rshift // next bit dup 1 and D4 p! // D4 1 rshift // next bit dup 1 and D5 p! // D5 1 rshift // next bit dup 1 and D6 p! // D6 1 rshift // next bit 1 and D7 p! // D7 // send 0 LCDe // 100 for next ; // reads the display data at the current // address // ( --- n) : LCDread LCDdin 1 LCDrw // read 1 LCDrs 1 LCDe 0 LCDe // pulse 1 LCDe 0 // start value // get values on databus D7 p@ if 1+ then // D7 1 lshift // next bit D6 p@ if 1+ then // D6 1 lshift // next bit D5 p@ if 1+ then // D5 1 lshift // next bit D4 p@ if 1+ then // D4 1 lshift // next bit D3 p@ if 1+ then // D3 1 lshift // next bit D2 p@ if 1+ then // D2 1 lshift // next bit D1 p@ if 1+ then // D1 1 lshift // next bit D0 p@ if 1+ then // D1 0 LCDrw // write (lcd i/p) LCDdout // back to normal state ; // // reset display using /RST : LCDreset 0 LCDrst 1 ms 1 LCDrst ; // ( n --- ) : LCDdata 1 LCDrs 0 LCDrw // write LCDout // 1 LCDrs ; // ( n --- ) : LCDcmd 0 LCDrs 0 LCDrw // write LCDout // 1 LCDrs ; : LCDinit LCDctrl // set up ports for o/p LCDdout 0 LCDrs // command 0 LCDrw // write LCDreset // pulse reset line 1 LCDcs1 1 LCDcs2 // switch on both displays &3f LCDcmd 10 ms // display on 1 LCDrs // data ; // ========== Basic x y positioning section ===================== // NOTE X AND Y ARE AS THE DATAHEET WHICH IS OPPOSITE CONVENTION // X is vertical and Y is horizontal // ( n --- ) panel select 0 = left 1 = right : LCDpanel if 0 LCDcs1 1 LCDcs2 else 1 LCDcs1 0 LCDcs2 then ; // ( n --- ) n= 0 to 7 : LCDxpos 7 min &b8 + LCDcmd ; // ( n --- ) n = 0 to 127 : LCDypos // -- accross both panels 127 min dup 63 > if 1 LCDpanel 64 - else 0 LCDpanel then &40 + LCDcmd ; // positions the cursor at x,y for reading or writing : LCDxy ( x y --- ) LCDypos LCDxpos ; // fills display with single byte // (x ---) : LCDfill 8 for // x 128 for // y j i LCDxy dup LCDdata next next drop ; // clears screen by filling with all 0xff : LCDcls &ff LCDfill ; // ============== GRAPHICS section ===================== // This section has words for drawing pixels, lines and boxes // It uses a variable called LCDpen, pen up or down to // determines if a line is drawn or erased. Conventional X Y // co-ordinates used X= horizontal, Y = vertical // x,y=0 is top left corner, x goes to the right max 128 and // y goes dowmnawards max 64 // Pen down or up stored as a variable : LCDpenDown 1 LCDpen ! ; : LCDpenUp 0 LCDpen ! ; // Draws one pixel at the given co-ordinates if pen down // Erases one pixel if pen up. // ( x y --- ) : LCDpix // Y is the vertical (opposite to datasheet) 8 /mod // get which row of bytes // the following is done twice because LCDread advances the address rot 2dup LCDxy LCDread >r LCDxy 1 swap lshift // move to pixel LCDpen @ // pen down or up if &ff swap bic r> and LCDdata // write else r> or LCDdata // write then ; // Draws Horizontal line, uses pendown/up // ( x y len --- ) : LCDver for 2dup // x y LCDpix 1+ // increment y next 2drop ; // Draws Vertical line, uses pendown/up // ( x y len --- ) : LCDhor for 2dup // x y LCDpix 1 +under // increment x next 2drop ; // Draws a box from top left to bottom right using // 4 co-ordinates // ( x1 y1 x2 y2 --- value) : #LCDhl# drop swap drop swap - 1+ ; // (x1,y1,x2,y2--Hl) [y2-y1] : #LCDvl# swap drop swap - swap drop 1+ ; // (x1,y1,x2,y2--Vl) [x2-x1] : #4dup# 2over 2over ; : #x2y1# drop rot drop swap ; : #x1y2# swap drop swap drop ; // x1,y1 = top left // x2,y2 = bottom right // ( x1 y1 x2 y2 --- ) : LCDbox #4dup# #LCDhl# >r 2over r> LCDhor // x1, y1, (HL) #4dup# #LCDvl# >r 2over r> LCDver // x1, y1, (VL) #4dup# #LCDhl# >r #4dup# #x1y2# r> LCDhor // x2, y1, (HL) #4dup# #LCDvl# >r #x2y1# r> LCDver // x1, y2, (VL) ; // given a 32bit word displays it as a horizontal // graphic starting at x,y // ( x y word ---) : #LCDmap# 32 for 1 lshiftc lcdpen ! >r 2dup LCDpix 1 +under // increment x r> next 2drop drop ; // Map is an easy what to create graphics. A 32bit // word represents 32 horizontal pixels starting at x,y // map-addr is the address of 32 bit words to map to the display // bit 1 is on and bit 0 is off // ( x y map-addr len ---) : LCDmap for dup >r @ >r 2dup r> #LCDmap# 1+ // increment y r> 4 + // next word next drop 2drop ;