00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00020
00037 #if FASTSERVO_CHANNELS > 6
00038 #error "too many fast servos"
00039 #endif
00040
00041
00042
00043 #define MAKENAME(n) const char fastServoNames##n[] PROGMEM = "FastServo."#n
00044 #define MAKEARRAY(s) static const char* s[] = {\
00045 s##1,s##2,s##3,s##4,s##5,s##6};
00046
00047 MAKENAME(1);
00048 MAKENAME(2);
00049 MAKENAME(3);
00050 MAKENAME(4);
00051 MAKENAME(5);
00052 MAKENAME(6);
00053 MAKEARRAY(fastServoNames);
00054
00055 #undef MAKENAME
00056 #define MAKENAME(s,n) const char fastServo##s##n[] PROGMEM = "FastServo."#n"."#s
00057
00058
00059 MAKENAME(Min,1);
00060 MAKENAME(Min,2);
00061 MAKENAME(Min,3);
00062 MAKENAME(Min,4);
00063 MAKENAME(Min,5);
00064 MAKENAME(Min,6);
00065 MAKEARRAY(fastServoMin);
00066
00067 MAKENAME(Max,1);
00068 MAKENAME(Max,2);
00069 MAKENAME(Max,3);
00070 MAKENAME(Max,4);
00071 MAKENAME(Max,5);
00072 MAKENAME(Max,6);
00073 MAKEARRAY(fastServoMax);
00074
00075 MAKENAME(Gain,1);
00076 MAKENAME(Gain,2);
00077 MAKENAME(Gain,3);
00078 MAKENAME(Gain,4);
00079 MAKENAME(Gain,5);
00080 MAKENAME(Gain,6);
00081 MAKEARRAY(fastServoGain);
00082
00083 MAKENAME(Offset,1);
00084 MAKENAME(Offset,2);
00085 MAKENAME(Offset,3);
00086 MAKENAME(Offset,4);
00087 MAKENAME(Offset,5);
00088 MAKENAME(Offset,6);
00089 MAKEARRAY(fastServoOffset);
00090 #undef MAKENAME
00091 #undef MAKEARRAY
00092
00093
00094 #define US2CLKS ((F_CPU / 8)/1000000)
00095
00096 #define sbi(reg,bit) reg |= _BV(bit)
00097 #define cbi(reg,bit) reg &= ~(_BV(bit));
00098
00099
00100 class FastServo : public Module
00101 {
00102 DECLARE_MODULE(FastServo,Module)
00103
00104
00105
00106
00107 FastServo()
00108 {
00109
00110
00111
00112
00113 AddSocketArray(fastServoNames, m_servoSockets, FASTSERVO_CHANNELS);
00114 AddSocketArray(fastServoMin, m_mins, FASTSERVO_CHANNELS);
00115 AddSocketArray(fastServoMax, m_maxs, FASTSERVO_CHANNELS);
00116 AddSocketArray(fastServoGain, m_gains, FASTSERVO_CHANNELS);
00117 AddSocketArray(fastServoOffset, m_offsets, FASTSERVO_CHANNELS);
00118
00119
00120 for (int ct=0; ct< FASTSERVO_CHANNELS; ct++)
00121 {
00122 m_mins[ct] = 1000;
00123 m_maxs[ct] = 2000;
00124 m_gains[ct] = 500;
00125 m_offsets[ct] = 1500;
00126 }
00127 }
00128
00129
00130
00131
00132 virtual void ParamChanged(Socket * param)
00133 {
00134 }
00135
00136
00137
00138 virtual void Init()
00139 {
00140 for (int ct=0; ct< FASTSERVO_CHANNELS; ct++)
00141 {
00142 InitPin(fastServoPins[ct],ct);
00143 }
00144
00145 SetInterval(5);
00146 SetPriority(20);
00147 }
00148
00149
00150 virtual void Loop(const unsigned long& interval)
00151 {
00152 for (int ct=0; ct< FASTSERVO_CHANNELS; ct++)
00153 {
00154
00155 float socket = m_servoSockets[ct];
00156 if (socket != m_servoWas[ct])
00157 {
00158 m_servoWas[ct] = socket;
00159 int value = m_servoSockets[ct] * m_gains[ct];
00160 value += m_offsets[ct];
00161 if(value > m_maxs[ct])
00162 {
00163 value = m_maxs[ct];
00164 }else if(value < m_mins[ct])
00165 {
00166 value = m_mins[ct];
00167 }
00168 *m_outputs[ct] = value * 2;
00169 }
00170 }
00171 }
00172
00173
00174
00175 private:
00176
00177 bool InitPin(int pin, int index)
00178 {
00179 pinMode(pin, OUTPUT);
00180 bool found = true;
00181 byte timer = 0;
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198 if (digitalPinToTimer(pin) == TIMER3A) {
00199
00200 sbi(TCCR3A, COM3A1);
00201
00202 m_outputs[index] = &OCR3A;
00203 timer = 3;
00204 } else if (digitalPinToTimer(pin) == TIMER3B) {
00205
00206 sbi(TCCR3A, COM3B1);
00207
00208 m_outputs[index] = &OCR3B;
00209 timer = 3;
00210 } else if (digitalPinToTimer(pin) == TIMER3C) {
00211
00212 sbi(TCCR3A, COM3C1);
00213
00214 m_outputs[index] = &OCR3C;
00215 timer = 3;
00216 } else if (digitalPinToTimer(pin) == TIMER4A) {
00217
00218 sbi(TCCR4A, COM4A1);
00219
00220 m_outputs[index] = &OCR4A;
00221 timer = 4;
00222 } else if (digitalPinToTimer(pin) == TIMER4B) {
00223
00224 sbi(TCCR4A, COM4B1);
00225
00226 m_outputs[index] = &OCR4B;
00227 timer = 4;
00228 } else if (digitalPinToTimer(pin) == TIMER4C) {
00229
00230 sbi(TCCR4A, COM4C1);
00231
00232 m_outputs[index] = &OCR4C;
00233 timer = 4;
00234 }
00235
00236 switch(timer)
00237 {
00238 case 3:
00239 TCCR3B = _BV(WGM33)|_BV(WGM32)|_BV(CS31);
00240 sbi(TCCR3A,WGM31);
00241 cbi(TCCR3A,WGM30);
00242 ICR3 = ((F_CPU / 8) / FASTSERVO_RATE);
00243 break;
00244
00245 case 4:
00246 TCCR4B = _BV(WGM43)|_BV(WGM42)|_BV(CS41);
00247 sbi(TCCR4A,WGM41);
00248 cbi(TCCR4A,WGM40);
00249 ICR4 = ((F_CPU / 8) / FASTSERVO_RATE);
00250 break;
00251
00252 default:
00253 m_outputs[index] = &scrapVal;
00254 return(false);
00255 }
00256 return(true);
00257 }
00258
00259 SocketF m_servoSockets[FASTSERVO_CHANNELS];
00260 ParameterF m_gains[FASTSERVO_CHANNELS];
00261 Parameter16 m_offsets[FASTSERVO_CHANNELS];
00262 Parameter16 m_mins[FASTSERVO_CHANNELS];
00263 Parameter16 m_maxs[FASTSERVO_CHANNELS];
00264 float m_servoWas[FASTSERVO_CHANNELS];
00265 volatile uint16_t* m_outputs[FASTSERVO_CHANNELS];
00266 static uint16_t scrapVal;
00267 };
00268
00269 uint16_t FastServo::scrapVal;
00270
00271 FastServo g_FastServo;
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391