Shop Learn
How does one stop a cog in Tachyon NEON 5r6? — Parallax Forums

How does one stop a cog in Tachyon NEON 5r6?

I am just starting to experiment with Tachyon Forth NEON 5r6. In the glossary it says there is a word STOP ( cog ---) that is supposed to stop a cog once it is running a word. When I try to use stop I get an error:

STOP ??? like it isn't in the dictionary. I wanted to know how to stop a cog once it is executing a word and return it to the task list so it can be restarted again. Can anyone help me with that? Also, is there a word like .S to show the stack? Where can I find an accurate glossary, or other documentation?



  • MJBMJB Posts: 1,200
    if you are just starting then you can do a lot of experiments in the console cog without usin g an other cog.

    And you do not have to stop a Tachyon cog at all. Just give it another task to do.
    A bit late here to elaborate now.

    .S should be there to show the stack

  • Peter JakackiPeter Jakacki Posts: 10,164
    edited 2019-12-08 01:22
    I really don't have time to design hardware and software for the P1 and P2 and other chips, and document everything, The glossary is incomplete and out of date and really needs some user input behind it where I can simply assist and fill in the blanks and answer questions. Use COGSTOP to stop a cog but you can also use

    There are other words such as LOADCOG etc that can load a cog from named binaries in upper EEPROM, treating these as if they were ROMs.

    Here is a section of code from EXTEND that allows "TASKS" to be run in cogs which have been preloaded with the Tachyon kernel and sitting in an idle loop, waiting for a job. If your job or task exits then it will simply return to the idle loop.
    However if you are simply testing bits of code you are better off just running that in the main Tachyon console. If your code locks up in an endless loop you can also send a terminal break which is recognized by the serial receive cog and reboots Tachyon.

    --- Find the next available cog that's free to run a task - ready and in IDLE
    pub TASK? ( -- task )
    	8 BEGIN 1- DUP TASK @ $1.0000 = OVER 0< OR UNTIL
    pub RUN ( pfa cog -- | USAGE: ' MYTASK TASK? RUN )
     	DUP 0 7 WITHIN IF TASK W! ELSE CR PRINT" Error - cog out of range " THEN
    --- run following code as a task in cog n
    pub RUN: ( n <code> -- )	R> SWAP RUN ;
    --- example: pri SENSORS	3 RUN: BEGIN 12 13 DISTANCE mm W! 15 DHT 'c W! rh W! 60 ms AGAIN ;
    \ Set starting address of a task's registers
    pub TASKREGS ( addr -- )		8 COG! ;
    pub COGINIT ( code pars cog -- ret ) 	 SWAP 16 << OR SWAP 2 << OR pCOGINIT ;
  • I am working on a project where I am pulse width modulating a analog meter movement. I want to have that routine running in a cog such that I can write a value to a variable in main memory that is read and displayed by the meter driving cog. Then I will have other cogs assigned to different tasks, such as measuring rpm and displaying that was well as distance measuring. So I wrote the routine and it is working great when I send it to a cog. The problem is that when I send another word to the cog, it continues to drive the meter and ignores the new word.

    I'm evaluating whether I can use Tachyon for other projects/ I am used to using polyFORTH, from FORTH, Inc. and Tachyon is sufficiently different due to the architecture of the Propeller for one thing. Also, Peter does things differently than I am used to. Just trying to get up to speed with his way of doing things. Yes, I found your comment about .S was there. I was trying to do it in lower case. I am used to not being case sensitive.

    I want to know how to start and stop cogs in order to change the tasks they do. I opened the glossary and couldn't find the answers to the question, since many of the commands listed didn't work as advertised. STOP ( cog --- ) being one of them. I could kill the routine with COGSTOP, but then it wouldn't start up again with a RUN command.
  • Peter, I am very impressed with the work you are doing and I can't imagine how busy you must be-seeing all the things you are working on. You do a good job. I don't understand enough to be helpful at this point. I am expecting to get a P2 soon and start with that project. The P1 is just too useful to ignore though. I have used it for a lot of things. Thank you for all the help. I'm sure to need more as time goes on.
  • Peter JakackiPeter Jakacki Posts: 10,164
    edited 2019-12-08 02:17
    There is already a 32-channel high frequency 8-bit PWM task built into Tachyon. Just start it up with the base frequency and pins and then you can call a routine to set the duty cycle for that channel(s). Since it is table based you can even output various waveforms or achieve higher frequencies at lower resolutions etc.

    As explained previously there are Tachyon cogs sitting idle ready to receive a task. This is not the same as coginit since the cogs have already been preloaded with an instance of Tachyon.

    The idle loop as shown below is very simple and calls the user code. It is up to the user code to return control back to the idle loop. The only way to otherwise override a non-compliant task is to reload that cog with an instance of Tachyon.

    As for many other Forths, I find that they are PC-centric, especially if they adhere to the "standards", since the standards themselves are PC-centric. Forth's greatest strength lies in providing a high-level interactive development environment on embedded micros, not in optimizing target compilation from a PC. Anyone working with the Propeller is already aware that they are not in Kansas anymore, and Tachyon does things not only the Propeller way, but also geared for real commercial turnkey products since that is what I developed it for.

    The other way to drive an analog meter is to simply use a hardware counter duty mode (not PWM) and an RC filter via the DAC word.
    --- Write an 8-bit value to the pin as a duty cycle - filter output for a voltage
    pub DAC! ( byte pin -- )	DUP LOW APIN DUTY 24 <<
    --- Set the value of the current FRQ either A or B
    pub FRQ ( n --  )		FRQA +CTR COG! ;
    --- Use duty cycle mode plus RC on a pin to generate a voltage from 0 to 3.3V (3.300 4 VOLTS)
    pub VOLTS ( volts.nnn pin -- )
    	DUP LOW APIN ABS 3300 MIN 130150.524 1000 */ DUTY FRQ

    : IDLE 		
    ---	Init Return stack and reset task job vector
    	!RP 0 COGID TASK W! 
    ---	  Init stack and set task flag and idle for 8ms (saves power)
    	  !SP 1 COGID TASK 2+ C! 8 ms 
    ---	  wait until a job is assigned
    ---	  Make sure it is not low-level kernel code and run it
    	  DUP 8>> IF ACALL THEN

    Here is the demo code for the 32 channel PWM from the EXTEND source which sets up P0..P15 up as pwm outputs at 7600Hz.
    ( TESTING )
    256 longs pwms
    $FFFF pwms 7600 PWM.START
    256 longs pwmtbl
    : PWM.DEMO
    	$00.FF.00.00 pwmtbl 7600 PWM.START
     	16 FROM 8 FOR I 14 - 20 * I PWM NEXT
  • ErNaErNa Posts: 1,557
    Hi Steve, it's hard to find a superlative in this time, where average is great, ordinary people are the best people, extremly smart, highly experienced, and you go to the market place in the afternoon and you ask the innocent question: why for heavens sake, when you turn water to sake, the best quality comes last and you can have qualities that where never imagined? So let me state: Peter is a averaged talented man, he's just able to squeeze 48 hours into one day and so he does what seems impossible. But still he is humble and so gives us an opportunity to do contributions ourselves to the Tachyon opus.
    In my current work I really would like to use Tachyon, but if you have a multi process application, you can not just switch this to Tachyon, being a novice. There is this damned learning curve.
    But with the event of P2 things will change, as Tachyon can be used to explore the P2 and many people will become acqainted.
    Whenever I have the P2D2 on my table, this journey for me will start. But I see the need to have a common mechanism to connect different processes transparently, may they be coded in any language. I will start over to show, how I do this in SPIN and ASM and how to improve my solution to make a common interface.
  • Yes, there is the learning curve, which I am in the middle of. I am doing what you described as multi process application. I have it basically working with Spin, and am now starting over and re-coding it with Tachyon, hence my learning curve. So far, it is going well. The answers to this posting have helped me move to another level my understanding of what I can do with Tachyon. I love the way I can factor my application into sections and run them in different cogs. I am driving an analog meter (50 uA) movement with a PWM signal because they are easy to read in bright sunlight. All of my other sensors are assigned to a different cog to keep there particular variables updated constantly. Then I have my main cog read the input switches and display the data. That is why I was trying to learn how to start and stop cogs because I was putting the sensor cogs in an endless loop, keeping their portion of the data updated. I have now learned how to do that by having a method to exit the loop and return to the idle loop as shown by .TASKS I am starting to get more comfortable with Tachyon and will continue to learn more.
  • Peter JakackiPeter Jakacki Posts: 10,164
    edited 2019-12-09 03:10
    Steve, you should use the simple RC circuit with a counter driving it to output an analog voltage as this frees up a cog. If you want 1V output on pin 5 just try "1.000 5 VOLTS" and a simple 1k + 100nf or so will produce a 1V signal. You may not even need this RC as the meter may filter the signal anyway although there are some very high frequency components in there.
    The VOLTS word will use the currently selected counter which defaults to A but you can change that by using "B" somewhere before the VOLTS word. If 5 and 6 were RC outputs I could output 1V and 2.5V like this:
    A 1.000 5 VOLTS   B 2.500 6 VOLTS

    One cog is setup as a background timer that every millisecond maintains the runtime counter, the time of day (which is loaded from a real RTC at reset), and user counters. These user counters normally countdown and optionally execute a user vector. If every 100ms you wanted to check a switch and perform some action, then this is how you could do it:
    TIMER mytimer  --- create a timer structure
    : MYALARM     
    ---	setup an alarm to initially trigger in 10ms
    	10 mytimer ALARM:
    ---	reload the timer for another 100ms
    	100 mytimer TIMEOUT

    When mytimer is first invoked through a TIMEOUT operation (automatically set with ALARM:) then it is linked into a list of background timers that are maintained every millisecond. The timer cog then scans this list and looks up the timer, and if it is non-zero, it will decrement it, and if it becomes zero it will check for and execute an alarm vector. The timers can be passive countdown or countup. Browse the EXTEND source for more information.

    BTW - The decimal point embedded in a number is simply for aesthetics although the position of the dp is available. A dp at the end of a number signifies that it is a double long or 64-bits.

    To improve readability I prefer to use lower case for variables and passives and uppercase for active words that do something other than push a value.

Sign In or Register to comment.