fl { i2c-charcterLCD made by using GPIO_Expander(PCF8574) Used 4bit-mode on characterLCD PropForth 5.5 2014/04/15 11:31:54 Character-LCD PCF8574 module Propeller Vcc -------- 3.3V GND -------- GND SDA -------- P29 SCL -------- P28 DB4 ----- P0 DB5 ----- P1 DB6 ----- P2 DB7 ----- P3 RS ----- P4 E ----- P5 LED- -Tr - P6 A0 -------- GND A1 -------- GND A2 -------- GND SDA data-bit bit7 bit6 bit5 bit4 bit3 bit2 bit1 bit0 LCD pin LED- E RS DB3 DB2 DB1 DB0 } \ =========================================================================== \ i2c \ =========================================================================== \ Modified _eewrite ( c1 -- t/f ) write c1 to the eeprom, true if there was an error \ Received acknowledge from i2c-device during scl is high \ scl/sda use pull-up resistor at hi \ clock:400kHz lockdict create _eewrite forthentry $C_a_lxasm w, h12C h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z2WyPW8 l, z1YVPQ0 l, z1rixnd l, z1Sy\C] l, z1[ixne l, z1Sy\C] l, z1bixne l, zfyPO1 l, z3[yP[K l, z1[ixnd l, z1Sy\C] l, z1[ixne l, z1Sy\C] l, z1YF\Nl l, z1viPR6 l, z1bixne l, z1Sy\C] l, z1bixnd l, z1SV01X l, z2WyPc7 l, z20iPik l, z3ryPb0 l, z1SV000 l, zW0000 l, zG0000 l, freedict { \ _eeread ( t/f -- c1 ) flag should be true is this is the last read \ scl/sda use pull-up resistor at hi \ clock:400kHz lockdict create _eeread forthentry $C_a_lxasm w, h12D h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z2WiPZB l, z2WyPO0 l, z1[ixne l, z2WyPj8 l, z1Sy\Ka l, z1[ixnf l, z1Sy\Ka l, z1XF\Vl l, znyPO1 l, z1bixnf l, z3[yPnN l, z26VPW0 l, z1rixne l, z1Sy\Ka l, z1[ixnf l, z1Sy\Ka l, z1bixnf l, z1bixne l, z1Sy\Ka l, z1SV01X l, z2WyPc3 l, z20iPik l, z3ryPb0 l, z1SV000 l, zW0000 l, zG0000 l, freedict } : err_msg ." I2C error" ; \ If error, print message \ ( n1 -- ) n1:t/f : err? if err_msg cr then ; \ Start i2c-commnication \ ( -- ) : _eestart _sdal _sdao \ Set sda to lo _scll _sclo \ Set scl to lo ; \ Stop i2c-commnication \ ( -- ) : _eestop _scli \ Release scl _sdai \ Release sda ; \ Display connected i2c-device's slave-address \ ( -- ) : i2c_detect hex \ Print lower ." 0 1 2 3 4 5 6 7 8 9 A B C D E F" cr \ ( n1 n2 ) n1:reserve address 's count n2:i2c_device's count n3:i2c_address 0 0 0 8 0 do \ Print 1-line dup .byte h3A emit space d16 0 do \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) dup i + 1 lshift _eewrite 0= if \ there is ACK dup i + dup .byte \ Get slave-addres dup 7 > swap h78 < and \ 0 to 7 and h78 to h7F if swap 1+ swap \ Count up device (eliminate reserve number) else rot 1+ rot2 then else ." --" then space \ Stop I2C _eestop loop cr \ next line d16 + loop drop decimal ." i2c_device:" . cr 0> if ." [0 - 7] and [h78 - h7F] are reserve-address" then cr cr ; \ =========================================================================== \ Constants \ =========================================================================== \ Slave addres h20 for PCF8574 h40 wconstant PCF8574 \ A2=A1=A0=0 0 wconstant addr_input h10 wconstant RS h20 wconstant E h40 wconstant LED- \ =========================================================================== \ Variables \ =========================================================================== wvariable char \ character number for using LCD wvariable line \ line number for using LCD wvariable cur_line \ current line number \ =========================================================================== \ Command for PCF8574 \ =========================================================================== \ Write 2bytes \ ( -- ) : swap_wr swap _eewrite or ; \ Output data[E(bit5) + RS(bit4) + lcd4bit(bit0-3)] to ports of PF8574 \ ( n1 n2 -- ) n1:data[4bit] n2:E+data[4bit] : out_PCF8574 \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) PCF8574 addr_input 1 lshift or _eewrite \ ( n1 n2 t/f ) swap_wr \ ( n1 t/f ) swap_wr \ ( t/f ) _eestop err? ; \ Output data[E(bit5) + RS(bit4) + lcd4bit(bit0-3)] to ports of PF8574 \ ( n1 -- ) n1:RS+data : GPIO dup E or \ Add E bit ( n1 E+n1 ) \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) PCF8574 addr_input 1 lshift or _eewrite \ ( n1 E+n1 t/f ) swap_wr \ ( n1 t/f ) swap_wr \ ( t/f ) _eestop err? ; \ =========================================================================== \ Command for LCD \ =========================================================================== \ Send command to HD44780 \ (n -- ) n:RS(bit8) data[bit7:0] : lcd_com dup h100 and if RS else 0 then \ RS bit swap 2dup \ ( h10/0 n h10/0 n ) \ upper 4bit 4 rshift hF and or \ ( h10/0 n RS+data[upper4bit] ) Add RS-bit to data LED- or GPIO 1 delms \ lower 4bit \ ( 10/0 n ) hF and or \ ( RS+data[upper4bit] ) Add RS-bit to data LED- or GPIO 1 delms ; \ Initialize HD44780 \ ( -- ) : lcd_init 0 0 out_PCF8574 \ 8bit mode d50 delms \ wait 50msec 3 h23 out_PCF8574 5 delms \ wait 5msec 3 h23 out_PCF8574 1 delms \ wait 1msec 3 h23 out_PCF8574 5 delms \ wait 5msec 2 h22 out_PCF8574 \ 1 delms \ 4bit mode h28 lcd_com \ FunctionSet DL=0 N=1 F=0 hC lcd_com \ DisplaySwitch D=1 C=B=0 1 lcd_com \ ScreenClear 6 lcd_com \ InputSet I/D=1 S=0 LED- 0 out_PCF8574 \ Backlight on d16 char W! 2 line W! \ defsult setting is 16Charcters & 2Lines ; \ Display character \ ( c -- ) c:character : lcd_char h100 or \ Add RS=1 to character-code lcd_com ; \ Set position to (x,y) \ x -- horizontal pos : 0x1 to 0x28 (decimal: 1 to 40Characters) \ y -- line number : 0x1 to 0x4 (decimal: 1 to 4Lines) \ DDRAM addres of 16X4 CHaracter-LCD \ 1Line [h00 ------ h0F] \ 2Line [h40 ------ h4F] \ 3Line [h10 ------ h1F] \ 4Line [h50 ------ h5F] \ ( x y -- ) : lcd_pos 2 u/mod swap 0= if 1 = \ line is even? if h40 else char W@ h10 = if h50 else h54 then then else 0= if 0 else char W@ h10 = if h10 else h14 then then then 1- + h80 or lcd_com \ Add DDRAM Addr command ; \ Clear LCD-screen \ ( -- ) : lcd_clr 1 lcd_com 2 delms ; \ Setup of display construction \ (x y -- ) : lcd_setup line W! char W! ; \ Display string \ ( cstr -- ) cstr:string addr : lcd_str C@++ \ ( c-addr+1 c1 ) c-addr+1: string's first char addr c1:string length dup if bounds do i C@ lcd_char loop \ Print string else 2drop then ; \ Print cr \ ( -- ) : lcd_cr cur_line W@ 1+ dup line W@ > \ Check if current_line+1 is bigger than using LCD-line if drop 1 1 lcd_pos 1 cur_line W! \ Move to lcd's up-left else dup 1 swap lcd_pos cur_line W! \ Move to lower line then ; \ Display decimal-number from Left \ d987654321 lcd_dec_L --> [987654321] \ d4321 lcd_dec_L -------> [4321] \ (n -- ) n:number variable tmp wvariable result : lcd_dec_L 0 result W! d1000000000 tmp L! dup h80000000 and if negate h2D lcd_char then \ Check if minus and print "-" d10 0 do dup tmp L@ >= \ Check if n is bigger than tmp if tmp L@ u/mod h30 + lcd_char 1 result W! \ Print number-char else result W@ tmp L@ 1 = or if h30 lcd_char then \ Print "0" then tmp L@ d10 u/ tmp L! \ Divide tmp by d10 loop drop ; \ Display decimal-number from Right \ cur_line is used for displaying number \ d987654321 d10 lcd_dec_L --> [ 987654321] \ d4321 d10 lcd_dec_L -------> [ 4321] \ d4321 5 lcd_dec_L -------> [ 4321] \ ( n1 n2 -- ) n1:number n2 digit(5 <= n2 <= d10) : lcd_dec_R 0 result W! \ d1000000000 tmp L! 5 max d10 min dup >r 1 swap 1- 0 do d10 u* loop tmp L! dup h80000000 and if negate 0 else 1 then swap \ check minus? r> 0 do dup tmp L@ >= \ Check if n is bigger than tmp if result W@ 0= if swap 0= \ Check if minus if i cur_line W@ lcd_pos h2D lcd_char \ Print "-"\ then then tmp L@ u/mod h30 + lcd_char 1 result W! \ Print number-char else result W@ tmp L@ 1 = or if h30 lcd_char \ Print "0" else bl lcd_char \ Print blank then then tmp L@ d10 u/ tmp L! \ Divide tmp by d10 loop drop ; \ Display hex number \ (n1 n2 -- ) n1:number n2:digit(1 to 8) [32bits is 8-digits(hex)] \ d100 4 lcd_hex --> [0064] \ d100 2 lcd_hex --> [64] : lcd_hex dup rot2 8 swap - 2 lshift lshift swap 0 do dup hF0000000 and d28 rshift dup d10 < if h30 + \ 0,1,2,3,4,5,6,7,8,9 else h37 + \ A,B,C,D,E,F then lcd_char 4 lshift loop drop ; \ Display binary number \ (n1 n2 -- ) n1:number n2:digits(1 to d32) [32bits is 32-digits(binary)] Digits is limit by using LCD's char : lcd_bin dup rot2 h20 swap - lshift swap 0 do dup h80000000 and if h31 else h30 then lcd_char \ Print "1" or "0" 1 lshift loop drop ; \ Print spaces \ ( n -- ) n:space's number printing on LCD : lcd_bl dup if 0 do bl lcd_char loop else drop then ; \ LCD Off (not erase display-data) \ ( -- ) : sleep 8 lcd_com \ display OFF 0 0 out_PCF8574 \ Backlight off ; \ Wake up LCD \ ( -- ) : wakeup LED- 0 out_PCF8574 \ Backlight on hC lcd_com \ display ON ; \ =========================================================================== \ demo \ =========================================================================== : test lcd_init h41 lcd_char ; : test1 c" sample" lcd_str ; \ Set bar_graph_font(horizontal) to CG-RAM \ ( -- ) : set_bar_graph h20 h40 6 0 do \ set 6 charcters 8 0 do \ set 8 lines for 1 character dup lcd_com \ command for character to CG-RAM swap dup lcd_char swap \ write data 1+ loop hF8 and swap dup 1 rshift or swap loop 2drop ; : demo lcd_init d16 4 lcd_setup \ 16characters 4line \ display char-code [0x20 - 0x7f] & [0xa0 - 0xff] h20 line W@ 2 = if 7 0 else 3 0 then do line W@ 2 = if i 3 = if 4 seti drop hA0 then 2 0 else 4 0 then do line W@ 4 = if j 1 = if i 2 = if h20 + thens 1 i 1+ lcd_pos d16 0 do dup lcd_char h100 delms 1+ loop loop loop drop lcd_clr \ display binary, hex, decimal c" 0x1+0x6 = b" lcd_str 1 6 + 4 lcd_bin 1 2 lcd_pos c" 0xACE+0xF=0x" lcd_str hACE hF + 4 lcd_hex 5 0 do d1000 delms loop lcd_clr 1 cur_line W! c" 0x12+0xe0=" lcd_str h12 hE0 + lcd_dec_L c" (D)" lcd_str lcd_cr c" 0x0-0x12=" lcd_str 0 h12 - lcd_dec_L c" (D)" lcd_str 5 0 do d1000 delms loop lcd_clr 1 cur_line W! d-987654321 lcd_dec_L lcd_cr d-54321 d10 lcd_dec_R 3 0 do d1000 delms loop hex set_bar_graph lcd_clr 1 cur_line W! c" Bar Graph" lcd_str 1 \ x-position char W@ 0 do 0 6 0 do dup lcd_char \ Print bar_graph character 1+ d100 delms swap dup 2 lcd_pos swap \ Set same x-position loop drop 1+ dup 2 lcd_pos \ Increment x-position loop drop char W@ 2 lcd_pos char W@ char W@ 0 do 5 6 0 do dup lcd_char \ Print bar_graph character 1- d100 delms swap dup 2 lcd_pos swap \ Set same x-positionap loop drop 1- dup 2 lcd_pos \ Decrement x-position loop drop lcd_clr c" Demo Finished" lcd_str 1 2 lcd_pos hB3 hC4 hDE hB6 hD8 hB1 h20 hC6 hB7 hB5 hB5 d11 0 do lcd_char loop ;