Encoder Front Page
SRS Home | Front Page | Monthly Issue | Index
Google
Search WWW Search seattlerobotics.org

The Vice-Prez Sez

Karl Lunt

 

I get enough questions about SBasic that I figured I ought to do a little SBasic FAQ. So here are answers to some of the most common questions about SB:

How do I change the state of an output line?

If all you want to do is set or clear an output line, you can use something like:

pokeb PORTB, 1 ; set PB0

pokeb PORTB, 0 ; clear PB0

These lines alter PB0, but they both have the side effect of clearing all other PORTB outputs. If you want to preserve the states of the other output lines, use something like:

pokeb PORTB, peekb(PORTB) or 1 ; set PB0

pokeb PORTB, ~peekb(PORTB) and $fe ; clear PB0

The first statement reads the byte at PORTB, ORs that value with a 1, then writes the result back to PORTB. The second statement reads the byte at PORTB, uses the ~ operator to invert all the bits, ANDs that value with $fe to clear PB0, then writes the result back to PORTB.

You can use a similar technique to toggle a selected bit:

pokeb PORTB, peekb(PORTB) xor 1 ; toggle PB0

This statement reverses the state of PB0, regardless of its initial state.

How do I use interrupts in SBasic?

When the 68hc11 receives an interrupt, the MCU saves the current state of the registers, fetchs the contents of the appropriate interrupt vector, and jumps to that address. So the key element of handling interrupts in SBasic is to ensure that the address of your interrupt routine gets stored in the correct vector address. The following example uses the real-time interrupt (RTI), as it may be the most commonly used.

Here is a typical RTI interrupt service routine (ISR):

interrupt $fff0 ; vector for RTI

if wait <> 0 ; if counter not yet 0...

wait = wait - 1 ; decrement it

endif

pokeb tflg2, %01000000 ; rearm RTI

end ; end of the ISR

You can put this routine anywhere you want in your SBasic source file, but it makes the most sense to put it after your variable declarations but before your MAIN label. The first line in this routine tells SBasic to write the address of this code block to the vector address $fff0, which happens to be the vector address for the RTI interrupt. The POKEB statement clears the RTI interrupt flag, ensuring that the next RTI interrupt will cause control to jump back to this routine again. Finally, the END statement returns control back to the interrupted code so your program can continue where it left off.

But you aren't done yet. You need to add code in the MAIN routine that turns on the specific interrupt subsystem. For the RTI, that code looks something like this:

main:

pokeb tflg2, %01000000 ; clear RTI interrupt flag

pokeb tmsk2, %01000000 ; allow RTI interrupts

interrupts on ; allow maskable interrupts

The last statement above unmasks all 68hc11 maskable interrupts. It isn't enough just to turn on specific interrupts such as the RTI. You also have to clear the processor's I-bit, which if set masks all maskable interrupts. Once the I-bit is cleared, the RTI interrupts should begin. If your code writes a number to variable WAIT, it will begin to decrement once each 4.1 msecs until it hits 0. Refer to the RTI ISR code above to see why WAIT changes value on each RTI interrupt.

How do I control a hobby servo motor with SBasic?

The simplest way is to use the servos.bas library file included with the SBasic distribution package. This library contains working code for controlling up to four servo motors, and reduces the entire job to something like:

gosub InstallServo, TOC5

This sets up the 68hc11 timer channel TOC5 to control a servo motor wired to PA3. The code in this library is a little complicated, but worth your time to examine closely. You will learn a lot about how the 68hc11 timer subsystems work. Be sure to have a copy of the Motorola 68hc11 Reference Manual (pink book) handy.

To alter the servo's position, your code must simply write a 16-bit value to register TOC5. The value written will generate a servo pulse at PA3 of a unique width. The servo will only respond to pulses with widths from about 0.5 to 1.5 msecs; these widths correspond to values from about $f400 to $fc00, though your mileage will vary. So your code can move a servo to a specified position by writing the appropriate value in the above range, then waiting for the servo to complete its motion.

That's it for this issue. If you would like more information on using SBasic, send me email at karllunt@seanet.com and I'll do some more SBasic tips in a later issue.

Keep on keeping on...

karllunt@seanet.com

http://www.seanet.com/~karllunt

"Technology marches on. Over you or through you, take your pick." Attributed to Stewart Brand