fl { i2c-charcterLCD made by using GPIO_Expander(MCP23017) Used 4bit-mode on characterLCD PropForth 5.5 2014/04/28 0:22:16 Character-LCD MCP23017 Propeller Vcc -----5V 3.3V GND --------------- GND SDA --level-shift-- P29 SCL --level-shift-- P28 DB4 ----- GPIOA0 DB5 ----- GPIOA1 DB6 ----- GPIOA2 DB7 ----- GPIOA3 RS ----- GPIOA4 R/W ----- GND --------------- GND E ----- GPIOA5 LED+ ----- 5V LED- --TR- GPIOA6 Buzzer --TR- GPIOA7 GPIOB7 ---- sw GPIOB6 ---- sw GPIOB5 ---- sw Vo -R-2R-- GPIOB4 R-2R-- GPIOB3 R-2R-- GPIOB2 R-2R-- GPIOB1 R-2R-- GPIOB0 A0 --------------- GND A1 --------------- GND A2 --------------- GND } \ =========================================================================== \ 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 ; \ Repeated Start \ ( -- ) : Sr _sdai \ Release sda _scli \ Release scl \ begin d28 px? until \ wait until scl is hi _sdao \ Set sda to lo _sclo \ Set sda 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 0 wconstant addr_input \ A2=A1=A0=0 h40 addr_input 1 lshift or wconstant MCP23017 \ reset pin 0 wconstant RST hFFFFFFFE constant RST_mask \ CharacterLCD h10 wconstant RS h20 wconstant E h40 wconstant LED- \ LED off h80 wconstant buzzer \ Buzzer on \ =========================================================================== \ Variables \ =========================================================================== wvariable char \ character number for using LCD wvariable line \ line number for using LCD wvariable cur_line \ current line number wvariable contrast \ contrast value [0 - 31] \ =========================================================================== \ Command for MCP23017 \ =========================================================================== \ Separate 16bits to 2bytes \ ( n1 -- n2 n3 ) n1:16bit[hex] n2:upper8bits n3:lower8bits : separate_byte dup hFF00 and 8 rshift swap hFF and ; \ Reset MCP23017 \ ( -- ) : reset RST pinout outa COG@ dup RST_mask and outa COG! \ Set RST to low RST_mask invert or outa COG! \ Set RST to hi ; \ Initialize ports \ ( -- ) : init_port \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) MCP23017 _eewrite \ Write register (IODIRA/IODIRB) 0 _eewrite or \ lower byte (IODIRA) 0 _eewrite or \ upper byte (IODIRB) hE0 _eewrite or \ Stop I2C _eestop err? ; \ Write on i2c and get t/f \ ( n1 n2 -- n3 ) n1:data n2:t/f n3:t/f : swap_wr swap _eewrite or ; \ Output data[E(bit5) + RS(bit4) + lcd4bit(bit0-3)] to ports[GPIOA/GPIOB] of MCP23017 \ ( n1 -- ) n1:RS+data : GPIO separate_byte \ ( upper8bits lower8bits ) \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) MCP23017 _eewrite \ ( upper8bits lower8bits t/f ) \ Write register h12 _eewrite or \ Select GPIOA-register \ ( upper8bits lower8bits t/f ) \ Write 2bytes swap_wr \ ( upper8bits t/f ) swap_wr \ ( t/f ) \ Stop I2C _eestop err? ; \ Write GPIOA and GPIOB \ ( n1 -- ) : 2GPIO dup E or \ Add E bit ( n1 E+n1 ) GPIO GPIO ; \ =========================================================================== \ Command for LCD \ =========================================================================== \ Shift contrast-value to 8bitleft \ ( -- ) : shift_cont contrast W@ 8 lshift ; \ 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 shift_cont or \ Add contrast 2GPIO 1 delms \ lower 4bit \ ( 10/0 n ) hF and or \ ( RS+data[upper4bit] ) Add RS-bit to data shift_cont or \ Add contrast 2GPIO 1 delms ; \ Initialize HD44780 \ ( -- ) : lcd_init reset init_port \ Initialize ports d10 contrast W! \ Set contrast to initial value \ 8bit mode d50 delms \ wait 50msec 3 2GPIO 5 delms \ wait 5msec 3 2GPIO 1 delms \ wait 1msec 3 2GPIO 5 delms \ wait 5msec 2 2GPIO \ 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 shift_cont GPIO \ Set contrast 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 ; \ LCD Off (not erase display-data) \ ( -- ) : sleep 8 lcd_com \ display OFF LED- shift_cont or GPIO \ Backlight off ; \ Wake up LCD \ ( -- ) : wakeup shift_cont GPIO \ Backlight on hC lcd_com \ display ON ; \ Buzzer on \ ( -- ) : buzzer_on buzzer shift_cont or GPIO d500 delms shift_cont GPIO ; \ Adjust contrast of LCD \ ( n1 -- ) n1:level[0 - 31] : contrast_adjst contrast W! shift_cont GPIO ; \ Read switch \ ( -- n1 ) n1:data[bit2-bit0] : SW \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) MCP23017 _eewrite \ ( t/f ) \ Write register h13 _eewrite or \ ( t/f ) \ Start read_process Sr \ Write slave address[rd], then receive Acknowledge-bit(ACK:Lo NACK:Hi) MCP23017 1 or _eewrite or \ ( t/f ) \ Read 1byte -1 _eeread \ ( t/f data ) \ Stop I2C _eestop swap err? 5 rshift ; \ =========================================================================== \ demo \ =========================================================================== \ 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 ;