Question about use of ON ... GOTO/GOSUB and LOOKDOWN in SX/B
![RobotWorkshop](https://forums.parallax.com/uploads/userpics/915/nCTRZ4MIBWKDB.jpg)
Ok, i'm not 100% clear on the way that the ON..GOTO/GOSUB will work when it gets values other than the ones in the list. Below is the example from the SX/B help file:
It is pretty obvious what will happen when RX_BYTE returns an L, R, or S. However it isn't so clear what it may do if any other characters are received. Part of this is due to that the LOOKDOWN command states that the value of cmd is unchanged if it doesn't match any of the characters. I see a potential problem with this in the code above. What happens if RX_BYTE happens to return a 0, 1, or 2? Wouldn't that also send it to the subroutines too? That being the case wouldn't you need to check to see if cmd was less than 3 and then skip over the next line if it was?
Has anyone else run into this?
Robert
Post Edited (RobotWorkshop) : 2/27/2008 10:09:03 PM GMT
FROM SX/B Help File... said...
A variant of the ON... instruction essentially combines LOOKDOWN into the syntax. For example:
Main:
cmd = RX_BYTE
LOOKDOWN cmd, "L", R", "S", cmd
ON cmd GOSUB Robot_Left, Robot_Right, Robot_Stop
GOTO Main
... can be combined to:
Main:
cmd = RX_BYTE
ON cmd = "L", R", "S" GOSUB Robot_Left, Robot_Right, Robot_Stop
GOTO Main
It is pretty obvious what will happen when RX_BYTE returns an L, R, or S. However it isn't so clear what it may do if any other characters are received. Part of this is due to that the LOOKDOWN command states that the value of cmd is unchanged if it doesn't match any of the characters. I see a potential problem with this in the code above. What happens if RX_BYTE happens to return a 0, 1, or 2? Wouldn't that also send it to the subroutines too? That being the case wouldn't you need to check to see if cmd was less than 3 and then skip over the next line if it was?
Has anyone else run into this?
Robert
Post Edited (RobotWorkshop) : 2/27/2008 10:09:03 PM GMT
Comments
It may seem verbose, but as the style is close to the assembly output it doesn't take a lot of code, and it's quite easy to add or disable features while testing.
What i'm trying to do which is a bit different from your code above is to check to see if any serial data has been received. If some has come in then it will deal with it and then go on to do some other processing before going back to the main loop again. If no data has been received then it goes ahead and does it's processing and loops back to main to check for serial data and so on. If this works out the way I hope it may be a useful technique to incorporate into other SX/B programs. Any suggestions for the code below?
The weird part is that it doesn't seem to fall through and do the regular processing unless I keep sending some data to it. It's almost as if my check to see if any characters are in the Serial receive buffer isn't working right. Besides that all the other routines seem to work ok. If I uncomment the first couple lines in the main routine it just displays the serial data on a set of 8 leds as a test. That part works perfect now. I had problems with that which were caused by extra Timer Interrupts but that was fixed by masking them off at the beginning of the program. Below is a section of the code where the main loop is:
' Enable ISR to start accepting serial data
active = True ' Serial RX disabled until this flag is True
HdBsy = False ' Tell Host we're ready for action!
actmov = False ' We're not in an active movement.
Main:
'Leds=RX_BYTE
'GOTO Main
IF rxBufCnt = 0 THEN
GOTO Motor_Control
ENDIF
' cmdChar should be non-zero for a mutli-byte command
IF cmdChar = 0 THEN
char = RX_BYTE
IF char = "C" THEN ' 67
GOSUB CLR_FLAGS
GOTO Motor_Control
ENDIF
IF char = "G" THEN ' 71
GOSUB GO_TARGET ' Goto position encTarget
GOTO Motor_Control
ENDIF
IF char = "H" THEN ' 72
GOSUB HOME_HEAD ' Set encTarget to 0 then set actmov = True
GOTO Motor_Control
ENDIF
IF char = "I" THEN ' 73
GOSUB INIT_HEAD ' Initialize head to point forward and set encValue & encTarget to 0
GOTO Motor_Control
ENDIF
IF char = "F" THEN ' 70
cmdChar = char ' Set LEDs near wheels
GOTO Motor_Control
ENDIF
IF char = "L" THEN ' 76
cmdChar = char ' Set LED's on front (8 LEDs)
GOTO Motor_Control
ENDIF
IF char = "S" THEN ' 83
cmdChar = char ' Set new encTarget postion
GOTO Motor_Control
ENDIF
' We must have received a junk command. Just flash the LEDs for now.
GOSUB COMM_ERR
ELSE
IF rxBufCnt > 0 THEN
IF char = "F" THEN ' 70
GOSUB FOOT_LEDS
cmdChar = 0
GOTO Motor_Control
ENDIF
IF char = "L" THEN ' 76
GOSUB Chest_Leds
cmdChar = 0
GOTO Motor_Control
ENDIF
ENDIF
IF rxBufCnt > 1 THEN
char = RX_CHKBYTE
IF char = "S" THEN ' 83
GOSUB Set_Target
cmdChar = 0
GOTO Motor_Control
ENDIF
ENDIF
ENDIF
Motor_Control:
IF actmov = True THEN
' Check encoder & remaining distance.
' Reached position? If so, stop movement and reset flag
encOffset = encTarget - encValue
IF encOffset.15 = True THEN
encOffset = -encOffset ' Use 2's complement to get ABS value
ENDIF
IF encOffset < 2 THEN
actmov = False
TIMER1 TIMER
LOW Spd1
HdBsy = False
ELSE
' We should be moving so adjust and update pwm
encOffset = encTarget - encValue
IF encOffset.15 = True THEN
Dir1 = 1 ' If the difference is negative we should move left
encOffset = -encOffset ' Use 2's complement to get ABS value
ELSE
Dir1 = 0
ENDIF
' Figure out how fast to move
m1Spd = 750 ' Slow
IF encOffset > 50 THEN
m1Spd = 925 ' Medium
ENDIF
IF encOffset > 100 THEN
m1Spd = 1110 ' Fast
ENDIF
TIMER1 PWM, m1Spd, dutyCycle
ENDIF
ENDIF
' check to see if head moved on it's own (or someone moved it)
' if more that allowable variance
' setup new movement and set flag
' IF encTarget = encValue THEN
' GOTO Done
' ENDIF
encOffset = encTarget - encValue
IF encOffset.15 = True THEN
encOffset = -encOffset
ENDIF
IF encOffset > 10 THEN
actmov = True
HdBsy = True
ENDIF
Done:
GOTO Main ' Go back and do it all again.
Post Edited (RobotWorkshop) : 2/27/2008 10:09:23 PM GMT
I can see the flag you added for rxReady. Do you see any reason why the just checking rxBufCnt wouldn't do the same thing?
For some reason this latest program i've been working on is just fighting me all the way. I'm sure it's just me overlooking something simple and it will stand out soon.
Robert
I can see that you've been primarily using the SX28 chips. Have you done much on the SX48 with your code? Bean mentioned in another thread that instead of using a BANK 0 that a BANK $10 should probably be used on the SX48. If that is the case than perhaps another topic for the help file (or book) could be using conditional compiling so that the same code can assemble for both the SX28 and SX48. It seems that for many programs there isn't much difference but for some it may help.
In high-level SX/B, there are no worries, all the gory bank-pointing stuff is automated -- in fact, I have learned a ton by looking at the output created by SX/B.
Hello Jon,
I'm confused. I've looked at the Serial code in your 16 Channel servo controller and compared it to the previous code for the ISR based serial routines. It appears that both are using an 8 byte circular buffer to store incoming serial characters. The part that is confusing is that you check a different bit in the latest code to see if the buffer is full:
JB rxBufCnt.4, RX_Done
and in the older version you have:
JB rxBufCnt.3, RX_Done
From looking at the code I would expect that the .3 is correct for an 8 byte buffer and the .4 would be for a 16 byte buffer. If that is the case I can see where some of your variables might get overwritten if the data came in fast enough. Is there another reason for this?
Robert