00001 /*!@file AppDevices/test-BeoChip.C test suite for Brian Hudson's BeoChip */ 00002 00003 // //////////////////////////////////////////////////////////////////// // 00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2001 by the // 00005 // University of Southern California (USC) and the iLab at USC. // 00006 // See http://iLab.usc.edu for information about this project. // 00007 // //////////////////////////////////////////////////////////////////// // 00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected // 00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency // 00010 // in Visual Environments, and Applications'' by Christof Koch and // 00011 // Laurent Itti, California Institute of Technology, 2001 (patent // 00012 // pending; application number 09/912,225 filed July 23, 2001; see // 00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status). // 00014 // //////////////////////////////////////////////////////////////////// // 00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit. // 00016 // // 00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can // 00018 // redistribute it and/or modify it under the terms of the GNU General // 00019 // Public License as published by the Free Software Foundation; either // 00020 // version 2 of the License, or (at your option) any later version. // 00021 // // 00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope // 00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the // 00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR // 00025 // PURPOSE. See the GNU General Public License for more details. // 00026 // // 00027 // You should have received a copy of the GNU General Public License // 00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write // 00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, // 00030 // Boston, MA 02111-1307 USA. // 00031 // //////////////////////////////////////////////////////////////////// // 00032 // 00033 // Primary maintainer for this file: Laurent Itti <itti@usc.edu> 00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/AppDevices/test-BeoChip.C $ 00035 // $Id: test-BeoChip.C 13708 2010-07-28 16:55:36Z itti $ 00036 // 00037 00038 #include "Component/ModelManager.H" 00039 #include "Devices/BeoChip.H" 00040 #include "Devices/DeviceOpts.H" 00041 #include "Util/MathFunctions.H" 00042 00043 #include <cstdlib> 00044 #include <iostream> 00045 00046 //! Our own little BeoChipListener 00047 class MyBeoChipListener : public BeoChipListener 00048 { 00049 public: 00050 MyBeoChipListener() 00051 { rawpwm[0] = 0; rawpwm[1] = 0; rawadc[0] = 0; rawadc[1] = 0; kbd = 0x1f; } 00052 00053 virtual ~MyBeoChipListener() 00054 { } 00055 00056 virtual void event(const BeoChipEventType t, const int valint, 00057 const float valfloat) 00058 { 00059 LDEBUG("Event: %d val = %d, fval = %f", int(t), valint, valfloat); 00060 switch(t) 00061 { 00062 case NONE: break; 00063 case PWM0: rawpwm[0] = valint; break; 00064 case PWM1: rawpwm[1] = valint; break; 00065 case KBD: kbd = valint; break; 00066 case ADC0: rawadc[0] = valint; break; 00067 case ADC1: rawadc[1] = valint; break; 00068 case RESET: LERROR("BeoChip RESET occurred!"); break; 00069 case ECHOREP: LINFO("BeoChip Echo reply received."); break; 00070 case INOVERFLOW: LERROR("BeoChip input overflow!"); break; 00071 case SERIALERROR: LERROR("BeoChip serial error!"); break; 00072 case OUTOVERFLOW: LERROR("BeoChip output overflow!"); break; 00073 default: LERROR("Unknown event %d received!", int(t)); break; 00074 } 00075 } 00076 00077 // note: ideally you would want to protect those by a mutex: 00078 volatile int rawpwm[2]; 00079 volatile int rawadc[2]; 00080 volatile int kbd; 00081 }; 00082 00083 //! This program provides basic interfacing to the BeoChip 00084 /*! See the BeoChip class for details. Press both extreme keys 00085 together on the BeoChip keyboard to quit. */ 00086 int main(const int argc, const char* argv[]) 00087 { 00088 MYLOGVERB = LOG_INFO; 00089 00090 // instantiate a model manager: 00091 ModelManager manager("BeoChip test program"); 00092 00093 // Instantiate our various ModelComponents: 00094 nub::soft_ref<BeoChip> b(new BeoChip(manager)); 00095 manager.addSubComponent(b); 00096 00097 // Parse command-line: 00098 if (manager.parseCommandLine(argc, argv, "<serdev> [all|anim|font|" 00099 "flood|rnd|esc|noflow|setServo] servo# servoPos", 1, 4) == false) 00100 return(1); 00101 00102 // let's configure our serial device: 00103 b->setModelParamVal("BeoChipDeviceName", manager.getExtraArg(0)); 00104 std::string task = ""; bool doall = false; 00105 if (manager.numExtraArgs() > 1) 00106 { 00107 task = manager.getExtraArg(1); 00108 doall = (task.compare("all") == 0); 00109 } 00110 00111 // do we want to disable flow control? 00112 if (task.compare("noflow") == 0) 00113 { 00114 b->setModelParamVal("BeoChipUseRTSCTS", false); 00115 LINFO("Disabled RTS/CTS flow control"); 00116 } 00117 00118 // let's register our listener: 00119 00120 rutz::shared_ptr<MyBeoChipListener> lis(new MyBeoChipListener); 00121 rutz::shared_ptr<BeoChipListener> lis2; lis2.dynCastFrom(lis); // cast down 00122 b->setListener(lis2); 00123 00124 // let's get all our ModelComponent instances started: 00125 manager.start(); 00126 00127 LINFO("Waiting for a bit. Turn BeoChip on if not already on."); sleep(2); 00128 LINFO("Echo request (should bring an echo reply back)..."); 00129 b->echoRequest(); sleep(1); 00130 00131 // set servo 00132 if (task.compare("setServo") == 0) 00133 { 00134 if (manager.numExtraArgs() > 3) 00135 { 00136 int servo = manager.getExtraArgAs<int>(2); 00137 int val = manager.getExtraArgAs<int>(3); 00138 LINFO("Setting servo %i to %i", servo, val); 00139 b->setServoRaw(servo, val); 00140 } else { 00141 LINFO("Need servo and position cmd"); 00142 } 00143 manager.stop(); 00144 exit(0); 00145 } 00146 00147 // random junk test: 00148 if (task.compare("rnd") == 0 || doall) 00149 { 00150 LINFO("Starting random junk flood..."); 00151 b->lcdClear(); 00152 b->lcdPrintf(0, 1, "Random junk flood"); sleep(1); 00153 for (int i = 0; i < 5000; i ++) 00154 { 00155 int val = randomUpToIncluding(255); 00156 if (val != 0xF9) b->writeByte(val); 00157 } 00158 b->lcdClear(); 00159 b->lcdPrintf(0, 1, "Random junk over"); sleep(1); 00160 sleep(30); 00161 b->lcdPrintf(0, 1, "Reset..."); sleep(1); 00162 LINFO("Reset BeoChip..."); 00163 b->resetChip(); sleep(1); 00164 } 00165 00166 // font test: 00167 if (task.compare("anim") == 0 || doall) 00168 { 00169 b->lcdClear(); 00170 // NOTE: can't send a zero char since it's our end of string marker... 00171 b->lcdPrintf(0, 0, "%c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c", 8, 1, 2, 3, 4, 00172 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); 00173 b->lcdPrintf(0, 3, "%c%c%c%c%c%c%c%c %c%c%c%c%c%c%c%c", 8, 1, 2, 3, 4, 00174 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); 00175 for (int i = 0; i < 8; i ++) 00176 { 00177 LINFO("Loading font %d...", i); 00178 b->lcdPrintf(0, 1, "Loading LCD font %d ", i); 00179 b->lcdLoadFont(i); 00180 sleep(3); 00181 } 00182 } 00183 00184 // animation test: 00185 if (task.compare("anim") == 0 || doall) 00186 { 00187 b->lcdClear(); b->lcdLoadFont(1); 00188 for (int i = 1; i < 8; i ++) 00189 { 00190 LINFO("Starting animation %d...", i); 00191 b->lcdClear(); 00192 b->lcdPrintf(0, 1, "LCD Animation %d ", i); 00193 b->lcdSetAnimation(i); 00194 sleep(10); 00195 } 00196 } 00197 00198 // serial flood test: we send 1000 commands that take more time to 00199 // execute than the interval at which they come in. The RTS/CTS flow 00200 // control will then be triggered: 00201 if (task.compare("flood") == 0 || doall) 00202 { 00203 LINFO("Trying an LCD clear flood..."); 00204 b->lcdPrintf(0, 0, "LCD clear flood"); sleep(1); 00205 for (int i = 0; i < 1000; i ++) b->lcdClear(); 00206 b->lcdPrintf(0, 0, "Clear flood is over."); sleep(5); 00207 00208 LINFO("Trying an LCD font flood..."); 00209 b->lcdPrintf(0, 0, "LCD font flood"); sleep(1); 00210 for (int i = 0; i < 1000; i ++) b->lcdLoadFont(i & 7); 00211 b->lcdPrintf(0, 0, "Font flood is over. "); sleep(15); 00212 00213 LINFO("Trying an LCD font/clear flood..."); 00214 b->lcdPrintf(0, 0, "LCD font/clear flood"); sleep(1); 00215 for (int i = 0; i < 1000; i ++) { b->lcdLoadFont(i & 7); b->lcdClear(); } 00216 b->lcdPrintf(0, 0, "Font/clr flood over "); sleep(15); 00217 } 00218 00219 // ESC calibration: 00220 if (task.compare("esc") == 0 || doall) 00221 { 00222 LINFO("Setting all servos to neutral (127)"); 00223 for (int i = 0; i < 8; i ++) b->setServoRaw(i, 127); 00224 LINFO("Press [RETURN] when ready for full-swing..."); 00225 getchar(); 00226 for (int j = 0; j < 10; j ++) 00227 { 00228 LINFO("Setting all servos to full forward (255)"); 00229 for (int i = 0; i < 8; i ++) b->setServoRaw(i, 255); 00230 usleep(750000); 00231 LINFO("Setting all servos to full reverse (0)"); 00232 for (int i = 0; i < 8; i ++) b->setServoRaw(i, 0); 00233 usleep(750000); 00234 } 00235 LINFO("Setting all servos to neutral (127)"); 00236 for (int i = 0; i < 8; i ++) b->setServoRaw(i, 127); 00237 LINFO("Press [RETURN] when done..."); 00238 getchar(); 00239 } 00240 00241 LINFO("Ok, have a look at the LCD screen now..."); 00242 00243 // load a cool custom font: 00244 b->lcdLoadFont(1); 00245 00246 // let's turn everything on: 00247 b->capturePulse(0, true); 00248 b->capturePulse(1, true); 00249 b->captureAnalog(0, true); 00250 b->captureAnalog(1, true); 00251 b->debounceKeyboard(true); 00252 b->captureKeyboard(true); 00253 00254 // let's play with the LCD: 00255 LINFO("Starting to play with the servos..."); 00256 b->lcdClear(); // 01234567890123456789 00257 b->lcdPrintf(0, 0, "test-BeoChip -- 1.00"); 00258 b->lcdPrintf(0, 1, "ADC=000/000 DOU=0000"); 00259 b->lcdPrintf(0, 2, "PWM=0000/0000 X "); 00260 b->lcdPrintf(0, 3, "Servos=000 KB=00000"); 00261 00262 // set servo 5 to 127, servo 6 to 0, and servo 7 to 255: 00263 b->setServoRaw(5, 127); 00264 b->setServoRaw(6, 0); 00265 b->setServoRaw(7, 255); 00266 00267 // let's play with the servos and monitor a bunch of things: 00268 int ani = 0; int dout = 0; bool keepgoing = true; 00269 while(keepgoing) 00270 { 00271 for (int p = 0; p < 256; p ++) 00272 { 00273 // print ADC values: 00274 b->lcdPrintf(4, 1, "%03d/%03d", lis->rawadc[0], lis->rawadc[1]); 00275 00276 // set and print dout values: 00277 char digout[5]; digout[4] = '\0'; 00278 for (int i = 0; i < 4; i ++) 00279 { 00280 digout[i] = (dout>>(3-i))&1 ? '1':'0'; 00281 b->setDigitalOut(3-i, (dout>>(3-i))&1?true:false); 00282 } 00283 b->lcdPrintf(16, 1, "%s", digout); dout ++; dout &= 15; 00284 00285 // print PWM values: 00286 b->lcdPrintf(4, 2, "%04d/%04d", lis->rawpwm[0], lis->rawpwm[1]); 00287 00288 // print keyboard values: 00289 char kb[6]; kb[5] = '\0'; 00290 for (int i = 0; i < 5; i ++) kb[i] = (lis->kbd>>(4-i))&1 ? '1':'0'; 00291 b->lcdPrintf(15, 3, "%s", kb); 00292 00293 // quit if both extreme keys pressed simultaneously: 00294 if (kb[0] == '0' && kb[4] == '0') { keepgoing = false; break; } 00295 00296 // print a little animated character, slow: 00297 if ((dout & 7) == 0) 00298 { b->lcdPrintf(17, 2, "%c", ani+8); ani ++; ani &= 7; } 00299 00300 // set the servos: 00301 for (int s = 0; s < 5; s ++) 00302 if (s & 1) b->setServoRaw(s, p); 00303 else b->setServoRaw(s, 256 - p); 00304 00305 // print current servo values: 00306 b->lcdPrintf(7, 3, "%03d", p); 00307 00308 // make sure we leave some CPU to our listener: 00309 usleep(50000); 00310 } 00311 } 00312 00313 manager.stop(); 00314 return 0; 00315 } 00316 00317 // ###################################################################### 00318 /* So things look consistent in everyone's emacs... */ 00319 /* Local Variables: */ 00320 /* indent-tabs-mode: nil */ 00321 /* End: */