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

14142444647109

Comments

  • artkennedyartkennedy Posts: 164
    edited 2014-03-17 - 18:37:06
    Thanks for the props. Yes, use the CMID$ etc in EXTEND, my pleasure. And thanks for the other tips - will use.
  • D.PD.P Posts: 790
    edited 2014-03-17 - 21:11:49
    artkennedy wrote: »
    Thanks for the props. Yes, use the CMID$ etc in EXTEND, my pleasure. And thanks for the other tips - will use.

    Hey Art thanks for all the comments, makes it a pleasure to follow your code.
  • artkennedyartkennedy Posts: 164
    edited 2014-03-17 - 22:56:37
    D.P wrote: »
    Hey Art thanks for all the comments, makes it a pleasure to follow your code.

    Smiling, gotta do that to understand it myself. I've written a lot of code for the hp48 and lost the ability to use and understand it because I did it on the calculator and did not document - had to stop that.

    Watch my stuff if you will and let me know if where it can be improved. It has been about 30 years since the last time I wrote forth code and then only one big personal project and Tachyon is way different - lot to learn.
  • artkennedyartkennedy Posts: 164
    edited 2014-03-17 - 22:58:32
    One thing I noticed:
    "A" . 41 ok
    " " . 3489 ok
    
    Is that intentional?
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-17 - 23:11:57
    artkennedy wrote: »
    One thing I noticed:
    "A" . 41 ok
    " " . 3489 ok
    
    Is that intentional?

    Yep, absolutely...... :)

    As you already know all "words" in Forth are separated by one or more spaces and "A" is neither a word nor a normal number but is processed by the number routine a little further to see if it qualifies as a character literal etc. In this it qualifies as a character literal.

    Now " is a word in Forth and it is used to build a string as you already know " this is a string" . So I guess you know what " " does then!? :)
    The blank character is also a VM instruction called BL and I also use it as a decimal 32 in loops etc. I suppose I could put in extra checks to see if it is an empty string but where do you stop?
  • artkennedyartkennedy Posts: 164
    edited 2014-03-18 - 11:17:06
    Good stuff.
  • artkennedyartkennedy Posts: 164
    edited 2014-03-18 - 12:08:35
    I want to use GETWORD. I have looked it up in the kernel. Ooof! Too deep for me.

    I'm putting on my waders. Somebody point me to the 'stream' ;-)
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-19 - 21:06:18
    I use 10Mhz crystals in practically all my designs but all the Parallax boards are 5MHz and this means that when I am compiling Tachyon source for myself I need to change this figure otherwise I like to leave it set for standard 5MHz for everyone else. But it would be nice to have the code check to see which crystal it is running on and so I got around to integrating PhiPi's CLKSET object into Tachyon as a RUNMOD called when Tachyon is initializing. I've tested this on a couple of boards and it works well so now I can leave the settings as if it were 10MHz but you don't have to change this if you compile for 5MHz.

    My sig also now includes a direct link to the latest binary which is the precompiled kernel plus EXTEND.fth. The default baudrate is 230400 baud and btw I use 12ms line delay.
  • D.PD.P Posts: 790
    edited 2014-03-19 - 21:58:51
    I use 10Mhz crystals in practically all my designs but all the Parallax boards are 5MHz and this means that when I am compiling Tachyon source for myself I need to change this figure otherwise I like to leave it set for standard 5MHz for everyone else. But it would be nice to have the code check to see which crystal it is running on and so I got around to integrating PhiPi's CLKSET object into Tachyon as a RUNMOD called when Tachyon is initializing. I've tested this on a couple of boards and it works well so now I can leave the settings as if it were 10MHz but you don't have to change this if you compile for 5MHz.

    My sig also now includes a direct link to the latest binary which is the precompiled kernel plus EXTEND.fth. The default baudrate is 230400 baud and btw I use 12ms line delay.

    Neat, is EXTEND.fth built with SMALL or not in the pre-comipled version? One less layer of complexity removed, thanks.

    That was lazy of me since .TASKS is there the binary in not SMALL.


    UPDATE: The binary works great on the PBOE.
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-19 - 22:22:24
    D.P wrote: »
    Neat, is EXTEND.fth built with SMALL or not in the pre-comipled version? One less layer of complexity removed, thanks.

    dp

    I'm guessing the ones that will be using the binary the most are the ones who just want to try it out with the minimum of fuss so it's the normal EXTEND with over 11KB free. Once you have loaded in EXTEND yourself on a small build it shouldn't worry again in that if you ever have to reload another module it is normally set to forget itself if it is already loaded.

    If you want to make a binary yourself just bear in mind that I changed the name to DUMPROM and also if you have an SD card in your system you can use SAVEROM to save to a preset file called ROM.BIN.
  • artkennedyartkennedy Posts: 164
    edited 2014-03-19 - 23:41:08
    Also the loop in STR>NUM looks like it's begging for the use of a <CMOVE which moves a block of memory just like CMOVE does but it calculates the end addresses and works backwards so it's safe to use for moving a block up a few bytes.
    BTW, the NUMBER routine in the kernel has been fixed so it just accepts any string now without expecting a count byte.

    Sure is nice to have NUMBER upgraded and to use <CMOVE.
    Here is the new STR>NUM:
    : STR>NUM             \ ( str chb -- num ) shift string 2 cells right, append len and base flag character
       SWAP DUP LEN$      \ ( str chb -- chb str len )
       1+                 \ ( chb str len -- chb str len1+ ) expand loop counter to include <null> at end of string
       OVER DUP 1+        \ ( chb str len1+ -- chb str len1+ str str1+ )
       ROT <CMOVE         \ ( chb str len1+ str str1+ -- chb str )
       SWAP OVER          \ ( chb str -- str chb str )
       C!                 \ ( str chb str -- str )
       NUMBER             \ ( str -- num flag ) flag = 0 if bad else ct of num chars, num = number to base of chb
    ;
    
  • artkennedyartkennedy Posts: 164
    edited 2014-03-20 - 00:15:39

    This has been upgraded to:
    30 BYTES dmmbuf
    which also initializes the array to zeros. There are also the corresponding WORDS and LONGS you can use to create an array

    I need an array for storing 16 sensor readings. Two bytes are needed for each.

    I find that his works fine:
    8 LONGS sensor
    or
    32 BYTES sensor

    But when I use:
    16 WORDS sensor
    WORDS lists the dictionary.

    I can just use the BYTES way - thought you might not have noticed this . . .
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-20 - 01:06:11
    artkennedy wrote: »
    I need an array for storing 16 sensor readings. Two bytes are needed for each.

    I find that his works fine:
    8 LONGS sensor
    or
    32 BYTES sensor

    But when I use:
    16 WORDS sensor
    WORDS lists the dictionary.

    I can just use the BYTES way - thought you might not have noticed this . . .

    LOL, missed that!

    The files have been updated so that WORDS followed by a CR will perform a listing while WORDS followed by a space(s) or tab will work like BYTES and LONGS. The binary has been updated.
  • artkennedyartkennedy Posts: 164
    edited 2014-03-20 - 01:48:03
    Best I can do so far with what I have been able to discover about GETWORD:
    : TEST       \ assign portion of input stream between spaces to string
        GETWORD        \ accept first segment of input stream
        GETWORD        \ accept second segment of input stream
        @PAD #11 +     \ point to segment in input buffer
        DMMINP$ COPY$  \ copy to variable
    ;
    

    Pretty clunky . . . tips?
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-20 - 03:23:37
    artkennedy wrote: »
    Best I can do so far with what I have been able to discover about GETWORD:
    : TEST       \ assign portion of input stream between spaces to string
        GETWORD        \ accept first segment of input stream
        GETWORD        \ accept second segment of input stream
        @PAD #11 +     \ point to segment in input buffer
        DMMINP$ COPY$  \ copy to variable
    ;
    

    Pretty clunky . . . tips?

    GETWORD only has one buffer for a word so it can't stack them as in GETWORD GETWORD so you need to copy them perhaps. You might have to remind me what you are trying to do again, what does the string look like? Hold on, I went back through your posts so I will assume it is this one "DC 399.9 uA<cr>"

    If that is all you are trying to read then why don't you let Forth parse it normally rather than wrangling with it? For instance you define DC which sets a variable/flag then 399.9 ends up on the stack and then you could have uA mA etc which will expect a number already on the stack etc. If the decimal point is important I could easily make sure that that information is made available in a variable.
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-20 - 07:39:53
    Originally Posted by artkennedy viewpost-right.png Best I can do so far with what I have been able to discover about GETWORD:
    GETWORD only has one buffer for a word so it can't stack them as in GETWORD GETWORD so you need to copy them perhaps. You might have to remind me what you are trying to do again, what does the string look like? Hold on, I went back through your posts so I will assume it is this one "DC 399.9 uA<cr>"

    If that is all you are trying to read then why don't you let Forth parse it normally rather than wrangling with it? For instance you define DC which sets a variable/flag then 399.9 ends up on the stack and then you could have uA mA etc which will expect a number already on the stack etc. If the decimal point is important I could easily make sure that that information is made available in a variable.

    I've implemented detecting decimal places in the kernel which can be read out with DPL and is valid for the last number entered. Numbers cannot start or end in a decimal point, here are some examples:
    12.345 DPL . 3 ok
    0.12345 DPL . 5 ok
    12345. --> 12345. <-- NOT FOUND
    12345.0 DPL . 1 ok
    .12345 --> .12345 <-- NOT FOUND

  • artkennedyartkennedy Posts: 164
    edited 2014-03-21 - 00:36:32
    GETWORD only has one buffer for a word so it can't stack them as in GETWORD GETWORD so you need to copy them perhaps. You might have to remind me what you are trying to do again, what does the string look like? Hold on, I went back through your posts so I will assume it is this one "DC 399.9 uA<cr>"

    If that is all you are trying to read then why don't you let Forth parse it normally rather than wrangling with it? For instance you define DC which sets a variable/flag then 399.9 ends up on the stack and then you could have uA mA etc which will expect a number already on the stack etc. If the decimal point is important I could easily make sure that that information is made available in a variable.

    That example string is only for one of the ranges of the DMM, the DC micoramp range. I would like to make a word that works for all the ranges. They have in common, in order, a type designator, <space>, number, <space>, range designator. The length of the first and third fields may vary slightly. Therefore I would like to parse the string using the spaces as delimiters. Wow, it just occurred to me - that is what GETWORD does. Right? I could just use GETWORD three times assigning the result sequentially to type$, reading$, and range$ and then using STR>NUM on reading$.

    As for how to use the result of GETWORD I'm not sure I understand how that is done ( that's not right - I am sure I don't understand ). What I have tried using @PAD was just a fake based on experimentation. Is that the proper way to access the result of a GETWORD event?

    DPL looks good. I had thought I might go back and add that to STR>NUM.

    I am rather cloudy about your suggestion re letting FORTH parse the input string. Thinking . . . -- holy cow! Do you mean by adding a colon and space to the front and a space and semi-colon to the end?!? Oh, I love tricks! Scratching head . . . how would that work? :-)

    This Tachyon environment is vast and I feel like a blind person feeling his way around the room from chair to chair. I really appreciate your patience and assistance.
  • artkennedyartkennedy Posts: 164
    edited 2014-03-21 - 00:46:27
    Sonuvagun!
    DECIMAL  ok
    GETWORD : DC 4.321 uA  --> uA <-- NOT FOUND
    ;  ok
    DC .S  Data Stack (1)
    $0000.10E1 - 4321
    $0000.0000 - 0 ok
    

    Oh (again). Predefine : uA reading ! ; (or something similar) I get it. That is excellent!
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-21 - 01:16:01
    artkennedy wrote: »
    Sonuvagun!
    DECIMAL  ok
    GETWORD : DC 4.321 uA  --> uA <-- NOT FOUND
    ;  ok
    DC .S  Data Stack (1)
    $0000.10E1 - 4321
    $0000.0000 - 0 ok
    

    Oh (again). Predefine : uA reading ! ; (or something similar) I get it. That is excellent!

    No, actually it's simplier than that, just let Forth interpret the text as it normally does. Of course Forth doesn't know DC or uA or anything like that but that's why you just define those words as I mentioned.
    The first word such as DC or AC etc could just leave a number on the stack so therefore thses words would be constants. The V and mV and uA are all words that expect two numbers to be on the stack and handle it accordingly. To go and write a routine to parse the string is almost like bypassing Forth itself, just let it do it's thing.

    To give an example, I have WEB/FTP/TELNET servers running in Forth and they must "parse" commands from clients, yet I don't have any special parser, I just define words like GET RETR USER PASS LIST PASV etc and that's it. There is no central parser.
    Remember, use the Forth Luke
  • MJBMJB Posts: 1,167
    edited 2014-03-21 - 08:53:54
    artkennedy wrote: »
    Sonuvagun!
    DECIMAL  ok
    GETWORD : DC 4.321 uA  --> uA <-- NOT FOUND
    ;  ok
    DC .S  Data Stack (1)
    $0000.10E1 - 4321
    $0000.0000 - 0 ok
    

    Oh (again). Predefine : uA reading ! ; (or something similar) I get it. That is excellent!
    Hi Art,

    you could have:
    BYTE acdc   \ 0 = DC, 1 = AC
    0 acdc C!
    BYTE scalefact  \ scale value by 10^scalefact
    1 scalefact  C!  \ 
    LONG dmmval      \ store the dmmvalue
    BYTE av \ 0 = volts, 1 = amperes
    : DC 0 acdc C! ;
    : AC 1 acdc C! ;
    : mA  -3 DPL - scalefact C! 1 av C! dmmval ! ;
    : uA   -6 DPL - scalefact C! 1 av C! dmmval ! ;
    \ now after typing AC 12.3 mA you have
    \ acdc = 1
    \ scalefact = -4
    \ dmmval = 123  == 123*10^-4 == 12.3mA 
    \ av = 1  == Amperes
    
    so no parser required !!!

    getting this was one of the heureca monemts about forth
    thanks Peter :-)
  • max72max72 Posts: 1,150
    edited 2014-03-21 - 08:55:23
    Insane!!
    Thanks both for the tools and the tutorials!
    Massimo
  • D.PD.P Posts: 790
    edited 2014-03-21 - 09:56:09
    MJB wrote: »
    Hi Art,

    you could have:
    BYTE acdc   \ 0 = DC, 1 = AC
    0 acdc C!
    BYTE scalefact  \ scale value by 10^scalefact
    1 scalefact  C!  \ 
    LONG dmmval      \ store the dmmvalue
    BYTE av \ 0 = volts, 1 = amperes
    : DC 0 acdc C! ;
    : AC 1 acdc C! ;
    : mA  -3 DPL - scalefact C! 1 av C! dmmval ! ;
    : uA   -6 DPL - scalefact C! 1 av C! dmmval ! ;
    \ now after typing AC 12.3 mA you have
    \ acdc = 1
    \ scalefact = -4
    \ dmmval = 123  == 123*10^-4 == 12.3mA 
    \ av = 1  == Amperes
    
    so no parser required !!!

    getting this was one of the heureca monemts about forth
    thanks Peter :-)

    YES, this also was the ah-ha moment for me, use the problems "language" to define the FORTH words. Thanks!
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-21 - 11:48:32
    NEWCNT and .LAP have been the two words that have been used when it comes to timing TF as to how fast or slow it is running. Recently the VM instruction LAP was added which attempted to be more precise as it would calculate the delta since the last LAP and left the result in a COGREG rather than push the result on the stack as it would not be deterministic or needed the first time. So I was using LAP followed by .LAP with a compensation factor so that an empty LAP .LAP combo would report zero, expect it varied. This was because .LAP is bytecode and sits in the hub and so introduced hub delays. So now I use the combination of LAP <code> LAP .LAP instead and I have also used independent registers for LAP so that RUNMODs etc don't interfere. The timing calculations have also been optimized so that now it can time events up to 5.368 seconds maximum as this is limited by the maximum counter value of 53.687 seconds which has to be divided by 80 to calculate microseconds but what I do is multiply by 10 first then shift right 3 hence the *10 reduction.

    Here are some raw results:
    LAP LAP .LAP 0.00us ok
    LAP NOP LAP .LAP 0.40us ok
    LAP NOP NOP LAP .LAP 0.80us ok
    DECIMAL ok
    LAP 0 LAP .LAP 1.00us ok
    LAP 0 LAP .LAP 1.00us ok
    LAP 0 LAP .LAP 1.00us ok
    LAP 0 LAP .LAP 1.00us ok
    LAP 0 LAP .LAP 1.20us ok
    !SP ok
    LAP 0 LAP .LAP 1.00us ok
    LAP 8 LAP .LAP !SP 1.40us ok
    LAP 1234 LAP .LAP !SP 2.20us ok
    LAP $FFFF_FFFF LAP .LAP !SP 3.40us ok
    10 0 LAP DO LOOP LAP .LAP 10.00us ok
    100 0 LAP DO LOOP LAP .LAP 64.00us ok
    1,000 0 LAP DO LOOP LAP .LAP 604.00us ok
    10,000 0 LAP DO LOOP LAP .LAP 6.00ms ok
    100,000 0 LAP DO LOOP LAP .LAP 60.00ms ok
    1,000,000 0 LAP DO LOOP LAP .LAP 600.00ms ok
    10,000,000 0 LAP DO LOOP LAP .LAP 631.29ms ok
    5,000,000 0 LAP DO LOOP LAP .LAP 3000.00ms ok
    1234 10 LAP * LAP .LAP 2.60us ok
    1234 10 LAP U/ LAP .LAP 9.20us ok
    !SP ok
    1234 5678 LAP + LAP .LAP 1.00us ok
    $A5 LAP SPIWR LAP .LAP 2.40us ok


    Notice just before the first !SP that the same 0 operation was now taking 1.2us and that's because the stack had overflowed into hub stack, the subsequent !SP brought it back again.The 10,000,000 DO LOOP line should report 6,000ms but instead reports 631.29ms as the counter has overflowed and that's the difference between 6 seconds and 5.368 seconds.

    LAP <code> LAP .LAP
    is the recommended and precise way of timing code. NEWCNT has been deprecated but is at present still an alias for LAP.

    So here is the iterative Fibonacci being timed again:
    DECIMAL ok
    47 6 DO CR ." fibo(" I . ." ) = " I LAP fibo LAP .LAP ." result =" . 10 +LOOP
    fibo(6) = 8.60us result =8
    fibo(16) = 11.60us result =987
    fibo(26) = 14.60us result =121393
    fibo(36) = 17.60us result =14930352
    fibo(46) = 20.60us result =1836311903 ok





  • artkennedyartkennedy Posts: 164
    edited 2014-03-21 - 23:14:26
    MJB wrote: »
    Hi Art,

    you could have:
    BYTE acdc   \ 0 = DC, 1 = AC
    0 acdc C!
    BYTE scalefact  \ scale value by 10^scalefact
    1 scalefact  C!  \ 
    LONG dmmval      \ store the dmmvalue
    BYTE av \ 0 = volts, 1 = amperes
    : DC 0 acdc C! ;
    : AC 1 acdc C! ;
    : mA  -3 DPL - scalefact C! 1 av C! dmmval ! ;
    : uA   -6 DPL - scalefact C! 1 av C! dmmval ! ;
    \ now after typing AC 12.3 mA you have
    \ acdc = 1
    \ scalefact = -4
    \ dmmval = 123  == 123*10^-4 == 12.3mA 
    \ av = 1  == Amperes
    
    so no parser required !!!

    getting this was one of the heureca monemts about forth
    thanks Peter :-)

    Wow! This is cool. Thanks all around. There are more lights in the room now.
  • AleAle Posts: 2,360
    edited 2014-03-21 - 23:47:58
    Peter,

    I have a short question... when you write something on the terminal to for example add a word, are the IDLE cogs being used ? or the terminal COG does everything ? (Could I spare cogs 2 to 6?)
  • MJBMJB Posts: 1,167
    edited 2014-03-22 - 04:27:52
    Ale wrote: »
    Peter,

    I have a short question... when you write something on the terminal to for example add a word, are the IDLE cogs being used ? or the terminal COG does everything ? (Could I spare cogs 2 to 6?)
    there is one special COG dedicated to receiving - at the moment (I remember Peter talking about joining Rx & Tx in one COG for multiple serial connections).
    The writing is done from the kernel, so can be done from ANY COG running the Tachyon interpreter. All done by EMIT and the higher level words, that build on it.
    Just directly bitbanged out.

    I am just wondering what will happen if several COGs try to write by EMIT -
    I would expect some garbage ... you would have to implement some cooperation between different writers.
  • MJBMJB Posts: 1,167
    edited 2014-03-22 - 08:06:33
    MJB wrote: »
    Hi Art,

    you could have:
    BYTE acdc   \ 0 = DC, 1 = AC
    0 acdc C!
    BYTE scalefact  \ scale value by 10^scalefact
    1 scalefact  C!  \ 
    LONG dmmval      \ store the dmmvalue
    BYTE av \ 0 = volts, 1 = amperes
    : DC 0 acdc C! ;
    : AC 1 acdc C! ;
    : mA  -3 DPL - scalefact C! 1 av C! dmmval ! ;
    : uA   -6 DPL - scalefact C! 1 av C! dmmval ! ;
    \ now after typing AC 12.3 mA you have
    \ acdc = 1
    \ scalefact = -4
    \ dmmval = 123  == 123*10^-4 == 12.3mA 
    \ av = 1  == Amperes
    
    so no parser required !!!

    getting this was one of the heureca monemts about forth
    thanks Peter :-)
    actually, a while back I had to parse a command of the form:
    !CMD123;456;789;1011<crlf>
    see: http://forums.parallax.com/showthread.php/141061-TACHYON-A-very-fast-and-compact-Forth-SD-file-handling-TELNET-FTP-WEB-servers?p=1126867&viewfull=1#post1126867
    unfortunately there are no spaces and no uniform separator at all.
    So then again luckily, there were no spaces - so Forth will take the whole command as a new word and throw the word-not-found-error.
    I did a little modification to the Tachyon kernel and set up a word-not-found handler.
    This will simply check for the starting !, take the first 3 command characters,
    then replaces the ";" separator with spaces in word buffer. and then I
    just stuff the string back to the front of the input buffer.
    so from !CMD123;456;789;1011
    I create "123 456 789 1011 CMD "
    and put this back to the input buffer (since I was new to forth I modified the Tachyon kernel for this - but I think it could have been done without).
    Then Tachyon takes over again, takes the numbers (0 .. 5 in my case)
    and then executes the command word.
    This is very elegant since I can easily extend the language with the many commands I need - one by one. No big case or parser required.
    http://forums.parallax.com/showthread.php/141061-TACHYON-A-very-fast-and-compact-Forth-SD-file-handling-TELNET-FTP-WEB-servers?p=1128483&viewfull=1#post1128483


    links to my example code and modified Tachyon1.0
  • artkennedyartkennedy Posts: 164
    edited 2014-03-24 - 17:51:42
    Much appreciated this submission from MJB. It helped me get my thoughts organized on this.
    I found a few things I thought should be changed.
    Please let me know if I am missing something.


    Changes:
    BYTE scalefact  \ scale value by 10^scalefact
    
    
    : mA  -3 DPL - scalefact C! 1 av C! dmmval ! ;
    : uA   -6 DPL - scalefact C! 1 av C! dmmval ! ;
    
    
    Changed to :
    
    
    LONG scalefact  \ scale value by 10^scalefact       \ must use LONG for negative values, is this true for other Forths?
    
    
    : mA  DPL -3 - scalefact ! 1 av C! dmmval ! ;       \ DPL must be first in order to operate on the input number
    : uA  DPL -6 - scalefact ! 1 av C! dmmval ! ;       \ ditto
    
    
    Dropped:
    
    
    \ don't think these are needed - works fine without.
    
    
    0 acdc C!
    1 scalefact !
    
    
    Added:
    
    
    DECIMAL   \ without a base designation character in input string Tachyon BASE must agree with input
    
    
    


    Here it is with changes made:

    
    FORGET acdc
    DECIMAL       \ without a base designation character Tachyon BASE must agree with input
    
    
    BYTE acdc   \ 0 = DC, 1 = AC
    LONG scalefact  \ scale value by 10^scalefact
    LONG dmmval      \ store the dmmvalue
    BYTE av \ 0 = volts, 1 = amperes
    : DC 0 acdc C! ;
    : AC 1 acdc C! ;
    : mA  DPL -3 - scalefact ! 1 av C! dmmval ! ;
    : uA  DPL -6 - scalefact ! 1 av C! dmmval ! ;
    \ now after typing AC 12.3 mA you have
    \ acdc = 1
    \ scalefact = -4
    \ dmmval = 123  == 123*10^-4 == 12.3mA
    \ av = 1  == Amperes
    
    
    


    My immediate project will always take DMM readings on the same scale without negative results so it will have no need for 'acdc' or 'scalefact' which will make for simpler code. However, I hope that there will be wider interest and more general code will be needed. This will be useful. Thanks.


    And especial thanks to Peter for Tachyon and showing me how simple this part could be. Kenobi-san, I shall remember.
    Forth On!
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-24 - 18:55:32
    artkennedy wrote: »
    Much appreciated this submission from MJB. It helped me get my thoughts organized on this.
    I found a few things I thought should be changed.
    Please let me know if I am missing something.

    The less I see the better it gets. When code or ideas are just converted from another language it can look quite unreadable (and awkward) but with a little Forth Zen it becomes too simple to be considered real software :)

    Here's a tip too because it looks like you are doing a -6 - which is the same as a 6 + plus you can factor the common section like this:
    : DC acdc C~ ;
    : AC acdc C~~ ;
    : uA    6
    : +A    DPL + scalefact ! dmmval ! av C~~   ;
    : mA    3 +A ;
    
    
  • Peter JakackiPeter Jakacki Posts: 9,360
    edited 2014-03-24 - 19:05:04
    MJB wrote: »
    actually, a while back I had to parse a command of the form:
    !CMD123;456;789;1011<crlf>
    see: http://forums.parallax.com/showthread.php/141061-TACHYON-A-very-fast-and-compact-Forth-SD-file-handling-TELNET-FTP-WEB-servers?p=1126867&viewfull=1#post1126867
    unfortunately there are no spaces and no uniform separator at all.
    So then again luckily, there were no spaces - so Forth will take the whole command as a new word and throw the word-not-found-error.
    I did a little modification to the Tachyon kernel and set up a word-not-found handler.
    This will simply check for the starting !, take the first 3 command characters,
    then replaces the ";" separator with spaces in word buffer. and then I
    just stuff the string back to the front of the input buffer.
    so from !CMD123;456;789;1011
    I create "123 456 789 1011 CMD "
    and put this back to the input buffer (since I was new to forth I modified the Tachyon kernel for this - but I think it could have been done without).
    Then Tachyon takes over again, takes the numbers (0 .. 5 in my case)
    and then executes the command word.
    This is very elegant since I can easily extend the language with the many commands I need - one by one. No big case or parser required.
    http://forums.parallax.com/showthread.php/141061-TACHYON-A-very-fast-and-compact-Forth-SD-file-handling-TELNET-FTP-WEB-servers?p=1128483&viewfull=1#post1128483


    links to my example code and modified Tachyon1.0

    TF allows you to change the delimiter so that you could make a ; a delimiter if you like. Here's a terminal session:
    [FONT=courier new]!CMD123;456;789;1011 --> !CMD123;456;789;1011 <-- NOT FOUND 
    : !CMD123 ;  ok
    ";" delim C!  ok
    !CMD123;456;789;1011  ok
    .S  Data Stack (3)
    $0000.1011 - 4113
    $0000.0789 - 1929
    $0000.0456 - 1110
    $0000.0000 - 0 ok
    0D delim C!  ok
    
    [/FONT]
    

    Of course it didn't separate the 123 from CMD but it's a start.
Sign In or Register to comment.