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

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