So we almost have an NMEA parser... :-)
Great stuff.
That's not hard at all, there are several different approaches but if we just try to process it naturally it looks a bit like this (terminal session):
[FONT=courier new]LONG lat,lon,alt ok
ok
: S NEGATE
: N lat ! ; ok
: W NEGATE
: E lon ! ; ok
: M alt ! ; ok
ok
BYTE gpssum ok
: ?GPS word C@ "*" = IF word 1+ NUMBER DROP gpssum C! THEN ; ok
: GPGGA DECIMAL ' ?GPS unum W! ; IMMEDIATE ok
"," delim C! ok
ok
[B]GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47[/B] ok
ok
( Horz dilution ) . 9 ok
( Satellites ) . 8 ok
( Fix quality ) . 1 ok
( UTC ) . 123519 ok
ok
lat @. 4807038 ok
lon @. 1131000 ok
alt @. 469 ok
gpssum C@ . 47 ok
[/FONT]
Of course it's not quite perfect but that's just a bit of Q&D code. I stripped the $ symbol first as $GPPGA was resolving as $A or 10, so that's something I might fix up in my number preprocessor but the ideas there. It would pay to have the decimal places latched so that this could be used as well.
EDIT: actually it's possible to execute postfix fashion so that we can also grab and store the other parameters like this:
[FONT=courier new]LONG lat,lon,alt
LONG sum,horz,sats,fix,utc
: S NEGATE
: N lat ! ;
: W NEGATE
: E lon ! ;
: M alt ! ;
: ?GPS word C@ "*" = IF word 1+ NUMBER DROP sum ! THEN ;
: &GPGGA horz ! sats ! fix ! utc ! prompt W~ ;
: GPGGA DECIMAL ' ?GPS unum W! ' &GPGGA prompt W! ; IMMEDIATE
"," delim C!
\ our sample data
GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
\ report what we found
lat @.
lon @.
alt @.
sum @.
horz @.
sats @.
fix @.
utc @.
{ which looks like this:
lat @. 4807038 ok
lon @. 1131000 ok
alt @. 469 ok
sum @. 47 ok
horz @. 9 ok
sats @. 8 ok
fix @. 1 ok
utc @. 123519 ok
}
[/FONT]
Peter - if one were worried about malicious inputs, would it be easy to limit the dictionary to NMEA words while parsing input in the manner that you show above?
Peter - if one were worried about malicious inputs, would it be easy to limit the dictionary to NMEA words while parsing input in the manner that you show above?
Yes, you can indeed and it's a very easy thing to do of course with one of the ways simply to have a control word/passphrase which terminates the dictionary links early. I need to do the same with Ethernet servers so I will probably build in something just for this as well as vocabulary support.
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 ;
New code for GETDMM.fth
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^(negate(scalefact))
LONG dmmval \ store the dmmvalue
BYTE av \ 0 = volts, -1 = amperes \ current or voltage
: DC acdc C~ ; \ first word from input stream is run and specifies the type of reading
: AC acdc C~~ ; \ in this case DC or AC
: mA DPL 3 + scalefact ! av C~~ dmmval ! ; \ second work from input stream is the quantity read by the meter and is
: uA DPL 6 + scalefact ! av C~~ dmmval ! ; \ processed based on the third word, in this case mA or uA
: mV DPL 3 + scalefact ! av C~ dmmval ! ; \ scalefact is postive rather than negative to agree with output of DPL
: uV DPL 6 + scalefact ! av C~ dmmval ! ; \ when reconstituting reading negate scalefact
That's good, it looks like there is a lot of common functionality being duplicated there though. How about this?
[FONT=courier new]: SCALE ( val scale av -- ) av C! DPL + scalefact ! dmmval ! ;
: mA 3 1 SCALE ; \ second work from input stream is the quantity read by the meter and is
: uA 6 1 SCALE ; \ processed based on the third word, in this case mA or uA
: mV 3 0 SCALE ; \ scalefact is postive rather than negative to agree with output of DPL
: uV 6 0 SCALE ; \ when reconstituting reading negate scalefact
[/FONT]
That's good, it looks like there is a lot of common functionality being duplicated there though. How about this?
[FONT=courier new]: SCALE ( val scale av -- ) av C! DPL + scalefact ! dmmval ! ;
: mA 3 1 SCALE ; \ second work from input stream is the quantity read by the meter and is
: uA 6 1 SCALE ; \ processed based on the third word, in this case mA or uA
: mV 3 0 SCALE ; \ scalefact is postive rather than negative to agree with output of DPL
: uV 6 0 SCALE ; \ when reconstituting reading negate scalefact
[/FONT]
Page 67 of this thread causes my head to hurt in a great way.
So we almost have an NMEA parser... :-)
Great stuff.
Epiphany! I've been trying to parse out raw GPS data for a total of three weeks now...figurative reams of paper that can fit on a postcard. That's one of the things I love about Forth...I'm just encumbered with several decades of "bad" habits from other programming languages.
I spent the last three weeks slammed in preparation for the Seattle Mini MakerFaire, and one of the main items we presented showcased Tachyon as a key part. I got lots of wows when I amateurishly and briefly explained Tachyon (even from some pretty militant Arduino developers).
I agree with D.P - it makes my head hurt in a good way too - kind of a 2x4 to the forehead, showing a huge paradigm I never conceived of questioning.
That's good, it looks like there is a lot of common functionality being duplicated there though. How about this?
That is sweet. Here it is incorporated with the rest:
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^(negate(scalefact))
LONG dmmval \ store the dmmvalue
BYTE av \ 0 = volts, -1 = amperes \ current or voltage
: DC acdc C~ ; \ first word from input stream is run and specifies the type of reading
: AC acdc C~~ ; \ in this case DC or AC
: SCALE ( val scale av -- ) av C! DPL + scalefact ! dmmval ! ;
: mA 3 1 SCALE ; \ second word from input stream is the quantity read by the meter and is
: uA 6 1 SCALE ; \ processed based on the third word, in this case mA or uA
: mV 3 0 SCALE ; \ scalefact is postive rather than negative to agree with output of DPL
: uV 6 0 SCALE ; \ when reconstituting reading negate scalefact
It was fun and quite an education to whip the "dmmval" word into shape but then I returned to the task of actually getting the reading from the DMM via the serial port instead of pasting the string to the console input.
Problem #1: After switching the input stream to the serial port, how is input different from the console via typing or pasting?
: GETDMM \ get reading from DMM, sends CR to trigger response, gets bytes until CR
DMMIO \ redirect I/O to DMM
#13 EMIT \ send request for data
\ ?? what has to happen here ??
CON \ return I/O to console
;
Problem #2: I had forgotten that with this meter the string is transmitted as 7-bits data 2-stop bits and thus arrives with the high bit of each byte set. Is it possible to clear the high bit for the whole string or must it be done byte by byte?
Ouch! Still not "there".
Just to be clear. As I did earlier I can load the input into a string with the high bit stripped if necessary but how is it then "fed" into Forth's wonderful word processor.
Since WAITLOW has been ' commented out and replaced with WAITHILO as per the kernel source, for some reason it won't resolve in the dictionary?
Also I have a peripheral (like artkennedy) that needs async comms. I guess the best approach is to use a seperate cog for async Rx (SERIN, which blocks) and "share" the data.
That is sweet. Here it is incorporated with the rest:
Problem #2: I had forgotten that with this meter the string is transmitted as 7-bits data 2-stop bits and thus arrives with the high bit of each byte set. Is it possible to clear the high bit for the whole string or must it be done byte by byte?
Ouch! Still not "there".
Just to be clear. As I did earlier I can load the input into a string with the high bit stripped if necessary but how is it then "fed" into Forth's wonderful word processor.
What should happen is that GETDMM should not bother returning to the console via CON, rather it should stay in DMMIO and you can add a CON to the end of SCALE so that it's all complete and automatic.
Now it would help if you posted your complete code but I looked back in the thread and found this definition : INfmDMM #22 SERIN ; which is the revectored KEY routine set by DMMIO.
What this should do is strip the 8th bit at that time so that you have #22 SERIN $7F AND so that Forth just finds normal characters.
So SCALE ends up being av C! DPL + scalefact ! dmmval ! and GETDMM is just DMMIO #13 EMIT without the CON.
That should work nicely and later on you could even add a timeout to return to the console in case the meter is not responding.
Since WAITLOW has been ' commented out and replaced with WAITHILO as per the kernel source, for some reason it won't resolve in the dictionary?
Also I have a peripheral (like artkennedy) that needs async comms. I guess the best approach is to use a seperate cog for async Rx (SERIN, which blocks) and "share" the data.
Try (WAITHILO) instead as it does not use the stack but needs a mask in COGREG3 and returns the count in COGREG0. It uses (WAITPNE) and (WAITPEQ).
For asynch I've just been using SERIN running in it's own cog so that it stores to a buffer and does whatever it needs to do.
[FONT=courier new]
WORD rxrd,rxwr
#128 == rxsize
rxsize BYTES buf232
12 LONGS stack232
\ Buffer data from the RS232 port - nothing else
pub RS232.TASK
stack232 SP! !SP
#9600 SERBAUD
rxrd W~ rxwr W~ buf232 rxsize ERASE
BEGIN
9 SERIN rxwr W@ rxsize 1- AND buf232 + C! rxwr W++
AGAIN
;
\ You can read the buffered data with this
pub GET232 ( -- ch|0 )
rxrd W@ rxsize 1- AND rxwr W@ rxsize 1- AND <>
IF
rxrd W@ rxsize 1- AND buf232 + C@
rxrd W++
ELSE 0
THEN
;
[/FONT]
I may just integrate a serial port module into TF but it just hasn't been pressing enough, I was basically waiting until I implement my PASM module loader which holds a library of objects in EEPROM (or SD) and you just pick and choose at runtime by module name.
Having done a tour of duty with Sal's PropForth and Dave Hein's pfth, I am now willing to join the fun with Tachyon.
Along the way, studied eForth's idea of how to create an inner and outer interpreter for any microcontroller.
About all, I have learned that Forth on 8 cogs is light years ahead of any other chip, including Chuck Moore's GA144 (of which I have two).
It has been a rather long journey to get here, but I really have enjoyed it all. So now I am going to try to get a Funduino I2C to LCD up and running in Tackyon. I get I have to port an Arduino library into Tackyon Forth.
So if we wanted to input our serial stream to the Tachyon interpreter in the RS232.TASK how would we revector the input so we could parse let's say the NMEA string example in that cog? I.E. the RS232.TASK cog is accepting the serial input from the gps module and parsing the strings? Here they be dragons.
So if we wanted to input our serial stream to the Tachyon interpreter in the RS232.TASK how would we revector the input so we could parse let's say the NMEA string example in that cog? I.E. the RS232.TASK cog is accepting the serial input from the gps module and parsing the strings? Here they be dragons.
Let's just say that we leave that other cog to just buffer the data and then we have the main cog switch it's input to the buffered serial stream as if we were typing it in from the console. This isn't any different then what FLOAD does for instance, in that it opens a file, then redirects console input to FGET reading in a byte at a time from the file "stream" vs the RS232 "stream".
Having done a tour of duty with Sal's PropForth and Dave Hein's pfth, I am now willing to join the fun with Tachyon.
Along the way, studied eForth's idea of how to create an inner and outer interpreter for any microcontroller.
About all, I have learned that Forth on 8 cogs is light years ahead of any other chip, including Chuck Moore's GA144 (of which I have two).
It has been a rather long journey to get here, but I really have enjoyed it all. So now I am going to try to get a Funduino I2C to LCD up and running in Tackyon. I get I have to port an Arduino library into Tackyon Forth.
Should be fun.
Sorry to say this but as brilliant as Chuck is he should just work at some pure research establishment as I rarely see any of his designs as being practical, whereas he started off as extremely practical. The GA144 is a case in point, while it's a fun project to get 144 micro-CPUs onto one chip it is a nightmare to get it to do anything useful. If in doubt then have a look at the appnotes and software downloads, or more correctly the almost entire lack or usefulness of them. Even if they got 10baseT working if ever then what's the point?
Now to be a little tacky Loo Pee even though it's pronounced the same way, you know it's Tachyon as in Tachometer etc
As for the I2C LCD it looks like it might just be a dumb 8-bit I/O expander so just make sure you write the low-level routines so that it looks like the software is just talking directly to the display, and of course there is never ever any need to read the busy bit. Then you can use as much of my character LCD code as you want.
So if we wanted to input our serial stream to the Tachyon interpreter in the RS232.TASK how would we revector the input so we could parse let's say the NMEA string example in that cog? I.E. the RS232.TASK cog is accepting the serial input from the gps module and parsing the strings? Here they be dragons.
Recovering from the whiplash thanks to artkennedy's DMM pursuit. There's a demolished paradigm I didn't even notice.
Looking at NMEA sentence parsing, would it be better to strip the "$" from the sentences while following D.P's stream of thought, or seeking some kind of exception for NMEA sentences...$GPGGA, $GPGSA, $GPRMC are all very common NMEA sentences, and will be interpreted as $A or $C. I'm assuming that Peter had a good reason to screen for numbers before commands (small fix may break much more).
Sorry to say this but as brilliant as Chuck is he should just work at some pure research establishment as I rarely see any of his designs as being practical, whereas he started off as extremely practical. The GA144 is a case in point, while it's a fun project to get 144 micro-CPUs onto one chip it is a nightmare to get it to do anything useful. If in doubt then have a look at the appnotes and software downloads, or more correctly the almost entire lack or usefulness of them. Even if they got 10baseT working if ever then what's the point?
Now to be a little tacky Loo Pee even though it's pronounced the same way, you know it's Tachyon as in Tachometer etc
As for the I2C LCD it looks like it might just be a dumb 8-bit I/O expander so just make sure you write the low-level routines so that it looks like the software is just talking directly to the display, and of course there is never ever any need to read the busy bit. Then you can use as much of my character LCD code as you want.
A. Chuck Moore's GA144 is indeed a dismal failure.
But it does make Forth on the Propeller absolutely brilliant. Where he failed, Chip Gracy has excelled in creating an excellent Forth microcontroller, and it appears to be an unintentional development.
B. The Funzino I2C to LCD certainly does appear to be a generic I2C port expander with some added features on the tiny board (power take off for back-lighting the LCD, contrast adjustment, and jumpers for addressing multiple units).
The underlying chip is a PCF8574 and Johnny Mac just provided some Spin code for it. That is a big help as the Arduino library stuff is harder for me to understand.
Recovering from the whiplash thanks to artkennedy's DMM pursuit. There's a demolished paradigm I didn't even notice.
Looking at NMEA sentence parsing, would it be better to strip the "$" from the sentences while following D.P's stream of thought, or seeking some kind of exception for NMEA sentences...$GPGGA, $GPGSA, $GPRMC are all very common NMEA sentences, and will be interpreted as $A or $C. I'm assuming that Peter had a good reason to screen for numbers before commands (small fix may break much more).
Unless I had a ultra-fast dictionary search method the number preprocessor does certainly speed up compilation speeds otherwise all numbers suffer from an exhaustive dictionary search first. Although I have fairly lax rules regarding number format I think I would like at least one decimal digit or a leading zero to make it acceptable as a number, so $A would not be a number but $0A would.
Therefore $GPGGA etc will not be accepted as numbers and so a match in the dictionary would be found. Yes, it is possible to just strip the $ from the sentence but I'm not altogether happy with $GPGGA being processed as a number because it doesn't look anything like one. Maybe I might even only allow symbols mixed in # type decimal numbers as come to think of it I never mix symbols with hex numbers.
Let's just say that we leave that other cog to just buffer the data and then we have the main cog switch it's input to the buffered serial stream as if we were typing it in from the console. This isn't any different then what FLOAD does for instance, in that it opens a file, then redirects console input to FGET reading in a byte at a time from the file "stream" vs the RS232 "stream".
So give this snippet:
WORD rxrd,rxwr
#128 == rxsize
rxsize BYTES buf232
12 LONGS stack232
#11 == prx
\ Buffer data from the RS232 port - nothing else
pub RS232.TASK
stack232 SP! !SP \ init data stack to 0, assign stack to this task
#9600 SERBAUD \ how fast are we going
rxrd W~ rxwr W~ buf232 rxsize ERASE \ clear rxrd, rxwr and erase buf232
BEGIN
prx SERIN rxwr W@ \ get serial byte, fetch rxwr buf232 index( -- 0 datadr )
rxsize 1- AND buf232 + C! \ compute buf232 addr and write data to buffer
rxwr W++ \ increment buffer pointer
AGAIN
;
\ You can read the buffered data with this
pub GET232 ( -- ch|0 )
rxrd W@ rxsize 1- AND rxwr W@ rxsize 1- AND <> \ compute if the buffer is empty
IF
rxrd W@ rxsize 1- AND buf232 + C@
rxrd W++
ELSE 0
THEN
;
\ We can do this
pub start232 ' RS232.TASK 4 RUN ;
pub getstream ' GET232 ukey ! ;
start232
100 ms
getstream
It can't be that easy? Really? If so no wonder I'm confused, constantly over engineering the solution. Seem though GET232 needs to return nothing if the buffer is empty?
Unless I had a ultra-fast dictionary search method the number preprocessor does certainly speed up compilation speeds otherwise all numbers suffer from an exhaustive dictionary search first. Although I have fairly lax rules regarding number format I think I would like at least one decimal digit or a leading zero to make it acceptable as a number, so $A would not be a number but $0A would.
Kind of what I guessed-creating a big problem to fix an otherwise small one, creating a notable performance sag while trying to fix a niche problem.
Therefore $GPGGA etc will not be accepted as numbers and so a match in the dictionary would be found. Yes, it is possible to just strip the $ from the sentence but I'm not altogether happy with $GPGGA being processed as a number because it doesn't look anything like one. Maybe I might even only allow symbols mixed in # type decimal numbers as come to think of it I never mix symbols with hex numbers.
I like the ability to use #PIN8, and am pretty sure we have a notable number of projects among the forum that would be affected by changing decimal processing. This may be tunnel vision on my (our) part, but I can see using the alpha prefixes in decimals (like #PIN8) massively more useful and common than in HEX, if it is used at all in HEX Anyone please chime in if you do this with HEX numbers. Pushing my limits of logic, I could see annotating a group of IOs like Global Pin Group "G" Pin A => $GPGGA, but that seems more like creating an excuse than really being practical...
If no one is prefixing their HEX numbers like #PIN8 (I would definately use #PIN10 rather than $PINA), I'd think that it would speed up preprocessing globally to eliminate this as part of permissible number formats (assuming there's not some magic/logic/strategy in the preprocessor I'm missing) and leaving the decimal preprocessing alone. I wouldn't mind needing to change from #PIN8 to #PIN08 on my stack of projects as I need to, but certainly don't want to force everyone unless it's more than my drooling over NMEA that is spawning it.
Requiring a change from Global Pin Group "G" Pin A => $GPGGA to $GPGG0A seems like it'd be a small sacrifice to open up NMEA communications! NMEA is the (American) National Marine Electronics Association, all of their protocols prefix their sentences with "$," and they standardize communications for GPS, depth finders, SONAR, some radio equipment, weather monitoring, on-ship radar just to name a few technologies, and NMEA is THE standard if any is selected for any of these types of devices.
EDIT: Dropbox files are up-to-date and I have created a FRUNS folder where these files can be copied to the SD card and are useful when you have a fully loaded system. It feels a bit like running batch files from floppy
There's been quite a few improvements on many fronts and some not so obvious. The network servers have been fixed up as there was a problem with the disconnection procedure but I believe that is sorted out now, it seems to run smoothly from remote sites. I have even been using ftp from the browser just as you enter ftp://tachyonforth.com it will come up with a file listing etc. Mind you I still intend to leave a Prop server running permanently although at present this system is under tests and constantly being bombarded by bing bots.
There are so many things to list but one of the things that I have been looking at doing is extending TF code into the SD file system. Well it turns out that there is a very very simple mechanism where if I type in a word that's unknown that it fails the dictionary search, the number conversion and finally bombs to an exception vector, which if set can find and open it as a file name and input it into TF. This may mean it is a simple script or it compiles a definition and runs it. For instance when I create a small build of EXTEND.fth there are some words that have been left out that I would like to use sometimes but I can't afford to have them hogging the little hub memory that remains.
So using a simple definition FRUN and tying to the exception vector then typing the unknown TASKS word automatically does what I need it to do:
[FONT=courier new]pub FRUN word FOPEN$ IF FINPUT THEN ; ok
ok
' FRUN unum W! ok
ok
[B]TASKS[/B] ok
[~ ok
.TASKS
0001: CONSOLE 0000 00 00 00 00 00 00
0002: IDLE 0000 01 00 00 00 00 00
0003: IDLE 0000 01 00 00 00 00 00
0004: IDLE 0000 01 00 00 00 00 00
0005: IDLE 0000 01 00 00 00 00 00
0006: RS232.TASK 51F4 01 00 00 00 00 00
0007: TIMERTASK 24F4 01 00 00 00 00 00 ok
FORGET .TASKS ok
[/FONT]
and so with MAP which is only ever used from the console rarely:
I will no doubt make this more general and may even allow precompiled code to run from the file system. There are a lot of diagnostics and "shell" commands that are well suited to this approach which will allow me to cram even more functionality into TF that goes beyond 32K.
EDIT: If I type .MAP which ends up searching the dictionary, number processing, file searching, loading, compiling, running (including scanning 32K hub RAM), then forgetting the functions just compiled, the whole process takes less than a second.
EDIT: What this automatic file search mechanism allows is that I can load code simply by typing the modules name, I no longer need to specifically type FLOAD <name>, now I just type <name>.
EDIT: Dropbox files are up-to-date and I have created a FRUNS folder where these files can be copied to the SD card and are useful when you have a fully loaded system. It feels a bit like running batch files from floppy
There's been quite a few improvements on many fronts and some not so obvious. The network servers have been fixed up as there was a problem with the disconnection procedure but I believe that is sorted out now, it seems to run smoothly from remote sites. I have even been using ftp from the browser just as you enter ftp://tachyonforth.com it will come up with a file listing etc. Mind you I still intend to leave a Prop server running permanently although at present this system is under tests and constantly being bombarded by bing bots.
There are so many things to list but one of the things that I have been looking at doing is extending TF code into the SD file system. Well it turns out that there is a very very simple mechanism where if I type in a word that's unknown that it fails the dictionary search, the number conversion and finally bombs to an exception vector, which if set can find and open it as a file name and input it into TF. This may mean it is a simple script or it compiles a definition and runs it. For instance when I create a small build of EXTEND.fth there are some words that have been left out that I would like to use sometimes but I can't afford to have them hogging the little hub memory that remains.
So using a simple definition FRUN and tying to the exception vector then typing the unknown TASKS word automatically does what I need it to do:
[FONT=courier new]pub FRUN word FOPEN$ IF FINPUT THEN ; ok
ok
' FRUN unum W! ok
ok
[B]TASKS[/B] ok
[~ ok
.TASKS
0001: CONSOLE 0000 00 00 00 00 00 00
0002: IDLE 0000 01 00 00 00 00 00
0003: IDLE 0000 01 00 00 00 00 00
0004: IDLE 0000 01 00 00 00 00 00
0005: IDLE 0000 01 00 00 00 00 00
0006: RS232.TASK 51F4 01 00 00 00 00 00
0007: TIMERTASK 24F4 01 00 00 00 00 00 ok
FORGET .TASKS ok
[/FONT]
and so with MAP which is only ever used from the console rarely:
I will no doubt make this more general and may even allow precompiled code to run from the file system. There are a lot of diagnostics and "shell" commands that are well suited to this approach which will allow me to cram even more functionality into TF that goes beyond 32K.
EDIT: If I type .MAP which ends up searching the dictionary, number processing, file searching, loading, compiling, running (including scanning 32K hub RAM), then forgetting the functions just compiled, the whole process takes less than a second.
EDIT: What this automatic file search mechanism allows is that I can load code simply by typing the modules name, I no longer need to specifically type FLOAD <name>, now I just type <name>.
Very nice indeed, this will allow the SMALL build of EXTEND to get SMALL-ER. Lots of user code could be run in this fashion as well! Now TACHYON can pack around 2gigs worth of utilities/examples, erh that ought to be enough? Time for me to write a few TACHYON "shell" scripts, thanks Peter
I just had a quick look at this chip but it looks very straightforward to configure and read. Have you tried to at all?
The general form of writing to this would be:
pub AD! ( byte reg -- ) I2CSTART $40 I2C! I2C! I2C! I2CSTOP ;
pub AD@ ( reg -- byte ) I2CSTART $40 I2C! I2C! I2CSTART $41 I2C! 1 I2C@ ;
I just had a quick look at this chip but it looks very straightforward to configure and read. Have you tried to at all?
The general form of writing to this would be:
pub AD! ( byte reg -- ) I2CSTART $40 I2C! I2C! I2C! I2CSTOP ;
pub AD@ ( reg -- byte ) I2CSTART $40 I2C! I2C! I2CSTART $41 I2C! 1 I2C@ ;
I was confused from the data sheet: Because it is the register to which the first data byte of every write operation is written automatically, the address pointer register does not have an address and does not reqire an address.
I have frobbed at the chip a bit, I will continue to do so.
Comments
Great stuff.
That's not hard at all, there are several different approaches but if we just try to process it naturally it looks a bit like this (terminal session):
Of course it's not quite perfect but that's just a bit of Q&D code. I stripped the $ symbol first as $GPPGA was resolving as $A or 10, so that's something I might fix up in my number preprocessor but the ideas there. It would pay to have the decimal places latched so that this could be used as well.
EDIT: actually it's possible to execute postfix fashion so that we can also grab and store the other parameters like this:
Great stuff...
Massimo
Yes, you can indeed and it's a very easy thing to do of course with one of the ways simply to have a control word/passphrase which terminates the dictionary links early. I need to do the same with Ethernet servers so I will probably build in something just for this as well as vocabulary support.
New code for GETDMM.fth
That's good, it looks like there is a lot of common functionality being duplicated there though. How about this?
Page 67 of this thread causes my head to hurt in a great way.
thanks peter
Why? Did you print it out and try to stick it in your ear? Remember, nothing smaller than a elbow.
Link?
Epiphany! I've been trying to parse out raw GPS data for a total of three weeks now...figurative reams of paper that can fit on a postcard. That's one of the things I love about Forth...I'm just encumbered with several decades of "bad" habits from other programming languages.
I spent the last three weeks slammed in preparation for the Seattle Mini MakerFaire, and one of the main items we presented showcased Tachyon as a key part. I got lots of wows when I amateurishly and briefly explained Tachyon (even from some pretty militant Arduino developers).
I agree with D.P - it makes my head hurt in a good way too - kind of a 2x4 to the forehead, showing a huge paradigm I never conceived of questioning.
Problem #1: After switching the input stream to the serial port, how is input different from the console via typing or pasting? Problem #2: I had forgotten that with this meter the string is transmitted as 7-bits data 2-stop bits and thus arrives with the high bit of each byte set. Is it possible to clear the high bit for the whole string or must it be done byte by byte?
Ouch! Still not "there".
Just to be clear. As I did earlier I can load the input into a string with the high bit stripped if necessary but how is it then "fed" into Forth's wonderful word processor.
Also I have a peripheral (like artkennedy) that needs async comms. I guess the best approach is to use a seperate cog for async Rx (SERIN, which blocks) and "share" the data.
What should happen is that GETDMM should not bother returning to the console via CON, rather it should stay in DMMIO and you can add a CON to the end of SCALE so that it's all complete and automatic.
Now it would help if you posted your complete code but I looked back in the thread and found this definition : INfmDMM #22 SERIN ; which is the revectored KEY routine set by DMMIO.
What this should do is strip the 8th bit at that time so that you have #22 SERIN $7F AND so that Forth just finds normal characters.
So SCALE ends up being av C! DPL + scalefact ! dmmval ! and GETDMM is just DMMIO #13 EMIT without the CON.
That should work nicely and later on you could even add a timeout to return to the console in case the meter is not responding.
Try (WAITHILO) instead as it does not use the stack but needs a mask in COGREG3 and returns the count in COGREG0. It uses (WAITPNE) and (WAITPEQ).
For asynch I've just been using SERIN running in it's own cog so that it stores to a buffer and does whatever it needs to do.
I may just integrate a serial port module into TF but it just hasn't been pressing enough, I was basically waiting until I implement my PASM module loader which holds a library of objects in EEPROM (or SD) and you just pick and choose at runtime by module name.
Along the way, studied eForth's idea of how to create an inner and outer interpreter for any microcontroller.
About all, I have learned that Forth on 8 cogs is light years ahead of any other chip, including Chuck Moore's GA144 (of which I have two).
It has been a rather long journey to get here, but I really have enjoyed it all. So now I am going to try to get a Funduino I2C to LCD up and running in Tackyon. I get I have to port an Arduino library into Tackyon Forth.
Should be fun.
Let's just say that we leave that other cog to just buffer the data and then we have the main cog switch it's input to the buffered serial stream as if we were typing it in from the console. This isn't any different then what FLOAD does for instance, in that it opens a file, then redirects console input to FGET reading in a byte at a time from the file "stream" vs the RS232 "stream".
Sorry to say this but as brilliant as Chuck is he should just work at some pure research establishment as I rarely see any of his designs as being practical, whereas he started off as extremely practical. The GA144 is a case in point, while it's a fun project to get 144 micro-CPUs onto one chip it is a nightmare to get it to do anything useful. If in doubt then have a look at the appnotes and software downloads, or more correctly the almost entire lack or usefulness of them. Even if they got 10baseT working if ever then what's the point?
Now to be a little tacky Loo Pee even though it's pronounced the same way, you know it's Tachyon as in Tachometer etc
As for the I2C LCD it looks like it might just be a dumb 8-bit I/O expander so just make sure you write the low-level routines so that it looks like the software is just talking directly to the display, and of course there is never ever any need to read the busy bit. Then you can use as much of my character LCD code as you want.
Recovering from the whiplash thanks to artkennedy's DMM pursuit. There's a demolished paradigm I didn't even notice.
Looking at NMEA sentence parsing, would it be better to strip the "$" from the sentences while following D.P's stream of thought, or seeking some kind of exception for NMEA sentences...$GPGGA, $GPGSA, $GPRMC are all very common NMEA sentences, and will be interpreted as $A or $C. I'm assuming that Peter had a good reason to screen for numbers before commands (small fix may break much more).
A. Chuck Moore's GA144 is indeed a dismal failure.
But it does make Forth on the Propeller absolutely brilliant. Where he failed, Chip Gracy has excelled in creating an excellent Forth microcontroller, and it appears to be an unintentional development.
B. The Funzino I2C to LCD certainly does appear to be a generic I2C port expander with some added features on the tiny board (power take off for back-lighting the LCD, contrast adjustment, and jumpers for addressing multiple units).
The underlying chip is a PCF8574 and Johnny Mac just provided some Spin code for it. That is a big help as the Arduino library stuff is harder for me to understand.
I may have something working soon.
Unless I had a ultra-fast dictionary search method the number preprocessor does certainly speed up compilation speeds otherwise all numbers suffer from an exhaustive dictionary search first. Although I have fairly lax rules regarding number format I think I would like at least one decimal digit or a leading zero to make it acceptable as a number, so $A would not be a number but $0A would.
Therefore $GPGGA etc will not be accepted as numbers and so a match in the dictionary would be found. Yes, it is possible to just strip the $ from the sentence but I'm not altogether happy with $GPGGA being processed as a number because it doesn't look anything like one. Maybe I might even only allow symbols mixed in # type decimal numbers as come to think of it I never mix symbols with hex numbers.
It can't be that easy? Really? If so no wonder I'm confused, constantly over engineering the solution. Seem though GET232 needs to return nothing if the buffer is empty?
Kind of what I guessed-creating a big problem to fix an otherwise small one, creating a notable performance sag while trying to fix a niche problem.
I like the ability to use #PIN8, and am pretty sure we have a notable number of projects among the forum that would be affected by changing decimal processing. This may be tunnel vision on my (our) part, but I can see using the alpha prefixes in decimals (like #PIN8) massively more useful and common than in HEX, if it is used at all in HEX Anyone please chime in if you do this with HEX numbers. Pushing my limits of logic, I could see annotating a group of IOs like Global Pin Group "G" Pin A => $GPGGA, but that seems more like creating an excuse than really being practical...
If no one is prefixing their HEX numbers like #PIN8 (I would definately use #PIN10 rather than $PINA), I'd think that it would speed up preprocessing globally to eliminate this as part of permissible number formats (assuming there's not some magic/logic/strategy in the preprocessor I'm missing) and leaving the decimal preprocessing alone. I wouldn't mind needing to change from #PIN8 to #PIN08 on my stack of projects as I need to, but certainly don't want to force everyone unless it's more than my drooling over NMEA that is spawning it.
Requiring a change from Global Pin Group "G" Pin A => $GPGGA to $GPGG0A seems like it'd be a small sacrifice to open up NMEA communications! NMEA is the (American) National Marine Electronics Association, all of their protocols prefix their sentences with "$," and they standardize communications for GPS, depth finders, SONAR, some radio equipment, weather monitoring, on-ship radar just to name a few technologies, and NMEA is THE standard if any is selected for any of these types of devices.
There's been quite a few improvements on many fronts and some not so obvious. The network servers have been fixed up as there was a problem with the disconnection procedure but I believe that is sorted out now, it seems to run smoothly from remote sites. I have even been using ftp from the browser just as you enter ftp://tachyonforth.com it will come up with a file listing etc. Mind you I still intend to leave a Prop server running permanently although at present this system is under tests and constantly being bombarded by bing bots.
There are so many things to list but one of the things that I have been looking at doing is extending TF code into the SD file system. Well it turns out that there is a very very simple mechanism where if I type in a word that's unknown that it fails the dictionary search, the number conversion and finally bombs to an exception vector, which if set can find and open it as a file name and input it into TF. This may mean it is a simple script or it compiles a definition and runs it. For instance when I create a small build of EXTEND.fth there are some words that have been left out that I would like to use sometimes but I can't afford to have them hogging the little hub memory that remains.
So using a simple definition FRUN and tying to the exception vector then typing the unknown TASKS word automatically does what I need it to do: and so with MAP which is only ever used from the console rarely:
I will no doubt make this more general and may even allow precompiled code to run from the file system. There are a lot of diagnostics and "shell" commands that are well suited to this approach which will allow me to cram even more functionality into TF that goes beyond 32K.
EDIT: If I type .MAP which ends up searching the dictionary, number processing, file searching, loading, compiling, running (including scanning 32K hub RAM), then forgetting the functions just compiled, the whole process takes less than a second.
EDIT: What this automatic file search mechanism allows is that I can load code simply by typing the modules name, I no longer need to specifically type FLOAD <name>, now I just type <name>.
Very nice indeed, this will allow the SMALL build of EXTEND to get SMALL-ER. Lots of user code could be run in this fashion as well! Now TACHYON can pack around 2gigs worth of utilities/examples, erh that ought to be enough? Time for me to write a few TACHYON "shell" scripts, thanks Peter
The general form of writing to this would be:
pub AD! ( byte reg -- ) I2CSTART $40 I2C! I2C! I2C! I2CSTOP ;
pub AD@ ( reg -- byte ) I2CSTART $40 I2C! I2C! I2CSTART $41 I2C! 1 I2C@ ;
I was confused from the data sheet: Because it is the register to which the first data byte of every write operation is written automatically, the address pointer register does not have an address and does not reqire an address.
I have frobbed at the chip a bit, I will continue to do so.
A little of topic but can you tell me why you chose to put Tachyon Forth on the Prop and not a conventional micro-controller, like a PIC or AVR?
Just curious.
regards,
rich