blob: 31d33cee188207f0b7445aa8d641360eb84e58a7 [file] [log] [blame]
Brian Silverman890a32a2018-03-11 15:41:56 -07001/*
2 * Software License Agreement
3 *
4 * Copyright (C) Cross The Road Electronics. All rights
5 * reserved.
6 *
7 * Cross The Road Electronics (CTRE) licenses to you the right to
8 * use, publish, and distribute copies of CRF (Cross The Road) firmware files (*.crf) and Software
9 * API Libraries ONLY when in use with Cross The Road Electronics hardware products.
10 *
11 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
12 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
14 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15 * CROSS THE ROAD ELECTRONICS BE LIABLE FOR ANY INCIDENTAL, SPECIAL,
16 * INDIRECT OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
17 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
18 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
19 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
20 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
21 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE
22 */
23
24package com.ctre.phoenix;
25
26import edu.wpi.first.wpilibj.hal.HAL;
27
28/**
29 * CTRE CANifier
30 *
31 * Device for interfacing common devices to the CAN bus.
32 */
33public class CANifier {
34 private long m_handle;
35
36 /**
37 * Enum for velocity periods
38 */
39 public enum VelocityPeriod {
40 Period_1Ms(1),
41 Period_2Ms(2),
42 Period_5Ms(5),
43 Period_10Ms(10),
44 Period_20Ms(20),
45 Period_25Ms(25),
46 Period_50Ms(50),
47 Period_100Ms(100);
48 public static VelocityPeriod valueOf(int value) {
49 for(VelocityPeriod period : values()) {
50 if(period.value == value) {
51 return period;
52 }
53 }
54 return null;
55 }
56 public final int value;
57 VelocityPeriod(int initValue) {
58 this.value = initValue;
59 }
60 }
61
62 /**
63 * Enum for the LED Output Channels
64 */
65 public enum LEDChannel {
66 LEDChannelA(0), LEDChannelB(1), LEDChannelC(2);
67 public static LEDChannel valueOf(int value) {
68 for (LEDChannel mode : values()) {
69 if (mode.value == value) {
70 return mode;
71 }
72 }
73 return null;
74 }
75
76 public final int value;
77
78 LEDChannel(int initValue) {
79 this.value = initValue;
80 }
81 }
82
83 /**
84 * Enum for the PWM Input Channels
85 */
86 public enum PWMChannel {
87 PWMChannel0(0), PWMChannel1(1), PWMChannel2(2), PWMChannel3(3);
88 public static PWMChannel valueOf(int value) {
89 for (PWMChannel mode : values()) {
90 if (mode.value == value) {
91 return mode;
92 }
93 }
94 return null;
95 }
96
97 public final int value;
98
99 PWMChannel(int initValue) {
100 this.value = initValue;
101 }
102 }
103
104 public final int PWMChannelCount = 4;
105
106 /**
107 * General IO Pins on the CANifier
108 */
109 public enum GeneralPin {
110 QUAD_IDX (CANifierJNI.GeneralPin.QUAD_IDX.value),
111 QUAD_B (CANifierJNI.GeneralPin.QUAD_B.value),
112 QUAD_A (CANifierJNI.GeneralPin.QUAD_A.value),
113 LIMR (CANifierJNI.GeneralPin.LIMR.value),
114 LIMF (CANifierJNI.GeneralPin.LIMF.value),
115 SDA (CANifierJNI.GeneralPin.SDA.value),
116 SCL (CANifierJNI.GeneralPin.SCL.value),
117 SPI_CS (CANifierJNI.GeneralPin.SPI_CS.value),
118 SPI_MISO_PWM2P (CANifierJNI.GeneralPin.SPI_MISO_PWM2P.value),
119 SPI_MOSI_PWM1P (CANifierJNI.GeneralPin.SPI_MOSI_PWM1P.value),
120 SPI_CLK_PWM0P (CANifierJNI.GeneralPin.SPI_CLK_PWM0P.value);
121 public static GeneralPin valueOf(int value) {
122 for (GeneralPin mode : values()) {
123 if (mode.value == value) {
124 return mode;
125 }
126 }
127 return null;
128 }
129
130 public final int value;
131
132 GeneralPin(int initValue) {
133 this.value = initValue;
134 }
135 }
136
137 /**
138 * Class to hold the pin values.
139 */
140 public static class PinValues {
141 public boolean QUAD_IDX;
142 public boolean QUAD_B;
143 public boolean QUAD_A;
144 public boolean LIMR;
145 public boolean LIMF;
146 public boolean SDA;
147 public boolean SCL;
148 public boolean SPI_CS_PWM3;
149 public boolean SPI_MISO_PWM2;
150 public boolean SPI_MOSI_PWM1;
151 public boolean SPI_CLK_PWM0;
152 }
153
154 private boolean[] _tempPins = new boolean[11];
155
156 private int m_deviceNumber;
157 /**
158 * Constructor.
159 * @param deviceId The CAN Device ID of the CANifier.
160 */
161 public CANifier(int deviceId) {
162 m_handle = CANifierJNI.JNI_new_CANifier(deviceId);
163 m_deviceNumber = deviceId;
164 HAL.report(63, deviceId + 1);
165 }
166
167 /**
168 * Sets the LED Output
169 * @param percentOutput Output duty cycle expressed as percentage.
170 * @param ledChannel Channel to set the output of.
171 */
172 public void setLEDOutput(double percentOutput, LEDChannel ledChannel) {
173 /* convert float to integral fixed pt */
174 if (percentOutput > 1) {
175 percentOutput = 1;
176 }
177 if (percentOutput < 0) {
178 percentOutput = 0;
179 }
180 int dutyCycle = (int) (percentOutput * 1023); // [0,1023]
181
182 CANifierJNI.JNI_SetLEDOutput(m_handle, dutyCycle, ledChannel.value);
183 }
184
185 /**
186 * Sets the output of a General Pin
187 * @param outputPin The pin to use as output.
188 * @param outputValue The desired output state.
189 * @param outputEnable Whether this pin is an output. "True" enables output.
190 */
191 public void setGeneralOutput(GeneralPin outputPin, boolean outputValue, boolean outputEnable) {
192 CANifierJNI.JNI_SetGeneralOutput(m_handle, outputPin.value, outputValue, outputEnable);
193 }
194
195 /**
196 * Sets the output of all General Pins
197 * @param outputBits A bit mask of all the output states. LSB->MSB is in the order of the #GeneralPin enum.
198 * @param isOutputBits A boolean bit mask that sets the pins to be outputs or inputs. A bit of 1 enables output.
199 */
200 public void setGeneralOutputs(int outputBits, int isOutputBits) {
201 CANifierJNI.JNI_SetGeneralOutputs(m_handle, outputBits, isOutputBits);
202 }
203
204 /**
205 * Gets the state of all General Pins
206 * @param allPins A structure to fill with the current state of all pins.
207 */
208 public void getGeneralInputs(PinValues allPins) {
209 CANifierJNI.JNI_GetGeneralInputs(m_handle, _tempPins);
210 allPins.LIMF = _tempPins[GeneralPin.LIMF.value];
211 allPins.LIMR = _tempPins[GeneralPin.LIMR.value];
212 allPins.QUAD_A = _tempPins[GeneralPin.QUAD_A.value];
213 allPins.QUAD_B = _tempPins[GeneralPin.QUAD_B.value];
214 allPins.QUAD_IDX = _tempPins[GeneralPin.QUAD_IDX.value];
215 allPins.SCL = _tempPins[GeneralPin.SCL.value];
216 allPins.SDA = _tempPins[GeneralPin.SDA.value];
217 allPins.SPI_CLK_PWM0 = _tempPins[GeneralPin.SPI_CLK_PWM0P.value];
218 allPins.SPI_MOSI_PWM1 = _tempPins[GeneralPin.SPI_MOSI_PWM1P.value];
219 allPins.SPI_MISO_PWM2 = _tempPins[GeneralPin.SPI_MISO_PWM2P.value];
220 allPins.SPI_CS_PWM3 = _tempPins[GeneralPin.SPI_CS.value];
221 }
222
223 /**
224 * Gets the state of the specified pin
225 * @param inputPin The index of the pin.
226 * @return The state of the pin.
227 */
228 public boolean getGeneralInput(GeneralPin inputPin) {
229 return CANifierJNI.JNI_GetGeneralInput(m_handle, inputPin.value);
230 }
231
232 /**
233 * Call GetLastError() generated by this object.
234 * Not all functions return an error code but can
235 * potentially report errors.
236 *
237 * This function can be used to retrieve those error codes.
238 *
239 * @return The last ErrorCode generated.
240 */
241 public ErrorCode getLastError() {
242 int retval = CANifierJNI.JNI_GetLastError(m_handle);
243 return ErrorCode.valueOf(retval);
244 }
245
246 /**
247 * Sets the PWM Output
248 * Currently supports PWM 0, PWM 1, and PWM 2
249 * @param pwmChannel Index of the PWM channel to output.
250 * @param dutyCycle Duty Cycle (0 to 1) to output. Default period of the signal is 4.2 ms.
251 */
252 public void setPWMOutput(int pwmChannel, double dutyCycle) {
253 if (dutyCycle < 0) {
254 dutyCycle = 0;
255 } else if (dutyCycle > 1) {
256 dutyCycle = 1;
257 }
258 if (pwmChannel < 0) {
259 pwmChannel = 0;
260 }
261
262 int dutyCyc10bit = (int) (1023 * dutyCycle);
263
264 CANifierJNI.JNI_SetPWMOutput(m_handle, (int) pwmChannel, dutyCyc10bit);
265 }
266
267 /**
268 * Enables PWM Outputs
269 * Currently supports PWM 0, PWM 1, and PWM 2
270 * @param pwmChannel Index of the PWM channel to enable.
271 * @param bEnable "True" enables output on the pwm channel.
272 */
273 public void enablePWMOutput(int pwmChannel, boolean bEnable) {
274 if (pwmChannel < 0) {
275 pwmChannel = 0;
276 }
277
278 CANifierJNI.JNI_EnablePWMOutput(m_handle, (int) pwmChannel, bEnable);
279 }
280
281 /**
282 * Gets the PWM Input
283 * @param pwmChannel PWM channel to get.
284 * @param dutyCycleAndPeriod Double array to hold Duty Cycle [0] and Period [1].
285 */
286 public void getPWMInput(PWMChannel pwmChannel, double[] dutyCycleAndPeriod) {
287 CANifierJNI.JNI_GetPWMInput(m_handle, pwmChannel.value, dutyCycleAndPeriod);
288 }
289
290 /**
291 * Gets the quadrature encoder's position
292 * @return Position of encoder
293 */
294 public int getQuadraturePosition() {
295 return CANifierJNI.JNI_GetQuadraturePosition(m_handle);
296 }
297
298 /**
299 * Sets the quadrature encoder's position
300 * @param newPosition Position to set
301 * @param timeoutMs
302 Timeout value in ms. If nonzero, function will wait for
303 config success and report an error if it times out.
304 If zero, no blocking or checking is performed.
305 * @return Error Code generated by function. 0 indicates no error.
306 */
307 public ErrorCode setQuadraturePosition(int newPosition, int timeoutMs) {
308 return ErrorCode.valueOf(CANifierJNI.JNI_SetQuadraturePosition(m_handle, newPosition, timeoutMs));
309 }
310
311 /**
312 * Gets the quadrature encoder's velocity
313 * @return Velocity of encoder
314 */
315 public int getQuadratureVelocity() {
316 return CANifierJNI.JNI_GetQuadratureVelocity(m_handle);
317 }
318
319 /**
320 * Configures the period of each velocity sample.
321 * Every 1ms a position value is sampled, and the delta between that sample
322 * and the position sampled kPeriod ms ago is inserted into a filter.
323 * kPeriod is configured with this function.
324 *
325 * @param period
326 * Desired period for the velocity measurement. @see
327 * #VelocityMeasPeriod
328 * @param timeoutMs
329 * Timeout value in ms. If nonzero, function will wait for
330 * config success and report an error if it times out.
331 * If zero, no blocking or checking is performed.
332 * @return Error Code generated by function. 0 indicates no error.
333 */
334 public ErrorCode configVelocityMeasurementPeriod(VelocityPeriod period, int timeoutMs) {
335 int retval = CANifierJNI.JNI_ConfigVelocityMeasurementPeriod(m_handle, period.value, timeoutMs);
336 return ErrorCode.valueOf(retval);
337 }
338
339 /**
340 * Sets the number of velocity samples used in the rolling average velocity
341 * measurement.
342 *
343 * @param windowSize
344 * Number of samples in the rolling average of velocity
345 * measurement. Valid values are 1,2,4,8,16,32. If another
346 * value is specified, it will truncate to nearest support value.
347 * @param timeoutMs
348 * Timeout value in ms. If nonzero, function will wait for
349 * config success and report an error if it times out.
350 * If zero, no blocking or checking is performed.
351 * @return Error Code generated by function. 0 indicates no error.
352 */
353 public ErrorCode configVelocityMeasurementWindow(int windowSize, int timeoutMs) {
354 int retval = CANifierJNI.JNI_ConfigVelocityMeasurementWindow(m_handle, windowSize, timeoutMs);
355 return ErrorCode.valueOf(retval);
356 }
357
358 /**
359 * Sets the value of a custom parameter. This is for arbitrary use.
360 *
361 * Sometimes it is necessary to save calibration/duty cycle/output
362 * information in the device. Particularly if the
363 * device is part of a subsystem that can be replaced.
364 *
365 * @param newValue
366 * Value for custom parameter.
367 * @param paramIndex
368 * Index of custom parameter. [0-1]
369 * @param timeoutMs
370 * Timeout value in ms. If nonzero, function will wait for
371 * config success and report an error if it times out.
372 * If zero, no blocking or checking is performed.
373 * @return Error Code generated by function. 0 indicates no error.
374 */
375 public ErrorCode configSetCustomParam(int newValue, int paramIndex, int timeoutMs) {
376 int retval = CANifierJNI.JNI_ConfigSetCustomParam(m_handle, newValue, paramIndex, timeoutMs);
377 return ErrorCode.valueOf(retval);
378 }
379
380 /**
381 * Gets the value of a custom parameter. This is for arbitrary use.
382 *
383 * Sometimes it is necessary to save calibration/duty cycle/output
384 * information in the device. Particularly if the
385 * device is part of a subsystem that can be replaced.
386 *
387 * @param paramIndex
388 * Index of custom parameter. [0-1]
389 * @param timoutMs
390 * Timeout value in ms. If nonzero, function will wait for
391 * config success and report an error if it times out.
392 * If zero, no blocking or checking is performed.
393 * @return Value of the custom param.
394 */
395 public int configGetCustomParam(int paramIndex, int timoutMs) {
396 int retval = CANifierJNI.JNI_ConfigGetCustomParam(m_handle, paramIndex, timoutMs);
397 return retval;
398 }
399
400 /**
401 * Sets a parameter. Generally this is not used.
402 * This can be utilized in
403 * - Using new features without updating API installation.
404 * - Errata workarounds to circumvent API implementation.
405 * - Allows for rapid testing / unit testing of firmware.
406 *
407 * @param param
408 * Parameter enumeration.
409 * @param value
410 * Value of parameter.
411 * @param subValue
412 * Subvalue for parameter. Maximum value of 255.
413 * @param ordinal
414 * Ordinal of parameter.
415 * @param timeoutMs
416 * Timeout value in ms. If nonzero, function will wait for
417 * config success and report an error if it times out.
418 * If zero, no blocking or checking is performed.
419 * @return Error Code generated by function. 0 indicates no error.
420 */
421 public ErrorCode configSetParameter(ParamEnum param, double value, int subValue, int ordinal, int timeoutMs) {
422 return configSetParameter(param.value, value, subValue, ordinal, timeoutMs);
423 }
424
425 /**
426 * Sets a parameter. Generally this is not used.
427 * This can be utilized in
428 * - Using new features without updating API installation.
429 * - Errata workarounds to circumvent API implementation.
430 * - Allows for rapid testing / unit testing of firmware.
431 *
432 * @param param
433 * Parameter enumeration.
434 * @param value
435 * Value of parameter.
436 * @param subValue
437 * Subvalue for parameter. Maximum value of 255.
438 * @param ordinal
439 * Ordinal of parameter.
440 * @param timeoutMs
441 * Timeout value in ms. If nonzero, function will wait for
442 * config success and report an error if it times out.
443 * If zero, no blocking or checking is performed.
444 * @return Error Code generated by function. 0 indicates no error.
445 */
446 public ErrorCode configSetParameter(int param, double value, int subValue, int ordinal, int timeoutMs) {
447 int retval = CANifierJNI.JNI_ConfigSetParameter(m_handle, param, value, subValue, ordinal,
448 timeoutMs);
449 return ErrorCode.valueOf(retval);
450 }
451 /**
452 * Gets a parameter. Generally this is not used.
453 * This can be utilized in
454 * - Using new features without updating API installation.
455 * - Errata workarounds to circumvent API implementation.
456 * - Allows for rapid testing / unit testing of firmware.
457 *
458 * @param param
459 * Parameter enumeration.
460 * @param ordinal
461 * Ordinal of parameter.
462 * @param timeoutMs
463 * Timeout value in ms. If nonzero, function will wait for
464 * config success and report an error if it times out.
465 * If zero, no blocking or checking is performed.
466 * @return Value of parameter.
467 */
468 public double configGetParameter(ParamEnum param, int ordinal, int timeoutMs) {
469 return CANifierJNI.JNI_ConfigGetParameter(m_handle, param.value, ordinal, timeoutMs);
470 }
471 /**
472 * Sets the period of the given status frame.
473 *
474 * @param statusFrame
475 * Frame whose period is to be changed.
476 * @param periodMs
477 * Period in ms for the given frame.
478 * @param timeoutMs
479 * Timeout value in ms. If nonzero, function will wait for
480 * config success and report an error if it times out.
481 * If zero, no blocking or checking is performed.
482 * @return Error Code generated by function. 0 indicates no error.
483 */
484 public ErrorCode setStatusFramePeriod(CANifierStatusFrame statusFrame, int periodMs, int timeoutMs) {
485 int retval = CANifierJNI.JNI_SetStatusFramePeriod(m_handle, statusFrame.value, periodMs, timeoutMs);
486 return ErrorCode.valueOf(retval);
487 }
488 /**
489 * Sets the period of the given status frame.
490 *
491 * @param statusFrame
492 * Frame whose period is to be changed.
493 * @param periodMs
494 * Period in ms for the given frame.
495 * @param timeoutMs
496 * Timeout value in ms. If nonzero, function will wait for
497 * config success and report an error if it times out.
498 * If zero, no blocking or checking is performed.
499 * @return Error Code generated by function. 0 indicates no error.
500 */
501 public ErrorCode setStatusFramePeriod(int statusFrame, int periodMs, int timeoutMs) {
502 int retval = CANifierJNI.JNI_SetStatusFramePeriod(m_handle, statusFrame, periodMs, timeoutMs);
503 return ErrorCode.valueOf(retval);
504 }
505
506 /**
507 * Gets the period of the given status frame.
508 *
509 * @param frame
510 * Frame to get the period of.
511 * @param timeoutMs
512 * Timeout value in ms. If nonzero, function will wait for
513 * config success and report an error if it times out.
514 * If zero, no blocking or checking is performed.
515 * @return Period of the given status frame.
516 */
517 public int getStatusFramePeriod(CANifierStatusFrame frame, int timeoutMs) {
518 return CANifierJNI.JNI_GetStatusFramePeriod(m_handle, frame.value, timeoutMs);
519 }
520
521 /**
522 * Sets the period of the given control frame.
523 *
524 * @param frame
525 * Frame whose period is to be changed.
526 * @param periodMs
527 * Period in ms for the given frame.
528 * @return Error Code generated by function. 0 indicates no error.
529 */
530 public ErrorCode setControlFramePeriod(CANifierControlFrame frame, int periodMs) {
531 int retval = CANifierJNI.JNI_SetControlFramePeriod(m_handle, frame.value, periodMs);
532 return ErrorCode.valueOf(retval);
533 }
534 /**
535 * Sets the period of the given control frame.
536 *
537 * @param frame
538 * Frame whose period is to be changed.
539 * @param periodMs
540 * Period in ms for the given frame.
541 * @return Error Code generated by function. 0 indicates no error.
542 */
543 public ErrorCode setControlFramePeriod(int frame, int periodMs) {
544 int retval = CANifierJNI.JNI_SetControlFramePeriod(m_handle, frame, periodMs);
545 return ErrorCode.valueOf(retval);
546 }
547
548 /**
549 * Gets the firmware version of the device.
550 *
551 * @return Firmware version of device.
552 */
553 public int getFirmwareVersion() {
554 return CANifierJNI.JNI_GetFirmwareVersion(m_handle);
555 }
556
557 /**
558 * Returns true if the device has reset since last call.
559 *
560 * @return Has a Device Reset Occurred?
561 */
562 public boolean hasResetOccurred() {
563 return CANifierJNI.JNI_HasResetOccurred(m_handle);
564 }
565
566 // ------ Faults ----------//
567 /**
568 * Gets the CANifier fault status
569 *
570 * @param toFill
571 * Container for fault statuses.
572 * @return Error Code generated by function. 0 indicates no error.
573 */
574 public ErrorCode getFaults(CANifierFaults toFill) {
575 int bits = CANifierJNI.JNI_GetFaults(m_handle);
576 toFill.update(bits);
577 return getLastError();
578 }
579 /**
580 * Gets the CANifier sticky fault status
581 *
582 * @param toFill
583 * Container for sticky fault statuses.
584 * @return Error Code generated by function. 0 indicates no error.
585 */
586 public ErrorCode getStickyFaults(CANifierStickyFaults toFill) {
587 int bits = CANifierJNI.JNI_GetStickyFaults(m_handle);
588 toFill.update(bits);
589 return getLastError();
590 }
591 /**
592 * Clears the Sticky Faults
593 *
594 * @return Error Code generated by function. 0 indicates no error.
595 */
596 public ErrorCode clearStickyFaults(int timeoutMs) {
597 int retval = CANifierJNI.JNI_ClearStickyFaults(m_handle, timeoutMs);
598 return ErrorCode.valueOf(retval);
599 }
600
601 /**
602 * Gets the bus voltage seen by the device.
603 *
604 * @return The bus voltage value (in volts).
605 */
606 public double getBusVoltage() {
607 return CANifierJNI.JNI_GetBusVoltage(m_handle);
608 }
609
610 /**
611 * @return The Device Number
612 */
613 public int getDeviceID(){
614 return m_deviceNumber;
615 }
616}