Try these TAQOZ code snippets and learn!



  • Peter JakackiPeter Jakacki Posts: 9,211
    edited 2020-06-21 - 02:18:17
    I've just updated the binary on SourceForge to enforce mounting of the SD card so that it reports correctly in the startup report. The default baud rate had also been dialed back to 115200 baud but remember that this can be changed at anytime after booting such as "2,000,000 CONBAUD" which takes effect immediately so change your terminal setting and backup after to lock it in. The README has also been updated, seeing too that it was incorrect anyway.

    I've attached the current files for convenience but if this is an old post then please go to my SourceForge site for the most current.
    CARD: SANDISK   SD SC64G REV$80 #35190404 DATE:2018/10
    KERNEL            Parallax P2  *TAQOZ RELOADED sIDE*  V2.6 'CHIP' Prop_Ver G 200MHz 200621-1000
       1508 *TEXT*          VGA BMP TEXT 190800-0000
       1260 *BMV*           BMV VIDEO PLAYER 190800-0000
        772 *WAVE*          WAVE AUDIO FILE PLAYER 190800-0000
        430 *BMP*           BMP FILE VIEWER 190800-0000
       1944 *TIM*           TAQOZ INTERACTIVE MEDIA - AUDIO, TEXT, IMAGE & VIDEO DRIVERS 200403-1200 
       4866 *TIA*           TAQOZ INTERACTIVE ASSEMBLER for the PARALLAX P2 - 200327-2300
       2528 *DISK*          SD DISK REPORTING & FORMATTING TOOLS 190800-0000
       4756 *TAFFS*         TAQOZ FAT32 FILE SYSTEM for SD CARD plus VIRTUAL MEMORY  200621-1000
       1400 *SPIRAM*        LY68L6400 8MB SPI RAM ACCESS 191020-0000
       1774 *DECOMPILER*    A decompiler for TAQOZ 190825-0000
       1312 *RTC*           RV-3028 RTC DATE and TIME 190800-0000
        814 *SMARTPINS*     SMARTPIN FUNCTIONS and drive modes 190800-0000
        400 *P2CLOCK*       P2 CLOCK CONTROL 190800-0000
       2184 *ANSI*          ANSI TERMINAL SUPPORT 200410-0000
        396 *EXTEND*        Primary kernel extensions 200621-1000
       5754 *SPIFLASH*
      CODE:         09DC4  40,388 bytes
      WORDS:        1C14E  15,905 bytes
      DATA:         01F40  1,138 bytes
      ROOM:                74,634 bytes
      PCB           P2      (P2D2)
      CLOCK IN      20.000000MHZ
      SD CARD       63 GB  SANDISK   SD SC64G REV$80 #35190404 DATE:2018/10
      SPI FLASH     16MB WINBOND $EF40_1800 #4837448895114529879
      USB           Silicon LaBS, EFM8UB3 P2D2v4  USB Bridge UB3_2.5.7A, 0005
      $36           P2D2 UB USB+SUPPORT  UUID:039BAD5834DEE811A8D742B1A51F80DA
      $A4           RV-3028 RTC
      $C4           Si5351A CLOCK GEN
                    2020/06/21 SUN 12:04:45   28.42'C   Vdd=1.832V
  • Peter JakackiPeter Jakacki Posts: 9,211
    edited 2020-06-21 - 04:51:23
    bob_g4bby wrote: »

    I saw Fred Blais's original of the "Hitchhikers Guide" to Taqoz ROM? I can take that on - thanks for the ROM listing.

    Today I wrote the shell of a "Getting Started Guide" see attached. Is there anyone else doing this as I wouldn't want to step on any toes. I'll flesh it out if you approve. If you make comments etc. just bounce a changed copy back to me. If it's not wanted, please tell me and I'm not in the least offended.

    This section of the forum is for snippets, should we communicate directly or by some other part of the forum? I'm at ' at bob.edwards50 '. (You can figure out my real address).

    Hey Bob, that looks real good. Only one problem. I'm no expert or entrepreneur, just a "bit" crazy, but I am from Brisbane :) If you're the ham, then I'm the eggs.

    I will have a good read through it, answer any questions, and offer any suggestions or corrections by way of an edited sentence or paragraph perhaps that I will email back to you each time. I also have copies of the Forth books in my Dropbox but also loaded them on SF as well.

    Don't forget that while TAQOZ is good for hobbyists and for education, that the primary reason I developed it was for commercial applications, so it's not a toy Forth, it is an industrial Forth. (just started reading your guide)

    EDIT: Maybe you should call this "The Bit Bashers Guide" :)
    In terms of editing it will be easier if the content is available on Google docs, perhaps one master doc and then break off and link sections into other docs for manageability. I've tentatively called this working copy on Google docs as "Bit Bashers Guide to the Parallax Universe - Using TAQOZ on the P2 Multicore MCU" (perhaps over two lines). Then the content can be combined and formatted up in Word (I use LibreOffice) as a nice printable document.
  • Hi,
    as I do find, that readability is a huge obstacle with forth, I would like to make 3 proposals for exampe code snippets:

    1. Please use indentations like in other languages. Please use rather short lines.
    2. Please add a comment to the first line of each word definition, what this word does, example:
    : .$ ( addr -- ) \ { Print null terminated string
        dup c@ dup while
            1 +
        drop drop
    ; \ }

    \ { and \ } can be used with editors which allow code folding. You can easily build a definition block, a library of words.
    You can make a program, which just prints the first line of each colon definition out of the source file and have some effortless dokumentation.

    3. As it is not easy to keep track, what is at the moment on which position on the stack, I want to promote a simple way of local variables. Originally I wanted to have named local variables, but this is complicated to implement and it turns out, that you don't really need them. Not my idea but from Mark Wills.
    A really helpfull compromise:
    : Locals_Library ; \ { simple locals Library ############################
    \ Partly from:
    create locals 60 cells allot \ locals stack
    variable lsp
    locals lsp !
    : >a ( n -- ) lsp @ ! ;
    : >b ( n -- ) lsp @ 4 + ! ;
    : >c ( n -- ) lsp @ 8 + ! ;
    : a> ( -- n ) lsp @ @ ;
    : b> ( -- n ) lsp @ 4 + @ ;
    : c> ( -- n ) lsp @ 8 + @ ;
    : lsp-> ( -- )  lsp @ 3 cells + lsp ! ; \ 6 +to lsp ;
    : <-lsp ( -- )  lsp @ 3 cells - lsp ! ; \ -6 +to lsp ;
    : loc_ lsp-> ; \ put 0 locals into local stack
    : loc_a lsp-> >a ; \ put 1 locals into local stack
    : loc_a_b lsp-> >b >a ; \ put 2 locals into local stack
    : loc_a_b_c lsp-> >c >b >a ; \ put 3 locals into local stack
    : endloc <-lsp ; \ free the local stack
    : testlocal loc_a_b_c ( a b c -- n ) 
         a> b> - c> * 
    endloc ;
    \ 5 2 7 testlocal

    As I do not have a P2 (yet) I have not tested this with it, but I think, there must be a way to implement this.

  • SuracSurac Posts: 49
    edited 2020-06-21 - 10:51:24
    Also my last contact with forth was on my Sinclair Spectrum, but how do I work with data that need to be accessed globally?
    In c like languages i would put it on the heap but there is no heap to my knowledge in forth
    Sure I can just put my data in a fixed location in hub, but that seems a little bit dangerous.
    Also is there a Memory map oft forth so see what areas are available in cog, lut and hub.

    I also want to know if forth uses some sort of bytecode execute engine if I start a word in a different cog. Or is the cog ram available?
  • JonnyMacJonnyMac Posts: 6,737
    edited 2020-06-21 - 22:04:02
    @Peter Jakacki Is there a mechanism in TAQOZ for reading/dumping the contents of the flash chip?

    A few minutes later...

    Is it:
    TAQOZ# SF $0000.0000 DUMP ---
    00000: FF 00 FF 00  FF 00 FF 00  FF 00 FF 00  FF 00 FF 00     '................' ok
  • @JonnyMac - Yes, you found it, kinda. Since DUMP requires a starting address and a count as well as an optional device modifier, you happened to have 0 on the stack beforehand while the $0000.0000 was simply a count of 0 where DUMP will print a minimum of 16 bytes per line. This is what happened when I tried exactly the same.
    TAQOZ# SF 0000.0000 DUMP --- 
    DEAD_BEEF: 58 15 80 FD  50 32 20 20  20 20 20 20  03 00 00 00     'X...P2      ....' ok

    Typically I'd dump some memory this way:
    TAQOZ# 0 64 SF DUMP --- 
    00000: FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF     '................'
    00010: FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF     '................'
    00020: FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF     '................'
    00030: FF FF FF FF  FF FF FF FF  FF FF FF FF  FF FF FF FF     '................'

    There's no strict syntax so it could be 0 or $0000 or 0,000,000 and SF can be anywhere before we execute DUMP, even on preceding lines. There are also other variations of DUMP.

    I've just done up a help text for DUMP.

    DUMP        ( addr bytes -- )       Dump memory or device as 16 bytes/line plus ASCII column
    DUMPW       ( addr bytes -- )       Dump 16-bit words
    DUMPL       ( addr bytes -- )       Dump 32-bit longs
    DUMPA       ( addr bytes -- )       Dump ASCII - 64 characters/line
    DUMPAW      ( addr bytes -- )       Dump ASCII Wide - 128 characters/line
    QD          ( addr -- )             Quick DUMP 32 bytes
    QW          ( addr -- )             Quick DUMP 16-bit words for 32 bytes
    DUMP may be redirected to read from memory other than hub RAM by selecting a device name.
    The device name is coded to redirect the 8/16/32-bit methods of DUMP's read routines.
    This always reverts back to hub RAM after every DUMP. 
    Standard devices:
    RAM                                 Set hub RAM as DUMP memory (defaults to RAM)
    COG                                 COG memory (might not work in ROM??)
    LUT                                 LUT memory
    SF                                  Serial Flash 
    SD                                  SD card file (4GB range within a file)
    Some extended devices:  
    RTC                                 Select RV-3028 RTC on I2C
    CG                                  Select Clock Generator on I2C 
    UB                                  Select UB3 USB micro on I2C
  • Here is an addition to the DUMP help file that shows how to create a new dump device.
    Creating a new DUMP device:
    If at least one method is coded equivalent to C@ which takes an address and returns a byte, 
    then it is possible to create a modifier for DUMP. 
    In this example we will create one for the ROM which can normally be accessed at $FC000 but
    we will make it appear as its own memory addressed from 0.
    pri ROMC@ ( addr -- byte )      $FC000 + C@ ;
    pri ROMW@ ( addr -- byte )      $FC000 + W@ ;
    pri ROM@ ( addr -- byte )      $FC000 + @ ;
    pub ROM                         AT ROMC@   AT ROMW@   AT ROM@  DUMP! ;
    { Usage:
    TAQOZ# $1000 $40 ROM DUMP --- 
    01000: 20 C0 47 A5  08 C0 07 F0  01 C4 07 51  E2 CB C3 5A     ' .G........Q...Z'
    01010: F7 C9 6F 0B  50 32 2D 4D  4F 4E 49 54  4F 52 20 56     '..o.P2-MONITOR V'
    01020: 31 2E 33 0D  0A 00 00 00  4C FA BF FD  D0 EF DF FE     '1.3.....L.......'
    01030: CC EF F0 FE  08 00 00 FF  00 04 DC FC  61 17 04 FB     '............a...' ok    
  • Christof,

    I agree about source code readability. Any code in the 'Getting Started' guide should be as you suggest - short and well presented, to set a good example to new programmers. A section can itemize best practice. Thanks for that
  • Commenting on 'snippets' and good forth practice. I remember reading Charles Moore said 'any forth word you write should not be much more than a few lines long'. Mm - not all of my words are that short. The art of forth factoring is easily underestimated I guess. Neither does my forth read like an english sentence to be more easily understood. It's a good goal to have, though. Peter's PIN related words read well and you can guess what they do.
  • I notice that the VFX forth has been free for non-commercial use for a while. They use a tool called 'docgen' to autogenerate html or Tex documents from comments laced with formatting commands. There have been various attempts at this by others. A big job, though, to retrofit to Taqoz , but food for thought.
  • One of the other reasons for short words is that it's easier to keep track of the stack. TAQOZ keeps the top 4 stack items in registers and so there is no ROLL or PICK etc, just to discourage bad practices, and also because it is more efficient too.

    There's also a sneaky trick with TAQOZ in that since code is contiguous and there are no headers in between, that a Forth word can fall-through to the next word. This is used in the MHZ KHZ HZ routines etc.

  • VonSzarvasVonSzarvas Posts: 1,987
    edited 2020-06-24 - 21:51:21
    If P2 boots into the built-in rom TAQOZ version (> ESC), is there a command to load/run the bix image of the newer TAQOZ from an SD card ? (instead of loading over serial or loading from sd card during P2 boot time).
  • TAQOZ ROM copies itself into the first 64k of hub RAM from which it runs, rather than ROM. So the only practical way to load TAQOZ from SD is to let the bootloader load it at reset or simply type RELOAD
  • You can transfer from TAQOZ to the SerialMonitor by pressing Ctl-D, and then you can load and run an SD file using the command<cr>

    1. There is no space between the "R"un command and the filename. The filename must be in uppercase
    eg RP56.BIX will load and run the program P56.BIX
    2. In P2 I am using the extensions .BIX and .BIY for P2 binaries so that files for P1 which use .BIN can co-exist on the same SD card.

    Attached are two P2 programs...
    P56.BIX will flash the P56 LED on the P2-EVAL.
    OS2.BIX will run my P2 OS using the serial P62/P63 at 115,200. Commands such as DIR, LS work. This is still experimental.

    580 x 685 - 85K
  • Thanks guys- both those tips will help.

    About bix... how to create that? Is that the binary that Pnut creates?
  • @Cluso99 chose bix and biy instead of bin because it is more likely to be unique. But it is just a raw binary so you can take the binary that PNut or other too creates and rename it to _BOOT_P2.BIX and copy it to the root directory of the FAT32 card.
  • Cluso99Cluso99 Posts: 16,263
    edited 2020-06-25 - 08:31:07
    VonSzarvas wrote: »
    Thanks guys- both those tips will help.

    About bix... how to create that? Is that the binary that Pnut creates?

    "2. In P2 I am using the extensions .BIX and .BIY for P2 binaries so that files for P1 which use .BIN can co-exist on the same SD card."

    For SD files on the P1 we used xxx.BIN for binary loaded P1 files created with PropTool (because FAT32 only supports 8+3 filenames).
    So as not to cause a conflict with P2 files I/we decided to use xxx.BIX for P2 binaries (created with pnut and probably fastspin). xxx.BIY was also used in the SD booter to allow for a second file to be loaded.
    So just rename your P2 binaries to FFFFFFFF.BIX (or FFFFFFFF.BIY) where FFFFFFFF is up to 8 characters for the filename in uppercase, and copy to your FAT32 formatted SD Card.

    The idea for two SD boot files is that you create two files, initially the same, and name them _BOOT_P2.BIX and _BOOT_P2.BIY.
    When you wish to update to a new boot file, for failsafe reasons, delete the old _BOOT_P2.BIY, then copy _BOOT_P2.BIY (this saves the current file to the old file), now delete _BOOT_P2.BIX, and then download (an OS download program to be written and not to be confused with PropTool/pnut/fastspin/loadp2) a new _BOOTP2.BIX. If the download fails the download program should ensure the file is not written or named _BOOT_P2.BIX. Therefore if the download failed, the SD boot will cause _BOOT_P2.BIY to be loaded (ie failsafe).

  • ok, got it. Will go experiment a little :)
    Thanks again.
  • Hi Peter,

    I am trying to understand the following.
    : AB 1; 
    AB .s
    ==> {1}
    : AB byte TJ 1 ;
    AB .s
    ==> {60772,1}  //Expecting {1,1}

    This is using a P2 EVAL Rev A

    Are there some special requirements surrounding bytes/bytes etc variable declaration

    For example a WORD which just declares a byte returns a value on the stack. Assumedly it's the assigned address but it's not what I expected
    : ABCD byte JC ; 
    ABCD  .s
    ==> {60773} // Expect {}
    353 x 174 - 4K
  • Peter JakackiPeter Jakacki Posts: 9,211
    edited 2020-07-06 - 03:21:20
    @VBBSim - I guess this is where we need not just a glossary, but usage examples too. But that is happening as we speak.

    What happened was quite logical in the second example since you embedded the definition of the variable in a regular Forth code definition. Normally a variable is defined outside of a code definition, but TAQOZ allows nesting of definitions. However, only constants take an initial value yet you are trying to incorrectly assign 1 to the byte variable TJ within the code definition AB.

    Look at this example where I define TJ as a constant but notice that the value for the constant had to be on the stack before we define TJ. Then I reference TJ inside of AB and print it.
    TAQOZ# 1 := TJ ---  ok
    TAQOZ# : AB  TJ . ; ---  ok
    TAQOZ# AB --- 1  ok
    If though you wanted to define a variable, you can use byte/word/long etc and a name, but what it does is similar to a constant in that it returns not the value, but the address of the value. This is what you saw in your : AB byte TJ 1 ; in that it returned the address of TJ but didn't return back to AB after that due to the way variables and constants are defined.

    Here's an example of defining a constant and a byte variable, how they work, and how they work together.
    TAQOZ# 12 := myconstant ---  ok
    TAQOZ# byte count1 ---  ok
    TAQOZ#  ---  ok
    TAQOZ# myconstant .L --- $0000_000C ok
    TAQOZ# count1 .L --- $0000_1B07 ok
    TAQOZ# myconstant count1 C! ---  ok
    TAQOZ# count1 C@ . --- 12  ok
    TAQOZ# myconstant . --- 12  ok
  • VBBSimVBBSim Posts: 24
    edited 2020-07-06 - 07:59:14
    > However, only constants take an initial value yet you are trying to incorrectly assign 1 to the byte variable TJ within the code definition AB.

    No, I was just probing why an unexpected value was being left on the stack

    >Normally a variable is defined outside of a code definition,

    This could be the key though. So I should define variables/constants outside of words definitions. Now I know that :smile:

    BTW - I sent you a PWM with another forth puzzle I would be grateful for help with

  • I found the cause of problem I sent the PM about, I wonder if you can help explain it / provide best practice for.

    What I am trying to do is return a value from inside a loop once a condition is met. I figured EXIT was the way to do this and it seems to work, but this must be breaking some internal counter because after 8 call's it causes a reset. of the system.
    TAQOZ# x
      Cold start
      Parallax P2  .:.:--TAQOZ--:.:.  V1.0--142          180530-0135
    TAQOZ# : TEST 8 1 DO I 4 = if I EXIT then LOOP ;  ok
    TAQOZ# TEST . 4 ok
    TAQOZ# TEST . 4 ok
    TAQOZ# TEST . 4 ok
    TAQOZ# TEST . 4 ok
    TAQOZ# TEST . 4 ok
    TAQOZ# TEST . 4 ok
    TAQOZ# TEST . 4 ok
    TAQOZ# TEST . 4 ok
      Parallax P2  .:.:--TAQOZ--:.:.  V1.0--142          180530-0135
  • @VBBSim - We normally use LEAVE to exit a loop early in Forth but it is for a very different reason in TAQOZ.
    Normally in Forth the loop parameters (limit and index) are stored on the return stack and once LOOP has terminated it removes these values, but obviously an EXIT would cause it to use the parameter as a return address, thereby crashing.

    TAQOZ keeps the return stack safe in this respect because it uses a third stack for loop parameters as well as loop branching. It will be forgiving enough but it normally is only 10 levels of 3 longs deep, so eventually you overflow it (actually it is 32 longs). In fact the loop stack overflows onto the return stack. I might put some wrap on the loop stack instead.

    This is the correct method (just on the command line)
    TAQOZ# 8 1 DO I 4 = IF I LEAVE THEN LOOP ---  ok
    TAQOZ# .S --- 
     DATA STACK (1)
    1   $0000_0004   4 ok

  • Trying a different implementation to early exit the loop
      Cold start
      Parallax P2  .:.:--TAQOZ--:.:.  V1.0--142          180530-0135
    TAQOZ# : TEST 7 FOR I 5 =  ?NEXT ;  ok
    TAQOZ# TEST .s
     DATA STACK (1)
    1   $FFFF_FFFF   -1 ok

    This implies the spec is
    NEXT? ( flag -- ) where flag is zero
    NEXT? ( flag flag ) where flag is non-zero

    Or is there something I don't understand about return values from DEFINED Words
Sign In or Register to comment.