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