FlashForth: for PIC and Atmega Wiki
Brought to you by:
oh2aun
\ Using FlashForth to interface a PIC18 to a Dot_Matrix Display . \ ****************************************************************** \ \ Filename: vfd_nagp1235_par.txt \ FlashForth: 5.0 \ MCU PIC18F6527 \ Application: vfd, dot matrix, 140x16, parallel port \ \ Author: Pete Zawasky \ Created: 3:07 PM 11/12/2019 ppz \ Last Edit 8:31 PM 01/08/2022 ppz \ \ ****************************************************************** \ FlashForth is licensed acording to the GNU General Public License \ ****************************************************************** \ This code is distributed in the hope that it will be useful, \ but WITHOUT ANY WARRANTY; without even the implied warranty \ of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. \ ****************************************************************** \ \ VFD driver using Port F and Port G. \ Words are defined for Futaba NAGP1235, \ 140 x 16 dot matrix display. \ Each line has 20 (5x7) characters viewable. \ PORT F $FF85 Bidirectional data RF<7..0> = D<7..0> \ bit 7 PBUSY Set upon receipt of 8-bit data or command \ Indicates processing of byte by vfd when \ VFD_/WR is returned high \ PORT G $FF86 VFD Control bits \ bit 2 VFD_RS Register Select (NOT USED at this time) \ bit 1 VFD_WR Write on lo-to-hi edge \ bit 0 VFD_RD Read after hi-to-lo \ \ Data Write requires VFD_RD = 1, VFD_WR 0->1 \ Status Read requires VFD_WR = 1, VFD_RD = 0 \ Data Read requires VFD_WR = 1, VFD_RD = 0 \ ****************************************************************** -vfd marker -vfd decimal ram \ Requires utility words \ Needs from asm.txt -- For convenience these are provided here. \ as2, clrf, movwf, movlw, \ \ microchip assembler arguments \ f = file \ d = destination \ a = access \ b = bit \ k = literal \ 0 constant w, \ Destination W register 1 constant f, \ Destination File 0 constant a, \ Force Access Bank 1 constant b, \ Force Bank Select Register \ \ : as2 ( opcode "name" -- ) ( f a -- ) \ co: \ does> rot ic, or ic, ; \ $6a as2 clrf, ( f a -- ) \ $6e as2 movwf, ( f a -- ) \ $0e00 as1 movlw, ( k -- ) $ff85 constant portf $ff86 constant portg $ff97 constant trisf $ff98 constant trisg $ffc1 constant adcon1 \ portg bits 0 constant VFD_RD \ read can occur after RD 1->0 1 constant VFD_WR \ write occurs when WR 1->0->1 2 constant VFD_RS \ NOT USED \ portf bits $80 constant VFD_D7 \ Data bit D7 mask -- PBUSY \ ****************************************************************** \ VFD initialization. \ Initial state is RF<7..0> - output \ RG<2..0> - output \ RS=1, WR=1, RD=1 \ : INIT_VFD_PORTS ( -- ) $07 portg c! \ RS, WR, RD $18 trisg c! \ RG<2..0> set to OUTPUT $0a adcon1 c! \ RF<7..0> set to DIGITAL $ff portf c! \ dummy data $00 trisf c! \ RF<7..0> set to OUTPUT ; \ ****************************************************************** \ VFD read and write timing. \ Idle Mode is Ready-to-Write, WR=1, RD=1. \ Byte Write to VFD. : VBYTE! ( 8b -- ) portf c! \ send 8bit data [ portg VFD_WR a, bcf, ] \ Write Mode [ portg VFD_WR a, bsf, ] \ write on LO->HI ; \ Idle Mode \ Byte Read from VFD. \ Only D7 is valid. : VBYTE@ ( -- 8b ) [ $ff movlw, trisf a, movwf, ] \ Port F set to INPUT [ portg VFD_RD a, bcf, ] \ Read Mode portf c@ \ read D<7..0> [ portg VFD_RD a, bsf, ] \ end read [ trisf a, clrf, ] \ Port F set to OUTPUT ; \ Idle Mode \ ****************************************************************** \ Test Busy Flag (PBUSY). \ Wait until PBUSY is HI. : ?PBUSY ( -- ) begin VBYTE@ VFD_D7 and 0= until ; \ ****************************************************************** \ VFD Write commands. \ Send 1 byte to VFD. : VFD! ( 8b -- ) ?PBUSY VBYTE! ; \ ****************************************************************** \ VFD Basic command Set. \ Backspace. : VBS ( -- ) $08 VFD! ; \ Horizontal Tab. \ Move cursor right 1 character position. : VHT ( -- ) $09 VFD! ; \ Line Feed. : VLF ( -- ) $0a VFD! ; \ Carriage Return. \ Move cursor to left end of current line. : VCR ( -- ) $0d VFD! ; \ Move cursor to Home Position. : VHOM ( -- ) $0b VFD! ; \ Clear Display and move cursor to Home Position. : VCLR ( -- ) $0c VFD! ; \ Initialize Display. \ Return display to its DEFAULT settings. \ cmd: ESC @ : VDEF ( -- ) $1b VFD! $40 VFD! ; \ Current Window Mode. \ MD1 $01 Overwrite Mode \ MD2 $02 Vertical Cursor Scroll Mode \ MD3 $03 Horizontal Cursor Scroll Mode \ cmd: US MDx : VMODE ( 1|2|3 -- ) $1f VFD! VFD! ; \ Set Cursor ON/OFF. \ 1=ON, 0=OFF \ cmd: US C n : VCUR ( 1|0 -- ) $1f VFD! $43 VFD! VFD! ; \ Set Cursor Position. \ Line1 yH=0, yL=0, xH=0|1, xL=0->255 \ Line2 yH=0, yL=1, xH=0|1, xL=0->255 \ cmd: US $ xL xH yL yH \ \ ( yH yL xH xL -- ) : VCURSET ( 0 1|0 1|0 8b -- ) $1f VFD! $24 VFD! 4 for VFD! next ; \ Brightness Setting. \ n = 1 -> 8 , 8 is brightest/default. \ cmd: US X n : VBRITE ( n -- ) $1f VFD! $58 VFD! VFD! ; \ Reverse Mode. \ New data only. \ cmd: US r n : VREV ( 1|0 -- ) $1f VFD! $72 VFD! VFD! ; \ ****************************************************************** \ Convenience. \ Set Character Entry Position. \ line 1 Character start address. : LINE1 ( pos -- ) 0 0 rot 7 * 0 swap VCURSET ; \ line 2 Character start address. : LINE2 ( pos -- ) 0 1 rot 7 * 0 swap VCURSET ; \ ****************************************************************** \ Graphics. \ constants $5000 constant scn_save \ screen save area of FLASH \ allows space for 49 screens $f300 constant scn_buff \ screen buffer area in RAM \ 1 screen \ Convert Image # to Save address in MCU memory. \ n is the graphics image reference # \ 0 is in RAM Buffer, 1 to 49 is in FLASH Save \ : image ( n -- addr ) dup 0= if drop scn_buff \ start addr of screen save area of RAM else 1- 280 * \ 280 bytes per screen (140x2) scn_save + \ offset into screen save area of FLASH then ; \ Finish receiving a command. \ Get next 3 ASCII characters of a command. \ Convert first 2 characters to a byte. \ Drop 3rd. \ : get_byte ( -- n ) key pad c! \ put 2 ASCII characters in PAD key pad 1+ c! 0 0 pad 2 >number \ convert 1st 2 characters to byte 2drop drop \ just want the byte key drop ; \ drop 3rd character, should be space or \r \ Display the single value u (00-ff) as a 2 character byte. \ Best to use current base as HEX. \ : .byte ( u -- ) base @ hex swap 0 <# # # #> type space base ! ; \ Save VFD graphics Image to MCU memory. \ CRs are for FlashForth Shell to upload entire image file bytes. \ ff_shell sends file 1 line at a time. \ : >VFD_BUF ( img# -- ) cr image !p>r \ start addr of VFD Image Buffer in MCU memory \ data + spaces + <CR>s = 840 chars 0 280 \ 840 / 3 = 280 for get_byte dup .byte \ convert 3 ASCII characters to a byte pc! p+ \ store in MCU memory 1+ dup 16 = if cr drop 0 then \ tell ff_shell to continue next drop r>p ; \ Update VFD graphics display from MCU memory. \ : VFD_BUF> ( img# -- ) image !p>r \ start addr of VFD Image Buffer in MCU memory \ data + spaces + <CR>s = 840 chars 280 \ 840 / 3 = 280 for pc@ \ get byte VFD! p+ \ send to VFD next r>p ; \ Real-time Bit Image Display. \ example -- fill Display Window, 140x16 dots \ requires image of 280 bytes \ e.g. <image #> 0 2 0 $8c VBIT \ cmd: US ( f $11 xL xH yL yH g d(1)...d(k) \ \ ( 0-49 yH yL xH xL -- ) : VBITS ( img# 0 2|1 1|0 256|1 -- ) $1f VFD! $28 VFD! $66 VFD! $11 VFD! 4 for VFD! next \ image size 1 VFD! \ g VFD_BUF> ; \ send image bytes \ ********************************************************************* \ Text display words. \ Line entry mode. : VEMIT ( 8b -- ) VFD! ; \ write byte to VFD : VSPACE ( -- ) bl VEMIT ; : VSPACES ( 8b -- ) 0 max \ don't want negative numbers for VSPACE next ; \ ********************************************************************* \ Output formatting and string words. : VTYPE ( addr +n -- ) for c@+ VEMIT next drop ; : V. ( n -- ) dup abs 0 <# #s swap sign #> VTYPE VSPACE ; \ Display right justified : V.R ( n field -- ) swap 0 <# #s #> rot over - VSPACES VTYPE VSPACE ; \ one decimal place : V.X ( n -- ) 0 <# # 46 hold #s #> VTYPE VSPACE ; \ one decimal place -- right justified : V.X.R ( n field -- ) swap 0 <# # 46 hold #s #> rot 1+ over - VSPACES VTYPE VSPACE ; \ : V."| ( -- ) \ runtime V." \ do$ \ get address of the in-line string \ COUNT \ VTYPE ; \ output string to display \ : V." ( -- ) \ usage V." ccc" , compile mode only postpone s" \ compile literal string up to " postpone VTYPE ; immediate : TEST_LINE ( -- ) V." PZEF Company " ; \ ********************************************************************* \ Tests. \ Initialize VFD. : VFD_ON ( -- ) INIT_VFD_PORTS VCLR 1 VBRITE 1 VCUR ; \ Blank VFD screen. : VFD_OFF ( -- ) VCLR 0 VCUR ; \ Scroll line 1 then line 2 left, 1 character at a time. : SCROLL_TEST ( -- ) VFD_ON begin TEST_LINE key? dup 0= if 250 ms then until key drop ; \ ********************************************************************* ram hex