TAQOZ P2 Boot Firmware

UPDATED! May 30, 2018   (pubdoc link) (edit/comment version)   ON HOLD DUE TO ABSENCE OF FEEDBACK (OF CONTENT)

INTRODUCTION

Back in 2012 I decided to write Tachyon Forth for the Parallax Propeller P8X32A or as we refer to it now simply as P1. Briefly, the reason for writing a Forth was not for Forth's sake although the appeal there was an interactive development environment resident on the P1, it was to get more out of the limited memory of the P1, but to also do so as fast as was possible for what is essentially a virtual machine with the view that serious commercial products could be produced based on the flexible P1.

In the years that followed Tachyon has proved itself, through the various original bytecode versions through to the version that now uses 16-bit word codes. The successor to the P1 is simply referred to as the P2 and although it is only available at present as an FPGA image for testing and development, nonetheless serious testing has been carried out for many years. As part of this testing I ported Tachyon across for the P2 and now Chip has announced that the P2 to be available hopefully sometime in 2018 will have 16kB of ROM of which he would only be using a couple of kB or so for the boot loader etc.

TAQOZ is implemented primarily for debugging hardware or testing out "what ifs" but it is still nonetheless a full Forth custom designed for the P2 and its hardware. As it stands the native TAQOZ wordcode can address code in a 16-bit address space while dictionary and data may reside anywhere in memory. So having software written in TWC (TAQOZ Word Code) is very compact and fast and 60kB of code represents a very very large program whereas FAT32, Ethernet servers and VGA would all fit in around 20kB of code space on the P1.

TAQOZ provides an interactive hardware debugging environment through its Forth console via a serial terminal emulator. Even without any "software" it is possible to exercise the hardware and write code on top of the TAQOZ dictionary, thus extending the language's vocabulary of words, all of which are a combination of various functions, constants, variables etc that are referred to by name. Parameters though are passed postfix style so that data is pushed onto a data stack and precede functions.

GETTING THE TAQOZ PROMPT UP

Connect a terminal and I recommend using ones that don't drop characters and support ANSI  such as TeraTerm, RealTerm, GtkTerm, Minicom. You can use any baud rate from 9600 to 2M baud (even 3M works) but by default select 115200, 8 data, 1 stop, no parity, no handshakes, no echo, no extra CR/LFs etc.

Now that you have your P2 connected to a terminal you can type a "greater than sign" and a "space" to autobaud the serial loader after which you can hit escape to escape to TAQOZ. That is the ASCII key sequence for $3E,$20,$1B.

GETTING STARTED

If all is well you should have the splash logo and the prompt.

----------------------------------------------------------------

  Parallax P2  .:.:--TAQOZ--:.:.  V1.0--142              180530-0135

----------------------------------------------------------------

TAQOZ#

Now enter WORDS to see which words are in the dictionary (or hit ^W)

TAQOZ# WORDS

DUP OVER SWAP ROT -ROT DROP 3RD 4TH 2DROP 3DROP NIP 2SWAP 2DUP ?DUP AND

ANDN OR XOR ROL ROR >> << SAR 2/ 2* 4/ 4* 8<< 16>> 8>> 9<< 9>> REV |< >|

>N >B >9 BITS NOT = <> 0= 0<> 0< < U< > U> <= => WITHIN DUPC@ C@ W@ @ C+!

C! C@++ W+! W! +! ! BIT! SET CLR SET? 1+ 1- 2+ 2- 4+ + - UM* * W* / U/

U// // */ UM// C++ C-- W++ W-- ++ -- RND GETRND SQRT SETDACS ~ ~~ W~ W~~

C~ C~~ L>S >W L>W W>B W>L B>W B>L MINS MAXS MIN MAX ABS -NEGATE ?NEGATE

NEGATE ON TRUE -1 FALSE OFF GOTO IF ELSE THEN BEGIN UNTIL AGAIN WHILE REPEAT

SWITCH CASE@ CASE= CASE> BREAK CASE ADO DO LOOP +LOOP FOR NEXT ?NEXT I

J LEAVE IC@ I+ BOUNDS H L T F R HIGH LOW FLOAT PIN@ WRPIN WXPIN WYPIN RDPIN

RQPIN AKPIN WAITPIN WRACK PIN @PIN ns PW PULSE PULSES HILO DUTY NCO HZ

KHZ MHZ MUTE BLINK PWM SAW BIT BAUD TXD RXD TXDAT WAITX WAITCNT REBOOT

RESET 0EXIT EXIT NOP CALL JUMP >R R> >L L> !SP DEPTH COG@ COG! LUT@ LUT!

COGID COGINIT COGSTOP NEWCOG COGATN POLLATN SETEDG POLLEDG KEY WKEY KEY!

CON NONE COM CONKEY CONEMIT SEROUT EMIT EMITS CRLF CR CLS SPACE SPACES

RAM DUMP: DUMP DUMPW DUMPL DUMPA DUMPAW QD QW DEBUG lsio COG LUT KB MB

M . PRINT .AS .AS" .DECL .DEC4 HOLD #> <# # #S <D> U. .DEC .BIN .H .B .BYTE

.W .WORD .L .LONG .ADDR PRINT$ LEN$ " ." CTYPE ?EXIT DATA? ERASE FILL CMOVE

<CMOVE s ms us CNT@ LAP LAP@ .LAP .ms HEX DEC BIN .S WORDS @WORDS GET$

SEARCH $># @DATA HERE @HERE @CODES uemit ukey char delim names TASK REG

@WORD SPIN | || , [W] ["] NULL$ $! $= ASM FORGET CREATE$ CREATE VAR pub

pri pre : ; [ ] ' := ==! ALIGN DATCON ALLOT org bytes words longs byte

word long res [C] GRAB NFA' CPA CFA \ --- ( { } IFNDEF IFDEF TAQOZ TERM

AUTO SPIRD SPIRDL SPIWB SPICE SPIWC SPIWW SPIWM SPIWL SPIPINS SPIRX SPITXE

SPITX WSLED WAIT CLKDIV RCSLOW HUBSET WP WE CLKHZ ERROR SFPINS SF? SFWE

SFINS SFWD SFSID SFJID SFER4 SFER32 SFER64 SFERASE SFWRPG BACKUP RESTORE

SFRDS SFWRS SFC@ SFW@ SF@ SF .SF SDBUF sdpins MOUNT DIR !SD !SX SD? CMD

ACMD cid SDWR SDRDS SDWRS FLUSH FOPEN FLOAD FGET FREAD FWRITE SECTOR SDRD

SDRDS SDADR SD@ SD! SDC@ SDC! SDW@ SD @FAT @BOOT @ROOT fat END  433 ok

TAQOZ#

These are all the words that TAQOZ understands that you can type in and run or build into new words that are added to the dictionary. Let's just try interacting with TAQOZ for a moment and make an LED blink. Assume we have an LED connected to P5 we can make it blink very simply with 5 BLINK which is defined simply as PIN 2 HZ where the word PIN takes the argument 5 off the top of the data stack and HZ takes the 2 and configures the selected pin as an NCO with a frequency of 2 HZ. Since TAQOZ boots up in RCFAST it is running at a 20MHz speed rather than 80MHz so it will be slower. To make it blink faster and since the pin has already been selected through PIN we can just type in 10 HZ instead or any other value.

Remember that all words and numbers should be separated by at least one space but they can even be on separate lines.

TAQOZ# 5 BLINK  ok

TAQOZ# 10 HZ  ok

The HZ word is using the smartpin mode so it doesn't need any code running continually to make it blink but to make the smartpin stop type MUTE 

If we have multiple LEDs connected to P0 to P7 we can make them all blink in one simple loop 8 0 DO I BLINK LOOP which specifies a limit and a starting index used by DO to setup a loop consisting of I BLINK . The I leaves the current loop index value on the stack which is then used by BLINK so that each time through the loop the index will increment up to the limit of 8 and exit the loop. This means that the index I will go through the values 0,1,2,3,4,5,6,7 branching back each time to just after DO but once it reaches 8 it does not loop back but continues after the word LOOP which in the case of the example executes an automatic EXIT or return operation back to the console ready for more input.

You can customise this simple 8 LED blinker by having a different blink rate for each LED like this: 8 0 DO I PIN I 2 + HZ LOOP

Now that creates an interesting pattern with the interaction between the LEDs.

TAQOZ# MUTE  ok

TAQOZ# 8 0 DO I PIN I 2 + HZ LOOP  ok

NEW WORDS

WORD

STACK

DESCRIPTION

WORDS

Display all the dictionary words (includes user words)

BLINK

( pin -- )

Select the smartpin and make it blink slowly

PIN

( pin -- )

Select a smartpin to use

HZ

( n -- )

Configure the preselected smart pin as an NCO set to n Hz

MUTE

Mute or stop the preselected smartpin

DO

( limit start -- )

Push limit and start index and loop start address onto the loop stack.

LOOP

Increment the loop index and loop back while index <> limit

I

( -- index )

Push the current loop index value onto the stack

STACK BASICS

You may find Forth style RPN "back-to-front" from conventional languages but that doesn't mean either one is better. Do you know that we use RPN in our speech? Everyone knows it takes 60 seconds to make 1 minute. Wait a minute, where's the RPN? Well in most computer language "styles" we might express that as "minute(1) = seconds(60)" so the latter is more mathematical but the former is more natural for English speakers. Where it doesn't seem natural is when we have more than one parameter as in adding numbers. Try this: 8 4 + which performs the addition after it has the parameters with the result left on the stack. After all though, you can't bake a cake before you have both eggs and flour available, just like Forth parameters where we bake the 8 and 4 with a + operation. You can type a single tiny dot . to print (and use) the number off the stack or you can type .S to view the stack.

TAQOZ# 8 4   ok

TAQOZ# .S

 DATA STACK (2)

1   $0000.0004   4

2   $0000.0008   8 ok

TAQOZ# +  ok

TAQOZ# .S

 DATA STACK (1)

1   $0000.000C   12 ok

TAQOZ#

NEW WORDS

WORD

STACK

DESCRIPTION

+

( n1 n2 -- n3 )

Add (and use) n1 and n2 and push the result n3 back onto the data stack

.S

Print and view the contents of the data stack non-destructively

.

( n -- )

Print the signed value in the current number base (default decimal)

BLINKING LEDs AGAIN

Making the LED blink the hard old way we need to stop those blinking LEDs first but they won't stop blinking after a reset or even a cold start (type ^Z). We could power it back up or we could use Forth to do the work for us: 8 0 DO I PIN MUTE LOOP 

Now that we shut them up here's the old way in Forth, but it is only a single line: BEGIN 5 HIGH 100 ms 5 LOW 100 ms AGAIN

That works but now it is locked up in an endless loop bounded by BEGIN AGAIN and the console doesn't respond!!! Don't panic, just hit escape four times in a row to get back to the console. If I wanted any key to stop the looping I could have typed: BEGIN 5 HIGH 100 ms 5 LOW 100 ms KEY UNTIL

KEY returns a character from the serial buffer and pushes the value onto the stack just like any other value. When the buffer is empty KEY returns a null value or the value 0. UNTIL uses a value off the top of the stack as a true/false flag and will continue looping until the value it true. In most languages 0 is false but any non-zero value can be true and such is the case with our BEGIN UNTIL loop.

NEW WORDS

WORD

STACK

DESCRIPTION

BEGIN

Mark (no code) the beginning of a BEGIN loop (no indexing or automatic count)

AGAIN

Jump back to the first word after BEGIN

UNTIL

( flg -- )

Until the flg is true loop back

HIGH

( pin -- )

Drive the pin high (automatically sets the direction register)

LOW

( pin -- )

Drive the pin low  (automatically sets the direction register)

ms

( n -- )

Wait for n milliseconds

KEY

( -- char )

Return with the next character in the console buffer or else a value of $00

DEFINING NEW WORDS

Forth is like tofu, it takes on the flavor of what you add to it and so the language can be extended with new definitions/functions referred to as words which are maintained in a dictionary. The dictionary is the goto place for when you are typing into the console and if what you type is not a number it will search the dictionary for a match and when found it looks up the code address field in that entry and compiles this, either as an interactive temporary compilation or as part of a new word being defined. Note though that some words are never normally compiled as they are directives needed to control the compiler and to create structures. These are referred to as immediate words (but even immediate words can be forced to compile using other immediate words!)

Now let's take the bit of code we used to create a blinking LED in software and create a new word called "BLINKY" like this:

: BLINKY BEGIN 5 HIGH 100 ms 5 LOW 100 ms KEY UNTIL ;

Remember to use at least one space between ALL words including : and ;

The name BLINKY has been added to the dictionary (you can type WORDS to check if you like) and so if we type BLINKY it will do just so.

TAQOZ# : BLINKY BEGIN 5 HIGH 100 ms 5 LOW 100 ms KEY UNTIL ;  ok

TAQOZ# BLINKY

Now BLINKY is "hard wired" to P5 and 100 ms delay but we could define a better BLINKY that takes a pin number and a delay value like this:

: BLINKER ( pin ms -- ) BEGIN OVER HIGH DUP ms OVER LOW DUP ms KEY UNTIL 2DROP ;

Welcome to manipulating the stack using DUP OVER and 2DROP (which is simply DROP DROP) etc.

TAQOZ# : BLINKER ( pin ms -- ) BEGIN OVER HIGH DUP ms OVER LOW DUP ms KEY UNTIL 2DROP ;  ok

TAQOZ# 2 20 BLINKER

If you want to run code in another cog then is a very quick and simple example to run it in COG#1 as a task. First however we need to run a new instance of TAQOZ in another cog (originally they were all loaded but the latest version doesn't automatically load them).

In this example we will choose cog#1 using 1 NEWCOG

TAQOZ# 1 NEWCOG  ok

Now that COG#1 has been loaded with a TAQOZ kernel it is sitting in a IDLE loop waiting for a task to perform. All we need to do is to give it the address of that task. To make BLINKER run continuously the blinking code is placed in a BEGIN AGAIN structure which will loop unconditionally after which we can find the address of BLINKER (using the tick symbol $27) and store it where cog#1 will be checking in its task variable.

TAQOZ# : BLINKER BEGIN 7 HIGH 100 ms 7 LOW 100 ms AGAIN ;  ok

TAQOZ# ' BLINKER 1 TASK W!  ok

The last line here I would pronounce as "address of - BLINKER - 1 TASK - W STORE"

NEW WORDS

WORD

STACK

DESCRIPTION

:

Read in the following word and create a new word in the dictionary

Does not execute any code while defining

;

Compile an EXIT word and ends definition - does not execute

EXIT

Exit word by returning to implicit caller

OVER

( n1 n2 -- n1 n2 n1 )

Duplicate the second stack item, that is push a copy over the top.

DUP

( n1 -- n1 n1 )

Duplicate the top stack item (copies and pushes)

DROP

( n1 -- )

Drop the top stack item (pops and discards)

2DROP

( n1 n2 -- )

Drop 2 stack items (pops the stack twice)

(

Stack comment up to trailing ) is ignored by the compiler (<--whitespace!)

'

( -- address )

Find the CFA (code field address) of the word following the tick.

W!

( n address -- )

Store n as a 16-bit word at address. (wrword  tos1,tos)

TASK

( cog# -- address )

Index the cog's task variable and return with its address.

Q: What code is compiled when we define a new word?

In the example of blinker we can look at the code compiled by finding the code address using the tick word which will leave the CFA (code field address) on the stack from which we can use that address and dump it in a suitable format:

TAQOZ# ' BLINKER $20 DUMPW

00.102C: 0074 0175 0071 D7C8 0074 0177 0071 D7C8        t.u.q...t.w.q...

00.103C: E0DA FC8A 0066 0061 013E 102C FE20 D892        ....f.a.>.,. ... ok

Substituting names for wordcodes

00.102C: OVER HIGH DUP  ms   OVER LOW  DUP  ms          t.u.q...t.w.q...

00.103C: KEY UNTIL 2DROP EXIT 013E 102C FE20 D892        ....f.a.>.,. ... ok

16-bit word size was chosen with DUMPW for 32 bytes and the first wordcode is $0074 which is the cog address of OVER. In fact any wordcode that is less than $400 is a cog/lut address which is executed by the wordcode interpreter loop. But $D7C8 is not a cog address but points to more wordcode. The $0074 following it is the same as the first wordcode which is OVER. We can use the tick symbol word to find the CFA of OVER to confirm this:

TAQOZ# ' OVER .W $0074 ok

Therefore, each 16-bit wordcode has a direct correspondence with a word in the BLINKER definition. If you follow it through past 2DROP ($0066) you will find that $0061 is not the ; word used to complete the definition, it is in fact the wordcode for EXIT since ; is an immediate word that tells the compiler to complete the definition and compile an EXIT. Wordcodes such as FC8A are compact wordcodes that are decoded further and in this case $FC8x means conditional branch backwards by n words. So $0A = to 10 words back from the next instruction which brings us back to the beginning.

Now as for the name BLINKER itself it is kept in the dictionary which is made up of a contiguous list of names that include the count byte and attributes, and the wordcode for the name. To find that entry use NFA' instead.

TAQOZ# NFA' OVER $10 DUMP

00.B406: 04 4F 56 45 52 74 00 04 53 57 41 50 7B 00 03 52        .OVERt..SWAP{..R ok

MORE SMARTPIN FUN

PWM is used everywhere from power supplies to motor speed control and even generating analog waveforms. By varying the on time of a repetitive pulse to the off time we can vary the average voltage (thereby power) which may be eventually filtered by mechanical motion, thermal response, or by a filter of some kind. The ratio of on to off time is called the duty cycle meaning that a square wave that has equally on and off has 50% duty cycle and can only deliver an average of 50% of the voltage whereas an on time of 1 in 4 would deliver an average of 25%. If you connect a heating element via a suitable driver you can vary the amount of heat simply by controlling the duty cycle and if the repetitive frequency is high enough the thermal response "filters" these pulses. Slow it right down from hundreds or thousands of times per second to many seconds and those pulses of heat will no longer be filtered or averaged out. Similarly we can generate a voltage by filtering a PWM signal with a simple resistor and capacitor filter so that 0% duty outputs 0V and 100% duty outputs the full signal voltage (normally 3.3V) but 25% will produce 825mV.  PWM is used in place of linear control because it can be controlled digitally and without the losses that result from "restricting" the power, a bit like putting your hand on an electric motor to try and slow it down!!.

The smartpins support a few different modes of PWM but if we have an LED connected to a pin we should be able to make it very dim with a 10% duty cycle PWM. This is how we can do it in TAQOZ after we have selected a pin to use, in this case 5 PIN and then 10 100 10 PWM which specifies on time in clock cycles, overall frame time (that is, the combined on and off time), and the frequency in clock cycles which should be fast enough to be filtered effectively, in this case by persistence of vision in the human eye. The example given uses a frame of 100 cycles just so that the on time can be expressed as a percentage. The longer the frame time the greater the resolution, but also the lower the repetitive frequency which is also prescaled by the last parameter.

Try different values but lastly try making the frequency value very high for a very slow frequency, slow enough that POV filtering becomes ineffective. Try 10 100 10000 PWM and you will see the LED pulse and now it seems brighter even though the duty cycle hasn't changed. Drop back to 1% with 1 100 10000 PWM and it will still flicker the same rate but be much dimmer.

Make a new name for our dimmer as part of Forth and use it:

TAQOZ# : DIMMER ( value pin -- )         PIN 100 10 PWM ;  ok

TAQOZ# 5 6 DIMMER  ok

TAQOZ# 20 6 DIMMER  ok

TAQOZ# 20 5 DIMMER  ok

We could have elected to not specify a pin directly but leave it out like the other examples and perhaps that would be more consistent like this instead:

TAQOZ# : DIMMER ( value -- )           100 10 PWM ;  ok

TAQOZ# 4 PIN 50 DIMMER  ok

TAQOZ# 5 PIN 1 DIMMER  ok

TAQOZ# 5 DIMMER  ok

Lastly in this console capture we setup 4 pins to output 4 different rates from 20 to 80% duty cycle with the resultant waveforms

TAQOZ# 5 PIN  ok

TAQOZ# 10 100 10 PWM  ok

TAQOZ# 10 100 10000 pwm  ok

TAQOZ# 1 100 10000 PWM  ok

TAQOZ# 4 0 DO I PIN I 1+ 20 * 100 10 PWM LOOP  ok

Another mode that is very useful is being able to generate an exact number pulses with controlled high and low times.

We can do it like this and show it alongside our previous PWM pulses for comparison.:

TAQOZ# 0 PIN 1000 3000 HILO 3 PULSES  ok

After specifying HILO we can play with 2 or 10 or 100 pulses etc.

NEW WORDS

WORD

STACK

DESCRIPTION

PWM

( on frame freq -- )

Enable PWM that turns on for on cycles, off for frame-on, and freq as a prescaler (more=slower)

HILO

( high low -- )

Specify High and Low times for subsequent PULSE or PULSES words

PULSES

( cnt -- )

Generate cnt pulses according to specified high and low times.

PULSE

Sames as PULSES but only one pulse

'

<name> ( -- cfa )

This immediate acting word finds the code address of the following word and leaves the value on the stack

NFA'

<name> ( -- nfa )

This immediate acting word finds the address of the word in the dictionary

.W

( n -- )

Print n as a 16-bit formatted hex word.

SMARTPINS AS ASYNCHRONOUS SERIAL UARTS

<WORK IN PROGRESS>

About the format of this document

The CONSOLE EXAMPLES column show the prompt and user input followed by the response and a final "ok" as indication of acceptance. It may be confusing therefore for those unfamiliar with Forth-like languages as to what constitutes user input and what constitutes the response. Rather than explaining all this I have colored in the user input in some examples as a guide.

Sample word description

Here this row covers both the FOR and the NEXT word since they are used together to form a simple loop.

WORDS

DESCRIPTION

CONSOLE EXAMPLES

FOR NEXT

Simple counted loop

FOR ( cnt -- )

TAQOZ# CRLF 3 FOR ." HELLO! " NEXT

HELLO! HELLO! HELLO!  ok

Boolean values of FALSE and TRUE are simply 0 or -1 ($FFFF_FFFF) although in fact any non-zero value can be accepted as a boolean true but not necessarily suitable for bitwise operations such as AND. For instance 4 IF and 8 IF would both resolve as true however 4 8 AND IF fails. Use 0<> to promote any non-zero to a full TRUE in such cases.

The stacks

TAQOZ is based on Tachyon Forth which maintains a data stack in LUT memory in each cog but keeps a copy of the top four elements in fixed registers in cog memory for quick and efficient access. Therefore there are no (ugly) PICK and ROLL operators so as to encourage clean and efficient coding using a minimum of stack manipulation. The "top of stack" element or the last one pushed etc is referred to simply as "tos". The stack is a last in, first out and functions that require and pass parameters draw from the top of the stack to usually no more than a depth of four elements.

In addition to the data and return stack, there is a dedicated loop parameter stack and a branch stack used internally by looping structures. Since the return stack is only used for return addresses we can then also access loops and parameters from any section of code that is not part of that loop.


LIST OF DEBUGGING CONTROL KEY SHORTCUTS

ESC ESC ESC ESC

ESC

^C

^W

^D

^Q

^S

^B

^X

^Z

^?

Reset (works even if Tachyon is not checking the console)

Discard the current console line input

Reset

List WORDS in dictionary

LSD Debugger in ROM (use ESC<CR> to return to TAQOZ)

Print data stack

Clear data stack

Block memory dump of first 64kB

Re-eXecute last line (very useful)

Cold start Zap - wipe new code and dictionary - restore settings

DEBUG List registers, current code an dictionary memory, and I/O


DEBUGGING

WORDS

DESCRIPTION

CONSOLE EXAMPLES

WORDS

List the current dictionary of words

^W shortcut

DUMP  DUMPW  DUMPL

DUMPA  DUMPAW

Dump selected memory as bytes, words, longs, ASCII, ASCII wide or a quick 32 byte fixed dump.

TAQOZ# @WORDS $20 DUMP

0B3F9: 04 44 45 4D  4F 00 10 03  44 55 50 73  00 04 4F 56         '.DEMO...DUPs..OV'

0B409: 45 52 77 00  04 53 57 41  50 7E 00 03  52 4F 54 82         'ERw..SWAP~..ROT.' ok

QD QW

Quick Dump or Quick dump Words.

Short form instead of typing "$20 DUMP" or "$20 DUMPW"

TAQOZ# : DEMO 10 2* . ;  ok

TAQOZ# ' DEMO QW

01000: F80A 00AE DA82 0063  013F 1000 D88A 0063         '......c.?.....c.'

01010: 0063 0000 0000 0000  0000 0000 0000 0000         'c...............' ok

COG  LUT RAM

SD FS SD SF

Modifies the next DUMP to use COG or LUT memory instead of the default HUB RAM. Resets to RAM after each DUMP

TAQOZ# 0 4 COG DUMP

00.0000:  FDA0.0990 FD90.00BC 0000.0000 0000.0000  ok

.S

List the contents of the data stack

Also accessible as the ^Q shortcut

TAQOZ# $CAFEBABE DUP $FFFF AND SWAP 16 >> .S

 DATA STACK x2

1   $0000.CAFE   51966

2   $0000.BABE   47806 ok

DEBUG

Dumps the various stacks, task registers, and quick dumps of sections of the current code and dictionary memory. ^? shortcut

LAP  .LAP

Measure LAP timing and report

TAQOZ# LAP 1234 5678 * LAP .LAP 242 cycles = 3.25us  ok

RESET

Reset the P2 chip.

^C or <break> shortcut

I/O PORTS

WORDS

DESCRIPTION

CONSOLE EXAMPLES

PIN@

Read the state of a pin

PIN ( pin -- state )

HIGH LOW FLOAT

Set the direction and output of a pin

( pin -- )

TAQOZ# 4 HIGH 4 PIN@ . -1 ok

TAQOZ# 4 LOW 4 PIN@ . 0 ok

H  L  F  R

Set the direction and output of a preselected pin via PIN or read the state via R

TAQOZ# 4 PIN  ok

TAQOZ# L R . 0 ok

TAQOZ# H R . -1 ok

PIN  @PIN

Select an I/O pin to operate on or read setting back

TAQOZ# 5 PIN @PIN . 5 ok

SMARTPINS

WORDS

DESCRIPTION

CONSOLE EXAMPLES

WRPIN WXPIN WYPIN RDPIN RQPIN AKPIN

Performs the same operation as the PASM instructions.

WAITPIN TXDAT DUTY NCO

HZ KHZ MHZ BLINK

Set PIN to NCO mode and output the frequency whereas BLINK sets an output to 2 Hz, effectively a "blink".

TAQOZ# 4 PIN 10 MHZ  ok

MUTE

Cancel the smartpin mode. Effectively muting any frequency, sound, or other function.

PWM  SAW

Set pin to PWM triangle mode using duty, frame, and divider parameters. Use SAW instead for sawtooth.

PWM ( duty frame div -- )

TAQOZ# 4 PIN  1000 4000 1 PWM  ok

TXD

Setup a pin as an asynchronous transmit using the supplied parameter as a baud rate.

TAQOZ# 34 PIN 8 BIT 40 M TXD @NAMES $10 TXDAT  ok

RXD

Setup a pin as an asynchronous receive using the supplied parameter as a baud rate.

BIT

Specify the data bits (1..32) to be used whenever a pin is switched to RXD or TXD modes. If this is not specified it will default to 8.

TAQOZ# 8 BIT 115200 TXD  ok

STACK OPERATORS

WORDS

DESCRIPTION

CONSOLE EXAMPLES

DUP OVER 3RD 4TH

Make a copy of the 1st, 2nd, 3rd, or 4th element and push onto the stack

TAQOZ# 1234 5678 9012 3456  .S

 DATA STACK x4

1   $0000.0D80   3456

2   $0000.2334   9012

3   $0000.162E   5678

4   $0000.04D2   1234 ok

TAQOZ# 4TH .S

 DATA STACK x5

1   $0000.04D2   1234

2   $0000.0D80   3456

3   $0000.2334   9012

4   $0000.162E   5678

5   $0000.04D2   1234 ok

?DUP

Duplicate the tos only if it is non-zero

TAQOZ# 1234 ?DUP 0 ?DUP .S

 DATA STACK x3

1   $0000.0000   0

2   $0000.04D2   1234

3   $0000.04D2   1234 ok

DROP 2DROP 3DROP

Drop and discard the top elements of the data stack, either 1, 2, or 3 levels.

TAQOZ# 1234 5678 9012 .S

 DATA STACK x3

1   $0000.2334   9012

2   $0000.162E   5678

3   $0000.04D2   1234 ok

TAQOZ# 2DROP .S

 DATA STACK x1

1   $0000.04D2   1234 ok

NIP

Nip out the second element

TAQOZ# 1234 5678 9012 NIP .S

 DATA STACK x2

1   $0000.2334   9012

2   $0000.04D2   1234 ok

SWAP

Swap the top two data elements

TAQOZ# 1234 5678 .S

 DATA STACK x2

1   $0000.162E   5678

2   $0000.04D2   1234 ok

TAQOZ# SWAP .S

 DATA STACK x2

1   $0000.04D2   1234

2   $0000.162E   5678 ok

ROT

Rotate the 3rd element to the top

TAQOZ# 1234 5678 9012 .S

 DATA STACK x3

1   $0000.2334   9012

2   $0000.162E   5678

3   $0000.04D2   1234 ok

TAQOZ# ROT .S

 DATA STACK x3

1   $0000.04D2   1234

2   $0000.2334   9012

3   $0000.162E   5678 ok

-ROT

Rotate the top element to the 3rd position (Reverse ROT)

equiv ROT ROT

TAQOZ# 1234 5678 9012 .S  

 DATA STACK x3

1   $0000.2334   9012

2   $0000.162E   5678

3   $0000.04D2   1234 ok

TAQOZ# -ROT .S

 DATA STACK x3

1   $0000.162E   5678

2   $0000.04D2   1234

3   $0000.2334   9012 ok

DEFINING

WORDS

DESCRIPTION

CONSOLE EXAMPLES

 pub pri pre : ;

Create new Forth word as public, private, preemptive, or default :

==

Create a long constant (CONSTANT)

byte word long

bytes words longs

Create and allocate variable(s) in the data area.

CREATE$ CREATE VARIABLE

BRANCHING

WORDS

DESCRIPTION

CONSOLE EXAMPLES

IF ELSE THEN

BEGIN AGAIN

WHILE REPEAT

EXIT 0EXIT ?EXIT

Exit now, on 0/false, on true.

LOOPING

WORDS

DESCRIPTION

CONSOLE EXAMPLES

DO ADO LOOP +LOOP

Execute code between DO LOOP until the index equals the limit.

DO ( limit start -- )

ADO ( start cnt -- )

TAQOZ# 8 0 DO I . LOOP 01234567 ok

TAQOZ# 0 8 ADO I . LOOP 01234567 ok

TAQOZ# 0 8 ADO I . 2 +LOOP 0246 ok

FOR NEXT

Simple counted loop

FOR ( cnt -- )

TAQOZ# CRLF 3 FOR ." HELLO! " NEXT

HELLO! HELLO! HELLO!  ok

?NEXT

Exit FOR NEXT loop early if flag is true (non-zero)

NEXT? ( flag -- )

I J K

I returns the current loop index while J and K return the index for outer loops.

XXX

WORDS

DESCRIPTION

CONSOLE EXAMPLES

TIMING

WORDS

DESCRIPTION

CONSOLE EXAMPLES

us ms s

Delay for microseconds, milliseconds, or seconds

TAQOZ# CNT@ 100 ms CNT@ SWAP - . 8000552 ok

CNT@ LAP .LAP LAP@

Timing code between each LAP and report results with .LAP. CNT@ reads the 32-bit CNT and LAP@ is used internally by .LAP

TAQOZ# LAP 1234 5678 * LAP .LAP 242 cycles = 3.25us ok

MEMORY

WORDS

DESCRIPTION

CONSOLE EXAMPLES

ERASE  FILL

Fill memory with byte or erase to zeros.

TAQOZ# $4.0000 $10 $FA FILL  ok

TAQOZ# $4.0000 $20 DUMP

04.0000: FA FA FA FA FA FA FA FA FA FA FA FA FA FA FA FA        ................

04.0010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00        ................ ok

 CMOVE  <CMOVE

Move memory bytes starting from source to destination by count

CMOVE ( src dst cnt -- )

or start backwards from end using <CMOVE

TAQOZ# @NAMES $4.0000 $20 CMOVE  ok

TAQOZ# $4.0000 $20 DUMP

04.0000: 03 54 52 49 80 86 1F 03 53 41 57 80 80 1F 03 44        .TRI....SAW....D

04.0010: 55 50 80 6B 00 04 32 44 55 50 80 6D 00 04 4F 56        UP.k..2DUP.m..OV ok

C@  W@  @

Fetch a byte, word, or long from hub memory

TAQOZ# @NAMES $10 DUMP

00.CFF2: 03 54 52 49 80 86 1F 03 53 41 57 80 80 1F 03 44        .TRI....SAW....D ok

TAQOZ# @NAMES C@ .BYTE 03 ok

C@++

Fetch a byte from memory and keep and increment the address

TAQOZ# $1000 C@++ .S

 DATA STACK x2

1   $0000.005C   92

2   $0000.1001   4097 ok

C!  W!  !

Store a byte, word, or long to hub memory

TAQOZ# $DEADBEEF $F000 !  ok

TAQOZ# $F000 $10 DUMP

00.F000: EF BE AD DE 00 00 00 00 00 00 00 00 00 00 00 00        ................ ok

C+!  W+!  +!

Add parameter directly to memory location.

TAQOZ# $600 $F000 +!  ok

TAQOZ# $F000 $10 DUMP

00.F000: EF C4 AD DE 00 00 00 00 00 00 00 00 00 00 00 00        ................ ok

COG@  COG!

LUT@  LUT!

Similar operation to @ and ! except COG or LUT memory is used

TAQOZ# 0 COG@ .LONG FDA0.0990 ok

TAQOZ# 0 LUT@ .LONG 0000.04D2 ok

TAQOZ# $CAFEBABE 2 COG! 2 COG@ .LONG  CAFE.BABE ok

C++ C-- W++ W-- ++ --

Increment or decrement memory

C~ C~~ W~ W~~ ~ ~~

Clear ~ or set ~~ the memory location

COMPARISON

WORDS

DESCRIPTION

CONSOLE EXAMPLES

0= 0<> 0<

Compare tos value with zero

TAQOZ# 0 0= . -1 ok

TAQOZ# 0 0<> . 0 ok

=  <>  <  >  

U<  U>  <=  =>

Compare top two values

WITHIN

XXX

WORDS

DESCRIPTION

CONSOLE EXAMPLES

Single Operand Instructions

These instructions work with a single operand and return with a single operand. Because they do not push or pop they are useful since they are both faster and more compact. For instance the word 8>> might simply be equivalent to 8 >> except it only needs a single wordcode and saves time by not having to push 8 and then pop it to discard afterwards since it is essentially a single PASM instruction.

WORDS

DESCRIPTION

CONSOLE EXAMPLES

1+ 2+ 4+

Increment the tos element by 1, 2, or 4

TAQOZ# 1234 2+ . 1236 ok

1- 2-

Decrement the tos element

TAQOZ# 1234 2- . 1232 ok

2/ 4/ 8>> 9>> 16>>

Shift tos right by 1, 2, 8, 9, or 16

( 2/ = 1 >> )

2* 4* 8<< 9<<

Shift tos left by 1, 2, 8, or 9

SPI

Serial Peripheral Interface is implemented as cog instructions that handle half-duplex read or write in increments of 8-bits. Once the SPI pins have been set then any read or write will automatically enable the Chip Enable and only requires a SPICE to turn it back off if required. Sometimes all that is required here is to SPICE just before starting a new command to reset the slave.

WORDS

STACK

DESCRIPTION

CONSOLE EXAMPLES

SPIWB SPIWW SPIWC

( n1 -- n1 )

Write Byte or Word or SD Command to SPI pins.

200ns/div example sending $A5 then SPICE

TAQOZ# $12345678 SPIWB .S

 DATA STACK x1

1   $0000.0078   120 ok

SPIWR

( n1 -- n2 )

Write msb byte and return with parameter rotated left 8 bits. Four successive SPIWRs will send all 32-bits

TAQOZ# $12345678 SPIWR .S

 DATA STACK x1

1   $3456.7812   878082066 ok

SPIRD

( n1 -- n2 )

Read 8-bits left into n1 so that n2 = n1<<8+new.

Four successive SPIRDs will receive 32-bits

SPICE

Release SPI CE line

SPIPINS

( &cs.mi.mo.ck -- )

Setup SPI pins as &ce.miso.mosi.sck

TAQOZ# &32.33.34.35 SPIPINS  ok                      

SPIRX SPITX SPITXE

( adr cnt -- )

Send or receive between memory and SPI

500ns/div example writing 4 bytes from memory

TAQOZ# &32.33.34.35 SPIPINS  ok

TAQOZ# 0 4 SPITXE SPICE  ok

CLKIN CLKOUT CLOCK WS2812

CHARACTER I/O

WORDS

DESCRIPTION

CONSOLE EXAMPLES

CONEMIT EMIT  

CRLF  CR  DOT

SPACE  SPACES EMITS

CONKEY KEY WKEY

KEY!

CON

 .B .BYTE .W .WORD .L .LONG .ADDR . PRINT @PAD HOLD >CHAR #> <# # #S <D> PRINT$ LEN$ U. .DEC

COG/HUB

WORDS

DESCRIPTION

CONSOLE EXAMPLES

COGID COGINIT COGSTOP COGATN

POLLATN SETEDG POLLEDG

HUBSET WP WE REBOOT

HUBSET operation or Write Protect/Enable ROM etc.

CONSTANTS

WORDS

DESCRIPTION

CONSOLE EXAMPLES

BUFFERS ROM VECTORS

TAQOZ# ROM .L $000F.C000 ok

TAQOZ# VECTORS .L $000F.FFE0 ok

TAQOZ# BUFFERS .L $0000.F000 ok

PTRA PTRB DIRA DIRB OUTA OUTB INA INB

TAQOZ# DIRA .W $01FA ok

TAQOZ# PTRA .W $01F8 ok

ON TRUE -1 FALSE OFF

TAQOZ# ON OFF .S

 DATA STACK x2

1   $0000.0000   0

2   $FFFF.FFFF   -1 ok

CLKFREQ CLKMHZ

Clock frequency constants

TAQOZ# CLKFREQ . 80000000 ok

MODIFIERS

WORDS

DESCRIPTION

CONSOLE EXAMPLES

KB MB M

VARIABLES

WORDS

DESCRIPTION

CONSOLE EXAMPLES

XXX

WORDS

DESCRIPTION

CONSOLE EXAMPLES

flags uemit ukey base digits prompt accept names  lines errors lastkey unum

        

REV

>N >B 9BITS         Mask tos to 4, 8, or 9 bits ( >N = $0F AND )

BOUNDS

+ -

IX LEAVE IC@ I+

AND ANDN OR XOR ROL ROR SAR

>> ( n cnt -- ) Shift n right for cnt

<<

|< >|

BITS NOT

BIT! SET CLR SET?

UM* * W* SQRT MIN MAX BMASK ABS -NEGATE ?NEGATE NEGATE

SHROUT SHRINP

SEROUT SERBAUD DELTA WAITCNT

SPLIT9 RESET 0EXIT EXIT NOP CALL JUMP BRANCH> >R R> >L L> !SP DEPTH

RND

REG keypoll CON DISCARD

 ERROR DUMP: / U/ U/MOD MOD */ ?EXIT MOVBYTES

HEX DEC BIN

@NAMES WORD$ SEARCH $># .S HERE @HERE @CODES

TASK @WORD SPIN GETRND | || ,

 == DATCON ALLOT [C] GRAB

' NFA' FORGET >CPA >CFA

 SWITCH CASE@ CASE= CASE>< BREAK CASE

\ --- ( { } IFNDEF IFDEF " ." CTYPE IDLE

.VER TACHYON CONSOLE AUTORUN

WAIT CLKDIV RCSLOW

END