Shop OBEX P1 Docs P2 Docs Learn Events
TACHYON O/S V3.0 JUNO - Furiously Fast Forth, FAT32+LAN+VGA+RS485+OBEX ROMS+FP+LMM+++ - Page 25 — Parallax Forums

TACHYON O/S V3.0 JUNO - Furiously Fast Forth, FAT32+LAN+VGA+RS485+OBEX ROMS+FP+LMM+++

12223252728109

Comments

  • MJBMJB Posts: 1,235
    edited 2013-07-05 08:31
    anybody already did / is thinking about a driver for the
    [h=2]nRF24L01+ Module[/h]in TACHYON ?

    there might be a way to use the OBEX code here.
    http://forums.parallax.com/showthread.php/130707-Looking-for-Faster-Objects-for-Nordic-Wireless-Modules-nRF24L01-and-nRF2401A/page3

    but given TACHYONs fast SPI functions it might be better to implement it the FORTH-way.

    Markus
  • Brian RileyBrian Riley Posts: 626
    edited 2013-07-05 10:22
    The DropBox Tachyon v21.spin, also tagged 130620, but appears to be a few lines shorter, does compile clean

    Current "bleeding edge" v2.1 still IDed as 130620 but with a change log entry dated 130705 compiles clean
  • D.PD.P Posts: 790
    edited 2013-07-05 11:09
    MJB wrote: »
    anybody already did / is thinking about a driver for the
    [h=2]nRF24L01+ Module[/h]in TACHYON ?

    there might be a way to use the OBEX code here.
    http://forums.parallax.com/showthread.php/130707-Looking-for-Faster-Objects-for-Nordic-Wireless-Modules-nRF24L01-and-nRF2401A/page3

    but given TACHYONs fast SPI functions it might be better to implement it the FORTH-way.

    Markus

    Thanks for clearing up the ITC example (inner task communication).

    And please keep your cut and paste examples comming, it really helps.

    I have had great sucess with Tachyon and all the example code Peter and others have offered. The chip you show should be no problem for Tachyon. I have been porting a driver to Tachyon from Arduino and I hear this little bird in my head saying "why don't you just do this in C, C++ and be done with it" as I stuggle learning a FORTH way of programming. I'm just about done with the driver and wow, how compact it has become and I continue to see more optimizations I can make! Holy cow Tachyon is fast and so much more elaborate than PASM. Just jump into that nRF2401 and start talking to it from the console, the WORDS you will want/need will start to form in you head as you TALK to the hardware.

    14.99$ for a breakout module I just might have to get a pair. Thanks for the link.
  • MJBMJB Posts: 1,235
    edited 2013-07-05 13:11
    D.P wrote: »
    Thanks for clearing up the ITC example (inner task communication).

    And please keep your cut and paste examples comming, it really helps.

    I have had great sucess with Tachyon and all the example code Peter and others have offered.
    The chip you show should be no problem for Tachyon.
    I have sample code in SPIN, PASM, Arduino-C and what I can read most easily BASCOM AVR-BASIC- which I used for many projects.
    I have been porting a driver to Tachyon from Arduino and I hear this little bird in my head saying "why don't you just do this in C, C++ and be done with it" as I stuggle learning a FORTH way of programming.
    I managed to get by in my professional life mostly without C
    my languages where BASIC, VB, Lisp, Smalltalk, Prolog and other exotic things.
    I'm just about done with the driver and wow, how compact it has become and I continue to see more optimizations I can make! Holy cow Tachyon is fast and so much more elaborate than PASM.
    what kind of driver are you creating?
    Just jump into that nRF2401 and start talking to it from the console, the WORDS you will want/need will start to form in you head as you TALK to the hardware.
    I might start porting the BASCOM example to TACHYON
    14.99$ for a breakout module I just might have to get a pair. Thanks for the link.
    no - this was long ago ...
    yesterday I ordered 10 for $12 from EBAY
    http://www.ebay.de/itm/121042000247?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1439.l2649
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-07-05 20:48
    MJB wrote: »
    anybody already did / is thinking about a driver for the
    nRF24L01+ Module

    in TACHYON ?

    there might be a way to use the OBEX code here.
    http://forums.parallax.com/showthread.php/130707-Looking-for-Faster-Objects-for-Nordic-Wireless-Modules-nRF24L01-and-nRF2401A/page3

    but given TACHYONs fast SPI functions it might be better to implement it the FORTH-way.

    Markus

    I do happen to have those modules in question but with nRF24L01s although I have never bothered to use them. Trying to port the obex code to Forth would be ugly and not very readable or efficient even if you got it to work. However looking at the datasheet it seems straightforward enough to interface this chip. I've started a Google document just to show you how I would go about it. I start off by looking at the signals, defining these, copying in the timing diagrams for reading and writing, and then writing the words to perform this low level function. In this case I decided to use the ESPIO module as I can configure that for 1 to 32 bits but in this case it is set for 8 bits so I can send 3 bytes. Of course I could have merged the bits as well and set it for 24 bit transfers. So this is where I'm at after not more than 15 minutes of work.

    Looking at someone else's code can be useful but also confusing so I try not to be confused. However sometimes when you have things well along it sometimes helpful to peer over their shoulder so to speak and compare so as to see if there some ideas that can be incorporated. Once you are at this stage it is not so confusing to look at someone else's code and you are more able to see through the clutter.

    Anyway, have a look at this document and if you would like to add to it in similar fashion then just email/pm me for editing privileges. I might not have much time to play with it but I can help move it along in hopefully the best direction.
  • D.PD.P Posts: 790
    edited 2013-07-06 01:48
    I do happen to have those modules in question but with nRF24L01s although I have never bothered to use them. Trying to port the obex code to Forth would be ugly and not very readable or efficient even if you got it to work. However looking at the datasheet it seems straightforward enough to interface this chip. I've started a Google document just to show you how I would go about it. I start off by looking at the signals, defining these, copying in the timing diagrams for reading and writing, and then writing the words to perform this low level function. In this case I decided to use the ESPIO module as I can configure that for 1 to 32 bits but in this case it is set for 8 bits so I can send 3 bytes. Of course I could have merged the bits as well and set it for 24 bit transfers. So this is where I'm at after not more than 15 minutes of work.

    Looking at someone else's code can be useful but also confusing so I try not to be confused. However sometimes when you have things well along it sometimes helpful to peer over their shoulder so to speak and compare so as to see if there some ideas that can be incorporated. Once you are at this stage it is not so confusing to look at someone else's code and you are more able to see through the clutter.

    Anyway, have a look at this document and if you would like to add to it in similar fashion then just email/pm me for editing privileges. I might not have much time to play with it but I can help move it along in hopefully the best direction.

    Really nice layout Peter, I will try to follow this style when preparing my Tachyon code for general consumption.
  • MJBMJB Posts: 1,235
    edited 2013-07-06 03:25
    I do happen to have those modules in question but with nRF24L01s although I have never bothered to use them. Trying to port the obex code to Forth would be ugly and not very readable or efficient even if you got it to work. However looking at the datasheet it seems straightforward enough to interface this chip. I've started a Google document just to show you how I would go about it. I start off by looking at the signals, defining these, copying in the timing diagrams for reading and writing, and then writing the words to perform this low level function. In this case I decided to use the ESPIO module as I can configure that for 1 to 32 bits but in this case it is set for 8 bits so I can send 3 bytes. Of course I could have merged the bits as well and set it for 24 bit transfers. So this is where I'm at after not more than 15 minutes of work.
    My thinking was in the same direction (maybe I already learned s.th. following your thread and code ;-) ... )
    an I was just searching the files with your dropbox code and this thread for ESPIO, but could not find a good example.
    Just was about to start from the little description in tachyon.spin.
    So thanks for the start. I am following an implementation in BASCOM, the AVR basic compiler by MCSelec.com,
    which I can read almost like mother tongue - and of course the datasheets I had downloaded.
    Looking at someone else's code can be useful but also confusing so I try not to be confused. However sometimes when you have things well along it sometimes helpful to peer over their shoulder so to speak and compare so as to see if there some ideas that can be incorporated. Once you are at this stage it is not so confusing to look at someone else's code and you are more able to see through the clutter.

    Anyway, have a look at this document and if you would like to add to it in similar fashion then just email/pm me for editing privileges. I might not have much time to play with it but I can help move it along in hopefully the best direction.
  • Brian RileyBrian Riley Posts: 626
    edited 2013-07-06 17:00
    On another subject .... for various reasons I have an I2C chip that I want on a separate buss. Now from EXTEND.fth we have
    \ 121214        - Replaced I2CPINS using CONSTANT method in place of using variables
    
     ...
    
    \ I/O "Constants" - variable to allow for redirection
    #P28 |< CONSTANT SCL
    #P29 |< CONSTANT SDA
    
    \ Assign the Prop's EEPROM pins (default)
    pub EEPROM
            #P29 #P28
    
    \ Assign the pins to use for the I2C bus
    pub I2CPINS ( sda scl -- )
            MASK ' SCL 1+ !
            MASK ' SDA 1+ !        
            ;
    

    In order to switch I2C between #P29/#P28 and #P15/#P14 Do I need to get rid of SDA/SCL as CONSTANTS and restore them as LONG variables, then code something like ?
    :  EEPROM  ( sda scl -- ) #P29  #P28 I2CPINS ;
    
    :  SI114 (sda scl -- ) #P15  #P14 I2CPINS ;
    
    I would imagine things might go faster if I created a set of constants for each buss and did the MASK once only for each.

    .... and I don't understand how EEPROM works in BACKUP ...

    \ V2 - Backup the current Tachyon Forth session
    pub BACKUP
            EEPROM
    \        64K? IF 0 $8000 $7FC0 ECOPY THEN		\ backup first 32K of EEPROM if 64 is available
            0 0 NFA' *end* $40 ALIGN OVER - ESAVE
            ;
    


    thanks in advance for any help ... BBR
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-07-06 18:37
    On another subject .... for various reasons I have an I2C chip that I want on a separate buss. Now from EXTEND.fth we have
    \ 121214        - Replaced I2CPINS using CONSTANT method in place of using variables
    
     ...
    
    \ I/O "Constants" - variable to allow for redirection
    #P28 |< CONSTANT SCL
    #P29 |< CONSTANT SDA
    
    \ Assign the Prop's EEPROM pins (default)
    pub EEPROM
            #P29 #P28
    
    \ Assign the pins to use for the I2C bus
    pub I2CPINS ( sda scl -- )
            MASK ' SCL 1+ !
            MASK ' SDA 1+ !        
            ;
    

    In order to switch I2C between #P29/#P28 and #P15/#P14 Do I need to get rid of SDA/SCL as CONSTANTS and restore them as LONG variables, then code something like ?
    :  EEPROM  ( sda scl -- ) #P29  #P28 I2CPINS ;
    
    :  SI114 (sda scl -- ) #P15  #P14 I2CPINS ;
    
    I would imagine things might go faster if I created a set of constants for each buss and did the MASK once only for each.

    .... and I don't understand how EEPROM works in BACKUP ...

    \ V2 - Backup the current Tachyon Forth session
    pub BACKUP
            EEPROM
    \        64K? IF 0 $8000 $7FC0 ECOPY THEN        \ backup first 32K of EEPROM if 64 is available
            0 0 NFA' *end* $40 ALIGN OVER - ESAVE
            ;
    


    thanks in advance for any help ... BBR

    There's no need to recode anything as setting the pin constants only takes microseconds and the real delay is just the I2C timing itself (400kHz). So your second I2C bus should be coded just as you have shown and there is no need to worry about getting rid of anything or other optimizations. I use a secondary I2C bus in one design simply because I had those extra pins on a header.

    The reason that BACKUP uses the EEPROM word is simply because it can only backup to the EEPROM on the default I2C bus and because I allow for redirection we want to force it back to the default state. If it didn't and some of your code had redirected the I2C pins then BACKUP would fail as it would not be able to find the EEPROMs and even if it did find "a" EEPROM then it would be of no use as it would not be the same EEPROM that the Prop boots from. Capice?

    Now getting back to this constants vs variables thing to tell the truth it's "much of a muchness" in that they both end up doing the same thing. The beauty about constants is that they read cleanly in code and there is one less operation as variables need to be fetched from their address. In V3 I will look at compile time optimizations which could see the sequence " ' SCL 1+ " which at present compiles to an inline literal plus an increment at runtime but in V3 would simply compile the incremented literal. However this once again is not totally necessary as Tachyon is very fast and the increment operation only takes an extra one byte and 400ns so it would only really be a concern if it were in a long loop.
  • D.PD.P Posts: 790
    edited 2013-07-06 19:14
    I'm trying to poll for async serail for the following bytes:
    07:40:00:2C:00:2F
    WHERE 
    07 = cmd byte
    40  MSB of obj word
    00  LSB of obj word
    2C  MSB of value word
    00  LSB of value word
    2F chksum byte created by XOR-ing the first five bytes
    

    My output side to this device works great, just not having any "luck" with my attempts to use a version of SERIN with WAITLOW to poll for the async data.

    Peter you mentioned a mult-port PASM module comming in V3, is there anything I else I can attempt until then? I really gave it a good shot today and learned a bunch more about Tachyon, so time very well spent in my book.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-07-06 20:41
    D.P wrote: »
    I'm trying to poll for async serail for the following bytes:
    07:40:00:2C:00:2F
    WHERE 
    07 = cmd byte
    40  MSB of obj word
    00  LSB of obj word
    2C  MSB of value word
    00  LSB of value word
    2F chksum byte created by XOR-ing the first five bytes
    

    My output side to this device works great, just not having any "luck" with my attempts to use a version of SERIN with WAITLOW to poll for the async data.

    Peter you mentioned a mult-port PASM module comming in V3, is there anything I else I can attempt until then? I really gave it a good shot today and learned a bunch more about Tachyon, so time very well spent in my book.

    Latency is always the killer with trying to do other things while waiting for asynch data. In fact if the latency was deterministic you could compensate for it but you have no way of knowing whether you sense a start bit right at the very start or perhaps it's not even the start bit but a data bit. In PASM it's still a problem for higher baud rates but you can get away with doing other things while waiting as long as the baud rate isn't too high. If 115K is pushing it for PASM then even 9600 can be flakey for non-WAITPxx interpreted code.

    However, just on the off chance that there may be some determinism in there and that you would be polling somewhere in the start bit I would adjust the start bit verification time from half a bit to around a quarter (or less). This might mean you sample each data bit early but it also gives you more of a margin if the start bit were detected late in it's cycle.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-07-06 20:44
    Latency is always the killer with trying to do other things while waiting for asynch data. In fact if the latency was deterministic you could compensate for it but you have no way of knowing whether you sense a start bit right at the very start or perhaps it's not even the start bit but a data bit. In PASM it's still a problem for higher baud rates but you can get away with doing other things while waiting as long as the baud rate isn't too high. If 115K is pushing it for PASM then even 9600 can be flakey for non-WAITPxx interpreted code.

    However, just on the off chance that there may be some determinism in there and that you would be polling somewhere in the start bit I would adjust the start bit verification time from half a bit to around a quarter (or less). This might mean you sample each data bit early but it also gives you more of a margin if the start bit were detected late in it's cycle.

    An alternative is if you have control of the encoding of your data is that you could always have the lsb set so that once you have detected a low all you need to do is WAITPEQ for a high after which you are guaranteed synch.
  • D.PD.P Posts: 790
    edited 2013-07-06 21:40
    An alternative is if you have control of the encoding of your data is that you could always have the lsb set so that once you have detected a low all you need to do is WAITPEQ for a high after which you are guaranteed synch.


    No determinism and not able to format the output of the device lsb first. I'm only using 9600.

    I'll try some of your suggestions.

    thanks

    GOT IT!!! With interactive Tachyon I was able nail this issue, it may not be pretty (yet) but every receive chksum is correct! Thanks for the hints Peter.

    Now to wrap this into it's own task and such, time for a nice walk and relaxation.
  • Brian RileyBrian Riley Posts: 626
    edited 2013-07-07 07:15
    There's no need to recode anything as setting the pin constants only takes microseconds and the real delay is just the I2C timing itself (400kHz). So your second I2C bus should be coded just as you have shown and there is no need to worry about getting rid of anything or other optimizations. I use a secondary I2C bus in one design simply because I had those extra pins on a header.

    The reason that BACKUP uses the EEPROM word is simply because it can only backup to the EEPROM on the default I2C bus and because I allow for redirection we want to force it back to the default state. If it didn't and some of your code had redirected the I2C pins then BACKUP would fail as it would not be able to find the EEPROMs and even if it did find "a" EEPROM then it would be of no use as it would not be the same EEPROM that the Prop boots from. Capice?

    Now getting back to this constants vs variables thing to tell the truth it's "much of a muchness" in that they both end up doing the same thing. The beauty about constants is that they read cleanly in code and there is one less operation as variables need to be fetched from their address. In V3 I will look at compile time optimizations which could see the sequence " ' SCL 1+ " which at present compiles to an inline literal plus an increment at runtime but in V3 would simply compile the incremented literal. However this once again is not totally necessary as Tachyon is very fast and the increment operation only takes an extra one byte and 400ns so it would only really be a concern if it were in a long loop.

    CONSTANTs/VARIABLEs ... it seems to me we had this conversation already, but indulge me a bit, if you would ... in effect the CONSTANT is being used as if it were a VARIABLE ???

    I did grasp why EEPROM is used in BACKUP, but what escapes me is how EEPROM works with the subsequent line of code.
    pub BACKUP
            EEPROM
            0 0 NFA' *end* $40 ALIGN OVER - ESAVE
            ;
    

    Pardon me here for getting a little lost, but I looked over all the code I quoted and I am not sure which to use to implement my EEPROM / SI114 switching.

    tnx ... BBR
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-07-07 08:12
    CONSTANTs/VARIABLEs ... it seems to me we had this conversation already, but indulge me a bit, if you would ... in effect the CONSTANT is being used as if it were a VARIABLE ???

    I did grasp why EEPROM is used in BACKUP, but what escapes me is how EEPROM works with the subsequent line of code.
    pub BACKUP
            EEPROM
            0 0 NFA' *end* $40 ALIGN OVER - ESAVE
            ;
    

    Pardon me here for getting a little lost, but I looked over all the code I quoted and I am not sure which to use to implement my EEPROM / SI114 switching.

    tnx ... BBR

    The CONSTANT is being used as a rewritable constant or if you like to look at it this way it happens to be a variable that automatically reads its contents without requiring a fetch, although I think that might sound confusing. By using a constant in the first place I can declare its value at compile time whereas a variable needs to be loaded with a default and as mentioned a variable always requires a fetch operation. Most of the time we simply want the value and we don't really care about changing it. What happens if I change SCL and SDA to variables? Then the bulk of the code will be pushing the address of the variable to the stack and then fetching the contents of that address thereby replacing the address on the stack with the value. A constant simply pushes that value onto the stack in one operation and this is less convoluted IMO than using a variable. But by all means a variable could be used but I prefer the rewritable constant method for pin definitions.

    Looking at the code you may also be confused by the definition of SCL and SDA as they are already set at compile to the default I2C pins.
    #P28 |< CONSTANT SCL
    #P29 |< CONSTANT SDA

    Then in BACKUP I'm setting those same constants back to their default values, what gives? That's because your SI114 word might change the value of the constants and now we need them changed back to the default for the EEPROM. When we execute BACKUP we need to talk to the EEPROM as that is where we are backing up to. Sure, it might already be set to P28 and P29 but we are making sure, as it is good practice to do so and really is neither here nor there in terms of speed.
  • D.PD.P Posts: 790
    edited 2013-07-07 11:20
    The CONSTANT is being used as a rewritable constant or if you like to look at it this way it happens to be a variable that automatically reads its contents without requiring a fetch, although I think that might sound confusing. By using a constant in the first place I can declare its value at compile time whereas a variable needs to be loaded with a default and as mentioned a variable always requires a fetch operation. Most of the time we simply want the value and we don't really care about changing it. What happens if I change SCL and SDA to variables? Then the bulk of the code will be pushing the address of the variable to the stack and then fetching the contents of that address thereby replacing the address on the stack with the value. A constant simply pushes that value onto the stack in one operation and this is less convoluted IMO than using a variable. But by all means a variable could be used but I prefer the rewritable constant method for pin definitions.

    Looking at the code you may also be confused by the definition of SCL and SDA as they are already set at compile to the default I2C pins.
    #P28 |< CONSTANT SCL
    #P29 |< CONSTANT SDA

    Then in BACKUP I'm setting those same constants back to their default values, what gives? That's because your SI114 word might change the value of the constants and now we need them changed back to the default for the EEPROM. When we execute BACKUP we need to talk to the EEPROM as that is where we are backing up to. Sure, it might already be set to P28 and P29 but we are making sure, as it is good practice to do so and really is neither here nor there in terms of speed.

    Now you both have me confused. I like to step through code and watch how the stack is modified.

    Doing so with this code has me perplexed.
    EEPROM      \  doesn't push anything but is defined as #P28 #P29   ?
    0 0 NFA' *end*    \ pushes a couple 0s and $744C    okay with that
    $40 ALIGN     \  creates $7480   okay with that
    OVER        \    okay so now the stack looks like  (0  0 7480 0 -- )
    -                \   and we get ( 0 0 0 7480 )    
    ESAVE    \   ESAVE ( ram eeprom cnt -- )   use ram 0 eeprom 0 and cnt of 7480   okay
    
    So my question is why doesn't the word EEPROM set the constants like
    #P28 |< CONSTANT SCL
    #P29 |< CONSTANT SDA 
    
    instead we have #P28 #P29 in the definition of EEPROM? Extend - Primary extensions to TACHYON kernel - 130607.1600
  • MJBMJB Posts: 1,235
    edited 2013-07-07 14:46
    I was offline for a short while and many new posts here
    and interestingly a CONSTANT vs. VARIABLE theme as well ...

    I hat a PM with Peter that triggered some 'research' that I will show here if s.o is interested
    \ test  declaring CONSTANTs vs inline constants
    
    \ !!! the following contains a major thought ERROR 
    \ !!! I hope you can find it.
    \ !!! if not see solution at bottom ;-)
    
    : TCiByte NEWCNT $46 LAPCNT .DEC ;
    : TCiWord NEWCNT $4647 LAPCNT .DEC ;
    : TCi3Byte NEWCNT $464748 LAPCNT .DEC ;
    : TCiLong NEWCNT $46474849 LAPCNT .DEC ;
    TCiByte  \ 0008 ok in us
    TCiWord  \ 0009 ok
    TCi3Byte \ 0009 ok
    TCiLong  \ 0010 ok
    NEWCNT LAPCNT .DEC \ 0007 ok  empty block timing
    
    \ ==== test with variables ====
    BYTE tb1
    $46 tb1 C!
    WORD tw1
    $4647 tw1 W!
    LONG tl1
    $46474849 tl1 !
    
    : TCcByte NEWCNT tb1 LAPCNT .DEC ;
    : TCcWord NEWCNT tw1 LAPCNT .DEC ;
    : TCcLong NEWCNT tl1 LAPCNT .DEC ;
    
    TCcByte     \ 0009 ok
    TCcWord       \ 0009 ok
    TCcLong     \ 0009 ok
    
    NEWCNT #1000 FOR NEXT LAPCNT .DEC CR           \ 0412 ok
    \ pushing 1000 times on stack will overflow, but Tachyon just ignores this ...
    NEWCNT #1000 FOR $46 NEXT LAPCNT .DEC CR       \ 2012 ok  ->  1.6us
    NEWCNT #1000 FOR $4647 NEXT LAPCNT .DEC CR     \ 2612 ok  ->  2.2us
    NEWCNT #1000 FOR $464748 NEXT LAPCNT .DEC CR   \ 3212 ok  ->  2.8us
    NEWCNT #1000 FOR $46474849 NEXT LAPCNT .DEC CR \ 3812 ok  ->  3.4us
    NEWCNT #1000 FOR tb1 NEXT LAPCNT .DEC CR       \ 3012 ok  ->  2.6us
    NEWCNT #1000 FOR tw1 NEXT LAPCNT .DEC CR       \ 3012 ok  ->  2.6us
    NEWCNT #1000 FOR tl1 NEXT LAPCNT .DEC CR       \ 3012 ok  ->  2.6us
    
    \  results:  byte and word inline constants execute faster then 
    \  variable access. But 3 byte and 4 byte/long inlines are slower.    
        
    \ ==== test with constants ====
    $46 == tb1 
    $4647 == tw1 
    $46474849 == tl1
    
    : TCcByte NEWCNT tb1 LAPCNT .DEC ;
    : TCcWord NEWCNT tw1 LAPCNT .DEC ;
    : TCcLong NEWCNT tl1 LAPCNT .DEC ;
    
    TCcByte           0010 ok
    TCcWord           0010 ok
    TCcLong            0010 ok
    
    NEWCNT #1000 FOR tb1 NEXT LAPCNT .DEC CR      \ 3412 ok  ->  3 us
    NEWCNT #1000 FOR tw1 NEXT LAPCNT .DEC CR      \ 3412 ok  ->  3 us
    NEWCNT #1000 FOR tl1 NEXT LAPCNT .DEC CR      \ 3412 ok  ->  3 us
    
    \ interrestingly CONSTANTS seem to be a little slower than variables
    \ the exercise to have a look at the TACHYON source to see why is left to the reader ;-)
    
    
    \ so what is the effect on memory size then?  (Peter please correct if required)
    
    \ inline constants are compiled a one BYTEcode plus the number of bytes required (1..4)
    \ access to a variable compiles as one BYTEcode 
    
    [SIZE=3][B]\ OK here is the solution to the above question WHERE IS THE ERROR???[/B][/SIZE]
    
    \ giving the NAME of a VARIABLE of course does NOT give the VALUE
    \ but only the ADDRESS (the variable does not 'know' it's size without
    \ a complicated check in the dict, where the next word starts
    \ this is probably the reason Tachyon does not care about it.
    \ It is left to the programmer to use the correct access operator C@,W@,@ C!,W!,!
    
    \ !! - this gives way to have word or byte access to a long variable !! 
    LONG LL  
    $01020304 LL !  
    LL  .       \   29F0  ok      the address of LL
    LL @ .      \ 1020304 ok
    LL C@ .     \ 4 ok           
    LL W@ .     \ 304 ok 
    LL 1+ C@ .  \ 3 ok
    LL 1+ W@ .  \ 304 ok     ---  this is interesting - W@ fetches word aligned !!!
    
    \  so again the timing test from above for the VARIABLES
    
    \ ==== test with variables AGAIN - hopefully correct now !!! ====
    BYTE tb1
    $46 tb1 C!
    WORD tw1
    $4647 tw1 W!
    LONG tl1
    $46474849 tl1 !
    
    : TCcByte NEWCNT tb1 C@ LAPCNT .DEC ;
    : TCcWord NEWCNT tw1 W@ LAPCNT .DEC ;
    : TCcLong NEWCNT tl1 @ LAPCNT .DEC ;
    
    TCcByte     \ 0010 ok
    TCcWord       \ 0010 ok
    TCcLong     \ 0010 ok
    
    NEWCNT #1000 FOR NEXT LAPCNT .DEC CR           \ 0412 ok
    \ pushing 1000 times on stack will overflow, but Tachyon just ignores this ...
    NEWCNT #1000 FOR $46 NEXT LAPCNT .DEC CR       \ 2012 ok  ->  1.6us
    NEWCNT #1000 FOR $4647 NEXT LAPCNT .DEC CR     \ 2612 ok  ->  2.2us
    NEWCNT #1000 FOR $464748 NEXT LAPCNT .DEC CR   \ 3212 ok  ->  2.8us
    NEWCNT #1000 FOR $46474849 NEXT LAPCNT .DEC CR \ 3812 ok  ->  3.4us
    NEWCNT #1000 FOR tb1 C@ NEXT LAPCNT .DEC CR    \ 3012 ok  ->  2.6us correct is 3412 = 3us
    NEWCNT #1000 FOR tw1 W@ NEXT LAPCNT .DEC CR    \ 3012 ok  ->  2.6us correct is 3412 = 3us
    NEWCNT #1000 FOR tl1 @ NEXT LAPCNT .DEC CR     \ 3012 ok  ->  2.6us correct is 3412 = 3us
    
    \  results:  byte and word and 3-byte inline constants execute faster then 
    \  variable access. But 4 byte/long inlines are slower.    
    \  
    \  so defined constants execute as fast as variables with the convenience
    \  of saving the @ operators.
    
    
  • IamretiredIamretired Posts: 56
    edited 2013-07-07 15:11
    I have a problem understanding the Data Stack. The Introduction to TACHYON FORTH has a table that seems to say the stack is limited to 12 elements;
    At initial startup I get
    ^D DEBUG
    DATA STACK
    01A6: 000001A6 00000004
    01A8: FFFFF9FF 00000000 00000000 00000000
    01AC: 00000000 00000000 00000000 00000000
    01B0: 00000000 00000000
    What is FFFFF9FF at address 01A8?

    I put on the stack 12 11 ........ 2 1 and did a ^D DEBUG.
    12 11 10 9 8 7 6 5 4 3 2 1 ok
    ^D DEBUG
    DATA STACK
    01A6: 000001A6 00000004
    01A8: 00000001 00000002 00000003 00000004
    01AC: 00000005 00000005 00000005 00000005
    01B0: 00000005 00000005
    I don't fully understand what I see. The 12 elements are evident and the first column appear to be addresses with the first element containing its own address. I don't know why 01A7 contains 00000004 or why my TOS is 01A8, and 01AC to 01B1 contains 00000005 ( where is 00000006 and 7 thru 12? ) .
    Thank you,
    Johnmb
  • MJBMJB Posts: 1,235
    edited 2013-07-07 15:32
    @BBR see how to rewrite a CONSTANT below

    @Peter ...
    I can not understand what you are writing about REWRITEABLE CONSTANTS
    BUT from your source it looks quite simple:

    I use this 'hack' to rewrite the constant value - seems to work
    $01020304 == CB
    CB .
    5 ' CB 1+ !
    CB .
    $0102 ' CB 2 + !
    CB .
    $010203 ' CB 3 + !
    CB .
    $01020304 ' CB 4 + !
    CB .
    
    why it works this way is an interesting topic
    
    In general works
    
    [SIZE=5][B]newval ' CONSTNAME 4 + ! [/B][/SIZE]   correctly  with one, two, 3 and 4 byte values 
    
    it is anyhow just the TOS that gets stored.
    so the magic above comes from the internals of !, which does a LONG
    alignment internally
    
    
  • MJBMJB Posts: 1,235
    edited 2013-07-07 15:38
    @lamretired

    I had the same question last year ...

    what happens is:
    DEBUG and the PRINT routines use the stack themselves and push things down,
    Since Tachyon does NOT give stack overflow errors it just pushes and pushes
    when you pop the lowest stack value is duplicated - and not filled with 0

    This means you can not expect to be able to use 12 stack entries for your program.
    You can easily create variables, arrays, tables ... if you need to store temp variables

    TACHYON is NOT the right vehicle for stack heavy e.g. recursive algorithms
  • Brian RileyBrian Riley Posts: 626
    edited 2013-07-07 15:51
    I almost have it licked but there's one thing that escapes me .... observe the console log below. I setup a few words to show how SCL/SDA get manipulated I can use EPROM and SI114 which use I2CPINS to correctly leaves the proper pair of pinmasks on the top of the stack. Then I try EEPROM and that works also. So then I create SI14X, which 'should be' EEPROM's functional equivalent for pins 14/15 it doesn't work ... it just leaves the pin #'s on the stack. Now I call the .PP word at the end of each test sequence, dumping the values of each of the #P-pins in question ... they never change ... EEPROM should not work, but it does ... WHY??? SI14X doesn't work .....and it shouldn't ... HOW TO MAKE IT WORK ??? or just use the routines that use I2CPINS???

    tnx ... BBR
      Propeller .:.:--TACHYON--:.:. Forth V21130620.0000
    
    NAMES:  $603D...7444 for 5127 (19942 bytes added) with 22225 bytes free
    CODE:   $0000...2C36 for 6191 (0529 bytes added) with 21450 bytes free
    CALLS:  0575 vectors free
    
    AUTORUN BOOT
    MODULES LOADED:
    2A25: EXT_BBR.fth         BASE BBR Extensions   - 20130605.0000
    1880: EXTEND.fth          Primary extensions to TACHYON kernel - 130701.2000
    ----------------------------------------------------------------
      ok
    : .I2CX SCL SDA .S 2DROP .S ;  ok
      ok
    :  EPROM         ( sda scl -- ) #P29  #P28 I2CPINS ;  ok
    :  SI114         ( sda scl -- ) #P15  #P14 I2CPINS ;  ok
      ok
    : .PP            ( -- ) #P29 . SPACE  #P28 . SPACE  #P15 . SPACE  #P14 . SPACE ;  ok
    .PP 1D 1C F E  ok
    .I2CX
    STACK: 00000000 FFFFF9FF 10000000 20000000
    STACK: 00000000 00000000 00000000 FFFFF9FF  ok
      ok
    .PP 1D 1C F E  ok
    SI114 .I2CX .PP
    STACK: 00000000 FFFFF9FF 00004000 00008000
    STACK: 00000000 00000000 00000000 FFFFF9FF 1D 1C F E  ok
    EEPROM .I2CX .PP
    STACK: 00000000 FFFFF9FF 10000000 20000000
    STACK: 00000000 00000000 00000000 FFFFF9FF 1D 1C F E  ok
      ok
    : SI14X #P15 #P14 ;  ok
      ok
    SI14X  .I2CX .PP
    STACK: 0000000F 0000000E 10000000 20000000
    STACK: 00000000 FFFFF9FF 0000000F 0000000E 1D 1C F E  ok
    
    
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-07-07 16:07
    MJB wrote: »
    I had the same question last year ...

    what happens is:
    DEBUG and the PRINT routines use the stack themselves and push things down,
    Since Tachyon does NOT give stack overflow errors it just pushes and pushes
    when you pop the lowest stack value is duplicated - and not filled with 0

    This means you can not expect to be able to use 12 stack entries for your program.
    You can easily create variables, arrays, tables ... if you need to store temp variables

    TACHYON is NOT the right vehicle for stack heavy e.g. recursive algorithms

    1. This means you can not expect to be able to use 12 stack entries for your program.

    True and false. When anorther cog is running your program then the full stack is available, the same is true if your code is running in turnkey mode. However if you are sitting at the console interacting with your code then the console routines require stack space too, as does the DEBUG word.

    2. You can easily create variables, arrays, tables ... if you need to store temp variables

    Also take a look at the use of locals in EXTEND.fth as this will move the stack parameters into variables which are referenced as if they were constants X1 X2 X3 X4. Personally I detest deep stacks and the use of PICK and ROLL as their use obfuscate the operation of the program and mentally juggling the stack in your head when you write the code is bad enough but can you understand what it is doing afterwards?

    3. TACHYON is NOT the right vehicle for stack heavy e.g. recursive algorithms[/QUOTE]

    Correct, because TACHYON is designed for speed and to suit the Propeller's unique cog/hub architecture. It is a very very easy matter to have a deep stack in hub RAM but while that may be good for CS101 exercises what is more important for embedded applications is the speed. I also wanted to avoid any inline LMM style PASM code because it's either encoded as numeric mumbo-jumbo or requires a resource hungry inline assembler. Once again the actual embedded use wins over any CS exercise for which a PC is much better suited.
  • IamretiredIamretired Posts: 56
    edited 2013-07-07 17:00
    Thank for your replies. I am learning FORTH so I don't anticipate 'heavy stack usage' .

    I don't know if you meant the following for me

    3. TACHYON is NOT the right vehicle for stack heavy e.g. recursive algorithms

    Correct, because TACHYON is designed for speed and to suit the Propeller's unique cog/hub architecture. It is a very very easy matter to have a deep stack in hub RAM but while that may be good for CS101 exercises what is more important for embedded applications is the speed. I also wanted to avoid any inline LMM style PASM code because it's either encoded as numeric mumbo-jumbo or requires a resource hungry inline assembler. Once again the actual embedded use wins over any CS exercise for which a PC is much better suited.

    I am not doing CS101 exercises, and from your reply it appears I may not be your intended audience.
    Let me know if I am not and I will go another route.

    Johnmb
  • D.PD.P Posts: 790
    edited 2013-07-07 18:54
    http://www.youtube.com/watch?v=P8Xr1p2qfPs

    Says it all.

    Thanks Peter

    and @ LR, I didn't know anything about FORTH befor Tachyon (except that my mentor told me I'd better learn long ago) and now I am writing basic drivers with Peter's et al help and this fabulous forum. So LR just dive in and start blinking lights, making sounds, talking to chps and don't get hung up with all the details for now. As you learn more FORTH and TACHYON study EXTEND.fth and ask questions.

    The video shows Tachyon on a Prop 1 running a RTC, 8 Channel ADC and driving the touch screen controlling a FORTH level tool i.e. steam. The clock is being updated lazy style using KEYPOLL.

    I've got so many COGs and so much code space left I'm just in awe. Even while KEYPOLL is updating the clock I am able to interacte completely with the hardware, who needs a debugger, Tachyon is in circuit debugger.

    Yes you could do all of this in spin, pasm, gcc but I bet it's not as fun (or as easy to debug). And when Prop2 comes out I don't need no fancy pasm2 or spin2 learning, just Tachyon P2 I hope.


    Now for a walk and a celebratory beer, cheers Peter.
  • Brian RileyBrian Riley Posts: 626
    edited 2013-07-07 21:20
    We have had a lot code involving the use of the TICK on this page like this example of updating a CONSTANT from Markus
    $01020304 == CB
    CB .
    5 ' CB 1+ !
    CB .
    $0102 ' CB 2 + !
    CB .
    $010203 ' CB 3 + !
    CB .
    $01020304 ' CB 4 + !
    CB .
    

    A couple of questions

    1 -- what exactly does the TICK do for you that leaving it out won't do?

    2 -- What is the general guideline for when to use it??
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-07-07 22:26
    We have had a lot code involving the use of the TICK on this page like this example of updating a CONSTANT from Markus
    $01020304 == CB
    CB .
    5 ' CB 1+ !
    CB .
    $0102 ' CB 2 + !
    CB .
    $010203 ' CB 3 + !
    CB .
    $01020304 ' CB 4 + !
    CB .
    

    A couple of questions

    1 -- what exactly does the TICK do for you that leaving it out won't do?

    2 -- What is the general guideline for when to use it??

    The tick is an immediate word in Forth and normally parses the following word to find it in the dictionary and pass the address of the code or parameter field. If it doesn't find it then it will return with a null rather than any error, this is intentional as I like to leave the error reporting to another layer.

    Tachyon works differently and also there is no real distinction between parameter an code field addresses as Tachyon assumes that whatever is pointed to is bytecode, that's why constants have a bytecode instuction which is aligned to just before a long boundary as all constants are treated as longs and the the PASM instruction RDLONG ignores the 2 lsbs of the address which is why Markus' experiments seem to magically work. So remember the tick of a constant actually returns with the address just before a long boundary, the 1+ then makes it point to the start of the long where the constant is stored, and adding 4 instead simply points to the end of a long but RDLONG simply ignores the 2 lsbs of the address anyway.

    You need to use tick anytime you need to know the absolute address in memory of the function such as when you want to run a task for instance you must pass the address of the function. Simply invoking the function will let it do whatever it is supposed to do but you really just want the address of it. Variables automatically return with the address of the storage location but they still need to be stored or fetched. Constants always fetch a long rather than the address of the long. If we want to force this constant to another value as in the case of pin redirection then we need to know the address of the storage location which is always one more than the address of the constant function.
  • MJBMJB Posts: 1,235
    edited 2013-07-08 01:04
    Iamretired wrote: »
    snip ...
    I am learning FORTH
    I don't know if you meant the following for me

    3. TACHYON is NOT the right vehicle for stack heavy e.g. recursive algorithms

    Correct, because TACHYON is designed for speed and to suit the Propeller's unique cog/hub architecture. It is a very very easy matter to have a deep stack in hub RAM but while that may be good for CS101 exercises what is more important for embedded applications is the speed. I also wanted to avoid any inline LMM style PASM code because it's either encoded as numeric mumbo-jumbo or requires a resource hungry inline assembler. Once again the actual embedded use wins over any CS exercise for which a PC is much better suited.

    I am not doing CS101 exercises, and from your reply it appears I may not be your intended audience.
    Let me know if I am not and I will go another route.

    Johnmb
    Hi John,
    this depends on what you are after.
    If you are interested in embedded work, blinking LEDs ;-) etc.
    then your place is here - no better combination around than Prop + TACHYON
    (also simple is AVR + BASCOM compiler ...)

    but if you are learing FORTH to be able to use every FORTH then you might be better on a PC with a 'standard' FORTH.
    Tachyon and PropForth (to a lesser extend) while being based on the FORTH idea, have quite a lot of specialties
    due to the special Propeller architecture. If you don't want to do embedded on the propeller, there is no need to learn all
    those specifics.
    And the stack size is just one of them.
    my2c
    Markus
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2013-07-08 01:59
    D.P wrote: »
    http://www.youtube.com/watch?v=P8Xr1p2qfPs

    Says it all.

    Thanks Peter

    and @ LR, I didn't know anything about FORTH befor Tachyon (except that my mentor told me I'd better learn long ago) and now I am writing basic drivers with Peter's et al help and this fabulous forum. So LR just dive in and start blinking lights, making sounds, talking to chps and don't get hung up with all the details for now. As you learn more FORTH and TACHYON study EXTEND.fth and ask questions.

    The video shows Tachyon on a Prop 1 running a RTC, 8 Channel ADC and driving the touch screen controlling a FORTH level tool i.e. steam. The clock is being updated lazy style using KEYPOLL.

    I've got so many COGs and so much code space left I'm just in awe. Even while KEYPOLL is updating the clock I am able to interacte completely with the hardware, who needs a debugger, Tachyon is in circuit debugger.

    Yes you could do all of this in spin, pasm, gcc but I bet it's not as fun (or as easy to debug). And when Prop2 comes out I don't need no fancy pasm2 or spin2 learning, just Tachyon P2 I hope.


    Now for a walk and a celebratory beer, cheers Peter.

    Nice looking screen there, you will have to let us know when you do a video of it in operation mit der "spitzensparken" und mit der Dampf und mit der blinklichter. Does it brew beer or do we have to get our own?
  • IamretiredIamretired Posts: 56
    edited 2013-07-08 12:36
    Everyone has been very helpful, but I am still left with the same questions.
    Given the stack contents after a reset (an initial condition) and after loading stack with 12 11 10 .....3 2 1 , why the unexpected result?

    I have a problem understanding the Data Stack. The Introduction to TACHYON FORTH has a table that seems to say the stack is limited to 12 elements;
    At initial startup I get
    ^D DEBUG
    DATA STACK
    01A6: 000001A6 00000004
    01A8: FFFFF9FF 00000000 00000000 00000000
    01AC: 00000000 00000000 00000000 00000000
    01B0: 00000000 00000000
    What is FFFFF9FF at address 01A8?

    I put on the stack 12 11 ........ 2 1 and did a ^D DEBUG.
    12 11 10 9 8 7 6 5 4 3 2 1 ok
    ^D DEBUG
    DATA STACK
    01A6: 000001A6 00000004
    01A8: 00000001 00000002 00000003 00000004
    01AC: 00000005 00000005 00000005 00000005
    01B0: 00000005 00000005
    I don't fully understand what I see. The 12 elements are evident and the first column appear to be addresses with the first element containing its own address. I don't know why 01A7 contains 00000004 or why my TOS is 01A8, and 01AC to 01B1 contains 00000005 ( where is 00000006 and 7 thru 12? ) .

    I am not questioning why it was designed this way. I want to know if there is a bug causing my unexpected result or as the questions above indicate 'what can I infer from the DEBUG listing?

    Thank you,
    Johnmb
  • D.PD.P Posts: 790
    edited 2013-07-08 16:34
    Iamretired wrote: »
    Everyone has been very helpful, but I am still left with the same questions.
    Given the stack contents after a reset (an initial condition) and after loading stack with 12 11 10 .....3 2 1 , why the unexpected result?

    I have a problem understanding the Data Stack. The Introduction to TACHYON FORTH has a table that seems to say the stack is limited to 12 elements;
    At initial startup I get
    ^D DEBUG
    DATA STACK
    01A6: 000001A6 00000004
    01A8: FFFFF9FF 00000000 00000000 00000000
    01AC: 00000000 00000000 00000000 00000000
    01B0: 00000000 00000000
    What is FFFFF9FF at address 01A8?

    I put on the stack 12 11 ........ 2 1 and did a ^D DEBUG.
    12 11 10 9 8 7 6 5 4 3 2 1 ok
    ^D DEBUG
    DATA STACK
    01A6: 000001A6 00000004
    01A8: 00000001 00000002 00000003 00000004
    01AC: 00000005 00000005 00000005 00000005
    01B0: 00000005 00000005
    I don't fully understand what I see. The 12 elements are evident and the first column appear to be addresses with the first element containing its own address. I don't know why 01A7 contains 00000004 or why my TOS is 01A8, and 01AC to 01B1 contains 00000005 ( where is 00000006 and 7 thru 12? ) .

    I am not questioning why it was designed this way. I want to know if there is a bug causing my unexpected result or as the questions above indicate 'what can I infer from the DEBUG listing?

    Thank you,
    Johnmb

    As Peter said the CONSOLE on which you are talking is using stack space, plus all the other magic that dumps the DEBUG to the CONSOLE.

    Why don't you just start pushing, popping, swapping, rotating the stack with a few numbers. I can never keep more than three parameters together in my head as is. If you insist on being stuck on the details of the crumbs left in the stack by the CONSOLE and DEBUG you just won't make any progress. Have you run all the examples from Peter's intro page? Made the noises? Printed the Stars? Grabbed a chip and .fth file from the list of demo code breadboard the chip and got it working? Have you seen the power of talking SPI, I2C, Serial directly to the chip from the console. Doing this with my logic analyzer next to me has saved me untold man hours of life expectancy.

    Did you see the graphics screen I'm working on? I never bothered to find out why my CONSOLE cog has stack crumbs in it and they have never stopped me or caused any issue. If I need to step through code I just put 0 0 0 0 on the stack and start stepping. Then I use .S to non destructively (nothing gets popped) show my stack manipulations. If my code does something wrong or unexpected I can post it here and either tachyon will be fixed or my code will be corrected (much more likely)

    To me FORTH is not a language, it is a development enviroment that is Hardware and Software specific i.e. each one is a little different. Tachyon is not ANSI FORTH as you know, it is a way of creating embedded devices using the prop chip's unique features and a very FORTHish way of development. Oh and it is fast, I was updating my clock on that graphics screen using KEYPOLL, little did I know it would call my routine in the backgound about 20,000 times a second, not quite a lazy update and it started to swamp the async serial line. I had to break my routine so it was only run once every 20,000 times it was called. Mind you I still have 5 free cogs all waiting to run more Tachyon code and the CONSOLE to control them all.

    What do you want to build/make using Tachyon/Forth and the Prop/s chip?

    Willing to help, share
Sign In or Register to comment.