CMUcam4 Arduino Interface Library  For Firmware Versions 1.00 - 1.03
Application Programmable Interface Online Documentation
 All Classes Files Functions Variables Macros Pages
CMUcam4.cpp
Go to the documentation of this file.
1 /***************************************************************************//**
2 * @file
3 * Portable %CMUcam4 interface library.
4 *
5 * @version @n 1.1
6 * @date @n 2/7/2013
7 *
8 * @authors @n Kwabena W. Agyeman & Christopher J. Leaf
9 * @copyright @n (c) 2013 Kwabena W. Agyeman & Christopher J. Leaf
10 * @n All rights reserved - Please see the end of the file for the terms of use
11 *
12 * @par Update History:
13 * @n v0.1 - Beta code - 3/20/2012
14 * @n v0.9 - Original release - 4/18/2012
15 * @n v1.0 - Documented and updated release - 8/3/2012
16 * @n v1.1 - Added support for the Arduino Due, fixed the send frame command,
17  and fixed a number of compile time warnings - 2/7/2013.
18 *******************************************************************************/
19 
20 #include "CMUcam4.h"
21 
22 /*******************************************************************************
23 * Constructor Functions
24 *******************************************************************************/
25 
27 {
28  CMUcom4 _copy;
29 
30  _state = DEACTIVATED;
31  _com = _copy;
32 }
33 
35 {
36  CMUcom4 _copy(port);
37 
38  _state = DEACTIVATED;
39  _com = _copy;
40 }
41 
42 /*******************************************************************************
43 * Helper Functions
44 *******************************************************************************/
45 
47  int row, int column)
48 {
49  if((pointer==NULL)||
52  {
54  }
55 
56  return ((pointer->pixels[(row * CMUCAM4_ID_T_C) + (column / 8)]
57  >> (7 - (column & 7))) & 1);
58 }
59 
61  int row, int column, int value)
62 {
63  int bitIndex; int byteIndex;
64 
65  if((pointer==NULL)||
68  {
70  }
71 
72  bitIndex = (7 - (column & 7));
73  byteIndex = ((row * CMUCAM4_ID_T_C) + (column / 8));
74 
75  pointer->pixels[byteIndex] =
76  (((~(1<<bitIndex))&(pointer->pixels[byteIndex]))|((value?1:0)<<bitIndex));
77 
79 }
80 
82  CMUcam4_image_data_t * source0,
83  CMUcam4_image_data_t * source1)
84 {
85  size_t index;
86 
87  if((destination == NULL) || (source0 == NULL) || (source1 == NULL))
88  {
90  }
91 
92  for(index = 0; index < CMUCAM4_ID_T_LENGTH; index++)
93  {
94  destination->pixels[index] =
95  (source0->pixels[index] & source1->pixels[index]);
96  }
97 
99 }
100 
102  CMUcam4_image_data_t * source0,
103  CMUcam4_image_data_t * source1)
104 {
105  size_t index;
106 
107  if((destination == NULL) || (source0 == NULL) || (source1 == NULL))
108  {
109  return CMUCAM4_RETURN_FAILURE;
110  }
111 
112  for(index = 0; index < CMUCAM4_ID_T_LENGTH; index++)
113  {
114  destination->pixels[index] =
115  (source0->pixels[index] | source1->pixels[index]);
116  }
117 
118  return CMUCAM4_RETURN_SUCCESS;
119 }
120 
122  CMUcam4_image_data_t * source0,
123  CMUcam4_image_data_t * source1)
124 {
125  size_t index;
126 
127  if((destination == NULL) || (source0 == NULL) || (source1 == NULL))
128  {
129  return CMUCAM4_RETURN_FAILURE;
130  }
131 
132  for(index = 0; index < CMUCAM4_ID_T_LENGTH; index++)
133  {
134  destination->pixels[index] =
135  (source0->pixels[index] ^ source1->pixels[index]);
136  }
137 
138  return CMUCAM4_RETURN_SUCCESS;
139 }
140 
142 {
143  size_t index;
144 
145  if(destination == NULL)
146  {
147  return CMUCAM4_RETURN_FAILURE;
148  }
149 
150  for(index = 0; index < CMUCAM4_ID_T_LENGTH; index++)
151  {
152  destination->pixels[index] =
153  (~destination->pixels[index]);
154  }
155 
156  return CMUCAM4_RETURN_SUCCESS;
157 }
158 
160 {
161  CMUcam4_entry_attributes_t * attributes;
162 
163  if(pointer == NULL)
164  {
165  return CMUCAM4_RETURN_FAILURE;
166  }
167 
168  attributes = ((CMUcam4_entry_attributes_t *) pointer->attributes);
169  return (attributes->readOnly == 'R');
170 }
171 
173 {
174  CMUcam4_entry_attributes_t * attributes;
175 
176  if(pointer == NULL)
177  {
178  return CMUCAM4_RETURN_FAILURE;
179  }
180 
181  attributes = ((CMUcam4_entry_attributes_t *) pointer->attributes);
182  return (attributes->hidden == 'H');
183 }
184 
186 {
187  CMUcam4_entry_attributes_t * attributes;
188 
189  if(pointer == NULL)
190  {
191  return CMUCAM4_RETURN_FAILURE;
192  }
193 
194  attributes = ((CMUcam4_entry_attributes_t *) pointer->attributes);
195  return (attributes->system == 'S');
196 }
197 
199 {
200  CMUcam4_entry_attributes_t * attributes;
201 
202  if(pointer == NULL)
203  {
204  return CMUCAM4_RETURN_FAILURE;
205  }
206 
207  attributes = ((CMUcam4_entry_attributes_t *) pointer->attributes);
208  return (attributes->volumeID == 'V');
209 }
210 
212 {
213  CMUcam4_entry_attributes_t * attributes;
214 
215  if(pointer == NULL)
216  {
217  return CMUCAM4_RETURN_FAILURE;
218  }
219 
220  attributes = ((CMUcam4_entry_attributes_t *) pointer->attributes);
221  return (attributes->directory == 'D');
222 }
223 
225 {
226  CMUcam4_entry_attributes_t * attributes;
227 
228  if(pointer == NULL)
229  {
230  return CMUCAM4_RETURN_FAILURE;
231  }
232 
233  attributes = ((CMUcam4_entry_attributes_t *) pointer->attributes);
234  return (attributes->archive == 'A');
235 }
236 
237 /*******************************************************************************
238 * State Functions
239 *******************************************************************************/
240 
242 {
243  int errorValue; int retVal0; int retVal1; static int resetTries;
244 
245  resetTries = CMUCAM4_RESET_TRIES;
246  errorValue = setjmp(_env);
247 
248  if(resetTries-- <= 0)
249  {
250  _com.end();
251  return errorValue;
252  }
253 
254  // Try to reset at fast, medium, and slow baud rates.
255 
256  _state = DEACTIVATED;
257  _setReadTimeout(CMUCAM4_RESET_TIMEOUT);
258 
259  if(errorValue)
260  {
261  _com.end();
262  }
263 
264  _com.begin(resetTries ? CMUCOM4_FAST_BAUD_RATE : CMUCOM4_MEDIUM_BAUD_RATE);
265  _com.write((uint8_t) '\0');
266  _com.write((uint8_t) '\0');
267  _com.write((uint8_t) '\0');
268  _com.write("\rRS\r");
269 
270  _com.end();
271  _com.begin(CMUCOM4_MEDIUM_BAUD_RATE);
272  _com.write((uint8_t) '\0');
273  _com.write((uint8_t) '\0');
274  _com.write((uint8_t) '\0');
275  _com.write("\rRS\r");
276 
277  _com.end();
278  _com.begin(CMUCOM4_SLOW_BAUD_RATE);
279  _com.write((uint8_t) '\0');
280  _com.write((uint8_t) '\0');
281  _com.write((uint8_t) '\0');
282  _com.write("\rRS\r");
283 
284  // Get the firmware version.
285 
286  _waitForString("\rCMUcam4 v");
287  _readText();
288 
289  if(sscanf(_resBuffer, "%1d.%2d ", &retVal0, &retVal1) != 2)
290  {
291  longjmp(_env, CMUCAM4_UNEXPECTED_RESPONCE);
292  }
293 
294  _version = ((_CMUcam4_version) ((retVal0 * 100) + retVal1));
295 
296  switch(_version)
297  {
298  case VERSION_100: break;
299  case VERSION_101: break;
300  case VERSION_102: break;
301  case VERSION_103: break;
302 
303  default: longjmp(_env, CMUCAM4_UNSUPPORTED_VERSION); break;
304  }
305 
306  _waitForIdle();
307 
308  // Adjust the baud rate.
309 
310  _setReadTimeout(CMUCAM4_NON_FS_TIMEOUT);
311  _com.write("BM ");
312 
313  switch(_version)
314  {
315  case VERSION_100:
316  case VERSION_101: _com.write(CMUCOM4_MEDIUM_BR_STRING); break;
317  case VERSION_102:
318  case VERSION_103: _com.write(resetTries ?
319  CMUCOM4_FAST_BR_STRING :
320  CMUCOM4_MEDIUM_BR_STRING); break;
321  }
322 
323  _com.write((uint8_t) '\r');
324  _waitForResponce();
325  _com.end();
326 
327  switch(_version)
328  {
329  case VERSION_100:
330  case VERSION_101: _com.begin(CMUCOM4_MEDIUM_BAUD_RATE); break;
331  case VERSION_102:
332  case VERSION_103: _com.begin(resetTries ?
333  CMUCOM4_FAST_BAUD_RATE :
334  CMUCOM4_MEDIUM_BAUD_RATE); break;
335  }
336 
337  _com.write((uint8_t) '\r');
338  _waitForResponce();
339  _waitForIdle();
340 
341  // Adjust the stop bits.
342 
343  _setReadTimeout(CMUCAM4_NON_FS_TIMEOUT);
344  _com.write("DM ");
345 
346  switch(_version)
347  {
348  case VERSION_100:
349  case VERSION_101: _com.write(CMUCOM4_MEDIUM_SB_STRING); break;
350  case VERSION_102:
351  case VERSION_103: _com.write(resetTries ?
352  CMUCOM4_FAST_SB_STRING :
353  CMUCOM4_MEDIUM_SB_STRING); break;
354  }
355 
356  _com.write((uint8_t) '\r');
357  _waitForResponce();
358  _waitForIdle();
359 
360  _state = ACTIVATED;
361  return CMUCAM4_RETURN_SUCCESS;
362 }
363 
365 {
366  if(_state == DEACTIVATED)
367  {
368  return CMUCAM4_NOT_ACTIVATED;
369  }
370 
371  _state = DEACTIVATED;
372  _com.end();
373 
374  return CMUCAM4_RETURN_SUCCESS;
375 }
376 
377 /*******************************************************************************
378 * System Level Commands
379 *******************************************************************************/
380 
382 {
383  return (_state == ACTIVATED) ? _version : CMUCAM4_NOT_ACTIVATED;
384 }
385 
387 {
388  return (_state == ACTIVATED) ? begin() : CMUCAM4_NOT_ACTIVATED;
389 }
390 
392 {
393  return _commandWrapper("SD\r", CMUCAM4_NON_FS_TIMEOUT);
394 }
395 
397 {
398  return _commandWrapper("SL\r", CMUCAM4_NON_FS_TIMEOUT);
399 }
400 
401 /*******************************************************************************
402 * Camera Module Commands
403 *******************************************************************************/
404 
405 int CMUcam4::cameraBrightness(int brightness)
406 {
407  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
408  "CB %d\r", brightness) < CMUCAM4_CMD_BUFFER_SIZE)
409  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
411 }
412 
413 int CMUcam4::cameraContrast(int contrast)
414 {
415  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
416  "CC %d\r", contrast) < CMUCAM4_CMD_BUFFER_SIZE)
417  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
419 }
420 
422 {
423  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
424  "CR %d\r", reg) < CMUCAM4_CMD_BUFFER_SIZE)
425  ? _intCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
427 }
428 
429 int CMUcam4::cameraRegisterWrite(int reg, int value, int mask)
430 {
431  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
432  "CW %d %d %d\r", reg, value, mask) < CMUCAM4_CMD_BUFFER_SIZE)
433  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
435 }
436 
437 /*******************************************************************************
438 * Camera Sensor Auto Control Commands
439 *******************************************************************************/
440 
442 {
443  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
444  "AG %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
445  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
447 }
448 
450 {
451  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
452  "AW %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
453  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
455 }
456 
457 /*******************************************************************************
458 * Camera Format Commands
459 *******************************************************************************/
460 
462 {
463  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
464  "HM %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
465  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
467 }
468 
469 int CMUcam4::verticalFlip(int active)
470 {
471  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
472  "VF %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
473  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
475 }
476 
477 /*******************************************************************************
478 * Camera Effect Commands
479 *******************************************************************************/
480 
482 {
483  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
484  "BW %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
485  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
487 }
488 
489 int CMUcam4::negativeMode(int active)
490 {
491  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
492  "NG %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
493  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
495 }
496 
497 /*******************************************************************************
498 * Auxiliary I/O Commands
499 *******************************************************************************/
500 
502 {
503  return _intCommandWrapper("GB\r", CMUCAM4_NON_FS_TIMEOUT);
504 }
505 
507 {
508  int errorValue; int resultValue; long returnValue;
509 
510  if((errorValue = _commandWrapper("GD\r", CMUCAM4_NON_FS_TIMEOUT)))
511  {
512  return errorValue;
513  }
514 
515  if((errorValue = setjmp(_env)))
516  {
517  return errorValue;
518  }
519 
520  _receiveData();
521  resultValue = (sscanf(_resBuffer, "%ld ", &returnValue) == 1);
522 
523  _waitForIdle();
524  return resultValue ? returnValue : CMUCAM4_UNEXPECTED_RESPONCE;
525 }
526 
528 {
529  return _intCommandWrapper("GP\r", CMUCAM4_NON_FS_TIMEOUT);
530 }
531 
533 {
534  return _intCommandWrapper("GR\r", CMUCAM4_NON_FS_TIMEOUT);
535 }
536 
538 {
539  return _intCommandWrapper("PI\r", CMUCAM4_NON_FS_TIMEOUT);
540 }
541 
542 int CMUcam4::panOutput(int direction, int output)
543 {
544  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
545  "PO %d %d\r", direction, output) < CMUCAM4_CMD_BUFFER_SIZE)
546  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
548 }
549 
551 {
552  return _intCommandWrapper("TI\r", CMUCAM4_NON_FS_TIMEOUT);
553 }
554 
555 int CMUcam4::tiltOutput(int direction, int output)
556 {
557  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
558  "TO %d %d\r", direction, output) < CMUCAM4_CMD_BUFFER_SIZE)
559  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
561 }
562 
564 {
565  return _intCommandWrapper("GI\r", CMUCAM4_NON_FS_TIMEOUT);
566 }
567 
568 int CMUcam4::setOutputs(int directions, int outputs)
569 {
570  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
571  "SO %d %d\r", directions, outputs) < CMUCAM4_CMD_BUFFER_SIZE)
572  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
574 }
575 
577 {
578  return _voidCommandWrapper("L0\r", CMUCAM4_NON_FS_TIMEOUT);
579 }
580 
581 int CMUcam4::LEDOn(long frequency)
582 {
583  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
584  "L1 %ld\r", frequency) < CMUCAM4_CMD_BUFFER_SIZE)
585  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
587 }
588 
589 /*******************************************************************************
590 * Servo Commands
591 *******************************************************************************/
592 
594 {
595  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
596  "GS %d\r", servo) < CMUCAM4_CMD_BUFFER_SIZE)
597  ? _intCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
599 }
600 
601 int CMUcam4::setServoPosition(int servo, int active, int pulseLength)
602 {
603  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
604  "SS %d %d %d\r", servo, active, pulseLength) < CMUCAM4_CMD_BUFFER_SIZE)
605  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
607 }
608 
609 int CMUcam4::automaticPan(int active, int reverse)
610 {
611  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
612  "AP %d %d\r", active, reverse) < CMUCAM4_CMD_BUFFER_SIZE)
613  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
615 }
616 
617 int CMUcam4::automaticTilt(int active, int reverse)
618 {
619  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
620  "AT %d %d\r", active, reverse) < CMUCAM4_CMD_BUFFER_SIZE)
621  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
623 }
624 
625 int CMUcam4::autoPanParameters(int proportionalGain, int derivativeGain)
626 {
627  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
628  "PP %d %d\r", proportionalGain, derivativeGain) < CMUCAM4_CMD_BUFFER_SIZE)
629  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
631 }
632 
633 int CMUcam4::autoTiltParameters(int proportionalGain, int derivativeGain)
634 {
635  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
636  "TP %d %d\r", proportionalGain, derivativeGain) < CMUCAM4_CMD_BUFFER_SIZE)
637  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
639 }
640 
641 /*******************************************************************************
642 * Television Commands
643 *******************************************************************************/
644 
646 {
647  return _voidCommandWrapper("M0\r", CMUCAM4_NON_FS_TIMEOUT);
648 }
649 
651 {
652  return _voidCommandWrapper("M1\r", CMUCAM4_NON_FS_TIMEOUT);
653 }
654 
655 int CMUcam4::monitorFreeze(int active)
656 {
657  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
658  "MF %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
659  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
661 }
662 
663 int CMUcam4::monitorSignal(int active)
664 {
665  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
666  "MS %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
667  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
669 }
670 
671 /*******************************************************************************
672 * Color Tracking Commands
673 *******************************************************************************/
674 
676 {
677  int errorValue; int resultValue;
678 
679  if(pointer == NULL)
680  {
681  return CMUCAM4_RETURN_FAILURE;
682  }
683 
684  if((errorValue = _commandWrapper("GT\r", CMUCAM4_NON_FS_TIMEOUT)))
685  {
686  return errorValue;
687  }
688 
689  if((errorValue = setjmp(_env)))
690  {
691  return errorValue;
692  }
693 
694  _receiveData();
695  resultValue = (sscanf(_resBuffer, "%d %d %d %d %d %d ",
696  &(pointer->redMin),
697  &(pointer->redMax),
698  &(pointer->greenMin),
699  &(pointer->greenMax),
700  &(pointer->blueMin),
701  &(pointer->blueMax)) == 6);
702 
703  _waitForIdle();
705 }
706 
708 {
709  int errorValue; int resultValue;
710 
711  if(pointer == NULL)
712  {
713  return CMUCAM4_RETURN_FAILURE;
714  }
715 
716  if((errorValue = _commandWrapper("GW\r", CMUCAM4_NON_FS_TIMEOUT)))
717  {
718  return errorValue;
719  }
720 
721  if((errorValue = setjmp(_env)))
722  {
723  return errorValue;
724  }
725 
726  _receiveData();
727  resultValue = (sscanf(_resBuffer, "%d %d %d %d ",
728  &(pointer->topLeftX),
729  &(pointer->topLeftY),
730  &(pointer->bottomRightX),
731  &(pointer->bottomRightY)) == 4);
732 
733  _waitForIdle();
735 }
736 
738 {
739  return _voidCommandWrapper("ST\r", CMUCAM4_NON_FS_TIMEOUT);
740 }
741 
742 int CMUcam4::setTrackingParameters(int redMin, int redMax,
743  int greenMin, int greenMax,
744  int blueMin, int blueMax)
745 {
746  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
747  "ST %d %d %d %d %d %d\r",
748  redMin, redMax, greenMin, greenMax, blueMin, blueMax)
749  < CMUCAM4_CMD_BUFFER_SIZE)
750  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
752 }
753 
755 {
756  return _voidCommandWrapper("SW\r", CMUCAM4_NON_FS_TIMEOUT);
757 }
758 
759 int CMUcam4::setTrackingWindow(int topLeftX, int topLeftY,
760  int bottomRightX, int bottomRightY)
761 {
762  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
763  "SW %d %d %d %d\r",
764  topLeftX, topLeftY, bottomRightX, bottomRightY)
765  < CMUCAM4_CMD_BUFFER_SIZE)
766  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
768 }
769 
771 {
772  int errorValue; static int resetTries; char cmdBuffer[CMUCAM4_IC_LENGTH];
773 
774  if(_state == DEACTIVATED)
775  {
776  return CMUCAM4_NOT_ACTIVATED;
777  }
778 
779  if(snprintf(cmdBuffer, CMUCAM4_IC_LENGTH,
780  CMUCAM4_IC_STRING, (_version / 100), (_version % 100))
781  >= (int) CMUCAM4_IC_LENGTH)
782  {
784  }
785 
786  resetTries = CMUCAM4_IDLE_TRIES;
787  errorValue = setjmp(_env);
788 
789  if(resetTries-- <= 0)
790  {
791  return errorValue;
792  }
793 
794  _setReadTimeout(CMUCAM4_IDLE_TIMEOUT);
795  _com.write((uint8_t) '\0');
796  _com.write((uint8_t) '\0');
797  _com.write((uint8_t) '\0');
798  _com.write("\rGV\r");
799  _waitForString(cmdBuffer);
800 
801  return CMUCAM4_RETURN_SUCCESS;
802 }
803 
805 {
806  return _commandWrapper("TC\r", CMUCAM4_NON_FS_TIMEOUT);
807 }
808 
809 int CMUcam4::trackColor(int redMin, int redMax,
810  int greenMin, int greenMax,
811  int blueMin, int blueMax)
812 {
813  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
814  "TC %d %d %d %d %d %d\r",
815  redMin, redMax, greenMin, greenMax, blueMin, blueMax)
816  < CMUCAM4_CMD_BUFFER_SIZE)
817  ? _commandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
819 }
820 
821 int CMUcam4::trackWindow(int redRange, int greenRange, int blueRange)
822 {
823  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
824  "TW %d %d %d\r", redRange, greenRange, blueRange)
825  < CMUCAM4_CMD_BUFFER_SIZE)
826  ? _commandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
828 }
829 
830 int CMUcam4::getHistogram(int channel, int bins)
831 {
832  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
833  "GH %d %d\r", channel, bins)
834  < CMUCAM4_CMD_BUFFER_SIZE)
835  ? _commandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
837 }
838 
840 {
841  return _commandWrapper("GM\r", CMUCAM4_NON_FS_TIMEOUT);
842 }
843 
845 {
846  int errorValue;
847 
848  if(pointer == NULL)
849  {
850  return CMUCAM4_RETURN_FAILURE;
851  }
852 
853  if((errorValue = _responceWrapper('F')))
854  {
855  return errorValue;
856  }
857 
858  if(strcmp(_resBuffer, "F ") != 0)
859  {
861  }
862 
863  if((errorValue = setjmp(_env)))
864  {
865  return errorValue;
866  }
867 
868  _readBinary(pointer->pixels, CMUCAM4_ID_T_LENGTH, CMUCAM4_ID_T_LENGTH, 0);
869 
870  return (_readWithTimeout() == '\r')
872 }
873 
875 {
876  int errorValue; char * buffer = (_resBuffer + sizeof('H')); size_t counter;
877 
878  if(pointer == NULL)
879  {
880  return CMUCAM4_RETURN_FAILURE;
881  }
882 
883  if((errorValue = _responceWrapper('H')))
884  {
885  return errorValue;
886  }
887 
888  for(counter = 0; counter < CMUCAM4_HD_1_T_LENGTH; counter++)
889  {
890  if((*buffer) == '\0')
891  {
893  }
894 
895  pointer->bins[counter] = ((uint8_t) strtol(buffer, &buffer, 10));
896  }
897 
898  if((*buffer) != '\0')
899  {
901  }
902 
903  return CMUCAM4_RETURN_SUCCESS;
904 }
905 
907 {
908  int errorValue; char * buffer = (_resBuffer + sizeof('H')); size_t counter;
909 
910  if(pointer == NULL)
911  {
912  return CMUCAM4_RETURN_FAILURE;
913  }
914 
915  if((errorValue = _responceWrapper('H')))
916  {
917  return errorValue;
918  }
919 
920  for(counter = 0; counter < CMUCAM4_HD_2_T_LENGTH; counter++)
921  {
922  if((*buffer) == '\0')
923  {
925  }
926 
927  pointer->bins[counter] = ((uint8_t) strtol(buffer, &buffer, 10));
928  }
929 
930  if((*buffer) != '\0')
931  {
933  }
934 
935  return CMUCAM4_RETURN_SUCCESS;
936 }
937 
939 {
940  int errorValue; char * buffer = (_resBuffer + sizeof('H')); size_t counter;
941 
942  if(pointer == NULL)
943  {
944  return CMUCAM4_RETURN_FAILURE;
945  }
946 
947  if((errorValue = _responceWrapper('H')))
948  {
949  return errorValue;
950  }
951 
952  for(counter = 0; counter < CMUCAM4_HD_4_T_LENGTH; counter++)
953  {
954  if((*buffer) == '\0')
955  {
957  }
958 
959  pointer->bins[counter] = ((uint8_t) strtol(buffer, &buffer, 10));
960  }
961 
962  if((*buffer) != '\0')
963  {
965  }
966 
967  return CMUCAM4_RETURN_SUCCESS;
968 }
969 
971 {
972  int errorValue; char * buffer = (_resBuffer + sizeof('H')); size_t counter;
973 
974  if(pointer == NULL)
975  {
976  return CMUCAM4_RETURN_FAILURE;
977  }
978 
979  if((errorValue = _responceWrapper('H')))
980  {
981  return errorValue;
982  }
983 
984  for(counter = 0; counter < CMUCAM4_HD_8_T_LENGTH; counter++)
985  {
986  if((*buffer) == '\0')
987  {
989  }
990 
991  pointer->bins[counter] = ((uint8_t) strtol(buffer, &buffer, 10));
992  }
993 
994  if((*buffer) != '\0')
995  {
997  }
998 
999  return CMUCAM4_RETURN_SUCCESS;
1000 }
1001 
1003 {
1004  int errorValue; char * buffer = (_resBuffer + sizeof('H')); size_t counter;
1005 
1006  if(pointer == NULL)
1007  {
1008  return CMUCAM4_RETURN_FAILURE;
1009  }
1010 
1011  if((errorValue = _responceWrapper('H')))
1012  {
1013  return errorValue;
1014  }
1015 
1016  for(counter = 0; counter < CMUCAM4_HD_16_T_LENGTH; counter++)
1017  {
1018  if((*buffer) == '\0')
1019  {
1021  }
1022 
1023  pointer->bins[counter] = ((uint8_t) strtol(buffer, &buffer, 10));
1024  }
1025 
1026  if((*buffer) != '\0')
1027  {
1029  }
1030 
1031  return CMUCAM4_RETURN_SUCCESS;
1032 }
1033 
1035 {
1036  int errorValue; char * buffer = (_resBuffer + sizeof('H')); size_t counter;
1037 
1038  if(pointer == NULL)
1039  {
1040  return CMUCAM4_RETURN_FAILURE;
1041  }
1042 
1043  if((errorValue = _responceWrapper('H')))
1044  {
1045  return errorValue;
1046  }
1047 
1048  for(counter = 0; counter < CMUCAM4_HD_32_T_LENGTH; counter++)
1049  {
1050  if((*buffer) == '\0')
1051  {
1053  }
1054 
1055  pointer->bins[counter] = ((uint8_t) strtol(buffer, &buffer, 10));
1056  }
1057 
1058  if((*buffer) != '\0')
1059  {
1061  }
1062 
1063  return CMUCAM4_RETURN_SUCCESS;
1064 }
1065 
1067 {
1068  int errorValue; char * buffer = (_resBuffer + sizeof('H')); size_t counter;
1069 
1070  if(pointer == NULL)
1071  {
1072  return CMUCAM4_RETURN_FAILURE;
1073  }
1074 
1075  if((errorValue = _responceWrapper('H')))
1076  {
1077  return errorValue;
1078  }
1079 
1080  for(counter = 0; counter < CMUCAM4_HD_64_T_LENGTH; counter++)
1081  {
1082  if((*buffer) == '\0')
1083  {
1085  }
1086 
1087  pointer->bins[counter] = ((uint8_t) strtol(buffer, &buffer, 10));
1088  }
1089 
1090  if((*buffer) != '\0')
1091  {
1093  }
1094 
1095  return CMUCAM4_RETURN_SUCCESS;
1096 }
1097 
1099 {
1100  int errorValue;
1101 
1102  if(pointer == NULL)
1103  {
1104  return CMUCAM4_RETURN_FAILURE;
1105  }
1106 
1107  if((errorValue = _responceWrapper('S')))
1108  {
1109  return errorValue;
1110  }
1111 
1112  return (sscanf(_resBuffer,
1113  "S %d %d %d %d %d %d %d %d %d %d %d %d ",
1114  &(pointer->RMean),
1115  &(pointer->GMean),
1116  &(pointer->BMean),
1117  &(pointer->RMedian),
1118  &(pointer->GMedian),
1119  &(pointer->BMedian),
1120  &(pointer->RMode),
1121  &(pointer->GMode),
1122  &(pointer->BMode),
1123  &(pointer->RStDev),
1124  &(pointer->GStDev),
1125  &(pointer->BStDev)) == 12)
1127 }
1128 
1130 {
1131  int errorValue;
1132 
1133  if(pointer == NULL)
1134  {
1135  return CMUCAM4_RETURN_FAILURE;
1136  }
1137 
1138  if((errorValue = _responceWrapper('T')))
1139  {
1140  return errorValue;
1141  }
1142 
1143  return (sscanf(_resBuffer,
1144  "T %d %d %d %d %d %d %d %d ",
1145  &(pointer->mx),
1146  &(pointer->my),
1147  &(pointer->x1),
1148  &(pointer->y1),
1149  &(pointer->x2),
1150  &(pointer->y2),
1151  &(pointer->pixels),
1152  &(pointer->confidence)) == 8)
1154 }
1155 
1156 int CMUcam4::pollMode(int active)
1157 {
1158  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1159  "PM %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
1160  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
1162 }
1163 
1164 int CMUcam4::lineMode(int active)
1165 {
1166  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1167  "LM %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
1168  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
1170 }
1171 
1172 int CMUcam4::switchingMode(int active)
1173 {
1174  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1175  "SM %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
1176  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
1178 }
1179 
1180 int CMUcam4::testMode(int active)
1181 {
1182  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1183  "TM %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
1184  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
1186 }
1187 
1188 int CMUcam4::colorTracking(int active)
1189 {
1190  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1191  "CT %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
1192  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
1194 }
1195 
1197 {
1198  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1199  "HT %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
1200  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
1202 }
1203 
1205 {
1206  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1207  "IF %d\r", active) < CMUCAM4_CMD_BUFFER_SIZE)
1208  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
1210 }
1211 
1212 int CMUcam4::noiseFilter(int threshold)
1213 {
1214  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1215  "NF %d\r", threshold) < CMUCAM4_CMD_BUFFER_SIZE)
1216  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)
1218 }
1219 
1220 /*******************************************************************************
1221 * File System Commands
1222 *******************************************************************************/
1223 
1224 int CMUcam4::changeAttributes(const char * fileOrDirectoryPathName,
1225  const char * attributes)
1226 {
1227  if((fileOrDirectoryPathName == NULL) || (attributes == NULL))
1228  {
1229  return CMUCAM4_RETURN_FAILURE;
1230  }
1231 
1232  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1233  "CA \"%s\" \"%s\"\r", fileOrDirectoryPathName, attributes)
1234  < CMUCAM4_CMD_BUFFER_SIZE)
1235  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_FS_TIMEOUT)
1237 }
1238 
1239 int CMUcam4::changeDirectory(const char * directoryPathAndName)
1240 {
1241  if(directoryPathAndName == NULL)
1242  {
1243  return CMUCAM4_RETURN_FAILURE;
1244  }
1245 
1246  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1247  "CD \"%s\"\r", directoryPathAndName)
1248  < CMUCAM4_CMD_BUFFER_SIZE)
1249  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_FS_TIMEOUT)
1251 }
1252 
1254 {
1255  int errorValue; int resultValue;
1256 
1257  if(pointer == NULL)
1258  {
1259  return CMUCAM4_RETURN_FAILURE;
1260  }
1261 
1262  if((errorValue = _commandWrapper("DI\r", CMUCAM4_FS_TIMEOUT)))
1263  {
1264  return errorValue;
1265  }
1266 
1267  if((errorValue = setjmp(_env)))
1268  {
1269  return errorValue;
1270  }
1271 
1272  _receiveData();
1273  memset(pointer->volumeLabel, '\0', CMUCAM4_VL_LENGTH + 1);
1274  memset(pointer->fileSystemType, '\0', CMUCAM4_FST_LENGTH + 1);
1275 
1276  resultValue = (sscanf(_resBuffer,
1277  "\"%" CMUCAM4_VL_LENGTH_STR "c\" "
1278  "\"%" CMUCAM4_FST_LENGTH_STR "c\" "
1279  "%lxh %lxh %lu %lu %lu %lu ",
1280  pointer->volumeLabel,
1281  pointer->fileSystemType,
1282  &(pointer->diskSignature),
1283  &(pointer->volumeIdentification),
1284  &(pointer->countOfDataSectors),
1285  &(pointer->bytesPerSector),
1286  &(pointer->sectorsPerCluster),
1287  &(pointer->countOfClusters)) == 8);
1288 
1289  _waitForIdle();
1290  return resultValue ? CMUCAM4_RETURN_SUCCESS : CMUCAM4_UNEXPECTED_RESPONCE;
1291 }
1292 
1294 {
1295  int errorValue; int resultValue;
1296 
1297  if(pointer == NULL)
1298  {
1299  return CMUCAM4_RETURN_FAILURE;
1300  }
1301 
1302  if((errorValue = _commandWrapper("DS\r", CMUCAM4_FS_TIMEOUT)))
1303  {
1304  return errorValue;
1305  }
1306 
1307  if((errorValue = setjmp(_env)))
1308  {
1309  return errorValue;
1310  }
1311 
1312  _receiveData();
1313 
1314  resultValue = (sscanf(_resBuffer,
1315  "%lu %lu ",
1316  &(pointer->freeSectorCount),
1317  &(pointer->usedSectorCount)) == 2);
1318 
1319  _waitForIdle();
1320  return resultValue ? CMUCAM4_RETURN_SUCCESS : CMUCAM4_UNEXPECTED_RESPONCE;
1321 }
1322 
1324 {
1325  return _voidCommandWrapper("FM\r", CMUCAM4_FS_TIMEOUT);
1326 }
1327 
1329  size_t size, unsigned long offset)
1330 {
1331  int errorValue; unsigned long directorySize;
1332 
1333  if((errorValue = _commandWrapper("LS\r", CMUCAM4_FS_TIMEOUT)))
1334  {
1335  return errorValue;
1336  }
1337 
1338  if((errorValue = setjmp(_env)))
1339  {
1340  return errorValue;
1341  }
1342 
1343  for(directorySize = 0; 1; directorySize++)
1344  {
1345  _receiveData();
1346 
1347  if((*_resBuffer) == ':')
1348  {
1349  break;
1350  }
1351 
1352  if((pointer != NULL) && (offset <= directorySize) &&
1353  ((directorySize - offset) < ((unsigned long) size)))
1354  {
1355  memset(pointer[directorySize - offset].name,
1356  '\0', CMUCAM4_NAME_LENGTH + 1);
1357  memset(pointer[directorySize - offset].attributes,
1358  '\0', CMUCAM4_ATTR_LENGTH + 1);
1359 
1360  if(sscanf(_resBuffer,
1361  " \"%" CMUCAM4_NAME_LENGTH_STR "c\" "
1362  "%" CMUCAM4_ATTR_LENGTH_STR "c ",
1363  pointer[directorySize - offset].name,
1364  pointer[directorySize - offset].attributes) != 2)
1365  {
1367  }
1368 
1369  pointer[directorySize - offset].size = 0;
1370 
1371  if(strchr(pointer[directorySize - offset].attributes, 'D') == NULL)
1372  {
1373  if(sscanf(_resBuffer,
1374  " \"%*" CMUCAM4_NAME_LENGTH_STR "c\" "
1375  "%*" CMUCAM4_ATTR_LENGTH_STR "c "
1376  "%lu ",
1377  &(pointer[directorySize - offset].size)) != 1)
1378  {
1380  }
1381  }
1382  }
1383  }
1384 
1385  return (long) directorySize; // Will be between 0 and 65,536 entries.
1386 }
1387 
1388 int CMUcam4::makeDirectory(const char * directoryPathAndName)
1389 {
1390  if(directoryPathAndName == NULL)
1391  {
1392  return CMUCAM4_RETURN_FAILURE;
1393  }
1394 
1395  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1396  "MK \"%s\"\r", directoryPathAndName)
1397  < CMUCAM4_CMD_BUFFER_SIZE)
1398  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_FS_TIMEOUT)
1400 }
1401 
1402 int CMUcam4::moveEntry(const char * oldEntryPathAndName,
1403  const char * newEntryPathAndName)
1404 {
1405  if((oldEntryPathAndName == NULL) || (newEntryPathAndName == NULL))
1406  {
1407  return CMUCAM4_RETURN_FAILURE;
1408  }
1409 
1410  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1411  "MV \"%s\" \"%s\"\r", oldEntryPathAndName, newEntryPathAndName)
1412  < CMUCAM4_CMD_BUFFER_SIZE)
1413  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_FS_TIMEOUT)
1415 }
1416 
1417 int CMUcam4::printLine(const char * filePathAndName, const char * textToAppend)
1418 {
1419  if((filePathAndName == NULL) || (textToAppend == NULL))
1420  {
1421  return CMUCAM4_RETURN_FAILURE;
1422  }
1423 
1424  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1425  "PL \"%s\" \"%s\"\r", filePathAndName, textToAppend)
1426  < CMUCAM4_CMD_BUFFER_SIZE)
1427  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_FS_TIMEOUT)
1429 }
1430 
1431 long CMUcam4::filePrint(const char * filePathAndName, uint8_t * buffer,
1432  size_t size, unsigned long offset)
1433 {
1434  int errorValue; unsigned long fileSize;
1435 
1436  if(filePathAndName == NULL)
1437  {
1438  return CMUCAM4_RETURN_FAILURE;
1439  }
1440 
1441  if(snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1442  "PR \"%s\"\r", filePathAndName) >= CMUCAM4_CMD_BUFFER_SIZE)
1443  {
1444  return CMUCAM4_COMMAND_OVERFLOW;
1445  }
1446 
1447  if((errorValue = _commandWrapper(_cmdBuffer, CMUCAM4_FS_TIMEOUT)))
1448  {
1449  return errorValue;
1450  }
1451 
1452  if((errorValue = setjmp(_env)))
1453  {
1454  return errorValue;
1455  }
1456 
1457  _receiveData();
1458 
1459  if(sscanf(_resBuffer, "%lu ", &fileSize) != 1)
1460  {
1462  }
1463 
1464  _readBinary(buffer, size, fileSize, offset);
1465 
1466  _waitForIdle();
1467  return (long) fileSize; // Will be between 0 and 2,147,483,647 bytes.
1468 }
1469 
1470 int CMUcam4::removeEntry(const char * fileOrDirectoryPathAndName)
1471 {
1472  if(fileOrDirectoryPathAndName == NULL)
1473  {
1474  return CMUCAM4_RETURN_FAILURE;
1475  }
1476 
1477  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1478  "RM \"%s\"\r", fileOrDirectoryPathAndName)
1479  < CMUCAM4_CMD_BUFFER_SIZE)
1480  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_FS_TIMEOUT)
1482 }
1483 
1485 {
1486  return _voidCommandWrapper("UM\r", CMUCAM4_FS_TIMEOUT);
1487 }
1488 
1489 /*******************************************************************************
1490 * Image Capture Commands
1491 *******************************************************************************/
1492 
1494 {
1495  return _voidCommandWrapper("DB\r", CMUCAM4_FS_TIMEOUT);
1496 }
1497 
1498 int CMUcam4::dumpFrame(int horizontalResolution, int verticalResolution)
1499 {
1500  return (snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1501  "DF %d %d\r", horizontalResolution, verticalResolution)
1502  < CMUCAM4_CMD_BUFFER_SIZE)
1503  ? _voidCommandWrapper(_cmdBuffer, CMUCAM4_FS_TIMEOUT)
1505 }
1506 
1508 {
1509  int errorValue;
1510 
1511  if(pointer == NULL)
1512  {
1513  return CMUCAM4_RETURN_FAILURE;
1514  }
1515 
1516  if((errorValue = _commandWrapper("SB\r", CMUCAM4_NON_FS_TIMEOUT)))
1517  {
1518  return errorValue;
1519  }
1520 
1521  if((errorValue = setjmp(_env)))
1522  {
1523  return errorValue;
1524  }
1525 
1526  _readBinary(pointer->pixels, CMUCAM4_ID_T_LENGTH, CMUCAM4_ID_T_LENGTH, 0);
1527 
1528  if(_readWithTimeout() != '\r')
1529  {
1531  }
1532 
1533  _waitForIdle();
1534  return CMUCAM4_RETURN_SUCCESS;
1535 }
1536 
1537 int CMUcam4::sendFrame(int horizontalResolution, int verticalResolution,
1538  uint16_t * buffer,
1539  size_t horizonalSize, size_t horizontalOffset,
1540  size_t verticalSize, size_t verticalOffset)
1541 {
1542  int errorValue; int serialBuffer0; int serialBuffer1;
1543  size_t indexX; size_t indexY; size_t resolutionX; size_t resolutionY;
1544 
1545  resolutionX = (CMUCAM4_FRAME_H_RES >> horizontalResolution);
1546  resolutionY = (CMUCAM4_FRAME_V_RES >> verticalResolution);
1547 
1548  if(snprintf(_cmdBuffer, CMUCAM4_CMD_BUFFER_SIZE,
1549  "SF %d %d\r", horizontalResolution, verticalResolution)
1550  >= CMUCAM4_CMD_BUFFER_SIZE)
1551  {
1552  return CMUCAM4_COMMAND_OVERFLOW;
1553  }
1554 
1555  if((errorValue = _commandWrapper(_cmdBuffer, CMUCAM4_NON_FS_TIMEOUT)))
1556  {
1557  return errorValue;
1558  }
1559 
1560  if((errorValue = setjmp(_env)))
1561  {
1562  return errorValue;
1563  }
1564 
1565  for(indexX = 0; indexX < resolutionX; indexX++)
1566  {
1567  _setReadTimeout(CMUCAM4_NON_FS_TIMEOUT);
1568 
1569  _receiveData();
1570 
1571  if((*_resBuffer) == ':')
1572  {
1574  }
1575 
1576  switch(_version)
1577  {
1578  case VERSION_100:
1579  case VERSION_101:
1580 
1581  if(strcmp(_resBuffer, "DAT:") != 0)
1582  {
1584  }
1585 
1586  break;
1587 
1588  case VERSION_102:
1589  case VERSION_103:
1590 
1591  if(strcmp(_resBuffer, "DAT: ") != 0)
1592  {
1594  }
1595 
1596  break;
1597  }
1598 
1599  for(indexY = 0; indexY < resolutionY; indexY++)
1600  {
1601  serialBuffer0 = (_readWithTimeout() & 0xFF);
1602  serialBuffer1 = (_readWithTimeout() & 0xFF);
1603 
1604  if((buffer != NULL) && (horizontalOffset <= indexX) &&
1605  ((indexX - horizontalOffset) < horizonalSize) &&
1606  (verticalOffset <= indexY) &&
1607  ((indexY - verticalOffset) < verticalSize))
1608  {
1609  buffer[((indexY - verticalOffset) * horizonalSize)
1610  + (indexX - horizontalOffset)]
1611  = ((uint16_t) (serialBuffer0 | (serialBuffer1 << 8)));
1612  }
1613  }
1614 
1615  if(_readWithTimeout() != '\r')
1616  {
1618  }
1619  }
1620 
1621  _waitForIdle();
1622  return CMUCAM4_RETURN_SUCCESS;
1623 }
1624 
1625 /*******************************************************************************
1626 * Private Functions
1627 *******************************************************************************/
1628 
1629 int CMUcam4::_voidCommandWrapper(const char * command, unsigned long timeout)
1630 {
1631  int errorValue;
1632 
1633  if((errorValue = _commandWrapper(command, timeout)))
1634  {
1635  return errorValue;
1636  }
1637 
1638  if((errorValue = setjmp(_env)))
1639  {
1640  return errorValue;
1641  }
1642 
1643  _waitForIdle();
1644  return CMUCAM4_RETURN_SUCCESS;
1645 }
1646 
1647 int CMUcam4::_intCommandWrapper(const char * command, unsigned long timeout)
1648 {
1649  int errorValue; int resultValue; int returnValue;
1650 
1651  if((errorValue = _commandWrapper(command, timeout)))
1652  {
1653  return errorValue;
1654  }
1655 
1656  if((errorValue = setjmp(_env)))
1657  {
1658  return errorValue;
1659  }
1660 
1661  _receiveData();
1662  resultValue = (sscanf(_resBuffer, "%d ", &returnValue) == 1);
1663 
1664  _waitForIdle();
1665  return resultValue ? returnValue : CMUCAM4_UNEXPECTED_RESPONCE;
1666 }
1667 
1668 int CMUcam4::_commandWrapper(const char * command, unsigned long timeout)
1669 {
1670  int errorValue;
1671 
1672  if((errorValue = idleCamera()))
1673  {
1674  return errorValue;
1675  }
1676 
1677  if((errorValue = setjmp(_env)))
1678  {
1679  return errorValue;
1680  }
1681 
1682  _setReadTimeout(timeout);
1683  _com.write(command);
1684  _waitForResponce();
1685 
1686  return CMUCAM4_RETURN_SUCCESS;
1687 }
1688 
1689 int CMUcam4::_responceWrapper(char responce)
1690 {
1691  int errorValue;
1692 
1693  if(_state == DEACTIVATED)
1694  {
1695  return CMUCAM4_NOT_ACTIVATED;
1696  }
1697 
1698  if((errorValue = setjmp(_env)))
1699  {
1700  return errorValue;
1701  }
1702 
1703  _setReadTimeout(CMUCAM4_NON_FS_TIMEOUT);
1704 
1705  for(;;)
1706  {
1707  _receiveData();
1708 
1709  if((*_resBuffer) == responce)
1710  {
1711  break;
1712  }
1713 
1714  if((*_resBuffer) == ':')
1715  {
1716  return CMUCAM4_STREAM_END;
1717  }
1718 
1719  if(strcmp(_resBuffer, "F ") == 0)
1720  {
1721  _readBinary(NULL, 0, CMUCAM4_ID_T_LENGTH, 0);
1722 
1723  if(_readWithTimeout() != '\r')
1724  {
1726  }
1727  }
1728  }
1729 
1730  return CMUCAM4_RETURN_SUCCESS;
1731 }
1732 
1733 void CMUcam4::_waitForIdle()
1734 {
1735  for(;;)
1736  {
1737  _readText();
1738 
1739  if(_startsWithString("MSG"))
1740  {
1741  continue; // Throw the message away.
1742  }
1743 
1744  _handleError();
1745 
1746  if((*_resBuffer) != ':')
1747  {
1748  longjmp(_env, CMUCAM4_UNEXPECTED_RESPONCE);
1749  }
1750 
1751  break;
1752  }
1753 }
1754 
1755 void CMUcam4::_waitForResponce()
1756 {
1757  _readText();
1758 
1759  if(strcmp(_resBuffer, "NCK") == 0)
1760  {
1761  _readText();
1762 
1763  if((*_resBuffer) == ':')
1764  {
1765  longjmp(_env, CMUCAM4_NCK_RESPONCE);
1766  }
1767 
1768  longjmp(_env, CMUCAM4_UNEXPECTED_RESPONCE);
1769  }
1770 
1771  if(strcmp(_resBuffer, "ACK") != 0)
1772  {
1773  longjmp(_env, CMUCAM4_UNEXPECTED_RESPONCE);
1774  }
1775 }
1776 
1777 void CMUcam4::_receiveData()
1778 {
1779  for(;;)
1780  {
1781  _readText();
1782 
1783  if(_startsWithString("MSG"))
1784  {
1785  continue; // Throw the message away.
1786  }
1787 
1788  _handleError();
1789 
1790  break;
1791  }
1792 }
1793 
1794 void CMUcam4::_handleError()
1795 {
1796  int errorValue; int sum; size_t index; size_t length;
1797 
1798  if(_startsWithString("ERR"))
1799  {
1800  sum = 0; length = strlen(_resBuffer);
1801 
1802  for(index = 0; index < length; index++)
1803  {
1804  sum += _resBuffer[index];
1805  }
1806 
1807  switch(sum)
1808  {
1809  case CMUCAM4_CAMERA_TIMEOUT_ERROR_SUM:
1810  errorValue = CMUCAM4_CAMERA_TIMEOUT_ERROR; break;
1811 
1812  case CMUCAM4_CAMERA_CONNECTION_ERROR_SUM:
1813  errorValue = CMUCAM4_CAMERA_CONNECTION_ERROR; break;
1814 
1815  case CMUCAM4_DISK_IO_ERROR_SUM:
1816  errorValue = CMUCAM4_DISK_IO_ERROR; break;
1817 
1818  case CMUCAM4_FILE_SYSTEM_CORRUPTED_SUM:
1819  errorValue = CMUCAM4_FILE_SYSTEM_CORRUPTED; break;
1820 
1821  case CMUCAM4_FILE_SYSTEM_UNSUPPORTED_SUM:
1822  errorValue = CMUCAM4_FILE_SYSTEM_UNSUPPORTED; break;
1823 
1824  case CMUCAM4_CARD_NOT_DETECTED_SUM:
1825  errorValue = CMUCAM4_CARD_NOT_DETECTED; break;
1826 
1827  case CMUCAM4_DISK_MAY_BE_FULL_SUM:
1828  errorValue = CMUCAM4_DISK_MAY_BE_FULL; break;
1829 
1830  case CMUCAM4_DIRECTORY_FULL_SUM:
1831  errorValue = CMUCAM4_DIRECTORY_FULL; break;
1832 
1833  case CMUCAM4_EXPECTED_AN_ENTRY_SUM:
1834  errorValue = CMUCAM4_EXPECTED_AN_ENTRY; break;
1835 
1836  case CMUCAM4_EXPECTED_A_DIRECTORY_SUM:
1837  errorValue = CMUCAM4_EXPECTED_A_DIRECTORY; break;
1838 
1839  case CMUCAM4_ENTRY_NOT_ACCESSIBLE_SUM:
1840  errorValue = CMUCAM4_ENTRY_NOT_ACCESSIBLE; break;
1841 
1842  case CMUCAM4_ENTRY_NOT_MODIFIABLE_SUM:
1843  errorValue = CMUCAM4_ENTRY_NOT_MODIFIABLE; break;
1844 
1845  case CMUCAM4_ENTRY_NOT_FOUND_SUM:
1846  errorValue = CMUCAM4_ENTRY_NOT_FOUND; break;
1847 
1848  // For v1.02 firmware and above.
1849  case CMUCAM4_ENTRY_ALREADY_EXISTS_SUM:
1850  errorValue = CMUCAM4_ENTRY_ALREADY_EXISTS; break;
1851 
1852  // For v1.01 firmware and below.
1853  case (CMUCAM4_ENTRY_ALREADY_EXISTS_SUM - 's'):
1854  errorValue = CMUCAM4_ENTRY_ALREADY_EXISTS; break;
1855 
1856  case CMUCAM4_DIRECTORY_LINK_MISSING_SUM:
1857  errorValue = CMUCAM4_DIRECTORY_LINK_MISSING; break;
1858 
1859  case CMUCAM4_DIRECTORY_NOT_EMPTY_SUM:
1860  errorValue = CMUCAM4_DIRECTORY_NOT_EMPTY; break;
1861 
1862  case CMUCAM4_NOT_A_DIRECTORY_SUM:
1863  errorValue = CMUCAM4_NOT_A_DIRECTORY; break;
1864 
1865  case CMUCAM4_NOT_A_FILE_SUM:
1866  errorValue = CMUCAM4_NOT_A_FILE; break;
1867 
1868  default:
1869  errorValue = CMUCAM4_UNEXPECTED_RESPONCE; break;
1870  }
1871 
1872  _readText();
1873 
1874  if((*_resBuffer) == ':')
1875  {
1876  longjmp(_env, errorValue);
1877  }
1878 
1879  longjmp(_env, CMUCAM4_UNEXPECTED_RESPONCE);
1880  }
1881 }
1882 
1883 void CMUcam4::_waitForString(const char * string)
1884 {
1885  size_t index; size_t length = strlen(string);
1886  memset(_resBuffer, '\0', CMUCAM4_RES_BUFFER_SIZE);
1887 
1888  do
1889  {
1890  for(index = 1; index < length; index++)
1891  {
1892  _resBuffer[index - 1] = _resBuffer[index];
1893  }
1894 
1895  _resBuffer[length - 1] = _readWithTimeout();
1896  }
1897  while(strcmp(_resBuffer, string) != 0);
1898 }
1899 
1900 int CMUcam4::_startsWithString(const char * string)
1901 {
1902  return (strncmp(_resBuffer, string, strlen(string)) == 0);
1903 }
1904 
1905 void CMUcam4::_readBinary(uint8_t * buffer, size_t size,
1906  unsigned long packetSize,
1907  unsigned long packetOffset)
1908 {
1909  int serialBuffer; unsigned long serialCounter;
1910 
1911  for(serialCounter = 0; serialCounter < packetSize; serialCounter++)
1912  {
1913  serialBuffer = _readWithTimeout();
1914 
1915  if((buffer != NULL) && (packetOffset <= serialCounter) &&
1916  ((serialCounter - packetOffset) < ((unsigned long) size)))
1917  {
1918  buffer[serialCounter - packetOffset] = ((uint8_t) serialBuffer);
1919  }
1920  }
1921 }
1922 
1923 void CMUcam4::_readText()
1924 {
1925  int serialBuffer; size_t serialCounter = 0;
1926  memset(_resBuffer, '\0', CMUCAM4_RES_BUFFER_SIZE);
1927 
1928  for(;;)
1929  {
1930  serialBuffer = _readWithTimeout();
1931 
1932  if(serialBuffer == '\r')
1933  {
1934  break;
1935  }
1936 
1937  _resBuffer[serialCounter++] = serialBuffer;
1938 
1939  if(serialCounter >= CMUCAM4_RES_BUFFER_SIZE)
1940  {
1941  longjmp(_env, CMUCAM4_RESPONCE_OVERFLOW);
1942  }
1943 
1944  switch(serialCounter)
1945  {
1946  case sizeof(':'):
1947 
1948  if((*_resBuffer) == ':')
1949  {
1950  return; // Found the idle character.
1951  }
1952 
1953  break;
1954 
1955  case (sizeof("F ") - 1):
1956 
1957  if(strcmp(_resBuffer, "F ") == 0)
1958  {
1959  return; // Found type F packet.
1960  }
1961 
1962  break;
1963 
1964  case (sizeof("DAT:") - 1):
1965 
1966  if(_state == ACTIVATED)
1967  {
1968  switch(_version)
1969  {
1970  case VERSION_100:
1971  case VERSION_101:
1972 
1973  if(strcmp(_resBuffer, "DAT:") == 0)
1974  {
1975  return; // Found a old style DAT packet.
1976  }
1977 
1978  break;
1979 
1980  case VERSION_102:
1981  case VERSION_103:
1982 
1983  break;
1984  }
1985  }
1986 
1987  break;
1988 
1989  case (sizeof("DAT: ") - 1):
1990 
1991  if(_state == ACTIVATED)
1992  {
1993  switch(_version)
1994  {
1995  case VERSION_100:
1996  case VERSION_101:
1997 
1998  break;
1999 
2000  case VERSION_102:
2001  case VERSION_103:
2002 
2003  if(strcmp(_resBuffer, "DAT: ") == 0)
2004  {
2005  return; // Found a new style DAT packet.
2006  }
2007 
2008  break;
2009  }
2010  }
2011 
2012  break;
2013 
2014  default: break;
2015  }
2016  }
2017 }
2018 
2019 void CMUcam4::_setReadTimeout(unsigned long timeout)
2020 {
2021  _timeout = timeout;
2022  _milliseconds = _com.milliseconds();
2023 }
2024 
2025 int CMUcam4::_readWithTimeout()
2026 {
2027  do
2028  {
2029  if((_com.milliseconds() - _milliseconds) >= _timeout)
2030  {
2031  longjmp(_env, CMUCAM4_SERIAL_TIMEOUT);
2032  }
2033  }
2034  while(_com.available() == 0);
2035 
2036  return _com.read();
2037 }
2038 
2039 /***************************************************************************//**
2040 * @file
2041 * @par MIT License - TERMS OF USE:
2042 * @n Permission is hereby granted, free of charge, to any person obtaining a
2043 * copy of this software and associated documentation files (the "Software"), to
2044 * deal in the Software without restriction, including without limitation the
2045 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
2046 * sell copies of the Software, and to permit persons to whom the Software is
2047 * furnished to do so, subject to the following conditions:
2048 * @n
2049 * @n The above copyright notice and this permission notice shall be included in
2050 * all copies or substantial portions of the Software.
2051 * @n
2052 * @n THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2053 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2054 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2055 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2056 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2057 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
2058 * SOFTWARE.
2059 *******************************************************************************/