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.simulation;
006
007import edu.wpi.first.hal.simulation.AddressableLEDDataJNI;
008import edu.wpi.first.hal.simulation.ConstBufferCallback;
009import edu.wpi.first.hal.simulation.NotifyCallback;
010import edu.wpi.first.wpilibj.AddressableLED;
011import java.util.NoSuchElementException;
012
013/** Class to control a simulated addressable LED. */
014public class AddressableLEDSim {
015  private final int m_index;
016
017  /** Constructs for the first addressable LED. */
018  public AddressableLEDSim() {
019    m_index = 0;
020  }
021
022  /**
023   * Constructs from an AddressableLED object.
024   *
025   * @param addressableLED AddressableLED to simulate
026   */
027  @SuppressWarnings("PMD.UnusedFormalParameter")
028  public AddressableLEDSim(AddressableLED addressableLED) {
029    // there is only support for a single AddressableLED, so no lookup
030    m_index = 0;
031  }
032
033  private AddressableLEDSim(int index) {
034    m_index = index;
035  }
036
037  /**
038   * Creates an AddressableLEDSim for a PWM channel.
039   *
040   * @param pwmChannel PWM channel
041   * @return Simulated object
042   * @throws NoSuchElementException if no AddressableLED is configured for that channel
043   */
044  public static AddressableLEDSim createForChannel(int pwmChannel) {
045    int index = AddressableLEDDataJNI.findForChannel(pwmChannel);
046    if (index < 0) {
047      throw new NoSuchElementException("no addressable LED found for PWM channel " + pwmChannel);
048    }
049    return new AddressableLEDSim(index);
050  }
051
052  /**
053   * Creates an AddressableLEDSim for a simulated index. The index is incremented for each simulated
054   * AddressableLED.
055   *
056   * @param index simulator index
057   * @return Simulated object
058   */
059  public static AddressableLEDSim createForIndex(int index) {
060    return new AddressableLEDSim(index);
061  }
062
063  /**
064   * Register a callback on the Initialized property.
065   *
066   * @param callback the callback that will be called whenever the Initialized property is changed
067   * @param initialNotify if true, the callback will be run on the initial value
068   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
069   *     this object so GC doesn't cancel the callback.
070   */
071  public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
072    int uid = AddressableLEDDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
073    return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelInitializedCallback);
074  }
075
076  /**
077   * Check if initialized.
078   *
079   * @return true if initialized
080   */
081  public boolean getInitialized() {
082    return AddressableLEDDataJNI.getInitialized(m_index);
083  }
084
085  /**
086   * Change the Initialized value of the LED strip.
087   *
088   * @param initialized the new value
089   */
090  public void setInitialized(boolean initialized) {
091    AddressableLEDDataJNI.setInitialized(m_index, initialized);
092  }
093
094  /**
095   * Register a callback on the output port.
096   *
097   * @param callback the callback that will be called whenever the output port is changed
098   * @param initialNotify if true, the callback will be run on the initial value
099   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
100   *     this object so GC doesn't cancel the callback.
101   */
102  public CallbackStore registerOutputPortCallback(NotifyCallback callback, boolean initialNotify) {
103    int uid = AddressableLEDDataJNI.registerOutputPortCallback(m_index, callback, initialNotify);
104    return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelOutputPortCallback);
105  }
106
107  /**
108   * Get the output port.
109   *
110   * @return the output port
111   */
112  public int getOutputPort() {
113    return AddressableLEDDataJNI.getOutputPort(m_index);
114  }
115
116  /**
117   * Change the output port.
118   *
119   * @param outputPort the new output port
120   */
121  public void setOutputPort(int outputPort) {
122    AddressableLEDDataJNI.setOutputPort(m_index, outputPort);
123  }
124
125  /**
126   * Register a callback on the length.
127   *
128   * @param callback the callback that will be called whenever the length is changed
129   * @param initialNotify if true, the callback will be run on the initial value
130   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
131   *     this object so GC doesn't cancel the callback.
132   */
133  public CallbackStore registerLengthCallback(NotifyCallback callback, boolean initialNotify) {
134    int uid = AddressableLEDDataJNI.registerLengthCallback(m_index, callback, initialNotify);
135    return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelLengthCallback);
136  }
137
138  /**
139   * Get the length of the LED strip.
140   *
141   * @return the length
142   */
143  public int getLength() {
144    return AddressableLEDDataJNI.getLength(m_index);
145  }
146
147  /**
148   * Change the length of the LED strip.
149   *
150   * @param length the new value
151   */
152  public void setLength(int length) {
153    AddressableLEDDataJNI.setLength(m_index, length);
154  }
155
156  /**
157   * Register a callback on whether the LEDs are running.
158   *
159   * @param callback the callback that will be called whenever the LED state is changed
160   * @param initialNotify if true, the callback will be run on the initial value
161   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
162   *     this object so GC doesn't cancel the callback.
163   */
164  public CallbackStore registerRunningCallback(NotifyCallback callback, boolean initialNotify) {
165    int uid = AddressableLEDDataJNI.registerRunningCallback(m_index, callback, initialNotify);
166    return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelRunningCallback);
167  }
168
169  /**
170   * Check if the LEDs are running.
171   *
172   * @return true if they are
173   */
174  public boolean getRunning() {
175    return AddressableLEDDataJNI.getRunning(m_index);
176  }
177
178  /**
179   * Change whether the LEDs are active.
180   *
181   * @param running the new value
182   */
183  public void setRunning(boolean running) {
184    AddressableLEDDataJNI.setRunning(m_index, running);
185  }
186
187  /**
188   * Register a callback on the LED data.
189   *
190   * @param callback the callback that will be called whenever the LED data is changed
191   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
192   *     this object so GC doesn't cancel the callback.
193   */
194  public CallbackStore registerDataCallback(ConstBufferCallback callback) {
195    int uid = AddressableLEDDataJNI.registerDataCallback(m_index, callback);
196    return new CallbackStore(m_index, uid, AddressableLEDDataJNI::cancelDataCallback);
197  }
198
199  /**
200   * Get the LED data.
201   *
202   * @return the LED data
203   */
204  public byte[] getData() {
205    return AddressableLEDDataJNI.getData(m_index);
206  }
207
208  /**
209   * Change the LED data.
210   *
211   * @param data the new data
212   */
213  public void setData(byte[] data) {
214    AddressableLEDDataJNI.setData(m_index, data);
215  }
216
217  /** Reset all simulation data for this LED object. */
218  public void resetData() {
219    AddressableLEDDataJNI.resetData(m_index);
220  }
221}