Shop OBEX P1 Docs P2 Docs Learn Events
TACHYON O/S V3.0 JUNO - Furiously Fast Forth, FAT32+LAN+VGA+RS485+OBEX ROMS+FP+LMM+++ - Page 57 — Parallax Forums

TACHYON O/S V3.0 JUNO - Furiously Fast Forth, FAT32+LAN+VGA+RS485+OBEX ROMS+FP+LMM+++

15455575960109

Comments

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-10-26 23:04
    D.P wrote: »
    Great news!!! I've been running into the dreading "dictionary is full" error after loading all the networking goodies and wondering what I need/can chop out. Look forward to testing this new functionality when ready.

    As the eternal optimist was heard saying as he plummeted from the top of the tall building "so far, so good". The SDWORDS conversion (71 bytes) just works and all the information seems to be there fine.
    Typing in this definition:
    pub LOOK ( <name> -- ) IMMEDIATE --- just a handy debug to dump the relevant word sector
    GETWORD 1- C@++ 7 SHL SWAP C@ + 9 SHL FILE@ + $100 SD DUMP
    ;
    then using it to have a look at a word sector:

    LOOK CONNECT
    0480_CA00: 07 43 4F 4E 54 45 4E 54 8A C0 C1 07 43 4F 4E 4E .CONTENT....CONN
    0480_CA10: 45 43 54 8A BF A9 07 43 4F 55 4E 54 55 50 82 C2 ECT....COUNTUP..
    0480_CA20: CE 07 43 4F 47 49 4E 49 54 82 C1 A7 07 43 4F 47 ..COGINIT....COG
    0480_CA30: 52 45 47 40 82 C1 3F 07 43 52 45 41 54 45 24 82 [EMAIL="REG@..?.CREATE"]REG@..?.CREATE[/EMAIL]$.
    0480_CA40: C1 1A 07 43 4C 4B 46 52 45 51 82 C1 09 07 43 4F ...CLKFREQ....CO
    0480_CA50: 4D 50 49 4C 45 A2 C2 60 07 43 4F 47 44 55 4D 50 MPILE..`.COGDUMP
    0480_CA60: 82 C2 17 07 43 4F 47 49 4E 49 54 82 C2 97 07 43 ....COGINIT....C
    0480_CA70: 4F 4E 53 4F 4C 45 82 C2 4B 00 00 00 00 00 00 00 ONSOLE..K.......
    0480_CA80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................

    So this is the sector that would be presented as the "dictionary" whenever I type in a 7 character word that starts with a capital C. The nulls at the end of the words would then be seen as an end of dictionary if there wasn't a match and it would either try to convert it to a number or fail to find the word which is normal.
  • D.PD.P Posts: 790
    edited 2014-10-26 23:23
    Your threats to move the dictionary out of ram seem to be materializing nicely. Many people have good ideas, but very few can pull them from the "ether" and place them into reality.
  • jay-tjay-t Posts: 6
    edited 2014-10-27 13:20
    I build a little robot inspired by the Mousey from Make magazine. It uses a Propeller as the controller.
    I wrote a little Tachyon Forth program to make it avoid obstacles via it's IR sensors.
    http://diy-2010.net/community/2014/04/05/mousey-ii-building-a-new-mousebot/

    Now I want to use a GPS receiver module and get the NMEA sentences over the serial port.
    Is there already a NMEA receive module for Tachyon somewhere?

    I tried to get the serial data with some:
    31 SERIN serb !

    Where "serb" is of BYTE type. How can I build a string out of this data?
    The goal is to get the NMEA string line from the GPS module.

    How is the interactive Forth shell handled? The GPS module is soldered to the RX/TX lines of the Propeller.
    So it shares the same serial lines with the shell serial input. Can the Forth shell interactive mode be switched off?

    Sorry for asking some newbie stuff...
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-10-27 16:09
    jay-t wrote: »
    I build a little robot inspired by the Mousey from Make magazine. It uses a Propeller as the controller.
    I wrote a little Tachyon Forth program to make it avoid obstacles via it's IR sensors.
    http://diy-2010.net/community/2014/04/05/mousey-ii-building-a-new-mousebot/

    Now I want to use a GPS receiver module and get the NMEA sentences over the serial port.
    Is there already a NMEA receive module for Tachyon somewhere?

    I tried to get the serial data with some:



    Where "serb" is of BYTE type. How can I build a string out of this data?
    The goal is to get the NMEA string line from the GPS module.

    How is the interactive Forth shell handled? The GPS module is soldered to the RX/TX lines of the Propeller.
    So it shares the same serial lines with the shell serial input. Can the Forth shell interactive mode be switched off?

    Sorry for asking some newbie stuff...

    Welcome to the forum Jay!

    Obviously to build a string you need to string bytes together, one after another, you can't do it with one byte. Your input routine should have a byte array that it can write the next character into and also a write index and the termination of that inputting is when it detects a CR. It's a good idea to write a null to the end of this input as it can be treated just like a string. That bit of code is fairly trivial and normally a good exercise for a beginner so if I give you an example then it's up to you to understand it and make any changes you need to make.

    There is also no problem with using the console serial for this except of course how do you interact with it and debug it then? So I recommend tying the GPS transmit to another port through a 10K resistor (in case it's a 5V signal) and just use SERIN. Remember that the ! word means it stores a long, whereas you want to store a byte at a time so of course you need C! instead (it represents "character store").

    Now it'll be interesting to see how you go with Mousey so please keep us updated, not just with the problems, but with the wins.

    BTW: Choose "Go Advanced" in the forum buttons and change the thread title to "Mousey II" or something, and you can also even edit your first post.

    #4800 SERBAUD --- set default baud rate for GPS
    #84 BYTES gpsbuf --- NMEA sentence max is 80 visible characters
    #P0 == rxdgps --- define out GPS receive port

    pub GETGPS ( -- array ) gpsbuf BEGIN 0 OVER C! rxdgps SERIN DUP $0D <> WHILE OVER C! 1+ REPEAT DROP gpsbuf ;

    GETGPS PRINT$
    $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47 ok
  • MJBMJB Posts: 1,235
    edited 2014-10-28 07:47
    jay-t wrote: »
    Is there already a NMEA receive module for Tachyon somewhere?
    .
    here was some discussion about a NMEA parser in TACHYON

    http://forums.parallax.com/showthread.php/141061-TACHYON-a-very-fast-and-compact-Forth-SDFS-TELNET-FTP-WEB-servers-EMAIL?p=1253073&viewfull=1#post1253073
  • ChameleonChameleon Posts: 14
    edited 2014-10-30 20:31
    MJB wrote: »

    Just a couple of gotcha's here...I've been looking into NMEA interface for a bit now, but on a back burner. Note that NMEA sentences permit nulls in the sentences. Peter's first suggestion (the thread MJB referenced) doesn't handle these nulls well, placing data in the wrong memory locations.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-10-30 20:56
    Chameleon wrote: »
    Just a couple of gotcha's here...I've been looking into NMEA interface for a bit now, but on a back burner. Note that NMEA sentences permit nulls in the sentences. Peter's first suggestion (the thread MJB referenced) doesn't handle these nulls well, placing data in the wrong memory locations.

    That's not really a problem as nulls are filtered out in normal KEY input so it doesn't matter how many you get, they just don't appear in a normal ASCII stream in Tachyon. Yes it is possible to read a null if you wanted to but the only reason why is because it would be part of a file transfer protocol or something. So don't worry about those nulls, I assure you, this NMEA stuff is child's play, there are so many ways to do it, and you can have fun with all of them. The thing is not to hold back from doing anything because of overthinking, there's enough of that on this forum!
  • ChameleonChameleon Posts: 14
    edited 2014-10-30 22:38
    That's not really a problem as nulls are filtered out in normal KEY input so it doesn't matter how many you get, they just don't appear in a normal ASCII stream in Tachyon. Yes it is possible to read a null if you wanted to but the only reason why is because it would be part of a file transfer protocol or something. So don't worry about those nulls, I assure you, this NMEA stuff is child's play, there are so many ways to do it, and you can have fun with all of them. The thing is not to hold back from doing anything because of overthinking, there's enough of that on this forum!
    LONG lat,lon,alt
    LONG sum,horz,sats,fix,utc
    
    : S    NEGATE
    : N    lat ! ;
    : W    NEGATE 
    : E    lon ! ; 
    : M    alt ! ; 
    
    : ?GPS        word C@ "*" = IF word 1+ NUMBER DROP sum ! THEN    ;
    
    : &GPGGA    horz ! sats ! fix ! utc ! prompt W~ ;
    : GPGGA        DECIMAL ' ?GPS unum W! ' &GPGGA prompt W! ; IMMEDIATE
    "," delim C!
    
    \ our sample data
    GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
    
    \ report what we found
    lat @.
    lon @.
    alt @.
    sum @.
    horz @.
    sats @.
    fix @.
    utc @.
    
    
    { which looks like this:
    lat @. 4807038 ok
    lon @. 1131000 ok
    alt @. 469 ok
    sum @. 47 ok
    horz @. 9 ok
    sats @. 8 ok
    fix @. 1 ok
    utc @. 123519 ok
    }[FONT=courier new]
    [/FONT]
    

    With this strategy (first suggestion from the previous thread), &GPGGA wierds out when one of the data fields is blank/NULL, such as "$GPGGA,123519,,,,1,08,0.9,545.4,M,46.9,M,,*47"

    ...Of course, this isn't a perfect NMEA sentence but is similar to what the GPS will send when it hasn't yet calculated a location fix. "Full postfix" treatment isn't possible while $GPGGA is still interpreted as $A, like #PIN4 is interpreted as #4.

    In $GPGGA, there are two fields (altitude / height above geoid) which are measured in Meters, but the postfix above treats any data followed by "M" as altitude

    --I've been mulling around with the idea of buffering an NMEA sentence at 4800 baud, stripping the "$" from the sentence identifier, replacing ",," with ",0," and then resending the corrected stream at 19200 baud, and handling the sentence postfix. Resending at 19200 baud should be able to fit between the sentences if your GPS is sending $GPGGA, $GPRMC, $GPGSA and $GPGSV at 1Hz. Certainly not the most elegant strategy, but seems to be a small-space solution to the above mentioned issues, within the small part of my world I control.

    Peter's postfix is certainly the fastest and most code-efficient approach, but has a couple of issues off the shelf. I'm certainly looking for the fastest route from what the GPS actually sends to what he initially proposed. I'm not trying to criticize, but want to keep jay-t (a newbie like me) from pulling his hair out over a couple of critical and already identified issues. I thought I was doing good with a three-page method to accomplish what Peter came so close to accomplishing in ten lines.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-10-30 23:13
    Chameleon wrote: »

    With this strategy (first suggestion from the previous thread), &GPGGA wierds out when one of the data fields is blank/NULL, such as "$GPGGA,123519,,,,1,08,0.9,545.4,M,46.9,M,,*47"

    ...Of course, this isn't a perfect NMEA sentence but is similar to what the GPS will send when it hasn't yet calculated a location fix. "Full postfix" treatment isn't possible while $GPGGA is still interpreted as $A, like #PIN4 is interpreted as #4.

    In $GPGGA, there are two fields (altitude / height above geoid) which are measured in Meters, but the postfix above treats any data followed by "M" as altitude

    --I've been mulling around with the idea of buffering an NMEA sentence at 4800 baud, stripping the "$" from the sentence identifier, replacing ",," with ",0," and then resending the corrected stream at 19200 baud, and handling the sentence postfix. Resending at 19200 baud should be able to fit between the sentences if your GPS is sending $GPGGA, $GPRMC, $GPGSA and $GPGSV at 1Hz. Certainly not the most elegant strategy, but seems to be a small-space solution to the above mentioned issues, within the small part of my world I control.

    Peter's postfix is certainly the fastest and most code-efficient approach, but has a couple of issues off the shelf. I'm certainly looking for the fastest route from what the GPS actually sends to what he initially proposed. I'm not trying to criticize, but want to keep jay-t (a newbie like me) from pulling his hair out over a couple of critical and already identified issues. I thought I was doing good with a three-page method to accomplish what Peter came so close to accomplishing in ten lines.

    Since the KISS just uses the comma as it would a space then it's just empty space to Forth but there's an easy fix for the empty CSV value problem and as always it's only a couple of lines of code if that. This little routine should work as it remembers the last character and checks for a double comma in which case it returns with a "0" instead and forces the second comma back into the stream with a KEY!.

    BYTE lastgps
    pub GPSKEY
        rxdgps SERIN DUP "," = lastgps C@ "," = AND        --- is this the second comma?
          IF KEY! "0" THEN            --- force it for next time but return a 0 now
        DUP lastgps C!
        ;[/FONT]
    
  • fridafrida Posts: 155
    edited 2014-10-31 13:41
    pub aa ( -- ) \ test
    $CC DUP . CR
    	#8 FOR
    		DUP 1 AND .
    		#1 SHR
    		NEXT
    	\	DROP
    CR
    . CR
    ;
    pub ab ( -- ) \ test
    $CC DUP . CR
    	#8 FOR
    		DUP 1 AND .
    		#1 SHR
    		NEXT
    		DROP
    CR
    . CR
    ;
    
    
    
    .VER 
      Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
     ok
    aa CC
    00110011
    0
     ok
    ab CC
    00110011
    1
     ok
    
    

    Why is the last print giving a "0" in aa, and giving a "1" in ab?
    I would expect the stack to be empty.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-10-31 15:08
    frida wrote: »
    pub aa ( -- ) \ test
    $CC DUP . CR
        #8 FOR
            DUP 1 AND .
            #1 SHR
            NEXT
        \    DROP
    CR
    . CR
    ;
    pub ab ( -- ) \ test
    $CC DUP . CR
        #8 FOR
            DUP 1 AND .
            #1 SHR
            NEXT
            DROP
    CR
    . CR
    ;
    
    
    
    .VER 
      Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
     ok
    aa CC
    00110011
    0
     ok
    ab CC
    00110011
    1
     ok
    
    

    Why is the last print giving a "0" in aa, and giving a "1" in ab?
    I would expect the stack to be empty.

    These two definitions can be reduced to simple one liners like this:

    $CC DUP . CR 8 FOR DUP 1 AND . 2/ NEXT CR . CR

    $CC DUP . CR 8 FOR DUP 1 AND . 2/ NEXT DROP CR . CR

    The trouble is that at the end of the second test you are dropping the remainder of $CC which is now 0 off the stack and telling Forth to print a number from an "empty" stack except there is always a "top of stack". If I paste in these one liners this is what I get.
    $CC DUP . CR 8 FOR DUP 1 AND . 2/ NEXT CR . CR CC
    00110011
    0
    ok
    ok
    $CC DUP . CR 8 FOR DUP 1 AND . 2/ NEXT DROP CR . CR CC
    00110011
    1
    ok

    Now before I run it I pad the stack with two numbers 12 34 then do it again I get:
    $CC DUP . CR 8 FOR DUP 1 AND . 2/ NEXT CR . CR CC
    00110011
    0
    ok
    ok
    $CC DUP . CR 8 FOR DUP 1 AND . 2/ NEXT DROP CR . CR CC
    00110011
    34
    ok

    So you can see there is nothing mysterious it's just you are operating outside of defined parameters and I forego a lot of this "stop everything and report error code mumbo-jumo" stuff which while fine on the testing bench only disrupts a system which could otherwise continue operating normally without downtime.

    TIP: There is never a need to prefix a # to single digits 0 to 9 as these will always be decimal but as a tip you could leave your system in DECIMAL mode and only prefix the hex and binary numbers. Also 2/ is more efficient than 1 SHR.

    Also there is no difference in TF interactive mode and compile mode, it always compiles, so you can use your loops and conditionals without having to create a definition or use "special" forms of those words as is common in traditional Forths.
  • fridafrida Posts: 155
    edited 2014-11-01 09:50
    Hej Peter!

    Thanks for the 12 34, now I can test my pub's.
    When I use . on the terminal with nothing on the stack I get -1 back, I understand this. But when I use . in my pub same condition, I get 1 back, this confused me a bit.
    With 12 34 I am back on track.
    But the next little pub confuses me a bit.
    pub ad CR 0 DO I . ."  " LOOP CR ;
    
      Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
    
      Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
    Clock frequency = 80,000,000
    NAMES:  $5C89...745E for 6101 (3715 bytes added)
    CODE:   $0000...34EC for 7447 (7212 bytes added)
    CALLS:  0450 vectors free
    RAM:    10141 bytes free
    
    MODULES LOADED: 
    18C0: EXTEND.fth          Primary extensions to TACHYON kernel - 141027-1000
    BOOT: EXTEND.boot
    
    ----------------------------------------------------------------
    pub ad CR 0 DO I . ."  " LOOP CR ;  ok
      ok
    15 ad 
    0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 
     ok
    16 ad 
    0 1 2 3 4 5 6 7 8 9 A B C D E F 
     ok
    17 ad 
    0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 
     ok
    
    All in hex, 15 and 17 I understand, but 16 I do not.
    Am I too sluggish on the uptake.

    15 . 15 ok
    16 . 10 ok
    17 . 17 ok
  • MJBMJB Posts: 1,235
    edited 2014-11-01 10:42
    MJB wrote: »
    I can reproduce it.
    interrestingly
    26 . 26 ok is correct
    just trying to figure out the kernel code to see how this can happen
    got it
    16 is one of the fast constants like -1, 0,1 ... 8,16, BL for 32, FALSE = 0, OFF = 0, ON = -1, TRUE = -1
    it is intercepted and handled independently of BASE setting.
    so definitely 16 independently of the base set is #16 $10

    so better set default base to 10 and mark all hex numbers clearly with $.

    maybe it should be renamed to #16 - can still be a fast constant.
    DECIMAL  \ sets input and output base
    15 . 15 ok
    16 . 16 ok
    #16 . 16 ok
    $10 . 16 ok
    .S  \ prints the stack in both DECIMAL and HEX  always good to cross check
    
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-01 15:36
    frida wrote: »
    Hej Peter!

    Thanks for the 12 34, now I can test my pub's.
    When I use . on the terminal with nothing on the stack I get -1 back, I understand this. But when I use . in my pub same condition, I get 1 back, this confused me a bit.
    With 12 34 I am back on track.
    But the next little pub confuses me a bit.
    pub ad CR 0 DO I . ."  " LOOP CR ;
    
      Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
    
      Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
    Clock frequency = 80,000,000
    NAMES:  $5C89...745E for 6101 (3715 bytes added)
    CODE:   $0000...34EC for 7447 (7212 bytes added)
    CALLS:  0450 vectors free
    RAM:    10141 bytes free
    
    MODULES LOADED: 
    18C0: EXTEND.fth          Primary extensions to TACHYON kernel - 141027-1000
    BOOT: EXTEND.boot
    
    ----------------------------------------------------------------
    pub ad CR 0 DO I . ."  " LOOP CR ;  ok
      ok
    15 ad 
    0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 
     ok
    16 ad 
    0 1 2 3 4 5 6 7 8 9 A B C D E F 
     ok
    17 ad 
    0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 
     ok
    
    All in hex, 15 and 17 I understand, but 16 I do not.
    Am I too sluggish on the uptake.

    15 . 15 ok
    16 . 10 ok
    17 . 17 ok

    Maybe you better check all sequences up to 4294967296? :) Do you want to be a beta tester? :)

    16 is one of the predefined fast constants just like 0 1 2 etc but unlike 0 to 9 which are the same in hex or decimal there is this little problem that you have come across. But I had decided by then when I had added it to the kernel that my hex numbers were all going to be prefixed to avoid any confusion at all. So if I meant 16 in hex then I would say $16 and indeed it's a force of habit now that all hex numbers I type in are prefixed.

    Now I have an additional leaning towards leaving the system in decimal mode as I can easily control radix of input and output without affecting everything globally. The variable base is a very nice feature of Forth but it also creates problems too which is why I have ways to force recognition of numbers. So my source code will always have hex numbers prefixed with $ but I have used # to make sure my decimal numbers are decimal but maybe if I leave the default base set to decimal then these won't need to be prefixed and if you see 16 just as it is, then it really is 16 decimal.

    As for printing numbers there are plenty of support words for that including the very flexible .NUM word which accepts a control word to specify digits, base, separators, leading blanks or zeros etc.
    Actually that brings up another point, the traditional dot that's used in Forth to print a number is a bit too terse in source code form as a tiny dot gets lost whereas during debug it's quick and easy. That's why I have aliases for many of these words such as PRINT and PRINT" so that these words stand out clearly in source code rather than . and ." so perhaps .NUM needs an alias too, PRINTNUM.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-02 00:14
    The problem: A fully loaded networked system only has a couple of KBs of RAM left for an application even after reclaiming memory. Although most of the dictionary is not needed at runtime, it is needed to compile the application, so the 10K it takes up cannot be freed before an application is compiled which results in a catch-22 situation.

    The proposed solution:
    Move the dictionary out of RAM into a file in such a way that words can be found quickly and easily, preferably at normal source code compile speeds.


    The result:
    The dictionary optimization code is up and running and fully integrated into Tachyon now. It sorts and stores the dictionary into indexed sectors so that for any word there is an indexed sector where the valid word will be found along with it's attribute and code header. The 7-bit index is generated from 5 lsbs of the first character plus 2 lsbs of it's count and this 7-bit index is used to open a 512-byte sector within the 64KB WORDS.DCT file.

    This method is fast and even if it needed to read in a sector for every word it only takes around 3ms per word. However a cache is implemented which pushes the latest header into the start of the cache including any matches in the cache itself to keep it fresh. So before a sector is indexed and read in, the cache is searched for a match first, which after it starts to fill up will end up scoring more and more hits, especially since it keeps it's hits fresh. The oldest words that get pushed or partially pushed off (variable lengths) the end of the cache become invalid anyway due to a null termination area.


    This works but that still leaves the problem of adding new words to the dictionary easily. Since the normal Tachyon dictionary grows downwards in memory it becomes a simple matter to say that the start of the cache is the default start of the dictionary. So instead of searching the "cache" Tachyon will use it's normal method of searching from "names" (pointer to the dictionary) and initally it's the same thing. Now as new defintions are created they are prepended to the "dictionary" which is now a combination of the new words growing downwards in memory but still cascading into the cache. It just works, and really well at that.

    To test it out properly I loaded my datalogging application onto a full system with EASYFILE and EASYNET running. Normally even after reclaiming all the private headers (about >2KBs worth) there is no room left after this and no easy way to add more to it. Now I leave all the private headers intact, have the application fully loaded in and there is around 6K free.


    You would also think that looking up each word from SD might be slow but the combination of indexed sectors, cache, and dictionary let me load my application in without any extra delays.

    This paves the way for adding even more features to what is essentially a little 32KB microcontroller. It's now possible to include VGA buffers and many other things including the assembler etc.

    <link to SDWORDS.fth>

    Out of interest here's a MAP listing with comments which prints out a packed byte for every xN bytes, some "bytes" are comprised of 16 or 256 bytes etc. However the main area of interest is in red where even with the whole dictionary intact and networking and application we still have almost 6K free. In terms of Forth code that's a whole continent.


    .MAP
    REGISTERS x16 (Forth registers)
    0024: .. .. .. .. 02 .. .. .. .. .. 01 .. 04 05 01 ..

    VECTORS x64 (all high level defs have a 16-bit vector)
    0124: 11 11 14 11 12 0D 18 0E 14 13 14 13 15 17 14 13
    0524: 14 15 14 15 13 12 15 18 19 18 18 18 18 16 1A 0D
    KERNEL CODE x256 (high level bytecode defintiions)
    0928: 63 63 88 88 6A 64 5B 68 71 64 79 64 58 73 77 42
    CODE x256 (EXTEND.fth + UTILITES + EASYFILE + EASYNET + APPLICATION)
    18C6: 64 5C 54 5B 72 6B 6D 64 66 67 6C 84 51 6A 60 6D
    28C6: 5D 6B 80 49 23 6A 70 6E 35 4B 3E 65 43 64 5B 5E
    38C6: 75 72 72 55 68 96 73 60 78 73 6D 61 88 7C 84 7B
    48C6: 67 85 6D 74 65 80 74 7C 6E 77 58 69 81 66 41 ..
    SPARE @576B: for 5,779
    DICTIONARY x256 (new words added after converting dictionary to file)
    6DFE: 6A
    (cache and private dictionary sector sit in here = 1K total)
    BUFFERS x64 (There are four 512-byte sector buffers for four open files in EASYFILE)
    7500: .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. ..
    7900: .. .. .. .. .. .. .. .. 11 15 19 1D 21 25 29 2D

    RX BUFFER x64 (Serial receive buffer - laid down over the PASM image)
    7D00: 0E 0C 0C 0C 0E 0D 0F 0E
    HUB STACK x16
    7F60: .. 01 01 .. .. .. .. .. .. ..
  • D.PD.P Posts: 790
    edited 2014-11-02 17:38
    So do we need a "--- convert the dictionary in RAM to a sorted and indexed dictionary in SDFS in the WORDS.DCT file (128K)" or a 64KB file as stated in this post.
    Also at the bottom of SDWORDS.fth you talk about loading all the goodies except the app and running SDWORDS then initializing with !SDWORDS.
    So step one: create a 64 or 128K blank file named WORDS.DCT on the SDCard
    Two: load up tachyon the way you want your kernel upto the application you are building/working on.
    Three: Run SDWORDS from the SDWORDS.fth module
    Four: BACKUP
    Five: initialize your rebooted Tachyon sessions with !SDWORDS to use the dictionary interactively and/or compile your app
    Six: you are able to simply forget your app or reboot for development ease
    Seven: backup again after your app is ready
    Eight: now you have so much code space you are bound to have even more fun

    Is this about right?
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-02 18:00
    D.P wrote: »
    So do we need a "--- convert the dictionary in RAM to a sorted and indexed dictionary in SDFS in the WORDS.DCT file (128K)" or a 64KB file as stated in this post.
    Also at the bottom of SDWORDS.fth you talk about loading all the goodies except the app and running SDWORDS then initializing with !SDWORDS.
    So step one: create a 64 or 128K blank file named WORDS.DCT on the SDCard
    Two: load up tachyon the way you want your kernel upto the application you are building/working on.
    Three: Run SDWORDS from the SDWORDS.fth module
    Four: BACKUP
    Five: initialize your rebooted Tachyon sessions with !SDWORDS to use the dictionary interactively and/or compile your app
    Six: you are able to simply forget your app or reboot for development ease
    Seven: backup again after your app is ready
    Eight: now you have so much code space you are bound to have even more fun

    Is this about right?

    I will probably try to automate this as easily as possible but for the moment I am invoking operations manually to check it all. Right now I'm seeing if I can load up the full EXTEND.fth etc, compact the dictionary after EASYFILE, load EASYNET, and compact again. In fact I may just create the word COMPACT to do this automatically so it works out whether it's a new dictionary or an addition etc.

    So steps at present are:
    1. Load in SDWORDS.fth on a system that has EASYFILE already loaded.
    2. Ensure you have a file called WORDS.DCT with at least 64KB available (only uses 64KB)
    3. Run SDWORDS which will populate WORDS.DCT sectors with those words as they are indexed
    4. When you want to release the old dictionary in RAM then run !SDWORDS which will init the cache, reset the dictionary to the start of cache, and revector the SEARCH method.
    5. BACKUP after !SDWORDS if you want to lock all this in now. Run .STATS to see how much RAM is now available.
    6. Load app normally and this can also be forgotten normally as well. Only way to forget compacted stuff at present is to do a COLD and start again.
    7. Forth Freaking Frolicking Fun

    Newer method may just use the one word COMPACT and then manually BACKUP in case there is an ooops!.

    BTW, I still have to add an FCREATE to EASYFILE to allow new files to be created in the system although I had been trying to avoid any FAT32 housekeeping on the embedded side previously.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-02 19:35
    I will probably try to automate this as easily as possible but for the moment I am invoking operations manually to check it all. Right now I'm seeing if I can load up the full EXTEND.fth etc, compact the dictionary after EASYFILE, load EASYNET, and compact again. In fact I may just create the word COMPACT to do this automatically so it works out whether it's a new dictionary or an addition etc.
    <snip>
    Newer method may just use the one word COMPACT and then manually BACKUP in case there is an ooops!.

    Just created COMPACT and tested it all out which is all you ever need to worry about for now and you can even compact the dictionary as you go as it will detect whether it is a new or additional operation.

    To test this out I loaded a full EXTEND.fth so it included the whole kit and kaboodle, loaded EPRINT, my hardware headers, SDCARD, EASYFILE and without trying to reclaim any headers as there is no need to I then loaded SDWORDS and had 1.4K free.
    Ran COMPACT and ended up with 9.3K free.
    Added W5200 and EASYNET and ended up with 1.7K
    Ran COMPACT and finally still have 3.9K free even with all the EXTEND fluff and ALL the headers intact!


    LISTWORDS Mounted SD Card
    Media mounted as 71CC.0203 mkfs.fat WIDGET FAT32 Cluster size = 4,096 Sectors = 4,512

    0000: @gateway @sip @mac @PAD @CNT @SCK @SCL @rtc @FAT @ATR @CMS @RCD
    0001: !PCB !WIZ autosend ANDN AVAR ansi ATN? ATN@ ATN! !ADC ADC@ APIN
    0001: !PCB ACMD !SDWORDS
    0002: BYTE base BELL BYTE BITS BOLD BPIN boot
    0003: CON] CASE contimer #CONNECT CDUP cwd$ CASE COG! COG@ CALL C@++ CONSTANT
    0003: CNT@ CON] CTRA CTRB COMPARE$ #adc CTR@ CTR! COLD CLUSTER@
    0004: dataport DROP DIRA DIRB DUMP DUTY DAC! date days DAY@ DAY! dir$
    0004: DIR? DIR! dictsect dict
    0005: ELSE eNET EMIT ELSE EXIT ECHO ESC? ESC[ ENQ! ENQ@ EERD ERRORLED
    0005: EASYFILE.fth
    0006: FILE &TIMEOUT &CON FlushSkt FEAT FREE FILL FRQA FRQB FIND &TR1 &TE1
    0006: &TR2 &TE2 FILE fats file FREM fkey FGET FPUT FCREATE$ FRUN
    0007: GETFNAME GET$ GRAB
    0008: HTTP HEAD (CREATE) HERE here HOLD (.") (OPCODE) HIGH HOME (VA) (CLKSET)
    0008: HELP (FORGET) HEX: (ls)
    0009: ifconfig IDLE I2CSTART I2C! I2C@
    000A: JUMP
    000B: KOLD KEY@ KEY! KEEP +HEX +NFA +SDWORDS
    000C: LEDS LOOP LREADSKT LIST LEN$ LOOP LONG LONGFILL LIKE leds LEDS
    000D: myGW myIP mySN MDTM MYOP MASK mod2load MID$ matchstr MUTE
    000E: .IPX .IP1 .@SKTBUF .PTR .NET .SOCKETS nettimer .BYTEDEC .IPD NFA' NOTFOUND .DEC
    000E: .VER .HEX NEXT NOOP .NUM .MODULES .PIN .MAP .LAP .AUTORUN .DAY .ASMONTH
    000E: .FAT .ATR .DIR NFA>SECT
    000F: oui2 OVER OUTA OUTB
    0010: PASS PORT PASV PRIVATE] PIN! PIN@ PHSA PHSB PINLOAD? PWM% PWM! PCB$
    0011: QUIT
    0012: READYLED RNFR RNTO RETR REST 2DUP REVECTOR RS232LED RS485LED READYLED RES@ rsvd
    0012: root
    0013: SET? SKT@ sDIP sPRO sCONNECT sSENDMAC sCLOSED? sDISCON? skt$ SYST SENDFILE SIZE
    0013: STOR SET? STOP SWITCH>< SWAP SPR! SQRT SARX SDERRLED SDBSYLED sdwr sdrd
    0013: sdhc SD2@ SD4@ SDRD SDWR sect/fat SPLITDEC SDSEARCH
    0014: TRUE THEN txwr type TYPE TERMINAL TASK THEN TRUE TYPE TASKREGS time
    0014: TIMEOUT? timerstk timerjob TIMERJOB tval term
    0015: USER ukey unum UNSMUDGE udir
    0016: VCFG VSCL VCLS
    0017: WAITSEND word WKEY WORD WATCHDOG WRITEHEX
    0018: XSHR XADR
    001B: [CON [WS2812] [PWM32!] [PRIVATE [CON [C,] [W,] [EPRINT]
    001C: <CR>
    001D: =dtk
    001E: >PFA >VEC >F83
    001F: ?FTP ?CONTENT ?LED ?EASYNET ?DUP
    0020: @BASE @txwr @ @HATR @MOSI @MISO @FILE @ROOT @BOOT @FEXT
    0021: !TXWR AUTO! ALLOCATED ALLOT AGAIN ! ALIAS ALIGN ANSI? A ALARM !LEDS
    0021: !SDIO
    0022: BREAK BREAK BCOMP " BEGIN BYTES BDUMP blksz B BCD++ byte/sect
    0023: CONIO contd COMMA codes # COGID CMOVE CLOCK CONIO CTYPE COPY$ CALL$
    0023: CountDown card? CARD? cache
    0024: DEBUG DEPTH DISCONNECTED? delim DEBUG DEPTH DELTA DUMPL DUMPW DUMPA DATE@ DATE!
    0024: DATE@ DATE! dboot
    0025: ERROR ERASE ENDIF EMITS % ERSCN eeadr ENDRD ESAVE ELOAD eebuf ECOPY
    0025: EFILL eFILE
    0026: &RECV fsave flags FALSE &WNDO &WNCS &WNCK &WNDI &IOCS &SFCS &SDCS &SDDO
    0026: &SDCK &SDDI FILE# &sdto FLUSH fat32 fboot file$ FILE$ FILE@ fread fstat
    0026: FPUTB FILE> FOPEN FLOAD
    0027: ' getsz '
    0028: ( HDUMP (KEY) ( (WAITPNE) (WAITPEQ) (NULLOUT) (rnd) HYPOT (SEP) (BDW) (ESC)
    0028: (COGINIT) (RECLAIM) (MAP) hexch (cat) (DIR)
    0029: I IPRAW INTS@ IFDEF I IMMEDIATE I2C!? IDUMP INFO@
    002A: *end* * J
    002B: KEEPALIVE +CALL +LOOP + K +CHAR +DIR!
    002C: LREAD LSEND LCKEY ledon lines , LEMIT LONGS LEAVE LBIT! LOCAL
    002C: LEFT$ lpace lscnt LISTWORDS
    002D: MOUNT - modloaded MASKS MASK? MATCH mount MOUNT
    002E: names . .LONG .WORD .BYTE navar .HEAD .DECX .ADDR NULL$ NORMALIZE .ATRS
    002E: .NAME .SPRS .PINS .HHMM .TIME .DATE .TIME .DATE .CARD .LIST .FILE
    002F: /
    0030: 0 PLAIN PPPoE PORT! pass$ 0EXIT 0 Published PRINT PINS@ PLAIN PWM.START
    0030: PROCESS_TOKEN parts
    0031: 1 QUIET 1
    0032: RETRYTIME RXSIZ RNFR$ RESET 2 2DROP radix RADIX RI232 RDRTC READFAT32 RCDSZ
    0032: ROMSZ
    0033: 3 SHL16 sMODE sCMD! sINTS sSTAT sPORT sDHAR sOPEN sSEND sSENDKEEP sRECV
    0033: sCLOSING? sendtimer SCRUB SPACE SPIRD SPIWR 3DROP 3 SWAPB STRIP SERIN SI2C!
    0033: SI2C@ SDBUF SDCLK STAT@
    0034: 4 TXSIZ tasks 4 TIMES TABLE TASK? TIMER ttint TIME@ TIME! TIMERTASK
    0034: TIME@ TIME!
    0035: UPORT user$ ufind uemit UNTIL U/MOD UNPRIVATE UPPER uboot ucard
    0036: vread
    0037: W5200.fth wMODE WCOLD WHILE WORDS WRRTC
    0038: 8 8 XSAVE XLOAD XADR!
    003A: :
    003B: [COMPILE] ; { [COMPILE] [SSD] { ;
    003C: < \ < | \
    003D: = } =
    003E: > ~ >CHAR > ~ ^ >CSTR >FILE
    003F: ?EXIT ?SENDPOLL ?SEND ?HTTP ?EXIT ?DICT
    0040: @wcold @ports @NAMES @X @. @WRFLG @FNAME @CTIME @CDATE @ADATE @FTIME @FDATE
    0040: @FCLST @FSIZE @FREAD
    0041: !WIZIO !WIZIP ADCBUF APPEND.BLK APPEND
    0042: BUFSIZ BINARY BL BOUNDS BACKUP BLKSIZ blklen
    0043: C@ C! CR CLOSED CONNECTED? CREATE CREATEWORD create #S #> CR C,
    0043: COGREG CMPSTR C! C@ C~ consav CURSOR CLKSET CE1372.fth CTS232 CLUST>SECT
    0044: DO disreq DISCONNECT digits DO DOUBLE DS dwidth $! $= DTR232 DSR232
    0044: DCD232 diradr dirbuf
    0045: eW5200 errors EXTEND.fth %% ERLINE ERASE$ EEPROM E@ E! ESAVEB EE EPRINT.fth
    0045: eprint EPRINT extbuf
    0046: FTPDAT FTPMSG FORGET FIXBIN fatptr fname$ FSIZE@ fwrite FINPUT FCLOSE FOPEN# FOPEN$
    0046: FDATE! FTIME! FSTAMP
    0047: GO '' GETRND
    0048: (RETR) (STOR) (EMIT) (.NUM) HZ hexbuf hexptr hexadr hexflg (SDWR) (SDRD) (.DIR)
    0049: IF IFNDEF IF INPUTS INVERT IN IX indent
    004B: +! ++ +TIMER +CACHE
    004C: LANLED L! L@ LWRITE LANKEY LCEMIT LANCON ledcnt LANSKT LOOKUP LSTACK L>
    004C: locals LANLED LOGSZ? ls
    004D: ms MACRAW ms -1 -- m@ M@ MATCH? MY ma
    004E: NETMAN NUMBER .S ." NEGATE .INDEX .TASKS .BLOCK .STATS .BOOTS .DTFMT .FYEAR
    004E: .FDATE .FTIME .FNAME .UTIME .FILES
    004F: ON OUTCLR OUTSET OR ON OK ok // /ROUND OPCODE
    0050: PRINT" prompt PRINT$ 0< 0= PUBLIC PRINT" P@ P! PINSET PINCLR PININP
    0050: PLLDIV pwmtbl PULSEWIDTH PRINT"
    0051: 1+ QW 1- 1+ 16 QHYPOT QW QWORDS QV
    0052: REBOOT RXREAD RETRYS REBOOT REPEAT 2- 2+ RUNMOD R> 2* 2/ RETURN
    0052: RADIX> RCFAST RCSLOW RIGHT$ RTS232 RXD232 rtcbuf RW RENAME
    0053: SPIWRW socket SOCKET sDPORT sSSIZE sRXMEM sTXMEM SUBNET sCLOSE sINACTIVE? sktbuf switch
    0053: SEARCH STACKS SWITCH SPIRDX SPIWRX SPIWRB SHRINP SHROUT STREND SETMOD SPACES STRING
    0053: second SEROUT SI2C!? SETPWM SDCARD.fth sdinfo sdpins sdsize sdbusy sector scanch SDBUSY
    0053: SDPINS SDERR? SDDAT! SECTOR SD sect/clust serial
    0054: TXREAD txtime txsize TELNET TO timers TXD232
    0055: un UpdateTXWR U. us U< U/ UNLOOP U> U! U@
    0056: vwrite VC VP VOLTS@ VirtualRTC
    0057: W! WBUFSZ WITHIN W! W@ WORDS: W~ WWORDS WRESET WPWRDN wrflgs WRSECT
    0058: XCALLS X1 X2 X3 X4 XY X@ X!
    005B: [NFA'] [WS2812CL] [PLOT] [SDWR] [SDRD] [SPIO] [~
    005C: <CMOVE <# || <> << |< <=
    005D: ]~ ]~ == =>
    005E: >UPPER >DIGIT >L >R >B >N >RADIX >W ~~ >> >|
    005F: ?CTRLS ?SDTIMEOUT ?MOUNT ?WRDCT
    0060: @subnet @SOCKET @TXBASE @SKTBUF @CE @SPISCK @EE @EEWAIT @FCLSTH @DIRBUF @FWRITE
    0061: AND !SP !TXBUFS aUTORUN autorun !SP !RP ABS AND ADO APPEND$ any
    0061: ANY atr ackI2C@ AUTORUN !SD ACTIVE?
    0062: BYE blkpoll BLKSEND BUFFERS baudcnt BCA BRANCH> B>W B>L bdw BCD>DEC
    0063: C+! CON C~~ COMPACT #SOCKET CONNECT constat #ftpmin #ftpmax CWD CONTENT CONSOLE
    0063: COGINIT CLS COGDUMP CLR C+! CLKFREQ CREATE$ CON COGREG! COGREG@ C++ C--
    0063: C~~ CNT COS COGINIT CLK ctr CTR CTRMODE COUNTUP CONBAUD #EP cid
    0063: csd crc CMD clshift cat COMPACT
    0064: DISCARD DISCREQ DISCARD DECIMAL DUP DS+ DPL dst DUMPROM DEC>BCD DIR dictflg
    0065: END EASYNET.fth ECHOREQ EASYNET EXECUTE EC! EC@ EW! EW@ EVERIFY END EXTEND.boot
    0065: eSD eof
    0066: filesel &SENDOK &DISCON FTP FINDSTR FOR FRQ filesel fatname FC! FOUTPUT FRESHEN
    0067: GATEWAY GETPAGE GET GETWORD GETLINE
    0068: (LSEND) HEX (:) (WORDS) (STRIP) HEXLOAD (SLIST) (.LIST)
    0069: INTMASK INA INB I2CPINS I2CSTOP
    006B: keypoll keypoll KEY KHZ
    006C: LC! LW! LC@ LW@ LANSEND LANEMIT LAN LITERAL lastkey LOADMOD LAP LOW
    006C: L>W LSP LOCATE$ LISTKEY LED LEDREG! LOADROM LOADIMG
    006D: --- MAC -NEGATE --- MODULE: MIN MAX MOD mc@ mw@ MC@ MW@
    006D: MODPINS MHZ MARKER? -FERASE
    006E: .IP .SOCKET netflgs NFA>CFA .STACKS NOP NOT NIP ... NULLOUT .RETSTK .I2CBUS
    006E: NCO .TIMERS .DT .SW .DT .SD nfasect
    006F: OFF OUTPUTS OFF OUT org ORG ocr oemname
    0070: pri PRIVATE pub PWD pri pub 0<> PRIVATE PFA>NFA PAR PLL pwmfreq
    0070: pwmmask PWMCOG.TASK PULSEWIDTHS PCB
    0072: RXSIZE@ RXWRITE RXBASE0 RXMASK0 RESTART READBUF REG REV ROR ROL ROT RELEASE
    0072: RND RAM REVERSE RUN runtime RECLAIM rootdir RENAME$
    0073: seconds SKT SIP sLISTEN sDISCON sESTAB? sCONNECTED? SetPORT SPINNER SWITCH= SWITCH@ SP!
    0073: SPIWR16 3RD SET SHL SHR SPR SIN SQR SPIPINS SETPINS SAR seconds
    0073: SERBAUD SCL SDA SETPWMS SETPWMW sectcrc SD@ SD! scancnt scanpos sdtimer SDRDBLK
    0073: sectors SAVEROM SAVEIMG SDWORDS.fth SDWORDS
    0074: TXFREE@ TXWRITE TCP TXBASE0 TXMASK0 TACHYON 4TH TAB tid TIMEOUT
    0075: UDP UIP UNKNOWN UM* U.N
    0076: VER volname
    0077: wizpins WIZ WAITCNT W+! WAITPNE WAITPEQ W>B W>L W++ W-- W~~ WAITKEY
    0077: wdt
    0078: XOR XC@ XC! XW@
    007B: [PWM32] [SPIOD] [ESPIO]
    007C: \\\
    007E: >|RCDSZ
    007F: ?SDCARD ?BACKUP ?TELNET ?DISCONNECT ?NEGATE ?BACKUP ?SDCARD ok
    .STATS
    Propeller .:.:--TACHYON--:.:. Forth V24141103.0500
    Clock frequency = 80,000,000
    NAMES: $70E0...74CD for 1005 (-1364 bytes added)
    CODE: $0000...617C for 23951 (3091 bytes added)
    CALLS: 0000 vectors free
    RAM: 3940 bytes free

  • D.PD.P Posts: 790
    edited 2014-11-02 20:35
    Just created COMPACT and tested it all out which is all you ever need to worry about for now and you can even compact the dictionary as you go as it will detect whether it is a new or additional operation.

    To test this out I loaded a full EXTEND.fth so it included the whole kit and kaboodle, loaded EPRINT, my hardware headers, SDCARD, EASYFILE and without trying to reclaim any headers as there is no need to I then loaded SDWORDS and had 1.4K free.
    Ran COMPACT and ended up with 9.3K free.
    Added W5200 and EASYNET and ended up with 1.7K
    Ran COMPACT and finally still have 3.9K free even with all the EXTEND fluff and ALL the headers intact!


    LISTWORDS Mounted SD Card

    .STATS
    Propeller .:.:--TACHYON--:.:. Forth V24141103.0500
    Clock frequency = 80,000,000
    NAMES: $70E0...74CD for 1005 (-1364 bytes added)
    CODE: $0000...617C for 23951 (3091 bytes added)
    CALLS: 0000 vectors free
    RAM: 3940 bytes free


    Whoa, 4K free, that is a giant tachyon / forth app since the kitchen sink has been loaded already.
  • MJBMJB Posts: 1,235
    edited 2014-11-03 01:52
    .STATS
    Propeller .:.:--TACHYON--:.:. Forth V24141103.0500
    Clock frequency = 80,000,000
    NAMES: $70E0...74CD for 1005 (-1364 bytes added)
    CODE: $0000...617C for 23951 (3091 bytes added)
    CALLS: 0000 vectors free
    RAM: 3940 bytes free

    if I remember correctly there are 1k call vectors in the XCALL, YCALL, ZCALL, WCALL tables each 256 entries.
    Aren't we at the limit now ?
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-03 02:22
    MJB wrote: »
    if I remember correctly there are 1k call vectors in the XCALL, YCALL, ZCALL, WCALL tables each 256 entries.
    Aren't we at the limit now ?

    Yes, you noticed, but it's all being taken care of. One of the main reasons I used vectors in the first place was so that Spin tool compiled bytecode kernel would play nice with bytes but not words, otherwise every single word would have to be broken up into high and low bytes with offsets etc. Doable, but such a pain. Secondly, using vectors meant that we could reduce a high-level call from 3 bytes (opcode+address) to 2 bytes where one of four opcodes each picks one of 256 16-bit vectors from the table.

    So there is nothing to stop us from using 3 byte calls at a higher level on top of the kernel. I have implemented the CALL16 and getting back to modifying the BCOMPILE word so that it if it runs out of vectors for new words it will just compile a CALL16 opcode followed by the absolute address of the function it is calling. No big deal and at this level there is no real difference in code size as it is only the references to new unvectored words that take an extra byte.

    Sometimes I feel like Harper from Andromeda, yeah baby, well at least when it all comes together and it works. When it doesn't then sometimes I feel like Harper from Andromeda.......IYKWIM
  • ChameleonChameleon Posts: 14
    edited 2014-11-03 19:14
    Since the RUNMOD function only requires the start address and count it is easy enough to have a blank area or any other area for that matter such as the tables in ROM but otherwise just feel free to use the BUFFERS area or part thereof.
    Initially you could: BUFFERS $800 ERASE BUFFERS pxlbytes + pxlbytes $FF FILL

    To blank all the LEDs: BUFFERS pxlbytes RUNMOD
    To light em up: BUFFERS pxlbytes + pxlbytes RUNMOD

    In fact rather than calling RUNMOD directly you should really have this:
    pub SHOW ( address -- ) pxlbytes RUNMOD #50 us ;

    So BLANK becomes pub BLANK BUFFERS SHOW ;

    Works fabulously! In efforts to be constantly wary to save vectors and bytes, I found an issue I don't understand...Can you see my error?
    pub BUF ( -- ) wsdata wsbytes + ; 
    
    pub BLANKBUFF ( -- ) BUF wsbytes $00 FILL ;
    
    pub BLANK ( -- ) BLANKBUFF #10 us BUF SHOW ;
    
    works perfectly, while
    pub BLANK ( -- ) 
        pub BLANKBUFF ( -- ) BUF wsbytes $00 FILL ;
        #10 us BUF SHOW ;
    
    does not.
    You can also define storage areas as constants with ORG such as:
    BUFFERS ORG
    pxlbytes DS pxldata
    1 DS tempgrn
    and so on to keep it all together without worrying about slamming into code.
    Your mini tutorial was helpful, but one added question: Is there a way to keep track of what part of the buffers has been claimed? Since my data is started at BUFFERS, I need to increment the "buffer" area to keep from wiping out the data I want preserved...OR is there a better way to ORG so that I don't run into the same issue where data is being stored in code space?
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-03 20:55
    Chameleon wrote: »
    Works fabulously! In efforts to be constantly wary to save vectors and bytes, I found an issue I don't understand...Can you see my error?
    pub BUF ( -- ) wsdata wsbytes + ; 
    
    pub BLANKBUFF ( -- ) BUF wsbytes $00 FILL ;
    
    pub BLANK ( -- ) BLANKBUFF #10 us BUF SHOW ;
    
    works perfectly, while
    pub BLANK ( -- ) 
        pub BLANKBUFF ( -- ) BUF wsbytes $00 FILL ;
        #10 us BUF SHOW ;
    
    does not.


    Your mini tutorial was helpful, but one added question: Is there a way to keep track of what part of the buffers has been claimed? Since my data is started at BUFFERS, I need to increment the "buffer" area to keep from wiping out the data I want preserved...OR is there a better way to ORG so that I don't run into the same issue where data is being stored in code space?

    It looks like you are over-thinking things a little as ORG and DS etc look after that stuff for you. The thing is that you can use this in one part of the code and then use it later and it still points to the next available area. But if you really want to know where it is just look in the org variable (lower-case). But you don't need to keep setting ORG, normally just once is fine.

    The 10 us is redundant here, it was used at the end of a transmission to ensure a minimum gap period, that's all.

    Now, it normally helps if I can see all your code rather than snippets but I'm wondering what you are trying to do by nesting a definition within a definition? Perhaps you copy and pasted without removing the ; after the FILL ?
    pub BLANK ( -- )
        [COLOR=#ff0000]pub BLANKBUFF ( -- ) BUF wsbytes $00 FILL ;[/COLOR]
        #10 us BUF SHOW ;
    
  • ChameleonChameleon Posts: 14
    edited 2014-11-04 03:04
    It looks like you are over-thinking things a little as ORG and DS etc look after that stuff for you. The thing is that you can use this in one part of the code and then use it later and it still points to the next available area. But if you really want to know where it is just look in the org variable (lower-case). But you don't need to keep setting ORG, normally just once is fine.

    The 10 us is redundant here, it was used at the end of a transmission to ensure a minimum gap period, that's all.

    Now, it normally helps if I can see all your code rather than snippets but I'm wondering what you are trying to do by nesting a definition within a definition? Perhaps you copy and pasted without removing the ; after the FILL ?
    pub BLANK ( -- )
        [COLOR=#ff0000]pub BLANKBUFF ( -- ) BUF wsbytes $00 FILL ;[/COLOR]
        #10 us BUF SHOW ;
    

    Doesn't nesting like this save memory? Obviously not a lot in this case, but I'm trying to be as efficient as possible from the start so as I learn and as my projects become more complex, I've developed good habits..Nesting is, of course only after I've tweaked and verified, when I'm cleaning up and commenting my code for later interactions.

    After I implemented your ORG recommendation ...
    BUFFERS ORG
    1         DS    wsgrn     --- 
    1         DS    wsred     ---
    1         DS    wsblu     ---
    wsbytes   DS    wsdata    ---
    
    
    If I tried
    BUFFERS $800 ERASE BUFFERS pxlbytes + pxlbytes $FF FILL
    
    it blanked out the data I was trying to preserve...I have packaged the whole thing into a module and have BACKUP'd the Prop. BUFFERS . returns the address of my ORG'd data ( wsgrn . = 7500, BUFFERS . = 7500)

    ...Is BUFFERS ORG the wrong way to setup the variables?

    I'm also not seeing the advantage of ERASE then FILL. Is there one I don't see other than cleaning up pseudo-random data for possible later use?
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-04 03:40
    Chameleon wrote: »
    Doesn't nesting like this save memory? Obviously not a lot in this case, but I'm trying to be as efficient as possible from the start so as I learn and as my projects become more complex, I've developed good habits..Nesting is, of course only after I've tweaked and verified, when I'm cleaning up and commenting my code for later interactions.

    After I implemented your ORG recommendation ...
    BUFFERS ORG
    1         DS    wsgrn     --- 
    1         DS    wsred     ---
    1         DS    wsblu     ---
    wsbytes   DS    wsdata    ---
    
    
    If I tried
    BUFFERS $800 ERASE BUFFERS pxlbytes + pxlbytes $FF FILL
    
    it blanked out the data I was trying to preserve...I have packaged the whole thing into a module and have BACKUP'd the Prop. BUFFERS . returns the address of my ORG'd data ( wsgrn . = 7500, BUFFERS . = 7500)

    ...Is BUFFERS ORG the wrong way to setup the variables?

    I'm also not seeing the advantage of ERASE then FILL. Is there one I don't see other than cleaning up pseudo-random data for possible later use?

    The semicolon just after the fill compiles as an EXIT so the code that you have after that will not execute plus this is something you never do in any Forth although Tachyon does allow multiple entry points.
    [COLOR=#000000][FONT=Arial]pub BLANK ( -- )     [/FONT][/COLOR]
    [COLOR=#ff0000][FONT=Arial]  pub BLANKBUFF ( -- ) [/FONT][/COLOR]
    [COLOR=#ff0000][FONT=Arial]      BUF wsbytes $00 FILL ;[/FONT][/COLOR][COLOR=#000000][FONT=Arial] <---------code will exit here because of the semicolon (it's an EXIT)     [/FONT][/COLOR]
    [COLOR=#000000][FONT=Arial]     #10 us BUF SHOW ; <------- the code here never gets executed[/FONT][/COLOR]
    
    
    Also remember that $00 compiles as a 2 byte opcode [BYTE] [00] whereas 0 is an opcode and compiles as a fast single byte opcode [0]. In this case it is neither here nor there but be aware of it if.

    Once again I can't help you too much when I can only look through a keyhole, just post all the code. For instance you have wsbytes specifying the number of bytes for wsdata but I don't know what value that is. Then you have pxlbytes which is another value I don't know. However BUFFERS $800 ERASE is going to wipe everything for sure, is that what you want?

    Try putting things like BUFFERS $800 ERASE on one line by itself and give it a comment so that you at least will know what you are trying to do, then put that BUFFERS pxlbytes + pxlbytes $FF FILL on it's own line with a comment. Be methodical and try talking to yourself as if you are explaining what you are doing to someone who is trying to follow along. As you verbalize your thoughts you will do as many of us have done and go "you idiot" or "of course, why didn't I see that before" etc.

    BTW, ERASE is the same thing as 0 FILL.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-06 21:44
    This particular thread has grown so much with over 140,000 view and 1700 posts and there is so much buried in here that I always wanted to save this thread locally so I could search it easily. So I installed the re-pagination add-on for FF which lets me right click the "next" or "page 2" in the thread and re-paginate it "load all". After a minute or so all the posts are visible so I saved this as a html with sub-folder but also pasted the text of it into this handy zip file:

    Tachyon forum html.zip
    tachyon forum.txt.zip
  • jay-tjay-t Posts: 6
    edited 2014-11-08 09:37
    I wrote a little program for my mouse bot.
    The bot should search light with it's phototransistors. I did a run with motor driver battery unplugged:

    Propeller .:.:--TACHYON--:.:. Forth V24140928.1630
    Clock frequency = 80,000,000
    NAMES: $5B01...745E for 6493 (102 bytes added)
    CODE: $0000...3DBF for 9314 (577 bytes added)
    CALLS: 0420 vectors free
    RAM: 7490 bytes free


    jimmy light measure
    turn right
    driveahead
    driveahead
    driveahead
    ...

    It just repeats the "driveahead" message over and over again. Without jumping back to the BEGIN statement.
    Here is the program:
    TACHYON
    
    : jimmybot.FTH            ." Jimmy the mouse bot main program " ;
    
    [~
    {
    The main control program for Jimmy the mouse bot.
    }
    
    	DECIMAL 
    	LONG irleft
    	LONG irright
    	LONG irfront
    	LONG turned
    	
    	LONG lightsensleft
    	LONG lightsensright
    	
    : jimmy
    	initpwm
    	
    	\ test IR LEDs
    	tirfront
    	tirleft
    	tirright
    	
    	\ test motors
    	 driveahead
    	 #500 ms
    	 drivestop
    	 #500 ms
    	
    	\ beeperok
    	#5000 ms
    	
    	BEGIN
    		sensorfront irfront !		\ store sensor data
    		#5 ms
    		sensorleft irleft !
    		#5 ms
    		sensorright irright !
    		0 turned !
    		
    		irfront @
    		-1 = IF
    			\ front free
    			
    			." light measure " CR
    			
    			\ measure light on left and right side
    			lightleft lightsensleft !
    			lightright lightsensright !
    			
    			lightsensleft @ lightsensright @
    			< IF 
    				\ left side is brighter, turn left
    				
    				irleft @
    				-1 = IF
    				
    					." turn left " CR
    				
    					drivestop
    					#1000 ms
    					
    					turnleft
    					#1000 ms
    					drivestop
    				ELSE 
    					\ left side blocked, go backwards and right
    					
    					." turn backwards right " CR
    					
    					drivestop
    					#1000 ms
    	
    					drivebackw
    					#500 ms
    	
    					turnright
    					#1000 ms
    					drivestop
    				THEN 
    			ELSE 
    				\ right side is brighter, turn right
    				
    				irright @
    				-1 = IF
    				
    					." turn right " CR
    				
    					drivestop
    					#1000 ms
    					
    					turnright
    					#1000 ms
    					drivestop
    				ELSE 
    					\ left side blocked, go backwards and left
    					
    					." turn backwards left " CR
    					
    					drivestop
    					#1000 ms
    	
    					drivebackw
    					#500 ms
    	
    					turnleft
    					#1000 ms
    					drivestop
    				THEN 
    			THEN 
    				
    			sensorfront irfront !		\ store sensor data
    			
    			irfront @
    			-1 = IF
    				\ front free, drive ahead
    				
    				." driveahead " CR
    				
    				driveahead
    				#500 ms
    				drivestop
    			THEN 
    		ELSE 
    			\ front blocked somewhere
    			
    			irfront @ irleft @ OR
    			-1 = IF
    				irleft @
    				-1 = IF
    				
    					." backwards and left " CR
    				
    					drivestop
    					#1000 ms
    					
    					drivebackw
    					#500 ms
    					
    					turnleft
    					#1000 ms
    					drivestop
    					
    					-1 turned !
    				THEN 
    			THEN 
    			
    			irfront @ irright @ OR
    			-1 = IF
    				irright @
    				-1 = IF
    				
    					." backwards right " CR
    				
    					drivestop
    					#1000 ms
    	
    					drivebackw
    					#500 ms
    	
    					turnright
    					#1000 ms
    					drivestop
    					
    					-1 turned !
    				THEN 
    			THEN
    			
    			turned @
    			0 = IF
    				\ no way to turn, drive backwards
    				
    				." backwards " CR
    				
    				drivestop
    				#1000 ms
    				
    				drivebackw
    				#500 ms
    				drivestop
    			THEN 
    		THEN 
    	AGAIN 
    	;
    	
    ]~
    END
    

    It should print out the "light measure" message after "driveahead" by jumping back to "BEGIN", but it never does this.
    Maybe I messed up something with my IF/ELSE/THEN stuff?

    I just have no idea what is going on there.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2014-11-09 18:39
    Many years ago I designed and built a wave player using a 20x4 LCD and PS/2 keypad that played files from a FAT16 SD card. The whole thing was written in Spin and PASM of course, as you do, well, at least back then.

    Then I developed Tachyon and one of the early snippets of code I wrote was for a bufferless wave player that read continuously from the SD card even though I hadn't written any filesystem stuff yet. Over the the weekend I just played with playing back files in a few different ways and I found that I could just manage 44,100Hz sample rate playback totally in Tachyon. Anyway I've tidied it up a bit and actually put in a small RUNMOD so I can push it harder and which grabs one sample, scales it, add bias, and feeds it out. So except for those dozen lines of PASM in the kernel, the rest is totally Forth.

    This code here will play a file in the background, and you can PAUSE or CONT or FADE or vary pitch interactively. Type PLAY <thisfile> to start play or add a small macro like TRACK so you can say 123 TRACK and it will play TRACK123.WAV. The full kit may come later but this is fun to play with. BTW, I use Audacity and convert MP3 stereo to mono, normalise, and export as a MS WAVE file.

    Code size = 735 bytes
    Names size = 335 bytes
    [FONT=courier new]TACHYON [~
    DECIMAL
    
    FORGET WAVEPLAY.fth
    pub WAVEPLAY.fth        ." Tachyon Wave file player - 141107-1500 " ;
    
    IFNDEF EASYFILE.fth
            CR ." !!!  This module requires EASYFILE.fth !!!          "
    !!!        
    }
    
    --- For cards larger than 4GB a sector address needs to be used instead of FILE@
    IFNDEF FSECT@
    pub FSECT@ ( -- sect )    file @FILE @ ;
    }
    
    --- define 2 contiguous audio buffers which are fed from the SDFS
    --- Use file 2 & 3
    2 FILE SDBUF        == ABUF
    ABUF            == BUF1
    BUF1 BLKSIZ +        == BUF2
    ABUF            == WBUF            --- Let player use it's own buffer constant which can be changed at runtime
    0 FILE
    
    --- Define our I/O pins which are fed to RC filters for audio, I use 220R + 100nF
    #P21            == LEFT
    #P20            == RIGHT
    
    --- default sampling rate
    44100            == RATE
    
    --- array to hold RIFF information from WAVE file
    128            BYTES riff
    
    --- RIFF WAVE HEADER OFFSETS
    riff $16 +        == @channels
    riff $18 +        == @samplerate
    riff $24 +        == @chunks        --- LIST INFO INAM IART chunks etc
    
    
    pub .TAGS
         CR ." Sample rate : " @samplerate @ $400A .NUM
         CR ." Channels    : " @channels W@ 1 = IF ." Mono " ELSE ." Stereo" THEN
         CR ." Title       : " riff $38 + PRINT$
        ;
        
    LONG    playfile,playsize
    
    LONG pitch,pitch100,track
    WORD pidx                            --- player updates it's buffer read index in this word
    BYTE pflg                            --- next word is foreground flag
    BYTE fade,pause
    
    
    pub SILENT        20 fade C! ;
    pub UNMUTE        0 fade C! ;
    
    pub PITCH ( +/-% -- )    NEGATE pitch100 @ SWAP % pitch100 @ + #1100 MAX pitch ! ;
    pub PAUSE        pause C~~ SILENT ;
    pub CONT        pause C~ UNMUTE ;
    
    
    --- PLAYER runs continuously in it's own cog feeding audio samples to the DAC
    pub PLAYER ( runs at 44100Hz using small RUNMOD )
         [WAVE]                            --- load PLAYER helped 
         RIGHT DUP PINCLR A BPIN
         LEFT DUP PINCLR A APIN %00111 CTRMODE            --- setup audio output
         fade 0 COGREG!                        --- pass pointer to fade control
         pitch 1 COGREG!                        --- allow pitch to vary
         pidx 2 COGREG!                        --- let runmod update it's read index
         CLKFREQ RATE / DUP pitch ! DUP pitch100 ! DELTA        --- setup WAITCNT sample rate
        BEGIN 
           WBUF $400 ADO RUNMOD 2 +LOOP                --- continously output 512x2 sample buffer
        AGAIN
    ;
    
    
    pub FeedBuffer ( buf -- )
         playfile @ SWAP SDRD DROP 
         playfile ++ playsize --
         ;
    
    --- foreground task - feeds wave buffer from file as needed
    pub PLAYPOLL
         playsize @ pause C@ NOT AND
         IF 
            pidx W@ BUF2 >                        --- if buffer read count < BLKSIZ then 1st buffer can be updated 
           IF pflg C@ 1 <> IF BUF1 FeedBuffer 1 pflg C! THEN
           ELSE pflg C@ 2 <> IF BUF2 FeedBuffer 2 pflg C! THEN
           THEN
         ELSE
           20 fade C!
        THEN
        ;
    
    
    pub PLAY ( <name> -- )  IMMEDIATE
        ?MOUNT
         0 FILE
            [COMPILE] FOPEN
     pub PLAYFILE                                --- play the currently open file
        PAUSE
        FSECT@ 0EXIT
        FSECT@ playfile ! FSIZE@ 9 SHR playsize !
        ' PLAYER 6 RUN                           --- make sure PLAYER is running
          BEGIN pidx W@ BUF2 = UNTIL             --- don't load anything until player is just using 2nd buffer
        BUF1 FeedBuffer 1 pflg C!                --- and load 1st buffer now
        ABUF riff #128 CMOVE                     --- save header
        $8000 ABUF W! ABUF ABUF 2+ $FE CMOVE     --- insert silence over WAV header in first 128 bytes
        ' PLAYPOLL keypoll W!                    --- polling will fill audio buffers as needed
        .TAGS                                    --- display some metatag info
          BEGIN pidx W@ BUF1 #128 + = UNTIL      --- let it play from this position to skip header
        CONT                                     --- continue playing
        PLAYPOLL                                 --- replenish buffers
        ;
    
    
    --- application specific
    
    pub TRACK ( nnn -- )
         DUP track !
         <# # # # #> " TRACK000.WAV" SWAP OVER 4 + 3 CMOVE FOPEN$ IF PLAYFILE THEN
         ;
    
    pub EVAC    911 TRACK ;
    
    ]~
    END
    
    [/FONT]
    
  • D.PD.P Posts: 790
    edited 2014-11-09 23:26
    Many years ago I designed and built a wave player using a 20x4 LCD and PS/2 keypad that played files from a FAT16 SD card. The whole thing was written in Spin and PASM of course, as you do, well, at least back then.

    Then I developed Tachyon and one of the early snippets of code I wrote was for a bufferless wave player that read continuously from the SD card even though I hadn't written any filesystem stuff yet. Over the the weekend I just played with playing back files in a few different ways and I found that I could just manage 44,100Hz sample rate playback totally in Tachyon. Anyway I've tidied it up a bit and actually put in a small RUNMOD so I can push it harder and which grabs one sample, scales it, add bias, and feeds it out. So except for those dozen lines of PASM in the kernel, the rest is totally Forth.

    This code here will play a file in the background, and you can PAUSE or CONT or FADE or vary pitch interactively. Type PLAY <thisfile> to start play or add a small macro like TRACK so you can say 123 TRACK and it will play TRACK123.WAV. The full kit may come later but this is fun to play with. BTW, I use Audacity and convert MP3 stereo to mono, normalise, and export as a MS WAVE file.

    Code size = 735 bytes
    Names size = 335 bytes
    [FONT=courier new]TACHYON [~
    DECIMAL
    
    FORGET WAVEPLAY.fth
    pub WAVEPLAY.fth        ." Tachyon Wave file player - 141107-1500 " ;
    
    IFNDEF EASYFILE.fth
            CR ." !!!  This module requires EASYFILE.fth !!!          "
    !!!        
    }
    
    --- For cards larger than 4GB a sector address needs to be used instead of FILE@
    IFNDEF FSECT@
    pub FSECT@ ( -- sect )    file @FILE @ ;
    }
    
    --- define 2 contiguous audio buffers which are fed from the SDFS
    --- Use file 2 & 3
    2 FILE SDBUF        == ABUF
    ABUF            == BUF1
    BUF1 BLKSIZ +        == BUF2
    ABUF            == WBUF            --- Let player use it's own buffer constant which can be changed at runtime
    0 FILE
    
    --- Define our I/O pins which are fed to RC filters for audio, I use 220R + 100nF
    #P21            == LEFT
    #P20            == RIGHT
    
    --- default sampling rate
    44100            == RATE
    
    --- array to hold RIFF information from WAVE file
    128            BYTES riff
    
    --- RIFF WAVE HEADER OFFSETS
    riff $16 +        == @channels
    riff $18 +        == @samplerate
    riff $24 +        == @chunks        --- LIST INFO INAM IART chunks etc
    
    
    pub .TAGS
         CR ." Sample rate : " @samplerate @ $400A .NUM
         CR ." Channels    : " @channels W@ 1 = IF ." Mono " ELSE ." Stereo" THEN
         CR ." Title       : " riff $38 + PRINT$
        ;
        
    LONG    playfile,playsize
    
    LONG pitch,pitch100,track
    WORD pidx                            --- player updates it's buffer read index in this word
    BYTE pflg                            --- next word is foreground flag
    BYTE fade,pause
    
    
    pub SILENT        20 fade C! ;
    pub UNMUTE        0 fade C! ;
    
    pub PITCH ( +/-% -- )    NEGATE pitch100 @ SWAP % pitch100 @ + #1100 MAX pitch ! ;
    pub PAUSE        pause C~~ SILENT ;
    pub CONT        pause C~ UNMUTE ;
    
    
    --- PLAYER runs continuously in it's own cog feeding audio samples to the DAC
    pub PLAYER ( runs at 44100Hz using small RUNMOD )
         [WAVE]                            --- load PLAYER helped 
         RIGHT DUP PINCLR A BPIN
         LEFT DUP PINCLR A APIN %00111 CTRMODE            --- setup audio output
         fade 0 COGREG!                        --- pass pointer to fade control
         pitch 1 COGREG!                        --- allow pitch to vary
         pidx 2 COGREG!                        --- let runmod update it's read index
         CLKFREQ RATE / DUP pitch ! DUP pitch100 ! DELTA        --- setup WAITCNT sample rate
        BEGIN 
           WBUF $400 ADO RUNMOD 2 +LOOP                --- continously output 512x2 sample buffer
        AGAIN
    ;
    
    
    pub FeedBuffer ( buf -- )
         playfile @ SWAP SDRD DROP 
         playfile ++ playsize --
         ;
    
    --- foreground task - feeds wave buffer from file as needed
    pub PLAYPOLL
         playsize @ pause C@ NOT AND
         IF 
            pidx W@ BUF2 >                        --- if buffer read count < BLKSIZ then 1st buffer can be updated 
           IF pflg C@ 1 <> IF BUF1 FeedBuffer 1 pflg C! THEN
           ELSE pflg C@ 2 <> IF BUF2 FeedBuffer 2 pflg C! THEN
           THEN
         ELSE
           20 fade C!
        THEN
        ;
    
    
    pub PLAY ( <name> -- )  IMMEDIATE
        ?MOUNT
         0 FILE
            [COMPILE] FOPEN
     pub PLAYFILE                                --- play the currently open file
        PAUSE
        FSECT@ 0EXIT
        FSECT@ playfile ! FSIZE@ 9 SHR playsize !
        ' PLAYER 6 RUN                           --- make sure PLAYER is running
          BEGIN pidx W@ BUF2 = UNTIL             --- don't load anything until player is just using 2nd buffer
        BUF1 FeedBuffer 1 pflg C!                --- and load 1st buffer now
        ABUF riff #128 CMOVE                     --- save header
        $8000 ABUF W! ABUF ABUF 2+ $FE CMOVE     --- insert silence over WAV header in first 128 bytes
        ' PLAYPOLL keypoll W!                    --- polling will fill audio buffers as needed
        .TAGS                                    --- display some metatag info
          BEGIN pidx W@ BUF1 #128 + = UNTIL      --- let it play from this position to skip header
        CONT                                     --- continue playing
        PLAYPOLL                                 --- replenish buffers
        ;
    
    
    --- application specific
    
    pub TRACK ( nnn -- )
         DUP track !
         <# # # # #> " TRACK000.WAV" SWAP OVER 4 + 3 CMOVE FOPEN$ IF PLAYFILE THEN
         ;
    
    pub EVAC    911 TRACK ;
    
    ]~
    END
    
    [/FONT]
    


    Just un-possible, I like this form of the word, now to get something warm to drink and unpack these words. Heater's gonna go crazy, I can hear it now (WHAT ABOUT FFT)
  • fridafrida Posts: 155
    edited 2014-11-10 08:03
    A 1 step into 1-wire.
    I was looking after a 1-wire object, but couldn't find one.
    I saw something in the dropbox, but it was a mix of spin and forth.
    So I started my own development of a 1-wire in forth.
    Now I have it running and spitting 3 temperaturer back on me.
    I have had a lot of fun, and it is almost like assembler.
    Have a look at the object.
    It seeks the 1-wire and returns the id numbers of the chips with crc8 check.
    Then it send the temperature back on the console.
Sign In or Register to comment.