/// <summary>
 /// Gets the specified pin from the pin cache. If the specified pin
 /// does not already exist in the cache, it will be cached first,
 /// then returned to the caller.
 /// </summary>
 /// <param name="pin">
 /// The pin to get from the cache.
 /// </param>
 /// <returns>
 /// The cached instance of the specified pin.
 /// </returns>
 public IPCA9685Pin GetPin(IPCA9685Pin pin)
 {
     if (!this._pinCache.Contains(pin))
     {
         this._pinCache.Add(pin);
     }
     return(this._pinCache[this._pinCache.IndexOf(pin)]);
 }
        /// <summary>
        /// Gets the PWM on/off values for the specified pin.
        /// </summary>
        /// <param name="pin">
        /// The pin to get the on/off values for (Channel 0 .. 15).
        /// </param>
        /// <returns>
        /// A tuple containing the on/off PWM values where Item1 contains the
        /// "on" value and Item2 contains the "Off" value.
        /// </returns>
        public Tuple <Int32, Int32> GetPwmOnOffValues(IPCA9685Pin pin)
        {
            if (!this.HasPin(pin))
            {
                throw new ArgumentException("The specified pin does not exist in the pin cache.");
            }

            return(new Tuple <Int32, Int32>(
                       this.GetPin(pin).PwmOnValue,
                       this.GetPin(pin).PwmOffValue
                       ));
        }
		/// <summary>
		/// Initializes a new instance of the <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/>
		/// class with a PCA9685 GPIO provider and pin.
		/// </summary>
		/// <param name="provider">
		/// The PCA9685 GPIO provider.
		/// </param>
		/// <param name="pin">
		/// The PCA9685 pin (channel) the servo is attached to.
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="provider"/> cannot be null. - or -
		/// <paramref name="pin"/> cannot be null.
		/// </exception>
		public PCA9685GpioServoDriver(PCA9685GpioProvider provider, IPCA9685Pin pin) {
			if (provider == null) {
				throw new ArgumentNullException("provider");
			}

			if (pin == null) {
				throw new ArgumentNullException("pin");
			}

			this._provider = provider;
			this._pin = pin;
			this.UpdateResolution();
		}
        /// <summary>
        /// Initializes a new instance of the <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/>
        /// class with a PCA9685 GPIO provider and pin.
        /// </summary>
        /// <param name="provider">
        /// The PCA9685 GPIO provider.
        /// </param>
        /// <param name="pin">
        /// The PCA9685 pin (channel) the servo is attached to.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="provider"/> cannot be null. - or -
        /// <paramref name="pin"/> cannot be null.
        /// </exception>
        public PCA9685GpioServoDriver(PCA9685GpioProvider provider, IPCA9685Pin pin)
        {
            if (provider == null)
            {
                throw new ArgumentNullException("provider");
            }

            if (pin == null)
            {
                throw new ArgumentNullException("pin");
            }

            this._provider = provider;
            this._pin      = pin;
            this.UpdateResolution();
        }
        /// <summary>
        /// Sets the always off.
        /// </summary>
        /// <param name="pin">
        /// The pin to set always off (Channel 0 .. 15).
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pin"/> cannot be null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pin"/> does not exist in the pin cache.
        /// </exception>
        /// <exception cref="InvalidPinModeException">
        /// The specified pin is not in PWM mode.
        /// </exception>
        /// <exception cref="IOException">
        /// Unable to write to the specified channel (pin address).
        /// </exception>
        public void SetAlwaysOff(IPCA9685Pin pin)
        {
            this.ValidatePin(pin, 1, 0);
            Int32 chan = pin.Address;

            try {
                this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_ON_L + 4 * chan), (Byte)0x00 });
                this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_ON_H + 4 * chan), (Byte)0x00 });
                this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_OFF_L + 4 * chan), (Byte)0x00 });
                this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_OFF_H + 4 * chan), (Byte)0x10 });
            }
            catch (IOException ioEx) {
                throw new IOException("Error while trying to write to channel: " + chan.ToString(), ioEx);
            }
            this.CachePinValues(pin, 1, 0);
        }
        /// <summary>
        /// Validates the specified pin and throws an exception if invalid.
        /// </summary>
        /// <param name="pin">
        /// The pin to validate.
        /// </param>
        /// <param name="onPosition">
        /// The PWM value to be considered in an "on" state.
        /// </param>
        /// <param name="offPosition">
        /// The PWM value to be considered in an "off" state.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pin"/> cannot be null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pin"/> does not exist in the pin cache.
        /// </exception>
        /// <exception cref="InvalidPinModeException">
        /// The specified pin is not in PWM mode.
        /// </exception>
        private void ValidatePin(IPCA9685Pin pin, Int32 onPosition, Int32 offPosition)
        {
            if (pin == null)
            {
                throw new ArgumentNullException("pin");
            }

            if (!this.HasPin(pin))
            {
                throw new ArgumentException("The specified pin does not exist in the pin cache.");
            }

            if (pin.Mode != PinMode.PWM)
            {
                String errMsg = "Invalid pin mode [" + Enum.GetName(typeof(PinMode), pin.Mode) +
                                "]; Unable to set PWM value " + onPosition.ToString() + ", " +
                                offPosition.ToString();
                throw new InvalidPinModeException(pin, errMsg);
            }
        }
        /// <summary>
        /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
        /// </summary>
        /// <filterpriority>2</filterpriority>
        /// <remarks>Call <see cref="Dispose"/> when you are finished using the
        /// <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/>. The <see cref="Dispose"/> method leaves
        /// the <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/> in an unusable state. After calling
        /// <see cref="Dispose"/>, you must release all references to the
        /// <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/> so the garbage collector can reclaim the
        /// memory that the <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/> was occupying.</remarks>
        public void Dispose()
        {
            if (this._isDisposed)
            {
                return;
            }

            if (this._provider != null)
            {
                this._provider.Dispose();
                this._provider = null;
            }

            if (this._pin != null)
            {
                this._pin.Dispose();
                this._pin = null;
            }

            this._pos        = 0;
            this._res        = 0;
            this._isDisposed = true;
        }
        /// <summary>
        /// Sets the PWM values for the specified pin. The LEDn_ON and LEDn_OFF
        /// counts can vary from 0 to 4095 max.<br/>
        /// The LEDn_ON and LEDn_OFF count registers should never be programmed
        /// with the same values.<br/><br/>
        /// Because the loading of the LEDn_ON and LEDn_OFF registers is via I2C-bus,
        /// and asynchronous to the internal oscillator, it is best to ensure that
        /// there are no visual artifacts of changing the ON and OFF values. This
        /// is achieved by updating the changes at the end of the LOW cycle.
        /// </summary>
        /// <param name="pin">
        /// The pin to set the PWM values for (Channel 0 .. 15).
        /// </param>
        /// <param name="onPos">
        /// The PWM threshold to consider the pin "on" (value between 0 and 4095).
        /// </param>
        /// <param name="offPos">
        /// The PWM threshold to consider the pin "off" (value between 0 and 4095).
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pin"/> cannot be null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pin"/> does not exist in the pin cache. - or -
        /// <paramref name="onPos"/> and <paramref name="offPos"/> are equal.
        /// </exception>
        /// <exception cref="InvalidPinModeException">
        /// The specified pin is not in PWM mode.
        /// </exception>
        /// <exception cref="IOException">
        /// Unable to write to the specified channel (pin address).
        /// </exception>
        public void SetPWM(IPCA9685Pin pin, Int32 onPos, Int32 offPos)
        {
            this.ValidatePin(pin, onPos, offPos);
            this.ValidatePwmValueInRange(onPos);
            this.ValidatePwmValueInRange(offPos);
            if (onPos == offPos)
            {
                throw new ArgumentException("ON [" + onPos.ToString() + "] and OFF [" + offPos.ToString() + "] values must be different.");
            }

            Int32 chan = pin.Address;

            try {
                this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_ON_L + 4 * chan), (Byte)((Byte)onPos & 0xFF) });
                this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_ON_H + 4 * chan), (Byte)((Byte)onPos >> 8) });
                this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_OFF_L + 4 * chan), (Byte)((Byte)offPos & 0xFF) });
                this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_OFF_H + 4 * chan), (Byte)((Byte)offPos >> 8) });
            }
            catch (IOException ioEx) {
                throw new IOException("Unable to write to channel: " + chan.ToString(), ioEx);
            }

            this.CachePinValues(pin, onPos, offPos);
        }
Example #9
0
		/// <summary>
		/// Sets the always off.
		/// </summary>
		/// <param name="pin">
		/// The pin to set always off (Channel 0 .. 15).
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="pin"/> cannot be null.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// <paramref name="pin"/> does not exist in the pin cache.
		/// </exception>
		/// <exception cref="InvalidPinModeException">
		/// The specified pin is not in PWM mode.
		/// </exception>
		/// <exception cref="IOException">
		/// Unable to write to the specified channel (pin address).
		/// </exception>
		public void SetAlwaysOff(IPCA9685Pin pin) {
			this.ValidatePin(pin, 1, 0);
			Int32 chan = pin.Address;
			try {
				this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_ON_L + 4 * chan), (Byte)0x00 });
				this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_ON_H + 4 * chan), (Byte)0x00 });
				this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_OFF_L + 4 * chan), (Byte)0x00 });
				this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_OFF_H + 4 * chan), (Byte)0x10 });
			}
			catch (IOException ioEx) {
				throw new IOException("Error while trying to write to channel: " + chan.ToString(), ioEx);
			}
			this.CachePinValues(pin, 1, 0);
		}
        /// <summary>
        /// Sets the pulse duration in microseconds.<br/>
        /// Make sure duration doesn't exceed period time (1,000,000/freq)!
        /// </summary>
        /// <param name="pin">
        /// The pin to set the pulse duration for (Channel 0 .. 15).
        /// </param>
        /// <param name="duration">
        /// Pulse duration in microseconds.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="pin"/> cannot be null.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// <paramref name="pin"/> does not exist in the pin cache.
        /// </exception>
        /// <exception cref="InvalidPinModeException">
        /// The specified pin is not in PWM mode.
        /// </exception>
        /// <exception cref="IOException">
        /// Unable to write to the specified channel (pin address).
        /// </exception>
        public void SetPWM(IPCA9685Pin pin, Int32 duration)
        {
            Int32 offPos = this.CalcOffPosForPulseDuration(duration);

            this.SetPWM(pin, duration);
        }
 /// <summary>
 /// Caches the pin values.
 /// </summary>
 /// <param name="pin">
 /// The pin to cache the on/off values for.
 /// </param>
 /// <param name="onPosition">
 /// The PWM threshold to consider the pin "on".
 /// </param>
 /// <param name="offPosition">
 /// The PWM threshold to consider the pin "off".
 /// </param>
 private void CachePinValues(IPCA9685Pin pin, Int32 onPosition, Int32 offPosition)
 {
     this.GetPin(pin).PwmOnValue  = onPosition;
     this.GetPin(pin).PwmOffValue = offPosition;
 }
 /// <summary>
 /// Determines whether this instance has pin the specified pin
 /// in the internal pin cache.
 /// </summary>
 /// <param name="pin">
 /// The pin to check for.
 /// </param>
 /// <returns>
 /// <c>true</c> if this instance has pin the specified pin; otherwise, <c>false</c>.
 /// </returns>
 public Boolean HasPin(IPCA9685Pin pin)
 {
     return(this._pinCache.Contains(pin));
 }
		/// <summary>
		/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
		/// </summary>
		/// <filterpriority>2</filterpriority>
		/// <remarks>Call <see cref="Dispose"/> when you are finished using the
		/// <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/>. The <see cref="Dispose"/> method leaves
		/// the <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/> in an unusable state. After calling
		/// <see cref="Dispose"/>, you must release all references to the
		/// <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/> so the garbage collector can reclaim the
		/// memory that the <see cref="CyrusBuilt.MonoPi.Components.Servos.PCA9685GpioServoDriver"/> was occupying.</remarks>
		public void Dispose() {
			if (this._isDisposed) {
				return;
			}

			if (this._provider != null) {
				this._provider.Dispose();
				this._provider = null;
			}

			if (this._pin != null) {
				this._pin.Dispose();
				this._pin = null;
			}

			this._pos = 0;
			this._res = 0;
			this._isDisposed = true;
		}
Example #14
0
		/// <summary>
		/// Gets the PWM on/off values for the specified pin.
		/// </summary>
		/// <param name="pin">
		/// The pin to get the on/off values for (Channel 0 .. 15).
		/// </param>
		/// <returns>
		/// A tuple containing the on/off PWM values where Item1 contains the
		/// "on" value and Item2 contains the "Off" value.
		/// </returns>
		public Tuple<Int32, Int32> GetPwmOnOffValues(IPCA9685Pin pin) {
			if (!this.HasPin(pin)) {
				throw new ArgumentException("The specified pin does not exist in the pin cache.");
			}

			return new Tuple<Int32, Int32>(
				this.GetPin(pin).PwmOnValue,
				this.GetPin(pin).PwmOffValue
			);
		}
Example #15
0
		/// <summary>
		/// Sets the pulse duration in microseconds.<br/>
		/// Make sure duration doesn't exceed period time (1,000,000/freq)!
		/// </summary>
		/// <param name="pin">
		/// The pin to set the pulse duration for (Channel 0 .. 15).
		/// </param>
		/// <param name="duration">
		/// Pulse duration in microseconds.
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="pin"/> cannot be null.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// <paramref name="pin"/> does not exist in the pin cache.
		/// </exception>
		/// <exception cref="InvalidPinModeException">
		/// The specified pin is not in PWM mode.
		/// </exception>
		/// <exception cref="IOException">
		/// Unable to write to the specified channel (pin address).
		/// </exception>
		public void SetPWM(IPCA9685Pin pin, Int32 duration) {
			Int32 offPos = this.CalcOffPosForPulseDuration(duration);
			this.SetPWM(pin, duration);
		}
Example #16
0
		/// <summary>
		/// Sets the PWM values for the specified pin. The LEDn_ON and LEDn_OFF
		/// counts can vary from 0 to 4095 max.<br/>
		/// The LEDn_ON and LEDn_OFF count registers should never be programmed
		/// with the same values.<br/><br/>
		/// Because the loading of the LEDn_ON and LEDn_OFF registers is via I2C-bus,
		/// and asynchronous to the internal oscillator, it is best to ensure that
		/// there are no visual artifacts of changing the ON and OFF values. This
		/// is achieved by updating the changes at the end of the LOW cycle.
		/// </summary>
		/// <param name="pin">
		/// The pin to set the PWM values for (Channel 0 .. 15).
		/// </param>
		/// <param name="onPos">
		/// The PWM threshold to consider the pin "on" (value between 0 and 4095).
		/// </param>
		/// <param name="offPos">
		/// The PWM threshold to consider the pin "off" (value between 0 and 4095).
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="pin"/> cannot be null.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// <paramref name="pin"/> does not exist in the pin cache. - or -
		/// <paramref name="onPos"/> and <paramref name="offPos"/> are equal.
		/// </exception>
		/// <exception cref="InvalidPinModeException">
		/// The specified pin is not in PWM mode.
		/// </exception>
		/// <exception cref="IOException">
		/// Unable to write to the specified channel (pin address).
		/// </exception>
		public void SetPWM(IPCA9685Pin pin, Int32 onPos, Int32 offPos) {
			this.ValidatePin(pin, onPos, offPos);
			this.ValidatePwmValueInRange(onPos);
			this.ValidatePwmValueInRange(offPos);
			if (onPos == offPos) {
				throw new ArgumentException("ON [" + onPos.ToString() + "] and OFF [" + offPos.ToString() + "] values must be different.");
			}

			Int32 chan = pin.Address;
			try {
				this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_ON_L + 4 * chan), (Byte)((Byte)onPos & 0xFF) });
				this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_ON_H + 4 * chan), (Byte)((Byte)onPos >> 8) });
				this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_OFF_L + 4 * chan), (Byte)((Byte)offPos & 0xFF) });
				this._busDevice.WriteBytes(this._busAddr, new Byte[] { (Byte)(PCA9685_LED0_OFF_H + 4 * chan), (Byte)((Byte)offPos >> 8) });
			}
			catch (IOException ioEx) {
				throw new IOException("Unable to write to channel: " + chan.ToString(), ioEx);
			}

			this.CachePinValues(pin, onPos, offPos);
		}
Example #17
0
		/// <summary>
		/// Caches the pin values.
		/// </summary>
		/// <param name="pin">
		/// The pin to cache the on/off values for.
		/// </param>
		/// <param name="onPosition">
		/// The PWM threshold to consider the pin "on".
		/// </param>
		/// <param name="offPosition">
		/// The PWM threshold to consider the pin "off".
		/// </param>
		private void CachePinValues(IPCA9685Pin pin, Int32 onPosition, Int32 offPosition) {
			this.GetPin(pin).PwmOnValue = onPosition;
			this.GetPin(pin).PwmOffValue = offPosition;
		}
Example #18
0
		/// <summary>
		/// Validates the specified pin and throws an exception if invalid.
		/// </summary>
		/// <param name="pin">
		/// The pin to validate.
		/// </param>
		/// <param name="onPosition">
		/// The PWM value to be considered in an "on" state.
		/// </param>
		/// <param name="offPosition">
		/// The PWM value to be considered in an "off" state.
		/// </param>
		/// <exception cref="ArgumentNullException">
		/// <paramref name="pin"/> cannot be null.
		/// </exception>
		/// <exception cref="ArgumentException">
		/// <paramref name="pin"/> does not exist in the pin cache.
		/// </exception>
		/// <exception cref="InvalidPinModeException">
		/// The specified pin is not in PWM mode.
		/// </exception>
		private void ValidatePin(IPCA9685Pin pin, Int32 onPosition, Int32 offPosition) {
			if (pin == null) {
				throw new ArgumentNullException("pin");
			}

			if (!this.HasPin(pin)) {
				throw new ArgumentException("The specified pin does not exist in the pin cache.");
			}

			if (pin.Mode != PinMode.PWM) {
				String errMsg = "Invalid pin mode [" + Enum.GetName(typeof(PinMode), pin.Mode) +
				                "]; Unable to set PWM value " + onPosition.ToString() + ", " +
								offPosition.ToString();
				throw new InvalidPinModeException(pin, errMsg);
			}
		}
Example #19
0
		/// <summary>
		/// Determines whether this instance has pin the specified pin
		/// in the internal pin cache.
		/// </summary>
		/// <param name="pin">
		/// The pin to check for.
		/// </param>
		/// <returns>
		/// <c>true</c> if this instance has pin the specified pin; otherwise, <c>false</c>.
		/// </returns>
		public Boolean HasPin(IPCA9685Pin pin) {
			return this._pinCache.Contains(pin);
		}
Example #20
0
		/// <summary>
		/// Gets the specified pin from the pin cache. If the specified pin
		/// does not already exist in the cache, it will be cached first,
		/// then returned to the caller.
		/// </summary>
		/// <param name="pin">
		/// The pin to get from the cache.
		/// </param>
		/// <returns>
		/// The cached instance of the specified pin.
		/// </returns>
		public IPCA9685Pin GetPin(IPCA9685Pin pin) {
			if (!this._pinCache.Contains(pin)) {
				this._pinCache.Add(pin);
			}
			return this._pinCache[this._pinCache.IndexOf(pin)];
		}