To use this file copy and paste this:    // #URL-lib "http://pin1.org/forthlib/flb/General/LCD-Graphic.flb"   into BV Terminal 3 or here to download.

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 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"

// 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


Full Contents of File

// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
// 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 --- )
: LCDrsRS  p!  ;
: LCDrwRW  p!  ; 
: LCDeE  p!  ;
: LCDcs1CS1  p!  ;
: LCDcs2CS2  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
: LCDreset0  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
: LCDpanelif  0  LCDcs1  1  LCDcs2  else  1  LCDcs1  0  LCDcs2  then  ;
// ( n --- ) n= 0 to 7
: LCDxpos7  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
: LCDpenDown1  LCDpen  !  ;
: LCDpenUp0  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
;