The lessons learned are documented here to maybe help other Propeller users:
0. Debugging of other COG methods can not used LCD, TERM or TV output, those types of Objects are not multi-COG aware. Use global variable to provide debug information back to the main program where the LCD, TERM or TV Object initialized those objects and "print" can be used.
1. Parameters passed by reference can be used with any method and the cognew statement
2. The calling statement should appear as:
- some_method ( @some_variable )
- long [ pArg ] := some_value
- set_some_variable := long [ pArg ]
- some_method ( @some_array )
- long [ pArg ] [ some_array_index ] := some_value
- some_variable := long [ pArg ] [ some_array_index ]
- long [ pArg [ some_array_index ] ] := some_value - IS WRONG
These ideas appear simple now, but they were learned (very much) the hard way, where the manual and simple examples were not much help.
This following is a contrived test program to simulate a long running background task, where control and progress can be monitored from the calling method.
CON WMin = 381 _CLKMODE = XTAL1 + PLL16X _XINFREQ = 5_000_000 CLK_FREQ = ((_clkmode-xtal1)>>6)*_xinfreq MS_001 = CLK_FREQ / 1_000 ' INFO for LCD #16, LCD_RS, LCD_RW, LCD_E, LCD_BL #12, LCD_DB4, LCD_DB5, LCD_DB6, LCD_DB7 #16, COLS #2, ROWS ' Arg Array Element Names, iSIZE must be last #0, iCTL, iSTAT, iPROGRESS, iSIZE ' Process Control States #0, cRUN, cABORT, cREPORT ' Returned Status States #0, sNOTSTARTED, sINIT, sRUNNING, sFINISHED, sABORTED OBJ LCD : "jm_lcd4_ez" ' Rev 1.4 VAR PUB Demo | subCogId, okay, Args[iSIZE], Stack ' Args and Stack could be Globals Args[iCTL] := cRUN Args[iSTAT] := sNOTSTARTED Args[iPROGRESS] := 99 LCD.Startx(LCD_BL, LCD_E, LCD_RW, LCD_RS, LCD_DB4, COLS, ROWS) LCD.cmd(LCD#CLS) ' Clear Screen LCD.blon LCD.str(string("Init:")) LCD.moveto(1,2) LCD.str(string("Stat: ")) LCD.moveto(8,2) LCD.str(string(",Prg:")) pauseSec(2) Args[iSTAT] := sINIT ' Assume RUNNING State okay := subCogID := cognew(mySUB2(@Args), @Stack) LCD.dec(okay) ' Report the New COG's Progress repeat while Args[iSTAT] < sFINISHED LCD.moveto(6,2) LCD.rjdec(Args[iSTAT], 2, " ") LCD.moveto(13,2) LCD.rjdec(Args[iPROGRESS], 3, " ") LCD.out("%") if Args[iPROGRESS] =< 75 ' To simulate an ABORT required condition Args[iCTL] := cABORT pause(200) ' Report Final Results LCD.moveto(6,2) LCD.rjdec(Args[iSTAT], 2, " ") LCD.moveto(13,2) LCD.rjdec(Args[iPROGRESS], 3, " ") pauseSec(1) LCD.moveto(1,1) LCD.str(string("Finished: ")) repeat ' Keep alive pauseSec(1) PUB mySUB2(pArgs) ' A simple cog, that calls yet another Method mySUB1(pArgs) PUB mySUB1(pArgs) pauseSec(2) ' Simulate Initization time long[pArgs][iSTAT] := sRUNNING repeat while long[pArgs][iPROGRESS] > 0 if long[pArgs][iCTL] == cABORT long[pArgs][iSTAT] := sABORTED QUIT long[pArgs][iPROGRESS]-- pause(200) ' This is the dummy program process activity long[pArgs][iSTAT] := sFINISHED DAT PRI pauseSec(sec) pause(1000 * sec) PUB pause(ms) waitcnt(((clkfreq / 1_000 * ms - 3932) #> WMin) + cnt) DAT
This program does not represent good Propeller programming practices, it was contrived just to understand parameter passing by reference. A typical or more correct strategy would use methods to control and report status of the sub COG or other methods.
Thanks Jeff, for the help
It is all fun with the Prop.
Lesson Learned Number "6."; has bitten me twice since this was first posted: Give the COG More Stack Space ! For now I am starting with 64 Longs, and will trim only if necessary. Previously I was using 16 or maybe 32 Longs for "cognew" stacks.