My first PASM
Bobb Fwed
Posts: 1,119
I am working on my first PASM program (first "machine language" program ever).
I am converting a rather trivial program over to PASM. It is a LED control program I use to not slow down the controller cog. I have the SPIN version, and my attempt at the the PASM. The PASM seems to work somewhat, but it starts a couple seconds later than it seems it should, the type 4 blink doesn't work at all, and it only seems to loop once. Please take a look and help me out.
SPIN:
PASM:
Edit: fixed mCode formatting issue
Post Edited (Bobb Fwed) : 2/2/2009 9:45:43 PM GMT
I am converting a rather trivial program over to PASM. It is a LED control program I use to not slow down the controller cog. I have the SPIN version, and my attempt at the the PASM. The PASM seems to work somewhat, but it starts a couple seconds later than it seems it should, the type 4 blink doesn't work at all, and it only seems to loop once. Please take a look and help me out.
SPIN:
VAR byte cog, cogon long ledstack[noparse][[/noparse]20] long ledblink PUB Main LED(0, 1) PUB LED (pin1, pin2) stop cogon := (cog := cognew(dance(pin1, pin2, @ledblink), @ledstack)) > 0 REPEAT waitcnt(clkfreq + cnt) blinktype(1) waitcnt(clkfreq + cnt) blinktype(2) waitcnt(clkfreq + cnt) blinktype(4) waitcnt(clkfreq + cnt) blinktype(3) PUB stop if cogon~ cogstop(cog) PUB blinktype (type) ledblink.byte[noparse][[/noparse] 3 ] := type ' shove to high byte PUB dance (pin1, pin2, typeAddr) | lled, i OUTA[noparse][[/noparse]pin1]~ OUTA[noparse][[/noparse]pin2]~ DIRA[noparse][[/noparse]pin1]~~ DIRA[noparse][[/noparse]pin2]~~ REPEAT ' repeat forever REPEAT UNTIL (lled := byte[noparse][[/noparse]typeAddr]) ' repeat nothing until type is set long[noparse][[/noparse]typeAddr] >>= 8 long[noparse][[/noparse]typeAddr] >>= 8 CASE lled 1: ' green OUTA[noparse][[/noparse]pin1]~ OUTA[noparse][[/noparse]pin2]~~ 2: ' yellow OUTA[noparse][[/noparse]pin1]~~ OUTA[noparse][[/noparse]pin2]~ 3: ' off OUTA[noparse][[/noparse]pin1]~ OUTA[noparse][[/noparse]pin2]~ 4: ' blink: to show "on" -- switches color REPEAT 2 pause(250) !OUTA[noparse][[/noparse]pin1] !OUTA[noparse][[/noparse]pin2] PUB pause (pause_ms) waitcnt(((clkfreq / 1000 * pause_ms) #> 381) + cnt)
PASM:
CON LED1_p = 0 LED2_p = 1 OBJ VAR byte cog, cogon word high_wait, low_wait long ledblink PUB LED | i stop cogon := (cog := cognew(@dance, @ledblink)) > 0 REPEAT waitcnt(clkfreq + cnt) blinktype(1) waitcnt(clkfreq + cnt) blinktype(2) waitcnt(clkfreq + cnt) blinktype(4) waitcnt(clkfreq + cnt) blinktype(3) PUB stop if cogon~ cogstop(cog) PUB blinktype (type) ledblink.byte[noparse][[/noparse] 3 ] := type ' shove to high byte DAT ORG 0 dance MOV DIRA, LED_p MOV OUTA, #0 danceloop ' loop forever :loop RDBYTE ledtype, PAR WZ RDLONG shft, PAR SHR shft, #8 WRLONG shft, PAR IF_NZ JMP #caseswitch JMP #:loop caseswitch ' same as switch/case type1 ' LED green CMP ledtype, #1 WZ IF_NZ JMP #type2 MOV OUTA, GREEN JMP #danceloop type2 ' LED yellow CMP ledtype, #2 WZ IF_NZ JMP #type3 MOV OUTA, YELLOW JMP #danceloop type3 ' LED off CMP ledtype, #3 WZ IF_NZ JMP #type4 MOV OUTA, #0 JMP #danceloop type4 ' blink color back and forth CMP ledtype, #4 WZ IF_NZ JMP #type5 MOV idx, #2 :loop MOV OUTA, NOT OUTA MOV waitlen, cnt ADD waitlen, pausetime WAITCNT waitlen, pausetime DJNZ idx, #:loop JMP #danceloop type5 JMP #danceloop ' back to top LED_p LONG |< LED1_p | |< LED2_p YELLOW LONG |< LED1_p GREEN LONG |< LED2_p pausetime LONG 1_000_000 waitlen LONG 0 shft LONG 0 idx LONG 0 ledtype BYTE 0 FIT 496
Edit: fixed mCode formatting issue
Post Edited (Bobb Fwed) : 2/2/2009 9:45:43 PM GMT
Comments
You're doing something similar in the PASM code and to me it just looks like trouble. You're watching a memory location to see if it becomes non-zero, but at the same time you're continually writing a zero into it. There's a very small window of time for the other cog to set the blink type. The window is even smaller for the PASM version.
When the controller cog calls blinktype(), it sets byte 3 to the value.
While the LED cog is waiting, it shifts that value toward byte 0. Once it is reached, it executes that value.
I realize that I should be locking those addresses during the operation, but I haven't had a problem yet with the SPIN version. The blink type commands can be sent as close as 1000 cycles from each other, and some of the blinktypes (not all are listed in the program) are as long as 60 seconds. So if the 60 second command gets called, at least one more command is queued while that is happening. In the final version, I'd like 4 more queued, but I'll have to get this working before I get to that.
OK. New task, can someone explain explain how the lock tasks work? I assume I locknew and get an ID, but how do I tell it what information is locked? Then I use lockset. When I am not accessing the info I use LockClr?
work? What is the best way to toggle a set of pins (like !OUTA[noparse]/noparse does in SPIN)