fl { 2-wire Driver for an HD44780 based LCD Character based display (8bit control) Used Hex D F/F(74HC174) PropForth 5.0 11/05/2012 13:49:19 2-wire LCD curcuit Propeller latch P0 0x0 clk P1 0x1 LCD backlight P2 0x2 wire should be short } hex \ _cfo ( n1 -- n2 ) n1 - desired frequency, n2 frqa/frqb : _cfo clkfreq 1- min 0 swap clkfreq um/mod swap clkfreq 2/ >= abs + ; : delsec 10 u/mod dup if 0 do 3E80 delms loop else drop then dup if 0 do 3E8 delms loop else drop then ; 1F8 wconstant ctra 1FA 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 10000000 + ctra COG! ; wvariable char \ character number for LCD:x wvariable line \ line number for LCD:y wvariable cur_line \ current line number \ serial out data(6bit) to shift-register \ ( n1 n2 n3 -- ) n1:shift-data n2:_latchm n3:_clkm lockdict create a_shift_data_8 forthentry $C_a_lxasm w, h124 h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z2WiPZB l, z1SyLI[ l, z2WiPeB l, z1SyLI[ l, zfyPOM l, z2WyPjB l, zgyPO1 l, z1bfxZD l, z1bixZC l, z2WiPyk l, z20yPrS l, z3ryPr0 l, z1[ixZD l, z1[ixZC l, z3[yPnP l, z1SyLI[ l, z1SV01X l, freedict \ ( -- ) set shift-register output to zero(6bit) lockdict create a_clk_out_8 forthentry $C_a_lxasm w, h11C h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z2WyPWA l, z1bixZB l, 0 l, 0 l, z1[ixZB l, 0 l, z3[yP[K l, z1SyLI[ l, z1SV01X l, freedict : _latch_out_l _latch pinlo ; : _latch_out_h _latch pinhi ; : _clk_out_l _clk pinlo ; : _clk_out_h _clk pinhi ; 1 _latch lshift constant _latchm 1 _clk lshift constant _clkm \ send hi-pulse to Enable-pin : lcd_enable _latch_out_h _latch_out_l ; \ send data to shift-register \ ( n -- ) n:lcd4bit(bit0-3) + RS(bit4) + E(bit5) : shift_out \ ( n1 n2 n3 -- ) n1:shift-data n2:_latchm n3:_clkm _latchm _clkm a_shift_data_8 ; \ reset shift-register : reset_sr _clkm a_clk_out_8 ; \ lcd_com - send command to HD44780 (n -- ) n:bit8=RS-bit bit7-0=LCD-data : lcd_com invert 1FF and dup 100 and if 100 else 0 then or 200 or 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 30 lcd_com 5 delms lcd_enable 1 delms lcd_enable 5 delms reset_sr \ reset shift-register 38 lcd_com 1 delms 8 lcd_com 1 delms 1 lcd_com 1 delms 6 lcd_com 1 delms C lcd_com 1 delms 10 char W! 2 line W! \ defsult setting is 16Charcters & 2Lines 3E8 set_bright \ 1kHz ; \ setup of display construction (x y -- ) : lcd_setup line W! char W! ; \ display character ( c -- ) : lcd_char 100 or \ Add RS=1 to character-code lcd_com reset_sr \ delay time ; \ display string ( cstr -- ) : lcd_str C@++ dup if bounds do i C@ lcd_char loop else 2drop then ; \ clear lcd ( -- ) : lcd_clear 1 lcd_com 1 delms ; { x -- horizontal pos : 0x1 to 0x28 (decimal: 1 to 40Characters) y -- line number : 0x1 to 0x4 (decimal: 1 to 4Lines) ( x y -- ) } : lcd_pos 2 u/mod swap 0= if 1 = \ line is even? if 40 else char W@ 10 = if 50 else 54 then then else 0= if 0 else char W@ 10 = if 10 else 14 then then then \ 1- + dup . 80 or lcd_com 1- + 80 or lcd_com ; \ output cr : LCD_cr cur_line W@ 1+ dup line W@ > if drop 1 1 lcd_pos 1 cur_line W! else dup 1 swap lcd_pos cur_line W! then ; \ display decimal number to covert hex (n -- ) n:hex-value variable tmp wvariable result : lcd_dec 0 result W! 3B9ACA00 tmp L! dup 80000000 and if invert 1+ 2D lcd_char then \ check minus? A 0 do dup tmp L@ >= if tmp L@ u/mod 30 + lcd_char 1 result W! else result W@ tmp L@ 1 = or if 30 lcd_char then then tmp L@ A u/ tmp L! loop drop ; \ display hex number (n1 n2 -- ) n1:hex-value n2:digits(1 to 8) : lcd_hex dup rot2 8 swap - 2 lshift lshift swap 0 do dup F0000000 and 1C rshift dup A < if 30 + else 37 + then lcd_char 4 lshift loop drop ; \ display binary number (n1 n2 -- ) n1:hex-value n2:digits(1 to 10) : lcd_bin dup rot2 20 swap - lshift swap 0 do dup 80000000 and if 31 else 30 then lcd_char 1 lshift loop drop ; \ output spaces ( n -- ) n:space's number output to LCD : lcd_blank dup if 0 do bl lcd_char loop else drop then ; : sleep \ LCD Off (not erase display-data) 8 lcd_com \ display OFF 0 ctra COG! _bright pinin ; : wakeup \ LCD On C lcd_com \ display ON 3E8 set_bright \ 1kHz ; : set_bar_graph 20 40 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 F8 and swap dup 1 rshift or swap loop 2drop ; : lcd_demo1 lcd_init 10 4 lcd_setup \ 16characters 4line \ display char-code [0x20 - 0x7f] & [0xa0 - 0xff] 20 line W@ 2 = if 7 0 else 3 0 then do line W@ 2 = if i 3 = if 4 seti drop A0 then 2 0 else 4 0 then do line W@ 4 = if j 1 = if i 2 = if 20 + then then then 1 i 1+ lcd_pos 10 0 do dup lcd_char 100 delms 1+ loop loop loop drop lcd_clear \ 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 ACE F + 4 lcd_hex 5 delsec lcd_clear 1 cur_line W! c" 0x12+0xe0=" lcd_str 12 E0 + lcd_dec c" (D)" lcd_str LCD_cr c" 0x0-0x12=" lcd_str 0 12 - lcd_dec c" (D)" lcd_str 5 delsec set_bar_graph lcd_clear c" Bar Graph" lcd_str 1 \ x-position char W@ 0 do 0 6 0 do dup lcd_char 1+ 64 delms swap dup 2 lcd_pos swap 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 1- 64 delms swap dup 2 lcd_pos swap loop drop 1- dup 2 lcd_pos loop drop lcd_clear c" Demo Finished" lcd_str 1 2 lcd_pos B3 C4 DE B6 D8 B1 20 C6 B7 B5 B5 B 0 do lcd_char loop ; : set_bar_graph2 40 8 0 do \ set 8 charcters 8 0 do \ set 8 lines for 1 character dup lcd_com \ command for character to CG-RAM 7 j - i < if 1F else 0 then lcd_char \ write data 1+ loop F8 and loop drop ; variable tmp1 : lcd_demo2 \ wave cnt COG@ lcd_init \ 10 4 lcd_setup \ 16characters 4line set_bar_graph2 lcd_clear c" Wave" lcd_str 1 2 lcd_pos 1 tmp L! 1 tmp1 L! 0 100 0 do dup char W@ 0 do dup lcd_char dup 7 = tmp L@ 1 = and if drop FF else dup FF = if drop 7 -1 tmp L! else dup 0 = if 1+ 1 tmp L! else tmp L@ + thens loop drop 1 2 lcd_pos dup 7 = tmp1 L@ 1 = and if drop FF else dup FF = if drop 7 -1 tmp1 L! else dup 0 = if 1+ 1 tmp1 L! else tmp1 L@ + thens loop drop 1 3 lcd_pos cnt COG@ swap - 13880 u/ lcd_dec c" msec" lcd_str ; \ This demo use 16characters X 4line LCD. wvariable X wvariable Y wvariable sign wvariable y_limit : demo3 cnt COG@ lcd_init 10 4 lcd_setup \ 16characters 4line set_bar_graph2 lcd_clear char W@ X W! line W@ Y W! 1 sign W! Y W@ 8 u* y_limit W! 1 0 \ ( cnt Y_incremrnt[X=1] Y_value -- ) at X-pos top 1000 0 do 2dup \ ( Y_incremrnt Y_value -- ) \ character -out to X-direction X W@ 0 do \ i dup 9 < if dup i 1+ Y W@ lcd_pos dup 8 = if drop FF then lcd_char i 1+ Y W@ 1- lcd_pos 0 lcd_char else \ ( Y_incremrnt Y_value -- ) dup 8 u/mod \ quotient ( Y_incremrnt Y_value remainder quotient -- ) i swap >r 1+ Y W@ r> 0 do 2dup lcd_pos FF lcd_char 1- loop nip \ remainder ( Y_incremrnt Y_value remainder Y-pos --) over 0<> if \ 2dup i 1+ swap lcd_pos lcd_char i 1+ swap lcd_pos lcd_char else i 1+ swap lcd_pos 0 lcd_char drop then then \ ( Y_incremrnt Y_value --) 2dup + dup y_limit W@ = if \ check if more than 1F drop nip -1 swap else \ check if less than 0 0< if nip 1 swap then then over + loop 2drop \ ( cnt Y_incremrnt[X=1] Y_value -- ) \ return X-pos to top 2dup + dup y_limit W@ = if \ check if more than 1F drop nip -1 swap else \ check if less than 0 0< if nip 1 swap then then over + loop 3drop ; decimal { fl build_BootOpt :rasm \ get _clkm mov $C_treg1 , $C_stTOS spop \ get _latchm mov $C_treg2 , $C_stTOS spop \ shift data to left shl $C_stTOS , # d22 \ set loop-count 8bit-mode mov $C_treg3 , # d11 __1 shl $C_stTOS , # 1 wc \ set latch to Hi/Lo if_c or outa , $C_treg2 \ clock pulse sec or outa , $C_treg1 mov $C_treg4 , cnt add $C_treg4 , # d28 waitcnt $C_treg4 , # 0 \ set _latch to Lo andn outa , $C_treg2 andn outa , $C_treg1 djnz $C_treg3 , # __1 spop jexit ;asm a_shift_data_8 fl build_BootOpt :rasm \ set loop-count 8bit-mode mov $C_treg1 , # d10 __1 \ pulse width 150nsec or outa , $C_stTOS nop nop andn outa , $C_stTOS nop djnz $C_treg1 , # __1 spop jexit ;asm a_clk_out_8 }