The lessons learned are documented here to maybe help other Propeller users:
Lessons Learned
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
- or
- set_some_variable := long [ pArg ]
- some_method ( @some_array )
- long [ pArg ] [ some_array_index ] := some_value
- some_variable := long [ pArg ] [ some_array_index ]
- but
- long [ pArg [ some_array_index ] ] := some_value - IS WRONG
Conclusion
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[32] ' 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.
UPDATE
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.
--
No comments:
Post a Comment