1313 Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
1414 Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
1515 Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
16- Copyright (C) 2009-2013 Jeff Hoefs. All rights reserved.
16+ Copyright (C) 2009-2014 Jeff Hoefs. All rights reserved.
1717
1818 This library is free software; you can redistribute it and/or
1919 modify it under the terms of the GNU Lesser General Public
@@ -83,10 +83,54 @@ signed char queryIndex = -1;
8383unsigned int i2cReadDelayTime = 0 ; // default delay time between i2c read request and Wire.requestFrom()
8484
8585Servo servos[MAX_SERVOS];
86+ byte servoPinMap[TOTAL_PINS];
87+ byte detachedServos[MAX_SERVOS];
88+ byte detachedServoCount = 0 ;
89+ byte servoCount = 0 ;
90+
91+
8692/* ==============================================================================
8793 * FUNCTIONS
8894 *============================================================================*/
8995
96+ void attachServo (byte pin, int minPulse, int maxPulse)
97+ {
98+ if (servoCount < MAX_SERVOS) {
99+ // reuse indexes of detached servos until all have been reallocated
100+ if (detachedServoCount > 0 ) {
101+ servoPinMap[pin] = detachedServos[detachedServoCount - 1 ];
102+ if (detachedServoCount > 0 ) detachedServoCount--;
103+ } else {
104+ servoPinMap[pin] = servoCount;
105+ servoCount++;
106+ }
107+ if (minPulse > 0 && maxPulse > 0 ) {
108+ servos[servoPinMap[pin]].attach (PIN_TO_DIGITAL (pin), minPulse, maxPulse);
109+ } else {
110+ servos[servoPinMap[pin]].attach (PIN_TO_DIGITAL (pin));
111+ }
112+ } else {
113+ Firmata.sendString (" Max servos attached" );
114+ }
115+ }
116+
117+ void detachServo (byte pin)
118+ {
119+ servos[servoPinMap[pin]].detach ();
120+ // if we're detaching the last servo, decrement the count
121+ // otherwise store the index of the detached servo
122+ if (servoPinMap[pin] == servoCount && servoCount > 0 ) {
123+ servoCount--;
124+ } else if (servoCount > 0 ) {
125+ // keep track of detached servos because we want to reuse their indexes
126+ // before incrementing the count of attached servos
127+ detachedServoCount++;
128+ detachedServos[detachedServoCount - 1 ] = servoPinMap[pin];
129+ }
130+
131+ servoPinMap[pin] = 255 ;
132+ }
133+
90134void readAndReportData (byte address, int theRegister, byte numBytes) {
91135 // allow I2C requests that don't require a register read
92136 // for example, some devices using an interrupt pin to signify new data available
@@ -180,8 +224,10 @@ void setPinModeCallback(byte pin, int mode)
180224 // the following if statements should reconfigure the pins properly
181225 disableI2CPins ();
182226 }
183- if (IS_PIN_SERVO (pin) && mode != SERVO && servos[PIN_TO_SERVO (pin)].attached ()) {
184- servos[PIN_TO_SERVO (pin)].detach ();
227+ if (IS_PIN_DIGITAL (pin) && mode != SERVO) {
228+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached ()) {
229+ detachServo (pin);
230+ }
185231 }
186232 if (IS_PIN_ANALOG (pin)) {
187233 reportAnalogCallback (PIN_TO_ANALOG (pin), mode == ANALOG ? 1 : 0 ); // turn on/off reporting
@@ -226,10 +272,12 @@ void setPinModeCallback(byte pin, int mode)
226272 }
227273 break ;
228274 case SERVO:
229- if (IS_PIN_SERVO (pin)) {
275+ if (IS_PIN_DIGITAL (pin)) {
230276 pinConfig[pin] = SERVO;
231- if (!servos[PIN_TO_SERVO (pin)].attached ()) {
232- servos[PIN_TO_SERVO (pin)].attach (PIN_TO_DIGITAL (pin));
277+ if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached ()) {
278+ // pass -1 for min and max pulse values to use default values set
279+ // by Servo library
280+ attachServo (pin, -1 , -1 );
233281 }
234282 }
235283 break ;
@@ -251,8 +299,8 @@ void analogWriteCallback(byte pin, int value)
251299 if (pin < TOTAL_PINS) {
252300 switch (pinConfig[pin]) {
253301 case SERVO:
254- if (IS_PIN_SERVO (pin))
255- servos[PIN_TO_SERVO ( pin) ].write (value);
302+ if (IS_PIN_DIGITAL (pin))
303+ servos[servoPinMap[ pin] ].write (value);
256304 pinState[pin] = value;
257305 break ;
258306 case PWM:
@@ -430,10 +478,11 @@ void sysexCallback(byte command, byte argc, byte *argv)
430478 int minPulse = argv[1 ] + (argv[2 ] << 7 );
431479 int maxPulse = argv[3 ] + (argv[4 ] << 7 );
432480
433- if (IS_PIN_SERVO (pin)) {
434- if (servos[PIN_TO_SERVO (pin)].attached ())
435- servos[PIN_TO_SERVO (pin)].detach ();
436- servos[PIN_TO_SERVO (pin)].attach (PIN_TO_DIGITAL (pin), minPulse, maxPulse);
481+ if (IS_PIN_DIGITAL (pin)) {
482+ if (servoPinMap[pin] < MAX_SERVOS && servos[servoPinMap[pin]].attached ()) {
483+ detachServo (pin);
484+ }
485+ attachServo (pin, minPulse, maxPulse);
437486 setPinModeCallback (pin, SERVO);
438487 }
439488 }
@@ -474,7 +523,7 @@ void sysexCallback(byte command, byte argc, byte *argv)
474523 Firmata.write (PWM);
475524 Firmata.write (8 );
476525 }
477- if (IS_PIN_SERVO (pin)) {
526+ if (IS_PIN_DIGITAL (pin)) {
478527 Firmata.write (SERVO);
479528 Firmata.write (14 );
480529 }
@@ -550,25 +599,32 @@ void systemResetCallback()
550599 if (isI2CEnabled) {
551600 disableI2CPins ();
552601 }
602+
553603 for (byte i=0 ; i < TOTAL_PORTS; i++) {
554604 reportPINs[i] = false ; // by default, reporting off
555605 portConfigInputs[i] = 0 ; // until activated
556606 previousPINs[i] = 0 ;
557607 }
558- // pins with analog capability default to analog input
559- // otherwise, pins default to digital output
608+
560609 for (byte i=0 ; i < TOTAL_PINS; i++) {
610+ // pins with analog capability default to analog input
611+ // otherwise, pins default to digital output
561612 if (IS_PIN_ANALOG (i)) {
562613 // turns off pullup, configures everything
563614 setPinModeCallback (i, ANALOG);
564615 } else {
565616 // sets the output to 0, configures portConfigInputs
566617 setPinModeCallback (i, OUTPUT);
567618 }
619+
620+ servoPinMap[i] = 255 ;
568621 }
569622 // by default, do not report any analog inputs
570623 analogInputsToReport = 0 ;
571624
625+ detachedServoCount = 0 ;
626+ servoCount = 0 ;
627+
572628 /* send digital inputs to set the initial state on the host computer,
573629 * since once in the loop(), this firmware will only send on change */
574630 /*
0 commit comments