Awesome work getting Tachyon together.
I am trying to edit SEE-v4.fth to compile correctly.
I understand DOFOR, but with what do I replace BITS?
I haven't found any mention of removing/replacing this word?
Awesome work getting Tachyon together.
I am trying to edit SEE-v4.fth to compile correctly.
I understand DOFOR, but with what do I replace BITS?
I haven't found any mention of removing/replacing this word?
Help?
( I am running v4.4 on a bare FLiP board.)
Hi Dave, I just tried the SEE.FTH from V4r4 folder and it works fine. Btw, I deprecated BITS in favor of applying an AND mask directly since V4 handles literals up to 15-bits easily.
7 BITS is the same as $7F AND
( 0093 $3718 ok ) SEE WORDS
0AAC CR
0AAE PRINT" DICTIONARY WORDS @"
0AC6 DUP
0AC8 .WORD
0ACA SPACE
0ACC CR
0ACE SPACE
0AD0 DUP
0AD2 C@
0AD4 OVER
0AD6 1+
0AD8 C@
0ADA OR
0ADC IF (0AF6)
0ADE DUP
0AE0 C@
0AE2 ?DUP
0AE4 IF (0AF2)
0AE6 OVER
0AE8 1+
0AEA SWAP
0AEC CTYPE
0AEE NFA>NFA
0AF0 GOTO $0AF4
0AF2 THEN
0AF2 1+
0AF4 GOTO $0ACE
0AF6 THEN
0AF6 2DROP
0AF8 GOTO CR
I boot Tachyon. (I'm using TeraTerm on Win 7)
I open SEE.fth in notepad.
There are no line breaks. (When I load it into my Hex Editor, I see that is uses 0A 0A instead of 0A 0D.)
It fails to load into Tachyon.
So I have to edit the source for it to load into Tachyon.
I have had no trouble loading EXTEND.fth and LIFE.fth...
Hi caskaz, if you want compact and efficient code here are a few Tachyon (and general Forth) tips.
If you want to read the state of a pin just:
swpin PIN@
which returns with a -1 if high or a 0 if low.
( 0088 $4758 ok ) 0 LAP PIN@ LAP .LAP
64 cycles at 96MHz = 0.666us
There is usually no need to convert a pin to a mask except for special operations. So to control an LED.
ledpin HIGH
ledpin LOW
or to write to the pin with a flag just:
mystate ledpin PIN!
To promote a value to a boolean rather than this:
alternate C@ IF 0 ELSE 1 ENDIF swState C! \ Set swState
try this:
alternate C@ 0= swState C!
If you want to promote a non-zero to a true just 0<>
There is also a variable called runtime which maintains the millisecond count since boot so you can use this as a way of checking how many milliseconds have elapsed
( 0096 $4758 ok ) runtime @ .
29103575
( 0097 $4758 ok ) runtime @ .
29105543
These are just a couple of code tips and there are a lot more but I will just dole these out at the moment to give you time to take them in. Eventually you will be able to reduce your switch led code to just a few lines and hopefully learn a lot about Tachyon and how to "think Forth"
caskaz - you can also call your little bit of code from an ALARM off the background timer cog. That way you are not limited to testing it in a BEGIN KEY UNTIL loop but it can run continually in the background. Alternatively, remove the BEGIN KEY UNTIL and simply:
' sw1 +POLL
and watch it work in the background (in between keystrokes)
There's a lot more you can do but I'm sure you are starting to get a bit of an idea.
BTW, the timer version would need to create a timer variable
TIMER swtmr
then it would need to reload that timer somewhere in the called routine (say 1ms for now)
1 swtmr TIMEOUT
then it would need to have the "alarm" action set
' sw1 swtmr ALARM
then it would need to startup the timer and it is just as easy to call it to do that.
However if you set the timeout for 10ms then you hardly even need to keep track of "debounce", it could be made a lot simpler.
caskaz - you can also call your little bit of code from an ALARM off the background timer cog. That way you are not limited to testing it in a BEGIN KEY UNTIL loop but it can run continually in the background. Alternatively, remove the BEGIN KEY UNTIL and simply:
' sw1 +POLL
and watch it work in the background (in between keystrokes)
There's a lot more you can do but I'm sure you are starting to get a bit of an idea.
.
.
.
Nice to see new faces here exploring Tachyon. Let the code reviews begin, thanks Peter.
Now for CAT and TAIL, I have a log files and I would like to TAIL 10 the file. Wondering the best approach
Find the end of the file.
Walk back the \n chars for the number specified, can we SEEK backwards?
CAT the file from that point forward.
Now to look at the guts of "EasyFile.fth" for clues. Still working V3 here due to IO needs of the current project.
How does I search WORD?
In case of PropForth, *** words.
Hi caskaz,
Look at this word definitionc for an example of I2C
pub DLVR@ ( -- ) \ sets the RESULT long
mSDA mSCL I2CPINS \ use private i2c bus pins
I2CSTART \ starts the bus
psir II2C! \ psir is the address of the device, write to bus
ackI2C@ 8<< \ read a byte, ack shift left
ackI2C@ OR 8<< \ do it again
ackI2C@ OR 8<< \ one more time shift into 3RD byte
1 I2C@ OR \ read 4TH byte, DON'T ACK
RESULT ! \ store the long
I2CSTOP \ stop the bus
EEPROM \ switch the I2C pins back to EEPROM default
;
Nice and clean, this is V3 code but I don't think it has changed.
All I2C transactions begin with I2CSTART and end with I2CSTOP. Everything in between is either writing or reading bytes. If reading bytes with I2C@ then an acknowledge bit also needs to be sent to the chip and so a parameter that matches the state of the data line during acknowledgment is used which is zero for active low ack and non-zero for non-ack. Some chips are picky about this ack and so when reading a EEPROM for instance we need to NAK (not ack) the last byte we read.
If we are writing to a PCF8574 I/O for instance it is very simple like this:
: IO! ( byte -- ) I2CSTART $40 I2C! I2C! I2CSTOP ;
0 I2C@ acknowledges the byte it just read but this is also available simply as ackI2C@
Hope that gives you a quick rundown but there are plenty of code examples in Dropbox and Google docs which you can find via the link pages.
EDIT: if you had multiple PCF8574 chips then it would pay to pass an address to IO@ and IO! which could be used to select the device.
All I2C transactions begin with I2CSTART and end with I2CSTOP. Everything in between is either writing or reading bytes. If reading bytes with I2C@ then an acknowledge bit also needs to be sent to the chip and so a parameter that matches the state of the data line during acknowledgment is used which is zero for active low ack and non-zero for non-ack. Some chips are picky about this ack and so when reading a EEPROM for instance we need to NAK (not ack) the last byte we read.
If we are writing to a PCF8574 I/O for instance it is very simple like this:
: IO! ( byte -- ) I2CSTART $40 I2C! I2C! I2CSTOP ;
0 I2C@ acknowledges the byte it just read but this is also available simply as ackI2C@
Hope that gives you a quick rundown but there are plenty of code examples in Dropbox and Google docs which you can find via the link pages.
EDIT: if you had multiple PCF8574 chips then it would pay to pass an address to IO@ and IO! which could be used to select the device.
I leave the explaining to you next time, I see how my example code could be really confusing hiding the ack/nak in the syntax
( 0001 $33B0 ok ) mSDA ???
( 0002 $33B0 ok ) mSCL ???
( 0003 $33B0 ok ) : IO@ I2CSTART ??? in 幹 玩t I2CSTART
Sorry caskaz my example was incomplete mSDA and mSCL are assigned to pin values, RESULT is a long and psir is an address all defined in the body of my code elsewhere.
See Peter's explanation regarding I2C, it is much more complete and clear.
My bad again - I thought I had aliases in there for these:
<I2C --- i2c start condition
<I2C> --- restart without checking busy
I2C> --- I2C stop - also releases I2C lines
Actually V3 called them I2CSTART and I2CSTOP and I may have had aliases for them at one point. The renaming may have been part of my general rethink with V4.
I leave the explaining to you next time, I see how my example code could be really confusing hiding the ack/nak in the syntax
Sorry David, I didn't think ackI2C@ was really hiding anything at all and that is not the reason I used 0 I2C@, it was simply because I wanted to mention the do's and don'ts of I2C buses to caskaz.
Please go on explaining, by all means.
btw, as regards to "seek", this is a relic from sequential I/O methods and I prefer "random access" virtual memory methods. If you have a relative pointer to the virtual memory and you want to "seek" 10 characters back then it is a simple matter of subtracting 10 from the pointer.
fread @ 10 -
Then use the virtual file" methods such as FSC@ FSC! FSADR to access this. Even though FSADR will buffer it for you and return with a pointer to this structure in hub memory, the problem there is that this may span a sector so you may just need to use fetch methods unless you happen to know that the record will never span a sector etc. I suppose it would be easy enough to have something that would guarantee that x bytes from the pointer are accessible in memory. Perhaps:
fread @ 10 - 10 FSBYTES
Where FSBYTES ( addr cnt -- bufadr ) will check for sector spanning and compensate if necessary.
Or maybe call it FSADRS
Of course too, in your request you simply wanted to cat from 10 bytes back:
fread @ 10 - (cat)
$A0 is the 8-bit address format although some datasheets like to refer to the 7-bit address format instead but the 8-bit is easier to use I find.
btw - 2* and 2/ are the preferred Forth words used to shift left and right by 1 bit.
( 0014 $4B20 PBJ ) 0 lap 2* lap .lap
32 cycles at 96MHz = 0.333us
( 0015 $4B20 PBJ )
( 0016 $4B20 PBJ ) 0 lap 1 shl lap .lap
160 cycles at 96MHz = 1.666us
Also there are bugs in your code, for instance:
0 8 1 DOFOR
DUP .BYTE
What are you DUPing?
Also, it is possible that the PCF8574 devices might only work at 100kHz as most I2C devices work at 400kHz or more these days. You might need to have a slower version of I2C! etc.
I leave the explaining to you next time, I see how my example code could be really confusing hiding the ack/nak in the syntax
Sorry David, I didn't think ackI2C@ was really hiding anything at all and that is not the reason I used 0 I2C@, it was simply because I wanted to mention the do's and don'ts of I2C buses to caskaz.
Please go on explaining, by all means.
btw, as regards to "seek", this is a relic from sequential I/O methods and I prefer "random access" virtual memory methods. If you have a relative pointer to the virtual memory and you want to "seek" 10 characters back then it is a simple matter of subtracting 10 from the pointer.
fread @ 10 -
Then use the virtual file" methods such as FSC@ FSC! FSADR to access this. Even though FSADR will buffer it for you and return with a pointer to this structure in hub memory, the problem there is that this may span a sector so you may just need to use fetch methods unless you happen to know that the record will never span a sector etc. I suppose it would be easy enough to have something that would guarantee that x bytes from the pointer are accessible in memory. Perhaps:
fread @ 10 - 10 FSBYTES
Where FSBYTES ( addr cnt -- bufadr ) will check for sector spanning and compensate if necessary.
Or maybe call it FSADRS
Of course too, in your request you simply wanted to cat from 10 bytes back:
fread @ 10 - (cat)
I'm confused now.
FOPEN RUNTIME0.TXT --- open the file
RW --- set to read write
0 APPEND --- get the end of file (address) ?
XADR --- get the physical address, also tried fread @ and nothing ?
100 - --- move 100 bytes back
(cat) --- output file from there
@D.P - Append needs appending - I will get right on it.
Neat, then I will port GardenControl entirely but about the syntax above, close for a V3 test? Using APPEND on a current project in V3, soon to be a V4 project.
Translated i2c_charLCD(using PCF8574) to Tachyon.
Wave takes 7.282sec.
I inserted 900 us(actual1.258msec)delay in lcd_com.
Incase of 800 us, this don't operate.
I don't understand this.
WORDs of I2C is for 400kHz?
There are WORDs for 100kHz-I2C-device?
Yes and no. I used to have some slower words available in V3 and this was also used by the i2c scan routine to check for slow speed devices as well. But what I would like to have is an adjustable speed I2C routine so that I can call slow, normal, and high speed devices etc all from the same routines. I think I can see a way of doing that too so I may as well experiment with it and hopefully just by specifying a bus frequency we can use all the same routines.
Translated i2c_charLCD(using PCF8574) to Tachyon.
Wave takes 7.282sec.
I inserted 900 us(actual1.258msec)delay in lcd_com.
Incase of 800 us, this don't operate.
I don't understand this.
Incase of PropForth, it takes 16.205sec.
There is only one operation that requires up to 1.5ms to execute and that is the display home/clear function, you don't need any delay at all for the other commands. I say home/clear because it seems strange that the datasheets continue to say "home" takes 1.5 which means that positioning a cursor takes longer than it does to clear RAM. I am going to check this myself but either way just use a delay for this command only otherwise you are just slowing everything down for this seldom used command.
Comments
KEY does not block and so always returns with a code so that if there is no key then the value returned is 0. So simply:
I'm finding useful WORD on 'TACHYON Forth GLOSSARY'.
But there is NOT KEY.
Awesome work getting Tachyon together.
I am trying to edit SEE-v4.fth to compile correctly.
I understand DOFOR, but with what do I replace BITS?
I haven't found any mention of removing/replacing this word?
Help?
( I am running v4.4 on a bare FLiP board.)
Hi Dave, I just tried the SEE.FTH from V4r4 folder and it works fine. Btw, I deprecated BITS in favor of applying an AND mask directly since V4 handles literals up to 15-bits easily.
7 BITS is the same as $7F AND
I boot Tachyon. (I'm using TeraTerm on Win 7)
I open SEE.fth in notepad.
There are no line breaks. (When I load it into my Hex Editor, I see that is uses 0A 0A instead of 0A 0D.)
It fails to load into Tachyon.
So I have to edit the source for it to load into Tachyon.
I have had no trouble loading EXTEND.fth and LIFE.fth...
Once I re-format SEE.fth it works fine.
BTW I always thought this discussion should have been titled:
"Tachyon v4 "Dawn" -- exploring new WORDS"
If you want to read the state of a pin just: which returns with a -1 if high or a 0 if low.
There is usually no need to convert a pin to a mask except for special operations. So to control an LED. or to write to the pin with a flag just:
To promote a value to a boolean rather than this: try this: If you want to promote a non-zero to a true just 0<>
There is also a variable called runtime which maintains the millisecond count since boot so you can use this as a way of checking how many milliseconds have elapsed
These are just a couple of code tips and there are a lot more but I will just dole these out at the moment to give you time to take them in. Eventually you will be able to reduce your switch led code to just a few lines and hopefully learn a lot about Tachyon and how to "think Forth"
There's a lot more you can do but I'm sure you are starting to get a bit of an idea.
BTW, the timer version would need to create a timer variable then it would need to reload that timer somewhere in the called routine (say 1ms for now) then it would need to have the "alarm" action set then it would need to startup the timer and it is just as easy to call it to do that.
However if you set the timeout for 10ms then you hardly even need to keep track of "debounce", it could be made a lot simpler.
Nice to see new faces here exploring Tachyon. Let the code reviews begin, thanks Peter.
Now for CAT and TAIL, I have a log files and I would like to TAIL 10 the file. Wondering the best approach
Find the end of the file.
Walk back the \n chars for the number specified, can we SEEK backwards?
CAT the file from that point forward.
Now to look at the guts of "EasyFile.fth" for clues. Still working V3 here due to IO needs of the current project.
How does I2C use? There is I2C-module.
What file do I load?
How does I search WORD?
In case of PropForth, *** words.
Hi caskaz,
Look at this word definitionc for an example of I2C
Nice and clean, this is V3 code but I don't think it has changed.
To read the same chip 0 I2C@ acknowledges the byte it just read but this is also available simply as ackI2C@
Hope that gives you a quick rundown but there are plenty of code examples in Dropbox and Google docs which you can find via the link pages.
EDIT: if you had multiple PCF8574 chips then it would pay to pass an address to IO@ and IO! which could be used to select the device.
I leave the explaining to you next time, I see how my example code could be really confusing hiding the ack/nak in the syntax
Sorry caskaz my example was incomplete mSDA and mSCL are assigned to pin values, RESULT is a long and psir is an address all defined in the body of my code elsewhere.
See Peter's explanation regarding I2C, it is much more complete and clear.
Actually V3 called them I2CSTART and I2CSTOP and I may have had aliases for them at one point. The renaming may have been part of my general rethink with V4.
Sorry David, I didn't think ackI2C@ was really hiding anything at all and that is not the reason I used 0 I2C@, it was simply because I wanted to mention the do's and don'ts of I2C buses to caskaz.
Please go on explaining, by all means.
btw, as regards to "seek", this is a relic from sequential I/O methods and I prefer "random access" virtual memory methods. If you have a relative pointer to the virtual memory and you want to "seek" 10 characters back then it is a simple matter of subtracting 10 from the pointer. Then use the virtual file" methods such as FSC@ FSC! FSADR to access this. Even though FSADR will buffer it for you and return with a pointer to this structure in hub memory, the problem there is that this may span a sector so you may just need to use fetch methods unless you happen to know that the record will never span a sector etc. I suppose it would be easy enough to have something that would guarantee that x bytes from the pointer are accessible in memory. Perhaps: Where FSBYTES ( addr cnt -- bufadr ) will check for sector spanning and compensate if necessary.
Or maybe call it FSADRS
Of course too, in your request you simply wanted to cat from 10 bytes back:
fread @ 10 - (cat)
I test PCF8574.
But cannot write data to it.
I checked wire-connection on breadboard.
I tested slaveaddress($20) by PropForth.
lsi2c is a command that lists all the I2C devices it can find so you can check your connections with that command which is also executed at boot.
$A0 is the 8-bit address format although some datasheets like to refer to the 7-bit address format instead but the 8-bit is easier to use I find.
btw - 2* and 2/ are the preferred Forth words used to shift left and right by 1 bit.
Also there are bugs in your code, for instance: What are you DUPing?
Also, it is possible that the PCF8574 devices might only work at 100kHz as most I2C devices work at 400kHz or more these days. You might need to have a slower version of I2C! etc.
I'm confused now.
I can only read nulls, isn't that a movie
Neat, then I will port GardenControl entirely but about the syntax above, close for a V3 test? Using APPEND on a current project in V3, soon to be a V4 project.
Wave takes 7.282sec.
I inserted 900 us(actual1.258msec)delay in lcd_com.
Incase of 800 us, this don't operate.
I don't understand this.
Incase of PropForth, it takes 16.205sec.
WORDs of I2C is for 400kHz?
There are WORDs for 100kHz-I2C-device?
There is only one operation that requires up to 1.5ms to execute and that is the display home/clear function, you don't need any delay at all for the other commands. I say home/clear because it seems strange that the datasheets continue to say "home" takes 1.5 which means that positioning a cursor takes longer than it does to clear RAM. I am going to check this myself but either way just use a delay for this command only otherwise you are just slowing everything down for this seldom used command.