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