Menu

PIC18 Dot-Matrix Display Log in to Edit

Mikael Nordman Pete Zawasky
\ 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

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.