Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 1 | // Copyright (c) FIRST and other WPILib contributors. |
| 2 | // Open Source Software; you can modify and/or share it under the terms of |
| 3 | // the WPILib BSD license file in the root directory of this project. |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 4 | |
| 5 | #include "frc/AddressableLED.h" |
| 6 | |
| 7 | #include <hal/AddressableLED.h> |
| 8 | #include <hal/FRCUsageReporting.h> |
| 9 | #include <hal/HALBase.h> |
| 10 | #include <hal/PWM.h> |
| 11 | #include <hal/Ports.h> |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 12 | #include <wpi/StackTrace.h> |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 13 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 14 | #include "frc/Errors.h" |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 15 | |
| 16 | using namespace frc; |
| 17 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 18 | AddressableLED::AddressableLED(int port) : m_port{port} { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 19 | int32_t status = 0; |
| 20 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 21 | auto stack = wpi::GetStackTrace(1); |
| 22 | m_pwmHandle = |
| 23 | HAL_InitializePWMPort(HAL_GetPort(port), stack.c_str(), &status); |
| 24 | FRC_CheckErrorStatus(status, "Port {}", port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 25 | if (m_pwmHandle == HAL_kInvalidHandle) { |
| 26 | return; |
| 27 | } |
| 28 | |
| 29 | m_handle = HAL_InitializeAddressableLED(m_pwmHandle, &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 30 | FRC_CheckErrorStatus(status, "Port {}", port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 31 | if (m_handle == HAL_kInvalidHandle) { |
| 32 | HAL_FreePWMPort(m_pwmHandle, &status); |
| 33 | } |
| 34 | |
| 35 | HAL_Report(HALUsageReporting::kResourceType_AddressableLEDs, port + 1); |
| 36 | } |
| 37 | |
| 38 | AddressableLED::~AddressableLED() { |
| 39 | HAL_FreeAddressableLED(m_handle); |
| 40 | int32_t status = 0; |
| 41 | HAL_FreePWMPort(m_pwmHandle, &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 42 | FRC_ReportError(status, "Port {}", m_port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 43 | } |
| 44 | |
| 45 | void AddressableLED::SetLength(int length) { |
| 46 | int32_t status = 0; |
| 47 | HAL_SetAddressableLEDLength(m_handle, length, &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 48 | FRC_CheckErrorStatus(status, "Port {} length {}", m_port, length); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 49 | } |
| 50 | |
| 51 | static_assert(sizeof(AddressableLED::LEDData) == sizeof(HAL_AddressableLEDData), |
| 52 | "LED Structs MUST be the same size"); |
| 53 | |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 54 | void AddressableLED::SetData(wpi::span<const LEDData> ledData) { |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 55 | int32_t status = 0; |
| 56 | HAL_WriteAddressableLEDData(m_handle, ledData.begin(), ledData.size(), |
| 57 | &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 58 | FRC_CheckErrorStatus(status, "Port {}", m_port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | void AddressableLED::SetData(std::initializer_list<LEDData> ledData) { |
| 62 | int32_t status = 0; |
| 63 | HAL_WriteAddressableLEDData(m_handle, ledData.begin(), ledData.size(), |
| 64 | &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 65 | FRC_CheckErrorStatus(status, "Port {}", m_port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 66 | } |
| 67 | |
| 68 | void AddressableLED::SetBitTiming(units::nanosecond_t lowTime0, |
| 69 | units::nanosecond_t highTime0, |
| 70 | units::nanosecond_t lowTime1, |
| 71 | units::nanosecond_t highTime1) { |
| 72 | int32_t status = 0; |
| 73 | HAL_SetAddressableLEDBitTiming( |
| 74 | m_handle, lowTime0.to<int32_t>(), highTime0.to<int32_t>(), |
| 75 | lowTime1.to<int32_t>(), highTime1.to<int32_t>(), &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 76 | FRC_CheckErrorStatus(status, "Port {}", m_port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 77 | } |
| 78 | |
| 79 | void AddressableLED::SetSyncTime(units::microsecond_t syncTime) { |
| 80 | int32_t status = 0; |
| 81 | HAL_SetAddressableLEDSyncTime(m_handle, syncTime.to<int32_t>(), &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 82 | FRC_CheckErrorStatus(status, "Port {}", m_port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 83 | } |
| 84 | |
| 85 | void AddressableLED::Start() { |
| 86 | int32_t status = 0; |
| 87 | HAL_StartAddressableLEDOutput(m_handle, &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 88 | FRC_CheckErrorStatus(status, "Port {}", m_port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 89 | } |
| 90 | |
| 91 | void AddressableLED::Stop() { |
| 92 | int32_t status = 0; |
| 93 | HAL_StopAddressableLEDOutput(m_handle, &status); |
Austin Schuh | 812d0d1 | 2021-11-04 20:16:48 -0700 | [diff] [blame^] | 94 | FRC_CheckErrorStatus(status, "Port {}", m_port); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 95 | } |
| 96 | |
| 97 | void AddressableLED::LEDData::SetHSV(int h, int s, int v) { |
Austin Schuh | 1e69f94 | 2020-11-14 15:06:14 -0800 | [diff] [blame] | 98 | SetLED(Color::FromHSV(h, s, v)); |
Brian Silverman | 8fce748 | 2020-01-05 13:18:21 -0800 | [diff] [blame] | 99 | } |