/*------------------------------------------------------*/
/*             68HC11 - Smart IO Card Driver            */
/*                 Motor Control Library                */
/*                                                      */
/*                      MOTOR.C                         */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/*                                                      */
/* Routines:                                            */
/*     interrupt tme_oc2()                              */
/*     interrupt tme_oc3()                              */
/*     mtr_init(PORT,A_TYPE,B_TYPE)                     */
/*     mtr_clock(ARRAY,t_time,duty)                     */
/*     mtr_send(AA,BB)                                  */
/*     mtr_mode(ARRAY,MODE)                             */
/*     mtr_on(ARRAY)                                    */
/*     mtr_off(ARRAY)                                   */
/*     mtr_stepcnt(ARRAY,stepcount)                     */
/*     mtr_forward(ARRAY)                               */
/*     mtr_reverse(ARRAY)                               */
/*     mtr_scoff(ARRAY)                                 */
/*     mtr_scon(ARRAY)                                  */
/*                                                      */
/*______________________________________________________*/


#define SIZE    10

unsigned int    A[SIZE];       /*-----------------------*/
unsigned int    B[SIZE];       /*  Motor Control Array  */
                               /*      Deffinitions     */
                               /*                       */
                               /* x[0] - port address   */
                               /* x[1] - control nibble */
                               /* x[2] - motor number   */
                               /*          0 = Motor A  */
                               /*          1 = Motor B  */
                               /* x[3] - motor type     */
                               /*          0 = Stepper  */
                               /*          1 = DC       */
                               /* x[4] - total time     */
                               /*          (in counts)  */
                               /* x[5] - duty cycle     */
                               /*          (in %)       */
                               /* x[6] - time on        */
                               /*          (in counts)  */
                               /* x[7] - time off       */
                               /*          (in counts)  */
                               /* x[8] - step count     */
                               /*          (steps to go */
                               /*          stepper mode */
                               /*          only. FFFFH  */
                               /*          indicates    */
                               /*          free run)    */
                               /*_______________________*/


unsigned int    temp;          /*     temp variable     */



/*------------------------------------------------------*/
/*               OC2 Interrupt for Motor A              */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Function: Create a timing signal for Motor A on pin  */
/*           PA6.                                       */
/*                                                      */
/*           mtr_init() MUST be called before this int  */
/*           is active.                                 */
/*______________________________________________________*/

interrupt tme_oc2()
{

#asm
        LDX     #REG_BASE
        BRCLR   PORTA,x %01000000 OC2_L1
        BCLR    PORTA,x %01000000
        LDD     _A+14
        JMP     OC2_L2
OC2_L1  BSET    PORTA,x %01000000
        LDD     _A+12
OC2_L2  ADDD    TCNT
        STD     TOC2
        LDAA    #%01000000
        staa    TFLG1
#endasm

if (A[8] != 0xffff) A[8]--;

if (A[8] == 0x0000) bit_clr(TMSK1, 0x40);
}


/*------------------------------------------------------*/
/*               OC3 Interrupt for Motor B              */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Function: Create a timing signal for Motor B on pin  */
/*           PA5.                                       */
/*                                                      */
/*           mtr_init() MUST be called before this int  */
/*           is active.                                 */
/*______________________________________________________*/


interrupt tme_oc3()
{
#asm
        LDX     #REG_BASE
        BRCLR   PORTA,x %00100000 OC3_L1
        BCLR    PORTA,x %00100000
        LDD     _B+14
        JMP     OC3_L2
OC3_L1  BSET    PORTA,x %00100000
        LDD     _B+12  
OC3_L2  ADDD    TCNT
        STD     TOC3
        LDAA    #%00100000
        staa    TFLG1
#endasm

if (B[8] != 0xffff) B[8]--;

if (B[8] == 0x0000) bit_clr(TMSK1, 0x20);

}



/*------------------------------------------------------*/
/*               Motor Control Initialization           */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_int(Port,A_TYPE,B_TYPE)                */
/* Where:    Port - address of expanded I/O Board       */
/*           A_TYPE and B_TYPE is motor type            */
/*               0 = stepper motor                      */
/*               1 = dc motor                           */
/*                                                      */
/* Function: To set up motor control arrays and timer   */
/*           interrupts                                 */
/*                                                      */
/*______________________________________________________*/


mtr_init(PORT,A_TYPE,B_TYPE)
unsigned int PORT;
unsigned int A_TYPE;
unsigned int B_TYPE;
{

        d_int();
        poke (TME_OC2_IV,tme_oc2);
        poke (TME_OC3_IV,tme_oc3);
        e_int();

        /* set up initial array values */
        A[0] = PORT;
        B[0] = PORT;

        A[1] = 0;
        B[1] = 0;

        A[2] = 0;
        B[2] = 1;

        mtr_send(A,B);

        A[3] = A_TYPE;
        B[3] = B_TYPE;

        A[8] = 0xffff;
        B[8] = 0xffff;

        mtr_clock(A,1000,50);
        mtr_clock(B,1000,25);

        if (A[3] == 1) bit_set (TMSK1,0x40);
        if (B[3] == 1) bit_set (TMSK1,0x20);

}


/*------------------------------------------------------*/
/*                Motor Clock Calculations              */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_clock(ARRAY,t_time,duty)               */
/* Where:    ARRAY - Motor (A or B)                     */
/*           t_time - Total time in counts              */
/*           duty - duty cycle                          */
/*               (set to 50 for stepper motor)          */
/*                                                      */
/* Function: To calculate on/off times for clock        */
/*           signals                                    */
/*                                                      */
/*______________________________________________________*/

mtr_clock(ARRAY,t_time,duty)
unsigned int ARRAY[SIZE];
unsigned int t_time;
unsigned int duty;
{

        ARRAY[4] = t_time;
        ARRAY[5] = duty;

        ARRAY[6] = t_time / 100 * duty; 
        ARRAY[7] = t_time / 100 * (100 - duty);

}

/*------------------------------------------------------*/
/*                     Motor Send                       */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          4/27/00                */
/*                                                      */
/* Call By:  mtr_send(AA,BB)                            */
/* NOTE:     Always called using mtr_send(A,B)          */
/*                                                      */
/* Function: sends control nibbles to proper output     */
/*           port. This routine is called by other      */
/*           functions in the library and should not    */
/*           be called directly.                        */
/*                                                      */
/*______________________________________________________*/

mtr_send(AA,AB)
unsigned int AA[SIZE];
unsigned int AB[SIZE];
{
        temp = AB[1]*16+AA[1];

        #asm
                ldaa _temp+1
                ldx _A
                staa $0,x
        #endasm
}


/*------------------------------------------------------*/
/*            Set Motor Mode (Stepper Motor Only)       */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_mode(ARRAY,MODE)                       */
/* Where:    ARRAY - Motor (A or B)                     */
/*           MODE:   0 =                                */
/*                   1 =                                */
/*                   2 =                                */
/*                   3 =                                */
/*                                                      */
/* Function: To slect the stepper motor mode (step      */
/*           sequence.                                  */
/*                                                      */
/*           This routine automatically sends the       */
/*           new mode to the motor control port.        */
/*                                                      */
/*______________________________________________________*/


mtr_mode(ARRAY,MODE)
unsigned int ARRAY[SIZE];
unsigned int MODE;
{
        ARRAY[1] = ARRAY[1] & 3;
        ARRAY[1] = MODE * 4 + ARRAY[1];

        mtr_send(A,B);
}

/*------------------------------------------------------*/
/*                     Start Motor                      */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_on(ARRAY)                              */
/* Where:    ARRAY - Motor (A or B)                     */
/*                                                      */
/* Function: To activate the selected motor. For a DC   */
/*           motor, this routine sets the on/off bit    */
/*           of the motor control nibble. For a Stepper */
/*           motor, this routine resets the clock       */
/*           generator (OC2 or OC3) and puts the clock  */
/*           into its free run mode (will keep running  */
/*           until stopped by calling mtr_off().        */
/*                                                      */
/*           Use mtr_stepcnt() to drive a stepper motor */
/*           for a known number of steps                */
/*                                                      */
/*______________________________________________________*/

mtr_on(ARRAY)
unsigned int ARRAY[SIZE];
{
        if (ARRAY[3] == 1)
        {
                ARRAY[1] = ARRAY[1] | 0x0002;
                mtr_send(A,B);
        }
        if (ARRAY[3] == 0)
        {
                if (ARRAY[2] == 0)
                {
                        ARRAY[8] = 0xffff;
                        bit_set(TMSK1,0x40);
                }
                if (ARRAY[2] == 1)
                {
                        ARRAY[8] = 0xffff;
                        bit_set(TMSK1,0x20);
                }
        }

}

/*------------------------------------------------------*/
/*                      Stop Motor                      */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_off(ARRAY)                             */
/* Where:    ARRAY - Motor (A or B)                     */
/*                                                      */
/* Function: To de-activate selected motor. For a DC    */
/*           motor, this routine clears the on/off bit  */
/*           of the motor control nibble. For a Stepper */
/*           motor, this routine stops the clock        */
/*           generator (OC2 or OC3).                    */
/*                                                      */
/*______________________________________________________*/

mtr_off(ARRAY)
unsigned int ARRAY[SIZE];
{
        if (ARRAY[3] == 1)
        {
                ARRAY[1] = ARRAY[1] & 0xFFFD;
                mtr_send(A,B);
        }
        if (ARRAY[3] == 0)
        {
                if (ARRAY[2] == 0)
                {
                        ARRAY[8] = 0x0;
                }
                if (ARRAY[2] == 1)
                {
                        ARRAY[8] = 0x0;
                }
        }

}

/*------------------------------------------------------*/
/*             Stepper Motor Stepcount Routine          */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_stepcnt(ARRAY,stepcount)               */
/* Where:    ARRAY - Motor (A or B)                     */
/*           stepcount - number of steps to execute     */
/*                   (1 to FFFF)                        */
/*                                                      */
/* Function: Sets up the clock driver to generate       */
/*           'stepcount' number of pulses and then stop */
/*                                                      */
/*______________________________________________________*/


mtr_stepcnt(ARRAY,stepcount)
unsigned int ARRAY[SIZE];
unsigned int stepcount;
{
        ARRAY[8] = stepcount;
        if (ARRAY[2] == 0)
        {
                bit_set(TMSK1,0x40);
        }
        if (ARRAY[2] == 1)
        {
                bit_set(TMSK1,0x20);
        }
}

/*------------------------------------------------------*/
/*             Drive Motor in Forward Direction         */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_forward(ARRAY)                         */
/* Where:    ARRAY - Motor (A or B)                     */
/*                                                      */
/* Function: Sets motor control nibble's direction bit  */
/*           to drive the motor in the forward          */
/*           direction.                                 */
/*______________________________________________________*/

mtr_forward(ARRAY)
unsigned int ARRAY[SIZE];
{
        ARRAY[1] = ARRAY[1] & 0xFFFE;
        mtr_send(A,B);
}


/*------------------------------------------------------*/
/*             Drive Motor in Reverse Direction         */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_reverse(ARRAY)                         */
/* Where:    ARRAY - Motor (A or B)                     */
/*                                                      */
/* Function: Sets motor control nibble's direction bit  */
/*           to drive the motor in the reverse          */
/*           direction.                                 */
/*______________________________________________________*/

mtr_reverse(ARRAY)
unsigned int ARRAY[SIZE];
{
        ARRAY[1] = ARRAY[1] | 0x0001;
        mtr_send(A,B);
}

/*------------------------------------------------------*/
/*                Stepper Motor Coils Off               */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_scoff(ARRAY)                           */
/* Where:    ARRAY - Motor (A or B)                     */
/*                                                      */
/* Function: Sets motor control nibble's on/off bit     */
/*           to turn off the coils of the stepper motor */
/*______________________________________________________*/

mtr_scoff(ARRAY)
unsigned int ARRAY[SIZE];
{
        ARRAY[1] = ARRAY[1] & 0xFFFD;
        mtr_send(A,B);
}


/*------------------------------------------------------*/
/*                Stepper Motor Coils On                */
/*                                                      */
/*                Written by:    Dan Kohn               */
/*                Rev:           1.0                    */
/*                Date:          1/20/00                */
/*                                                      */
/* Call By:  mtr_scon(ARRAY)                            */
/* Where:    ARRAY - Motor (A or B)                     */
/*                                                      */
/* Function: Sets motor control nibble's on/off bit     */
/*           to turn on the coils of the stepper motor  */
/*______________________________________________________*/

mtr_scon(ARRAY)
unsigned int ARRAY[SIZE];
{
        ARRAY[1] = ARRAY[1] | 0x0002;
        mtr_send(A,B);
}


