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.CANBus;
010import com.ctre.phoenix6.StatusCode;
011import com.ctre.phoenix6.controls.jni.ControlJNI;
012import com.ctre.phoenix6.hardware.traits.*;
013import com.ctre.phoenix6.signals.*;
014
015import edu.wpi.first.units.*;
016import edu.wpi.first.units.measure.*;
017import static edu.wpi.first.units.Units.*;
018
019import java.util.HashMap;
020import java.util.Map;
021
022/**
023 * Animation that creates a rainbow throughout all the LEDs.
024 * <p>
025 * 
026 */
027public final class RainbowAnimation implements ControlRequest, Cloneable {
028    /**
029     * The index of the first LED this animation controls (inclusive). Indices 0-7
030     * control the onboard LEDs, and 8-399 control an attached LED strip
031     * <p>
032     * If the start index is greater than the end index, the direction will be
033     * reversed. The direction can also be changed using the Direction parameter.
034     */
035    public int LEDStartIndex;
036    /**
037     * The index of the last LED this animation controls (inclusive). Indices 0-7
038     * control the onboard LEDs, and 8-399 control an attached LED strip.
039     * <p>
040     * If the end index is less than the start index, the direction will be
041     * reversed. The direction can also be changed using the Direction parameter.
042     */
043    public int LEDEndIndex;
044    /**
045     * The slot of this animation, within [0, 7]. Each slot on the CANdle can store
046     * and run one animation.
047     */
048    public int Slot = 0;
049    /**
050     * The brightness of the animation, as a scalar from 0.0 to 1.0.
051     */
052    public double Brightness = 1.0;
053    /**
054     * The direction of the animation.
055     */
056    public AnimationDirectionValue Direction = AnimationDirectionValue.Forward;
057    /**
058     * The frame rate of the animation, from [2, 1000] Hz. This determines the speed
059     * of the animation.
060     * <p>
061     * A frame is defined as a transition in the state of the LEDs, advancing the
062     * rainbow by about 3 degrees of hue (out of 360 degrees).
063     * 
064     * <ul>
065     *   <li> Units: Hz
066     * </ul>
067     * 
068     */
069    public double FrameRate = 100;
070
071    /**
072     * The frequency at which this control will update.
073     * This is designated in Hertz, with a minimum of 20 Hz
074     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
075     * Some update frequencies are not supported and will be
076     * promoted up to the next highest supported frequency.
077     * <p>
078     * If this field is set to 0 Hz, the control request will
079     * be sent immediately as a one-shot frame. This may be useful
080     * for advanced applications that require outputs to be
081     * synchronized with data acquisition. In this case, we
082     * recommend not exceeding 50 ms between control calls.
083     */
084    public double UpdateFreqHz = 20;
085
086    /**
087     * Animation that creates a rainbow throughout all the LEDs.
088     * <p>
089     * 
090     * 
091     * @param LEDStartIndex The index of the first LED this animation controls
092     *                      (inclusive). Indices 0-7 control the onboard LEDs, and
093     *                      8-399 control an attached LED strip
094     *                      <p>
095     *                      If the start index is greater than the end index, the
096     *                      direction will be reversed. The direction can also be
097     *                      changed using the Direction parameter.
098     * @param LEDEndIndex The index of the last LED this animation controls
099     *                    (inclusive). Indices 0-7 control the onboard LEDs, and
100     *                    8-399 control an attached LED strip.
101     *                    <p>
102     *                    If the end index is less than the start index, the
103     *                    direction will be reversed. The direction can also be
104     *                    changed using the Direction parameter.
105     */
106    public RainbowAnimation(int LEDStartIndex, int LEDEndIndex) {
107        this.LEDStartIndex = LEDStartIndex;
108        this.LEDEndIndex = LEDEndIndex;
109    }
110
111    @Override
112    public String getName() {
113        return "RainbowAnimation";
114    }
115
116    @Override
117    public String toString() {
118        String ss = "Control: RainbowAnimation\n";
119        ss += "    LEDStartIndex: " + LEDStartIndex + "\n";
120        ss += "    LEDEndIndex: " + LEDEndIndex + "\n";
121        ss += "    Slot: " + Slot + "\n";
122        ss += "    Brightness: " + Brightness + "\n";
123        ss += "    Direction: " + Direction + "\n";
124        ss += "    FrameRate: " + FrameRate + " Hz" + "\n";
125        return ss;
126    }
127
128    @Override
129    public StatusCode sendRequest(CANBus network, int deviceHash) {
130        return StatusCode.valueOf(ControlJNI.JNI_RequestControlRainbowAnimation(
131                network.getNameUTF8Bytes(), deviceHash, UpdateFreqHz, LEDStartIndex, LEDEndIndex, Slot, Brightness, Direction.value, FrameRate));
132    }
133
134    /**
135     * Gets information about this control request.
136     *
137     * @return Map of control parameter names and corresponding applied values
138     */
139    @Override
140    public Map<String, String> getControlInfo() {
141        var controlInfo = new HashMap<String, String>();
142        controlInfo.put("Name", getName());
143        controlInfo.put("LEDStartIndex", String.valueOf(this.LEDStartIndex));
144        controlInfo.put("LEDEndIndex", String.valueOf(this.LEDEndIndex));
145        controlInfo.put("Slot", String.valueOf(this.Slot));
146        controlInfo.put("Brightness", String.valueOf(this.Brightness));
147        controlInfo.put("Direction", String.valueOf(this.Direction));
148        controlInfo.put("FrameRate", String.valueOf(this.FrameRate));
149        return controlInfo;
150    }
151    
152    /**
153     * Modifies this Control Request's LEDStartIndex parameter and returns itself for
154     * method-chaining and easier to use request API.
155     * <p>
156     * The index of the first LED this animation controls (inclusive). Indices 0-7
157     * control the onboard LEDs, and 8-399 control an attached LED strip
158     * <p>
159     * If the start index is greater than the end index, the direction will be
160     * reversed. The direction can also be changed using the Direction parameter.
161     *
162     * @param newLEDStartIndex Parameter to modify
163     * @return Itself
164     */
165    public RainbowAnimation withLEDStartIndex(int newLEDStartIndex) {
166        LEDStartIndex = newLEDStartIndex;
167        return this;
168    }
169    
170    /**
171     * Modifies this Control Request's LEDEndIndex parameter and returns itself for
172     * method-chaining and easier to use request API.
173     * <p>
174     * The index of the last LED this animation controls (inclusive). Indices 0-7
175     * control the onboard LEDs, and 8-399 control an attached LED strip.
176     * <p>
177     * If the end index is less than the start index, the direction will be
178     * reversed. The direction can also be changed using the Direction parameter.
179     *
180     * @param newLEDEndIndex Parameter to modify
181     * @return Itself
182     */
183    public RainbowAnimation withLEDEndIndex(int newLEDEndIndex) {
184        LEDEndIndex = newLEDEndIndex;
185        return this;
186    }
187    
188    /**
189     * Modifies this Control Request's Slot parameter and returns itself for
190     * method-chaining and easier to use request API.
191     * <p>
192     * The slot of this animation, within [0, 7]. Each slot on the CANdle can store
193     * and run one animation.
194     *
195     * @param newSlot Parameter to modify
196     * @return Itself
197     */
198    public RainbowAnimation withSlot(int newSlot) {
199        Slot = newSlot;
200        return this;
201    }
202    
203    /**
204     * Modifies this Control Request's Brightness parameter and returns itself for
205     * method-chaining and easier to use request API.
206     * <p>
207     * The brightness of the animation, as a scalar from 0.0 to 1.0.
208     *
209     * @param newBrightness Parameter to modify
210     * @return Itself
211     */
212    public RainbowAnimation withBrightness(double newBrightness) {
213        Brightness = newBrightness;
214        return this;
215    }
216    
217    /**
218     * Modifies this Control Request's Direction parameter and returns itself for
219     * method-chaining and easier to use request API.
220     * <p>
221     * The direction of the animation.
222     *
223     * @param newDirection Parameter to modify
224     * @return Itself
225     */
226    public RainbowAnimation withDirection(AnimationDirectionValue newDirection) {
227        Direction = newDirection;
228        return this;
229    }
230    
231    /**
232     * Modifies this Control Request's FrameRate parameter and returns itself for
233     * method-chaining and easier to use request API.
234     * <p>
235     * The frame rate of the animation, from [2, 1000] Hz. This determines the speed
236     * of the animation.
237     * <p>
238     * A frame is defined as a transition in the state of the LEDs, advancing the
239     * rainbow by about 3 degrees of hue (out of 360 degrees).
240     * 
241     * <ul>
242     *   <li> Units: Hz
243     * </ul>
244     * 
245     *
246     * @param newFrameRate Parameter to modify
247     * @return Itself
248     */
249    public RainbowAnimation withFrameRate(double newFrameRate) {
250        FrameRate = newFrameRate;
251        return this;
252    }
253    
254    /**
255     * Modifies this Control Request's FrameRate parameter and returns itself for
256     * method-chaining and easier to use request API.
257     * <p>
258     * The frame rate of the animation, from [2, 1000] Hz. This determines the speed
259     * of the animation.
260     * <p>
261     * A frame is defined as a transition in the state of the LEDs, advancing the
262     * rainbow by about 3 degrees of hue (out of 360 degrees).
263     * 
264     * <ul>
265     *   <li> Units: Hz
266     * </ul>
267     * 
268     *
269     * @param newFrameRate Parameter to modify
270     * @return Itself
271     */
272    public RainbowAnimation withFrameRate(Frequency newFrameRate) {
273        FrameRate = newFrameRate.in(Hertz);
274        return this;
275    }
276    
277    /**
278     * Helper method to get this Control Request's FrameRate parameter converted
279     * to a unit type. If not using the Java units library, {@link #FrameRate}
280     * can be accessed directly instead.
281     * <p>
282     * The frame rate of the animation, from [2, 1000] Hz. This determines the speed
283     * of the animation.
284     * <p>
285     * A frame is defined as a transition in the state of the LEDs, advancing the
286     * rainbow by about 3 degrees of hue (out of 360 degrees).
287     * 
288     * <ul>
289     *   <li> Units: Hz
290     * </ul>
291     * 
292     *
293     * @return FrameRate
294     */
295    public Frequency getFrameRateMeasure() {
296        return Hertz.of(FrameRate);
297    }
298
299    /**
300     * Sets the frequency at which this control will update.
301     * This is designated in Hertz, with a minimum of 20 Hz
302     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
303     * Some update frequencies are not supported and will be
304     * promoted up to the next highest supported frequency.
305     * <p>
306     * If this field is set to 0 Hz, the control request will
307     * be sent immediately as a one-shot frame. This may be useful
308     * for advanced applications that require outputs to be
309     * synchronized with data acquisition. In this case, we
310     * recommend not exceeding 50 ms between control calls.
311     *
312     * @param newUpdateFreqHz Parameter to modify
313     * @return Itself
314     */
315    @Override
316    public RainbowAnimation withUpdateFreqHz(double newUpdateFreqHz) {
317        UpdateFreqHz = newUpdateFreqHz;
318        return this;
319    }
320
321    /**
322     * Sets the frequency at which this control will update.
323     * This is designated in Hertz, with a minimum of 20 Hz
324     * (every 50 ms) and a maximum of 1000 Hz (every 1 ms).
325     * Some update frequencies are not supported and will be
326     * promoted up to the next highest supported frequency.
327     * <p>
328     * If this field is set to 0 Hz, the control request will
329     * be sent immediately as a one-shot frame. This may be useful
330     * for advanced applications that require outputs to be
331     * synchronized with data acquisition. In this case, we
332     * recommend not exceeding 50 ms between control calls.
333     *
334     * @param newUpdateFreqHz Parameter to modify
335     * @return Itself
336     */
337    @Override
338    public RainbowAnimation withUpdateFreqHz(Frequency newUpdateFreqHz) {
339        UpdateFreqHz = newUpdateFreqHz.in(Hertz);
340        return this;
341    }
342
343    @Override
344    public RainbowAnimation clone() {
345        try {
346            return (RainbowAnimation)super.clone();
347        } catch (CloneNotSupportedException ex) {
348            /* this should never happen */
349            throw new RuntimeException(ex);
350        }
351    }
352}
353