]> code.bitgloo.com Git - abelleisle/vex5106z.git/commitdiff
libZEPHYR began
authorClyne Sullivan <tullivan99@gmail.com>
Mon, 30 Nov 2015 21:01:54 +0000 (16:01 -0500)
committerClyne Sullivan <tullivan99@gmail.com>
Mon, 30 Nov 2015 21:01:54 +0000 (16:01 -0500)
include/API.h
include/main.h
include/zephyr.h [new file with mode: 0644]
src/auto.c
src/auton.c [deleted file]
src/init.c
src/opcontrol.c
src/zephyr.c [new file with mode: 0644]

index 7de788979e7819d7afef280213a88786d56dacf1..32d8686b67f9efb7cc2cc707399af3c5c7d6f15f 100644 (file)
@@ -504,6 +504,7 @@ unsigned int imeInitializeAll();
  * * \c 240.448 for the 269 IME\r
  * * \c 627.2 for the 393 IME in high torque mode (factory default)\r
  * * \c 392 for the 393 IME in high speed mode\r
+ * * \c 261.333 for the 393 IME in turbo speed mode\r
  *\r
  * If the IME address is invalid, or the IME has not been reset or initialized, the value\r
  * stored in *value is undefined.\r
@@ -527,6 +528,7 @@ bool imeGet(unsigned char address, int *value);
  * * \c 30.056 for the 269 IME\r
  * * \c 39.2 for the 393 IME in high torque mode (factory default)\r
  * * \c 24.5 for the 393 IME in high speed mode\r
+ * * \c 16.3333125 for the 393 IME in turbo speed mode\r
  *\r
  * If the IME address is invalid, or the IME has not been reset or initialized, the value\r
  * stored in *value is undefined.\r
index d1fcdb4e479413b2061cc30671674f1190dbed4b..7022f1187b45e24e523b1e87f4db217e586f775b 100644 (file)
@@ -2,44 +2,12 @@
 #define MAIN_H_\r
 \r
 #include <API.h>\r
-\r
-#define LCD_PORT uart1\r
-\r
-#define ANALOG_PORT(x) (x+13)\r
+#include <zephyr.h>\r
 \r
 #ifdef __cplusplus\r
 extern "C" {\r
 #endif\r
 \r
-/*\r
- *     Aliases for all the motors, stored in an enum for convenience.\r
-*/\r
-\r
-enum MOTOR_PORT_MAP {\r
-       UNUSED = 0,\r
-       CANNON1,\r
-       CANNON2,\r
-       CANNON3,\r
-       CANNON4,\r
-       INTAKE,\r
-       DRIVER,\r
-       DRIVEL,\r
-       LIFT1,\r
-       LIFT2,\r
-       ROTATER,\r
-};\r
-\r
-enum IME_PORT_MAP {\r
-       IDRIVER = 0,\r
-       IDRIVEL,\r
-       IROTATER,\r
-       ILIFT1,\r
-       ILIFT2,\r
-       ICANNONL,\r
-       ICANNONR\r
-};\r
-\r
-\r
 void autonomous();\r
 void initializeIO();\r
 void initialize();\r
diff --git a/include/zephyr.h b/include/zephyr.h
new file mode 100644 (file)
index 0000000..844416a
--- /dev/null
@@ -0,0 +1,90 @@
+#ifndef ZEPHYR_H_
+#define ZEPHYR_H_
+
+#include <main.h>
+
+#define APPLY_THRESH(n,t)      if(n < t && n > -t){ n = 0;}
+
+/*
+ *     Comment to disable LCD support.
+*/
+
+#define LCD_PORT       uart1
+
+#define LCD_RATE       500
+
+#ifdef LCD_PORT
+
+void zLCDInit(void);
+void zLCDStart(void);
+
+void zLCDWrite(unsigned char,  // 1-based Line Number
+                          const char *,        // Text
+                          ...);
+
+void zLCDSetUpdateFunc(void (*)(void *));      // Function Pointer
+void zLCDClearUpdateFunc(void);
+
+#endif // LCD_PORT
+
+/*
+ *     Comment to disable gyro support.
+*/
+
+#define GYRO_PORT      2
+
+#ifdef GYRO_PORT
+
+void zGyroInit(void);
+
+#endif // GYRO_PORT
+
+/*
+ *     Comment to disable IME support.
+*/
+
+#define IME_ENABLE
+
+#ifdef IME_ENABLE
+
+void zIMEInit(void);
+
+#endif // IME_ENABLE
+
+/*
+ *     DRIVE_NORMAL will override tank drive options.
+*/
+
+#define DRIVE_JOY                      1
+#define DRIVE_THRESHOLD                10
+
+//#define DRIVE_NORMAL         3
+
+#define DRIVE_TANK_LEFT                3
+#define DRIVE_TANK_RIGHT       2
+
+#define zJoyDigital(j,g,b)     joystickGetDigital(j,g,b)
+#define zJoyAnalog(j,a)                joystickGetAnalog(j,a)
+
+void zMotorSet(const char *,   // Motor Name
+                          char                         // Desired Speed
+                          );
+char zMotorGet(const char *);  // Motor Name
+
+#ifdef IME_ENABLE
+
+int zMotorIMEGet(const char *);                        // Motor Name
+int zMotorIMEGetVelocity(const char *);        // Motor Name
+
+#endif // IME_ENABLE
+
+void zDriveUpdate(void);
+
+char zGetDigitalMotorSpeed(unsigned char,      // Joystick No.
+                                                  unsigned char,       // Button Group
+                                                  unsigned char,       // Positive Button
+                                                  unsigned char,       // Negative Button
+                                                  char                         // Desired Speed
+                                                  );
+
+#endif // ZEPHYR_H_
index 3c8f2ef3b382a95b3d2bf89cbf663a670ad2c303..23324284dd2e0b8b3de18b522351ac6ff0374c29 100644 (file)
@@ -1,16 +1,16 @@
 #include <main.h>\r
 \r
-#define TARGET_SPEED 65\r
+/*#define TARGET_SPEED 65\r
 \r
 static unsigned int time;\r
 \r
 void autoDelay(unsigned int ms){\r
        delay(ms);\r
        time-=ms;\r
-}\r
+}*/\r
 \r
 void autonomous(){\r
-       static char speed = 0;\r
+       /*static char speed = 0;\r
 \r
        time = 15000;\r
 \r
@@ -36,6 +36,6 @@ void autonomous(){
        //while(1);\r
        delay(time);\r
 \r
-       motorStopAll();\r
+       motorStopAll();*/\r
 \r
 }\r
diff --git a/src/auton.c b/src/auton.c
deleted file mode 100644 (file)
index 8af90eb..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-#include <main.h>
-
-extern Gyro gyro;
-
-#ifndef PI
-#define PI 3.14159265L
-#endif // PI
-
-#define RPM_DEFAULT_MAX                160                             //      Max RPM of high-speed motor
-#define RPM_CANNON_MAX         4000                    //      Max RPM of cannon (motor + gears)
-#define RPM_CANNON_INC         31.49606299L    //      Expected change in RPM per joystick increment
-
-#define RPM_THRESHOLD          100                             //      A margin of error for matching the target RPM
-
-#define INC_FAULT                      2                               //      Boost given to motors when left and right don't match RPM
-#define INC_NORMAL                     2                               //      Used to match actual velocity to the target
-
-#define ROT_THRESHOLD          (PI/8)                  //      Margin of error for auto-aiming
-#define ROT_SPEED                      30                              //      How fast to rotate the cannon for aiming (for linear aiming only)
-
-static double rpmTarget = 0;   // Contains the desired RPM
-
-static double rpmCannL = 0;            // Left side's RPM
-static double rpmCannR = 0;            // Right side's RPM
-static double rpmCannA = 0;            // Average of the two above
-
-static double rotCannon = 0;   // Cumulative rotation of the cannon in radians
-
-/**
- * Calculates RPMs from cannon motors.
- *
- * There are two IMEs on the cannon, one per each side. This function converts the raw
- * velocity reading from the motors and converts it to rotations per minute (RPM).
- * Results are stored in global variables defined above, as well as an average of the
- * two.
- */
-
-void cannUpdate(void){
-       int cl,cr,rc;
-
-       /*
-        *      Read raw velocity values.
-       */
-
-       imeGetVelocity(ICANNONL,&cl);
-       imeGetVelocity(ICANNONR,&cr);
-
-       /*
-        *      Divide by a divisor given in API.h and multiply the result by the cannon's gear ratio.
-       */
-
-       rpmCannL = cl / 24.5L * 25.0L;
-       rpmCannR = cr / 24.5L * 25.0L;
-
-       /*
-        *      Calculate an average of the two results from above.
-       */
-
-       rpmCannA = (rpmCannL + rpmCannR) / 2;
-
-       /*
-        *      Find the cumulative rotation of the cannon for auto-aiming.
-       */
-
-       imeGet(IROTATER,&rc);
-
-       rotCannon = rc / 627.2L * 5;
-       rotCannon *= 2*PI;                              // convert to radians
-
-}
-
-/**
- * Sets a target RPM for the cannon.
- *
- * This calculates a target RPM by simply multiplying the current position of a jostick axis
- * by a predetermined increment that is 1/127th of the highest possible RPM of the cannon.
- *
- * @param a value returned from a call to joystickGetAnalog()
- */
-
-void cannTarget(char jpos){
-       rpmTarget = jpos * RPM_CANNON_INC;
-}
-
-/**
- * Runs/Updates the actual speed of the cannon motors.
- *
- * Speeds for each side of the cannon are kept inside the scope of this function. Two checks
- * are made before applying the motor speeds. The first one will increase the speed of one
- * side of the cannon if the RPMs of the two sides aren't reasonably equal. The second check
- * will bring the overall speeds up or down depending on where the actual average RPM is
- * compared to the target. Following these checks is the setting of the motor speeds.
- */
-
-void cannRun(void){
-       static char speedCannL = 0;
-       static char speedCannR = 0;
-
-       /*
-        *      Make sure cannon motors are up to about the same speed (as in RPM).
-       */
-
-                if(rpmCannR < rpmTarget + RPM_THRESHOLD && rpmCannL < rpmCannR - RPM_THRESHOLD) speedCannL += INC_FAULT;
-       else if(rpmCannL < rpmTarget + RPM_THRESHOLD && rpmCannR < rpmCannL - RPM_THRESHOLD) speedCannR += INC_FAULT;
-
-       /*
-        *      Adjust motor velocities to match the target.
-       */
-
-       if(rpmTarget > rpmCannA + RPM_THRESHOLD){
-               speedCannL += INC_NORMAL;
-               speedCannR += INC_NORMAL;
-       }else if(rpmTarget < rpmCannA - RPM_THRESHOLD){
-               speedCannL -= INC_NORMAL;
-               speedCannR -= INC_NORMAL;
-       }
-
-       /*
-        *      Apply the calculated motor speeds.
-       */
-
-       motorSet(CANNON1,speedCannL);
-       motorSet(CANNON2,speedCannR);
-       motorSet(CANNON3,speedCannL);
-       motorSet(CANNON4,speedCannR);
-}
-
-/**
- * Aims the cannon towards a specified location(?)
- *
- * ... . Also sets the motor speed.
- *
- * @param a rotation to base calculations of off (preferably that of the robot's body)
- */
-
-void cannAim(double r){
-       static char speed = 0;
-
-       /*
-        *      Do simple linear adjustments to have okay-ish aim. Once self-location is accomplished
-        *      a more accurate function could be used to adjust aim.
-       */
-
-                if(rotCannon > r + ROT_THRESHOLD) speed =  ROT_SPEED;
-       else if(rotCannon < r - ROT_THRESHOLD) speed = -ROT_SPEED;
-       else                                                               speed =  0;
-
-       /*
-        *      Apply the resulting speed to the motor.
-       */
-
-       motorSet(ROTATER,speed);
-}
index a59dcba2405a8e17896b0fd9864d95bfd5b2d070..3c1a7d2dc6f68f887af150f64215984a90a61977 100644 (file)
@@ -1,32 +1,14 @@
 #include <main.h>\r
 \r
-Gyro gyro;\r
-unsigned int imeCount;\r
-\r
 void initializeIO(){\r
-       pinMode(ANALOG_PORT(1),INPUT_ANALOG);   // Power expander status port\r
-       pinMode(1,OUTPUT);                                              // LED\r
-       pinMode(2,INPUT);\r
-       pinMode(3,INPUT);\r
-       pinMode(4,INPUT);\r
 }\r
 \r
 void initialize(){\r
 \r
-       //      Initialize the LCDs.\r
-\r
-       lcdInit(uart1);\r
-       lcdClear(uart1);\r
-       lcdSetBacklight(uart1,1);\r
-\r
-       //      Setup sensors.\r
+       zLCDInit();\r
+       zGyroInit();\r
+       zIMEInit();\r
 \r
-       imeCount = imeInitializeAll();\r
-       gyro=gyroInit(2,0);\r
-\r
-       lcdPrint(uart1,1,"%u IMEs :)",imeCount);\r
-       delay(1000);\r
-       lcdPrint(uart1,1,"ready...");\r
        delay(1000);\r
 \r
 }\r
index 8e410fa1b560d50aeb0ffe6cb48fc93b546fb2f1..e5955ebfe2b1aa1c1513247dabc28c713154b23b 100644 (file)
 #include <main.h>\r
-#include <stdint.h>\r
-#include <math.h>\r
 \r
-#define PI 3.1415926535L\r
-\r
-extern Gyro gyro;      // Originally defined in init.c\r
-\r
-static double Vl,      // left wheel velocity\r
-                         Vr,   // right wheel velocity\r
-                         Vc,   // center/average velocity\r
-                         Va,   // angular velocity\r
-                         Vra;  // velocity ratio\r
-\r
-static double R;       // radius of current circular path\r
-\r
-static double Px=0,    // X position\r
-                         Py=0; // Y position\r
-\r
-void operatorLCD(void *start){\r
-       while(1){\r
-\r
-               lcdPrint(uart1,1,"%.3lf, %.3lf",R,Va);\r
-\r
-               delay(100);\r
-       }\r
-}\r
-\r
-static unsigned int START;\r
+void lcdUpdateFunc(void *);\r
 \r
 void operatorControl(){\r
 \r
-       static char uiinc = 0;  // See below\r
-       static char in=0,lift;  // Used to set the multiple cannon motors to the same joy-stick reading.\r
-\r
-       static char joy;\r
+       static char lift;\r
 \r
-       /*\r
-        *      Start other tasks.\r
-       */\r
-\r
-       START = ((!digitalRead(3)) | (!digitalRead(4)<<1)) + 1;\r
-       taskCreate(operatorLCD ,TASK_DEFAULT_STACK_SIZE,&START,TASK_PRIORITY_DEFAULT);\r
+       zLCDStart();\r
+       zLCDSetUpdateFunc(lcdUpdateFunc);\r
 \r
        while(1){\r
 \r
-               //      Set the drive motors speeds.\r
+               /*\r
+                *      Handle drive controls and update drive motor speeds.\r
+               */\r
 \r
-               joy=joystickGetAnalog(1,3);\r
-               if(joy < 10 && joy > -10)joy=0;\r
-               motorSet(DRIVEL,joy);\r
-               joy=joystickGetAnalog(1,2);\r
-               if(joy < 10 && joy > -10)joy=0;\r
-               motorSet(DRIVER,joy);\r
+               zDriveUpdate();\r
 \r
                //      Set the rotating motor speed.\r
 \r
-               motorSet(ROTATER,-joystickGetAnalog(2,1)/4);\r
-\r
-               in=joystickGetAnalog(2,3);\r
-\r
-               motorSet(CANNON1,in);\r
-               motorSet(CANNON2,in);\r
-               motorSet(CANNON3,in);\r
-               motorSet(CANNON4,in);\r
+               zMotorSet("ROTATER",-zJoyAnalog(2,1)/4);\r
 \r
                // Set the intake's speed.\r
 \r
-               motorSet(INTAKE,joystickGetDigital(1,6,JOY_UP  )?  127 :\r
-                                               joystickGetDigital(1,6,JOY_DOWN)? -127 :\r
-                                               0 );\r
+               zMotorSet("INTAKE",zGetDigitalMotorSpeed(1,6,JOY_UP,JOY_DOWN,127));\r
 \r
                // Set the lift's speed.\r
 \r
-               lift=joystickGetDigital(2,6,JOY_UP  )?  127 :\r
-                        joystickGetDigital(2,6,JOY_DOWN)? -127 :\r
-                        0 ;\r
+               lift=zGetDigitalMotorSpeed(2,6,JOY_UP,JOY_DOWN,127);\r
 \r
-               motorSet(LIFT1,lift);\r
-               motorSet(LIFT2,lift);\r
-\r
-               /*\r
-                *      Miscellaneous operation handlers.\r
-                */\r
-\r
-               if(++uiinc==20){        // Equates to every 200ms\r
-                       uiinc=0;\r
-\r
-                       // Run autonomous (for testing wo/ competition switch).\r
-\r
-                       if(joystickGetDigital(1,7,JOY_RIGHT))\r
-                               autonomous();\r
-\r
-                       // Test\r
-\r
-                       if(joystickGetDigital(1,7,JOY_LEFT)){\r
-\r
-                       }\r
-\r
-               }\r
+               zMotorSet("LIFT1",lift);\r
+               zMotorSet("LIFT2",lift);\r
 \r
                delay(10);      // Short delay to allow task switching\r
+       }\r
+}\r
 \r
-               /*\r
-                *      Get the velocity of the two (IME'd) drive motors.\r
-               */\r
-\r
-               static int vl,vr;\r
-\r
-               imeGetVelocity(1,&vl);\r
-               imeGetVelocity(0,&vr);\r
-\r
-               /*\r
-                *      Convert the raw reading to rotations a minute, then inches per minute, then inches\r
-                *      per second.\r
-               */\r
-\r
-               Vl =  vl /* RPM Divisor         */ / 39.2L\r
-                                /* Wheel Circumference */ * 8\r
-                                /* Minutes to seconds  */ / 60;\r
-\r
-               Vr = -vr / 39.2L * 8 / 60;      // Right wheel IME is inverted\r
-\r
-               Vc = (Vl + Vr) / 2;                     // Average/Center velocity\r
-\r
-               /*\r
-                *      Round down the results to the nearest inch, and enforce a 2 in/s threshold.\r
-               */\r
-\r
-               Vl = floor(Vl);\r
-               Vr = floor(Vr);\r
-\r
-               if(Vl < 2 && Vl > -2) Vl = 0;\r
-               if(Vr < 2 && Vr > -2) Vr = 0;\r
-\r
-               /*\r
-                *      Calculate the ratio of the higher velocity to the lowest, for determining the\r
-                *      radius of the circle the robot is forming.\r
-               */\r
-\r
-               if(((!Vr) & (Vl!=0)) ||\r
-                  ((!Vl) & (Vr!=0)) ){\r
-\r
-                       /*\r
-                        *      One wheel isn't moving, the radius is the distance between the wheels.\r
-                       */\r
-\r
-                       R = 15;\r
-                       goto CONT;\r
-\r
-               }else if((Vr > Vl) & (Vl > 0) ||        // Curve to forwards right\r
-                                (Vl > Vr) & (Vl < 0) ){        // Curve to backwards right\r
-\r
-                       Vra = Vr / Vl;\r
-\r
-               }else if((Vl > Vr) & (Vr > 0) ||        // Curve to forwards left\r
-                                (Vr > Vl) & (Vr < 0) ){        // Curve to backwards left\r
-\r
-                       Vra = Vl / Vr;\r
-\r
-               }else Vra = 0;                                          // No movement?\r
-\r
-               if(Vra<0) Vra *= -1;                            // get absolute value of the ratio\r
-\r
-               /*\r
-                *      "Plug-n'-chug" for a radius, assuming that the radius will increase by 7.5 (the\r
-                *      halfway between the wheels on the robot) when multiplied by the ratio.\r
-               */\r
-\r
-               for(R = 0; R < 200; R++){\r
-\r
-                       if(R * Vra > R + 7 &&           // Allow a one inch margin of error\r
-                          R * Vra < R + 8)break;       //\r
-               }\r
-\r
-CONT:\r
-\r
-               /*\r
-                *      Calculate the anglular velocity of the robot.\r
-               */\r
-\r
-               Va = Vc / R;\r
-\r
-               /*\r
-                *      Determine the increase in X and Y position based on the angular velocity and the\r
-                *      average total movement.\r
-               */\r
+void lcdUpdateFunc(void *unused_param){\r
+       static double liftIME;\r
 \r
-               Px += cos(Va) * Vc * .01;       // Convert per second velocity to per 10ms, as the motors\r
-               Py += sin(Va) * Vc * .01;       // have only been at this velocity for that time (above).\r
+       liftIME = (zMotorIMEGetVelocity("LIFT1") - zMotorIMEGetVelocity("LIFT2")) / 2 / 16.3333125L;\r
 \r
-       }\r
+       zLCDWrite(1,"%.3lf",liftIME);\r
 }\r
diff --git a/src/zephyr.c b/src/zephyr.c
new file mode 100644 (file)
index 0000000..847f95a
--- /dev/null
@@ -0,0 +1,192 @@
+#include <zephyr.h>
+#include <main.h>
+
+#include <string.h>
+
+#ifdef LCD_PORT
+
+static void (*_lcdUpdateFunc)(void *);
+static char lcdBuffer[2][16];
+
+void zLCDHandler(void *unused_param){
+       while(1){
+               lcdSetText(LCD_PORT,1,lcdBuffer[0]);
+               lcdSetText(LCD_PORT,2,lcdBuffer[1]);
+
+               if(_lcdUpdateFunc)
+                       _lcdUpdateFunc(unused_param);
+
+               delay(LCD_RATE);
+       }
+}
+
+void zLCDInit(void){
+       lcdInit(LCD_PORT);
+       lcdClear(LCD_PORT);
+       lcdSetBacklight(LCD_PORT,true);
+}
+
+void zLCDStart(void){
+       taskCreate(zLCDHandler,
+                          TASK_DEFAULT_STACK_SIZE,
+                          NULL,
+                          TASK_PRIORITY_DEFAULT
+                          );
+
+       memset(&lcdBuffer,0,32);
+       strcpy(lcdBuffer[0]," libZEPHYR v1.0 ");
+}
+
+void zLCDWrite(unsigned char line,const char *text,...){
+       va_list args;
+       char buf[16];
+       va_start(args,text);
+       sprintf(buf,text,args);
+       va_end(args);
+       strcpy(lcdBuffer[line-1],buf);
+}
+
+void zLCDSetUpdateFunc(void (*func)(void *)){
+       _lcdUpdateFunc = func;
+}
+
+void zLCDClearUpdateFunc(void){
+       _lcdUpdateFunc = 0;
+}
+
+#endif // LCD_PORT
+
+#ifdef GYRO_PORT
+
+static Gyro gyro;
+static bool gyroEnabled = false;
+
+void zGyroInit(void){
+       if((gyro=gyroInit(2,0))){
+               gyroEnabled = true;
+       }
+}
+
+#endif // GYRO_PORT
+
+/*
+ *     A map of what's plugged into the motor ports.
+ *     Expected declarations:
+ *
+ *     DRIVEL  -       Left drive port
+ *     DRIVER  -       Right drive port
+ *
+*/
+
+#define MOTOR_PORT_COUNT       10
+
+#ifdef IME_ENABLE
+#define MOTOR_IME_COUNT                5
+#endif // IME_ENABLE
+
+const char *MOTOR_PORT_MAP[MOTOR_PORT_COUNT] = {
+       "UNUSED1",
+       "UNUSED2",
+       "UNUSED3",
+       "UNUSED4",
+       "INTAKE",
+       "DRIVER",
+       "DRIVEL",
+       "LIFT1",
+       "LIFT2",
+       "ROTATER"
+};
+
+#ifdef IME_ENABLE
+
+const char *MOTOR_IME_MAP[MOTOR_IME_COUNT] = {
+       "DRIVER",
+       "DRIVEL",
+       "ROTATER",
+       "LIFT1",
+       "LIFT2"
+};
+
+static unsigned int imeCount = 0;
+
+void zIMEInit(void){
+       imeCount = imeInitializeAll();
+}
+
+#endif // IME_ENABLE
+
+void zMotorSet(const char *motor,char speed){
+       for(unsigned char i=0;i<MOTOR_PORT_COUNT;i++){
+               if(!strcmp(MOTOR_PORT_MAP[i],motor)){
+                       motorSet(i+1,speed);
+                       return;
+               }
+       }
+}
+
+char zMotorGet(const char *motor){
+       for(unsigned char i=0;i<MOTOR_PORT_COUNT;i++){
+               if(!strcmp(MOTOR_PORT_MAP[i],motor)){
+                       return motorGet(i+1);
+               }
+       }
+       return 0;
+}
+
+#ifdef IME_ENABLE
+
+int zMotorIMEGet(const char *motor){
+       int IMEValue = 0;
+       for(unsigned char i=0;i<imeCount;i++){
+               if(!strcmp(MOTOR_IME_MAP[i],motor)){
+                       imeGet(i,&IMEValue);
+                       break;
+               }
+       }
+       return IMEValue;
+}
+
+int zMotorIMEGetVelocity(const char *motor){
+       int IMEValue = 0;
+       for(unsigned char i=0;i<imeCount;i++){
+               if(!strcmp(MOTOR_IME_MAP[i],motor)){
+                       imeGetVelocity(i,&IMEValue);
+                       break;
+               }
+       }
+       return IMEValue;
+}
+
+#endif // IME_ENABLE
+
+void zDriveUpdate(void){
+
+#ifdef DRIVE_NORMAL
+       char s = joystickGetAnalog(DRIVE_JOY,DRIVE_NORMAL);
+
+       APPLY_THRESH(s,DRIVE_THRESHOLD);
+
+       motorSet(DRIVEL,s);
+       motorSet(DRIVER,s);
+
+#else
+
+       char l,r;
+
+       l = joystickGetAnalog(DRIVE_JOY,DRIVE_TANK_LEFT);
+       r = joystickGetAnalog(DRIVE_JOY,DRIVE_TANK_RIGHT);
+
+       APPLY_THRESH(l,DRIVE_THRESHOLD);
+       APPLY_THRESH(r,DRIVE_THRESHOLD);
+
+       zMotorSet("DRIVEL",l);
+       zMotorSet("DRIVER",r);
+
+#endif // DRIVE_NORMAL
+
+}
+
+char zGetDigitalMotorSpeed(unsigned char joy,unsigned char btn_group,unsigned char btn_pos,unsigned char btn_neg,char speed){
+       return joystickGetDigital(joy,btn_group,btn_pos) ?  speed :
+                  joystickGetDigital(joy,btn_group,btn_neg) ? -speed : 0;
+}