| Starting PIC Forth | ||||||||
If you are using a Unix-like environment you
can type "make interactive" from the PIC Forth directory to start PIC
Forth in interactive mode. The actual command (which might be useful for
Windows users) is:gforth picforth.fs -e 'host picquit' You can also name a hex file to make and it will create the hex file from the corresponding .fs file. The command is: gforth picforth.fs -e 'include xxx.fs file-dump xxx.hex map bye' Assuming your source file is xxx.fs and you want to create xxx.hex. For now, stick with interactive mode. Try a simple program: main : test 3 2 + recurse ; This defines a word test that is your main program. It will add three plus two and keep doing it forever (recurse). Right? Not exactly. PIC Forth has a disassembler built in, so issue this command: see test This will show you: ; name: test
; max return-stack depth: 0
0x0005 3004 movlw 0x05
0x0006 0384 decf 0x04,f
0x0007 0080 movwf 0x00
0x0008 2805 goto 0x005 ; test
PIC Forth knows it can compute 2 + 3 at compile time so it does it. The first line loads 5 into W. The next two lines push it onto the stack (FSR, register 4, is the stack pointer). INDF (register 0) is the top of stack. Then a goto jumps to location 5, the start of the program. To turn this into a hex file, type: file-dump xxx.hex Of course, replace xxx with the name of your choice. You can also see a map of memory used by issuing the map command. Use bye to quit. Consider this program: 0 pin-b led
: init led >output ;
: pulse led high led low ;
: mainloop begin pulse again ;
main : test init mainloop ;
The first line sets a word led to refer to port B pin 0. Then three
words are defined:
Then the test word, which is the main program, calls init and mainloop.
If you disassemble the code (dis
command) you'll see that each word is a subroutine:
0x0000 018A clrf 0x0A
0x0001 280C goto 0x00C ; (init-picforth)
0x0002 0000 nop
; name: init
; max return-stack depth: 0
0x0003 1683 bsf 0x03,5
0x0004 1006 bcf 0x06,0
0x0005 1283 bcf 0x03,5
0x0006 0008 return
; name: pulse
; max return-stack depth: 0
0x0007 1406 bsf 0x06,0
0x0008 1006 bcf 0x06,0
0x0009 0008 return
; name: mainloop
; max return-stack depth: 1
0x000A 2007 call 0x007 ; pulse
0x000B 280A goto 0x00A ; mainloop (rs depth: 1)
; name: (init-picforth)
; max return-stack depth: 0
0x000C 3032 movlw 0x32
0x000D 0084 movwf 0x04
; name: test
; max return-stack depth: 1
0x000E 2003 call 0x003 ; init
0x000F 280A goto 0x00A ; mainloop (rs depth: 1)
This is typical of a high level language and not very efficient at run time. However, having the words broken up (factored) like this make the program easy to read and maintain. However, Forth can let you have both efficient code at run time and easy to read code at compile time: 0 pin-b led
macro
: init led >output ;
: pulse led high led low ;
: mainloop begin pulse again ;
target
main : test init mainloop ;
This is the same as before, except for the introduction of the macro
word before the word definitions. The target word reverses the effect of
the macro word. When you disassemble this you get:
0x0000 018A clrf 0x0A
0x0001 2803 goto 0x003 ; (init-picforth)
0x0002 0000 nop
; name: (init-picforth)
; max return-stack depth: 0
0x0003 3032 movlw 0x32
0x0004 0084 movwf 0x04
; name: test
; max return-stack depth: 0
0x0005 1683 bsf 0x03,5
0x0006 1006 bcf 0x06,0
0x0007 1283 bcf 0x03,5
0x0008 1406 bsf 0x06,0
0x0009 1006 bcf 0x06,0
0x000A 2808 goto 0x008 ; test + 0x003
Now all the "subroutines" were expanded inline! You can define variables and constants in several different ways. Here's part of a program that uses a counter:
$F0 constant divreset create counter 0 , \ This makes a variable and initializes it to 0 variable s1-len \ This variable is not initialized When you want to read the value of a variable you use @. So if nothing has changed since the program started, this line will put zero on the top of the stack: counter @ Storing requires the ! word so this sets counter = 10: 10 counter ! There are shortcut words that do things like add directly to a variable (+!) or subtracts directly from a variable (-!). So to decrement counter, you might write: 1 counter -!
|