/// <summary> /// Creates an instance and reads current values. /// </summary> /// <remarks> /// <para> /// The required mode bits are set, but the device state and PWM values unchanged (supporting recovery). /// Initializing without restart allows the caller decide whether to recover or reset the device. /// Before starting any output be sure to check the <see cref="INavioPwmDevice.Frequency"/>. /// </para> /// <para> /// To start with new settings, call <see cref="Reset"/> then set <see cref="Enabled"/>. /// </para> /// </remarks> public Navio1LedPwmDevice() { try { // Initialize members _pwmChannels = new PwmPulse[PwmChannelCount]; _pwmChannelsReadOnly = new ReadOnlyCollection <PwmPulse>(_pwmChannels); // Connect to hardware _device = new Pca9685Device(I2cControllerIndex, ChipNumber, ExternalClockSpeed); _enablePin = GpioExtensions.Connect(GpioControllerIndex, OutputEnableGpioPin, GpioPinDriveMode.Output, GpioSharingMode.Exclusive); // Read properties Read(); } catch { // Close devices in case partially initialized _device?.Dispose(); _enablePin?.Dispose(); // Continue error throw; } }
/// <summary> /// Sets a single channel value. /// </summary> void INavioPwmDevice.SetChannel(int number, PwmPulse value) { // Thread-safe lock lock (_lock) { // Validate if (number < 1 || number > PwmChannelCount) { throw new ArgumentOutOfRangeException(nameof(number)); } var index = number - 1; // Check frequency matches (no per-channel frequency on this device) if (value.Frequency != _device.Frequency) { throw new ArgumentOutOfRangeException(nameof(value.Frequency)); } // Do nothing when unchanged var oldValue = _pwmChannels[index]; if (value == oldValue) { return; } // Write new value _device.WriteChannelMs(PwmChannelIndex + index, value.Width); // Update property _pwmChannels[index] = value; } }
/// <summary> /// Reads the PWM channels from the device then updates the related properties. /// </summary> void INavioPwmDevice.Read() { // Thread-safe lock lock (_lock) { // Read channels together (BGR ordered) var channels = _device.ReadChannels(PwmChannelIndex, PwmChannelCount); // Update channel properties var frequency = _device.Frequency; for (int index = 0; index < PwmChannelCount; index++) { var widthTicks = channels[index].Width; var widthMs = Pca9685ChannelValue.CalculateWidthMs(frequency, widthTicks); _pwmChannels[index] = PwmPulse.FromWidth(frequency, widthMs); } } }
/// <summary> /// Reads the LED & PWM channels from the device then updates the related properties. /// </summary> public void Read() { // Thread-safe lock lock (_lock) { // Read all PWM and LED channels _device.ReadAll(); // Update LED properties _ledRed = ~_device.Channels[LedRedChannelIndex].Width & 0xfff; _ledGreen = ~_device.Channels[LedGreenChannelIndex].Width & 0xfff; _ledBlue = ~_device.Channels[LedGreenChannelIndex].Width & 0xfff; // Update PWM properties var frequency = _device.Frequency; for (int index = 0, pwmIndex = PwmChannelIndex; index < PwmChannelCount; index++, pwmIndex++) { var widthTicks = _device.Channels[pwmIndex].Width; var widthMs = Pca9685ChannelValue.CalculateWidthMs(frequency, widthTicks); _pwmChannels[index] = PwmPulse.FromWidth(frequency, widthMs); } } }