Shop OBEX P1 Docs P2 Docs Learn Events
Tachyon V4 "DAWN" - exploring new worlds - Page 15 — Parallax Forums

Tachyon V4 "DAWN" - exploring new worlds

1121315171830

Comments

  • I patched the Tachyon 4.4 kernel to align simple word and long variables.

    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:
    BEGIN <do stuff> KEY UNTIL
    
  • Thank you Peter.

    I'm finding useful WORD on 'TACHYON Forth GLOSSARY'.
    But there is NOT KEY.
  • DaveJensonDaveJenson Posts: 372
    edited 2017-06-13 16:22
    Hi Peter,

    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.)
  • DaveJenson wrote: »
    Hi Peter,

    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
    
    


  • DaveJensonDaveJenson Posts: 372
    edited 2017-06-13 18:23
    Ok, here's what happens for me.

    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.
  • I see that too, strange.... I've fixed it up as CRLF now.
  • DaveJensonDaveJenson Posts: 372
    edited 2017-06-13 18:34
    Thanks!

    BTW I always thought this discussion should have been titled:

    "Tachyon v4 "Dawn" -- exploring new WORDS"
  • Translated sw to Tachyon.
  • 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" :)


  • Reduced code-size(328byte->302byte).
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-06-14 06:01
    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.

  • caskazcaskaz Posts: 957
    edited 2017-06-15 02:44
    Hi.

    How does I2C use?
    ( 0001 $33B0  ok )   I2CSTART  ???
    
    There is I2C-module.
    What file do I load?

    How does I search WORD?
    In case of PropForth, *** words.
  • D.PD.P Posts: 790
    edited 2017-06-15 04:07
    caskaz wrote: »
    Hi.

    How does I2C use?
    ( 0001 $33B0  ok )   I2CSTART  ???
    
    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
    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.

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-06-15 04:26
    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 ;
    
    To read the same chip
    : IO@ ( -- byte )  I2CSTART $41 I2C! 0 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.
  • Hi.
    ( 0001 $33B0  ok )   mSDA  ???
    ( 0002 $33B0  ok )   mSCL  ???
    ( 0003 $33B0  ok )   : IO@ I2CSTART ???  in 幹 玩t I2CSTART
    
  • 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 ;
    
    To read the same chip
    : IO@ ( -- byte )  I2CSTART $41 I2C! 0 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

  • D.PD.P Posts: 790
    edited 2017-06-15 06:13
    caskaz wrote: »
    Hi.
    ( 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.

  • There are NOT I2CSTART and I2CSTOP.
    ( 0001 $33B0  ok )   : test I2CSTART  ??? in 幹 玩t I2CSTART
                                                                 $40 I2C! I2C! I2CSTOP  ??? in 幹幹 at I2CSTOP
                                                                                                               ;
    ( 0002 $33B6  ok )
    
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-06-15 08:38
    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.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-06-15 09:01
    D.P wrote: »
    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)
  • Hi Peter

    I test PCF8574.
    But cannot write data to it.
    I checked wire-connection on breadboard.
    I tested slaveaddress($20) by PropForth.
    ( 0001 $33B0  ok )   : test <I2C $40 I2C! I2C! I2C> ;
    ( 0002 $33BA  ok )   $80 test  <--- Data isn't change on PCF8574.
    ( 0003 $33BA  ok )   : i2cScan
    0
    ( 0004 $33BA  ++ )   0 8 1 DOFOR
    ( 0005 $33BA  ++ )        DUP .BYTE space space space
    ( 0006 $33BA  ++ )        0 #16 1 DOFOR
    ( 0007 $33BA  ++ )             <I2C DUP I + 1 SHL I2C!?
    ( 0008 $33BA  ++ )             IF 0 ELSE 1 ENDIF . SPACE
    ( 0009 $33BA  ++ )        LOOP
    ( 0010 $33BA  ++ )        CR
    ( 0011 $33BA  ++ )        #16 +
    ( 0012 $33BA  ++ )   LOOP
    ( 0013 $33BA  ++ )   ;
    ( 0014 $33F8  ok )   i2cScan
    00     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    10     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    20     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    30     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    40     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    50     1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0  <--$50  eeprom
    60     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    70     0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
    ( 0015 $33F8  ok )
    
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-06-15 14:27
    caskaz

    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.
    ( 0011 $4B20 PBJ )   lsi2c
    
    *** I2C ***
    A0 EEPROM
    A2 EEPROM
    

    $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.

  • D.P wrote: »
    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
    

    I can only read nulls, isn't that a movie :)



  • @D.P - Append needs appending - I will get right on it.
  • @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.

    Incase of PropForth, it takes 16.205sec.
  • Hi Peter.

    WORDs of I2C is for 400kHz?
    There are WORDs for 100kHz-I2C-device?
  • caskaz wrote: »
    Hi Peter.

    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.
  • caskaz wrote: »
    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.
Sign In or Register to comment.