/**********************************************************************
 *                 Copyright by Mekatronix 1998                       *
 * Title          motorme.c                                           *
 * Programmer     Keith L. Doty                                       *
 * Date           May  3, 1999                                        *
 * Version        1.1                                                 *
 * Description                                                        *
 *    This module controls the left and right wheel motors of the     *
 *    TALRIK robot. Functions perform motor initialization and motor  *
 *    speed control. Two PWM interrupt drivers for motor0 (PA5,OC3)   *
 *    (Right Wheel Motor) and motor1 (PA6, OC2) (Left Wheel Motor)    *
 *    control motor speed.                                            *
 *                                                                    *
 *    Driver motor0 uses OC3 and motor1 uses OC2 timers for the PWM.  *
 *                                                                    *
 * Version History:                                                   *
 *                                                                    *
 **********************************************************************/


/*************************** Includes *********************************/

#include <hc11.h>
#include <mil.h>

/************************ End of Includes *****************************/


/*************************** Constants ********************************/

#define motor0 TOC3_isr
#define motor1 TOC2_isr

/*Full period for a motor in clock cycles. A clock cycle is 0.5 microseconds*/
#define PERIODM 65,500

/* One percent of motor period in clock cycles*/
#define PERIOD_1PC 655   

#define LEFT_MOTOR 1
#define RIGHT_MOTOR 0

/************************ End of Constants ****************************/


/*************************** Prototypes *******************************/

#pragma interrupt_handler TOC2_isr, TOC3_isr;
   void init_motorme(void);
   void motor0();
   void motor1();
   void motorme(int, int);


/************************ End of Prototypes ***************************/


/**************************** Globals *********************************/


/* Specifies the PWM duty cycle for motor0 and motor1 */   
   int duty_cycle[2]; 

/************************* End of Globals *****************************/

void init_motorme(void)
/**********************************************************************
 * Function description: This routine enables the motor interrupt     *
 *    service routines and starts the PWM signal low.		      *
 * Returns:              None                                         *
 *                                                                    *
 * Inputs                                                             *
 *   Parameters: None                                                 *
 *   Globals:    None                                                 *
 *   Registers:  TCTL1,TMSK1, DDRD                                    *
 * Outputs                                                            *
 *   Parameters: None                                                 *
 *   Globals:    None                                                 *
 *   Registers:  TCTL1,TMSK1,                                         *
 * Functions called: None                                             *
 * Notes: This routine MUST be called to enable motor operation!      *
 **********************************************************************/
{
  INTR_OFF();

/* Set OC2 and OC3 to output low */
  SET_BIT(TCTL1,0xA0);
  CLEAR_BIT(TCTL1,0x50);
  SET_BIT(DDRD, 0x30);

/* Set PWM duty cycle to 0 first */
   duty_cycle[LEFT_MOTOR] = duty_cycle[RIGHT_MOTOR] =0;

/* Enable motor interrupts on OC2 and OC3 */
  SET_BIT(TMSK1,0x60);

  INTR_ON();
}
/***********************End init_motorme ******************************/


void motorme(int index, int per_cent_duty_cycle)
/************************************************************************
 * Function description:						*
 *   Sets duty cycle and direction of motor specified by index.	    	*
 *				                                        *
 * Returns:                                                           	*
 *                                                                    	*
 * Inputs                                                             	*
 *   Parameters: index: 0 = left motor, 1 = right motor               	*
 *		     -100 <= per_cent_duty_cycle<= 100%		        *
 *   Globals:    None                                                 	*
 *   Registers:  None                                                 	*
 * Outputs                                                            	*
 *   Parameters: None                                                 	*
 *   Globals:    duty_cycle[index]					*
        0 <= duty_cycle[index]<= PERIOD (Typically, PERIOD = 65,500)  	*
 *   Registers:  None                                                 	*
 * Functions called: None                                             	*
 * Notes: Checks for proper input bounds. 			 	*
 ************************************************************************/
{
  if (per_cent_duty_cycle < 0)
     {
        per_cent_duty_cycle = -per_cent_duty_cycle; /* Make positive */
     /* Set negative direction of motors */
  	if (index == RIGHT_MOTOR) CLEAR_BIT(PORTD,0x20); /*Right motor*/
        if (index == LEFT_MOTOR) CLEAR_BIT(PORTD,0x10); /*Left motor*/
     }
  else
     {
     /* Set positive direction of motors */
        if (index == RIGHT_MOTOR) SET_BIT(PORTD, 0x20); /*Right motor*/
        if (index == LEFT_MOTOR) SET_BIT(PORTD, 0x10); /*Left motor*/
     }

/* At this point per_cent_duty_cycle must be a positive number less
 * than 100. If not make it so.
 */
  if (per_cent_duty_cycle > 100) per_cent_duty_cycle = 100;
  duty_cycle[index] = per_cent_duty_cycle*PERIOD_1PC;

}
/*********************** End motor ***********************************/

void motor0(void)
/************************************************************************
 * Function description:						*
 *	This interrupt routine controls the PWM to motor0 using OC3. For*
 *	the TALRIK II robot motor0 is the left motor.			*
 * Returns:	None                                                    *
 *                                                                    	*
 * Inputs                                                             	*
 *   Parameters: 	None						*
 *   Globals: 	duty_cycle[RIGHT_MOTOR]					*
 *   Registers:  	TCTL1, TOC3					*
 * Outputs								*
 *   Parameters: 	None						*
 *   Globals:    	None						*
 *   Registers:  	TCTL1, TOC2, TFLG1				*
 * Functions called: CLEAR_BIT, SET_BIT					*
 * Notes: init_motortk() assumed to have executed			*
 ************************************************************************/
{
/* Keep the motor off if no duty cycle specified.*/
//  if(duty_cycle[RIGHT_MOTOR] == 0)
//   {
//    CLEAR_BIT(TCTL1, 0x10);
//   }
//  else
//    if(TCTL1 & 0x10)
//     {
//      TOC3 += duty_cycle[RIGHT_MOTOR];      /* Keep up for width */
//      CLEAR_BIT(TCTL1,0x10);                /*  Set to turn off */
//     }
//    else
//     {
//      TOC3 += (PERIODM - duty_cycle[RIGHT_MOTOR]);
//      SET_BIT(TCTL1,0x10);                  /* Set to raise signal */
//     }
  CLEAR_FLAG(TFLG1,0x20);                 /* Clear OC3F interrupt Flag */
}
/*********************** End motor0 ***********************************/


void motor1 (void)
/************************************************************************
 * Function description:								*
 *	This interrupt routine controls the PWM to motor1 using OC2. For	*
 *	the TALRIK II robot motor1 is the right motor.			     	*
 * Returns:	None                                                      	*
 *                                                                    	*
 * Inputs                                                             	*
 *   Parameters: 	None									*
 *   Globals: 	duty_cycle[LEFT_MOTOR]						*
 *   Registers:  	TCTL1, TOC2								*
 * Outputs											*
 *   Parameters: 	None									*
 *   Globals:    	None									*
 *   Registers:  	TCTL1, TOC2, TFLG1						*
 * Functions called: CLEAR_BIT, SET_BIT						*
 * Notes: init_motortk() assumed to have executed				*
 ************************************************************************/
{
/* Keep the motor off if no duty cycle specified.*/
//  if(duty_cycle[LEFT_MOTOR] == 0)
//   {
//    CLEAR_BIT(TCTL1, 0x40);
//   }
//  else
//    if(TCTL1 & 0x40)
//     {
//      TOC2 += duty_cycle[LEFT_MOTOR];  /* Keep pulse width up for duty_cycle */
//      CLEAR_BIT(TCTL1,0x40);  /*  Prepare to turn off next OC2 interrupt*/
//     }
//    else
//     {
//       TOC2 += (PERIODM - duty_cycle[LEFT_MOTOR]);
//       SET_BIT(TCTL1,0x40);   /* Prepare to raise signal next OC2 intr. */
//     }
  CLEAR_FLAG(TFLG1,0x40);     /* Clear OC2F interrupt Flag */

}
/********************** End motor1 **************************************/

