PASM2/FORTH
The ROM (internal) FORTH interface needs only a PropPlug and a serial terminal emulator to work.
It is possible to call multiple assembly language functions in another cog from FORTH.
This can be done by setting a shared command variable like for instance 'Cmd'.
PASM2 commands can then be investigated interactively to find out exactly how they work.
This can be used to make documentation.
Functions DoPush and DoPop shown below work with the initialized cog's hardware stack.
The opcodes can be found by hand assembly if no assembler is available.
The FORTH words in this block set up a cog to do this.
long Cmd long Xhub long Yhub 27 longs TestCode $FD800007 TestCode 0 + ! --- JMP #\ClearCmd ' Cmd TestCode 4 + ! --- Cmd_ptr LONG 0 ' Pointers Xhub TestCode 8 + ! --- X_ptr LONG 0 ' to hub (for Xhub) Yhub TestCode 12 + ! --- Y_ptr LONG 0 ' variables. (for Yhub) $00000000 TestCode 16 + ! --- Cmd LONG 0 ' Local command to exec. $00000000 TestCode 20 + ! --- Xcog LONG 0 ' Local input variable. $00000000 TestCode 24 + ! --- Ycog LONG 0 ' Local return variable. --- '---------------------------------------------------- $F6040800 TestCode 28 + ! --- ClearCmd MOV Cmd,#0 ' Clear command. $FC600801 TestCode 32 + ! --- WRLONG Cmd,Cmd_ptr ' Store in hub. $FB000801 TestCode 36 + ! --- DoInstr RDLONG Cmd,Cmd_ptr ' Get command from hub. $F21C0800 TestCode 40 + ! --- CMP Cmd,#0 WCZ ' $AD800009 TestCode 44 + ! --- IF_Z JMP #\DoInstr ' If (Cmd==0) Wait. $ED800007 TestCode 48 + ! --- IF_LE JMP #\ClearCmd ' If (Cmd<=0) Clear Cmd. $F21C0802 TestCode 52 + ! --- CMP Cmd,#2 WCZ ' $1D800007 TestCode 56 + ! --- IF_A JMP #\ClearCmd ' If (Cmd>2) Clear Cmd. --- '---------------------------------------------------- $FD600830 TestCode 60 + ! --- JMPREL Cmd ' Jump table. $FD800009 TestCode 64 + ! --- JMP #\DoInstr ' 0=Do nothing. $FD800013 TestCode 68 + ! --- JMP #\DoPush ' 1=Do first function. $FD800017 TestCode 72 + ! --- JMP #\DoPop ' 2=Do second function. --- '---------------------------------------------------- $FD640C5F TestCode 76 + ! --- DoPush DRVNOT #6 $FB000A02 TestCode 80 + ! --- RDLONG Xcog,X_ptr ' Xcog=Xhub; $FD600A2A TestCode 84 + ! --- PUSH Xcog ' $FD800007 TestCode 88 + ! --- JMP #\ClearCmd ' --- '---------------------------------------------------- $FD640C5F TestCode 92 + ! --- DoPop DRVNOT #6 $FD600C2B TestCode 96 + ! --- POP Ycog ' $FC600C03 TestCode 100 + ! --- WRLONG Ycog,Y_ptr ' Store Ycog to Yhub. $FD800007 TestCode 104 + ! --- JMP #\ClearCmd ' TestCode 1 COGINIT --- ok
Then the cog's (in this case) two functions can be used like this.
3 Xhub ! --- Stores 3 in the shared memory variable Xhub to be pushed to the stack.
1 Cmd ! --- Stores 1 into Cmd. This causes the DoPush function to push Xhub to the stack.
2 Cmd ! --- Stores 2 into Cmd. This causes the the DoPop function to pop Yhub from the stack.
Yhub @ . --- Prints the resulting Yhub.
This block shows 10 numbers being pushed to the hardware stack.
# 10 Xhub ! 1 Cmd ! --- ok # 9 Xhub ! 1 Cmd ! --- ok # 8 Xhub ! 1 Cmd ! --- ok # 7 Xhub ! 1 Cmd ! --- ok # 6 Xhub ! 1 Cmd ! --- ok # 5 Xhub ! 1 Cmd ! --- ok # 4 Xhub ! 1 Cmd ! --- ok # 3 Xhub ! 1 Cmd ! --- ok # 2 Xhub ! 1 Cmd ! --- ok # 1 Xhub ! 1 Cmd ! --- ok
And this shows trying to read them back.
# 2 Cmd ! Yhub @ . --- 1 ok # 2 Cmd ! Yhub @ . --- 2 ok # 2 Cmd ! Yhub @ . --- 3 ok # 2 Cmd ! Yhub @ . --- 4 ok # 2 Cmd ! Yhub @ . --- 5 ok # 2 Cmd ! Yhub @ . --- 6 ok # 2 Cmd ! Yhub @ . --- 7 ok # 2 Cmd ! Yhub @ . --- 8 ok # 2 Cmd ! Yhub @ . --- 8 ok (The cog's hardware stack is indeed 8 levels deep.)
Many things could be investigated using this idea.
1. The CNT counter.
2. Bit operations.
3. Conditional execution.
4. JMP CALL RET branching.
5. Smart pins.
6. Math instructions details. Like how the Carry and Zero flags work.
7. CORDIC functions.
8. Repeating instructions.
9. FIFO/Streamer.
10. Locks.
11. Event handling.
12. Etc...