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