/// <summary> /// Sets multiple channel values at once. /// </summary> void INavioPwmDevice.SetChannels(int number, IList <PwmPulse> values, int count) { // Thread-safe lock lock (_lock) { // Validate if (number < 1 || number > PwmChannelCount) { throw new ArgumentOutOfRangeException(nameof(number)); } if (values == null) { throw new ArgumentNullException(nameof(values)); } if (count < 1 || number + count > PwmChannelCount) { throw new ArgumentOutOfRangeException(nameof(count)); } // Build device values, check frequency and detect change var changed = false; var channelValues = new List <Pca9685ChannelValue>(); for (var index = 0; index < count; index++) { // Get value and convert to channel value var value = values[index]; channelValues.Add(Pca9685ChannelValue.FromWidthMs(value.Width, value.Frequency, 0)); // Check frequency if (value.Frequency != _device.Frequency) { throw new ArgumentOutOfRangeException(nameof(value.Frequency)); } // Check value var oldValue = _pwmChannels[number + index - 1]; if (value != oldValue) { changed = true; } } // Do nothing when unchanged if (!changed) { return; } // Write new value _device.WriteChannels(PwmChannelIndex + number - 1, channelValues); // Update properties for (var index = 0; index < count; index++) { _pwmChannels[index] = values[index]; } } }
/// <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> /// Sets the LED <see cref="INavioLedDevice.Red"/>, <see cref="INavioLedDevice.Green"/> and /// <see cref="INavioLedDevice.Blue"/> values together (in one operation). /// </summary> /// <param name="red">Red value in the range 0-<see cref="INavioLedDevice.MaximumValue"/>.</param> /// <param name="green">Green value in the range 0-<see cref="INavioLedDevice.MaximumValue"/>.</param> /// <param name="blue">Blue value in the range 0-<see cref="INavioLedDevice.MaximumValue"/>.</param> void INavioLedDevice.SetRgb(int red, int green, int blue) { // Thread-safe lock lock (_lock) { // Validate if (red < 0 || red > Pca9685ChannelValue.Maximum) { throw new ArgumentOutOfRangeException(nameof(red)); } if (green < 0 || green > Pca9685ChannelValue.Maximum) { throw new ArgumentOutOfRangeException(nameof(green)); } if (blue < 0 || blue > Pca9685ChannelValue.Maximum) { throw new ArgumentOutOfRangeException(nameof(blue)); } // Invert values var inverseRed = ~red & 0x0fff; var inverseGreen = ~green & 0x0fff; var inverseBlue = ~blue & 0x0fff; // Set all three LED channels together (BGR order) var values = new Pca9685ChannelValue[] { Pca9685ChannelValue.FromWidth(inverseBlue), Pca9685ChannelValue.FromWidth(inverseGreen), Pca9685ChannelValue.FromWidth(inverseRed) }; _device.WriteChannels(0, values); // Update cached values _ledBlue = blue; _ledGreen = green; _ledRed = red; } }
/// <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); } } }