Shop OBEX P1 Docs P2 Docs Learn Events
3D Printer, 3D Bresenham's Line in SPIN. — Parallax Forums

3D Printer, 3D Bresenham's Line in SPIN.

davidsaundersdavidsaunders Posts: 1,559
edited 2015-04-22 06:56 in Propeller 1
Here:
VAR
  LONG CX
  LONG CY
  LONG CZ
  LONG DX
  LONG DY
  LONG DZ
  LONG SX
  LONG SY
  LONG SZ
  LONG ER
  LONG E
  LONG E2
  LONG ER2

PUB LineTo3D(X,Y,Z)
  DX := UABS(CX - X)
  IF CX < X
    SX := 1
  ELSE
    SX := -1


  DY := UABS(CY - Y)
  IF CY < Y
    SY := 1
  ELSE
    SY := -1

  DZ := UABS(CZ - Z)
  IF CZ < Z
    SZ := 1
  ELSE
    SZ := -1

  IF DX > DY
    ER := DX / 2
    IF DX > DZ
      ER2 := DX / 2
    ELSE
      ER2 := -DZ / 2
  ELSE
    IF DY > DZ
      ER2 := DY / 2
    ELSE
      ER2 := -DZ / 2
    ER := -DY / 2

  REPEAT WHILE (TRUE)
    IF X == CX AND Y == CY
      QUIT
    E := ER
    E2 := ER2
    IF E > (-DX)
      ER -= DY
      CX += SX
      MvX(SX)
    IF E < DY
      ER += DX
      CY += DY
      MvY(SY)
    IF DX > DY
      IF E2 > (-DX)
        ER2 -= DZ
      IF E2 < DZ
        ER2 += DX
        CZ += SZ
        MvZ(SZ) 
    ELSE
      IF E2 > (-DY)
        ER2 -= DZ
      IF E2 < DZ
        ER2 += DY
        CZ += SZ
        MvZ(SZ) 
And the 2D version from which the 3D was derived (also mine):
VAR
  LONG CX
  LONG CY
  LONG DX
  LONG DY
  LONG SX
  LONG SY
  LONG ER
  LONG E

PUB LineTo(X,Y)
  DX := UABS(CX - X)
  IF CX < X
    SX := 1
  ELSE
    SX := -1

  DY := UABS(CY - Y)
  IF CY < Y
    SY := 1
  ELSE
    SY := -1

  IF DX > DY
    ER := DX / 2
  ELSE
    ER := -DY / 2

  REPEAT WHILE (TRUE)
    IF X == CX AND Y == CY
      QUIT
    E := ER
    IF E > (-DX)
      ER -= DY
      CX += SX
      MvX(SX)
    IF E < DY
      ER += DX
      CY += DY
      MvY(SY)

Note that CX, CY, and CZ are the current X, Y, and Z positions.

Comments

  • Mark_TMark_T Posts: 1,981
    edited 2015-04-21 07:37
    There is another approach for getting steps that avoids Bressenham's jitter altogether, which is to step your
    x, y, z variables by steps of YZ, ZX, XY (where upper case X, Y, Z are the total steps in each axis), until
    they all reach XYZ - whichever of x, y, z is smallest produces a step, then gets incremented, and the time
    value is bressenham'd against this smallest value. Time goes T ticks as the x, y, z values go XYZ. Typically
    64 bit arithmetic is needed for this.

    This doesn't help with acceleration / deceleration ramps though, but that can be added as a more complex
    bressenham style relationship between T and x,y,z I think.

    [ by the way you have explicitly ignore axes with zero movement, otherwise the XYZ product falls to zero ]
  • kwinnkwinn Posts: 8,697
    edited 2015-04-21 08:07
    I haven't done anything involving Bresenham's line algorithm for a long time, but I do wonder if it would not be simpler to use the time between steps (delta time) for the calculation, and if anyone has done anything along that line.

    Assuming the XYZ motors can start and accellerate at the same speed the longest line would determine the maximum starting speed and acceleration. The other axes would have have longer delta times based on it's length relative to that of the longest line. The rates of accelleration could also be calculated the same way.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-21 08:23
    Mark_T wrote: »
    There is another approach for getting steps that avoids Bressenham's jitter altogether, which is to step your
    x, y, z variables by steps of YZ, ZX, XY (where upper case X, Y, Z are the total steps in each axis), until
    they all reach XYZ - whichever of x, y, z is smallest produces a step, then gets incremented, and the time
    value is bressenham'd against this smallest value. Time goes T ticks as the x, y, z values go XYZ. Typically
    64 bit arithmetic is needed for this.

    This doesn't help with acceleration / deceleration ramps though, but that can be added as a more complex
    bressenham style relationship between T and x,y,z I think.

    [ by the way you have explicitly ignore axes with zero movement, otherwise the XYZ product falls to zero ]
    I know that I have left out the case of 0 movement, that is done with external checking, and passes the current value for the zero move axis, I do need to add a check to prevent divide by 0 though.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-21 08:25
    kwinn wrote: »
    I haven't done anything involving Bresenham's line algorithm for a long time, but I do wonder if it would not be simpler to use the time between steps (delta time) for the calculation, and if anyone has done anything along that line.

    Assuming the XYZ motors can start and accellerate at the same speed the longest line would determine the maximum starting speed and acceleration. The other axes would have have longer delta times based on it's length relative to that of the longest line. The rates of accelleration could also be calculated the same way.
    That is definitely a good thought, I will have to think on that a bit.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-21 08:35
    So for timed movement we would be talking something like:

    Assuming that all steppers are of equal ability:
    PSEUDOCODE:
    DX :=  ABS(X1 - X0)
    DY := ABS(Y1 - Y0)
    DZ := ABS(Z1 - Z0)
    IF DX > DY AND DX > DZ
      XSPEED := FULLSPEED
      YSPEED := (XSPEED / (DX / DY))
      ZSPEED := (XSPEED / (DX / DZ))
    END IF
    
    REMARK Repeat above if block for Y biggest and Z biggest.
    
    That is just off the top of my head, then have a separate loop watching the counter for when to step each. Is that the basic idea of what you are suggesting??
  • Phil Pilgrim (PhiPi)Phil Pilgrim (PhiPi) Posts: 23,514
    edited 2015-04-21 08:47
    Remember that your actual speed in 3-space, in the case of X biggest, is not FULLSPEED, but
    FULLSPEED * √(1 + (DY / DX)2 + (DZ / DX)2)
    So if you want the actual speed to be FULLSPEED, you have to divide FULLSPEED by the square-root term.

    BTW, I'd forget about Bresenham. It's not suitable for motor control due to the jitter. The approach cited by Mark_T is much better.

    -Phil
  • idbruceidbruce Posts: 6,197
    edited 2015-04-21 13:06
    kwinn
    Assuming the XYZ motors can start and accellerate at the same speed the longest line would determine the maximum starting speed and acceleration. The other axes would have have longer delta times based on it's length relative to that of the longest line. The rates of accelleration could also be calculated the same way.

    I have recently done something similar with my drivers, but they all run in different cogs and the speed is constant with no ramping. The longest axis is first determined and the total travel time is calculated. The other axes step pulse rate are determined by the total travel time of the longest axis.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-21 13:42
    Remember that your actual speed in 3-space, in the case of X biggest, is not FULLSPEED, but
    FULLSPEED * √(1 + (DY / DX)2 + (DZ / DX)2)
    So if you want the actual speed to be FULLSPEED, you have to divide FULLSPEED by the square-root term.

    BTW, I'd forget about Bresenham. It's not suitable for motor control due to the jitter. The approach cited by Mark_T is much better.

    -Phil
    FULLSPEED as a identifier name above refers to the fastest single axis speed for the current move, and would be calculated before hand, from the desired linear speed.

    Though I do thank you for your thoughts,.
  • kwinnkwinn Posts: 8,697
    edited 2015-04-21 20:08
    So for timed movement we would be talking something like:

    Assuming that all steppers are of equal ability:
    PSEUDOCODE:
    DX :=  ABS(X1 - X0)
    DY := ABS(Y1 - Y0)
    DZ := ABS(Z1 - Z0)
    IF DX > DY AND DX > DZ
      XSPEED := FULLSPEED
      YSPEED := (XSPEED / (DX / DY))
      ZSPEED := (XSPEED / (DX / DZ))
    END IF
    
    REMARK Repeat above if block for Y biggest and Z biggest.
    
    That is just off the top of my head, then have a separate loop watching the counter for when to step each. Is that the basic idea of what you are suggesting??

    Close, but not exactly what I had in mind. Sometimes I have a hard time putting what I visualize into words so I will try a simple example using motor steps instead of actual distances. No accelleration and maximum speed is 1000 steps/second for X, Y, and Z.

    Lets say we want to move from X = 1, Y = 1, Z = 1 to X = 1001, Y = 501, Z = 251

    The number of motor steps would be Xs = 1000, Ys = 500, Zs = 250

    The delta time (in clks at 80MHz) would be Xd = 80_000, Yd = 160_000, Zd = 320_000

    If each stepper is controlled by it's own cog and the 3 stepper cogs are synchronized all they need to “draw” or travel over that line is the number of steps to take and the delta time between each step.

    Cog X would step the motor 1000 times with a delay of 80,000 clocks between each step.
    Cog Y would step the motor 500 times with a delay of 160,000 clocks between each step.
    Cog Z would step the motor 250 times with a delay of 320,000 clocks between each step.

    Not much more difficult to have a pasm program running in a single cog do it either.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-21 20:37
    kwinn wrote: »
    Close, but not exactly what I had in mind. Sometimes I have a hard time putting what I visualize into words so I will try a simple example using motor steps instead of actual distances. No accelleration and maximum speed is 1000 steps/second for X, Y, and Z.

    Lets say we want to move from X = 1, Y = 1, Z = 1 to X = 1001, Y = 501, Z = 251

    The number of motor steps would be Xs = 1000, Ys = 500, Zs = 250

    The delta time (in clks at 80MHz) would be Xd = 80_000, Yd = 160_000, Zd = 320_000

    If each stepper is controlled by it's own cog and the 3 stepper cogs are synchronized all they need to “draw” or travel over that line is the number of steps to take and the delta time between each step.

    Cog X would step the motor 1000 times with a delay of 80,000 clocks between each step.
    Cog Y would step the motor 500 times with a delay of 160,000 clocks between each step.
    Cog Z would step the motor 250 times with a delay of 320,000 clocks between each step.

    Not much more difficult to have a pasm program running in a single cog do it either.
    Ok I do indeed see what you are saying, and kind of what I was thinking you meant.

    So Assuming a move from X,Y,Z to X1,Y1,Z1; if Cog X is the greatest distance, and X is to move with a delay of XDelay between stepps, then the speed for the other two would be:
    YDelay := XDelay * (abs(x1-x) / abs(y1-y))
    ZDelay := XDelay * (abs(x1-x) / abs(y1-y))

    Is that what you are saying?

    If I understand correctly I think I get the idea. I think it is time for me to write a little PASM (thankfully my preferred language on the propeller).

    I give you many thank you's for the advice.
  • davidsaundersdavidsaunders Posts: 1,559
    edited 2015-04-21 21:36
    kwinn wrote: »
    Close, but not exactly what I had in mind. Sometimes I have a hard time putting what I visualize into words so I will try a simple example using motor steps instead of actual distances. No accelleration and maximum speed is 1000 steps/second for X, Y, and Z.

    Lets say we want to move from X = 1, Y = 1, Z = 1 to X = 1001, Y = 501, Z = 251

    The number of motor steps would be Xs = 1000, Ys = 500, Zs = 250

    The delta time (in clks at 80MHz) would be Xd = 80_000, Yd = 160_000, Zd = 320_000

    If each stepper is controlled by it's own cog and the 3 stepper cogs are synchronized all they need to “draw” or travel over that line is the number of steps to take and the delta time between each step.

    Cog X would step the motor 1000 times with a delay of 80,000 clocks between each step.
    Cog Y would step the motor 500 times with a delay of 160,000 clocks between each step.
    Cog Z would step the motor 250 times with a delay of 320,000 clocks between each step.

    Not much more difficult to have a pasm program running in a single cog do it either.
    Just to be sure I have this correct:

    You mean something like:
    'This is a simple stepper motor controler for a three axis device like a 3D printer.
    
    'We are only using full stepping for this one.
    
    CON
    
    xBase = 0
    yBase = 4
    zBase = 8
    xPinM = $000F      'Pin Mask for X axis stepper.
    yPinM = $00F0      'Pin Mask for Y axis stepper.
    zPinM = $0F00      'Pin Mask for Z axis stepper.
    zrPin = 12         'Zeroing switch input.
    xMax =  $7FFFFFFF  'Furthest from zero allowed for X axis.
    yMax =  $7FFFFFFF  'Furthest from zero allowed for Y axis.
    zMax =  $7FFFFFFF  'Furthest from zero allowed for Z axis.
    xDely = 156250
    yDely = 156250
    zDely = 156250
    
    'The parameter offsets in the array that the cog reads:
    pCX = 0
    pCY = 1
    pCZ = 2
    pNX = 3
    pNY = 4
    pNZ = 5
    pDX = 6
    pDY = 7
    pDZ = 8
    pGo = 9
    
    
    VAR
    LONG DY, DX, DZ
    LONG PBLCK[12]
    LONG xDelay, yDelay, zDelay
    
    PUB MoveTo(ax, ay, az)
       DX := UABS(ax - PBLCK[pCX])
       DY := UABS(ay - PBLCK[pCY])
       DZ := UABS(az - PBLCK[pCZ])
    
       IF DX > DY AND DX > DZ
         PBLCK[pDX] := xDelay
         PBLCK[pDy] := ((DX << 4)  * ((DX / DY) << 4)) >> 4
         PBLCK[pDz] := ((DX << 4)  * ((DX / DZ) << 4)) >> 4
         pBLCK[pNX] := ax
         pBLCK[pNY] := aY
         pBLCK[pNZ] := aZ
         PBLCK[pGo] := 1
    
    
    
    PRI UABS(v)
      IF v < 0
        v := -v
    
      RETURN v
    
    
    
    PUB Init
      COGNEW(Main, @PBLCK)
      xDelay := xDely
      yDelay := yDely
      zDelay := zDely
    
    
    DAT
          ORG
    Main     MOV    DIRA,  Msk
    
    :Lp      JMPRET GetP_R,GetP
             OR     CG,    CG   WZ
      IF_NZ  JMPRET DoLine_R, DoLine
      IF_Z   JMP    #:Lp
    
    '&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    '&#9474;PROC: GetP                                                        &#9474;
    '&#9474;                                                                  &#9474;
    '&#9474;*DESCRIPTION:                                                     &#9474;
    '&#9474; Reads the parameter block from HUB RAM.  Takes 432  to 446 clock &#9474;
    '&#9474; cycles.                                                          &#9474;
    '&#9474;                                                                  &#9474;
    '&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    GetP     MOV    Ptr,   PAR         'PAR points at the Parameter block.
             MOV    Lptr,  #CurX       'COG Address of first parameter.
             MOV    C,     #12
    Lp0      MOVS   upd0,  ptr
             ADD    LPtr,  #4
    upd0     RDLONG Lptr,  Ptr
             DJNZ   C,     #Lp0
             JMP GetP_R
    
    PutP     MOVI upd0, :upw
             JMP GetP                   '142, 18
    
    :upw     WRLONG Lptr,  Ptr
    
    PutP_R
    GetP_R   RET
    
    '&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    '&#9474;PROC: PutP                                                        &#9474;
    '&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    'PutP     MOV    Ptr,   PAR         'PAR points at the Parameter block.
    '         MOV    Lptr,  #CurX       'COG Address of first parameter.
    '         MOV    C,     #12
    ':Lp      MOVS   :upd,  ptr
    '         ADD    LPtr,  #4
    ':upd     WRLONG Lptr,  Ptr
    '         DJNZ   C,     #:Lp
    
    'PutP_R   RET
    
    
    '&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    '&#9474;PROC: DoLine:                                                     &#9474;
    '&#9474;                                                                  &#9474;
    '&#9474;*DESCRIPTION:                                                     &#9474;
    '&#9474;Moves X, Y, and Z based on the delays until the move is complete. &#9474;
    '&#9474;                                                                  &#9474;
    '&#9474;                                                                  &#9474;
    '&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    DoLine   MOV    XT,    CNT
             MOV    YT,    CNT
             MOV    ZT,    CNT
             ADD    XT,    XDly
             ADD    YT,    YDly
             ADD    YT,    YDly
    :Lp
             CMP    XT,    CNT     WZ,WC
      IF_BE  ADD    XT,    CNT
      IF_BE  JMPRET MvX_R, MvX
             CMP    YT,    CNT     WZ,WC
      IF_BE  ADD    YT,    CNT
      IF_BE  JMPRET MvY_R, MvY
             CMP    YT,    CNT     WZ,WC
      IF_BE  ADD    YT,    CNT
      IF_BE  JMPRET MvY_R, MvY
    
             CMP    CurX,  X       WZ,WC
      IF_BE  CMP    CurY,  Y       WZ,WC
      IF_BE  CMP    CurZ,  Z
      IF_BE  JMPRET PutP_R,PutP
      IF_BE  RET
             JMP    #:LP
    
    DoLine_R RET
    
    
    '&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    '&#9474;PROC: MvX:                                                        &#9474;
    '&#9474;                                                                  &#9474;
    '&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    MvX      SUB    X,     CurX    NR,WC,WZ
             MOV    T,     Stps
      IF_Z   JMP    MvX_R
      IF_C   SUB    CurX,  #1
      IF_NC  ADD    CurX,  #1
             MOV    T0,    CurX
             AND    T0,    #$3
             SHL    T,     XBase
             SHR    T,     T0
             MOV    T0,    OUTA
             ANDN   T0,    XMsk
             JMP    #Mv_T
    
    
    '&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    '&#9474;PROC: MvY:                                                        &#9474;
    '&#9474;                                                                  &#9474;
    '&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    MvY      SUB    Y,     CurY    NR,WC,WZ
             MOV    T,     Stps
      IF_Z   JMP    MvX_R
      IF_C   SUB    CurY,  #1
      IF_NC  ADD    CurY,  #1
             MOV    T0,    CurY
             AND    T0,    #$3
             SHL    T,     YBase
             SHR    T,     T0
             MOV    T0,    OUTA
             ANDN   T0,    YMsk
             JMP    #Mv_T
    
    
       
    '&#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    '&#9474;PROC: MvZ:                                                        &#9474;
    '&#9474;                                                                  &#9474;
    '&#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    MvZ      SUB    Z,     CurZ    NR,WC,WZ
             MOV    T,     Stps
      IF_Z   JMP    MvX_R
      IF_C   SUB    CurZ,  #1
      IF_NC  ADD    CurZ,  #1
             MOV    T0,    CurZ
             AND    T0,    #$3
             SHL    T,     ZBase
             SHR    T,     T0
             MOV    T0,    OUTA
             ANDN   T0,    ZMsk
    Mv_T     OR     T0,    T
             MOV    OUTA,  T0         
    MvX_R
    MvY_R
    MvZ_R    RET
    
    
      CurX   LONG 0                     'The current X Position in steps.
      CurY   LONG 0                     'The current Y Position in steps.
      CurZ   LONG 0                     'The current Z Position in steps.
      X      LONG 0                     'The requested X position in steps.
      Y      LONG 0                     'The requested Y position in steps.
      Z      LONG 0                     'The requested Z position in steps.
      XDly   LONG xDely                 'The delay between X steps, in clock cycles.
      YDLY   LONG yDely                 'The delay between Y steps, in clock cycles.
      ZDLY   LONG zDely                 'The delay between Z steps, in clock cycles.
      CG     LONG 0                     'A flag to tell us when to go.
     
      C      LONG 0                     'Used in loops as an index.
      T      LONG 0                     'Used to store in process values.
      T0     LONG 0
    
      XT     LONG 0
      YT     LONG 0
      ZT     LONG 0
        
      Stps   LONG %0011_0110_1100_1001  'The step output values.
    
      Msk    LONG (xPinM | yPinM | zPinM)
      XMsk   LONG xPinM
      YMsk   LONG yPinM
      ZMsk   LONG zPinM
      Lptr   LONG 0
      Ptr    LONG 0
    
    
      'The states of a the four pins to control a steper in forward order.
     'cStep  BYTE %0011, %0110, %1100, %1001
    
    
    {{
    &#9484;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9488;
    &#9474;                                                   TERMS OF USE: MIT License                                                  &#9474;                                                            
    &#9500;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9508;
    &#9474;Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation    &#9474; 
    &#9474;files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy,    &#9474;
    &#9474;modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software&#9474;
    &#9474;is furnished to do so, subject to the following conditions:                                                                   &#9474;
    &#9474;                                                                                                                              &#9474;
    &#9474;The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.&#9474;
    &#9474;                                                                                                                              &#9474;
    &#9474;THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE          &#9474;
    &#9474;WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR         &#9474;
    &#9474;COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,   &#9474;
    &#9474;ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                         &#9474;
    &#9492;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9472;&#9496;
    }}
    
  • kwinnkwinn Posts: 8,697
    edited 2015-04-22 06:56
    @davidsaunders

    Yes, that looks pretty much like what I had in mind. I have only taken the time to skim through your code, so I may be wrong.
Sign In or Register to comment.