PC+W error
BebopALot
Posts: 79
Hi folks, I have been learning a lot of assembly lately and trying to write some programs a little differently. Lately I have been playing around with state machines. Can some one please help me with my error?
Everything goes well until I have this command,
mov w, stateselect
JMP PC+W
JMP Routine1
JMP Routine2
I get bad call error or something like that. Stateselect is always either binary 1 (0000_0001) or 2 (0000_0010).
What am I doing wrong?
Everything goes well until I have this command,
mov w, stateselect
JMP PC+W
JMP Routine1
JMP Routine2
I get bad call error or something like that. Stateselect is always either binary 1 (0000_0001) or 2 (0000_0010).
What am I doing wrong?
Comments
Not sure about the error message, but Stateselect should be 0 to offset to the line after the JMP PC+W, or 1 to offset two lines farther.
Often there is even an easier way to do the state jumps with the intermediary table, and that is to use the address of the routine itself. Some restrictions, such as you must remain on the same page.
Cheers,
Peter
Post Edited (pjv) : 3/3/2006 4:57:43 PM GMT
Unfortunately, when SXSim tries to
mov PC, Stateselect
its giving me a "bad jump or return address"
I'll investigate further.
Cheers,
Peter (pjv)
I am doing something a little different here than last time. First I am bursting two pins simulataneously for 75us at 40Khz while keeping a 40KHz carrier wave active through the burst and then silent periods. Using your tips for a State Machine, this was easy and reliable in its design. The tricky part was that every 12.5 us all pins are OFF regardless of which state (burst or wait) so I NOT a register every 12.5us to toggle between those two states and use an OldState variable to prevent state loss. Looks like it works fine. I have several loop variables set to 1 just because in the future I may use them to increase the interupt count.
Thanks for helping me learn Peter,
BBAL
;5.120 MHz version
Device SX28L, Turbo, Stackx, OSCHS3
IRC_CAL IRC_SLOW
FREQ 5_120_000
RESET ResetEntry
ORG $000
Interrupt ; Interrupt Routine - always starts at 0
Mov w, State
Mov Ra, w
Setb Flag.0
Mov w, #-64
Retiw
Org $08
State DS 1
Flag DS 1
Loop1 DS 1
Loop2 DS 1
Loop3 DS 1
StateSelect DS 1
OnOffSelect DS 1
OldState DS 1
ResetEntry
; de-glitch initial state
Mov w, #%0000
Mov Ra, w ; set register A output to digital LOW
Mov w, #%0000_0000
Mov Rb, w ; set register B output to digital LOW
Mov w, #%0000_0000
Mov Rc, w ; set register C output to digital LOW
; configure ports
Mov M, #$0f ; access TRIS mode
Mov W, #%0000 ; bits 0-3 are outputs
Mov !Ra, W ; make Ra0-Ra3 outputs
Mov W, #%0000_0000 ; all bits output
Mov !Rb, W ; set Port B pins to output
Mov W, #%0000_0000 ; all bits output
Mov !Rc, w ; set Port C pins to output
; configure interrupt
Mov w, #%1011_1111
Mov RTCC, w ; set RTCC to 191
Mov w, #%1001_1111
Mov !option, w ; set RTCC without prescaler
; Initialize
Mov w, #%0000_0000
Mov State, w ; set State pins to 0's
Mov w, #Burst ; set stateselect to burst
Mov StateSelect, w
Mov w, #%0000_0000 ; set initially to off - but first output will flip and write
Mov OnOffSelect, w
Mov w, #%0000_0001 ; set to trigger state change
Mov Loop1, w
Mov w, #%0000_0001
Mov Loop2, w
Mov w, #%0000_0001
Mov Loop3, w
Clrb Flag.0
; **************************** HERE I REMOVED THE $100 which stopped the error
Main
Sb Flag.0 ; test for interupt occured
JMP Main
; come here every 12.5us
Clrb Flag.0 ; clear interupt flag
NOT OnOffSelect ; toggle "odd even"
Sb OnOffSelect.0 ; every other 12.5us all pins = 0
JMP LoState ;
Mov w, Oldstate ; go here if odd
Mov State, w
decsz Loop1 ; countdown
JMP Main
decsz Loop2
JMP Main
decsz Loop3
JMP Main
Mov PC, StateSelect ; load the state number
Burst
Mov w, #%1011 ; State 1 ON config (Tx2.N/A.CW.TX1) - come here every 25 us
Mov State, w
; load State 1 Loop Values
Mov w, #%0000_0100 ; 1 more than needed for dec command to time correctly
Mov Loop1, w ; inner loop value
Mov w, #%0000_0001 ; 1 (0 really)
Mov Loop2, w ; middle loop value
Mov w, #%0000_0001 ; 1 (0 really)
Mov Loop3, w ; outer loop value
3 interupts, done
Mov StateSelect, #Wait ; pre-load next state
JMP Exit
Wait Mov w, #%0010 ; State 2 ON config (Tx2.N/A.CW.TX1)
Mov State, w
; load State 2 Loop Values
Mov w, #%1010_0001 ; 161
Mov Loop1, w ; inner loop value
Mov w, #%0000_0001
Mov Loop2, w ; middle loop value
Mov w, #%0000_0001
Mov Loop3, w ; outer loop value
Mov StateSelect, #Burst ; pre-load next state
JMP Exit
LoState Mov w, State ; save old state value to reload on even toggle
Mov OldState, w
Mov w, #%0000 ; all off
Mov State, w
Exit
JMP Main
So I guess all is working.
A couple of point of advice/suggestions.
1. I just learned this, and wish to pass it on; when you want to post a reply which has code in it, then use the full reply button at the end of the thread labeled "Post Reply" rather than the "Quick Reply" The reason is that the full featured method has the ability through the selection button labeled "#" to post your code with preserving its format, and that's a big help. It makes it so much more readable. Until someone had pointed this out to me I would just use the "Quick Reply" method, post my code which would then have its formatting (mostly tabs) stripped out, and I would post-edit it with spaces to make it look more reasonable. That was a real pain. Now I can post code pretty much the way I originally formatted it.
2. In your program when you invoke the state jumper, you need to be sure your jumps are always to the page that your jumper is located in. If jou need to go to a different page, then you need to use an intermediate jump, one to the current page which then executes another jump to another page, but of course not before you have performed an appropriate "page" instruction. The assembler's @ operator before the address name is great for this.
3. The state jumper uses·the 8 bit variable "StateAddr", so that can only address the lower 256 bytes of·the current·page. So, if you need to jump to the high 256 bytes of·the current·page, you are forced to use the intermediate jump method.
4. Do be sure, that after your state-jump to another page, that when you wish to return to the Mainline, you don't forget to set the page of the Mainline using the Page instruction or, better yet, the @ operator in front of the mainline address as per my example.
There are yet other, more involved tricks, but we'll just leave this for now.... hope this helps some more.
Cheers,
Peter (pjv)
What does "Mainline" refer to ? The beginning of the main progam labeled Main?
Yes, sorry if I was not clear. It is all that other code, whatever it might be, that you need to run as well as the state code.
Cheers,
Peter (pjv)