fl { 2-wire Driver for an HD44780 based LCD Character based display (8bit control) Used Hex D-F/F(74HC174) PropForth 5.5 2013/04/03 13:10:36 2-wire LCD curcuit Propeller latch P0 0x0 clk P1 0x1 LCD backlight P2 0x2 wire should be short } \ _cfo ( n1 -- n2 ) n1 - desired frequency, n2 frqa/frqb : _cfo clkfreq 1- min 0 swap clkfreq um/mod swap clkfreq 2/ >= abs + ; \ a cog special register [ifndef ctra h1F8 wconstant ctra ] [ifndef frqa h1FA wconstant frqa ] \ Edit 2 constant below to match your hardware 0 wconstant _latch 1 wconstant _clk \ Comment out when not using brightness-control 2 wconstant _bright \ set LCD's braightness to oscillate pin at the specified frequency \ ( n1 --) n1 is the frequency, uses ctra NCO-mode : set_bright _cfo frqa COG! _bright dup pinout h10000000 + ctra COG! ; wvariable char \ character number for using LCD wvariable line \ line number for using LCD wvariable cur_line \ current line number \ Serial out data(10bits) to shift-register \ ( n1 n2 n3 -- ) n1:shift-data n2:_latch n3:_clk lockdict create a_shift_data_8bit forthentry $C_a_lxasm w, h125 h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z2WyPW1 l, zfiPZB l, z1SyLI[ l, z2WyPb1 l, zfiPeB l, z1SyLI[ l, zfyPOM l, z2WyPjB l, zgyPO1 l, z1jixZD l, z1bixZC l, z2WiPyk l, z20yPrS l, z3ryPr0 l, z1[ixZC l, z3[yPnR l, z1SyLI[ l, z1SV01X l, freedict \ Set shift-register output to zero(10bits) \ ( n1 -- ) n1:_clk lockdict create a_clk_out_8bit forthentry $C_a_lxasm w, h11E h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z2WyPW1 l, zfiPZB l, z1SyLI[ l, z2WyPbA l, z1bixZC l, 0 l, 0 l, z1[ixZC l, 0 l, z3[yPfN l, z1SV01X l, freedict : _latch_out_l _latch pinlo ; : _latch_out_h _latch pinhi ; : _clk_out_l _clk pinlo ; : _clk_out_h _clk pinhi ; \ Send hi-pulse to Enable-pin : lcd_enable _latch_out_h _latch_out_l ; \ Send data to shift-register \ ( n -- ) n:E(bit9) + RS(bit8) + lcd8bit(bit7-0) : shift_out _latch _clk a_shift_data_8bit ; \ Reset shift-register(D-FF) \ ( -- ) : reset_sr _clk a_clk_out_8bit ; \ Send command to HD44780 \ (n -- ) n:bit8=RS-bit bit7-0=LCD-data : lcd_com invert h1FF and h200 or \ Add Enable-bit shift_out lcd_enable reset_sr ; \ Setup propeller pins and initialize HD44780 \ ( -- ) : lcd_init \ set from P**(_data) to P**(_clk) to output _latch 2 0 do dup pinout 1+ loop drop reset_sr \ Reset shift-register(D-FF) \ Initialize Character-LCD d50 delms \ wait 50msec h30 lcd_com \ FunctionSet DL=1 N=F=0 5 delms lcd_enable \ FunctionSet 1 delms lcd_enable \ FunctionSet 5 delms reset_sr \ Reset shift-register(D-FF) h38 lcd_com 1 delms \ FunctionSet DL=1 N=1 F=0 1 lcd_com 1 delms \ ScreenClear 6 lcd_com 1 delms \ InputSet I/D=1 S=0 hC lcd_com 1 delms \ DisplaySwitch D=1 C=B=0 reset_sr \ Reset shift-register(D-FF) d16 char W! 2 line W! \ default setting is 16Charcters & 2Lines d1000 set_bright \ 1kHz ; \ 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 ctra COG! _bright pinin ; \ Wake up LCD \ ( -- ) : wakeup \ LCD On hC lcd_com \ display ON d1000 set_bright \ 1kHz ; { \ Send 10bits to D-FF \ ( n1 n2 n3 -- ) n1:10bits-data n2:_latch n3 _clk \ $C_treg1 -- _clkm \ $C_treg2 -- _latchm \ $C_treg3 -- loop counter fl build_BootOpt :rasm \ get _clkm mov $C_treg1 , # 1 shl $C_treg1 , $C_stTOS spop \ get _latchm mov $C_treg2 , # 1 shl $C_treg2 , $C_stTOS spop \ shift data to left shl $C_stTOS , # d22 \ set loop-count 8bit-mode \ E(1bit) + RS(1bit) + 8bit + "0"(1bit) mov $C_treg3 , # d11 __1 shl $C_stTOS , # 1 wc \ set latch to Hi/Lo muxc outa , $C_treg2 \ clock pulse Hi:500nsec Lo:200nsec or outa , $C_treg1 mov $C_treg4 , cnt add $C_treg4 , # d28 waitcnt $C_treg4 , # 0 \ set _latch to Lo andn outa , $C_treg1 djnz $C_treg3 , # __1 spop jexit ;asm a_shift_data_8bit \ Send D-FF all output to low \ ( n1 -- ) n1:_clk \ $C_treg1 -- _clkm \ $C_treg2 -- loop counter fl build_BootOpt :rasm mov $C_treg1 , # 1 shl $C_treg1 , $C_stTOS spop \ set loop-count 8bit-mode mov $C_treg2 , # d10 __1 \ pulse width Hi:150nsec Lo:150nsec or outa , $C_treg1 nop nop andn outa , $C_treg1 nop djnz $C_treg2 , # __1 jexit ;asm a_clk_out_8bit }