the new numbers work for the BOE. Tried SanDisk and Kingston 2GB uSD cards.
Returning to an earlier post of mine, the BOE SD slot has CS pulled up, thus defeating "KEYPOLL SDPOLL" ... It all works just each time a card is inserted or removed an SD command needs to be done to force TF to take note of SD card change of status.
Peter, does this code handle SDHC cards? I have seen some good prices lately.
I just added the BOE parameters that were handed to me but I double checked the schematic and entered the pin numbers individually using the SDCS SDK MOSI MISO words and had a look at the long it generated and it was different from what was supplied. So the definition has been corrected.
Before it was: $19171816 SDPINS but after entering:
#25 SDCS
#23 SCK
#24 MOSI
#22 MISO
ok
I read the result as
sdpins @ .LONG 17181619 ok
So the correct long is: $17181619 SDPINS
Thanks Peter, PEBKAC on my part, appreciate all that you have done!
I have been experimenting with the TACHYON spi words, which I have generalized, extended and applied to accessing serial flash memory. The code shown below was based on my PropForth SPI application.
{ TACHYON SPI Driver for Flash Memory }
'' SPI Words based on Peter Jackabi's spi sd & mcp3208 wordsets.
'' Pin Masks - adjust to suit.
#27 MASK CONSTANT .sclk
#26 MASK CONSTANT .miso
#25 MASK CONSTANT .mosi
#24 MASK CONSTANT .spcs
\ ( -- ) Initialize spi engine (2.8 MHz).
: SPI
#8 3 COGREG!
.miso 2 COGREG!
.mosi 1 COGREG!
.sclk 0 COGREG!
.spcs OUTSET
.mosi OUTCLR
.sclk OUTCLR ;
\ ( n1 -- ) n1 is the number of bits to be transmitted.
: SPCNT 3 COGREG! ;
\ (on/off -- ) Selects/Deselects spi memory.
: SPSET 0= .spcs OUT ;
\ ( -- ) Executes kernel spi engine.
: SPIO [SPIO] RUNMOD ;
\ ( -- b ) Leaves 1 byte on stack.
: SP@ -1 SPIO $FF AND ;
\ ( b -- ) Sends 1 byte to device.
: SP! #24 SHL SPIO DROP ;
\ ( w -- ) Sends 1 word to device.
: SP2!
DUP #8 SHR SP! SP! ;
\ ( a -- ) Sends 3 byte address to device.
: SP3!
DUP 10 SHR SP! DUP 8 SHR SP! SP! ;
\ ( l -- ) Sends 1 long to device.
: SP4!
#32 SPCNT SPIO DROP #8 SPCNT ;
\ ( -- w ) Leaves 1 word on stack.
: SP2@
SP@ #8 SHL SP@ OR ;
\ ( -- a ) Leaves 3 bytes on stack.
: SP3@
#24 SPCNT -1 SPIO 8 SPCNT $FFFFFF AND ;
\ ( -- l) Leaves 1 long on stack.
: SP4@
#32 SPCNT -1 SPIO 8 SPCNT $FFFFFFFF AND ;
'' SPI Flash Memory Access Wordset
'' Define page and sector sizes in bytes. Adjust to suit specific memory.
'' Values given are for the ST M2516 (Digilent PModSF).
'' Values for the Numonyx Omneo P5Q PCM (Digilent PModSF2) are 64 & 128k and the
'' winbond W25X16 are 256 and 4k.
#256 CONSTANT page
#65536 CONSTANT sector
'' Define input and output buffers as page sizes.
TABLE inbuf page ALLOT
TABLE outbuf page ALLOT
'' Define the active page address.
LONG paddr
\ ( n1 n2 -- ) Set page n1 (0 - 255) address in sector n2 (0-31).
: PGAD
page * SWAP sector * + paddr ! ;
\ ( -- ) Clear input buffer.
: INBUF
inbuf page 0 FILL ;
\ ( -- ) Clear output buffer.
: OUTBUF
outbuf page 0 FILL ;
\ ( -- id ) Leaves memory id on stack. Pmod-SF: $202015 Pmod-SF2: $20DA18
: RDID
ON SPSET $9F SP! SP3@ OFF SPSET ;
\ ( -- ) Write Enable instruction.
: WREN
ON SPSET $06 SP! OFF SPSET ;
\ ( -- ) Write Disable instruction.
: WRDI
ON SPSET $04 SP! OFF SPSET ;
\ ( -- b ) Read status register. Leaves byte b on stack
: RDSR
ON SPSET $05 SP! SP@ OFF SPSET ;
\ ( b -- ) Write byte b to status register.
: WRSR
WREN ON SPSET $01 SP! SP! OFF SPSET ;
\ ( n1 -- ) Erase sector n1 (0 - 31). Sets all bits in sector to 1.
: SE
WREN ON SPSET $D8 SP! sector * SP3! OFF SPSET ;
\ ( -- ) Bulk (chip) erase. Sets all bits to 1.
: BE
WREN ON SPSET $C7 SP! OFF SPSET ;
\ ( n1 - ) Increment page address where n1 is 1, 2, or 4.
: PADDR+
paddr @ + paddr ! ;
'' The following commands implement th ememory read instructions.
\ ( -- ) Set READ command.
: RD
$03 SP! paddr @ SP3! ;
\ ( -- b ) Read 1 byte from memory at paddr, incrementing the page address.
: READ
ON SPSET RD SP@ OFF SPSET 1 PADDR+ ;
\ ( -- w ) Read 1 word from memory at paddr.
: WREAD
ON SPSET RD SP2@ OFF SPSET 2 PADDR+ ;
\ ( -- l ) Read 1 long from mempry at paddr.
: LREAD
ON SPSET RD SP4@ OFF SPSET 4 PADDR+ ;
'' The following instructions implement the memory write instructions.
'' For the PModSF2, the following definition of PP should be used so that
'' pages may be written over without erasure, as required with flash memories.
{ : PP $22 SP! paddr @ SP3! ; }
\ ( -- ) Set Page Programming command.
: PP
$02 SP! paddr @ SP3! ;
\ ( b -- ) Write 1 byte to memory at paddr, incrementing the page address.
: WRITE
WREN ON SPSET PP SP! OFF SPSET 1 PADDR+ ;
\ ( w -- ) Write 1 word to memory at paddr.
: WWRITE
WREN ON SPSET PP SP2! OFF SPSET 2 PADDR+ ;
\ ( l -- ) Write 1 long to memory at paddr.
: LWRITE
WREN ON SPSET PP SP4! OFF SPSET 4 PADDR+ ;
My next step is to revise the PropForth C3 SPI Application for TACHYON.
Well, a long evening coding, a long morning testing, and a long afternoon commenting and the servo code inspired by JonnyMac's Servo8 in Spin is done for Tachyon Forth. As requested I tried to comment every line. I did 90% of the work on a PropBOE, Spin Compiles on a recent vintage iMac using 0.8.1 of SimpleIDE subrunning BST and ZTerm for console and TextMate for TF edits.
Since V2 at this present moment seems quite stable I am releasing it into the Dropbox folder along with the HS-SerialRxL object. The Google document is available for those who have the link but it is not always stable as this is the main document I use for development. The HS-SerialRxL object includes a symbol decoder and filter so that it automatically detects a source code load via the [~ symbols which I believe would be unique enough to not encounter normally. Once it detects this symbol it will switch on filtering which removes redundant whitespace, strips out all forms of comments (except the double tick versions '' ). The tilde symbol is checked by the object and then it looks at the last character received before this and processes this as a command (or none). Since the symbol is passed through the object I also have these defined in EXTEND.fth as a little bit more than just a dummy definition. They also turn "echo" on or off thus removing most of the echoed characters during load. Eventually the output will be clean expect for line numbers and error messages etc.
I've also reduced my standard baud rate to 921600 which is the maximum that TeraTerm can handle plus it's also a standard baud rate that the Bluetooth modules can handle too. The line delay on my Minicom is set to 25ms which is a compromise between compilation speeds and receive buffer size which is set to 1K.
Currently V2 just has these enhancements along with the faster stacked branch operations. Once I have tested the next lot of enhancements I will update the Dropbox files. At present the .fth files are compatible and I will try to keep them that way, at least until V2 progresses to V2.1.
Some week ago I tested the I2C connection with the 7-seg shield from gravitech, this in combination withe ASC+ propeller board.
On this shield is a SAA1064 chip with address $70. The connections worked well, I could send data to this 7-seg display
Yesterday I tried it again with no results.
On the shield are tree I2C devices
I2CBUS was not able to detect the device at address $70.
Tested on a bare arduino board and all was working well.
Is there something changed in the mean time?
Some week ago I tested the I2C connection with the 7-seg shield from gravitech, this in combination withe ASC+ propeller board.
On this shield is a SAA1064 chip with address $70. The connections worked well, I could send data to this 7-seg display
Yesterday I tried it again with no results.
On the shield are tree I2C devices
I2CBUS was not able to detect the device at address $70.
Tested on a bare arduino board and all was working well.
Is there something changed in the mean time?
Yes, the I2C now runs at 400kHz which is why my SAA1064 driver accesses the slower I2C! method SI2C!. Perhaps I can get I2CBUS to scan at the slower speed as well as the higher speed. The SAA1064 is quite old when I2C was only ever 100kHz speed whereas many devices these days run at 400kHz.
Yes, the I2C now runs at 400kHz which is why my SAA1064 driver accesses the slower I2C! method SI2C!. Perhaps I can get I2CBUS to scan at the slower speed as well as the higher speed. The SAA1064 is quite old when I2C was only ever 100kHz speed whereas many devices these days run at 400kHz.
Should be fine when there is a slow version for testing the I2CBUS
I have no knowledge about this, but can you detect with a slower version a fast version?
Should be fine when there is a slow version for testing the I2CBUS
I have no knowledge about this, but can you detect with a slower version a fast version?
I modified I2CBUS immediately after my previous post to just do a slow scan and pick everything up. All the faster devices will work at the slower speed as it is really only the device's internal noise filter that's different on the newer devices.
However I have just redone I2CBUS (maybe that should be called I2CSCAN) so that it detects the speed of devices and reports. I could get fancy and try to tell you what the device is etc but that can get a little complicated too as I have an RTC chip that responds as if it is a second EEPROM. Here's the output from I2CBUS:
I2CBUS
Slow Device at 0070 00 00 00 00 00 00 00 00
Fast Device at 00A0 00 F3 34 00 00 FC 34 00 ok
I modified I2CBUS immediately after my previous post to just do a slow scan and pick everything up. All the faster devices will work at the slower speed as it is really only the device's internal noise filter that's different on the newer devices.
However I have just redone I2CBUS (maybe that should be called I2CSCAN) so that it detects the speed of devices and reports. I could get fancy and try to tell you what the device is etc but that can get a little complicated too as I have an RTC chip that responds as if it is a second EEPROM. Here's the output from I2CBUS:
I2CBUS
Slow Device at 0070 00 00 00 00 00 00 00 00
Fast Device at 00A0 00 F3 34 00 00 FC 34 00 ok
Since V2 at this present moment seems quite stable I am releasing it into the Dropbox folder along with the HS-SerialRxL object. The Google document is available for those who have the link but it is not always stable as this is the main document I use for development. The HS-SerialRxL object includes a symbol decoder and filter so that it automatically detects a source code load via the [~ symbols which I believe would be unique enough to not encounter normally. Once it detects this symbol it will switch on filtering which removes redundant whitespace, strips out all forms of comments (except the double tick versions '' ). The tilde symbol is checked by the object and then it looks at the last character received before this and processes this as a command (or none). Since the symbol is passed through the object I also have these defined in EXTEND.fth as a little bit more than just a dummy definition. They also turn "echo" on or off thus removing most of the echoed characters during load. Eventually the output will be clean expect for line numbers and error messages etc.
I've also reduced my standard baud rate to 921600 which is the maximum that TeraTerm can handle plus it's also a standard baud rate that the Bluetooth modules can handle too. The line delay on my Minicom is set to 25ms which is a compromise between compilation speeds and receive buffer size which is set to 1K.
Currently V2 just has these enhancements along with the faster stacked branch operations. Once I have tested the next lot of enhancements I will update the Dropbox files. At present the .fth files are compatible and I will try to keep them that way, at least until V2 progresses to V2.1.
Using the current V2, Extend.fth, SDCard.fth in the dropbox on the PBOE (with the correct SD pins now $17181619 SDPINS) everything compiles and I2CBUS works correctly. However I can't get the SD card to work now with a constant "SD Card Error" no matter which version of Extend and SDCard extensions I try with V2. Everything works correctly with V1.1 FYI
Using the current V2, Extend.fth, SDCard.fth in the dropbox on the PBOE (with the correct SD pins now $17181619 SDPINS) everything compiles and I2CBUS works correctly. However I can't get the SD card to work now with a constant "SD Card Error" no matter which version of Extend and SDCard extensions I try with V2. Everything works correctly with V1.1 FYI
Alas, V2 is splayed open on the operating table with it's gizzards out and stitching it back together bit by bit. However the Dropbox version should be fine as it won't get updated until I'm happy with the changes. If you are using a BOE configuration then bear in mind that I have coded in a separate card detect routine to suit it however the earlier version had a small bug. Since all the commands and primitives are available it is very easy to find out what is going wrong if you are adventurous enough. It is a lot of fun just interacting with the card and the SD commands to see how they respond and what happens if....
So if this is a bug report then could you please let me know the configuration as well, thanks.
Alright, V2 has been stitched up again with a few changes externally. Something to note is that I wanted to fix the ' (tick) word up so that it returned the actual "parameter field address" or bytecode address rather than anything to do with the header. So tick does not require a >PFA to convert it, I know that's a pain but it'll pass. If you want the name field address or NFA just use NFA' and from there NFA>CFA which points to the CFA although it's not really a CFA the same as conventional Forths.
Everything else should work the same it's just that the dictionary got a count byte added to it to help speed up searching and jumping to the next entry. Originally I was going to run the dictionary totally out of EEPROM and it didn't make any sense to try and jump to the next name as this just slows down an uncomplicated sequential read. Now however the dictionary includes the count byte in the compare string function so it can lead to an earlier reject and skip on to the next. In the precompiled source code it was too much of a pain to have to calculate the length of each entry and manually insert it so I just inserted a dummy byte before each name in the dictionary and have a startup routine scan the dictionary and fill in the count for me (I'm lazy).
Since the dictionary builds down and scans forward there is no need for a link field as it is very easy to get to the next name either by using the count byte + fixed offset or scanning forward to the attribute byte with it's 8th bit set.
BACKUP just does a simple byte for byte backup of the 32K of RAM to EEPROM now as there is no overwriting of cog images etc since I gave the serial buffer it's own 1K RAM (I'm generous).
EDIT: Use the latest version of HS-SerialRxL from the Dropbox folder
I'm not worried about using a bit more RAM at present as the time will come when I get serious about reclaiming memory. In the meantime it's about functionality. I've tested EXTEND.fth and SDCARD.fth and they are all working well so V2 is fine to use 'as is' while I progress onto the next stage of having the user dictionary running from EEPROM or far more preferably SD or SPI memory where it will page into RAM. Have a look at these two 4K loads:
8000 6000 1000 NEWCNT XLOAD .LAP 5,192us ok
8000 6000 1000 NEWCNT ELOAD .LAP 202,755us ok
Big difference, the SD memory reads in a 4K chunk in 5ms vs the 202ms with the EEPROM and the SD code is not even fully optimized yet.
I was able to build v1.1 on a Propeller Platform USB with SD just fine. Shifting down to 115200 baud from 230400 I was able to build 2.0 on a PropBOE and Propeller Platform Through hole with add-on uSD. The only glitch I see is after I manually initiate a BACKUP for the SD words on V2/PropBOE subsequent invocations of BACKUP can produce a non functioning boot image.
Yes, I have come across that and I am now working on it. Since BACKUP is doing a full 32K backup it looks like there is one small area in the Spin initialization code for the serial object that I just need to fix.
Alright, V2 has been stitched up again with a few changes externally. Something to note is that I wanted to fix the ' (tick) word up so that it returned the actual "parameter field address" or bytecode address rather than anything to do with the header. So tick does not require a >PFA to convert it, I know that's a pain but it'll pass. If you want the name field address or NFA just use NFA' and from there NFA>CFA which points to the CFA although it's not really a CFA the same as conventional Forths.
[/FONT]
I was able to build V2 with the lastest HS-SerialRxL, Extend and SDCard extensions sucessfully and they work correctly on the Prop BOE. I thought my last message stated PBOE was at issue, I will be more specific next time I report any problems or self induced errors.
I was able to build V2 with the lastest HS-SerialRxL, Extend and SDCard extensions sucessfully and they work correctly on the Prop BOE. I thought my last message stated PBOE was at issue, I will be more specific next time I report any problems or self induced errors.
I saw it was a PBOE but I wasn't sure which files they were, whether they were the Dropbox (stable) or Google files (bleeding edge). It can be a juggle.
I am having problems getting VECTORS to work. Specifically, what are the definitions of index, range, and limit with respect to VECTORS?
Also what does LOOKUP do?
NickL
Hi NIck, funny thing is someone just asked me that question in an email. I will try to insert some explanatory notes in the source document for some of these special words. Basically VECTORS or it's alias LOOKUP just does a simple indexed lookup in a jump table but with a range check and default execution vector. Here is my explanation from the email.
In regard to CASE did you see how VECTORS (or LOOKUP) is being used in CHARLCD.fth?
pub LCDCTRLS ( ctrl -- ) '' Look up and execute the code that corresponds to the ctrl character
$10 LOOKUP LCDchar { Default vector if equal or above limit of $10 }
So all that LOOKUP basically does is execute one of the words in the list depending upon the index so that 0 execute NOP and 1 executes LCDHOME etc. But to help the application along you need some range checking otherwise a large index could execute garbage outside the table which is why we have:
$10 LOOKUP LCDchar
So $10 is the ceiling and if anything reaches the ceiling (BTW, including $10) then it won't index into the table but execute a default word which is LCDchar.
Is there a chance for getting an example of PWM in TACHYON?
Jan Kromhout
Hellevoetsluis-NL
I'm having a look at it right now. You know that there is a really easy neat method for getting 50 to 100% PWM by using 2 counters with only an initial setting and no maintenance software? Anyhow, I will play with some variations of PWM.
Is there a chance for getting an example of PWM in TACHYON?
Jan Kromhout
Hellevoetsluis-NL
Here's a bit of quick code to play with. It runs at about 833Hz and for testing purposes it will exit on a key press. You can have this run inside another cog and have it read a hub variable each time to change it's duty cycle.
I will continue to look at improvements and multichannel operation etc.
: PWM ( duty pin -- )
SWAP #100 MIN
#1000 * #100005 OVER - ROT \ Scale to lower frequency ( duty off pin )
<BEGIN
DUP PINSET
3RD DELTA
DUP PINCLR
OVER DELTA
KEY? AND
UNTIL>
3DROP
;
Played a little more with multichannel PWM and came up with this one for starters. It can run 8 channels of 8-bit PWM at 183Hz. I will do another version where I will tweak the kernel a little so I should be able to do 1KHz comfortably.
EDIT: Go to this page for the 1kHz version (at the bottom of the page)
[FONT=courier new]BYTE pwmpins,pwmcnt
TABLE pwm #256 ALLOT
: PWMCOG
pwmpins C@ pwmcnt C@ MASKS OUTCLR
#1700 DELTA
<BEGIN
pwm $100
ADO
I C@ pwmpins C@ SHL P!
WAITCNT
LOOP
AGAIN>
;
: PWM! ( duty8 ch -- )
MASK
pwm 3RD \ set duty cycle high
ADO
DUP I SET
LOOP
$100 3RD - ROT pwm + SWAP
ADO
DUP I CLR
LOOP
DROP
;
' PWMCOG CONSTANT #pwmcog
: RUNPWM ( pwmpins pwmcnt -- )
pwmcnt C! pwmpins C!
#pwmcog 4 RUN
;
: % ( %duty -- duty8 )
8 SHL #100 /
;
\ Usage:
0 8 RUNPWM \ Starts up COG 4 to use pins 0 to 7
$80 0 PWM! \ Set PWM channel 0 for 50%
#25 % 7 PWM! \ Set PWM channel 7 for 25%[/FONT]
OK Peter,
Please explain to those of us amongst the vast unwashed, the finer points of what the difference between <BEGIN ... UNTIL> and BEGIN ... UNTIL ...... inquiring minds want to know! ;-]
OK Peter,
Please explain to those of us amongst the vast unwashed, the finer points of what the difference between <BEGIN ... UNTIL> and BEGIN ... UNTIL ...... inquiring minds want to know! ;-]
Internally in the Spin tool compiled kernel they are handy as I do not need to specify a branch address. Externally they are a little more useful in fast and tight loops as they minimise the overhead of looping. They are an extension of DO...LOOP & FOR..NEXT in that these were made as stacked branches using markers that are setup when the loop begins as they loop faster. The stacked branch also does not have a range limit whereas the displacement in the standard bytecode is limit to -255.
The traditional approach for BEGIN....UNTIL is for BEGIN to leave a marker at compile time (but no code) which UNTIL checks and compiles a conditional branch along with a branch address. where we look at this code example from PWM.fth both ways.
\ code snippet with conventional BEGIN UNTIL
BEGIN
CLOCK OVER DELTA
CLOCK DUP DELTA
KEY? AND \ keep doing this until we hit a key
UNTIL
\ compiles as
addr CLOCK OVER DELTA
addr+3 CLOCK DUP DELTA
addr+6 KEY? AND
addr+9 (UNTIL),11 \ Conditional branch instruction plus displacement backwards to "addr" (IP-11)
\ code snippet using stacked BEGIN UNTIL
<BEGIN
CLOCK OVER DELTA
CLOCK DUP DELTA
KEY? AND \ keep doing this until we hit a key
UNTIL>
\ compiles as
addr <BEGIN \ Compiles the <BEGIN opcode which actually pushes the IP onto the marker stack
addr+1 CLOCK OVER DELTA
addr+4 CLOCK DUP DELTA
addr+7 KEY? AND
addr+10 UNTIL> \ UNTIL> pops from the top of the marker stack into the IP (equivalent to JUMP TO MARK ADDRESS)
So functionally these are the same but stacked branches can be faster and also easier especially when coding bytecode in DAT structures in the Spin tool. The <BEGIN and UNTIL> are the actual bytecodes whereas BEGIN UNTIL etc are compiler control words that decide what needs to be compiled. So actually the stacked branch instructions simplfy the compiler too.
I have now a working 7-segment display version.
What I am try to do is use the TMP75 thermomether to read.
When I look to the original Arduino code it looks like
while (1)
{
Wire.RequestFrom($92,2) / request 2 bytes from register TMP75
t_H=Wire.receive() \ Get register-0
t_L=Wire.receive() \ Get register-1
.........
}
How can't this be translate into the I2C routines of TACHYON
So functionally these are the same but stacked branches can be faster and also easier especially when coding bytecode in DAT structures in the Spin tool. The <BEGIN and UNTIL> are the actual bytecodes whereas BEGIN UNTIL etc are compiler control words that decide what needs to be compiled. So actually the stacked branch instructions simplfy the compiler too.
Thanks Peter ... now I am left with one question on this matter ... should there now be a choice for me <BEGIN ... UNTIL> versus BEGIN ... UNTIL ? If so what do I consider in selecting one or the other? ... OOOORRRRR just use <BEGIN ... UNTIL> and forget about the latter.
I have now a working 7-segment display version.
What I am try to do is use the TMP75 thermomether to read.
When I look to the original Arduino code it looks like
while (1)
{
Wire.RequestFrom($92,2) / request 2 bytes from register TMP75
t_H=Wire.receive() \ Get register-0
t_L=Wire.receive() \ Get register-1
.........
}
How can't this be translate into the I2C routines of TACHYON
SCRUB THIS - IT'S NOT QUITE RIGHT - I NEED TO READ THE DATASHEET MORE CLOSELY
The base 8-bit address of the TMP75 is $90 but there are three address pins that can allow 8 devices with addresses from $90..$9E so the $92 in the example is not the normal default address. Check your connections.
Basically you need to write to the device to set it's pointer register which if set to 2 then addresses Tlow followed by Thigh. So after the set pointer operation you need to start again in read mode to read these registers. Like this:
I2CSTART $90 I2C! 2 I2C!
I2CSTART $91 I2C! 0 I2C@ 1 I2C@ I2CSTOP
Combine that code into a more general-purpose word that can address one of several devices:
: TEMP@ ( ch -- temp )
I2CSTART 2* $90 + \ Form I2C address
DUP I2C! \ Address chip (blind mode)
2 I2C! \ and write 2 as the next byte to set register pointer to 2
I2CSTART 1+ I2C! \ Now use I2C address but set R/W to 1 (1+)
0 I2C@ 1 I2C@ 8 SHL OR \ Fetch two bytes from device and combine into one word
I2CSTOP
;
BTW, The code 0 I2C@ means fetch a byte and send a low for the acknowledge (keep reading more) while 1 I2C@ will fetch a byte but not acknowledge this as this is the last byte to read.
Thanks Peter ... now I am left with one question on this matter ... should there now be a choice for me <BEGIN ... UNTIL> versus BEGIN ... UNTIL ? If so what do I consider in selecting one or the other? ... OOOORRRRR just use <BEGIN ... UNTIL> and forget about the latter.
If you are not sure just use the regular BEGIN..UNTIL since you can force an exit from this without consequences. The <BEGIN..UNTIL> should only be used if it's a clean loop, that is, it is structured in having only one entry and one exit. So don't bother with these special words then.
SCRUB THIS - IT'S NOT QUITE RIGHT - I NEED TO READ THE DATASHEET MORE CLOSELY
The base 8-bit address of the TMP75 is $90 but there are three address pins that can allow 8 devices with addresses from $90..$9E so the $92 in the example is not the normal default address. Check your connections.
Basically you need to write to the device to set it's pointer register which if set to 2 then addresses Tlow followed by Thigh. So after the set pointer operation you need to start again in read mode to read these registers. Like this:
I2CSTART $90 I2C! 2 I2C!
I2CSTART $91 I2C! 0 I2C@ 1 I2C@ I2CSTOP
Combine that code into a more general-purpose word that can address one of several devices:
: TEMP@ ( ch -- temp )
I2CSTART 2* $90 + \ Form I2C address
DUP I2C! \ Address chip (blind mode)
2 I2C! \ and write 2 as the next byte to set register pointer to 2
I2CSTART 1+ I2C! \ Now use I2C address but set R/W to 1 (1+)
0 I2C@ 1 I2C@ 8 SHL OR \ Fetch two bytes from device and combine into one word
I2CSTOP
;
BTW, The code 0 I2C@ means fetch a byte and send a low for the acknowledge (keep reading more) while 1 I2C@ will fetch a byte but not acknowledge this as this is the last byte to read.
As you see the address is really $92
I2CBUS
Fast Device at 0000 FF FF FF FF FF FF FF FF
Slow Device at 0070 80 80 80 80 80 80 80 80
Fast Device at 0092 1C F0 FF FF FF FF FF FF
Fast Device at 00A0 FF FF FF FF FF FF FF FF ok
Comments
Returning to an earlier post of mine, the BOE SD slot has CS pulled up, thus defeating "KEYPOLL SDPOLL" ... It all works just each time a card is inserted or removed an SD command needs to be done to force TF to take note of SD card change of status.
Peter, does this code handle SDHC cards? I have seen some good prices lately.
Thanks Peter, PEBKAC on my part, appreciate all that you have done!
My next step is to revise the PropForth C3 SPI Application for TACHYON.
NickL
I've also reduced my standard baud rate to 921600 which is the maximum that TeraTerm can handle plus it's also a standard baud rate that the Bluetooth modules can handle too. The line delay on my Minicom is set to 25ms which is a compromise between compilation speeds and receive buffer size which is set to 1K.
Currently V2 just has these enhancements along with the faster stacked branch operations. Once I have tested the next lot of enhancements I will update the Dropbox files. At present the .fth files are compatible and I will try to keep them that way, at least until V2 progresses to V2.1.
Some week ago I tested the I2C connection with the 7-seg shield from gravitech, this in combination withe ASC+ propeller board.
On this shield is a SAA1064 chip with address $70. The connections worked well, I could send data to this 7-seg display
Yesterday I tried it again with no results.
On the shield are tree I2C devices
I2CBUS was not able to detect the device at address $70.
Tested on a bare arduino board and all was working well.
Is there something changed in the mean time?
Yes, the I2C now runs at 400kHz which is why my SAA1064 driver accesses the slower I2C! method SI2C!. Perhaps I can get I2CBUS to scan at the slower speed as well as the higher speed. The SAA1064 is quite old when I2C was only ever 100kHz speed whereas many devices these days run at 400kHz.
Should be fine when there is a slow version for testing the I2CBUS
I have no knowledge about this, but can you detect with a slower version a fast version?
However I have just redone I2CBUS (maybe that should be called I2CSCAN) so that it detects the speed of devices and reports. I could get fancy and try to tell you what the device is etc but that can get a little complicated too as I have an RTC chip that responds as if it is a second EEPROM. Here's the output from I2CBUS:
I2CBUS
Slow Device at 0070 00 00 00 00 00 00 00 00
Fast Device at 00A0 00 F3 34 00 00 FC 34 00 ok
Thanks for this quick service!
Using the current V2, Extend.fth, SDCard.fth in the dropbox on the PBOE (with the correct SD pins now $17181619 SDPINS) everything compiles and I2CBUS works correctly. However I can't get the SD card to work now with a constant "SD Card Error" no matter which version of Extend and SDCard extensions I try with V2. Everything works correctly with V1.1 FYI
So if this is a bug report then could you please let me know the configuration as well, thanks.
Everything else should work the same it's just that the dictionary got a count byte added to it to help speed up searching and jumping to the next entry. Originally I was going to run the dictionary totally out of EEPROM and it didn't make any sense to try and jump to the next name as this just slows down an uncomplicated sequential read. Now however the dictionary includes the count byte in the compare string function so it can lead to an earlier reject and skip on to the next. In the precompiled source code it was too much of a pain to have to calculate the length of each entry and manually insert it so I just inserted a dummy byte before each name in the dictionary and have a startup routine scan the dictionary and fill in the count for me (I'm lazy).
Since the dictionary builds down and scans forward there is no need for a link field as it is very easy to get to the next name either by using the count byte + fixed offset or scanning forward to the attribute byte with it's 8th bit set.
BACKUP just does a simple byte for byte backup of the 32K of RAM to EEPROM now as there is no overwriting of cog images etc since I gave the serial buffer it's own 1K RAM (I'm generous).
EDIT: Use the latest version of HS-SerialRxL from the Dropbox folder
I'm not worried about using a bit more RAM at present as the time will come when I get serious about reclaiming memory. In the meantime it's about functionality. I've tested EXTEND.fth and SDCARD.fth and they are all working well so V2 is fine to use 'as is' while I progress onto the next stage of having the user dictionary running from EEPROM or far more preferably SD or SPI memory where it will page into RAM. Have a look at these two 4K loads:
8000 6000 1000 NEWCNT XLOAD .LAP 5,192us ok
8000 6000 1000 NEWCNT ELOAD .LAP 202,755us ok
Big difference, the SD memory reads in a 4K chunk in 5ms vs the 202ms with the EEPROM and the SD code is not even fully optimized yet.
Here's the current hex map of the 32K of RAM (each "byte" = 64 bytes averaged) EDIT: used average instead of OR'ed
0 8000 MAP
0000: 1E 00 00 00 00 00 43 77 6C 66 6B 67 74 6A 6D 7C
0400: 6F 5C 72 7F 91 7C 76 6F 7E 76 76 71 A1 9E 93 7A
0800: 5C 00 00 01 11 0A 1A 05 2D 62 62 5A 47 50 54 89
0C00: 8D 7D 87 4F 4B 3C 54 5E 57 53 58 4D 4D 5C 52 65
1000: 65 71 68 59 57 71 75 77 7A 7A 5F 4E 64 61 55 66
1400: 60 57 53 53 4E 5C 68 64 78 6C 76 60 3E 50 43 18
1800: 19 26 2D 28 1C 20 2F 3B 1F 30 33 3D 48 FF FF FF
1C00: FF FF FF FF FF FF FF FF FF FF FF FF FF F2 53 4A
2000: 49 56 74 6B 6D 68 68 74 67 66 62 5D 60 37 32 39
2400: 37 36 40 3F 42 49 4B 4B 46 50 50 50 52 54 53 50
2800: 48 53 52 53 52 51 56 59 5B 6E 6E 6F 5B 57 5D 64
2C00: 5A 64 5C 5E 29 06 0B 08 12 11 0E 07 0D 10 10 80
3000: 4B 2C 32 31 38 3A 3B 3D 3E 3C 3B 3A 3A 3D 3D 43
3400: 69 7F 6F 6D 78 8B A9 69 04 00 00 00 00 00 00 00
3800: 3A 29 56 3D 58 44 47 67 7F 63 67 7C 79 67 55 63
3C00: 55 5E 4D 6F 5F 75 7C 62 63 6D 4F 6B 61 66 66 71
4000: 15 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
4C00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
5000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
5400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
5800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
5C00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
6000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
6400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
6800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
6C00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
7000: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
7400: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
7800: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
7C00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ok
I was able to build V2 with the lastest HS-SerialRxL, Extend and SDCard extensions sucessfully and they work correctly on the Prop BOE. I thought my last message stated PBOE was at issue, I will be more specific next time I report any problems or self induced errors.
I saw it was a PBOE but I wasn't sure which files they were, whether they were the Dropbox (stable) or Google files (bleeding edge). It can be a juggle.
Also what does LOOKUP do?
NickL
Hi NIck, funny thing is someone just asked me that question in an email. I will try to insert some explanatory notes in the source document for some of these special words. Basically VECTORS or it's alias LOOKUP just does a simple indexed lookup in a jump table but with a range check and default execution vector. Here is my explanation from the email.
In regard to CASE did you see how VECTORS (or LOOKUP) is being used in CHARLCD.fth?
pub LCDCTRLS ( ctrl -- ) '' Look up and execute the code that corresponds to the ctrl character
$10 LOOKUP LCDchar { Default vector if equal or above limit of $10 }
NOP LCDHOME LCDchar LCDINIT
LCDchar LCDchar LCDchar BEEP
LCDchar LCDchar LCDLF LCDchar
LCDCLS LCDCR LCDchar LCDchar
;
So all that LOOKUP basically does is execute one of the words in the list depending upon the index so that 0 execute NOP and 1 executes LCDHOME etc. But to help the application along you need some range checking otherwise a large index could execute garbage outside the table which is why we have:
$10 LOOKUP LCDchar
So $10 is the ceiling and if anything reaches the ceiling (BTW, including $10) then it won't index into the table but execute a default word which is LCDchar.
Is there a chance for getting an example of PWM in TACHYON?
Jan Kromhout
Hellevoetsluis-NL
Here's a bit of quick code to play with. It runs at about 833Hz and for testing purposes it will exit on a key press. You can have this run inside another cog and have it read a hub variable each time to change it's duty cycle.
I will continue to look at improvements and multichannel operation etc.
EDIT: Go to this page for the 1kHz version (at the bottom of the page)
Please explain to those of us amongst the vast unwashed, the finer points of what the difference between <BEGIN ... UNTIL> and BEGIN ... UNTIL ...... inquiring minds want to know! ;-]
Internally in the Spin tool compiled kernel they are handy as I do not need to specify a branch address. Externally they are a little more useful in fast and tight loops as they minimise the overhead of looping. They are an extension of DO...LOOP & FOR..NEXT in that these were made as stacked branches using markers that are setup when the loop begins as they loop faster. The stacked branch also does not have a range limit whereas the displacement in the standard bytecode is limit to -255.
The traditional approach for BEGIN....UNTIL is for BEGIN to leave a marker at compile time (but no code) which UNTIL checks and compiles a conditional branch along with a branch address. where we look at this code example from PWM.fth both ways. So functionally these are the same but stacked branches can be faster and also easier especially when coding bytecode in DAT structures in the Spin tool. The <BEGIN and UNTIL> are the actual bytecodes whereas BEGIN UNTIL etc are compiler control words that decide what needs to be compiled. So actually the stacked branch instructions simplfy the compiler too.
I have now a working 7-segment display version.
What I am try to do is use the TMP75 thermomether to read.
When I look to the original Arduino code it looks like
while (1)
{
Wire.RequestFrom($92,2) / request 2 bytes from register TMP75
t_H=Wire.receive() \ Get register-0
t_L=Wire.receive() \ Get register-1
.........
}
How can't this be translate into the I2C routines of TACHYON
Thanks Peter ... now I am left with one question on this matter ... should there now be a choice for me <BEGIN ... UNTIL> versus BEGIN ... UNTIL ? If so what do I consider in selecting one or the other? ... OOOORRRRR just use <BEGIN ... UNTIL> and forget about the latter.
The base 8-bit address of the TMP75 is $90 but there are three address pins that can allow 8 devices with addresses from $90..$9E so the $92 in the example is not the normal default address. Check your connections.
Basically you need to write to the device to set it's pointer register which if set to 2 then addresses Tlow followed by Thigh. So after the set pointer operation you need to start again in read mode to read these registers. Like this:
I2CSTART $90 I2C! 2 I2C!
I2CSTART $91 I2C! 0 I2C@ 1 I2C@ I2CSTOP
Combine that code into a more general-purpose word that can address one of several devices: BTW, The code 0 I2C@ means fetch a byte and send a low for the acknowledge (keep reading more) while 1 I2C@ will fetch a byte but not acknowledge this as this is the last byte to read.
As you see the address is really $92
I2CBUS
Fast Device at 0000 FF FF FF FF FF FF FF FF
Slow Device at 0070 80 80 80 80 80 80 80 80
Fast Device at 0092 1C F0 FF FF FF FF FF FF
Fast Device at 00A0 FF FF FF FF FF FF FF FF ok