(Help) I can't do anything right with PASM today, even a simple timer loop
I feel like I'm in the twilight zone ...
I know the second code block is long (it is there in case someone wanted to compile the whole thing), but it is a PASM template I use and the important part of the code I have put in the first code block, as well as its output to the PST in the quotation. I tried to do a simple timer to check an issue with another code block and I can't even get the timer to work. Does everyone have these days or is it just me?
startTime (1834539093) - endTime (1834707489) is not 2 as Pst16 indicates, it's actually 168396 which I don't think it correct either as it shouldn't be that high, it should be around 100 cycles.
The entire code for compilation, is below
I know the second code block is long (it is there in case someone wanted to compile the whole thing), but it is a PASM template I use and the important part of the code I have put in the first code block, as well as its output to the PST in the quotation. I tried to do a simple timer to check an issue with another code block and I can't even get the timer to work. Does everyone have these days or is it just me?
restart
mov startTime, cnt
add alive, #1
wrlong alive, pstPtr13
wrlong pinMask, pstPtr1
wrlong pin, pstPtr2
end
mov endTime, cnt
wrlong startTime, pstPtr14
wrlong endTime, pstPtr15
sub endTime, startTime
wrlong endTime, pstPtr16
jmp #restart
From the PST wrote:Pst1: 00000000000000000000000000010000
Pst2: 4
Pst3: 16
Pst4: 0
Pst5: 0
Pst6: 0
Pst7: 0
Pst8: 0
Pst9: 0
Pst10: 0
Pst11: 0
Pst12: 0
Pst13: 261657325
Pst14: 1834539093
Pst15: 1834707489
Pst16: 2
startTime (1834539093) - endTime (1834707489) is not 2 as Pst16 indicates, it's actually 168396 which I don't think it correct either as it shouldn't be that high, it should be around 100 cycles.
The entire code for compilation, is below
{
WHAT OBJECT SHOULD DO GOES HERE
}
CON
_CLKMODE = XTAL1 + PLL16X
_CLKFREQ = 80_000_000
' current code only allows from 1Hz upwards
MIN_FREQUENCY = 1
' dunno which upper limit can be achieved by the SPIN-code
MAX_FREQUENCY = 9200
BAUDRATE = 115_200
_byteLimit = 100
OBJ
pst : "Parallax Serial Terminal"
n : "Numbers"
VAR
byte b_delimiter, b_prefix[_byteLimit], b_suffix[_byteLimit]
byte b_waitingToBeParsed[_byteLimit]
byte b_byteMoveIndex
byte b_RxString[_byteLimit]
' Shared cog/hub variables and addresses
long l_cog
long l_pst1
long l_pst2
long l_pst3
long l_pst4
long l_pst5
long l_pst6
long l_pst7
long l_pst8
long l_pst9
long l_pst10
long l_pst11
long l_pst12
long l_pst13
long l_pst14
long l_pst15
long l_pst16
long l_pin
' Non pst shared
' Non shared
long l_tmp
long l_updateRateDenominator, l_sendAllValuesOnce, l_sendAllValues, l_myReceivedByte
' Test variables here
long l_updateTest
long l_cntTest
long l_prefix
long l_suffix
pub main
b_delimiter := "="
l_updateTest := 2
pst.Start( BAUDRATE )
l_tmp:=-1
repeat while l_tmp==-1
pst.str( string( " ",$0d,"== please press key to start ==",$0d ) )
l_tmp:=pst.rxcheck
if l_tmp==-1
waitcnt( clkfreq+cnt )
pst.Clear
pst.str( string( "Starting COG!",$0d ) )
pstInitScreen
l_pin := 4
init(0)
{pst.str(string("updateTest value: "))
pst.dec(l_updateTest)
pst.char(13)}
repeat
pstCom
{l_cntTest += 1
waitcnt((clkfreq/10)+ cnt)
pst.dec(l_updateTest)
pst.char(13)}
pub init(tmp)
waitcnt((clkfreq*1) + cnt) ' let screen initialize
return l_cog := cognew(@pasmstart, @l_cog) + 1
PUB pstCom | lpcnt1,lpcnt2, timeStamp
lpcnt1:=0
lpcnt2:=0
timeStamp := cnt
'repeat
charAt( 12,2 , proc[ lpcnt1 ] )
lpcnt1 := (lpcnt1+1) & 3
charAt( 28,2 , proc[ lpcnt2 ] )
lpcnt2 := (lpcnt2+1) & 3
charAt( 12, 4, " " ) ' ("object1 cog:") )
pst.Dec(l_cog)
pst.str(@spaces)
charAt( 43, 4, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 72, 4, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 102, 4, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 12, 5, " " ) ' (":") )
pst.Dec(-7)
pst.str(@spaces)
charAt( 43, 5, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 72, 5, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 102, 5, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 12, 6, " " ) ' (":") )
pst.dec(-7)
pst.str(@spaces)
charAt( 43, 6, " " ) ' ( ":" ) )
pst.dec(-7)
pst.str(@spaces)
charAt( 72, 6, " " ) ' ( ) )
pst.dec(-7)
pst.str(@spaces)
charAt( 102, 6, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 12, 7, " " ) ' (":" ) )
pst.dec(-7)
pst.str(@spaces)
charAt( 43, 7, " " ) ' (":") )
pst.dec(-7)
pst.str(@spaces)
charAt( 72, 7, " " ) ' (":") )
pst.dec(-7)
pst.str(@spaces)
charAt( 102, 7, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 12, 8, " " ) ' (":" ) )
pst.dec(-7)
pst.str(@spaces)
charAt( 43, 8, " " ) ' (":") )
pst.dec(-7)
pst.str(@spaces)
charAt( 72, 8, " " ) ' (":") )
pst.dec(-7)
pst.str(@spaces)
charAt( 102, 8, " " ) ' ( ":" ) )
pst.Dec(-7)
pst.str(@spaces)
charAt( 12, 9, " " ) ' (":" ) )
pst.dec(-7)
pst.str(@spaces)
charAt( 12, 21, " " ) ' ("Pst1:") )
pst.bin(getPst1, 32)
pst.str(@spaces)
charAt( 12, 22, " " ) ' ("Pst2:") )
pst.dec(getPst2)
pst.str(@spaces)
charAt( 12, 23, " " ) ' ("Pst3:") )
pst.dec(getPst3)
pst.str(@spaces)
charAt( 12, 24, " " ) ' ("Pst4:") )
pst.dec(getPst4)
pst.str(@spaces)
charAt( 12, 25, " " ) ' ("Pst5:") )
pst.dec(getPst5)
pst.str(@spaces)
charAt( 12, 26, " " ) ' ("Pst6:") )
pst.dec(getPst6)
pst.str(@spaces)
charAt( 12, 27, " " ) ' ("Pst7:") )
pst.dec(getPst7)
pst.str(@spaces)
charAt( 12, 28, " " ) ' ("Pst8:") )
pst.dec(getPst8)
pst.str(@spaces)
charAt( 12, 29, " " ) ' ("Pst9:") )
pst.dec(getPst9)
pst.str(@spaces)
charAt( 12, 30, " " ) ' ("Pst10:") )
pst.dec(getPst10)
pst.str(@spaces)
charAt( 12, 31, " " ) ' ("Pst11:") )
pst.dec(getPst11)
pst.str(@spaces)
charAt( 12, 32, " " ) ' ("Pst12:") )
pst.dec(getPst12)
pst.str(@spaces)
charAt( 12, 33, " " ) ' ("Pst13:") )
pst.dec(getPst13)
pst.str(@spaces)
charAt( 12, 34, " " ) ' ("Pst14:") )
pst.dec(getPst14)
pst.str(@spaces)
charAt( 12, 35, " " ) ' ("Pst15:") )
pst.dec(getPst15)
pst.str(@spaces)
charAt( 12, 36, " " ) ' ("Pst16:") )
pst.dec(l_updateTest)'getPst16)
pst.str(@spaces)
if (l_sendAllValuesOnce == 1)
if(cnt > (timeStamp + (clkfreq/l_updateRateDenominator)))
sendValues
l_sendAllValuesOnce := 0
if (l_sendAllValues == 1)
sendValues
l_myReceivedByte := pst.RxCheck
if l_myReceivedByte <> -1
b_waitingToBeParsed[b_byteMoveIndex++] := l_myReceivedByte
'pst.str(@b_waitingToBeParsed)
'pst.str(string(pst#NL))
if l_myReceivedByte == 13
DelimiterFinder(@b_waitingToBeParsed)
ByteFill(@b_waitingToBeParsed, 0, strsize(@b_waitingToBeParsed))
b_byteMoveIndex := 0
'printAt(12, 41, " ")
'pst.str(b_prefix)
'printAt(12, 42, " ")
'pst.str(b_suffix)
PUB sendValues | localIndex, pstSendAllValues
' Initialize variables here
localIndex := 0
pstSendAllValues := 0
printAt(1,40, String("sendAllValues()"))
PUB pstInitScreen
printAt( 1,2, string("Main loop [ ]") )
printAt( 20,2, string("Update [ ]") )
printAt( 3,4, string("cog:") )
printAt( 33, 4, string( "cog:" ) )
printAt( 63,4, string("cog:") )
printAt( 93,4, string("cog:") )
printAt( 3,5, string("crGap RPM:") )
printAt( 33, 5, string( "caGap RPM:" ) )
printAt( 63,5, string("+Degrees:") )
printAt( 93,5, string("Targ Ang:") )
printAt( 3,6, string("crTth RPM:") )
printAt( 33, 6, string( "caTth RPM:" ) )
printAt( 63, 6, string( ":" ) )
printAt( 93, 6, string( "angDiff:" ) )
printAt( 3,7, string("crGapTime:" ) )
printAt( 33,7, string("caGapTime:") )
printAt( 63,7, string("cr-CaTime:") )
printAt( 93,7, string("hz:") )
printAt( 3,8, string("crAvgCyc:") )
printAt( 33,8, string("caAvgCyc:") )
printAt( 63,8, string("Cycl/Deg:") )
printAt( 93,8, string("hzCycles:") )
printAt( 3,9, string("toothNum:") )
{printAt( 33,8, string("T Cnt Max") )
printAt( 3,9, string("Min") )
printAt( 33,9, string("Max") )
printAt( 3,10, string("Gap Cnt") )
printAt( 33,10, string("Gap Cnt/Sec") )
printAt( 33,11, string("Gap Rpm:") ) }
printAt( 3,21, string("Pst1:") )
printAt( 3,22, string("Pst2:") )
printAt( 3,23, string("Pst3:") )
printAt( 3,24, string("Pst4:") )
printAt( 3,25, string("Pst5:") )
printAt( 3,26, string("Pst6:") )
printAt( 3,27, string("Pst7:") )
printAt( 3,28, string("Pst8:") )
printAt( 3,29, string("Pst9:") )
printAt( 3,30, string("Pst10:") )
printAt( 3,31, string("Pst11:") )
printAt( 3,32, string("Pst12:") )
printAt( 3,33, string("Pst13:") )
printAt( 3,34, string("Pst14:") )
printAt( 3,35, string("Pst15:") )
printAt( 3,36, string("Pst16:") )
DAT
org 0
pasmstart
add cogPtr, par
add pstPtr1, par
add pstPtr2, par
add pstPtr3, par
add pstPtr4, par
add pstPtr5, par
add pstPtr6, par
add pstPtr7, par
add pstPtr8, par
add pstPtr9, par
add pstPtr10, par
add pstPtr11, par
add pstPtr12, par
add pstPtr13, par
add pstPtr14, par
add pstPtr15, par
add pstPtr16, par
add pin, par
initialize
rdlong pin, pin
mov ctra, POS_DETECT ' ctra measures high phase
add ctra, pin
mov frqa, #1
mov ctrb, NEG_DETECT ' ctrb measures low phase
add ctrb, pin
mov frqb, #1
mov pinMask, #1 ' create pin mask
shl pinMask, pin
mov ina, pinMask
mov inb, pinMask
mov loopCnt, cnt
restart
mov startTime, cnt
add alive, #1
wrlong alive, pstPtr13
wrlong pinMask, pstPtr1
wrlong pin, pstPtr2
end
mov endTime, cnt
wrlong startTime, pstPtr14
wrlong endTime, pstPtr15
sub endTime, startTime
wrlong endTime, pstPtr16
jmp #restart
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Unsigned Divide
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LNDivide mov LNDivideQuotient, #0 ' Setup to divide.
mov LNDivideBuffer, #0 '
mov LNDivideCounter, #32 '
cmp LNDivideDivsor, #0 wz ' Clear if dividing by zero.
if_z mov LNDivideDividend, #0 '
if_z jmp #LNDivide_ret '
LNDivideLoopPre shr LNDivideDivsor, #1 wc, wz ' Align divisor MSB and count size.
rcr LNDivideBuffer, #1 '
if_nz djnz LNDivideCounter, #LNDivideLoopPre '
LNDivideLoopPost cmpsub LNDivideDividend, LNDivideBuffer wc ' Preform division.
rcl LNDivideQuotient, #1 '
shr LNDivideBuffer, #1 '
djnz LNDivideCounter, #LNDivideLoopPost '
'wrlong LNDivideQuotient, pstptr7
'wrlong LNDivideDividend, pstptr8
mov divisionResult, LNDivideQuotient
LNDivide_ret ret ' Return. Remainder in dividend on exit.
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Unsigned Multiply
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LNMultiply mov LNMultiplyProduct, #0 ' Clear product.
LNMultiplyLoop shr LNMultiplyMultiplicand, #1 wc ' Preform multiplication.
if_c add LNMultiplyProduct, LNMultiplyMultiplier '
shl LNMultiplyMultiplier, #1 '
tjnz LNMultiplyMultiplicand, #LNMultiplyLoop '
mov multiplicationResult, LNMultiplyProduct
LNMultiply_ret ret ' Return.
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' Data
' /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
' --------------------------------------------------------------------------------------------------
cogPtr long 0
pstPtr1 long 4
pstPtr2 long 8
pstPtr3 long 12
pstPtr4 long 16
pstPtr5 long 20
pstPtr6 long 24
pstPtr7 long 28
pstPtr8 long 32
pstPtr9 long 36
pstPtr10 long 40
pstPtr11 long 44
pstPtr12 long 48
pstPtr13 long 52
pstPtr14 long 56
pstPtr15 long 60
pstPtr16 long 64
pin long 68
' Standard variables here
divisionResult long 0
multiplicationResult long 0
startTime long 0
startTimeT long 0
prevStartTime long 0
endTime long 0
alive long 0
prevLoopCnt long 0
loopCnt long 0
loopCntT long 0
timer long 0
' Variables with non 0 values here
clk long 80000000
phaseOne long 1
phaseTwo long 2
phaseThree long 3
phaseFour long 4
phaseFive long 5
phaseSix long 6
phaseSeven long 7
POS_DETECT long %01000 << 26
NEG_DETECT long %01100 << 26
tix long 100000
' Temporary variables here
loopCountTemp long 0
' Reserved variables here
tmp1 res 1
tmp2 res 1
pinMask res 1 ' mask for frequency input pin
' //////////////////////Math Run Time Variables/////////////////////////////////////////////////////////////////////////////////////
LNDivideBuffer res 1
LNDivideCounter res 1
LNDivideDividend res 1
LNDivideDivsor res 1
LNDivideQuotient res 1
LNMultiplyMultiplicand res 1
LNMultiplyMultiplier res 1
LNMultiplyProduct res 1
fit 492
PUB DelimiterFinder(RxStringAddr) : idx | localCount, localIndex, pstDelimiterFinder
' Initialize variables here
localIndex := 0
pstDelimiterFinder := 0
printAt(1,40, string(" "))
repeat
ifnot localCount := byte[RxStringAddr][idx++] ' ifnot c, itterate to the next byte in byte[RxStringAddr] ?
printAt( 1,40, String("No delimiter, aborted"))
return -1
charAt(1+idx,39,localCount)
' pst.dec(localCount)
' pst.str(string(pst#NL))
until localCount == b_delimiter'localCount == "="
bytemove(@b_prefix, RxStringAddr, --idx) ' idx points to the character after the delimiter, copy prefix
b_prefix[idx] := 0 ' add terminator
RxStringAddr += idx + 1 ' advance pointer, skip delimiter (+1)
bytemove(@b_suffix, RxStringAddr, strsize(RxStringAddr) +1) ' copy tail including the existing terminator (+1)
'pst.str(b_prefix)
'pst.char(13)
'pst.hex(b_suffix,1)
'pst.char(13)
variableUpdator(@b_prefix, @b_suffix)
PUB variableUpdator(preAddr, sufAddr) | localIndex, pstVariableUpdator, updateValue ' variableUpdator(@prefix, @suffix)
' Initialize variables here
localIndex := 0
'pst.str(long[preAddr])
'pst.char(13)
'pst.str(sufAddr)
'pst.char(13)
'charAt(1,40, " ")
'printAt(1,40, string(" "))
if strcomp(preAddr, string("updateRateDenominator")) 'strcomp(@prefix, var1)
l_updateRateDenominator := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010) ' converts from a string to a dec
pst.str(l_updateRateDenominator)
'pst.str(string(pst#NL))
if strcomp(preAddr, string("sendAllValuesOnce")) 'strcomp(@prefix, var1)
l_sendAllValuesOnce := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010) ' converts from a string to a dec
'pst.str(l_sendAllValuesOnce)
'pst.str(string(pst#NL))
if strcomp(preAddr, string("sendAllValues")) 'strcomp(@prefix, var1)
l_sendAllValues := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010) ' converts from a string to a dec
'pst.str(l_sendAllValues)
'pst.str(string(pst#NL))
if strcomp(preAddr, string("update")) 'strcomp(@prefix, var1)
l_updateTest := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010) ' converts from a string to a dec
'genCa.setVariableDegreeDelay(updateValue)
'charAt( 12, 40, " " )
'pst.str(string("update was updated"))
'pst.char(13)
{if strcomp(preAddr, l_i1Name) 'strcomp(@prefix, var1)
l_i1value := n.FromStr(sufAddr, %000_000_000_0_0_000000_01010) ' n.FromStr(@suffix, %000_000_000_0_0_000000_01010) ' converts from a string to a dec
long sendAllValuesOnce
long sendAllValues
}
pstInitScreen
dat
spaces byte " ",0
proc byte "-/|\"
pub charAt( x,y,c )
' output a character if it's in screen-range and if it's a printable character
if x>0 and x<109 and y>0 and y<75 and c>31 and c<128
posbuf[1]:=x
posbuf[2]:=y
posbuf[3]:=c
pst.str(@posbuf)
pub printAt( x, y, text)
' set cursor position and print string
posbuf[1]:=x
posbuf[2]:=y
posbuf[3]:=0
pst.str(@posbuf)
pst.str( text )
dat
' a buffer to assemble the bytestream for positioning
posbuf byte 2, 0, 0, 0, 0
pub getCog
result := l_cog
pub getPst1
result := l_pst1
pub getPst2
result := l_pst2
pub getPst3
result := l_pst3
pub getPst4
result := l_pst4
pub getPst5
result := l_pst5
pub getPst6
result := l_pst6
pub getPst7
result := l_pst7
pub getPst8
result := l_pst8
pub getPst9
result := l_pst9
pub getPst10
result := l_pst10
pub getPst11
result := l_pst11
pub getPst12
result := l_pst12
pub getPst13
result := l_pst13
pub getPst14
result := l_pst14
pub getPst15
result := l_pst15
pub getPst16
result := l_pst16

Comments
Perry
So I tried waitcnt with PASM for the first time and apparently it does not function like the spin waitcnt. It seems like it should be a relatively simple command but like the thread title says, nothing was going right today.
If I waitcnt for 10000 cycles, should that be sufficient? Can I just do the following?
mov cntT, cnt add cntT, tenThousandCycles waitcnt cntT, #0Perry
In assembly, WAITCNT xx,yy works like this:
On encountering the WAITCNT instruction, the cog suspends execution until the 32 bit sytem counter value located in CNT reaches the 32 bit value held in cog location xx.
On reaching that value, (which could take up to 53 or so seconds at 80 MHz) the 32 bit value held in cog location yy is instantly added to the value at location xx, prepping the counter for another wait to THAT count if you should desire. To effect that, you would presumably do some code, and loop back to the previous WAITCNT. Every time that WAITCNT is encountered, the cog will wait until the system counter reaches the appropriate value.... and that is the current value in xx, which is then incremented by the value in yy.
Do note, that the value in yy could be zero, and also that in using the # literal designator, yy could be an immediate value. from 0 through 511.
Hope that helps.
Cheers,
Peter (pjv)
Actually it was. In the interest of humbling myself I had a mistake in my template that I had not realized. In the code below, it should have been printing the value returned when I called getPst16, which you can see is commented out. Instead it was printing a hardcoded variable all of the time, so I've been chasing my tail for about 3 hours now. Talk about humble pie!
Once that was straightened out, it printed the values I expected and magically my PASM waitcnt started working (as it was actually working all along). As I said, I learn everything the hard way, which is not to my liking. Working code block is below.
restart mov startTime, cnt ' copy cnt to startTime add alive, #1 ' add "1" to the alive count wrlong alive, pstPtr13 ' write the alive count to hub ram for the pst wrlong pinMask, pstPtr1 ' write the pinMask to hub ram for the pst wrlong pin, pstPtr2 ' write the pin number to hub ram for the pst end mov cntT, cnt ' copy read only cnt to temporary variable add cntT, tix ' add tix value to temporary cnt variable waitcnt cntT, #0 ' wait until cnt value exceeds temporary variable mov endTime, cnt ' copy cnt to endTime wrlong startTime, pstPtr14 ' write start time to pst wrlong endTime, pstPtr15 ' write end time to pst sub endTime, startTime ' subtract startTime from endTime wrlong endTime, pstPtr16 ' print difference to hub ram for pst, should be around 100k with current tix value jmp #restartcharAt( 12, 36, " " ) ' ("Pst16:") ) pst.dec(l_updateTest)'getPst16) pst.str(@spaces)Thank you kindly for your reply. This is a good explanation which helps me wrap my head around this a little better. My mistake turned out to be more due to not taking a break and over looking something obvious, then my understanding of the PASM wait cnt, although I now understand it even better with your explanation. Thank you for that.
Attachment not found.
I was expecting days of frustration and was not convinced that the I2C code would not stop on itself in some random and inobservable way but it worked! :P
To answer your question.... yes I have those days, more often than not. I'm just thankful when there are coding errors and not smoke-inducing hardware errors.
@photomankc, it's nice to hear it isn't only me