001package com.ctre.phoenix.motorcontrol;
002
003import com.ctre.phoenix.ErrorCode;
004import com.ctre.phoenix.motorcontrol.can.BaseTalon;
005import com.ctre.phoenix.motorcontrol.can.MotControllerJNI;
006
007/**
008 * Collection of sensors available to a motor controller.
009 *
010 * For best performance and update-rate, 
011 * we recommend using the configSelectedFeedbackSensor() and getSelectedSensor*() routines.
012 * However there are occasions where accessing raw sensor values may be useful or convenient.
013 * Particularly if you are seeding one sensor based on another, or need to circumvent sensor-phase.
014 *
015 * Use the getSensorCollection() routine inside your motor controller to create a sensor collection.
016 */
017public class SensorCollection {
018
019        private long _handle;
020
021        /**
022         * Constructor for SensorCollection
023         * @param motorController Motor Controller to connect Collection to
024         */
025        public SensorCollection(BaseTalon motorController) {
026                _handle = motorController.getHandle();
027        }
028
029        /**
030         * Get the position of whatever is in the analog pin of the Talon, regardless of
031         *   whether it is actually being used for feedback.
032         * <p>
033         * This method relies on the Status 4 message, which has a default period of 150ms. For more
034         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
035         *
036         * @return  the 24bit analog value.  The bottom ten bits is the ADC (0 - 1023)
037         *          on the analog pin of the Talon. The upper 14 bits tracks the overflows and underflows
038         *          (continuous sensor).
039         */
040
041        public int getAnalogIn() {
042                return MotControllerJNI.GetAnalogIn(_handle);
043        }
044
045        /**
046         * Sets analog position.
047         *
048         * @param   newPosition The new position.
049         * @param   timeoutMs
050     *            Timeout value in ms. If nonzero, function will wait for
051     *            config success and report an error if it times out.
052     *            If zero, no blocking or checking is performed.
053         *
054         * @return  an ErrorCode.
055         */
056
057        public ErrorCode setAnalogPosition(int newPosition, int timeoutMs) {
058                int retval = MotControllerJNI.SetAnalogPosition(_handle, newPosition, timeoutMs);
059                return ErrorCode.valueOf(retval);
060        }
061
062        /**
063         * Get the position of whatever is in the analog pin of the Talon, regardless of whether
064         *   it is actually being used for feedback.
065         * <p>
066         * This method relies on the Status 4 message, which has a default period of 150ms. For more
067         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
068         *
069         * @return  the ADC (0 - 1023) on analog pin of the Talon.
070         */
071
072        public int getAnalogInRaw() {
073                return MotControllerJNI.GetAnalogInRaw(_handle);
074        }
075
076        /**
077         * Get the velocity of whatever is in the analog pin of the Talon, regardless of
078         *   whether it is actually being used for feedback.
079         * <p>
080         * This method relies on the Status 4 message, which has a default period of 150ms. For more
081         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
082         *
083         * @return  the speed in units per 100ms where 1024 units is one rotation.
084         */
085
086        public int getAnalogInVel() {
087                return MotControllerJNI.GetAnalogInVel(_handle);
088        }
089
090        /**
091         * Get the quadrature position of the Talon, regardless of whether
092         *   it is actually being used for feedback.
093         * <p>
094         * This method relies on the Status 3 message, which has a default period of 150ms. For more
095         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
096         *
097         * @return  the quadrature position.
098         */
099
100        public int getQuadraturePosition() {
101                return MotControllerJNI.GetQuadraturePosition(_handle);
102        }
103
104        /**
105         * Change the quadrature reported position.  Typically this is used to "zero" the
106         *   sensor. This only works with Quadrature sensor.  To set the selected sensor position
107         *   regardless of what type it is, see SetSelectedSensorPosition in the motor controller class.
108         *
109         * @param   newPosition The position value to apply to the sensor.
110         * @param   timeoutMs
111     *            Timeout value in ms. If nonzero, function will wait for
112     *            config success and report an error if it times out.
113     *            If zero, no blocking or checking is performed.
114         *
115         * @return  error code.
116         */
117
118        public ErrorCode setQuadraturePosition(int newPosition, int timeoutMs) {
119                int retval = MotControllerJNI.SetQuadraturePosition(_handle, newPosition, timeoutMs);
120                return ErrorCode.valueOf(retval);
121        }
122
123    
124    /**
125     * Change the quadrature reported position based on pulse width. This can be used to 
126     * effectively make quadrature absolute. For rotary mechanisms with >360 movement (such
127     * as typical swerve modules) bookend0 and bookend1 can be both set to 0 and 
128     * bCrossZeroOnInterval can be set to true. For mechanisms with less than 360 travel (such
129     * as arms), bookend0 and bookend1 should be set to the pulse width values at the two 
130     * extremes. If the interval crosses over the pulse width value of 0 (or any multiple of
131     * 4096), bCrossZeroOnInterval should be true and otherwise should be false. An offset can
132     * also be set.
133     *
134     * @param   bookend0    value at extreme 0
135     * @param   bookend1    value at extreme 1
136     * @param   bCrossZeroOnInterval    True iff zero/wrap-around cross occurs as mechanism moves from bookend0 to bookend1.
137     * @param   offset      (Optional) Value to add to pulse width 
138     * @param   timeoutMs   (Optional) How long to wait for confirmation.  Pass zero so that call
139     *                      does not block.
140     *
141     * @return  error code.
142     */
143
144    public ErrorCode syncQuadratureWithPulseWidth(int bookend0, int bookend1, boolean bCrossZeroOnInterval, int offset, int timeoutMs) {   
145        int ticksPerRevolution = 4096;
146        /* Normalize bookends (should be 0 - ticksPerRevolution) */
147        bookend0 &= (ticksPerRevolution - 1);
148        bookend1 &= (ticksPerRevolution - 1);
149      
150        /* Assign greater and lesser bookend */
151        int greaterBookend;
152        int lesserBookend;
153        
154        if(bookend0 > bookend1)
155        {
156            greaterBookend = bookend0;
157            lesserBookend = bookend1;
158        }
159        else
160        {
161            greaterBookend = bookend1;
162            lesserBookend = bookend0;
163        }
164
165        int average = (greaterBookend + lesserBookend) / 2;
166 
167        /* Get Fractional Part of Pulse Width Position (0 - ticksPerRevolution) */
168        int pulseWidth = getPulseWidthPosition();
169        pulseWidth &= (ticksPerRevolution - 1);
170        
171        if(bCrossZeroOnInterval) 
172        {
173            /*
174             * If the desire is to have the *** part be the interval 
175             * (2048 - 3277 and crosses over 0): 
176             *
177             *                            
178             *                        1024
179             *                     *********    
180             *                    ***********   
181             *                   *************  
182             *                  *************** 
183             *                 *****************
184             *                 *****************
185             *                 *****************
186             *            2048 ***************** 0
187             *                         *********
188             *                         *********
189             *                         *********
190             *                         *********
191             *                        **********
192             *                        ********* 
193             *                        ********  
194             *                       ********   
195             *                       *******
196             *                     3277   
197             *
198             * The goal is to center the discontinuoity between 2048 and 3277 in the blank.
199             * So all pulse width values greater than the avg of the two bookends should be 
200             * reduced by ticksPerRevolution.
201             */
202            if(pulseWidth > average)
203            {            
204                pulseWidth -= ticksPerRevolution;
205            }
206        }
207        else
208        {
209            /*
210             * If the desire is to have the blank part be the interval 
211             * (2048 - 3277 and crosses over 0): 
212             *
213             *                            
214             *                        1024
215             *                     *********    
216             *                    ***********   
217             *                   *************  
218             *                  *************** 
219             *                 *****************
220             *                 *****************
221             *                 *****************
222             *            2048 ***************** 0
223             *                         *********
224             *                         *********
225             *                         *********
226             *                         *********
227             *                        **********
228             *                        ********* 
229             *                        ********  
230             *                       ********   
231             *                       *******
232             *                     3277   
233             *
234             * The goal is to center the discontinuoity between 2048 and 3277 in the ***.
235             * So all pulse width values less than the (ticksPerRevolution / 2 - avg of 
236             * the two bookends) & ticksPerRevolution should be increased by 
237             * ticksPerRevolution.
238             */
239            if(pulseWidth < ((ticksPerRevolution / 2 - average) & 0x0FFF))
240            {            
241                pulseWidth += ticksPerRevolution;
242            }
243        }
244       
245        pulseWidth += offset;
246 
247        return setQuadraturePosition(pulseWidth, timeoutMs);
248    }
249
250    /**
251     * Change the quadrature reported position based on pulse width. This can be used to 
252     * effectively make quadrature absolute. For rotary mechanisms with >360 movement (such
253     * as typical swerve modules) bookend0 and bookend1 can be both set to 0 and 
254     * bCrossZeroOnInterval can be set to true. For mechanisms with less than 360 travel (such
255     * as arms), bookend0 and bookend1 should be set to the pulse width values at the two 
256     * extremes. If the interval crosses over the pulse width value of 0 (or any multiple of
257     * 4096), bCrossZeroOnInterval should be true and otherwise should be false. An offset can
258     * also be set.
259     *
260     * @param   bookend0    value at extreme 0
261     * @param   bookend1    value at extreme 1
262     * @param   bCrossZeroOnInterval    True iff zero/wrap-around cross occurs as mechanism moves from bookend0 to bookend1.
263     *
264     * @return  error code.
265     */
266    public ErrorCode syncQuadratureWithPulseWidth(int bookend0, int bookend1, boolean bCrossZeroOnInterval) {
267        int offset = 0;
268        int timeoutMs = 0;
269        return syncQuadratureWithPulseWidth(bookend0, bookend1, bCrossZeroOnInterval, offset, timeoutMs);
270    }   
271        /**
272         * Get the quadrature velocity, regardless of whether
273         *   it is actually being used for feedback.
274         * <p>
275         * This method relies on the Status 3 message, which has a default period of 150ms. For more
276         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
277         *
278         * @return  the quadrature velocity in units per 100ms.
279         */
280
281        public int getQuadratureVelocity() {
282                return MotControllerJNI.GetQuadratureVelocity(_handle);
283        }
284
285        /**
286         * Gets pulse width position, regardless of whether
287         *   it is actually being used for feedback.
288         * <p>
289         * This method relies on the Status 8 message, which has a default period of 150ms. For more
290         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
291         *
292         * @return  the pulse width position.
293         */
294
295        public int getPulseWidthPosition() {
296                return MotControllerJNI.GetPulseWidthPosition(_handle);
297        }
298
299        /**
300         * Sets pulse width position.
301         *
302         * @param   newPosition The position value to apply to the sensor.
303         * @param   timeoutMs
304     *            Timeout value in ms. If nonzero, function will wait for
305     *            config success and report an error if it times out.
306     *            If zero, no blocking or checking is performed.
307         *
308         * @return  an ErrErrorCode
309         */
310        public ErrorCode setPulseWidthPosition(int newPosition, int timeoutMs) {
311                int retval = MotControllerJNI.SetPulseWidthPosition(_handle, newPosition, timeoutMs);
312                return ErrorCode.valueOf(retval);
313        }
314
315        /**
316         * Gets pulse width velocity, regardless of whether
317         *   it is actually being used for feedback.
318         * <p>
319         * This method relies on the Status 8 message, which has a default period of 150ms. For more
320         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
321         *
322         * @return  the pulse width velocity in units per 100ms (where 4096 units is 1 rotation).
323         */
324
325        public int getPulseWidthVelocity() {
326                return MotControllerJNI.GetPulseWidthVelocity(_handle);
327        }
328
329        /**
330         * Gets pulse width rise to fall time.
331         * <p>
332         * This method relies on the Status 8 message, which has a default period of 150ms. For more
333         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
334         *
335         * @return  the pulse width rise to fall time in microseconds.
336         */
337
338        public int getPulseWidthRiseToFallUs() {
339                return MotControllerJNI.GetPulseWidthRiseToFallUs(_handle);
340        }
341
342        /**
343         * Gets pulse width rise to rise time.
344         * <p>
345         * This method relies on the Status 8 message, which has a default period of 150ms. For more
346         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
347         *
348         * @return  the pulse width rise to rise time in microseconds.
349         */
350
351        public int getPulseWidthRiseToRiseUs() {
352                return MotControllerJNI.GetPulseWidthRiseToRiseUs(_handle);
353        }
354
355        /**
356         * Gets pin state quad a.
357         * <p>
358         * This method relies on the Status 3 message, which has a default period of 150ms. For more
359         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
360         *
361         * @return  the pin state of quad a (1 if asserted, 0 if not asserted).
362         */
363
364        public boolean getPinStateQuadA() {
365                return MotControllerJNI.GetPinStateQuadA(_handle) != 0;
366        }
367
368        /**
369         * Gets pin state quad b.
370         * <p>
371         * This method relies on the Status 3 message, which has a default period of 150ms. For more
372         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
373         *
374         * @return  Digital level of QUADB pin (1 if asserted, 0 if not asserted).
375         */
376
377        public boolean getPinStateQuadB() {
378                return MotControllerJNI.GetPinStateQuadB(_handle) != 0;
379        }
380
381        /**
382         * Gets pin state quad index.
383         * <p>
384         * This method relies on the Status 3 message, which has a default period of 150ms. For more
385         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
386         *
387         * @return  Digital level of QUAD Index pin (1 if asserted, 0 if not asserted).
388         */
389
390        public boolean getPinStateQuadIdx() {
391                return MotControllerJNI.GetPinStateQuadIdx(_handle) != 0;
392        }
393
394        /**
395         * Is forward limit switch closed.
396         * <p>
397         * This method relies on the Status 1 message, which has a default period of 10ms. For more
398         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
399         *
400         * @return  '1' iff forward limit switch is closed, 0 iff switch is open. This function works
401         *          regardless if limit switch feature is enabled.  Remote limit features do not impact this routine.
402         */
403
404        public boolean isFwdLimitSwitchClosed() {
405                return MotControllerJNI.IsFwdLimitSwitchClosed(_handle) != 0;
406        }
407
408        /**
409         * Is reverse limit switch closed.
410         * <p>
411         * This method relies on the Status 1 message, which has a default period of 10ms. For more
412         * information, see: https://phoenix-documentation.readthedocs.io/en/latest/ch18_CommonAPI.html
413         *
414         * @return  '1' iff reverse limit switch is closed, 0 iff switch is open. This function works
415         *          regardless if limit switch feature is enabled.  Remote limit features do not impact this routine.
416         */
417
418        public boolean isRevLimitSwitchClosed() {
419                return MotControllerJNI.IsRevLimitSwitchClosed(_handle) != 0;
420        }
421}