Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

LedEngine.cc

Go to the documentation of this file.
00001 #include "LedEngine.h"
00002 #include "MotionManager.h"
00003 #include "Shared/WorldState.h"
00004 #include "Shared/ERS210Info.h"
00005 #include "Shared/ERS220Info.h"
00006 #include "Shared/ERS7Info.h"
00007 
00008 /*! This is "Mimic the number" style */
00009 const LEDBitMask_t LedEngine::ERS210numMasks[11] = {
00010   ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::TopBrLEDMask, //0
00011   
00012   ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopLLEDMask,  //1
00013   
00014   ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask, //2
00015   
00016   ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::TopLLEDMask
00017   |ERS210Info::TopBrLEDMask, //3
00018   
00019   ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopLLEDMask,  //4
00020 
00021   ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopBrLEDMask, //5
00022 
00023   ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::MidLLEDMask
00024   |ERS210Info::TopRLEDMask|ERS210Info::TopBrLEDMask, //6
00025 
00026   ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask,  //7
00027 
00028   ERS210Info::BotRLEDMask|ERS210Info::BotLLEDMask|ERS210Info::MidRLEDMask|ERS210Info::MidLLEDMask
00029   |ERS210Info::TopRLEDMask|ERS210Info::TopLLEDMask|ERS210Info::TopBrLEDMask, //8
00030 
00031   ERS210Info::BotLLEDMask|ERS210Info::MidLLEDMask|ERS210Info::TopRLEDMask|ERS210Info::TopLLEDMask
00032   |ERS210Info::TopBrLEDMask,  //9
00033 
00034   ERS210Info::BotLLEDMask //.
00035 };
00036 /*! This is "Count the dots" style */
00037 const LEDBitMask_t LedEngine::ERS220numMasks[11] = {
00038   ERS220Info::ModeLEDMask, //0
00039 
00040   ERS220Info::FaceBackLeftLEDMask, //1
00041 
00042   ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask, //2
00043 
00044   ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask, //3
00045 
00046   ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
00047   |ERS220Info::FaceFrontRightLEDMask, //4
00048 
00049   ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
00050   |ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask, //5
00051 
00052   ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
00053   |ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask, //6
00054 
00055   ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
00056   |ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask
00057   |ERS220Info::FaceFrontALEDMask, //7
00058 
00059   ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
00060   |ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask
00061   |ERS220Info::FaceFrontALEDMask|ERS220Info::FaceFrontBLEDMask, //8
00062 
00063   ERS220Info::FaceBackLeftLEDMask|ERS220Info::FaceCenterLeftLEDMask|ERS220Info::FaceFrontLeftLEDMask
00064   |ERS220Info::FaceFrontRightLEDMask|ERS220Info::FaceCenterRightLEDMask|ERS220Info::FaceBackRightLEDMask
00065   |ERS220Info::FaceFrontALEDMask|ERS220Info::FaceFrontBLEDMask|ERS220Info::FaceFrontCLEDMask, //9
00066 
00067   ERS220Info::FaceFrontLeftLEDMask //.
00068 };
00069 /*
00070 / *! This is "Mimic the number" style * /
00071 const LEDBitMask_t LedEngine::ERS7numMasks[11] = {
00072   (ERS7Info::FaceLEDPanelMask<< 5)|(ERS7Info::FaceLEDPanelMask<< 3), //0
00073   (ERS7Info::FaceLEDPanelMask<< 7)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 1), //1
00074   (ERS7Info::FaceLEDPanelMask<<10)|(ERS7Info::FaceLEDPanelMask<< 9)|(ERS7Info::FaceLEDPanelMask<< 5)|(ERS7Info::FaceLEDPanelMask<<3), //2
00075   (ERS7Info::FaceLEDPanelMask<< 7)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 1)|(ERS7Info::FaceLEDPanelMask<<5), //3
00076   (ERS7Info::FaceLEDPanelMask<<10)|(ERS7Info::FaceLEDPanelMask<<11)|(ERS7Info::FaceLEDPanelMask<< 5)|(ERS7Info::FaceLEDPanelMask<<7)|(ERS7Info::FaceLEDPanelMask<<3)|(ERS7Info::FaceLEDPanelMask<<1), //4
00077   (ERS7Info::FaceLEDPanelMask<< 7)|(ERS7Info::FaceLEDPanelMask<< 9)|(ERS7Info::FaceLEDPanelMask<<11)|(ERS7Info::FaceLEDPanelMask<<5), //5
00078   (ERS7Info::FaceLEDPanelMask<< 9)|(ERS7Info::FaceLEDPanelMask<< 5)|(ERS7Info::FaceLEDPanelMask<< 3), //6
00079   (ERS7Info::FaceLEDPanelMask<< 9)|(ERS7Info::FaceLEDPanelMask<< 7)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<<1), //7
00080   (ERS7Info::FaceLEDPanelMask<<10)|(ERS7Info::FaceLEDPanelMask<<11)|(ERS7Info::FaceLEDPanelMask<< 9)|(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<<7)|(ERS7Info::FaceLEDPanelMask<<3), //8
00081   (ERS7Info::FaceLEDPanelMask<< 9)|(ERS7Info::FaceLEDPanelMask<< 5)|(ERS7Info::FaceLEDPanelMask<< 7)|(ERS7Info::FaceLEDPanelMask<<3)|(ERS7Info::FaceLEDPanelMask<<1), //9
00082   (ERS7Info::FaceLEDPanelMask<< 1) //.
00083 };
00084 */
00085 /*! This is "Count the dots" style */
00086 const LEDBitMask_t LedEngine::ERS7numMasks[11] = {
00087   0, //0
00088   (ERS7Info::FaceLEDPanelMask<<11), //1
00089 
00090   (ERS7Info::FaceLEDPanelMask<< 4)|(ERS7Info::FaceLEDPanelMask<< 5), //2
00091 
00092   (ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<<11)|(ERS7Info::FaceLEDPanelMask<< 3), //3
00093 
00094   (ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 8)
00095   |(ERS7Info::FaceLEDPanelMask<<9), //4
00096 
00097   (ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 8)
00098   |(ERS7Info::FaceLEDPanelMask<<9)|(ERS7Info::FaceLEDPanelMask<<11), //5
00099 
00100   (ERS7Info::FaceLEDPanelMask<< 0)|(ERS7Info::FaceLEDPanelMask<< 1)|(ERS7Info::FaceLEDPanelMask<< 4)
00101   |(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7), //6
00102 
00103   (ERS7Info::FaceLEDPanelMask<< 0)|(ERS7Info::FaceLEDPanelMask<< 1)|(ERS7Info::FaceLEDPanelMask<< 4)
00104   |(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)
00105   |(ERS7Info::FaceLEDPanelMask<<11), //7
00106 
00107   (ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 4)
00108   |(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)
00109   |(ERS7Info::FaceLEDPanelMask<< 8)|(ERS7Info::FaceLEDPanelMask<<9), //8
00110 
00111   (ERS7Info::FaceLEDPanelMask<< 2)|(ERS7Info::FaceLEDPanelMask<< 3)|(ERS7Info::FaceLEDPanelMask<< 4)
00112   |(ERS7Info::FaceLEDPanelMask<<5)|(ERS7Info::FaceLEDPanelMask<< 6)|(ERS7Info::FaceLEDPanelMask<< 7)
00113   |(ERS7Info::FaceLEDPanelMask<< 8)|(ERS7Info::FaceLEDPanelMask<<9)|(ERS7Info::FaceLEDPanelMask<<11), //9
00114 
00115   (ERS7Info::FaceLEDPanelMask<< 1) //.
00116 };
00117 
00118 
00119 LedEngine::LedEngine() : dirty(true), numCycling(0), nextFlashEnd((unsigned int)-1) {
00120   for(unsigned int i=0; i<NumLEDs; i++) {
00121     infos[i].flashtime=0;
00122     infos[i].starttime=0;
00123   }
00124   clear();
00125 }
00126 
00127 void LedEngine::recalcFlashEnd(void) {
00128   unsigned int t = get_time();
00129   nextFlashEnd=(unsigned int)-1;
00130   for(unsigned int i=0; i<NumLEDs; i++)
00131     if(infos[i].flashtime>t && nextFlashEnd>infos[i].flashtime)
00132       nextFlashEnd=infos[i].flashtime;
00133 }
00134 
00135 int LedEngine::isDirty() {
00136   unsigned int t = get_time();
00137   if(t>nextFlashEnd) {
00138     dirty=true;
00139     recalcFlashEnd();
00140   };
00141   return dirty;
00142 }
00143 
00144 int LedEngine::updateLEDs(const MotionCommand* caller, LEDBitMask_t mask/*=AllLEDMask*/) {
00145   unsigned int t = get_time();
00146   if (t>nextFlashEnd) recalcFlashEnd();
00147   for(unsigned int i=0; i<NumLEDs; i++)
00148     if((mask>>i)&1)
00149       for(unsigned int f=0; f<NumFrames; f++)
00150         motman->setOutput(caller, i+LEDOffset,calcValue(i,t+f*FrameTime),f);
00151   bool tmp=dirty;
00152   dirty = numCycling>0;
00153   return tmp;
00154 }
00155 
00156 int LedEngine::updateLEDs(OutputCmd cmds[NumLEDs]) {
00157   unsigned int t = get_time();
00158   if (t>nextFlashEnd) recalcFlashEnd();
00159   for(unsigned int i=0; i<NumLEDs; i++)
00160       cmds[i].value=calcValue(i,t);
00161   bool tmp=dirty;
00162   dirty = numCycling>0;
00163   return tmp;
00164 }
00165 
00166 int LedEngine::updateLEDFrames(OutputCmd cmds[NumLEDs][NumFrames]) {
00167   unsigned int t = get_time();
00168   if (t>nextFlashEnd) recalcFlashEnd();
00169   for(unsigned int i=0; i<NumLEDs; i++)
00170     for(unsigned int f=0; f<NumFrames; f++)
00171       cmds[i][f].value=calcValue(i,t+f*FrameTime);
00172   bool tmp=dirty;
00173   dirty = numCycling>0;
00174   return tmp;
00175 }
00176 
00177 void LedEngine::invert(LEDBitMask_t leds) {
00178   if(leds!=0) {
00179     dirty=true;
00180     for(unsigned int i=0; i<NumLEDs; i++)
00181       if((leds>>i)&1)
00182         if(infos[i].isCycling)
00183           infos[i].amp*=-1;
00184         else
00185           infos[i].value=1-infos[i].value;
00186   }
00187 }
00188 void LedEngine::set(LEDBitMask_t leds, float value) {
00189   if(leds!=0) {
00190     dirty=true;
00191     for(unsigned int i=0; i<NumLEDs; i++)
00192       if((leds>>i)&1) {
00193         infos[i].value=value;
00194         if(infos[i].isCycling) {
00195           numCycling--;
00196           infos[i].isCycling=false;
00197         }
00198       }
00199   }
00200 }
00201 void LedEngine::cflash(LEDBitMask_t leds, float value, unsigned int ms) {
00202   dirty=true;
00203   unsigned int t = get_time();
00204   if(t+ms<nextFlashEnd)
00205     nextFlashEnd=t+ms;
00206   for(unsigned int i=0; i<NumLEDs; i++) {
00207     infos[i].flashvalue=((leds>>i)&1)*value;
00208     infos[i].flashtime=t+ms;
00209   }
00210 }
00211 void LedEngine::flash(LEDBitMask_t leds, float value, unsigned int ms) {
00212   if(leds!=0) {
00213     dirty=true;
00214     unsigned int t = get_time();
00215     if(t+ms<nextFlashEnd)
00216       nextFlashEnd=t+ms;
00217     for(unsigned int i=0; i<NumLEDs; i++)
00218       if((leds>>i)&1) {
00219         infos[i].flashvalue=value;
00220         infos[i].flashtime=t+ms;
00221       }
00222   }
00223 }
00224 void LedEngine::flash(LEDBitMask_t leds, unsigned int ms) {
00225   if(leds!=0) {
00226     dirty=true;
00227     unsigned int t = get_time();
00228     if(t+ms<nextFlashEnd)
00229       nextFlashEnd=t+ms;
00230     for(unsigned int i=0; i<NumLEDs; i++)
00231       if((leds>>i)&1) {
00232         infos[i].flashvalue=calcFlash(calcValue(i,t));
00233         infos[i].flashtime=t+ms;
00234       }
00235   }
00236 }
00237 /*!@param leds the bitmask of leds to apply this to
00238  * @param period the period of the cycle (milliseconds), includes an on and off
00239  * @param amp the amplitude of the cycle - note that this is clipped at 0 and 1.
00240  * @param offset the vertical offset of the cycle - simply shifts the baseline of the cycle up or down
00241  * @param phase the phase within the cycle to start at (specify in milliseconds)
00242  *
00243  * When this function is called, the starting time is stored as current time + phase.
00244  *
00245  * The equation used is \f[\cos(\frac{2\pi(t-starttime)}{period})*(\frac{-amp}{2})+.5+offset\f]
00246  * 
00247  * The idea is that with a amplitude=1 and offset=0, it will start at
00248  * 0, ramp up to 1, and then ramp down again.  The arguments to this
00249  * function will let you control all parameters of the cycle.
00250  *
00251  * You can get a blink-on/off instead of cycle on/off by using a very large amplitude.
00252  */
00253 void LedEngine::cycle(LEDBitMask_t leds, unsigned int period, float amp, float offset, int phase) {
00254   //  cout << "cycle("<<leds<<","<<period<<","<<amp<<","<<offset<<","<<phase<<")"<<endl;
00255   if(leds!=0) {
00256     dirty=true;
00257     unsigned int start = get_time()+phase;
00258     for(unsigned int i=0; i<NumLEDs; i++)
00259       if((leds>>i)&1) {
00260         if(!infos[i].isCycling)
00261           numCycling++;
00262         infos[i].isCycling=true;
00263         infos[i].amp=amp;
00264         infos[i].period=period;
00265         infos[i].starttime=start;
00266         infos[i].offset=offset;
00267       }
00268   }
00269 }
00270 void LedEngine::clear() {
00271   for(unsigned int i=0; i<NumLEDs; i++) {
00272     infos[i].value=0;
00273     infos[i].flashtime=0;
00274     infos[i].isCycling=false;
00275   }
00276   numCycling=0;
00277   dirty=true;
00278 }
00279 
00280 void LedEngine::extendFlash(unsigned int ms) {
00281   for(unsigned int i=0; i<NumLEDs; i++)
00282     if(infos[i].flashtime!=0)
00283       infos[i].flashtime+=ms;
00284   if(nextFlashEnd!=0)
00285     nextFlashEnd+=ms;
00286   dirty=true;
00287 }
00288 
00289 void LedEngine::displayNumber(int x, numStyle_t style) {
00290   switch(style) {
00291   case onedigit: {
00292     const LEDBitMask_t * numMasks=ERS210numMasks; //Default to 210's mask on new models - might not have as many LEDs
00293     WorldState * st=WorldState::getCurrent();
00294     if(st->robotDesign & WorldState::ERS220Mask)
00295       numMasks=ERS220numMasks;
00296     if(st->robotDesign & WorldState::ERS7Mask)
00297       numMasks=ERS7numMasks;
00298     if(x>9 || x<-9) {
00299       ccycle(FaceLEDMask&~TopBrLEDMask,333,10,-5);
00300       infos[TopBrLEDOffset-LEDOffset].value=x<0?1:0;
00301     } else {
00302       clear();
00303       if(x<0) {
00304         set(numMasks[-x],1);
00305         infos[TopBrLEDOffset-LEDOffset].value=infos[TopBrLEDOffset-LEDOffset].value*.5+.25;
00306       } else
00307         set(numMasks[x],1);
00308     }
00309     } break;
00310   case twodigit:
00311     if(x>99 || x<-99) {
00312       ccycle(FaceLEDMask&~TopBrLEDMask,333,10,-5);
00313       infos[TopBrLEDOffset-LEDOffset].value=x<0?1:0;
00314     } else {
00315       clear();
00316       if(x<0) {
00317         infos[TopBrLEDOffset-LEDOffset].value=1;
00318         x=-x;
00319       }
00320       setOneOfTwo(x%10,BotLLEDOffset-LEDOffset,MidLLEDOffset-LEDOffset,TopLLEDOffset-LEDOffset);
00321       setOneOfTwo(x/10,BotRLEDOffset-LEDOffset,MidRLEDOffset-LEDOffset,TopRLEDOffset-LEDOffset);
00322     }
00323     break;
00324   }
00325 }
00326 void LedEngine::setOneOfTwo(unsigned int x, unsigned int low, unsigned int mid, unsigned int high) {
00327   if(x==0)
00328     return;
00329   float bg = ((x-1)/3)/3.0;
00330   float fg = bg+.333333333;
00331   if(WorldState::getCurrent()->robotDesign & WorldState::ERS7Mask)
00332     bg*=bg; // dim the background a bit more on ERS7
00333   switch(x%3) {
00334   case 1:
00335     infos[high].value=bg;
00336     infos[mid].value=bg;
00337     infos[low].value=fg;
00338     break;
00339   case 2:
00340     infos[high].value=bg;
00341     infos[mid].value=fg;
00342     infos[low].value=bg;
00343     break;
00344   case 0:
00345     infos[high].value=fg;
00346     infos[mid].value=bg;
00347     infos[low].value=bg;
00348     break;
00349   }
00350 }
00351 
00352 void LedEngine::displayPercent(float x, percentStyle_t left_style, percentStyle_t right_style) {
00353   clear();
00354   if(x<0) {
00355     set(FaceLEDMask,.25);
00356     return;
00357   }
00358   if(x>1) {
00359     set(FaceLEDMask,.75);
00360     return;
00361   }
00362   if(left_style==major)
00363     setColumn(x,BotLLEDMask,MidLLEDMask,TopLLEDMask,TopBrLEDMask);
00364   if(right_style==major)
00365     setColumn(x,BotRLEDMask,MidRLEDMask,TopRLEDMask,TopBrLEDMask);
00366   x*=4;
00367   x-=(int)x;
00368   if(left_style==minor)
00369     setColumn(x,BotLLEDMask,MidLLEDMask,TopLLEDMask,TopBrLEDMask);
00370   if(right_style==minor)
00371     setColumn(x,BotRLEDMask,MidRLEDMask,TopRLEDMask,TopBrLEDMask);
00372 }
00373 
00374 void LedEngine::setColumn(float x, unsigned int low, unsigned int mid, unsigned int high, unsigned int top) {
00375   LEDBitMask_t solid=0;
00376   LEDBitMask_t partial=0;
00377   switch((int)(4*x)) {
00378   case 4:
00379     solid|=top;
00380   case 3:
00381     solid|=high;
00382   case 2:
00383     solid|=mid;
00384   case 1:
00385     solid|=low;
00386   }
00387   switch((int)(4*x)) {
00388   case 3:
00389     partial=top; break;
00390   case 2:
00391     partial=high; break;
00392   case 1:
00393     partial=mid; break;
00394   case 0:
00395     partial=low; break;
00396   }
00397   float partialvalue=(x*4)-(int)(x*4);
00398   set(partial,partialvalue);
00399   set(solid,1);
00400 }
00401 
00402 
00403 /*! @file
00404  * @brief Implements LedEngine, which provides basic LED effects to anything that inherits or instantiates it
00405  * @author ejt (Creator)
00406  *
00407  * $Author: ejt $
00408  * $Name: tekkotsu-3_0 $
00409  * $Revision: 1.18 $
00410  * $State: Exp $
00411  * $Date: 2006/08/22 22:23:04 $
00412  */

Tekkotsu v3.0
Generated Wed Oct 4 00:03:43 2006 by Doxygen 1.4.7