I am really liking the way Tachyon parses as soon as you enter a space and reports "NOT FOUND" so that you can then press ESC and not even disturb the stack. *Slick*
This has been elusive for me for some reason. I'm just now proceding from FORTH/Tachyon syntax to more "how it works" stuff.
Getting past this hurdle has helped me greatly, I just couldn't glean what I needed from within the source.
Now I have renewed motivation, thanks for the "thorn removal"
UPDATE, while this has removed the keyboard issue the LCD is "no op", LCD checked with console testing? I've tried with $20,$30 ALLOT for regs1
UPDATE2****** NEED TO HAVE A BLANK LINE BETWEEN EACH ALLOT STATEMENT, ARRG I BEEN BITTEN BY THIS BEFORE! BEWARE
TABLE regs1 $20 ALLOT \ some room for temp register + uemit and ukey
TABLE stacktsk $40 ALLOT
\ shoud be
TABLE regs1 $20 ALLOT \ some room for temp register + uemit and ukey
TABLE stacktsk $40 ALLOT
I can fix the blank line thing, it's just that I keep forgetting about it but if you leave out the end-of-line comment it also works fine too. Just place the comment up above it. It has to do with termination of looking for more names although TABLE itself should never need to do this but it's based on AVARIABLE which does.
As long as nothing has set the LCD serial data pin high such as during testing then your task should be able to run but I will hook-up one of my serial LCDs and try it out anyway.
EDIT: you could also release the LCD serial data pin after transmit as the LCD should have a pullup.
pub LCDEMIT 9 PINSET 9 SEROUT 9 PININP ;
I am really liking the way Tachyon parses as soon as you enter a space and reports "NOT FOUND" so that you can then press ESC and not even disturb the stack. *Slick*
I did have that changed to ??? during normal interactive mode but to make the error pop out a bit more during a source code load I did the --> badword <-- NOT FOUND message instead. So don't be surprised if it seems to revert back to ??? because that is less invasive when we are typing whereas the NOT FOUND is useful during a TACHYON ...... END type load.
The parsing as you type is really compile as you type so you don't have to create a definition just to run "compile only" words as they work the same outside of a definition as they do inside, an example:
$80 BL DO I EMIT LOOP
Will execute immediately you hit the enter key without having to put this inside a definition.
BTW, You don't even need to hit ESC as it is quite happy just to continue on. Clearing the stack on an error seems to be a standard Forth thing but I always found it to be more of a nuisance, type type doh, retype retype doh and so on.
EDIT: The compile as you go approach also means I don't have to have a text input buffer large enough to accommodate the longest line, I only need a word buffer wide enough to accommodate the longest word (32 characters).
I can fix the blank line thing, it's just that I keep forgetting about it but if you leave out the end-of-line comment it also works fine too. Just place the comment up above it. It has to do with termination of looking for more names although TABLE itself should never need to do this but it's based on AVARIABLE which does.
As long as nothing has set the LCD serial data pin high such as during testing then your task should be able to run but I will hook-up one of my serial LCDs and try it out anyway.
EDIT: you could also release the LCD serial data pin after transmit as the LCD should have a pullup.
pub LCDEMIT 9 PINSET 9 SEROUT 9 PININP ;
Everything works after the additional line between the TABLE definitions. I will remember/document about the comments and the release of the serial pin.
Thanks
I am working to interface a DMM to the Propeller. It communicates with 7 bits and 2 stop bits. I have tested it with an hp48 calculator at 8.1. Works fine if you clear the high bit of incoming data. For some reason PropForth would not cooperate with this although I did a successful test using the calculator to simulate the DMM by transmitting the same string with the high bits set. Maybe something I overlooked.
Currently I am learning to use Tachyon and testing still with the calculator doing the FakeDMM thing. I have established communication and get the string in to the prop. The test string is "DC 4.321 V". I have written code to extract the numeric part of the string "4.321" or "-1.234", as the case may be, so I need to find the spaces. Of course I could just assume ;-) the result to always be positive and it would always be in the same place - easy. But I would rather make a more general method. And after I get the number as a string I will want to make it a number - don't know how yet - have ideas - surely been done before.
Here is the code and the problems: [ how do I put code in one of those nice little windows? ]
dmmbuf .STR DC 4.321 V ok
: .DMM
dmmbuf $20 STRING D$ \ assign DMM reading to D$
BL D$ LOCATE$ 1+ $20 STRING N$ \ drop left side of string before number
N$ DUP BL OVER LOCATE$ \ find trailing space
SWAP - LEFT$ \ drop all after number
N$ D$ COPY$
FORGET N$
;
Problems:
Won't run. Can't FORGET it. It places the strings in the dictionary before it is even executed. Arrrrh!
I am working to interface a DMM to the Propeller. It communicates with 7 bits and 2 stop bits. I have tested it with an hp48 calculator at 8.1. Works fine if you clear the high bit of incoming data. For some reason PropForth would not cooperate with this although I did a successful test using the calculator to simulate the DMM by transmitting the same string with the high bits set. Maybe something I overlooked.
Currently I am learning to use Tachyon and testing still with the calculator doing the FakeDMM thing. I have established communication and get the string in to the prop. The test string is "DC 4.321 V". I have written code to extract the numeric part of the string "4.321" or "-1.234", as the case may be, so I need to find the spaces. Of course I could just assume ;-) the result to always be positive and it would always be in the same place - easy. But I would rather make a more general method. And after I get the number as a string I will want to make it a number - don't know how yet - have ideas - surely been done before.
Here is the code and the problems: [ how do I put code in one of those nice little windows? ]
dmmbuf .STR DC 4.321 V ok
: .DMM
dmmbuf $20 STRING D$ \ assign DMM reading to D$
BL D$ LOCATE$ 1+ $20 STRING N$ \ drop left side of string before number
N$ DUP BL OVER LOCATE$ \ find trailing space
SWAP - LEFT$ \ drop all after number
N$ D$ COPY$
FORGET N$
;
Problems:
Won't run. Can't FORGET it. It places the strings in the dictionary before it is even executed. Arrrrh!
I can't declare a STRING in a definition so Peter will have the answer, but this does work so your logic is right
" DC 4.321 V" $20 STRING dmmbuf ok
NULL$ $20 STRING D$ ok
NULL$ $20 STRING N$ ok
: DMM
dmmbuf D$ COPY$
BL D$ LOCATE$ 1+ N$ COPY$ \
N$ DUP BL OVER LOCATE$ \
SWAP - LEFT$ \
N$ D$ COPY$
; ok
DMM ok
N$ .STR 4.321 ok
D$ .STR 4.321 ok
Pretty sure you could refactor one string and use the temporary buffers if memory is of concern.
"Add BUFFERS word which points to the 2K VM image (reusable as temporary buffers - do not backup as Tachyon will not be able to boot)"
I am working to interface a DMM to the Propeller. It communicates with 7 bits and 2 stop bits. I have tested it with an hp48 calculator at 8.1. Works fine if you clear the high bit of incoming data. For some reason PropForth would not cooperate with this although I did a successful test using the calculator to simulate the DMM by transmitting the same string with the high bits set. Maybe something I overlooked.
Currently I am learning to use Tachyon and testing still with the calculator doing the FakeDMM thing. I have established communication and get the string in to the prop. The test string is "DC 4.321 V". I have written code to extract the numeric part of the string "4.321" or "-1.234", as the case may be, so I need to find the spaces. Of course I could just assume ;-) the result to always be positive and it would always be in the same place - easy. But I would rather make a more general method. And after I get the number as a string I will want to make it a number - don't know how yet - have ideas - surely been done before.
Here is the code and the problems: [ how do I put code in one of those nice little windows? ]
dmmbuf .STR DC 4.321 V ok
: .DMM
dmmbuf $20 STRING D$ \ assign DMM reading to D$
BL D$ LOCATE$ 1+ $20 STRING N$ \ drop left side of string before number
N$ DUP BL OVER LOCATE$ \ find trailing space
SWAP - LEFT$ \ drop all after number
N$ D$ COPY$
FORGET N$
;
Problems:
Won't run. Can't FORGET it. It places the strings in the dictionary before it is even executed. Arrrrh!
About the forum formating, it uses BBCode and you can enter this directly or press the ADVANCED button down the bottom right of the edit window and you get a whole lot of other options. So when you paste code into the window then select that section and click the # button which will enclose the text in code tags.
The STRING word is a defining word, that is it creates a new defintion and the rule is that you do not create new definitions inside another one, so logically these should be defined before .DMM . So STRING and FORGET etc are all defining words that execute immediately even during compile so no Forth ever expects to use them in the way that you have defined .DMM
Anyway, you are doing it the hard way, all the parsing and conversion is built into TF, don't assemble the whole line into a buffer just parse it word by word (direct key input) and use GETWORD DECIMAL NUMBER when you are expecting data from the DMM. The AC/DC part of the message would also be handled by a preceding GETWORD and storing that result in a string like this GETWORD dmm$ COPY$ etc.
I could write the code for you but it is simpler than you think so I will let you have a bit more of a play with TF. Of couse if you have to have it in a bufffer to parse just remember that NUMBER will parse a string but define that string just like any variable or constant, outside of another defintion.
EDIT: You would never say in any Forth
: MyTest 1234 CONSTANT mycon mycon . ;
But of course you do it like this:
1234 CONSTANT mycon
: MyTest mycon . ;
So STRING is similar to CONSTANT and VARIABLE and so on. Even if the first example compiled somehow what would happend each time you ran it is that it would create another new definition called mycon, after testing that ten times you would have 10 new "mycons" in the dictionary, clearly not what you would want to happen.
BTW, any use of the BACKUP word is normally safe, it skips those areas it would never want to overwrite in EEPROM.
While searching for a pic32 forth, I came across the program FORFITER (Lubos Pekny www.forth.cz). It is a terminal program designed to use with FORTH. It combines a terminal with an editor. It effectively eliminates copy/paste as a tool to entend forth. I am now using forfiter instead of tera term.
About the forum formating, it uses BBCode and you can enter this directly or press the ADVANCED button down the bottom right of the edit window and you get a whole lot of other options. So when you paste code into the window then select that section and click the # button which will enclose the text in code tags.
The STRING word is a defining word, that is it creates a new defintion and the rule is that you do not create new definitions inside another one, so logically these should be defined before .DMM . So STRING and FORGET etc are all defining words that execute immediately even during compile so no Forth ever expects to use them in the way that you have defined .DMM
Anyway, you are doing it the hard way, all the parsing and conversion is built into TF, don't assemble the whole line into a buffer just parse it word by word (direct key input) and use GETWORD DECIMAL NUMBER when you are expecting data from the DMM. The AC/DC part of the message would also be handled by a preceding GETWORD and storing that result in a string like this GETWORD dmm$ COPY$ etc.
I could write the code for you but it is simpler than you think so I will let you have a bit more of a play with TF. Of couse if you have to have it in a bufffer to parse just remember that NUMBER will parse a string but define that string just like any variable or constant, outside of another defintion.
EDIT: You would never say in any Forth
: MyTest 1234 CONSTANT mycon mycon . ;
But of course you do it like this:
1234 CONSTANT mycon
: MyTest mycon . ;
So STRING is similar to CONSTANT and VARIABLE and so on. Even if the first example compiled somehow what would happend each time you ran it is that it would create another new definition called mycon, after testing that ten times you would have 10 new "mycons" in the dictionary, clearly not what you would want to happen.
BTW, any use of the BACKUP word is normally safe, it skips those areas it would never want to overwrite in EEPROM.
NUMBER in my version doesn't seem to work according to the comments in the Tachyon V2.3 source regarding valid conversion forms. Else my syntax is wrong?
Propeller .:.:--TACHYON--:.:. Forth V23140216.1600
NAMES: $5DC9...74EF for 5926 (3412 bytes added)
CODE: $0000...3352 for 7212 (6994 bytes added)
CALLS: 0482 vectors free
RAM: 10871 bytes free
AUTORUN EXTEND.boot
MODULES LOADED:
1800: EXTEND.fth Primary extensions to TACHYON kernel - 140216-1400
----------------------------------------------------------------
" 1234d" $10 STRING D$ ok
.S
STACK: 0000.0000 0000.0000 FFFF.F9FF 0000.0010 ok
D$ TYPE$ 1234d ok
.S
STACK: 0000.0000 0000.0000 FFFF.F9FF 0000.0010 ok
D$ NUMBER ok
.S
STACK: 0000.0000 FFFF.F9FF 0000.0010 0000.0000 ok
NUMBER in my version doesn't seem to work according to the comments in the Tachyon V2.3 source regarding valid conversion forms. Else my syntax is wrong?
NUMBER ' ( str -- value digits | false )
Acceptable forms are:
$1000 hex number
1000h
#1000 decimal number
1000d
00 binary number
1000b
While it is true that NUMBER will take a string from GETWORD and convert it, it does not appear to work with strings in general and this is simply because NUMBER is expecting a string with a preceding count as is used in GETWORD. It stills looks like a string, it's that it just happens to have the count of the string in the byte preceding it.
I may change the operation of NUMBER to work with strings in general but in the meantime this will work:
[FONT=courier new]
\ Create a string variable to hold the longest number (binary with separators)
" 1234" #40 STRING num$
pub STR>NUM ( str -- num digits | false )
num$ 1+ $!
num$ 1+ LEN$ num$ C!
num$ 1+ NUMBER
;
[/FONT]
While it is true that NUMBER will take a string from GETWORD and convert it, it does not appear to work with strings in general and this is simply because NUMBER is expecting a string with a preceding count as is used in GETWORD. It stills looks like a string, it's that it just happens to have the count of the string in the byte preceding it.
I may change the operation of NUMBER to work with strings in general but in the meantime this will work:
[FONT=courier new]
\ Create a string variable to hold the longest number (binary with separators)
" 1234" #40 STRING num$
pub STR>NUM ( str -- num digits | false )
num$ 1+ $!
num$ 1+ LEN$ num$ C!
num$ 1+ NUMBER
;
[/FONT]
I'm integrating floating point into TF but if I do this at compile time it adds another 2K to the memory footprint that while acceptable during evaluation stage is really wasteful when you start cramming in other modules and your application. What I am thinking of doing is specifying that the image of the floating point module and other modules reside in the top 32k of a 64kB EEPROM so that main hub memory is not lost. Normally a Prop loads a cog from an image in hub memory and that 2K or so area is normally waster afterwards. In the case of TF the hub memory area that held the TF cog image is reused at runtime for buffers, as is also the smaller receive cog image as it is reused for serial buffers. This is fine as when I do a backup of the TF system it bypasses these areas as it doesn't need to backup buffers which of course it shouldn't anyway as it needs to have the TF and serial images available at boot-time.
Anyhow, getting back to allowing TF to make efficient use of it's hub memory without imposing extra hardware on the system other than using a 64kB EEPROM instead of the normal 32kB, I need to have any additional cog images out of the way but readily accessible at boot time. The logical place for this is in the top 32kB of the 64kB EEPROM where a boot-time program can load the images that are required into cogs without messing with hub memory. Since coginit requires the image to be in hub ram I just load the EEPROM image into the 2K buffer area vacated by the TF image. This would allow me to be able to load the floating-point image as well as others such as VGA, serial, etc into cogs while TF is booting. Of course these images could also reside on SD instead but that may not be present while EEPROM always is.
Does that scheme sound acceptable? Are there other cog objects that you would like? In the case of floating point I just use the PASM from F32 as would be the case with serial, VGA etc.
BTW, the image is initially loaded into EEPROM in a similar manner to extending the kernel, except we load a hex file.
EDIT: in the case of a VGA/TV text driver I could compile and load the module normally as I could reuse the image ram for the display buffer. But the EEPROM scheme is more flexible.
EDIT: Rather than a pure hex file I could use the listing generated by BST and paste that into my TF module source, that's uncomplicated and readable, and TF could just filter out the code it needs to load into EEPROM. There's lot's of information in the listing, here's a sample:
I think it is a great addition.
The 4 serial ports is a good candidate too, but probably the best would be to have a small how to in order to implement our object or add an existing one.
Tell me if I'm wrong, but after all the 2 main configurations are the coprocessor style (where the pasm cog waits for the arguments and executes one of the possible operations) and the silently running, where the pasm code is doing its work independently, and in case shares data in and out via a HUB array.
If we were able to create the code we could be able to speed up the obex translation, and also adding our own pasm modules.
Massimo
I added a new instruction to the PASM kernel that takes just one extra long and now I run the Fibonacci benchmark with much faster results. I might never use the new instruction in anything else but then again I might. It just replaces the OVER + SWAP operation and since it only added one extra long in the kernel I thought why not.
DECIMAL ok
1 26 ADO CR ." fibo(" I . ." ) = " NEWCNT I fibo .LAP ." result =" . LOOP
fibo(1) = 11us result =1
fibo(2) = 12us result =1
fibo(3) = 13us result =2
fibo(4) = 14us result =3
fibo(5) = 15us result =5
fibo(6) = 16us result =8
fibo(7) = 17us result =13
fibo(8) = 18us result =21
fibo(9) = 19us result =34
fibo(10) = 20us result =55
fibo(11) = 21us result =89
fibo(12) = 22us result =144
fibo(13) = 23us result =233
fibo(14) = 24us result =377
fibo(15) = 25us result =610
fibo(16) = 26us result =987
fibo(17) = 27us result =1597
fibo(18) = 28us result =2584
fibo(19) = 29us result =4181
fibo(20) = 30us result =6765
fibo(21) = 31us result =10946
fibo(22) = 32us result =17711
fibo(23) = 33us result =28657
fibo(24) = 34us result =46368
fibo(25) = 35us result =75025
fibo(26) = 36us result =121393 ok
I added a new instruction to the PASM kernel that takes just one extra long and now I run the Fibonacci benchmark with much faster results. I might never use the new instruction in anything else but then again I might. It just replaces the OVER + SWAP operation and since it only added one extra long in the kernel I thought why not.
DECIMAL ok
1 26 ADO CR ." fibo(" I . ." ) = " NEWCNT I fibo .LAP ." result =" . LOOP
fibo(1) = 11us result =1
fibo(2) = 12us result =1
fibo(3) = 13us result =2
fibo(4) = 14us result =3
fibo(5) = 15us result =5
fibo(6) = 16us result =8
fibo(7) = 17us result =13
fibo(8) = 18us result =21
fibo(9) = 19us result =34
fibo(10) = 20us result =55
fibo(11) = 21us result =89
fibo(12) = 22us result =144
fibo(13) = 23us result =233
fibo(14) = 24us result =377
fibo(15) = 25us result =610
fibo(16) = 26us result =987
fibo(17) = 27us result =1597
fibo(18) = 28us result =2584
fibo(19) = 29us result =4181
fibo(20) = 30us result =6765
fibo(21) = 31us result =10946
fibo(22) = 32us result =17711
fibo(23) = 33us result =28657
fibo(24) = 34us result =46368
fibo(25) = 35us result =75025
fibo(26) = 36us result =121393 ok
Based on the previous results I would say 1 long went a long way. As far as the F32 "hack" (the optimal way to connect a rotary phone switch to cause the best track switching to occur with the least fuss, "tech model railroad club") I can't wait to start using it. I agree with max72 it would be nice to be able to push our own "mods" this way but not necessary. I think F32 now gives Tachyon just about everything one could need. Telnet, FTP, HTTP, Sockets, Floating Point, Strings, RTC provisions, SD access, partial FAT16/32, I2C, SPI, ASync and best of all a console to rule them all! I was gathering UI needs from co-workers the other day and even they said "hey wait don't you have to go rebuild the software or something before you show us again" as I worked directly on the console as the equipment was running! Thanks Peter.
fibo(1) = 13us result =1
fibo(2) = 16us result =1
fibo(3) = 19us result =2
fibo(4) = 22us result =3
fibo(5) = 25us result =5
fibo(6) = 28us result =8
fibo(7) = 31us result =13
fibo(8) = 34us result =21
fibo(9) = 37us result =34
fibo(10) = 40us result =55
fibo(11) = 43us result =89
fibo(12) = 46us result =144
fibo(13) = 49us result =233
fibo(14) = 52us result =377
fibo(15) = 55us result =610
fibo(16) = 58us result =987
fibo(17) = 61us result =1597
fibo(18) = 64us result =2584
fibo(19) = 67us result =4181
fibo(20) = 70us result =6765
fibo(21) = 73us result =10946
fibo(22) = 76us result =17711
fibo(23) = 79us result =28657
fibo(24) = 82us result =46368
fibo(25) = 85us result =75025
fibo(26) = 88us result =121393 ok
Kuroneko has been helping out today with tweaking some of the PASM code which has freed up a handful of longs, and also the 8 channel PWM. So that's prompted me to tidy up some other stuff too and also fully implement and test the 32 channel PWM. These outputs are jitter free as best as they can be measured, there is a scope trace in the kernel source document you can look at but what I did was zoom in to 25ns/div at 50 ms after the trigger and leave the scope on infinite persistence. There was no jitter at all even though you can see the hairy rise time etc and the only thing that crept in was about 10ns of drift over 10 minutes or more, but no jitter, just rock steady. The reason for 32 channels is so that you can make any and as many pins as you like a PWM output
You need 256 longs for a table that can be used to store all the calculated duty cycles for 32 channels over 256 samples (8-bit). The init code looks like this:
[FONT=courier new]TABLE pwms #1024 ALLOT \ allocate a 256 longs table for the PWM map
#5000 PWMFREQ \ Set the frequecy
\ Start up PWM using from P0..7, P16..P23 for 16 channels
$FF00FF pwms RUNPWM32
#50 % 2 MASK PWM32! \ set P2 to 50 % duty
#25 % $0F0000 PWM32! \ set P16..P19 to 25 % duty[/FONT]
The signed divide also runs faster from 47us down to 18us whereas the unsigned divide U/ takes 10us. The multiply ops take around 4 or 5 us.
Kuroneko has been helping out today with tweaking some of the PASM code which has freed up a handful of longs, and also the 8 channel PWM. So that's prompted me to tidy up some other stuff too and also fully implement and test the 32 channel PWM. These outputs are jitter free as best as they can be measured, there is a scope trace in the kernel source document you can look at but what I did was zoom in to 25ns/div at 50 ms after the trigger and leave the scope on infinite persistence. There was no jitter at all even though you can see the hairy rise time etc and the only thing that crept in was about 10ns of drift over 10 minutes or more, but no jitter, just rock steady. The reason for 32 channels is so that you can make any and as many pins as you like a PWM output
You need 256 longs for a table that can be used to store all the calculated duty cycles for 32 channels over 256 samples (8-bit). The init code looks like this:
[FONT=courier new]TABLE pwms #1024 ALLOT \ allocate a 256 longs table for the PWM map
#5000 PWMFREQ \ Set the frequecy
\ Start up PWM using from P0..7, P16..P23 for 16 channels
$FF00FF pwms RUNPWM32
#50 % 2 MASK PWM32! \ set P2 to 50 % duty
#25 % $0F0000 PWM32! \ set P16..P19 to 25 % duty[/FONT]
The signed divide also runs faster from 47us down to 18us whereas the unsigned divide U/ takes 10us. The multiply ops take around 4 or 5 us.
Just sorted through some problems on my side with kuroneko and then fired up his version of PWM32 and now that runs up to 6.940kHz. no make that 7.6kHz
Controlling individual pins or groups of pins is easy and of course you can always create your methods like these
75 % 2 SETPWM ( set P2 to 75% duty)
or
32 16 8 SETPWMS ( set P16..P23 to 32/256 duty cycle)
or you might like to specify the range like Spin in which case we could modify SETPWMS
32 16 23 SETPWMS
etc
These methods calculate the entries in a 1K byte table for all 256 samples of 32 channels which the PWM cog just reads from. So it's also possible to put arbitrary waveforms in the table too or even higher frequencies with less resolution, for instance if I set the channel bit in each alternate long I would have a 6.94kHz * 128 or 888.32kHz square wave on that pin (now 972.8kHz)
As mentioned earlier these PWM outputs are table based and jitter free.
So just a few days ago I managed to get 36us for 26 iterations of the fibonacci sequence. Now I have added some more instructions and some bytecode magic.... the fibo routine takes just 7 code bytes and runs how fast?
DECIMAL ok
1 26 ADO CR ." fibo(" I . ." ) = " NEWCNT I fibo .LAP ." result =" . LOOP
fibo(1) = 9us result =1
fibo(2) = 10us result =1
fibo(3) = 10us result =2
fibo(4) = 10us result =3
fibo(5) = 10us result =5
fibo(6) = 11us result =8
fibo(7) = 11us result =13
fibo(8) = 11us result =21
fibo(9) = 12us result =34
fibo(10) = 12us result =55
fibo(11) = 12us result =89
fibo(12) = 13us result =144
fibo(13) = 13us result =233
fibo(14) = 13us result =377
fibo(15) = 13us result =610
fibo(16) = 14us result =987
fibo(17) = 14us result =1597
fibo(18) = 14us result =2584
fibo(19) = 15us result =4181
fibo(20) = 15us result =6765
fibo(21) = 15us result =10946
fibo(22) = 16us result =17711
fibo(23) = 16us result =28657
fibo(24) = 16us result =46368
fibo(25) = 16us result =75025
fibo(26) = 17us result =121393 ok
So just a few days ago I managed to get 36us for 26 iterations of the fibonacci sequence. Now I have added some more instructions and some bytecode magic.... the fibo routine takes just 7 code bytes and runs how fast?
DECIMAL ok
1 26 ADO CR ." fibo(" I . ." ) = " NEWCNT I fibo .LAP ." result =" . LOOP
fibo(1) = 9us result =1
fibo(2) = 10us result =1
fibo(3) = 10us result =2
fibo(4) = 10us result =3
fibo(5) = 10us result =5
fibo(6) = 11us result =8
fibo(7) = 11us result =13
fibo(8) = 11us result =21
fibo(9) = 12us result =34
fibo(10) = 12us result =55
fibo(11) = 12us result =89
fibo(12) = 13us result =144
fibo(13) = 13us result =233
fibo(14) = 13us result =377
fibo(15) = 13us result =610
fibo(16) = 14us result =987
fibo(17) = 14us result =1597
fibo(18) = 14us result =2584
fibo(19) = 15us result =4181
fibo(20) = 15us result =6765
fibo(21) = 15us result =10946
fibo(22) = 16us result =17711
fibo(23) = 16us result =28657
fibo(24) = 16us result =46368
fibo(25) = 16us result =75025
fibo(26) = 17us result =121393 ok
Here's the iterative results from Heater's GCC LMM code.
I'm happy to have this speed without the need for C. And so much more!
As generally I am impressed with TF. Even if reading Forth code is as useful for me as reading spin-binary's in HEX.
But 7 code bytes IS impressive. What I am missing here is D.P.'s excitement over the speed. Heaters Fibo in compiled C finishes 26 iteration before TF does ONE?
As generally I am impressed with TF. Even if reading Forth code is as useful for me as reading spin-binary's in HEX.
But 7 code bytes IS impressive. What I am missing here is D.P.'s excitement over the speed. Heaters Fibo in compiled C finishes 26 iteration before TF does ONE?
Enjoy!
Mike
What's also very interesting is the loop time, if we look at the difference in timing between 1 and 26 iterations it is 17-9 for TF which is of course 8us vs GCC's 8us, the same! So not having the cog dedicated to a benchmark means the other 9us is spent in TF coming from doing something useful, calling the function, stacking the parameters, unstacking, and returning back to something useful again up to 17us later. Oh well.....
EDIT: just thinking about this abysmal 17us to run a fibo(26), I think Spin could almost run one and a half bytecode instructions in this same amount of time!
As generally I am impressed with TF. Even if reading Forth code is as useful for me as reading spin-binary's in HEX.
But 7 code bytes IS impressive. What I am missing here is D.P.'s excitement over the speed. Heaters Fibo in compiled C finishes 26 iteration before TF does ONE?
Enjoy!
Mike
One (GCC) is a compiled to benchmark one off program, does nothing more.
The other is able to run along side FTP, HTTP, TELNET, SD CARD and console access in ONE cog! I thought that the TF fibo just being 9 us slower than the almighty GCC was fantastic, but now I understand it runs at the same speed. Do you understand?
17-9=8. Did not look at it this way. Sad that me and forth do not get along. Seems my brain is indoctrinated by non prefix languages. I tried but cant wrap my head around it.
17-9=8. Did not look at it this way. Sad that me and forth do not get along. Seems my brain is indoctrinated by non prefix languages. I tried but cant wrap my head around it.
Enjoy!
Mike
Ah, I see Mike, you can't wrap your head around it, but I see from your avatar that perhaps your head's bin rappin' da PC C.
It's so much more fun that way hey? Whereas my avatar (which btw is reproducible on the serial terminal -prop) is going yabba dabba doo!
My first languages were "machine code", assembler, Basic, even Fortran, then C, with my introduction to Forth in there somewhere.
Ah,... Whereas my avatar (which btw is reproducible on the serial terminal -prop) is going yabba dabba doo!
You got me curious ... how to display your Avatar on a serial terminal? Or did you mean to display "yabba dabba doo"?
I do use different languages also, my last fulltime Cobol Job was somewhere at the end of the last century. Over the years I needed usually to change the Language when changing the Job. But say switching from VB.net to C#.net is not a really big task, the framework stays the same, just the syntax varies a bit. Things like C might be no big thing either - I hadn't had the need for yet. Since a couple of weeks I use JavaScript since @Heater talked me into it, but all of those languages are very alike in the way they handle stuff. Forth is quite different.
As to my Avatar ... that picture was probably taken while I was trying to understand FORTH.
You got me curious ... how to display your Avatar on a serial terminal? Or did you mean to display "yabba dabba doo"?
I do use different languages also, my last fulltime Cobol Job was somewhere at the end of the last century. Over the years I needed usually to change the Language when changing the Job. But say switching from VB.net to C#.net is not a really big task, the framework stays the same, just the syntax varies a bit. Things like C might be no big thing either - I hadn't had the need for yet. Since a couple of weeks I use JavaScript since @Heater talked me into it, but all of those languages are very alike in the way they handle stuff. Forth is quite different.
As to my Avatar ... that picture was probably taken while I was trying to understand FORTH.
Enjoy!
Mike
It was incredibly hard for me at first. Now it's fun. Hairless monkeys hate "to change", confirmation bias and peer packing can ruin the mind.
You got me curious ... how to display your Avatar on a serial terminal? Or did you mean to display "yabba dabba doo"?
I do use different languages also, my last fulltime Cobol Job was somewhere at the end of the last century. Over the years I needed usually to change the Language when changing the Job. But say switching from VB.net to C#.net is not a really big task, the framework stays the same, just the syntax varies a bit. Things like C might be no big thing either - I hadn't had the need for yet. Since a couple of weeks I use JavaScript since @Heater talked me into it, but all of those languages are very alike in the way they handle stuff. Forth is quite different.
As to my Avatar ... that picture was probably taken while I was trying to understand FORTH.
Enjoy!
Mike
Good come back Mike, hi5!
My avatar was taken from an ANSI graphics that I would display on compatible terminals, such as TeraTerm, even Hyperterminal. I will post a special edition of EXTEND.fth which will test to see if the terminal is compatible and then display my avatar on boot. In fact I can even test the terminal's baud rate settings etc to automatically adapt.
EDIT: Didn't want to make a new post but I shaved a few more microseconds from my fibo, still going for more:
fibo(22) = 12us result =17711
fibo(23) = 12us result =28657
fibo(24) = 13us result =46368
fibo(25) = 13us result =75025
fibo(26) = 13us result =121393
and
fibo(46) = 19us result =1836311903 ok
kuroneko has written fibo in PASM and gets 3.6us for fibo(46)
My avatar was taken from an ANSI graphics that I would display on compatible terminals, such as TeraTerm, even Hyperterminal. I will post a special edition of EXTEND.fth which will test to see if the terminal is compatible and then display my avatar on boot. In fact I can even test the terminal's baud rate settings etc to automatically adapt.
Anyone who is using TeraTerm or Hyperterminal can compile the latest kernel and EXTEND.fth and my avatar should appear on boot. My minicom doesn't handle these characters properly but I still need to fully activate the automatic terminal test software so that it only displays on compatible terminals.
Here are some of the latest fibonacci results:
fibo(2) = 6us result =1
fibo(3) = 6us result =2
fibo(23) = 12us result =28657
fibo(24) = 13us result =46368
fibo(25) = 13us result =75025
fibo(26) = 13us result =121393
Comments
I can fix the blank line thing, it's just that I keep forgetting about it but if you leave out the end-of-line comment it also works fine too. Just place the comment up above it. It has to do with termination of looking for more names although TABLE itself should never need to do this but it's based on AVARIABLE which does.
As long as nothing has set the LCD serial data pin high such as during testing then your task should be able to run but I will hook-up one of my serial LCDs and try it out anyway.
EDIT: you could also release the LCD serial data pin after transmit as the LCD should have a pullup.
pub LCDEMIT 9 PINSET 9 SEROUT 9 PININP ;
I did have that changed to ??? during normal interactive mode but to make the error pop out a bit more during a source code load I did the --> badword <-- NOT FOUND message instead. So don't be surprised if it seems to revert back to ??? because that is less invasive when we are typing whereas the NOT FOUND is useful during a TACHYON ...... END type load.
The parsing as you type is really compile as you type so you don't have to create a definition just to run "compile only" words as they work the same outside of a definition as they do inside, an example:
$80 BL DO I EMIT LOOP
Will execute immediately you hit the enter key without having to put this inside a definition.
BTW, You don't even need to hit ESC as it is quite happy just to continue on. Clearing the stack on an error seems to be a standard Forth thing but I always found it to be more of a nuisance, type type doh, retype retype doh and so on.
EDIT: The compile as you go approach also means I don't have to have a text input buffer large enough to accommodate the longest line, I only need a word buffer wide enough to accommodate the longest word (32 characters).
Everything works after the additional line between the TABLE definitions. I will remember/document about the comments and the release of the serial pin.
Thanks
Currently I am learning to use Tachyon and testing still with the calculator doing the FakeDMM thing. I have established communication and get the string in to the prop. The test string is "DC 4.321 V". I have written code to extract the numeric part of the string "4.321" or "-1.234", as the case may be, so I need to find the spaces. Of course I could just assume ;-) the result to always be positive and it would always be in the same place - easy. But I would rather make a more general method. And after I get the number as a string I will want to make it a number - don't know how yet - have ideas - surely been done before.
Here is the code and the problems: [ how do I put code in one of those nice little windows? ]
dmmbuf .STR DC 4.321 V ok
: .DMM
dmmbuf $20 STRING D$ \ assign DMM reading to D$
BL D$ LOCATE$ 1+ $20 STRING N$ \ drop left side of string before number
N$ DUP BL OVER LOCATE$ \ find trailing space
SWAP - LEFT$ \ drop all after number
N$ D$ COPY$
FORGET N$
;
Problems:
Won't run. Can't FORGET it. It places the strings in the dictionary before it is even executed. Arrrrh!
I can't declare a STRING in a definition so Peter will have the answer, but this does work so your logic is right
Pretty sure you could refactor one string and use the temporary buffers if memory is of concern.
"Add BUFFERS word which points to the 2K VM image (reusable as temporary buffers - do not backup as Tachyon will not be able to boot)"
About the forum formating, it uses BBCode and you can enter this directly or press the ADVANCED button down the bottom right of the edit window and you get a whole lot of other options. So when you paste code into the window then select that section and click the # button which will enclose the text in code tags.
The STRING word is a defining word, that is it creates a new defintion and the rule is that you do not create new definitions inside another one, so logically these should be defined before .DMM . So STRING and FORGET etc are all defining words that execute immediately even during compile so no Forth ever expects to use them in the way that you have defined .DMM
Anyway, you are doing it the hard way, all the parsing and conversion is built into TF, don't assemble the whole line into a buffer just parse it word by word (direct key input) and use GETWORD DECIMAL NUMBER when you are expecting data from the DMM. The AC/DC part of the message would also be handled by a preceding GETWORD and storing that result in a string like this GETWORD dmm$ COPY$ etc.
I could write the code for you but it is simpler than you think so I will let you have a bit more of a play with TF. Of couse if you have to have it in a bufffer to parse just remember that NUMBER will parse a string but define that string just like any variable or constant, outside of another defintion.
EDIT: You would never say in any Forth
: MyTest 1234 CONSTANT mycon mycon . ;
But of course you do it like this:
1234 CONSTANT mycon
: MyTest mycon . ;
So STRING is similar to CONSTANT and VARIABLE and so on. Even if the first example compiled somehow what would happend each time you ran it is that it would create another new definition called mycon, after testing that ten times you would have 10 new "mycons" in the dictionary, clearly not what you would want to happen.
BTW, any use of the BACKUP word is normally safe, it skips those areas it would never want to overwrite in EEPROM.
NickL
NUMBER in my version doesn't seem to work according to the comments in the Tachyon V2.3 source regarding valid conversion forms. Else my syntax is wrong?
NUMBER ' ( str -- value digits | false )
Acceptable forms are:
$1000 hex number
1000h
#1000 decimal number
1000d
%1000 binary number
1000b
While it is true that NUMBER will take a string from GETWORD and convert it, it does not appear to work with strings in general and this is simply because NUMBER is expecting a string with a preceding count as is used in GETWORD. It stills looks like a string, it's that it just happens to have the count of the string in the byte preceding it.
I may change the operation of NUMBER to work with strings in general but in the meantime this will work:
This is what works for me
Anyhow, getting back to allowing TF to make efficient use of it's hub memory without imposing extra hardware on the system other than using a 64kB EEPROM instead of the normal 32kB, I need to have any additional cog images out of the way but readily accessible at boot time. The logical place for this is in the top 32kB of the 64kB EEPROM where a boot-time program can load the images that are required into cogs without messing with hub memory. Since coginit requires the image to be in hub ram I just load the EEPROM image into the 2K buffer area vacated by the TF image. This would allow me to be able to load the floating-point image as well as others such as VGA, serial, etc into cogs while TF is booting. Of course these images could also reside on SD instead but that may not be present while EEPROM always is.
Does that scheme sound acceptable? Are there other cog objects that you would like? In the case of floating point I just use the PASM from F32 as would be the case with serial, VGA etc.
BTW, the image is initially loaded into EEPROM in a similar manner to extending the kernel, except we load a hex file.
EDIT: in the case of a VGA/TV text driver I could compile and load the module normally as I could reuse the image ram for the display buffer. But the EEPROM scheme is more flexible.
EDIT: Rather than a pure hex file I could use the listing generated by BST and paste that into my TF module source, that's uncomplicated and readable, and TF could just filter out the code it needs to load into EEPROM. There's lot's of information in the listing, here's a sample:
Have a look at what the hybrid source code document will look like, here's one here, it's unfinished but might work out.
The 4 serial ports is a good candidate too, but probably the best would be to have a small how to in order to implement our object or add an existing one.
Tell me if I'm wrong, but after all the 2 main configurations are the coprocessor style (where the pasm cog waits for the arguments and executes one of the possible operations) and the silently running, where the pasm code is doing its work independently, and in case shares data in and out via a HUB array.
If we were able to create the code we could be able to speed up the obex translation, and also adding our own pasm modules.
Massimo
DECIMAL ok
1 26 ADO CR ." fibo(" I . ." ) = " NEWCNT I fibo .LAP ." result =" . LOOP
fibo(1) = 11us result =1
fibo(2) = 12us result =1
fibo(3) = 13us result =2
fibo(4) = 14us result =3
fibo(5) = 15us result =5
fibo(6) = 16us result =8
fibo(7) = 17us result =13
fibo(8) = 18us result =21
fibo(9) = 19us result =34
fibo(10) = 20us result =55
fibo(11) = 21us result =89
fibo(12) = 22us result =144
fibo(13) = 23us result =233
fibo(14) = 24us result =377
fibo(15) = 25us result =610
fibo(16) = 26us result =987
fibo(17) = 27us result =1597
fibo(18) = 28us result =2584
fibo(19) = 29us result =4181
fibo(20) = 30us result =6765
fibo(21) = 31us result =10946
fibo(22) = 32us result =17711
fibo(23) = 33us result =28657
fibo(24) = 34us result =46368
fibo(25) = 35us result =75025
fibo(26) = 36us result =121393 ok
Based on the previous results I would say 1 long went a long way. As far as the F32 "hack" (the optimal way to connect a rotary phone switch to cause the best track switching to occur with the least fuss, "tech model railroad club") I can't wait to start using it. I agree with max72 it would be nice to be able to push our own "mods" this way but not necessary. I think F32 now gives Tachyon just about everything one could need. Telnet, FTP, HTTP, Sockets, Floating Point, Strings, RTC provisions, SD access, partial FAT16/32, I2C, SPI, ASync and best of all a console to rule them all! I was gathering UI needs from co-workers the other day and even they said "hey wait don't you have to go rebuild the software or something before you show us again" as I worked directly on the console as the equipment was running! Thanks Peter.
You need 256 longs for a table that can be used to store all the calculated duty cycles for 32 channels over 256 samples (8-bit). The init code looks like this:
The signed divide also runs faster from 47us down to 18us whereas the unsigned divide U/ takes 10us. The multiply ops take around 4 or 5 us.
Don't forget there's the serial LCD rolling odometer demo too.
Notice the online kernel has 5 MHz crytal settings now.
Looks good here.
Controlling individual pins or groups of pins is easy and of course you can always create your methods like these
75 % 2 SETPWM ( set P2 to 75% duty)
or
32 16 8 SETPWMS ( set P16..P23 to 32/256 duty cycle)
or you might like to specify the range like Spin in which case we could modify SETPWMS
32 16 23 SETPWMS
etc
These methods calculate the entries in a 1K byte table for all 256 samples of 32 channels which the PWM cog just reads from. So it's also possible to put arbitrary waveforms in the table too or even higher frequencies with less resolution, for instance if I set the channel bit in each alternate long I would have a 6.94kHz * 128 or 888.32kHz square wave on that pin (now 972.8kHz)
As mentioned earlier these PWM outputs are table based and jitter free.
7.6kHz 25% waveform
DECIMAL ok
1 26 ADO CR ." fibo(" I . ." ) = " NEWCNT I fibo .LAP ." result =" . LOOP
fibo(1) = 9us result =1
fibo(2) = 10us result =1
fibo(3) = 10us result =2
fibo(4) = 10us result =3
fibo(5) = 10us result =5
fibo(6) = 11us result =8
fibo(7) = 11us result =13
fibo(8) = 11us result =21
fibo(9) = 12us result =34
fibo(10) = 12us result =55
fibo(11) = 12us result =89
fibo(12) = 13us result =144
fibo(13) = 13us result =233
fibo(14) = 13us result =377
fibo(15) = 13us result =610
fibo(16) = 14us result =987
fibo(17) = 14us result =1597
fibo(18) = 14us result =2584
fibo(19) = 15us result =4181
fibo(20) = 15us result =6765
fibo(21) = 15us result =10946
fibo(22) = 16us result =17711
fibo(23) = 16us result =28657
fibo(24) = 16us result =46368
fibo(25) = 16us result =75025
fibo(26) = 17us result =121393 ok
Wow!!
I'm happy to have this speed without the need for C. And so much more!
But 7 code bytes IS impressive. What I am missing here is D.P.'s excitement over the speed. Heaters Fibo in compiled C finishes 26 iteration before TF does ONE?
Enjoy!
Mike
What's also very interesting is the loop time, if we look at the difference in timing between 1 and 26 iterations it is 17-9 for TF which is of course 8us vs GCC's 8us, the same! So not having the cog dedicated to a benchmark means the other 9us is spent in TF coming from doing something useful, calling the function, stacking the parameters, unstacking, and returning back to something useful again up to 17us later. Oh well.....
EDIT: just thinking about this abysmal 17us to run a fibo(26), I think Spin could almost run one and a half bytecode instructions in this same amount of time!
One (GCC) is a compiled to benchmark one off program, does nothing more.
The other is able to run along side FTP, HTTP, TELNET, SD CARD and console access in ONE cog! I thought that the TF fibo just being 9 us slower than the almighty GCC was fantastic, but now I understand it runs at the same speed. Do you understand?
17-9=8. Did not look at it this way. Sad that me and forth do not get along. Seems my brain is indoctrinated by non prefix languages. I tried but cant wrap my head around it.
Enjoy!
Mike
Ah, I see Mike, you can't wrap your head around it, but I see from your avatar that perhaps your head's bin rappin' da PC C.
It's so much more fun that way hey? Whereas my avatar (which btw is reproducible on the serial terminal -prop) is going yabba dabba doo!
My first languages were "machine code", assembler, Basic, even Fortran, then C, with my introduction to Forth in there somewhere.
You got me curious ... how to display your Avatar on a serial terminal? Or did you mean to display "yabba dabba doo"?
I do use different languages also, my last fulltime Cobol Job was somewhere at the end of the last century. Over the years I needed usually to change the Language when changing the Job. But say switching from VB.net to C#.net is not a really big task, the framework stays the same, just the syntax varies a bit. Things like C might be no big thing either - I hadn't had the need for yet. Since a couple of weeks I use JavaScript since @Heater talked me into it, but all of those languages are very alike in the way they handle stuff. Forth is quite different.
As to my Avatar ... that picture was probably taken while I was trying to understand FORTH.
Enjoy!
Mike
It was incredibly hard for me at first. Now it's fun. Hairless monkeys hate "to change", confirmation bias and peer packing can ruin the mind.
Good come back Mike, hi5!
My avatar was taken from an ANSI graphics that I would display on compatible terminals, such as TeraTerm, even Hyperterminal. I will post a special edition of EXTEND.fth which will test to see if the terminal is compatible and then display my avatar on boot. In fact I can even test the terminal's baud rate settings etc to automatically adapt.
EDIT: Didn't want to make a new post but I shaved a few more microseconds from my fibo, still going for more:
fibo(22) = 12us result =17711
fibo(23) = 12us result =28657
fibo(24) = 13us result =46368
fibo(25) = 13us result =75025
fibo(26) = 13us result =121393
and
fibo(46) = 19us result =1836311903 ok
kuroneko has written fibo in PASM and gets 3.6us for fibo(46)
Anyone who is using TeraTerm or Hyperterminal can compile the latest kernel and EXTEND.fth and my avatar should appear on boot. My minicom doesn't handle these characters properly but I still need to fully activate the automatic terminal test software so that it only displays on compatible terminals.
Here are some of the latest fibonacci results:
fibo(2) = 6us result =1
fibo(3) = 6us result =2
fibo(23) = 12us result =28657
fibo(24) = 13us result =46368
fibo(25) = 13us result =75025
fibo(26) = 13us result =121393
fibo(46) = 19us result =1836311903 ok