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.EncoderDataJNI;
008import edu.wpi.first.hal.simulation.NotifyCallback;
009import edu.wpi.first.wpilibj.Encoder;
010import java.util.NoSuchElementException;
011
012/** Class to control a simulated encoder. */
013public class EncoderSim {
014  private final int m_index;
015
016  /**
017   * Constructs from an Encoder object.
018   *
019   * @param encoder Encoder to simulate
020   */
021  public EncoderSim(Encoder encoder) {
022    m_index = encoder.getFPGAIndex();
023  }
024
025  private EncoderSim(int index) {
026    m_index = index;
027  }
028
029  /**
030   * Creates an EncoderSim for a digital input channel. Encoders take two channels, so either one
031   * may be specified.
032   *
033   * @param channel digital input channel
034   * @return Simulated object
035   * @throws NoSuchElementException if no Encoder is configured for that channel
036   */
037  public static EncoderSim createForChannel(int channel) {
038    int index = EncoderDataJNI.findForChannel(channel);
039    if (index < 0) {
040      throw new NoSuchElementException("no encoder found for channel " + channel);
041    }
042    return new EncoderSim(index);
043  }
044
045  /**
046   * Creates an EncoderSim for a simulated index. The index is incremented for each simulated
047   * Encoder.
048   *
049   * @param index simulator index
050   * @return Simulated object
051   */
052  public static EncoderSim createForIndex(int index) {
053    return new EncoderSim(index);
054  }
055
056  /**
057   * Register a callback on the Initialized property of the encoder.
058   *
059   * @param callback the callback that will be called whenever the Initialized property is changed
060   * @param initialNotify if true, the callback will be run on the initial value
061   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
062   *     this object so GC doesn't cancel the callback.
063   */
064  public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
065    int uid = EncoderDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
066    return new CallbackStore(m_index, uid, EncoderDataJNI::cancelInitializedCallback);
067  }
068
069  /**
070   * Read the Initialized value of the encoder.
071   *
072   * @return true if initialized
073   */
074  public boolean getInitialized() {
075    return EncoderDataJNI.getInitialized(m_index);
076  }
077
078  /**
079   * Change the Initialized value of the encoder.
080   *
081   * @param initialized the new value
082   */
083  public void setInitialized(boolean initialized) {
084    EncoderDataJNI.setInitialized(m_index, initialized);
085  }
086
087  /**
088   * Register a callback on the count property of the encoder.
089   *
090   * @param callback the callback that will be called whenever the count property is changed
091   * @param initialNotify if true, the callback will be run on the initial value
092   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
093   *     this object so GC doesn't cancel the callback.
094   */
095  public CallbackStore registerCountCallback(NotifyCallback callback, boolean initialNotify) {
096    int uid = EncoderDataJNI.registerCountCallback(m_index, callback, initialNotify);
097    return new CallbackStore(m_index, uid, EncoderDataJNI::cancelCountCallback);
098  }
099
100  /**
101   * Read the count of the encoder.
102   *
103   * @return the count
104   */
105  public int getCount() {
106    return EncoderDataJNI.getCount(m_index);
107  }
108
109  /**
110   * Change the count of the encoder.
111   *
112   * @param count the new count
113   */
114  public void setCount(int count) {
115    EncoderDataJNI.setCount(m_index, count);
116  }
117
118  /**
119   * Register a callback on the period of the encoder.
120   *
121   * @param callback the callback that will be called whenever the period is changed
122   * @param initialNotify if true, the callback will be run on the initial value
123   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
124   *     this object so GC doesn't cancel the callback.
125   */
126  public CallbackStore registerPeriodCallback(NotifyCallback callback, boolean initialNotify) {
127    int uid = EncoderDataJNI.registerPeriodCallback(m_index, callback, initialNotify);
128    return new CallbackStore(m_index, uid, EncoderDataJNI::cancelPeriodCallback);
129  }
130
131  /**
132   * Read the period of the encoder.
133   *
134   * @return the encoder period
135   */
136  public double getPeriod() {
137    return EncoderDataJNI.getPeriod(m_index);
138  }
139
140  /**
141   * Change the encoder period.
142   *
143   * @param period the new period
144   */
145  public void setPeriod(double period) {
146    EncoderDataJNI.setPeriod(m_index, period);
147  }
148
149  /**
150   * Register a callback to be called whenever the encoder is reset.
151   *
152   * @param callback the callback
153   * @param initialNotify whether to run the callback on the initial value
154   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
155   *     this object so GC doesn't cancel the callback.
156   */
157  public CallbackStore registerResetCallback(NotifyCallback callback, boolean initialNotify) {
158    int uid = EncoderDataJNI.registerResetCallback(m_index, callback, initialNotify);
159    return new CallbackStore(m_index, uid, EncoderDataJNI::cancelResetCallback);
160  }
161
162  /**
163   * Check if the encoder has been reset.
164   *
165   * @return true if reset
166   */
167  public boolean getReset() {
168    return EncoderDataJNI.getReset(m_index);
169  }
170
171  /**
172   * Change the reset property of the encoder.
173   *
174   * @param reset the new value
175   */
176  public void setReset(boolean reset) {
177    EncoderDataJNI.setReset(m_index, reset);
178  }
179
180  /**
181   * Register a callback to be run whenever the max period of the encoder is changed.
182   *
183   * @param callback the callback
184   * @param initialNotify whether to run the callback on the initial value
185   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
186   *     this object so GC doesn't cancel the callback.
187   */
188  public CallbackStore registerMaxPeriodCallback(NotifyCallback callback, boolean initialNotify) {
189    int uid = EncoderDataJNI.registerMaxPeriodCallback(m_index, callback, initialNotify);
190    return new CallbackStore(m_index, uid, EncoderDataJNI::cancelMaxPeriodCallback);
191  }
192
193  /**
194   * Get the max period of the encoder.
195   *
196   * @return the max period of the encoder
197   */
198  public double getMaxPeriod() {
199    return EncoderDataJNI.getMaxPeriod(m_index);
200  }
201
202  /**
203   * Change the max period of the encoder.
204   *
205   * @param maxPeriod the new value
206   */
207  public void setMaxPeriod(double maxPeriod) {
208    EncoderDataJNI.setMaxPeriod(m_index, maxPeriod);
209  }
210
211  /**
212   * Register a callback on the direction of the encoder.
213   *
214   * @param callback the callback that will be called whenever the direction is changed
215   * @param initialNotify if true, the callback will be run on the initial value
216   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
217   *     this object so GC doesn't cancel the callback.
218   */
219  public CallbackStore registerDirectionCallback(NotifyCallback callback, boolean initialNotify) {
220    int uid = EncoderDataJNI.registerDirectionCallback(m_index, callback, initialNotify);
221    return new CallbackStore(m_index, uid, EncoderDataJNI::cancelDirectionCallback);
222  }
223
224  /**
225   * Get the direction of the encoder.
226   *
227   * @return the direction of the encoder
228   */
229  public boolean getDirection() {
230    return EncoderDataJNI.getDirection(m_index);
231  }
232
233  /**
234   * Set the direction of the encoder.
235   *
236   * @param direction the new direction
237   */
238  public void setDirection(boolean direction) {
239    EncoderDataJNI.setDirection(m_index, direction);
240  }
241
242  /**
243   * Register a callback on the reverse direction.
244   *
245   * @param callback the callback that will be called whenever the reverse direction is changed
246   * @param initialNotify if true, the callback will be run on the initial value
247   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
248   *     this object so GC doesn't cancel the callback.
249   */
250  public CallbackStore registerReverseDirectionCallback(
251      NotifyCallback callback, boolean initialNotify) {
252    int uid = EncoderDataJNI.registerReverseDirectionCallback(m_index, callback, initialNotify);
253    return new CallbackStore(m_index, uid, EncoderDataJNI::cancelReverseDirectionCallback);
254  }
255
256  /**
257   * Get the reverse direction of the encoder.
258   *
259   * @return the reverse direction of the encoder
260   */
261  public boolean getReverseDirection() {
262    return EncoderDataJNI.getReverseDirection(m_index);
263  }
264
265  /**
266   * Set the reverse direction.
267   *
268   * @param reverseDirection the new value
269   */
270  public void setReverseDirection(boolean reverseDirection) {
271    EncoderDataJNI.setReverseDirection(m_index, reverseDirection);
272  }
273
274  /**
275   * Register a callback on the samples-to-average value of this encoder.
276   *
277   * @param callback the callback that will be called whenever the samples-to-average is changed
278   * @param initialNotify if true, the callback will be run on the initial value
279   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
280   *     this object so GC doesn't cancel the callback.
281   */
282  public CallbackStore registerSamplesToAverageCallback(
283      NotifyCallback callback, boolean initialNotify) {
284    int uid = EncoderDataJNI.registerSamplesToAverageCallback(m_index, callback, initialNotify);
285    return new CallbackStore(m_index, uid, EncoderDataJNI::cancelSamplesToAverageCallback);
286  }
287
288  /**
289   * Get the samples-to-average value.
290   *
291   * @return the samples-to-average value
292   */
293  public int getSamplesToAverage() {
294    return EncoderDataJNI.getSamplesToAverage(m_index);
295  }
296
297  /**
298   * Set the samples-to-average value.
299   *
300   * @param samplesToAverage the new value
301   */
302  public void setSamplesToAverage(int samplesToAverage) {
303    EncoderDataJNI.setSamplesToAverage(m_index, samplesToAverage);
304  }
305
306  /**
307   * Change the encoder distance.
308   *
309   * @param distance the new distance
310   */
311  public void setDistance(double distance) {
312    EncoderDataJNI.setDistance(m_index, distance);
313  }
314
315  /**
316   * Read the distance of the encoder.
317   *
318   * @return the encoder distance
319   */
320  public double getDistance() {
321    return EncoderDataJNI.getDistance(m_index);
322  }
323
324  /**
325   * Change the rate of the encoder.
326   *
327   * @param rate the new rate
328   */
329  public void setRate(double rate) {
330    EncoderDataJNI.setRate(m_index, rate);
331  }
332
333  /**
334   * Get the rate of the encoder.
335   *
336   * @return the rate of change
337   */
338  public double getRate() {
339    return EncoderDataJNI.getRate(m_index);
340  }
341
342  /** Resets all simulation data for this encoder. */
343  public void resetData() {
344    EncoderDataJNI.resetData(m_index);
345  }
346}