001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj; 006 007import edu.wpi.first.hal.AddressableLEDJNI; 008import edu.wpi.first.hal.FRCNetComm.tResourceType; 009import edu.wpi.first.hal.HAL; 010import edu.wpi.first.hal.PWMJNI; 011 012/** 013 * A class for driving addressable LEDs, such as WS2812B, WS2815, and NeoPixels. 014 * 015 * <p>By default, the timing supports WS2812B and WS2815 LEDs, but is configurable using {@link 016 * #setBitTiming(int, int, int, int)} 017 * 018 * <p>Some LEDs use a different color order than the default GRB. The color order is configurable 019 * using {@link #setColorOrder(ColorOrder)}. 020 * 021 * <p>Only 1 LED driver is currently supported by the roboRIO. However, multiple LED strips can be 022 * connected in series and controlled from the single driver. 023 */ 024public class AddressableLED implements AutoCloseable { 025 /** Order that color data is sent over the wire. */ 026 public enum ColorOrder { 027 /** RGB order. */ 028 kRGB(AddressableLEDJNI.COLOR_ORDER_RGB), 029 /** RBG order. */ 030 kRBG(AddressableLEDJNI.COLOR_ORDER_RBG), 031 /** BGR order. */ 032 kBGR(AddressableLEDJNI.COLOR_ORDER_BGR), 033 /** BRG order. */ 034 kBRG(AddressableLEDJNI.COLOR_ORDER_BRG), 035 /** GBR order. */ 036 kGBR(AddressableLEDJNI.COLOR_ORDER_GBR), 037 /** GRB order. This is the default order. */ 038 kGRB(AddressableLEDJNI.COLOR_ORDER_GRB); 039 040 /** The native value for this ColorOrder. */ 041 public final int value; 042 043 ColorOrder(int value) { 044 this.value = value; 045 } 046 047 /** 048 * Gets a color order from an int value. 049 * 050 * @param value int value 051 * @return color order 052 */ 053 public ColorOrder fromValue(int value) { 054 return switch (value) { 055 case AddressableLEDJNI.COLOR_ORDER_RBG -> kRBG; 056 case AddressableLEDJNI.COLOR_ORDER_BGR -> kBGR; 057 case AddressableLEDJNI.COLOR_ORDER_BRG -> kBRG; 058 case AddressableLEDJNI.COLOR_ORDER_GRB -> kGRB; 059 case AddressableLEDJNI.COLOR_ORDER_GBR -> kGBR; 060 case AddressableLEDJNI.COLOR_ORDER_RGB -> kRGB; 061 default -> kGRB; 062 }; 063 } 064 } 065 066 private final int m_pwmHandle; 067 private final int m_handle; 068 069 /** 070 * Constructs a new driver for a specific port. 071 * 072 * @param port the output port to use (Must be a PWM header, not on MXP) 073 */ 074 public AddressableLED(int port) { 075 m_pwmHandle = PWMJNI.initializePWMPort(HAL.getPort((byte) port)); 076 m_handle = AddressableLEDJNI.initialize(m_pwmHandle); 077 HAL.report(tResourceType.kResourceType_AddressableLEDs, port + 1); 078 } 079 080 @Override 081 public void close() { 082 if (m_handle != 0) { 083 AddressableLEDJNI.free(m_handle); 084 } 085 if (m_pwmHandle != 0) { 086 PWMJNI.freePWMPort(m_pwmHandle); 087 } 088 } 089 090 /** 091 * Sets the color order for this AddressableLED. The default order is GRB. 092 * 093 * <p>This will take effect on the next call to {@link #setData(AddressableLEDBuffer)}. 094 * 095 * @param order the color order 096 */ 097 public void setColorOrder(ColorOrder order) { 098 AddressableLEDJNI.setColorOrder(m_handle, order.value); 099 } 100 101 /** 102 * Sets the length of the LED strip. 103 * 104 * <p>Calling this is an expensive call, so it's best to call it once, then just update data. 105 * 106 * <p>The max length is 5460 LEDs. 107 * 108 * @param length the strip length 109 */ 110 public void setLength(int length) { 111 AddressableLEDJNI.setLength(m_handle, length); 112 } 113 114 /** 115 * Sets the LED output data. 116 * 117 * <p>If the output is enabled, this will start writing the next data cycle. It is safe to call, 118 * even while output is enabled. 119 * 120 * @param buffer the buffer to write 121 */ 122 public void setData(AddressableLEDBuffer buffer) { 123 AddressableLEDJNI.setData(m_handle, buffer.m_buffer); 124 } 125 126 /** 127 * Sets the bit timing. 128 * 129 * <p>By default, the driver is set up to drive WS2812B and WS2815, so nothing needs to be set for 130 * those. 131 * 132 * @param highTime0NanoSeconds high time for 0 bit (default 400ns) 133 * @param lowTime0NanoSeconds low time for 0 bit (default 900ns) 134 * @param highTime1NanoSeconds high time for 1 bit (default 900ns) 135 * @param lowTime1NanoSeconds low time for 1 bit (default 600ns) 136 */ 137 public void setBitTiming( 138 int highTime0NanoSeconds, 139 int lowTime0NanoSeconds, 140 int highTime1NanoSeconds, 141 int lowTime1NanoSeconds) { 142 AddressableLEDJNI.setBitTiming( 143 m_handle, 144 highTime0NanoSeconds, 145 lowTime0NanoSeconds, 146 highTime1NanoSeconds, 147 lowTime1NanoSeconds); 148 } 149 150 /** 151 * Sets the sync time. 152 * 153 * <p>The sync time is the time to hold output so LEDs enable. Default set for WS2812B and WS2815. 154 * 155 * @param syncTimeMicroSeconds the sync time (default 280us) 156 */ 157 public void setSyncTime(int syncTimeMicroSeconds) { 158 AddressableLEDJNI.setSyncTime(m_handle, syncTimeMicroSeconds); 159 } 160 161 /** 162 * Starts the output. 163 * 164 * <p>The output writes continuously. 165 */ 166 public void start() { 167 AddressableLEDJNI.start(m_handle); 168 } 169 170 /** Stops the output. */ 171 public void stop() { 172 AddressableLEDJNI.stop(m_handle); 173 } 174}