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