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.DutyCycleDataJNI;
008import edu.wpi.first.hal.simulation.NotifyCallback;
009import edu.wpi.first.wpilibj.DutyCycle;
010import java.util.NoSuchElementException;
011
012/** Class to control a simulated duty cycle digital input. */
013public class DutyCycleSim {
014  private final int m_index;
015
016  /**
017   * Constructs from a DutyCycle object.
018   *
019   * @param dutyCycle DutyCycle to simulate
020   */
021  public DutyCycleSim(DutyCycle dutyCycle) {
022    m_index = dutyCycle.getFPGAIndex();
023  }
024
025  private DutyCycleSim(int index) {
026    m_index = index;
027  }
028
029  /**
030   * Creates a DutyCycleSim for a digital input channel.
031   *
032   * @param channel digital input channel
033   * @return Simulated object
034   * @throws NoSuchElementException if no DutyCycle is configured for that channel
035   */
036  public static DutyCycleSim createForChannel(int channel) {
037    int index = DutyCycleDataJNI.findForChannel(channel);
038    if (index < 0) {
039      throw new NoSuchElementException("no duty cycle found for channel " + channel);
040    }
041    return new DutyCycleSim(index);
042  }
043
044  /**
045   * Creates a DutyCycleSim for a simulated index. The index is incremented for each simulated
046   * DutyCycle.
047   *
048   * @param index simulator index
049   * @return Simulated object
050   */
051  public static DutyCycleSim createForIndex(int index) {
052    return new DutyCycleSim(index);
053  }
054
055  /**
056   * Register a callback to be run when this duty cycle input is initialized.
057   *
058   * @param callback the callback
059   * @param initialNotify whether to run the callback with the initial state
060   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
061   *     this object so GC doesn't cancel the callback.
062   */
063  public CallbackStore registerInitializedCallback(NotifyCallback callback, boolean initialNotify) {
064    int uid = DutyCycleDataJNI.registerInitializedCallback(m_index, callback, initialNotify);
065    return new CallbackStore(m_index, uid, DutyCycleDataJNI::cancelInitializedCallback);
066  }
067
068  /**
069   * Check whether this duty cycle input has been initialized.
070   *
071   * @return true if initialized
072   */
073  public boolean getInitialized() {
074    return DutyCycleDataJNI.getInitialized(m_index);
075  }
076
077  /**
078   * Define whether this duty cycle input has been initialized.
079   *
080   * @param initialized whether this object is initialized
081   */
082  public void setInitialized(boolean initialized) {
083    DutyCycleDataJNI.setInitialized(m_index, initialized);
084  }
085
086  /**
087   * Register a callback to be run whenever the frequency changes.
088   *
089   * @param callback the callback
090   * @param initialNotify whether to call the callback with the initial state
091   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
092   *     this object so GC doesn't cancel the callback.
093   */
094  public CallbackStore registerFrequencyCallback(NotifyCallback callback, boolean initialNotify) {
095    int uid = DutyCycleDataJNI.registerFrequencyCallback(m_index, callback, initialNotify);
096    return new CallbackStore(m_index, uid, DutyCycleDataJNI::cancelFrequencyCallback);
097  }
098
099  /**
100   * Measure the frequency.
101   *
102   * @return the duty cycle frequency
103   */
104  public int getFrequency() {
105    return DutyCycleDataJNI.getFrequency(m_index);
106  }
107
108  /**
109   * Change the duty cycle frequency.
110   *
111   * @param frequency the new frequency
112   */
113  public void setFrequency(int frequency) {
114    DutyCycleDataJNI.setFrequency(m_index, frequency);
115  }
116
117  /**
118   * Register a callback to be run whenever the output changes.
119   *
120   * @param callback the callback
121   * @param initialNotify whether to call the callback with the initial state
122   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
123   *     this object so GC doesn't cancel the callback.
124   */
125  public CallbackStore registerOutputCallback(NotifyCallback callback, boolean initialNotify) {
126    int uid = DutyCycleDataJNI.registerOutputCallback(m_index, callback, initialNotify);
127    return new CallbackStore(m_index, uid, DutyCycleDataJNI::cancelOutputCallback);
128  }
129
130  /**
131   * Measure the output from this duty cycle port.
132   *
133   * @return the output value
134   */
135  public double getOutput() {
136    return DutyCycleDataJNI.getOutput(m_index);
137  }
138
139  /**
140   * Change the duty cycle output.
141   *
142   * @param output the new output value
143   */
144  public void setOutput(double output) {
145    DutyCycleDataJNI.setOutput(m_index, output);
146  }
147
148  /** Reset all simulation data for the duty cycle output. */
149  public void resetData() {
150    DutyCycleDataJNI.resetData(m_index);
151  }
152}