TACHYON V4 IFDEF 2w_charLCD.fth @rest org FORGET 2w_charLCD.fth } pub 2w_charLCD.fth ." 2-wire Character LCD 2017/06/12 9:35:37 " ; @org W@ == @rest --- remember { 2017/06/12 9:35:43 Translated 2-wire_charLCD frpm PropForth to Tachyon 2x16 or 4x16 characterLCD } \ =========================================================================== \ Constants \ =========================================================================== \ User-defined #P0 == data #P1 == clk \ CharacterLCD $10 == RS $20 == LED- $40 == E \ =========================================================================== \ Variables \ =========================================================================== word char \ character number for using LCD word line \ line number for using LCD word cur_line \ current line number word sleep_on \ sleep_on flag word result word tmp1 long tmp2 long dir1 long dir2 \ =========================================================================== \ Command for 74HC164 \ =========================================================================== : data_l data LOW ; : data_h data HIGH ; : clk_l clk LOW ; : clk_h clk HIGH ; \ Send hi-pulse to Enable-pin \ ( -- ) : lcd_enable data_h #500 us data_l #500 us ; \ Send data to shift-register \ ( n -- ) n:E(bit6) + LED_on(bit5) + RS(bit4) + lcd4bit(bit3-0) : shift_out 1 SHL \ Shift 1bit to left #24 REV \ flip 8bits so msb will be first to shift right out data MASK SWAP \ create an iomask+data combo for SHRPUT 8 FOR SHROUT clk HIGH clk LOW NEXT 2DROP ; \ reset shift-register \ ( -- ) : reset_sr 7 FOR clk_h clk_l NEXT ; \ =========================================================================== \ Command for LCD \ =========================================================================== \ Send command to HD44780 \ (n -- ) n:bit4=RS-bit bit3-0=LCD-data : lcd_com reset_sr DUP $100 AND IF RS ELSE 0 ENDIF \ RS bit SWAP 2DUP \ ( 10/0 n 10/0 n ) \ upper 4bit 4 SHR $F AND OR E OR \ Add RS-bit and Enable-bit shift_out lcd_enable reset_sr \ lower 4bit \ ( 10/0 n ) $F AND OR E OR \ Add RS-bit and Enable-bit shift_out lcd_enable reset_sr \ Set RS and DB4-DB7 to Hi, and Set LED_on to hi if sleep is inactive $1F sleep_on W@ IF LED- OR ENDIF \ Add LED_on shift_out ; \ Setup propeller pins and initialize HD44780 \ ( -- ) : lcd_init 0 sleep_on W! \ Clear shift-register output reset_sr \ 8bit mode #100 ms \ wait 100msec $43 shift_out lcd_enable \ FunctionSet 5 ms lcd_enable \ FunctionSet 1 ms lcd_enable \ FunctionSet 5 ms reset_sr \ Clear shift-register \ 4bit mode 2 lcd_com $28 lcd_com \ FunctionSet DL=0 N=1 F=0 $C lcd_com \ DisplaySwitch D=1 C=B=0 1 lcd_com \ ScreenClear 6 lcd_com \ InputSet I/D=1 S=0 reset_sr \ Clear shift-register #100 ms #16 char W! 2 line W! \ defsult setting is 16Charcters & 2Lines ; \ Display character \ ( c -- ) c:character code 'A'=h41 : lcd_char $100 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 = IF $40 ELSE $50 ENDIF \ Line is 2 or 4 ELSE 0= IF 0 ELSE $10 ENDIF \ Line is 1 or 3 ENDIF 1- + $80 OR lcd_com \ Add DDRAM Addr command ; \ Clear LCD-screen \ ( -- ) : lcd_clr 1 lcd_com 2 ms ; \ Setup of display construction \ (x y -- ) : lcd_setup line W! char W! ; \ Display string \ ( n1 -- ) n1:string sample:[ " ABC" ] : lcd_str DUP LEN$ \ ( address length ) \ DUP 0 > ?DUP IF 1 \ ( start length cnt ) DOFOR I C@ lcd_char LOOP \ Print string ELSE 2DROP ENDIF ; \ Rdirect string to charLCD \ How to use:LCD PRINT" Hellow" CON : LCD ' lcd_char uemit W! ; \ 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 ENDIF ; \ Display decimal-number from Left \ d987654321 lcd_dec --> [987654321] \ d4321 lcd_dec -------> [4321] \ (n -- ) n:number : lcd_dec 0 tmp1 W! #1000000000 tmp2 ! DUP $80000000 AND IF NEGATE $2D lcd_char ENDIF \ Check if minus and print "-" #10 FOR DUP tmp2 @ => \ Check if n is bigger than tmp IF tmp2 @ U/MOD $30 + lcd_char 1 tmp1 W! \ Print number-char ELSE tmp1 W@ tmp2 @ 1 = OR IF $30 lcd_char ENDIF \ Print "0" ENDIF tmp2 @ #10 U/ tmp2 ! \ Divide tmp by d10 NEXT DROP ; \ Print spaces \ ( n -- ) n:space's number printing on LCD : lcd_bl ?DUP IF FOR $20 lcd_char NEXT ELSE DROP ENDIF ; \ LCD Off (not erase display-data) \ ( -- ) : sleep 1 sleep_on W! 8 lcd_com ; \ Wake up LCD \ ( -- ) : wakeup 0 sleep_on W! $C lcd_com ; \ =========================================================================== \ demo \ =========================================================================== \ Set bar_graph_font(horizontal) to CG-RAM \ ( -- ) : set_bar_graph1 $20 $40 6 FOR \ set 6 charcters 8 FOR \ set 8 lines for 1 character DUP lcd_com \ command for character to CG-RAM SWAP DUP lcd_char SWAP \ write data 1+ NEXT $F8 AND SWAP DUP 1 SHR OR SWAP NEXT 2DROP ; \ Set bar_graph_font(vertical) to CG-RAM \ ( -- ) : set_bar_graph2 $40 0 8 1 DOFOR \ Set 8 charcters 0 8 1 DOFOR \ Set 8 lines for 1 character DUP lcd_com \ command for character to CG-RAM \ J:Outer loop index(CG RAM addr) \ I:inner(current) loop index (each line for character) 7 J - I < IF $1F ELSE 0 ENDIF lcd_char \ Write data 1+ LOOP $F8 AND LOOP DROP ; \ Print all characters and Bar Graph on 2x14 charLCD : demo lcd_init \ d16 4 lcd_setup \ 16characters 4line 1 cur_line W! \ ----- display character-code [0x20 - 0x7f] & [0xa0 - 0xff] ----- $20 \ 1st character BEGIN 1 cur_line W@ lcd_pos \ Set position #16 FOR DUP lcd_char 1+ #10 ms NEXT \ Print characters on LCD-Line 1 cur_line W+! \ \increment line-number cur_line W@ line W@ > IF 1 cur_line W! ENDIF \ Check line number DUP $80 = IF DROP $A0 ENDIF DUP $100 = IF 1 ELSE 0 ENDIF \ Finish? UNTIL DROP #500 ms \ ----- Bar Graph ----- lcd_clr LCD PRINT" Bar Graph" CON set_bar_graph1 1 #16 FOR 0 6 1 DOFOR I lcd_char \ Print bar_graph character DUP 2 lcd_pos \ Set same x-position LOOP 1+ DUP 2 lcd_pos \ Increment x-position NEXT DROP #16 2 lcd_pos #16 #16 FOR 5 6 -1 DOFOR I lcd_char DUP 2 lcd_pos LOOP 1- DUP 2 lcd_pos \ Decrement x-position NEXT DROP #100 ms \ WAVE lcd_clr LCD PRINT" WAVE" CON set_bar_graph2 1 dir1 ! 0 \ First character addrss LAP #256 FOR DUP \ Print character toward horizontal on 2nd line 1 2 lcd_pos dir1 @ dir2 ! #16 FOR DUP lcd_char \ Write char DUP 7 = dir2 @ 1 = AND IF DROP $FF ELSE DUP $FF = IF DROP 7 -1 dir2 ! ELSE DUP 0 = IF 1+ 1 dir2 ! ELSE dir2 @ + ENDIF ENDIF ENDIF NEXT DROP \ Set next character on start-position(1,2) DUP 7 = dir1 @ 1 = AND IF DROP $FF ELSE DUP $FF = IF DROP 7 -1 dir1 ! ELSE DUP 0= IF 1+ 1 dir1 ! ELSE dir1 @ + ENDIF ENDIF ENDIF NEXT LAP .LAP DROP ; END \ ?BACKUP