Tachyon NEON V5 (FAT32 and Ethernet Servers in 32kB EEPROM!)

11617181921

Comments

  • MJBMJB Posts: 1,161
    I used the command line tool under Linux; I think that loading the file into PropellerIDE added some line breaks or something which prevented it from working. Certainly it is working now!

    /opt/parallax/bin/propeller-load -r TACHYON.binary

    Now all I have to do is learn Forth! :-D

    welcome - and have FUN

    just start with Peter's examples and oneliners with immediate feedback
    then work through the stack words and watch a lot with .S
    so you get a feeling whats going on under the hood

  • Peter JakackiPeter Jakacki Posts: 9,220
    edited 2019-10-27 - 03:56:26
    @SirWorldwide
    There is just so much runtime and dev stuff built into Tachyon that I tend to forget myself. Even the control key shortcuts are handy such as ^? to list the current stack and stats. ^S is also handy for clearing the stack too. If you want to know more about a word then type HELP <word> and it will list the internals of it including header info.

    A terminal capture example of using HELP
    ...  : MYDEMO 10 FOR I . NEXT ;
    ...  MYDEMO --> 0 1 2 3 4 5 6 7 8 9  ok
    ...  HELP MYDEMO 
    5A3C 3C84 0 MYDEMO
    ADDR: DATA  NAME
    3C84: 800A  10
    3C86: 0156  FOR
    3C88: 0172  I
    3C8A: 0416  .
    3C8C: 0166  NEXT
    3C8E: 005A  EXIT
    

    If you want to test code that can fit onto one line then you don't need to define a word before executing it. In the case of MYDEMO you could just as easily type in "10 FOR I . NEXT" interactively. Normally you can't have compile-only words executed interactively in traditional Forths, and there are no special interpret vs compile words either so that ." HELLO WORD" works either way.
  • Hi there,
    Is there a way to include files to build your application?
    INCLUDE CONFIG.FTH
    INCLUDE RELAY.FTH
    INCLUDE ALARM.FTH
    INCLUDE MAIN.FTH
    
  • MJBMJB Posts: 1,161
    kdewey wrote: »
    Hi there,
    Is there a way to include files to build your application?
    INCLUDE CONFIG.FTH
    INCLUDE RELAY.FTH
    INCLUDE ALARM.FTH
    INCLUDE MAIN.FTH
    

    Forth does not use a classical compile/link model. Instead an IMAGE-Model.
    Just start from a base Tachyon image with Kernel, Extend, (Filesystem ...) loaded.
    And then paste in additional code from your editor into the terminal.
    after "loading"/"including" all this code
    do a BACKUP and the actual status of the image is saved into EEPROM - ready at next boot.

  • @ErNa - it's worse than that! :smile: Not only is there a test version of EASYFILE but there is also the TAQOZ version being rehashed, all into one. So all those goodies that I've done for TAQOZ including formatting etc will work on the P1 too! In the process Tachyon and TAQOZ will be more compatible which may involve some renaming etc so that the new Tachyon will become a V6 Turbo. Part of this testing involves digging out dozens of different designs of mine and checking it on them too. I am even playing with one of Cluso99's P8XBlade2 modules that I had to replace the crystal with a 6Mhz cylindrical type to get it working though. Wonder what was wrong with it? :wink:


    If it weren't for compatibility I would never bother with any MS filesystem. Besides none of them are really designed for SD cards or embedded systems. But I try to make the best of it by imposing my own operating conditions once it is in a system.
    Unusual as I test all pcbs properly. Remember it uses a 12MHz xtal so you must use pllx8.
  • RS_JimRS_Jim Posts: 1,373
    edited 2019-12-10 - 15:27:41
    edit post deleted
  • MJBMJB Posts: 1,161
    Hi @Peter Jakacki
    while reading
    module EXTEND ." Primary extensions to TACHYON V5 kernel - 190916-0730 " ;

    I discovered that WRAP is defined as pre as well as pub
    --- define a wrap constant := val & size-1
    pre WRAP
    CREATE ( size -- ) W,
    DOES> ( val -- val2 ) R> W@ 1- AND
    ;

    pub WRAP ( on/off -- ) '?' ESCB '7' AEMIT asw ;

    to my understanding the later will make the first unaccessible.
    ' WRAP 10 DUMP gives the pub code.

    I like the clean programming with CREATE DOES> :-)

  • @MJB - There's so much stuff packed into the humble P1 with Tachyon that even I lose track of it all :)

    I see the pre WRAP is defined as a modulo wrap constant defining word, but I can't remember ever using it! The latter WRAP to control ANSI wrapping could be used but once again I've never used it.

    I would rename the pre WRAP to something to indicate modulo operation perhaps.

    So, when are you going to start using TAQOZ and the P2???
  • MJBMJB Posts: 1,161
    @MJB - There's so much stuff packed into the humble P1 with Tachyon that even I lose track of it all :)
    ....
    So, when are you going to start using TAQOZ and the P2???

    as you see at least I started with Tachyon again.
    Just interfacing a
    pzem-004t
    power monitor to log what my water pumps are doing.

    Very dry here - luckily just one big rain event filled most of my reservoir, so for the comming summer I am ok now.
    Hope you are save with all the bush fires there ...

    TAQOZ and the P2: when P2D2 + dev board are ready let me (us) know the cost so I can order
  • I can't find the dropbox file anymore?
    Thanks
  • All the Tachyon and TAQOZ files are under the Tachyon link which should also be in my sig.
  • Hi Peter
    Years ago with T3.0 you helped with I2C clock stretching; this was the resulting code
    --- clock stretching responsive I2C@  written by Peter J
    --- Fetch a byte from the I2C bus - mirror ack signal 0 in = 0 out
    pub XI2C@	( ack -- data  ) \ 36.6us
    	SDA DUP INPUTS 0  ( ack iomask dat )
    	  8 FOR
                SCL INPUTS BEGIN SCL IN UNTIL
                SHRINP SCL OUTCLR
                NEXT
    	ROT 0= IF OVER OUTCLR THEN
     	CLOCK NOP CLOCK SWAP INPUTS
     	SDA OUTCLR SCL OUTCLR
    	BL REV						--- flip 8 msbs of long back into 8 lsbs
     	;
    
    --- Write a byte to the I2C bus and return with the ack flag :
    --- written by Peter J, PR added clock stretching
    --- enter and exit with both SDA and SCL  driven low by propeller Master
    --- This routine runs at an I2C speed of 400kHz
    --- 38.4us
    pub XI2C!? ( data -- flg )					--- write a byte to the I2C bus and return with the ack  0=ack	)
    	#24 REV							--- put into lsb first format for SHROUT
    	SDA DUP OUTSET SWAP					--- data masks
    	8 FOR
    	  SHROUT
    	  SCL INPUTS BEGIN SCL IN UNTIL
              SCL OUTCLR
    	  NEXT							--- loop
    	DROP DUP INPUTS						--- Float SDA
    	SCL INPUTS BEGIN SCL IN UNTIL
            IN 0<> SCL OUTCLR  SDA OUTCLR                           --- ack clock
    	;
    
    
    It is time to move to T5.7 and add new code to my P1 controller, but my lab is under Covid-19 lockdown, so I can't test this directly. Do you see any problems with running this stretching code under T5.7?
    Thank you!
  • Hi Peter
    Years ago with T3.0 you helped with I2C clock stretching; this was the resulting code
    --- clock stretching responsive I2C@  written by Peter J
    --- Fetch a byte from the I2C bus - mirror ack signal 0 in = 0 out
    pub XI2C@	( ack -- data  ) \ 36.6us
    	SDA DUP INPUTS 0  ( ack iomask dat )
    	  8 FOR
                SCL INPUTS BEGIN SCL IN UNTIL
                SHRINP SCL OUTCLR
                NEXT
    	ROT 0= IF OVER OUTCLR THEN
     	CLOCK NOP CLOCK SWAP INPUTS
     	SDA OUTCLR SCL OUTCLR
    	BL REV						--- flip 8 msbs of long back into 8 lsbs
     	;
    
    --- Write a byte to the I2C bus and return with the ack flag :
    --- written by Peter J, PR added clock stretching
    --- enter and exit with both SDA and SCL  driven low by propeller Master
    --- This routine runs at an I2C speed of 400kHz
    --- 38.4us
    pub XI2C!? ( data -- flg )					--- write a byte to the I2C bus and return with the ack  0=ack	)
    	#24 REV							--- put into lsb first format for SHROUT
    	SDA DUP OUTSET SWAP					--- data masks
    	8 FOR
    	  SHROUT
    	  SCL INPUTS BEGIN SCL IN UNTIL
              SCL OUTCLR
    	  NEXT							--- loop
    	DROP DUP INPUTS						--- Float SDA
    	SCL INPUTS BEGIN SCL IN UNTIL
            IN 0<> SCL OUTCLR  SDA OUTCLR                           --- ack clock
    	;
    
    
    It is time to move to T5.7 and add new code to my P1 controller, but my lab is under Covid-19 lockdown, so I can't test this directly. Do you see any problems with running this stretching code under T5.7?
    Thank you!

    No, that seems to check out and you never drive SCL high and there is enough time from SCL float to reading as well.
  • PaulRowntreePaulRowntree Posts: 150
    edited 2020-05-09 - 16:27:37
    Thanks Peter! I tried loading my code over the V5.7 (spin+extend), and it seemed to screw up during the load. This is just a bare QuickStart bard from Parallax, no interface hardware. Went back to v3.0 and it seemed to load fine. Are there any obvious changes to my codes that I have to attend to in going from v3.0 to v5.7?

    Thanks!
  • Peter JakackiPeter Jakacki Posts: 9,220
    edited 2020-05-10 - 00:39:32
    Well I'm assuming since you are using V3 methods that you have defined SCL and SDA bit-masks? V5 uses more compact pin numbers so just define it like this:
    *SDA |< := SDA
    *SCL |< := SCL
    
    V5 can still use the mask with the way that you have it in your code using OUTxxx and INPUTS etc. In fact when it comes to writing to a multibit field, such as an 8-bit data bus, I still use the OUTCLR and OUTSET which work very well in that regard.

    BTW, I noticed you using the BL constant which in V3 had a few constants defined for speed but it makes no difference in V5 since a wordcode can encode 15-bits into itself. In this case just use the more readable value 32 in place of BL.
    ...  LAP 0 LAP .LAP --> 80 cycles = 0.833us  ok
    ...  LAP 12345 LAP .LAP --> 80 cycles = 0.833us  ok
    

  • I was just about to ask you about both of those things!

    Is there a T5 convention for the leading * in a name?

    Plus, I see that == is now :=, and for some reason my LONG x,y is not working .. will split into two lines

    Getting close!
    Thanks!
  • Yes, I used that simply to show that this is a pin constant, as a reminder, but not strict.

    The == is confusing but I definitely didn't want the verbose "constant" that Forth uses since it obfuscates the actual value and name imo which I want to stand out in a listing. So I used a Spin style assignment.

    The csv enhancement I implemented later on for V3 I hadn't implemented in V5 although I could since it can be quite compact, but so far I haven't seen a need for it.
  • I think I understand. Since my clock stretching uses I2C routines in EXTEND (I2CSTART, I2CSTOP, I2CPINS) that have changed their use of SCL/SDA from a mask to a pin, I think I will try to adapt my stretching to the pin approach.

    What is the advantage to using 'programmable constants' defined as
    --- Programmable pin constants
    pub *SCL	28 ;
    pub *SDA	29 ;
    

    that are read and written by
    *SCL *SDA 
    28 ' *SCL :=!  29 ' *SDA :=!
    

    instead of
    long *SCL
    long *SDA
    

    that are read and written by
    *SDA @  *SDA @
    28 *SCL !  29 *SDA !
    

    ? Feel free to say RTF Forum ... :)
  • A constant is more compact and more "constant" than a variable :) Rarely will it change but the fact that the constant is called rather than compiled as a literal means you can redirect your I2C bus elsewhere. Perhaps you want an I2C bus that is running 20 meters away (and you can), so you might just have lines that don't interfere with the EEPROM booting and so on.
  • PaulRowntreePaulRowntree Posts: 150
    edited 2020-05-10 - 20:49:37
    You are reading my mind Peter. My app is an analog data acquisition/control board. The 8 I2C ADC's on two buses are going full out, most of the time, the parallel-bus DACs have 2 of 8 very active channels. I want to move the ADCs into a cog, the DACs into another.

    If I don't use COMPACT, then Tachyon would never be using the EEPROM's SCL and SDA ... is that correct?

    If I do have to COMPACT, then send an interactive command while some cogs are running the ADCs, we should anticipate problems?

    More discovery for me ...Is the following
    *SDA MASK	:= @SDA
    

    a substitution that takes place when loading / interpreting input? ie, a direct text substitution which is then parsed? I see it creates a new word in teh dictionary, does that means it still has to parse the the meaning each time it is found in code? Confused.
  • You are reading my mind Peter. My app is an analog data acquisition/control board. The 8 I2C ADC's on two buses are going full out, most of the time, the parallel-bus DACs have 2 of 8 very active channels. I want to move the ADCs into a cog, the DACs into another.

    If I don't use COMPACT, then Tachyon would never be using the EEPROM's SCL and SDA ... is that correct?

    If I do have to COMPACT, then send an interactive command while some cogs are running the ADCs, we should anticipate problems?

    More discovery for me ...Is the following
    *SDA MASK	:= @SDA
    

    a substitution that takes place when loading / interpreting input? ie, a direct text substitution which is then parsed? I see it creates a new word in teh dictionary, does that means it still has to parse the the meaning each time it is found in code? Confused.

    Forth doesn't enforce rules and neither do I, for myself or anybody else although conventions (including naming conventions) help. That's the attraction of Forth, you can totally change it to suit but you can totally mess it up too.

    But using a constant mainly avoided using a fetch as well. I would imagine that if I was running several buses that I would perhaps create a name for each device and each name would set the correct bus and device address. If you were interested in being able to run these buses independently and concurrently then you could easily assign a cog for each bus since there are plenty of cogs available, or even one cog that continually acquired data into memory in the background.

    As for parsing, that only happens at the compilation stage when you define a word. Once it is defined it will just execute. A variable and a constant are somewhat similar except a variable is an address constant that points to memory which has been dedicated for storage. A constant could be an address, or anything else but does not reserve any other memory when it is first defined.

    This example shows memory being allocated for variables, and then how we can define a constant that behaves exactly like the variable.
    ...  long mylong
    ...  mylong .L --> 0000.7604  ok
    ...  long somemore
    ...  somemore .L --> 0000.7608  ok
    ...  mylong := myvars
    ...  myvars .L --> 0000.7604  ok
    

    So mylong pointed to $7604 but that doesn't tell you how much memory you have allocated, it just allocates 4 bytes in this case. We test that by defining another variable and checking that its address is 4 bytes after, which it is. Now I define a constant myvars that has the same value as mylong for no other good reason except to demonstrate this flexibility. But variables will always require an extra storing and fetching or fill/move operation whereas a constant is more concise (and compact from a code point of view).

  • MJBMJB Posts: 1,161
    edited 2020-05-11 - 18:31:25
    ...

    More discovery for me ...Is the following
    *SDA MASK	:= @SDA
    

    a substitution that takes place when loading / interpreting input? ie, a direct text substitution which is then parsed? I see it creates a new word in the dictionary, does that means it still has to parse the the meaning each time it is found in code? Confused.
    Hi Paul,
    there is no complex things going on like " text substitution which is then parsed"
    Forth is very simple. At a SPACE or CRLF the word is terminated and immediately executed.
    So here
    *SDA seems to be defined as a constant
    so executing it just puts the value of the constant on the stack when the space is encountered
    The next word is MASK
    which just takes the top of stack and generates the MASK and puts the result back there replacing the old value
    then the := word is of a special kind
    it creates a CONSTANT
    by reading the next word from the console as the constant name
    and taking the value on top of stack storing it as the consants value.
    That's all



  • Hi Peter
    Yes, I see these things about a day or more after you point them out. The *SDA MASK := @SDA is a good example. I have to relearn every time I go back at this.

    I am getting stuck at the running the bus in a cog, since the pins are stored and recalled from the global 'programmable constants' *SCL, *SDA. But I see that the SCL mask is also stored in COGREG#15 for use in CLOCK (I think!); written by <I2C. Are there any unused COGREG that could be used for the SDA mask, so that each cog would have an independent I2C bus identification? These masks could be set in I2CPINS, and pulled out with COG@ as needed.

    COGREG 1-3 have no names in the spin file ... any chance they could be locked down for use as the SDA mask? I understand that COGREGs are precious resources.

    Pulling out one's hair is a good thing when in months long lockdown ...
  • @PaulRowntree - I've been relearning stuff myself, and pulling my hair out too. That's what makes it all fun, rather than so Ho Hum. I've been relearning ARM assembly, but specifically the 16-bit Thumb instruction mode and its many limitations. Man, am I glad that I can program the P2 without all that Thumb nonsense which btw, doesn't seem to blend in well with the way the plethora of peripherals (if you think that's a mouthful, read the datasheets) are mapped in memory all over so that it is not possible to use a base address register for all of them, you have to keep loading 32-bit pointers into register to use for reading and writing to these peripherals, but Thumb can't load much in the way of immediate operands into its registers and always requires the whole ldr xx,=<address> thing where the 32-bits for the address are stored in another location etc. Anyway, I digress.....

    For your special buses there is absolutely no problem if you are running them in different cogs. The easiest way is to just have dedicated I2C routines that have their own SDAx and SCLx names as well as the routines. Normally I wouldn't do it this way but the routines are only a handful of bytes and you want clock stretching anyway. So, keep it simple and get it going. Later on you could probably see a better way of doing it although you already have it working.

    An example.
    --- channel A I2C read routine ( assume CLOCK mask has been set or just manually SCL INPUT/OUTCLR it.
    pub AI2C@	( ack -- data  ) \ 36.6us
    	SDAA DUP INPUTS 0  ( ack iomask dat )
    	  8 FOR
                SCLA INPUTS BEGIN SCLA IN UNTIL
                SHRINP SCLA OUTCLR
                NEXT
    	ROT 0= IF OVER OUTCLR THEN --- ack bit
     	SCLA INPUTS NOP SCLA OUTCLR  --- ack clock
     	SWAP OUTCLR SCLA OUTCLR --- SDA low SCL low (ready for any STOP etc) 
    	BL REV						--- flip 8 msbs of long back into 8 lsbs
     	;
    
  • OK, I guess it makes sense to just make cog-ready words that do the job.... probably less time than I have been strategizing changes to the EXTEND package.

    Thanks!
  • Peter JakackiPeter Jakacki Posts: 9,220
    edited 2020-05-12 - 06:13:42
    Or else SDA and SCL are task registers constants. 1 cogreg! sets the memory area to use. Define SDA as : SDA 7 REG C@ MASK ; and simply setup 7 REG with the pin number.
    Sorry for messing with you, just make it work first, whichever way you can and then polish it up later.

    btw - I can make this change in EXTEND to make I2C more cog friendly beforehand. I will post an update later after some tests. This will let you get on with your actual project.
  • That sounds exactly what I was thinking of ... although I don't know anything about task registers. How are they different from COGREGs ? I see them in the glossary, but are there complete examples to see how they are setup and used? Is it a fixed block size, or expandable?

    Thanks Peter .. I sense convergence ...
  • almost done ... I don't see anywhere that @SDA is reset to the new iomask of the new SDA pin when the pins are reassigned ... am I missing something? I want to make sure my cogging codes cover all aspects of the switch.
  • almost done ... I don't see anywhere that @SDA is reset to the new iomask of the new SDA pin when the pins are reassigned ... am I missing something? I want to make sure my cogging codes cover all aspects of the switch.

    I've been sidetracked getting the Tachyon Sourceforge page up. I will check out the changes now and update them. Go to files/Tachyon/Forth and grab the EXTEND.FTH in the next hour.
Sign In or Register to comment.