Mindstorms 3rd Party ROBOTC Drivers RobotC
[Home] [Download] [Submit a bug/suggestion] [ROBOTC Forums] [Blog] [Support this project]

HTRCX-driver.h

Go to the documentation of this file.
00001 /*!@addtogroup HiTechnic
00002  * @{
00003  * @defgroup HTRCX IR Link RCX comms
00004  * HiTechnic IR Link RCX Comms Driver
00005  * @{
00006  */
00007 
00008 /*
00009  * $Id: HTRCX-driver.h 46 2011-01-16 16:56:49Z xander $
00010  */
00011 
00012 #ifndef _HTRCX_H_
00013 #define _HTRCX_H_
00014 /** \file HTRCX-driver.h
00015  * \brief HiTechnic IR Link RCX Comms Driver
00016  *
00017  * HTRCX-driver.h provides an API for the HiTechnic IR Link Sensor to allow
00018  * communication between the NXT and RCX.
00019  *
00020  * Changelog:
00021  * - 1.0: Initial release
00022  * - 1.1: HTRCXreadResp now clears entire IR read buffer after read
00023  *
00024  * Credits:
00025  * - Big thanks to HiTechnic for providing me with the hardware necessary to write and test this.
00026  *
00027  * License: You may use this code as you wish, provided you give credit where its due.
00028  *
00029  * THIS CODE WILL ONLY WORK WITH ROBOTC VERSION 2.00 AND HIGHER.
00030  * \author Xander Soldaat (mightor_at_gmail.com)
00031  * \date 31 October 2010
00032  * \version 1.1
00033  * \example HTRCX-test1.c
00034  */
00035 
00036 #pragma systemFile
00037 
00038 #ifndef _COMMON_H_
00039 #include "common.h"
00040 #endif
00041 
00042 tByteArray HTRCXI2CRequest;
00043 tByteArray HTRCXI2CReply;
00044 tByteArray HTRCXIRMsg;
00045 
00046 byte HTRCXCmdToggle = 0;
00047 
00048 // Function prototypes
00049 bool HTRCXsendHeader(tSensors link);
00050 void HTRCXencode(tSensors link, tByteArray &iBuffer, tByteArray &oBuffer);
00051 bool HTRCXreadResp(tSensors link, tByteArray &response);
00052 bool HTRCXplaySound(tSensors link, unsigned byte sound);
00053 bool HTRCXsendByte(tSensors link, unsigned byte data);
00054 bool HTRCXsendWord(tSensors link, short data);
00055 bool HTRCXmotorOn(tSensors link, unsigned byte _motor);
00056 bool HTRCXmotorOff(tSensors link, unsigned byte _motor);
00057 bool HTRCXmotorFwd(tSensors link, unsigned byte _motor);
00058 bool HTRCXmotorRev(tSensors link, unsigned byte _motor);
00059 bool HTRCXmotorPwr(tSensors link, unsigned byte _motor, unsigned byte power);
00060 
00061 
00062 /**
00063  * Sends the RCX IR message header with all the trimmings.
00064  *
00065  * Note: this is an internal function and should be not be called directly.
00066  * @param link the sensor port number
00067  * @return true if no error occured, false if it did
00068  */
00069 bool HTRCXsendHeader(tSensors link) {
00070   memset(HTRCXI2CRequest, 0, sizeof(tByteArray));
00071 
00072   // Send the 0x55 0x55 0x00 IR message header
00073   HTRCXI2CRequest[0] = 8;
00074   HTRCXI2CRequest[1] = 0x02;
00075   HTRCXI2CRequest[2] = 0x4A;
00076   HTRCXI2CRequest[3] = 0x55;
00077   HTRCXI2CRequest[4] = 0xFF;
00078   HTRCXI2CRequest[5] = 0x00;
00079   HTRCXI2CRequest[6] = 0x03;
00080   HTRCXI2CRequest[7] = 0x00;
00081   HTRCXI2CRequest[8] = 0x01;
00082 
00083   return writeI2C(link, HTRCXI2CRequest, 0);
00084 }
00085 
00086 
00087 /**
00088  * This encodes the message into the standard RCX format with
00089  * opcodes, data and their complements, followed by a checksum.\n
00090  * The output is an I2C message that can be sent to the IR Link.\n
00091  * This does NOT send the IR message header.
00092  *
00093  * Note: this is an internal function and should be not be called directly.
00094  * @param link the sensor port number
00095  * @param iBuffer the IR message that is to be sent by the IR Link to the RCX
00096  * @param oBuffer the I2C message to be sent to the IR Link
00097  */
00098 void HTRCXencode(tSensors link, tByteArray &iBuffer, tByteArray &oBuffer) {
00099   int checksum = 0;
00100   int msgsize = iBuffer[0];
00101 
00102   // Max size of an RCX message is 5 bytes due to the encoding and additional
00103   // info needed for the IR Link.
00104   if (msgsize > 5) return;
00105 
00106   // Calculate the total size of the I2C packet.
00107   // I2C packet info + msgsize (with inverse) + checksum + IR Link info
00108   oBuffer[0] = 2 + (msgsize * 2) + 2 + 3;
00109   oBuffer[1] = 0x02;
00110   oBuffer[2] = 0x4D - ((msgsize * 2) + 2);
00111 
00112   // Build the outgoing IR message and inverse
00113   // Keep track of checksum
00114   for (int i = 0; i < msgsize; i++) {
00115     checksum += iBuffer[i + 1];
00116     oBuffer[3 + (i * 2)] =  iBuffer[i + 1];
00117     oBuffer[4 + (i * 2)] = ~iBuffer[i + 1];
00118     //oBuffer[4 + (i * 2)] = ~oBuffer[3 + (i * 2)];
00119   }
00120 
00121   // Add checksum to outoing packet
00122   oBuffer[3 + (msgsize * 2)] =   checksum & 0xFF;
00123   oBuffer[4 + (msgsize * 2)] = ~(checksum & 0xFF);
00124 
00125   // Generate IR Link info
00126   oBuffer[3 + (msgsize * 2) + 2] = (msgsize * 2) + 2;
00127   oBuffer[4 + (msgsize * 2) + 2] = 0x00;
00128   oBuffer[5 + (msgsize * 2) + 2] = 0x01;
00129 }
00130 
00131 
00132 /**
00133  * Read a message sent by the RCX.  You will need to poll frequently to
00134  * check if a message has been sent. The number of bytes received is
00135  * in the first element of the response array.  If it is non-zero, a message
00136  * was received.
00137  *
00138  * @param link the sensor port number
00139  * @param response the IR message that was received from the RCX
00140  * @return true if no error occured, false if it did
00141  */
00142 bool HTRCXreadResp(tSensors link, tByteArray &response) {
00143   memset(HTRCXI2CRequest, 0, sizeof(tByteArray));
00144   memset(HTRCXI2CReply, 0, sizeof(tByteArray));
00145   memset(response, 0, sizeof(tByteArray));
00146 
00147   HTRCXI2CRequest[0] = 2;
00148   HTRCXI2CRequest[1] = 0x02;
00149   HTRCXI2CRequest[2] = 0x50;
00150 
00151   if (!writeI2C(link, HTRCXI2CRequest, 16))
00152     return false;
00153 
00154   if (!readI2C(link, HTRCXI2CReply, 16))
00155     return false;
00156 
00157   // Print the contents
00158   // printBuffer(HTRCXI2CReply);
00159 
00160   if ((HTRCXI2CReply[0] > 0) && (HTRCXI2CReply[0] < 16)) {
00161     memcpy(response, HTRCXI2CReply, HTRCXI2CReply[0]);
00162   }
00163 
00164   memset(HTRCXI2CRequest, 0, sizeof(tByteArray));
00165   // Clear the buffer count
00166   HTRCXI2CRequest[0] = 16;
00167   HTRCXI2CRequest[1] = 0x02;
00168   HTRCXI2CRequest[2] = 0x50;
00169   return writeI2C(link, HTRCXI2CRequest, 0);
00170 }
00171 
00172 
00173 /**
00174  * Tell the RCX to play a sound.  Sounds are numbered 0-5
00175  *
00176  * @param link the sensor port number
00177  * @param sound the sound to play, numbered 0-6
00178  * @return true if no error occured, false if it did
00179  */
00180 bool HTRCXplaySound(tSensors link, unsigned byte sound) {
00181   // Toggle the toggle bit for dupe command detection
00182   HTRCXCmdToggle ^= 0x08;
00183   HTRCXIRMsg[0] = 2;
00184   HTRCXIRMsg[1] = 0x51 + HTRCXCmdToggle;
00185   HTRCXIRMsg[2] = sound;
00186 
00187   HTRCXsendHeader(link);
00188   wait1Msec(12);
00189   HTRCXencode(link, HTRCXIRMsg, HTRCXI2CRequest);
00190   writeI2C(link, HTRCXI2CRequest, 0);
00191   wait1Msec(12);
00192 
00193   return true;
00194 }
00195 
00196 
00197 /**
00198  * Send a single byte message to the RCX
00199  *
00200  * @param link the sensor port number
00201  * @param data the data to be sent to the RCX
00202  * @return true if no error occured, false if it did
00203  */
00204 bool HTRCXsendByte(tSensors link, unsigned byte data) {
00205   HTRCXIRMsg[0] = 2;
00206   HTRCXIRMsg[1] = 0xF7;   // No need to toggle this, apparently.
00207   HTRCXIRMsg[2] = data;
00208 
00209   HTRCXsendHeader(link);
00210   wait1Msec(12);
00211   HTRCXencode(link, HTRCXIRMsg, HTRCXI2CRequest);
00212   writeI2C(link, HTRCXI2CRequest, 0);
00213   wait1Msec(12);
00214 
00215   return true;
00216 }
00217 
00218 /**
00219  * Send 2 bytes message to the RCX as a short.
00220  *
00221  * NOTE: This only works with the ROBOTC firmware on the RCX
00222  * @param link the sensor port number
00223  * @param data the data to be sent to the RCX
00224  * @return true if no error occured, false if it did
00225  */
00226 bool HTRCXsendWord(tSensors link, short data) {
00227   HTRCXIRMsg[0] = 3;
00228   HTRCXIRMsg[1] = 0xA2;
00229   HTRCXIRMsg[2] = data & 0xFF;
00230   HTRCXIRMsg[3] = (data >> 8) & 0xFF;
00231 
00232   HTRCXsendHeader(link);
00233   wait1Msec(12);
00234   HTRCXencode(link, HTRCXIRMsg, HTRCXI2CRequest);
00235   writeI2C(link, HTRCXI2CRequest, 0);
00236   wait1Msec(12);
00237 
00238   return true;
00239 }
00240 
00241 
00242 /**
00243  * Turn the specified motor on
00244  *
00245  * NOTE: This does not currently work with the ROBOTC firmware on the RCX
00246  * @param link the sensor port number
00247  * @param _motor the motor channel to turn on
00248  * @return true if no error occured, false if it did
00249  */
00250 bool HTRCXmotorOn(tSensors link, unsigned byte _motor) {
00251   // Toggle the toggle bit for dupe command detection
00252   HTRCXCmdToggle ^= 0x08;
00253   HTRCXIRMsg[0] = 2;
00254   HTRCXIRMsg[1] = 0x21 + HTRCXCmdToggle;
00255   HTRCXIRMsg[2] = _motor + 0x80 + 0x40;
00256 
00257   HTRCXsendHeader(link);
00258   wait1Msec(12);
00259   HTRCXencode(link, HTRCXIRMsg, HTRCXI2CRequest);
00260   writeI2C(link, HTRCXI2CRequest, 0);
00261   wait1Msec(12);
00262 
00263   return true;
00264 }
00265 
00266 
00267 /**
00268  * Turn the specified motor off
00269  *
00270  * NOTE: This does not currently work with the ROBOTC firmware on the RCX
00271  * @param link the sensor port number
00272  * @param _motor the motor channel to turn off
00273  * @return true if no error occured, false if it did
00274  */
00275 bool HTRCXmotorOff(tSensors link, unsigned byte _motor) {
00276   // Toggle the toggle bit for dupe command detection
00277   HTRCXCmdToggle ^= 0x08;
00278   HTRCXIRMsg[0] = 2;
00279   HTRCXIRMsg[1] = 0x21 + HTRCXCmdToggle;
00280   HTRCXIRMsg[2] = _motor;
00281 
00282   HTRCXsendHeader(link);
00283   wait1Msec(12);
00284   HTRCXencode(link, HTRCXIRMsg, HTRCXI2CRequest);
00285   writeI2C(link, HTRCXI2CRequest, 0);
00286   wait1Msec(12);
00287 
00288   return true;
00289 }
00290 
00291 
00292 /**
00293  * Move the specified motor forward
00294  *
00295  * NOTE: This does not currently work with the ROBOTC firmware on the RCX
00296  * @param link the sensor port number
00297  * @param _motor the motor channel to move forward
00298  * @return true if no error occured, false if it did
00299  */
00300 bool HTRCXmotorFwd(tSensors link, unsigned byte _motor) {
00301   // Toggle the toggle bit for dupe command detection
00302   HTRCXCmdToggle ^= 0x08;
00303   HTRCXIRMsg[0] = 2;
00304   HTRCXIRMsg[1] = 0xE1 + HTRCXCmdToggle;
00305   HTRCXIRMsg[2] = _motor + 0x80;
00306 
00307   HTRCXsendHeader(link);
00308   wait1Msec(12);
00309   HTRCXencode(link, HTRCXIRMsg, HTRCXI2CRequest);
00310   writeI2C(link, HTRCXI2CRequest, 0);
00311   wait1Msec(12);
00312 
00313   return true;
00314 }
00315 
00316 
00317 /**
00318  * Move the specified motor reverse
00319  *
00320  * NOTE: This does not currently work with the ROBOTC firmware on the RCX
00321  * @param link the sensor port number
00322  * @param _motor the motor channel to move reverse
00323  * @return true if no error occured, false if it did
00324  */
00325 bool HTRCXmotorRev(tSensors link, unsigned byte _motor) {
00326   // Toggle the toggle bit for dupe command detection
00327   HTRCXCmdToggle ^= 0x08;
00328   HTRCXIRMsg[0] = 2;
00329   HTRCXIRMsg[1] = 0xE1 + HTRCXCmdToggle;
00330   HTRCXIRMsg[2] = _motor;
00331 
00332   HTRCXsendHeader(link);
00333   wait1Msec(12);
00334   HTRCXencode(link, HTRCXIRMsg, HTRCXI2CRequest);
00335   writeI2C(link, HTRCXI2CRequest, 0);
00336   wait1Msec(12);
00337 
00338   return true;
00339 }
00340 
00341 
00342 /**
00343  * Set the motor power.
00344  *
00345  * NOTE: This does not currently work with the ROBOTC firmware on the RCX
00346  * @param link the sensor port number
00347  * @param _motor the motor channel to change the power level of
00348  * @param power the amount of power to be applied to the motor
00349  * @return true if no error occured, false if it did
00350  */
00351 bool HTRCXmotorPwr(tSensors link, unsigned byte _motor, unsigned byte power) {
00352   // Toggle the toggle bit for dupe command detection
00353   HTRCXCmdToggle ^= 0x08;
00354   HTRCXIRMsg[0] = 3;
00355   HTRCXIRMsg[1] = 0x13 + HTRCXCmdToggle;
00356   HTRCXIRMsg[2] = _motor;
00357   HTRCXIRMsg[3] = 2;
00358   HTRCXIRMsg[4] = power;
00359 
00360   HTRCXsendHeader(link);
00361   wait1Msec(12);
00362   HTRCXencode(link, HTRCXIRMsg, HTRCXI2CRequest);
00363   writeI2C(link, HTRCXI2CRequest, 0);
00364   wait1Msec(12);
00365 
00366   return true;
00367 }
00368 
00369 #endif // _HTRCX_H_
00370 
00371 /*
00372  * $Id: HTRCX-driver.h 46 2011-01-16 16:56:49Z xander $
00373  */
00374 /* @} */
00375 /* @} */