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 WS2812Bs and NeoPixels.
014 *
015 * <p>By default, the timing supports WS2812B LEDs, but is configurable using setBitTiming()
016 *
017 * <p>Only 1 LED driver is currently supported by the roboRIO. However, multiple LED strips can be
018 * connected in series and controlled from the single driver.
019 */
020public class AddressableLED implements AutoCloseable {
021  private final int m_pwmHandle;
022  private final int m_handle;
023
024  /**
025   * Constructs a new driver for a specific port.
026   *
027   * @param port the output port to use (Must be a PWM header, not on MXP)
028   */
029  public AddressableLED(int port) {
030    m_pwmHandle = PWMJNI.initializePWMPort(HAL.getPort((byte) port));
031    m_handle = AddressableLEDJNI.initialize(m_pwmHandle);
032    HAL.report(tResourceType.kResourceType_AddressableLEDs, port + 1);
033  }
034
035  @Override
036  public void close() {
037    if (m_handle != 0) {
038      AddressableLEDJNI.free(m_handle);
039    }
040    if (m_pwmHandle != 0) {
041      PWMJNI.freePWMPort(m_pwmHandle);
042    }
043  }
044
045  /**
046   * Sets the length of the LED strip.
047   *
048   * <p>Calling this is an expensive call, so it's best to call it once, then just update data.
049   *
050   * <p>The max length is 5460 LEDs.
051   *
052   * @param length the strip length
053   */
054  public void setLength(int length) {
055    AddressableLEDJNI.setLength(m_handle, length);
056  }
057
058  /**
059   * Sets the LED output data.
060   *
061   * <p>If the output is enabled, this will start writing the next data cycle. It is safe to call,
062   * even while output is enabled.
063   *
064   * @param buffer the buffer to write
065   */
066  public void setData(AddressableLEDBuffer buffer) {
067    AddressableLEDJNI.setData(m_handle, buffer.m_buffer);
068  }
069
070  /**
071   * Sets the bit timing.
072   *
073   * <p>By default, the driver is set up to drive WS2812Bs, so nothing needs to be set for those.
074   *
075   * @param highTime0NanoSeconds high time for 0 bit (default 400ns)
076   * @param lowTime0NanoSeconds low time for 0 bit (default 900ns)
077   * @param highTime1NanoSeconds high time for 1 bit (default 900ns)
078   * @param lowTime1NanoSeconds low time for 1 bit (default 600ns)
079   */
080  public void setBitTiming(
081      int highTime0NanoSeconds,
082      int lowTime0NanoSeconds,
083      int highTime1NanoSeconds,
084      int lowTime1NanoSeconds) {
085    AddressableLEDJNI.setBitTiming(
086        m_handle,
087        highTime0NanoSeconds,
088        lowTime0NanoSeconds,
089        highTime1NanoSeconds,
090        lowTime1NanoSeconds);
091  }
092
093  /**
094   * Sets the sync time.
095   *
096   * <p>The sync time is the time to hold output so LEDs enable. Default set for WS2812B.
097   *
098   * @param syncTimeMicroSeconds the sync time (default 280us)
099   */
100  public void setSyncTime(int syncTimeMicroSeconds) {
101    AddressableLEDJNI.setSyncTime(m_handle, syncTimeMicroSeconds);
102  }
103
104  /**
105   * Starts the output.
106   *
107   * <p>The output writes continuously.
108   */
109  public void start() {
110    AddressableLEDJNI.start(m_handle);
111  }
112
113  /** Stops the output. */
114  public void stop() {
115    AddressableLEDJNI.stop(m_handle);
116  }
117}