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

Tachyon V4 "DAWN" - exploring new worlds

1161719212230

Comments

  • FROM BY FOR NEXT
    Woke up early this morning and decided to implement the new FOR NEXT with a combined loop parameter and branch stack in hub RAM as indexing this in cog RAM is way too clumsy and consumes way too much cog memory anyway. FOR now pushes 4 (not a pun) parameters onto the loop stack and maintains 4 registers in cog memory for the current loop. I decided on calling the INDEX and STEP methods FROM and BY. With that accomplished here is the very first tentative step for 4.5's FOR NEXT.
    Propeller .:.:--TACHYON--:.:. Forth V4X5 DAWN 450170705.0600
    
     Cold start - no user code - setting defaults  
    --------------------------------------------------------------------------------
    ( 0001 $1B40  ok )   10 FOR I . SPACE NEXT
    0 1 2 3 4 5 6 7 8 9 
    ( 0002 $1B40  ok )   100 FROM 10 FOR I . SPACE NEXT
    100 101 102 103 104 105 106 107 108 109 
    ( 0003 $1B40  ok )   100 FROM -1 BY 10 FOR I . SPACE NEXT
    100 99 98 97 96 95 94 93 92 91 
    ( 0004 $1B40  ok )
    

    Because it was way too awkward and slow to implement an efficient loop stack in cog memory that pushed and popped four parameters at a time, this was moved to hub memory and now there are a whopping 27 longs spare in the Tachyon cog. I think I'll go to town with that!
  • MJBMJB Posts: 1,235
    ... ...
    now there are a whopping 27 longs spare in the Tachyon cog. I think I'll go to town with that!

    If you continue like this, then when P2 comes out, Tachyon will need no COG space any more ... ;-)

    Maybe we can have 2 simultaneous RUMMODs now or one giant one ?
    If the space is in one contiguous block.
  • MJBMJB Posts: 1,235
    btw - what is the new loop speed compared to the old V3 one?

    can the values of outside loops still be accessed as before?
    like i / j / k ...
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-07-05 00:21
    To test the speed of the new FOR NEXT I had to modify and load EXTEND. Amazingly it compiled fine:
    Propeller .:.:--TACHYON--:.:. Forth V4X5 DAWN 450170705.0600
                                                                
    MODULES LOADED:                                             
    1B40: EXTEND.fth          Primary extensions to TACHYON V4.5 kernel  - 170706-0930
                                                                
    AUTORUN BOOT                                                
    FREQ = 96.0MHz                                              
    *** INITS ***                                               
    Loading cog 3 E50A F32                                      
    *** ROMS ***                                                
    0,848 VGA32x15                                              
    0,392 HSUART                                                
    1,900 F32                                                   
    0,196 MONO16                                                
    1,900 F32                                                   
    *** I2C ***                                                 
    A0 EEPROM                                                   
                                                                
    INTERCOM: &00.00.00.00 @2,000,000
     CODE:$3602 =13314 bytes   NAME:$5A2A =6614 bytes   DATA:$76E8 =216 bytes    =9256 bytes free    Data Stack (0)
    
    --------------------------------------------------------------------------------
    ( 0001 $3602  ok )
    

    I then tested the looping speed
    ( 0002 $3602  ok )   
    ( 0003 $3602  ok )   1000000 LAP FOR NEXT LAP .LAP
    48000240 cycles at 96MHz = 500.002ms 
    
    So, that's fine at 500ns/loop.

    But what about setup and exit latencies?
    ( 0004 $3602  ok )   0 LAP FOR LAP .LAP
    160 cycles at 96MHz = 1.666us 
    ( 0005 $3602  ok )   0 LAP FOR NEXT LAP .LAP
    272 cycles at 96MHz = 2.833us 
    ( 0006 $3602  ok )   1 LAP FOR NEXT LAP .LAP
    288 cycles at 96MHz = 3.000us 
    

    FOR itself requires 1.666us to execute and stack the previous loop. The overall FOR NEXT overhead is 3us where it stacks and unstacks 4 parameters.

    Checking the 4.4 kernel for comparison:
    ( 1973 $35B6  ok )   1000000 LAP FOR NEXT LAP .LAP
    48000176 cycles at 96MHz = 500.001ms 
    ( 1974 $35B6  ok )   0 LAP FOR NEXT LAP .LAP
    208 cycles at 96MHz = 2.166us 
    ( 1975 $35B6  ok )   1 LAP FOR NEXT LAP .LAP
    224 cycles at 96MHz = 2.333us 
    ( 1977 $35B6  ok )   0 1 1 LAP DOFOR LOOP LAP .LAP
    448 cycles at 96MHz = 4.666us 
    ( 1978 $35B6  ok )   0 0 1 LAP DOFOR LOOP LAP .LAP
    432 cycles at 96MHz = 4.500us
     
    ( 1981 $35B6  ok )   LAP 0 1 1 DOFOR LOOP LAP .LAP
    688 cycles at 96MHz = 7.166us
    
    The FOR NEXT loop times are the same although overhead is a fraction less. However to compare this properly we also run a single (non-looping) DOFOR LOOP which takes 4.666us vs the 3us in V4.5. So V4.5 has comparable FOR NEXT overhead but faster when compared to DOFOR LOOP overhead in V4.4.

    V4.5 full FROM BY FOR NEXT overhead is 10.333us where FROM and BY are high-level wordcode at present.
    ( 1979 $3602  ok )   1 1 0 LAP FROM BY FOR NEXT LAP .LAP
    992 cycles at 96MHz = 10.333us 
    
    Obviously now that I have spare memory I can implement FROM and BY in PASM which I have just done:
    ( 1973 $35C2  ok )   1 1 0 lap FROM BY FOR NEXT LAP .LAP
    448 cycles at 96MHz = 4.666us 
    
    That's the same overhead as it is for a DOFOR LOOP in V4.4. No problem but obviously FOR NEXT overhead does not always require FROM or BY.

    The J index is maintained in a register but K was deprecated in V4.4 since it would take too much to maintain K although it could be done in V4.5
    btw - 42 longs spare at present for RUNMODs vs 23 normally
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-07-05 06:28
    For V4.5 I managed to fit in +LOOP which is just a single PASM opcode for BY! NEXT operation, ADO which is a single PASM opcode for SWAP FROM FOR, and lastly LOOP which is just an alias for NEXT. They are all FOR NEXT loops though where the FOR count is not affected by BY which is only used to increment the FROM index. Traditional DO +LOOP uses a limit that the index is compared against rather than a count.
    ( 1976 $35C2  ok )   
    ( 1977 $35C2  ok )   100 10 ADO I . SPACE LOOP
    100 101 102 103 104 105 106 107 108 109 
    ( 1978 $35C2  ok )   100 10 ADO I . SPACE 2 +LOOP
    100 102 104 106 108 110 112 114 116 118 
    ( 1979 $35C2  ok )   8 FOR I . SPACE NEXT
    0 1 2 3 4 5 6 7 
    ( 1980 $35C2  ok )   100 FROM 2 BY 8 FOR I . SPACE NEXT
    100 102 104 106 108 110 112 114 
    ( 1981 $35C2  ok )   4 FOR 4 FOR I . ',' EMIT J . SPACE NEXT NEXT
    0,0 1,0 2,0 3,0 0,1 1,1 2,1 3,1 0,2 1,2 2,2 3,2 0,3 1,3 2,3 3,3 
    ( 1982 $35C2  ok )
    
  • Hi.

    I try to understand TIMER.
    I loaded TIMER.fth.
    But any LEDs not on.
    Why?
    TACHYON V4
                  
    IFDEF timer.fth
    @rest	org
    FORGET timer.fth
    }
    
    pub timer        ." timer  2017/06/17 11:49:45 " ;
    
    @org W@	== @rest	--- remember
    
    
     \ * SIMPLE ROUTINE TO EXERCISE ALL 8 LEDS WITH TACHYON TIMERS
    \ * AND ALARMS ON THE  PROP QUICKSTART BOARD
    \ * 
    \ * USE THE WORD "BLINKEM" TO START THE LIGHTS 
    \ * AND "STOPEM" TO STOP THE LIGHTS
    
    
    0 == #mt0
    1 == #mt1
    2 == #mt2
    3 == #mt3
    4 == #mt4
    5 == #mt5
    6 == #mt6
    7 == #mt7
    
    : blink0 #16 PIN@ IF #16 LOW #500 ELSE #16 HIGH #50 THEN #mt0 TIMEOUT ;
    : b0 ' blink0 #mt0  ALARM ;
    
    : blink1 #17 PIN@ IF #17 LOW #300 ELSE #17 HIGH #50 THEN #mt1 TIMEOUT ;
    : b1 ' blink1 #mt1  ALARM ;
    
    : blink2 #18 PIN@ IF #18 LOW #150 ELSE #18 HIGH #50 THEN #mt2 TIMEOUT ;
    : b2 ' blink2 #mt2  ALARM ;
    
    : blink3 #19 PIN@ IF #19 LOW #285 ELSE #19 HIGH #50 THEN #mt3 TIMEOUT ;
    : b3 ' blink3 #mt3  ALARM ;
    
    : blink4 #20 PIN@ IF #20 LOW #175 ELSE #20 HIGH #50 THEN #mt4 TIMEOUT ;
    : b4 ' blink4 #mt4  ALARM ;
    
    : blink5 #21 PIN@ IF #21 LOW #335 ELSE #21 HIGH #50 THEN #mt5 TIMEOUT ;
    : b5 ' blink5 #mt5  ALARM ;
    
    : blink6 #22 PIN@ IF #22 LOW #100 ELSE #22 HIGH #50 THEN #mt6 TIMEOUT ;
    : b6 ' blink6 #mt6  ALARM ;
    
    : blink7 #23 PIN@ IF #23 LOW #195 ELSE #23 HIGH #50 THEN #mt7 TIMEOUT ;
    : b7 ' blink7 #mt7  ALARM ;
    
    : clrpin $FF0000 OUTCLR ;
    
    : BLINKEM  b0 b1 b2 b3 b4 b5 b6 b7  8 FOR #25 I * 1 + I TIMEOUT NEXT ;
    
    : STOPEM    8 FOR ' clrpin I ALARM NEXT ;
    
     END
    
    \ ?BACKUP
    
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-07-05 13:06
    caskaz wrote: »
    Hi.

    I try to understand TIMER.
    I loaded TIMER.fth.
    But any LEDs not on.
    Why?

    TIMERS are not numbered, you need to setup a TIMER <name> structure and then use that name as the address for TIMEOUT, TIMEOUT?, and ALARM.
    For instance:
    TIMER #mt0 ( creates a timer structure variable with room for a timer, an alarm vector, flags, link etc)
    : blink0 #16 PIN@ IF #16 LOW #500 ELSE #16 HIGH #50 THEN #mt0 TIMEOUT ;
    : b0 ' blink0 #mt0  ALARM 1 #mt0 TIMEOUT ;
    

    It is necessary to load and kick the timer off which is what 1 #mt0 TIMEOUT does and it also makes sure that the timer is linked into the timer list so that TIMER.TASK can service it every millisecond.
    The simple counted FOR NEXT loops won't work although there was a much earlier version of the timers years ago that were simply preallocated and numbered. I found from that that it was easier to create a timer by name and link it into a list so that we could have as many or as little timers as we liked. To stop a timer simply load it with 0 either with:
    0 #mt0 TIMEOUT
    
    or
    0 #mt0 !
    
    since the first long in the timer structure is the actual timer part.

    BTW, I see you must be using the new style FOR NEXT in V4.5 as that supports a loop index. Normally I is only used with DO LOOPs but in 4.5 all FOR NEXT loops always maintain an implied index FORM and step BY which if not specified defaults to 0 for the start index FROM and 1 for the step BY.



  • Are the alarms working with the timers? My bad code again?

    Hi caskaz

    Try this, not tested for syntax errors, away from hardware
    TACHYON V4
                  
    IFDEF timer.fth
    @rest	org
    FORGET timer.fth
    }
    
    pub timer        ." timer  2017/06/17 11:49:45 " ;
    
    @org W@	== @rest	--- remember
    
    
     \ * SIMPLE ROUTINE TO EXERCISE ALL 8 LEDS WITH TACHYON TIMERS
    \ * AND ALARMS ON THE  PROP QUICKSTART BOARD
    \ * 
    \ * USE THE WORD "BLINKEM" TO START THE LIGHTS 
    \ * AND "STOPEM" TO STOP THE LIGHTS
    
    
    TIMER mt0
    TIMER mt1
    TIMER mt2
    TIMER mt3
    TIMER mt4
    TIMER mt5
    TIMER mt6
    TIMER mt7
    
    : blink0 #16 PIN@ IF #16 LOW #500 ELSE #16 HIGH #50 THEN mt0 TIMEOUT ;     --- timer alarm rountine and reset
    B0 ' blink0 mt0  ALARM  ;                                                       ---  assign blink0 as mt0 alarm vector
    
    : blink1 #17 PIN@ IF #17 LOW #300 ELSE #17 HIGH #50 THEN mt1 TIMEOUT ;
    : B1 ' blink1 mt1  ALARM ;
    
    : blink2 #18 PIN@ IF #18 LOW #150 ELSE #18 HIGH #50 THEN mt2 TIMEOUT ;
    : B2 ' blink2 mt2  ALARM ;
    
    : blink3 #19 PIN@ IF #19 LOW #285 ELSE #19 HIGH #50 THEN mt3 TIMEOUT ;
    : B3 ' blink3 mt3  ALARM ; 
    
    : blink4 #20 PIN@ IF #20 LOW #175 ELSE #20 HIGH #50 THEN mt4 TIMEOUT ;
    : B4 ' blink4 mt4  ALARM ;
    
    : blink5 #21 PIN@ IF #21 LOW #335 ELSE #21 HIGH #50 THEN mt5 TIMEOUT ;
    : B5 ' blink5 mt5  ALARM ;
    
    : blink6 #22 PIN@ IF #22 LOW #100 ELSE #22 HIGH #50 THEN mt6 TIMEOUT ;
    : B6 ' blink6 mt6  ALARM ;
    
    : blink7 #23 PIN@ IF #23 LOW #195 ELSE #23 HIGH #50 THEN mt7 TIMEOUT ;
    : B7 ' blink7 mt7  ALARM ;
    
    : clrpin $FF0000 OUTCLR ;
    
    : BLINKEM  
       B0 B1 B2 B3 B4 B5 B6 B7    --- assign the alarm vector to timers  
       0 mt0 TIMEOUT              --- start all the timers
       0 mt1 TIMEOUT
       0 mt2 TIMEOUT
       0 mt3 TIMEOUT
       0 mt4 TIMEOUT
       0 mt5 TIMEOUT
       0 mt6 TIMEOUT
       0 mt7 TIMEOUT
    ; 
    
    : STOPEM   
      0 mt0  ALARM      --- assign the alarm vectors to null, they will stop after the last timeout.
      0 mt1  ALARM 
      0 mt2  ALARM
      0 mt3  ALARM
      0 mt4  ALARM
      0 mt5  ALARM
      0 mt6  ALARM
      0 mt7  ALARM
    ;
    
     END
    
    \ ?BACKUP
    

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-07-05 23:44
    D.P and caskaz - BLINKEM should write a non-zero TIMEOUT (usually 1). It is just as easy to put that 1 TIMEOUT in B0 to B7 after you set the ALARM.

    At startup all those timers aren't linked or recognized by Tachyon, but once user code calls TIMEOUT it links the timer in and maintains it every millisecond. Bear in mind that if the timer cog is expected to control outputs that you need to make sure that another cog hasn't tried to directly set the outputs since outputs are OR'd. Also since the timer cog services the timers every millisecond it also means that any alarm function should execute in well under a millisecond. If your alarm function requires millisecond delays etc then it is usually best if it is called on a regular basis and maintain its own prescaler to time lengthy events but of course there are lots of ways to slice and dice.
  • D.P and caskaz - BLINKEM should write a non-zero TIMEOUT (usually 1). It is just as easy to put that 1 TIMEOUT in B0 to B7 after you set the ALARM.

    At startup all those timers aren't linked or recognized by Tachyon, but once user code calls TIMEOUT it links the timer in and maintains it every millisecond. Bear in mind that if the timer cog is expected to control outputs that you need to make sure that another cog hasn't tried to directly set the outputs since outputs are OR'd. Also since the timer cog services the timers every millisecond it also means that any alarm function should execute in well under a millisecond. If your alarm function requires millisecond delays etc then it is usually best if it is called on a regular basis and maintain its own prescaler to time lengthy events but of course there are lots of ways to slice and dice.
    Got to some hardware,

    Yes I figured out that 0 is not valid for TIMEOUT.
    This works but doesn't clear all the lights after stopem? I can't even #PIN LOW, but restarting blinkem flashes them all again?

    
    TACHYON V4
                  
    IFDEF timer.fth
    @rest	org
    FORGET timer.fth
    }
    
    pub timer        ." timer  2017/06/17 11:49:45 " ;
    
    @org W@	== @rest	--- remember
    
    
     \ * SIMPLE ROUTINE TO EXERCISE ALL 8 LEDS WITH TACHYON TIMERS
    \ * AND ALARMS ON THE  PROP QUICKSTART BOARD
    \ * 
    \ * USE THE WORD "BLINKEM" TO START THE LIGHTS 
    \ * AND "STOPEM" TO STOP THE LIGHTS
    
    
    TIMER mt0
    TIMER mt1
    TIMER mt2
    TIMER mt3
    TIMER mt4
    TIMER mt5
    TIMER mt6
    TIMER mt7
    
    : blink0 #16 PIN@ IF #16 LOW #500 ELSE #16 HIGH #50 THEN mt0 TIMEOUT ;     --- timer alarm rountine and reset
    : B0 ' blink0 mt0  ALARM  ;                                                       ---  assign blink0 as mt0 alarm vector
    
    : blink1 #17 PIN@ IF #17 LOW #300 ELSE #17 HIGH #50 THEN mt1 TIMEOUT ;
    : B1 ' blink1 mt1  ALARM ;
    
    : blink2 #18 PIN@ IF #18 LOW #150 ELSE #18 HIGH #50 THEN mt2 TIMEOUT ;
    : B2 ' blink2 mt2  ALARM ;
    
    : blink3 #19 PIN@ IF #19 LOW #285 ELSE #19 HIGH #50 THEN mt3 TIMEOUT ;
    : B3 ' blink3 mt3  ALARM ; 
    
    : blink4 #20 PIN@ IF #20 LOW #175 ELSE #20 HIGH #50 THEN mt4 TIMEOUT ;
    : B4 ' blink4 mt4  ALARM ;
    
    : blink5 #21 PIN@ IF #21 LOW #335 ELSE #21 HIGH #50 THEN mt5 TIMEOUT ;
    : B5 ' blink5 mt5  ALARM ;
    
    : blink6 #22 PIN@ IF #22 LOW #100 ELSE #22 HIGH #50 THEN mt6 TIMEOUT ;
    : B6 ' blink6 mt6  ALARM ;
    
    : blink7 #23 PIN@ IF #23 LOW #195 ELSE #23 HIGH #50 THEN mt7 TIMEOUT ;
    : B7 ' blink7 mt7  ALARM ;
    
    : clrpin $FF0000 OUTCLR ;
    
    : BLINKEM  
       B0 B1 B2 B3 B4 B5 B6 B7    --- assign the alarm vector to timers  
       #10 mt0 TIMEOUT             --- start all the timers
       #20 mt1 TIMEOUT
       #30 mt2 TIMEOUT
       #40 mt3 TIMEOUT
       #50 mt4 TIMEOUT
       #60 mt5 TIMEOUT
       #70 mt6 TIMEOUT
       #80 mt7 TIMEOUT
    ; 
    
    : STOPEM   
      0 mt0  ALARM      --- assign the alarm vectors to null, they will stop after the last timeout.
      0 mt1  ALARM 
      0 mt2  ALARM
      0 mt3  ALARM
      0 mt4  ALARM
      0 mt5  ALARM
      0 mt6  ALARM
      0 mt7  ALARM
      500 ms 
      8 FOR I #16 + LOW NEXT 
    ;
    
     END
    
    \ ?BACKUP
    
    

  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-07-06 01:05
    @D.P - you are running STOPEM from the main Tachyon cog but the timer cog is the one that is using the I/O and still has the DIR set for output and if the output is high, you can't pull it low.
    Bear in mind that if the timer cog is expected to control outputs that you need to make sure that another cog hasn't tried to directly set the outputs since outputs are OR'd.

    Taking into consideration that this code is really only for a demonstration anyway perhaps we could code STOPEM by exploiting the fact that your alarm code sets the pin low (on its side) if it sees that it is high. So set the LEDs high and not low, do not disable the ALARM but simply change all the timers to 1, wait 2 ms, after which all the alarms will have set their outputs low, then write a 0 TIMEOUT for all of them and then release all the LEDs. Does that make sense? It may look awkward but that's because that's not how we would normally use the timers but the demo is useful as a learning exercise.

    Alternatively you could run STOPEM as an extra alarm function to zero all the timeouts, and turn off all the LEDs.
    Hint - rather than creating another timer for this, just use the "wdt" watchdog timer, set the alarm function for it to zero all the other timeouts and turn off the LEDs.

    EDIT: I see I have TIMERJOB just for this very thing.
    ' STOPEM TIMERJOB
    
  • @D.P - you are running STOPEM from the main Tachyon cog but the timer cog is the one that is using the I/O and still has the DIR set for output and if the output is high, you can't pull it low.
    Bear in mind that if the timer cog is expected to control outputs that you need to make sure that another cog hasn't tried to directly set the outputs since outputs are OR'd.

    Taking into consideration that this code is really only for a demonstration anyway perhaps we could code STOPEM by exploiting the fact that your alarm code sets the pin low (on its side) if it sees that it is high. So set the LEDs high and not low, do not disable the ALARM but simply change all the timers to 1, wait 2 ms, after which all the alarms will have set their outputs low, then write a 0 TIMEOUT for all of them and then release all the LEDs. Does that make sense? It may look awkward but that's because that's not how we would normally use the timers but the demo is useful as a learning exercise.

    Alternatively you could run STOPEM as an extra alarm function to zero all the timeouts, and turn off all the LEDs.
    Hint - rather than creating another timer for this, just use the "wdt" watchdog timer, set the alarm function for it to zero all the other timeouts and turn off the LEDs.

    EDIT: I see I have TIMERJOB just for this very thing.
    ' STOPEM TIMERJOB
    

    Right that OR'd thing again.

    I'll work another demo.

  • @D.P - just try that last suggestion without any changes, just ' STOPEM TIMERJOB sounds like it will work.
  • Peter JakackiPeter Jakacki Posts: 10,193
    edited 2017-07-06 14:12
    V4.5 testing has been going well and I am now testing EASYNET and tracking down that wizpin bug. A few other bugs were fixed elsewhere as well and so this version is working just fine.
    Now some notes on those changes:

    V4.5 Notes


    FOR NEXT loops now maintain an index and step count even if they are not specified.
    If they are not specified then the starting index is 0 by default and the step count
    is 1 by default. LOOP is now the same as NEXT.
    The traditional DO LOOP which uses a limit and a start index is not supported
    but ADO will take a start index and a loop count.
    +LOOP works just like NEXT except it modifies the step count
    The thing to remember about these new loops is that the loop count is the actual
    number of times that it loops for regardless of step count.

    The loop and branch stack are now in hub RAM at $180 where every loop uses
    4 longs. If Tachyon is run in other cogs that use loops then some stack space
    should be allocated. Usually 3 or 4 levels is more than enough so 64 bytes max.
    16 longs mystk
    mystk LP!
    


    Usage:
    10 FOR I . SPACE FOR@ . NEXT		--- print index and loop count
    $4000 FROM 4 BY 8 FOR I @ .LONG NEXT	--- Print 8 longs from memory at $4000
    

    FUNCTIONS
    FROM ( startindex -- )			--- Set starting index for loops (default is 0)
    BY ( stepcnt -- )			--- Set amount that index is to be incremented by (signed, default is 1)
    ADO ( startindex loopcnt -- )		--- Sets the FROM starting index before executing FOR
    FOR ( loopcnt -- )			--- Works just like a standard FOR NEXT but maintains an index and step count
    NEXT					--- decrement loopcnt and loop if not zero while incrementing index by stepcnt
    LOOP					--- alias for NEXT
    +LOOP ( stepcnt -- )			--- Change the step count then execute NEXT
    FOR@ ( -- loopcnt )			--- Fetch the current loop count
    FOR! ( loopcnt -- )			--- Overwrite the current loop count
    BY! ( stepcnt -- )			--- Overwrite the current step count
    LP! ( addr -- )				--- Set the loop stack pointer
    
  • D.PD.P Posts: 790
    edited 2017-07-06 15:10
    V4.5 testing has been going well and I am now testing EASYNET and tracking down that wizpin bug. A few other bugs were fixed elsewhere as well and so this version is working just fine.
    Now some notes on those changes:

    V4.5 Notes


    FOR NEXT loops now maintain an index and step count even if they are not specified.
    If they are not specified then the starting index is 0 by default and the step count
    is 1 by default. LOOP is now the same as NEXT.
    The traditional DO LOOP which uses a limit and a start index is not supported
    but ADO will take a start index and a loop count.
    +LOOP works just like NEXT except it modifies the step count
    The thing to remember about these new loops is that the loop count is the actual
    number of times that it loops for regardless of step count.

    The loop and branch stack are now in hub RAM at $180 where every loop uses
    4 longs. If Tachyon is run in other cogs that use loops then some stack space
    should be allocated. Usually 3 or 4 levels is more than enough so 64 bytes max.
    16 longs mystk
    mystk LP!
    


    Usage:
    10 FOR I . SPACE FOR@ . NEXT		--- print index and loop count
    $4000 FROM 4 BY 8 FOR I @ .LONG NEXT	--- Print 8 longs from memory at $4000
    

    FUNCTIONS
    FROM ( startindex -- )			--- Set starting index for loops (default is 0)
    BY ( stepcnt -- )			--- Set amount that index is to be incremented by (signed, default is 1)
    ADO ( startindex loopcnt -- )		--- Sets the FROM starting index before executing FOR
    FOR ( loopcnt -- )			--- Works just like a standard FOR NEXT but maintains an index and step count
    NEXT					--- decrement loopcnt and loop if not zero while incrementing index by stepcnt
    LOOP					--- alias for NEXT
    +LOOP ( stepcnt -- )			--- Change the step count then execute NEXT
    FOR@ ( -- loopcnt )			--- Fetch the current loop count
    FOR! ( loopcnt -- )			--- Overwrite the current loop count
    BY! ( stepcnt -- )			--- Overwrite the current step count
    LP! ( addr -- )				--- Set the loop stack pointer
    
    ' stopem TIMERJOB
    
    works correctly. But then a statem call shows the lights flashing at 23 second intervals. That's odd and familiar. As you said just a testing program to work out TIMERS.

    4.5 seems to be our new porting target from V3 then?

  • caskazcaskaz Posts: 957
    edited 2017-07-06 23:53
    Hi Peter.

    Executed [BLINKEM]. LEDs blinked.
    Executed
    ' STOPEM TIMERJOB
    
    LEDs are off.
    Again executed [BLINKEM]. This is different from 1st [BLINKEM].
    Why 2nd [BLINKEM] is not blinking?

    I use TachyonV4.4 DAWN 440170620.2200.

  • @ caskaz, yes I get the same results.
  • D.P caskaz, can you use the Forth to diagnose what the problem is? I will try later when I'm better and all I would do is exercise the code that's there and check variables. Maybe I might make .VARS display contents too. Back soon I hope
  • @caskaz, peter this code works correctly.
    
    IFDEF timer.fth
    @rest	org
    FORGET timer.fth
    }
    
    pub         ." timer  2017/06/17 11:49:45 " ;
    
    @org W@	== @rest	--- remember
    
    
     \ * SIMPLE ROUTINE TO EXERCISE ALL 8 LEDS WITH TACHYON TIMERS
    \ * AND ALARMS ON THE  PROP QUICKSTART BOARD
    \ * 
    \ * USE THE WORD "BLINKEM" TO START THE LIGHTS 
    \ * AND "STOPEM" TO STOP THE LIGHTS
    
    
    TIMER mt0
    TIMER mt1
    TIMER mt2
    TIMER mt3
    TIMER mt4
    TIMER mt5
    TIMER mt6
    TIMER mt7
    
    : blink0 #16 PIN@ IF #16 LOW #500 ELSE #16 HIGH #50 THEN mt0 TIMEOUT ;     --- timer alarm rountine and reset
    : B0 ' blink0 mt0  ALARM  ;                                                       ---  assign blink0 as mt0 alarm vector
    
    : blink1 #17 PIN@ IF #17 LOW #300 ELSE #17 HIGH #50 THEN mt1 TIMEOUT ;
    : B1 ' blink1 mt1  ALARM ;
    
    : blink2 #18 PIN@ IF #18 LOW #150 ELSE #18 HIGH #50 THEN mt2 TIMEOUT ;
    : B2 ' blink2 mt2  ALARM ;
    
    : blink3 #19 PIN@ IF #19 LOW #285 ELSE #19 HIGH #50 THEN mt3 TIMEOUT ;
    : B3 ' blink3 mt3  ALARM ; 
    
    : blink4 #20 PIN@ IF #20 LOW #175 ELSE #20 HIGH #50 THEN mt4 TIMEOUT ;
    : B4 ' blink4 mt4  ALARM ;
    
    : blink5 #21 PIN@ IF #21 LOW #335 ELSE #21 HIGH #50 THEN mt5 TIMEOUT ;
    : B5 ' blink5 mt5  ALARM ;
    
    : blink6 #22 PIN@ IF #22 LOW #100 ELSE #22 HIGH #50 THEN mt6 TIMEOUT ;
    : B6 ' blink6 mt6  ALARM ;
    
    : blink7 #23 PIN@ IF #23 LOW #195 ELSE #23 HIGH #50 THEN mt7 TIMEOUT ;
    : B7 ' blink7 mt7  ALARM ;
    
    : clrpin $FF0000 OUTCLR ;
    
    : BLINKEM  
       B0 B1 B2 B3 B4 B5 B6 B7    --- assign the alarm vector to timers  
       #10 mt0 TIMEOUT             --- start all the timers
       #20 mt1 TIMEOUT
       #30 mt2 TIMEOUT
       #40 mt3 TIMEOUT
       #50 mt4 TIMEOUT
       #60 mt5 TIMEOUT
       #70 mt6 TIMEOUT
       #80 mt7 TIMEOUT
    ; 
    
    : ALLOFF 8 FOR I #16 + LOW NEXT ;
    
    : STOPEM   
      0 mt0  ALARM      --- assign the alarm vectors to null, they will stop after the last timeout.
      0 mt1  ALARM 
      0 mt2  ALARM
      0 mt3  ALARM
      0 mt4  ALARM
      0 mt5  ALARM
      0 mt6  ALARM
      0 mt7  ALARM
      100 ms 
      ' ALLOFF TIMERJOB       --- set all the pins low in the TIMER COG context
    ;
    
     END
    
    \ ?BACKUP
    
    
  • D.P - ' STOPEM TIMERJOB would work except for the unnecessary blocking delay which is a big no-no for any timer function. Just remove the delay and combine STOPEM and ALLOFF. The earlier <mask> OUTCLR is far easier to use rather than the ALLOFF though.
  • Hi D.P.

    I tried your modified code.
    2nd [BLINKEM] is not blinking.
    It is same as uploaded movie.

  • D.P - ' STOPEM TIMERJOB would work except for the unnecessary blocking delay which is a big no-no for any timer function. Just remove the delay and combine STOPEM and ALLOFF. The earlier <mask> OUTCLR is far easier to use rather than the ALLOFF though.

    Well I had to try the FOR NEXT just to make sure I didn't miss anything in that writeup.

    And DOH! 500 ms in the TIMERJOB, that would leave a mark. So here is the last example, it works repeatedly on and off correctly, dropped the loop and MASK the OUTCLR
    IFDEF timer.fth
    @rest	org
    FORGET timer.fth
    }
    
    pub         ." timer  2017/06/17 11:49:45 " ;
    
    @org W@	== @rest	--- remember
    
    
     \ * SIMPLE ROUTINE TO EXERCISE ALL 8 LEDS WITH TACHYON TIMERS
    \ * AND ALARMS ON THE  PROP QUICKSTART BOARD
    \ * 
    \ * USE THE WORD "BLINKEM" TO START THE LIGHTS 
    \ * AND "STOPEM" TO STOP THE LIGHTS
    
    
    TIMER mt0
    TIMER mt1
    TIMER mt2
    TIMER mt3
    TIMER mt4
    TIMER mt5
    TIMER mt6
    TIMER mt7
    
    : blink0 #16 PIN@ IF #16 LOW #500 ELSE #16 HIGH #50 THEN mt0 TIMEOUT ;     --- timer alarm rountine and reset
    : B0 ' blink0 mt0  ALARM  ;                                                       ---  assign blink0 as mt0 alarm vector
    
    : blink1 #17 PIN@ IF #17 LOW #300 ELSE #17 HIGH #50 THEN mt1 TIMEOUT ;
    : B1 ' blink1 mt1  ALARM ;
    
    : blink2 #18 PIN@ IF #18 LOW #150 ELSE #18 HIGH #50 THEN mt2 TIMEOUT ;
    : B2 ' blink2 mt2  ALARM ;
    
    : blink3 #19 PIN@ IF #19 LOW #285 ELSE #19 HIGH #50 THEN mt3 TIMEOUT ;
    : B3 ' blink3 mt3  ALARM ; 
    
    : blink4 #20 PIN@ IF #20 LOW #175 ELSE #20 HIGH #50 THEN mt4 TIMEOUT ;
    : B4 ' blink4 mt4  ALARM ;
    
    : blink5 #21 PIN@ IF #21 LOW #335 ELSE #21 HIGH #50 THEN mt5 TIMEOUT ;
    : B5 ' blink5 mt5  ALARM ;
    
    : blink6 #22 PIN@ IF #22 LOW #100 ELSE #22 HIGH #50 THEN mt6 TIMEOUT ;
    : B6 ' blink6 mt6  ALARM ;
    
    : blink7 #23 PIN@ IF #23 LOW #195 ELSE #23 HIGH #50 THEN mt7 TIMEOUT ;
    : B7 ' blink7 mt7  ALARM ;
    
    : clrpin $FF0000 OUTCLR ;
    
    : BLINKEM  
       B0 B1 B2 B3 B4 B5 B6 B7    --- assign the alarm vector to timers  
       #10 mt0 TIMEOUT             --- start all the timers
       #20 mt1 TIMEOUT
       #30 mt2 TIMEOUT
       #40 mt3 TIMEOUT
       #50 mt4 TIMEOUT
       #60 mt5 TIMEOUT
       #70 mt6 TIMEOUT
       #80 mt7 TIMEOUT
    ; 
    
    
    : STOP-all
      0 mt0  ALARM      --- assign the alarm vectors to null, they will stop after the last timeout.
      0 mt1  ALARM 
      0 mt2  ALARM
      0 mt3  ALARM
      0 mt4  ALARM
      0 mt5  ALARM
      0 mt6  ALARM
      0 mt7  ALARM
      $FF0000 OUTCLR   ---   clear all pins
    ;
    
    : STOPEM ' STOP-all TIMERJOB ;
    
     END
    
    \ ?BACKUP
    
    
  • MJBMJB Posts: 1,235
    D.P wrote: »
    D.P - ' STOPEM TIMERJOB would work except for the unnecessary blocking delay which is a big no-no for any timer function. Just remove the delay and combine STOPEM and ALLOFF. The earlier <mask> OUTCLR is far easier to use rather than the ALLOFF though.

    Well I had to try the FOR NEXT just to make sure I didn't miss anything in that writeup.

    And DOH! 500 ms in the TIMERJOB, that would leave a mark. So here is the last example, it works repeatedly on and off correctly, dropped the loop and MASK the OUTCLR
    IFDEF timer.fth
    @rest	org
    FORGET timer.fth
    }
    
    pub         ." timer  2017/06/17 11:49:45 " ;
    
    @org W@	== @rest	--- remember
    
    
     \ * SIMPLE ROUTINE TO EXERCISE ALL 8 LEDS WITH TACHYON TIMERS
    \ * AND ALARMS ON THE  PROP QUICKSTART BOARD
    \ * 
    \ * USE THE WORD "BLINKEM" TO START THE LIGHTS 
    \ * AND "STOPEM" TO STOP THE LIGHTS
    
    
    TIMER mt0
    TIMER mt1
    TIMER mt2
    TIMER mt3
    TIMER mt4
    TIMER mt5
    TIMER mt6
    TIMER mt7
    
    : blink0 #16 PIN@ IF #16 LOW #500 ELSE #16 HIGH #50 THEN mt0 TIMEOUT ;     --- timer alarm rountine and reset
    : B0 ' blink0 mt0  ALARM  ;                                                       ---  assign blink0 as mt0 alarm vector
    
    : blink1 #17 PIN@ IF #17 LOW #300 ELSE #17 HIGH #50 THEN mt1 TIMEOUT ;
    : B1 ' blink1 mt1  ALARM ;
    
    : blink2 #18 PIN@ IF #18 LOW #150 ELSE #18 HIGH #50 THEN mt2 TIMEOUT ;
    : B2 ' blink2 mt2  ALARM ;
    
    : blink3 #19 PIN@ IF #19 LOW #285 ELSE #19 HIGH #50 THEN mt3 TIMEOUT ;
    : B3 ' blink3 mt3  ALARM ; 
    
    : blink4 #20 PIN@ IF #20 LOW #175 ELSE #20 HIGH #50 THEN mt4 TIMEOUT ;
    : B4 ' blink4 mt4  ALARM ;
    
    : blink5 #21 PIN@ IF #21 LOW #335 ELSE #21 HIGH #50 THEN mt5 TIMEOUT ;
    : B5 ' blink5 mt5  ALARM ;
    
    : blink6 #22 PIN@ IF #22 LOW #100 ELSE #22 HIGH #50 THEN mt6 TIMEOUT ;
    : B6 ' blink6 mt6  ALARM ;
    
    : blink7 #23 PIN@ IF #23 LOW #195 ELSE #23 HIGH #50 THEN mt7 TIMEOUT ;
    : B7 ' blink7 mt7  ALARM ;
    
    : clrpin $FF0000 OUTCLR ;
    
    : BLINKEM  
       B0 B1 B2 B3 B4 B5 B6 B7    --- assign the alarm vector to timers  
       #10 mt0 TIMEOUT             --- start all the timers
       #20 mt1 TIMEOUT
       #30 mt2 TIMEOUT
       #40 mt3 TIMEOUT
       #50 mt4 TIMEOUT
       #60 mt5 TIMEOUT
       #70 mt6 TIMEOUT
       #80 mt7 TIMEOUT
    ; 
    
    
    : STOP-all
      0 mt0  ALARM      --- assign the alarm vectors to null, they will stop after the last timeout.
      0 mt1  ALARM 
      0 mt2  ALARM
      0 mt3  ALARM
      0 mt4  ALARM
      0 mt5  ALARM
      0 mt6  ALARM
      0 mt7  ALARM
      $FF0000 OUTCLR   ---   clear all pins
    ;
    
    : STOPEM ' STOP-all TIMERJOB ;
    
     END
    
    \ ?BACKUP
    
    
    while it is nice to see many timers in action,
    to blink a few LEDs I would definitely choose a table based approach with just a single timer,
    far less code and much clearer.

    And while timers are automatically linked, they could still be put into a TABLE and referenced by indexed address instead of so many definitions. But that would definitely NOT be a beginners example any more ;-)

  • @MJB - I suppose that sometimes I tend to code something that is compact and "elegant" (i.e. simple and efficient) but it is not always obvious to others :)

    @caskaz - While I encourage anyone using Forth to always use it for debugging since it is so simple to do so, it is however helpful too if you copy and paste the text of your terminal screen as "code" so that we can see what it is that "didn't work". If you used D.P's code he last posted it should work since he checked it.

    V4.5 update

    I've fixed up a few things in EASYNET and doubled the speed of reading blocks of data from the W5500 chip too. I'm also making good use of FL which fast loads text to the specified file or to TEMP.TXT if no name is specified. At the moment you still have to hit the escape key after (or during) it has transferred and it automatically FLOADs the file. This is useful because once the dictionary has been compacted into EEPROM the searching is a lot slower, so FL allows pasting/sending a file without slowing down.

    I'm feeling the line editing pinch so I will be implementing this feature next where we can a full line and it doesn't get processed until we hit enter. I will keep a history file on EEPROM to help with interactive editing. This does not affect TACHYON block load mode though, it will still compile word by word, number by number, with case sensitivity.

    FEATURE REQUEST
    I was thinking about this the other day that some of you fellow Tachyonites may be secretly wishing "oh, if only". So here's your chance, spell out your request, and if possible, I will see if I can implement it. You never know where this leads.
  • MJBMJB Posts: 1,235
    edited 2017-07-09 00:33
    @MJB - I suppose that sometimes I tend to code something that is compact and "elegant" (i.e. simple and efficient) but it is not always obvious to others :)
    Hi Peter,
    yes - right, you
    tend to code something that is compact and "elegant" (i.e. simple and efficient) but it is not always obvious to others :)
    quite often ;-)

    But if you are referring to @caskaz's / D.P.'s example above, which is definitely 'simple/straight forward', but not as elegant and efficient with all the code duplication ... (except for demonstration of timers) then I am really missing something ....
    What ??
    I expected you to agree to my statement ;-)

    I'm feeling the line editing pinch so I will be implementing this feature next where we can a full line and it doesn't get processed until we hit enter. I will keep a history file on EEPROM to help with interactive editing. This does not affect TACHYON block load mode though, it will still compile word by word, number by number, with case sensitivity.
    hmm -
    I really liked the immediate compilation which tells if a word is misspelled / unknown immediately.
    Not sure if getting this only at the end of the line is better ... ???



  • @MJB, Hah! just happen to check the forum with a glass of Knappstein red in hand :)

    The demo code that D.P used was simple but not at all efficient, but it was good for the purpose of getting a feel of timers and in the process learning about how to use them and things to avoid like multiple cogs accessing I/O or using delays in timer alarms. So my post was an observation and also an acknowledgement.

    If I introduce line editing and history that doesn't preclude word by word compilation since that is also the mode that TACHYON END block load mode uses. I'm also thinking of also making this detect if a file system is present and automatically perform a FL fast load. Any "improvements" only increase our options, never limit them.
  • Hi D.P.

    I trued your latest code.
    BLINKEN <-- Starting LED blinking
    STOPEN <-- Blinking stop but some LEDs still on
    BLINKEN <-- Re-starting LED blinking
    STOPEN <-- Blinking stop but some LEDs still on

    I retry BLINKEN & STOPEN.
    Sometimes all LED are off.
    Why?
  • caskaz - can you show us a copy & paste of your terminal screen? Are you typing ' STOPEM TIMEJOB to stop them?

    paste terminal screen as "code" like this:
    Propeller .:.:--TACHYON--:.:. Forth V4X5 DAWN 450170705.1015
    
    MODULES LOADED: 
    50DC: EASYNET.fth         WIZNET NETWORK SERVERS 170421.0000 
    484C: W5500.fth           WIZNET W5500 driver 170708.0000 
    
    35DA: EASYFILE.fth        SDHC card + FAT32 Virtual Memory Access File System Layer V1.2 170705-1120 
    1B00: EXTEND.fth          Primary extensions to TACHYON V4.5 kernel  - 170706-0930
    AUTORUN 
    FREQ = 96.0MHz
    *** INITS ***
    INIT#0 3B60 
    INIT#1 5D38 EASYNET
    Loading cog 3 E50A F32     
    *** ROMS ***
    0,848 VGA32x15  
    0,392 HSUART    
    1,900 F32       
    *** I2C ***
    A0 EEPROM
    
    INTERCOM: &00.00.00.00 @2,000,000
     CODE:$5D8E =23438 bytes   NAME:$66AE =3410 bytes   DATA:$7A6E =1118 bytes    =2336 bytes free    Data Stack (0)
    
    
    Mounted D20D.AA60-CB4A.74CF mkfs.fat IOT5500     FAT32   7,947MB (4,096/cluster)
    *** Tachyon Forth EASYNET Network Servers and EASYFILE File Server *** 
    
     ... ready! 
    
    NETWORK STATUS:
    LINK *UP*
    HARDWARE: WIZnet W5500 V4
    SRC IP    192.168.000.098
    MASK      255.255.255.000
    GATEWAY   192.168.000.001
    MAC       02.FF.2F.2B.7F.A7.
    SKT HH:MM:SS MODE  PORT  DEST TXRD TXWR RXRD RXWR RXSZ  IR STATUS            IP ADDR
    #1  00:00:03 TCP     21 35942     .    .    .    .    . 00 14 LISTEN       
    #3  00:00:03 TCP  10001 55672     .    .    .    .    . 00 14 LISTEN       
    #4  00:00:03 TCP     80 54052     .    .    .    .    . 00 14 LISTEN       
    
    * WEB, FTP, and TELNET servers running * 
    --------------------------------------------------------------------------------
    ( 0001 $5D8E  ok )   
    Mounted D20D.AA60-CB4A.74CF mkfs.fat IOT5500     FAT32   7,947MB (4,096/cluster)
    
  • [/quote]
    while it is nice to see many timers in action,
    to blink a few LEDs I would definitely choose a table based approach with just a single timer,
    far less code and much clearer.

    And while timers are automatically linked, they could still be put into a TABLE and referenced by indexed address instead of so many definitions. But that would definitely NOT be a beginners example any more ;-)

    [/quote]
    How about some source MJB. For me it's about participating in the Tachyon thread with source where/when I can. Also you never know what source could find a little bug in the kernel. This practice source also reinforced the rule "timer code cannot exceed the 1 ms execution or things becomes bad, quickly"
    caskaz wrote: »
    Hi D.P.

    I trued your latest code.
    BLINKEN <-- Starting LED blinking
    STOPEN <-- Blinking stop but some LEDs still on
    BLINKEN <-- Re-starting LED blinking
    STOPEN <-- Blinking stop but some LEDs still on

    I retry BLINKEN & STOPEN.
    Sometimes all LED are off.
    Why?
    Hi caskaz,

    I've tried the source a bunch of times and it works correctly, will download the lastest 4x5 spin and extend and try again.

    I will update this post with results.



  • FEATURE REQUEST:

    I would like those:
    iomask IN: dira 0
    iomask OUT: dira 1

    iomask LOW: outa 0
    iomask HIGH: outa 1

    I know dira 0 is the same as iomask INPUTS
    and dira 1 is the same as iomask OUTPUTS
    but I can't make output high or low whitout touching the dira register also.
Sign In or Register to comment.