001/*
002 * Copyright (C) Cross The Road Electronics.  All rights reserved.
003 * License information can be found in CTRE_LICENSE.txt
004 * For support and suggestions contact support@ctr-electronics.com or file
005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases
006 */
007package com.ctre.phoenix6.controls;
008
009import com.ctre.phoenix6.StatusCode;
010import com.ctre.phoenix6.controls.jni.ControlJNI;
011import com.ctre.phoenix6.hardware.traits.*;
012
013import edu.wpi.first.units.*;
014import edu.wpi.first.units.measure.*;
015import static edu.wpi.first.units.Units.*;
016
017import java.util.HashMap;
018import java.util.Map;
019
020/**
021 * Plays a single tone at the user specified frequency.
022 */
023public class MusicTone extends ControlRequest implements Cloneable
024{
025    /**
026     * Sound frequency to play.  A value of zero will silence the device. The
027     * effective frequency range is 10-20000 Hz.  Any nonzero frequency less than 10
028     * Hz will be capped to 10 Hz.  Any frequency above 20 kHz will be capped to 20
029     * kHz.
030     * 
031     * <ul>
032     *   <li> Units: Hz
033     * </ul>
034     * 
035     */
036    public double AudioFrequency;
037
038    /**
039     * The period at which this control will update at.
040     * This is designated in Hertz, with a minimum of 20 Hz
041     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
042     * <p>
043     * If this field is set to 0 Hz, the control request will
044     * be sent immediately as a one-shot frame. This may be useful
045     * for advanced applications that require outputs to be
046     * synchronized with data acquisition. In this case, we
047     * recommend not exceeding 50 ms between control calls.
048     */
049    public double UpdateFreqHz = 100;
050
051    /**
052     * Plays a single tone at the user specified frequency.
053     * 
054     * @param AudioFrequency    Sound frequency to play.  A value of zero will
055     *                          silence the device. The effective frequency range is
056     *                          10-20000 Hz.  Any nonzero frequency less than 10 Hz
057     *                          will be capped to 10 Hz.  Any frequency above 20 kHz
058     *                          will be capped to 20 kHz.
059     */
060    public MusicTone(double AudioFrequency)
061    {
062        super("MusicTone");
063        this.AudioFrequency = AudioFrequency;
064    }
065
066    /**
067     * Plays a single tone at the user specified frequency.
068     * 
069     * @param AudioFrequency    Sound frequency to play.  A value of zero will
070     *                          silence the device. The effective frequency range is
071     *                          10-20000 Hz.  Any nonzero frequency less than 10 Hz
072     *                          will be capped to 10 Hz.  Any frequency above 20 kHz
073     *                          will be capped to 20 kHz.
074     */
075    public MusicTone(Frequency AudioFrequency)
076    {
077        this(AudioFrequency.in(Hertz));
078    }
079
080    @Override
081    public String toString()
082    {
083        String ss = "Control: MusicTone\n";
084        ss += "    AudioFrequency: " + AudioFrequency + " Hz" + "\n";
085        return ss;
086    }
087
088    @Override
089    public StatusCode sendRequest(String network, int deviceHash)
090    {
091        return StatusCode.valueOf(ControlJNI.JNI_RequestControlMusicTone(
092                network, deviceHash, UpdateFreqHz, AudioFrequency));
093    }
094
095    /**
096     * Gets information about this control request.
097     *
098     * @return Map of control parameter names and corresponding applied values
099     */
100    @Override
101    public Map<String, String> getControlInfo()
102    {
103        var controlInfo = new HashMap<String, String>();
104        controlInfo.put("Name", getName());
105        controlInfo.put("AudioFrequency", String.valueOf(this.AudioFrequency));
106        return controlInfo;
107    }
108    
109    /**
110     * Modifies this Control Request's AudioFrequency parameter and returns itself for
111     * method-chaining and easier to use request API.
112     * <p>
113     * Sound frequency to play.  A value of zero will silence the device. The
114     * effective frequency range is 10-20000 Hz.  Any nonzero frequency less than 10
115     * Hz will be capped to 10 Hz.  Any frequency above 20 kHz will be capped to 20
116     * kHz.
117     * 
118     * <ul>
119     *   <li> Units: Hz
120     * </ul>
121     * 
122     *
123     * @param newAudioFrequency Parameter to modify
124     * @return Itself
125     */
126    public MusicTone withAudioFrequency(double newAudioFrequency)
127    {
128        AudioFrequency = newAudioFrequency;
129        return this;
130    }
131    
132    /**
133     * Modifies this Control Request's AudioFrequency parameter and returns itself for
134     * method-chaining and easier to use request API.
135     * <p>
136     * Sound frequency to play.  A value of zero will silence the device. The
137     * effective frequency range is 10-20000 Hz.  Any nonzero frequency less than 10
138     * Hz will be capped to 10 Hz.  Any frequency above 20 kHz will be capped to 20
139     * kHz.
140     * 
141     * <ul>
142     *   <li> Units: Hz
143     * </ul>
144     * 
145     *
146     * @param newAudioFrequency Parameter to modify
147     * @return Itself
148     */
149    public MusicTone withAudioFrequency(Frequency newAudioFrequency)
150    {
151        AudioFrequency = newAudioFrequency.in(Hertz);
152        return this;
153    }
154    
155    /**
156     * Helper method to get this Control Request's AudioFrequency parameter converted
157     * to a unit type. If not using the Java units library, {@link #AudioFrequency}
158     * can be accessed directly instead.
159     * <p>
160     * Sound frequency to play.  A value of zero will silence the device. The
161     * effective frequency range is 10-20000 Hz.  Any nonzero frequency less than 10
162     * Hz will be capped to 10 Hz.  Any frequency above 20 kHz will be capped to 20
163     * kHz.
164     * 
165     * <ul>
166     *   <li> Units: Hz
167     * </ul>
168     * 
169     *
170     * @return AudioFrequency
171     */
172    public Frequency getAudioFrequencyMeasure()
173    {
174        return Hertz.of(AudioFrequency);
175    }
176
177    /**
178     * Sets the period at which this control will update at.
179     * This is designated in Hertz, with a minimum of 20 Hz
180     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
181     * <p>
182     * If this field is set to 0 Hz, the control request will
183     * be sent immediately as a one-shot frame. This may be useful
184     * for advanced applications that require outputs to be
185     * synchronized with data acquisition. In this case, we
186     * recommend not exceeding 50 ms between control calls.
187     *
188     * @param newUpdateFreqHz Parameter to modify
189     * @return Itself
190     */
191    @Override
192    public MusicTone withUpdateFreqHz(double newUpdateFreqHz)
193    {
194        UpdateFreqHz = newUpdateFreqHz;
195        return this;
196    }
197
198    /**
199     * Sets the period at which this control will update at.
200     * This is designated in Hertz, with a minimum of 20 Hz
201     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
202     * <p>
203     * If this field is set to 0 Hz, the control request will
204     * be sent immediately as a one-shot frame. This may be useful
205     * for advanced applications that require outputs to be
206     * synchronized with data acquisition. In this case, we
207     * recommend not exceeding 50 ms between control calls.
208     *
209     * @param newUpdateFreqHz Parameter to modify
210     * @return Itself
211     */
212    @Override
213    public MusicTone withUpdateFreqHz(Frequency newUpdateFreqHz)
214    {
215        UpdateFreqHz = newUpdateFreqHz.in(Hertz);
216        return this;
217    }
218
219    @Override
220    public MusicTone clone()
221    {
222        try {
223            return (MusicTone)super.clone();
224        } catch (CloneNotSupportedException ex) {
225            /* this should never happen */
226            throw new RuntimeException(ex);
227        }
228    }
229}
230