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.
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?
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.
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.
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.
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
;
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 . . .
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.
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
;
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.
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
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.
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
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
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?)
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.
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
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!
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 ;
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
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.
Comments
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.
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?
I'm putting on my waders. Somebody point me to the 'stream' ;-)
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.
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.
Sure is nice to have NUMBER upgraded and to use <CMOVE.
Here is the new STR>NUM:
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.
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.
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
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.
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
you could have: so no parser required !!!
getting this was one of the heureca monemts about forth
thanks Peter :-)
Thanks both for the tools and the tutorials!
Massimo
YES, this also was the ah-ha moment for me, use the problems "language" to define the FORTH words. Thanks!
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
Wow! This is cool. Thanks all around. There are more lights in the room now.
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?)
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.
!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
I found a few things I thought should be changed.
Please let me know if I am missing something.
Changes:
Here it is with changes made:
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!
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:
TF allows you to change the delimiter so that you could make a ; a delimiter if you like. Here's a terminal session:
Of course it didn't separate the 123 from CMD but it's a start.