November 26, 2024, 03:24:03 PM

News:

Be sure to checkout our Vixen interfaces in the Library forum -- if you want PC automation at near zero cost, EFX-TEK and Vixen is a great combination of tools.


How would one program a compound WHILE statement?

Started by migman, October 03, 2010, 04:20:38 PM

Previous topic - Next topic

migman

I've been trying to get the following functions to compile.  I'm trying to put together some functions to move single or multiple servos simultaneously.  I have up to three servos to move at the same time.  I get an error that there are too many parameters in the while statement.  From what I can determine from code examples there are none that address this feature.  I'm aware that the & and AND commands are are for manipulating bits.  I've used structures like this in other languages like 'C' but can't find examples in SX/B.  Any suggestions of how to restructure the functions would be useful.   SEE the FUNC EYES_CENTER code.  Or the FUNC CENTER_ALL code as examples of what I'm trying to do.  The definitions are from the Servo6Digital10.SXB code from the forum.

FUNC EYES_UP
 FOR idx4 = pos(4) TO HI_LIMIT STEP 1
   put pos(4), idx4
   DELAY_MS 10
 NEXT
 RETURN
ENDFUNC

FUNC EYES_UD_MID
 FOR idx4 = pos(4) TO MID
   IF idx4 < MID THEN
     INC idx4
   ELSE
     DEC idx4
   put pos(4), idx4
   DELAY_MS 10
 NEXT
 RETURN
ENDFUNC

FUNC EYES_CENTER
 idx0 = pos(3)
 idx1 = pos(3)
 DO WHILE idx3 <> MID AND idx4 <> MID
 IF idx3 > MID THEN
   DEC idx3
 ENDIF
 IF idx3 < MID THEN
   INC idx3
 ENDIF
 IF idx4 > MID THEN
   DEC idx4
 ENDIF
 IF idx4 < MID THEN
   INC idx4
 ENDIF
   put pos(3), idx3
   put pos(4), idx4
   DELAY_MS 10
 LOOP
 RETURN
ENDFUNC

FUNC LEFT_UP
 idx0 = pos(0)
 idx1 = pos(1)
 DO WHILE idx0 > LO_LIMIT && idx1 < HI_LIMIT
 IF idx0 > LO_LIMIT THEN
   DEC idx0
 ENDIF
 IF idx1 < HI_LIMIT THEN
   INC idx1
 ENDIF
   put pos(0), idx0
   put pos(1), idx1
   DELAY_MS 10
 LOOP
 RETURN
ENDFUNC

FUNC RIGHT_UP
 idx0 = pos(0)
 idx1 = pos(1)
 DO WHILE idx0 < HI_LIMIT && idx1 < HI_LIMIT
 IF idx0 < HI_LIMIT THEN
   INC idx0
 ENDIF
 IF idx1 < HI_LIMIT THEN
   INC idx1
 ENDIF
   put pos(0), idx0
   put pos(1), idx1
   DELAY_MS 10
 LOOP
 RETURN
ENDFUNC

FUNC LEFT_DWN
 idx0 = pos(0)
 idx1 = pos(1)
 DO WHILE idx0 < HI_LIMIT && idx1 > LO_LIMIT
 IF idx0 < HI_LIMIT THEN
   INC idx0
 ENDIF
 IF idx1 > LO_LIMIT THEN
   DEC idx1
 ENDIF
   put pos(0), idx0
   put pos(1), idx1
   DELAY_MS 10
 LOOP
 RETURN
ENDFUNC

FUNC RIGHT_DWN
 idx0 = pos(0)
 idx1 = pos(1)
 DO WHILE idx0 > LO_LIMIT && idx1 > LO_LIMIT
 IF idx0 > LO_LIMIT THEN
   DEC idx0
 ENDIF
 IF idx1 > LO_LIMIT THEN
   DEC idx1
 ENDIF
   put pos(0), idx0
   put pos(1), idx1
   DELAY_MS 5
 LOOP
 RETURN
ENDFUNC

FUNC CENTER_ALL
 idx0 = pos(0)
 idx1 = pos(1)
 idx2 = pos(2)
 DO WHILE idx0 <> MID && idx1 <> MID && idx2 <> MID
 IF idx0 < MID THEN
   INC idx0
 ENDIF
 IF idx0 > MID THEN
   DEC idx1
 ENDIF
 IF idx1 < MID THEN
   INC idx1
 ENDIF
 IF idx1 > MID THEN
   DEC idx1
 ENDIF
 IF idx2 < MID THEN
   INC idx2
 ENDIF
 IF idx2 > MID THEN
   DEC idx2
 ENDIF
   put pos(0), idx0
   put pos(1), idx1
   put pos(2), idx2
   DELAY_MS 5
 LOOP
 RETURN
ENDFUNC

JonnyMac

It's really quite difficult to assist with an advanced Prop-SX program unless you let us open it in and editor and run it for ourselves.  Please consider attaching your complete program.
Jon McPhalen
EFX-TEK Hollywood Office

JonnyMac

On problem I see from the get-go, however, is that you seem to have multiple servos that are not being refreshed every 20ms as they need to be.  ANY load on the servo without refreshing every 20ms will cause it to drift.  With the Prop-SX one can create a virtual servo controller in the interrupt that allows you to write to position variables and not worry about refreshing (it will be handled automatically).
Jon McPhalen
EFX-TEK Hollywood Office

migman

Her is the whole thing - cut down a bit:

'  Taken from Servo6_Digital10   BY
'   Author.... Jon Williams, EFX-TEK
'              Copyright (c) 2008-2009 EFX-TEK
'              Some Rights Reserved
'              -- see http://creativecommons.org/licenses/by/3.0/

'   channel... 0 to  5 for servos
'              6 to 15 for digital outputs
'
'   value..... 55 to 245 for servos (150 = center)
'              >127 = on for digital channels
'              <128 = off for digital channels
'
' Default baud rate is 38.4K but can be changed down to as low as 2400.


' Device Settings

ID              "Srvo6+10"

DEVICE          SX28, OSCHS2, BOR42
FREQ            50_000_000

' I/O Pins

Trigger         PIN     RC.6 INPUT              ' P15 SETUP = DN (trainer)
Leds            PIN     RC                      ' P8..P13 (trainer)
OutsHi          PIN     RC   OUTPUT             ' solenoid control outputs
Out9           PIN     RC.7                    ' use P15/OUT15
' Out8           PIN     RC.6                    ' use P14/OUT14
Out7           PIN     RC.5                    ' use P13/OUT13
Out6           PIN     RC.4                    ' use P12/OUT12
Out5           PIN     RC.3                    ' use P11/OUT11
Out4           PIN     RC.2                    ' use P10/OUT10
Out3           PIN     RC.1                    ' use P9/OUT9
Out2           PIN     RC.0                    ' use P8/OUT8

OutsLo          PIN     RB   OUTPUT
Out1           PIN     RB.7                    ' use P7/OUT7
Out0           PIN     RB.6                    ' use P6/OUT6

ServoCtrl       PIN     RB   OUTPUT             ' servo control pins
Servo5         PIN     RB.5                    ' use P5
Servo4         PIN     RB.4                    ' use P4
Servo3         PIN     RB.3                    ' use P3
Servo2         PIN     RB.2                    ' use P2
Servo1         PIN     RB.1                    ' use P1
Servo0         PIN     RB.0                    ' use P0

TX              PIN     RA.3 OUTPUT             ' to PC
RX              PIN     RA.2 INPUT              ' from PC
SCL             PIN     RA.1 INPUT              ' EE clock line (I2C)
SDA             PIN     RA.0 INPUT              ' EE data line (I2C)

' Note: TX, SCL, and SDA lines are not used by this program


' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------

IsOn            CON     1
IsOff           CON     0

Yes             CON     1
No              CON     0

LO_LIMIT        CON     65                      ' to prevent servo burn-up
MID             CON     155
HI_LIMIT        CON     245



' Variables


flags           VAR     Byte                    ' (keep global)
isrFlag        VAR     flags.0
rxReady        VAR     flags.1                 ' rx byte waiting

sync            VAR     Byte
chan            VAR     Byte
value           VAR     Byte
mask            VAR     Byte

rxSerial        VAR     Byte (16)
rxBuf          VAR     rxSerial(0)             ' 8-byte buffer
rxCount        VAR     rxSerial(8)             ' rx bit count
rxDivide       VAR     rxSerial(9)             ' bit divisor timer
rxByte         VAR     rxSerial(10)            ' recevied byte
rxHead         VAR     rxSerial(11)            ' buffer head (write to)
rxTail         VAR     rxSerial(12)            ' buffer tail (read from)
rxBufCnt       VAR     rxSerial(13)            ' # bytes in buffer

svoData         VAR     Byte (16)               ' bank servo data
pos            VAR     svoData(0)              ' position table
pos0           VAR     svoData(0)
pos1           VAR     svoData(1)
pos2           VAR     svoData(2)
pos3           VAR     svoData(3)
pos4           VAR     svoData(4)
pos5           VAR     svoData(5)
pos6           VAR     svoData(6)
pos7           VAR     svoData(7)
svoTix         VAR     svoData(8)              ' isr divider
svoFrame_LSB   VAR     svoData(9)              ' frame timer
svoFrame_MSB   VAR     svoData(10)
svoIdx         VAR     SvoData(11)             ' active servo pointer
svoTimer       VAR     svoData(12)             ' pulse timer
svoPin         VAR     svoData(13)             ' active servo pin

dbTimer         VAR     Byte
Incr      VAR   Byte

idx0            VAR     Byte
idx1            VAR     Byte
idx2            VAR     Byte
idx3            VAR     Byte
idx4            VAR     Byte
idx5            VAR     Byte

' =========================================================================
  INTERRUPT NOPRESERVE 300_000                  ' (4)   run every 3.333 uS
' =========================================================================

Mark_ISR:
  \ SETB  isrFlag                               ' (1)


' not used but not yet removed  from Servo6_Digital10
' ----------------
' Servo Processing
' ----------------
'
Test_Servo_Tix:
  ASM
    BANK  svoData                               ' (1)
    INC   svoTix                                ' (1)   update divider
    CJB   svoTix, #3, Servo_Done                ' (4/6) done?
    CLR   svoTix                                ' (1)   yes, reset for next

' Code below this point runs every 10 uS

Check_Frame_Timer:
    CJNE  svoFrame_LSB, #2000 & 255, Inc_FrTmr  ' (4/6) svoFrame = 2000 (20 ms)?
    CJNE  svoFrame_MSB, #2000 >>  8, Inc_FrTmr  ' (4/6)
    CLR   svoFrame_LSB                          ' (1)   yes, reset
    CLR   svoFrame_MSB                          ' (1)
    MOV   svoPin, #%0000_0001                   ' (2)   start servo sequence
    CLR   svoIdx                                ' (1)   point to servo 0
    MOV   FSR, #pos                             ' (2)
    MOV   svoTimer, IND                         ' (2)
    JMP   Refesh_Servo_Outs                     ' (3)

Inc_FrTmr:
    INC   svoFrame_LSB                          ' (1)   DEC svoFrame
    ADDB  svoFrame_MSB, Z                       ' (2)

Check_Servo_Timer:
    TEST  svoPin                                ' (1)   any servos on?
    SNZ                                         ' (1)
     JMP  Servo_Done                            ' (1)   no, exit
    DEC   svoTimer                              ' (1)   yes, update timer
    SZ                                          ' (1)   still running?
     JMP  Servo_Done                            ' (1)   yes, exit

Reload_Servo_Timer:
    INC   svoIdx                                ' (1)   point to next servo
    MOV   W, #pos                               ' (1)   get pulse timing
    ADD   W, svoIdx                             ' (1)
    MOV   FSR, W                                ' (1)
    MOV   W, IND                                ' (1)
    MOV   svoTimer, W                           ' (1)   move to timer

Select_Next_Servo:
    CLC                                         ' (1)
    RL    svoPin                                ' (1)
    AND   svoPin, #%0011_1111                   ' (2)   limit servo channels

Refesh_Servo_Outs:
    AND   ServoCtrl, #%1100_0000                ' (2)   clear last
    OR    ServoCtrl, svoPin                     ' (2)   update outputs

Servo_Done:
  ENDASM



ISR_Exit:
  RETURNINT                                     ' (4)
'  Too be removed most likely from here to above

' -------------------------------------------------------------------------
' Subroutine / Function Declarations
' -------------------------------------------------------------------------

RX_BYTE         FUNC    1, 0                    ' receive a byte
DELAY_MS        SUB     2, 2, Word, Word        ' shell for PAUSE

NOD_DWN         FUNC    1, 0
NOD_UP          FUNC    1, 0
NOD_MID         FUNC    1, 0
TURN_LEFT       FUNC    1, 0
TURN_RIGHT      FUNC    1, 0
TURN_MID        FUNC    1, 0
TILT_LEFT       FUNC    1, 0
TILT_RIGHT      FUNC    1, 0
TILT_MID        FUNC    1, 0
EYES_LEFT       FUNC    1, 0
EYES_RIGHT      FUNC    1, 0
EYES_RL_MID     FUNC    1, 0
EYES_DWN        FUNC    1, 0
EYES_UP         FUNC    1, 0
EYES_UD_MID     FUNC    1, 0
EYES_CENTER     FUNC    2, 0
LEFT_DWN        FUNC    2, 0
RIGHT_DWN       FUNC    2, 0
LEFT_UP         FUNC    2, 0
RIGHT_UP        FUNC    2, 0
CENTER_ALL      FUNC    3, 0

' =========================================================================
  PROGRAM Start
' =========================================================================

Start:
  TX = 1                                        ' set TX line to idle

  ' center servos
  PUT pos, MID, MID, MID, MID, MID, MID

  PLP_A = %0000
  TRIS_C = %1100_0000                           ' make RC.0 .. RC.5 outputs


Main:
  Leds = IsOff
  dbTimer = 0

Check_Trigger:
'  PAUSE 1
  INC dbTimer
  IF Trigger = IsOff THEN Main
  IF dbTimer < 100 THEN Check_Trigger

Zip_It:   ' just playing with the prop-1 trainer here
  FOR chan = 0 TO 4
    Leds = 1 << chan
    DELAY_MS 100
  NEXT
  FOR chan = 5 TO 0 STEP -1
    Leds = 1 << chan
    DELAY_MS 100
  NEXT
  Leds = IsOff

  FOR Incr = MID TO LO_LIMIT STEP -1     ' This will be replaced by calls
    put pos, Incr, Incr                  ' to the Functions
    DELAY_MS 5
  NEXT

  FOR Incr = LO_LIMIT TO HI_LIMIT STEP 1
    put pos, Incr, Incr
    DELAY_MS 5
   NEXT                                  ' Functions replace to here

  IF Trigger = IsOn THEN Zip_It

  GOTO Main

overs


' Subroutine / Function Code

SUB DELAY_MS
  PAUSE __wparam12
  ENDSUB

FUNC NOD_DWN                    ' Functions to control servos
  FOR idx0 = pos(0) TO LO_LIMIT STEP -1
    put pos(0), idx0
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC NOD_UP
  FOR idx0 = pos(0) TO HI_LIMIT STEP 1
    put pos(0), idx0
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC NOD_MID
  FOR idx0 = pos(0) TO MID
    IF idx0 < MID THEN
      INC idx0
    ELSE
      DEC idx0
    put pos(2), idx2
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC TURN_LEFT
  FOR idx1 = pos(1) TO LO_LIMIT STEP -1
    put pos(1), idx1
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC TURN_RIGHT
  FOR idx1 = pos(1) TO HI_LIMIT STEP 1
    put pos(1), idx1
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC TURN_MID
  FOR idx1 = pos(1) TO MID
    IF idx1 < MID THEN
      INC idx1
    ELSE
      DEC idx1
    put pos(2), idx1
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC TILT_LEFT
  FOR idx2 = pos(2) TO LO_LIMIT STEP -1
    put pos(2), idx2
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC TILT_RIGHT
  FOR idx2 = pos(2) TO HI_LIMIT STEP 1
    put pos(2), idx2
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC TILT_MID
  FOR idx2 = pos(2) TO MID
    IF idx2 < MID THEN
      INC idx2
    ELSE
      DEC idx2
    put pos(2), idx2
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC EYES_LEFT
  FOR idx3 = pos(3) TO LO_LIMIT STEP -1
    put pos(3), idx3
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC EYES_RIGHT
  FOR idx3 = pos(3) TO HI_LIMIT STEP 1
    put pos(3), idx3
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC EYES_RL_MID
  FOR idx3 = pos(3) TO MID
    IF idx3 < MID THEN
      INC idx3
    ELSE
      DEC idx3
    put pos(3), idx3
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC EYES_DWN
  FOR idx4 = pos(4) TO LO_LIMIT STEP -1
    put pos(4), idx4
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC EYES_UP
  FOR idx4 = pos(4) TO HI_LIMIT STEP 1
    put pos(4), idx4
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC EYES_UD_MID
  FOR idx4 = pos(4) TO MID
    IF idx4 < MID THEN
      INC idx4
    ELSE
      DEC idx4
    put pos(4), idx4
    DELAY_MS 5
  NEXT
  RETURN
ENDFUNC

FUNC EYES_CENTER
  idx0 = pos(3)
  idx1 = pos(3)
  DO WHILE idx3 <> MID AND idx4 <> MID
  IF idx3 > MID THEN
    DEC idx3
  ENDIF
  IF idx3 < MID THEN
    INC idx3
  ENDIF
  IF idx4 > MID THEN
    DEC idx4
  ENDIF
  IF idx4 < MID THEN
    INC idx4
  ENDIF
    put pos(3), idx3
    put pos(4), idx4
    DELAY_MS 5
  LOOP
  RETURN
ENDFUNC

FUNC LEFT_UP
  idx0 = pos(0)
  idx1 = pos(1)
  DO WHILE idx0 > LO_LIMIT && idx1 < HI_LIMIT
  IF idx0 > LO_LIMIT THEN
    DEC idx0
  ENDIF
  IF idx1 < HI_LIMIT THEN
    INC idx1
  ENDIF
    put pos(0), idx0
    put pos(1), idx1
    DELAY_MS 5
  LOOP
  RETURN
ENDFUNC

FUNC RIGHT_UP
  idx0 = pos(0)
  idx1 = pos(1)
  DO WHILE idx0 < HI_LIMIT && idx1 < HI_LIMIT
  IF idx0 < HI_LIMIT THEN
    INC idx0
  ENDIF
  IF idx1 < HI_LIMIT THEN
    INC idx1
  ENDIF
    put pos(0), idx0
    put pos(1), idx1
    DELAY_MS 5
  LOOP
  RETURN
ENDFUNC

FUNC LEFT_DWN
  idx0 = pos(0)
  idx1 = pos(1)
  DO WHILE idx0 < HI_LIMIT && idx1 > LO_LIMIT
  IF idx0 < HI_LIMIT THEN
    INC idx0
  ENDIF
  IF idx1 > LO_LIMIT THEN
    DEC idx1
  ENDIF
    put pos(0), idx0
    put pos(1), idx1
    DELAY_MS 5
  LOOP
  RETURN
ENDFUNC

FUNC RIGHT_DWN
  idx0 = pos(0)
  idx1 = pos(1)
  DO WHILE idx0 > LO_LIMIT && idx1 > LO_LIMIT
  IF idx0 > LO_LIMIT THEN
    DEC idx0
  ENDIF
  IF idx1 > LO_LIMIT THEN
    DEC idx1
  ENDIF
    put pos(0), idx0
    put pos(1), idx1
    DELAY_MS 5
  LOOP
  RETURN
ENDFUNC

FUNC CENTER_ALL
  idx0 = pos(0)
  idx1 = pos(1)
  idx2 = pos(2)
  DO WHILE idx0 <> MID && idx1 <> MID && idx2 <> MID
  IF idx0 < MID THEN
    INC idx0
  ENDIF
  IF idx0 > MID THEN
    DEC idx1
  ENDIF
  IF idx1 < MID THEN
    INC idx1
  ENDIF
  IF idx1 > MID THEN
    DEC idx1
  ENDIF
  IF idx2 < MID THEN
    INC idx2
  ENDIF
  IF idx2 > MID THEN
    DEC idx2
  ENDIF
    put pos(0), idx0
    put pos(1), idx1
    put pos(2), idx2
    DELAY_MS 5
  LOOP
  RETURN
ENDFUNC                        'End of Servo control functions.

JonnyMac

October 03, 2010, 06:59:14 PM #4 Last Edit: October 03, 2010, 07:01:24 PM by JonnyMac
This is the first section giving you trouble:

DO WHILE idx3 <> MID AND idx4 <> MID
 ' stuff
LOOP


You can't do it -- SX/B only allows one conditional test per line.  You can change it to:

DO
 IF idx3 = MID THEN Exit
 IF idx4 = MID THEN Exit
 ' loop stuff
LOOP


I'd do it this way just for clean form.

Don't use PUT with a single array element, just assign the new value.  Instead of

PUT pos(0), idx0

Use:

pos(0) = idx0
Jon McPhalen
EFX-TEK Hollywood Office

JonnyMac

BTW, functions are used to return a value -- yours don't  You should just make them subroutines as this will generate a little less code (and they're easier to define).
Jon McPhalen
EFX-TEK Hollywood Office

migman

If I understand what you wrote in the example, if either idx value equals MID then exit the DO - LOOP.   That is not exactly what I was trying to accomplish.  I want the loop to continue to run until both idx values equal MID not just until the first one gets there.  (idx3 not equal MID) AND (idx4 not equal MID).  I think I understand the logic change (change the not equal to EQUAL and change the AND to an OR) supposed to be equivalent but you then made it exit instead of executing the loop which makes the logic wrong.   How can I get two tests so that either continue the same one loop.

I originally had the FUNC's defined as SUBroutines but was getting an error so I changed them to FUNC's only to find the problem to be with the earlier Define of the SUBroutine.  It should have been    EYE_CENTER   SUB  0    or    EYE_CENTER   SUB  2, 0  not sure which?  Two parameters are used as input - pos(3) and pos(4) but nothing is returned.

BigRez

If they both must equal MID, then the loop would be structured very close to what Jon had:

DO
  IF idx3 = MID AND idx4 = MID THEN Exit
  ' loop stuff
LOOP

JonnyMac

October 03, 2010, 11:13:41 PM #8 Last Edit: October 03, 2010, 11:18:14 PM by JonnyMac
Can't do that Mike as SX/B doesn't allow compound statements.

Here's what I'd do.  First, I'd redefine anything that doesn't return a value as a SUBroutine:

EYES_CENTER     SUB     0, 0

And I would re-code it like this (it compiles):

SUB EYES_CENTER
 idx0 = pos(3)
 idx1 = pos(3)

EC_Move:
 IF idx3 = MID THEN
   IF idx4 = MID THEN
     GOTO EC_Exit
   ENDIF
 ENDIF

 IF idx3 > MID THEN
   DEC idx3
 ELSEIF idx3 < MID THEN
   INC idx3  
 ENDIF
 pos(3) = idx3

 IF idx4 > MID THEN
   DEC idx4
 ELSEIF idx4 < MID THEN
   INC idx4
 ENDIF
 pos(4) = idx4

 DELAY_MS 5
 GOTO EC_Move

EC_Exit:
 ENDSUB
Jon McPhalen
EFX-TEK Hollywood Office

migman

what about like this then:

SUB EYES_CENTER
  idx3 = pos(3)
  idx4 = pos(4)

DO
  IF idx3 = MID THEN
    IF idx4 = MID THEN
      Exit
    ENDIF
  ENDIF

  IF idx3 > MID THEN
    DEC idx3
  ELSEIF idx3 < MID THEN
    INC idx3 
  ENDIF
  pos(3) = idx3

  IF idx4 > MID THEN
    DEC idx4
  ELSEIF idx4 < MID THEN
    INC idx4
  ENDIF
  pos(4) = idx4

  DELAY_MS 40
LOOP

JonnyMac

It might work (you'll have to try) but my rule is no more than five or so lines within a DO-LOOP as long structures can make the code really difficult to follow, especially when attempting to troubleshoot.  Skip fancy, go for simple, robust code.  ;D
Jon McPhalen
EFX-TEK Hollywood Office