Now you can download a copy of these docs so you can use them offline! Download now
CANJaguar.cpp
1 /*----------------------------------------------------------------------------*/
2 /* Copyright (c) FIRST 2009. All Rights Reserved. */
3 /* Open Source Software - may be modified and shared by FRC teams. The code */
4 /* must be accompanied by the FIRST BSD license file in $(WIND_BASE)/WPILib. */
5 /*----------------------------------------------------------------------------*/
6 
7 #include "CANJaguar.h"
8 #define tNIRIO_i32 int
9 #include "ChipObject/NiFpga.h"
10 #include "CAN/JaguarCANDriver.h"
11 #include "CAN/can_proto.h"
12 #include "NetworkCommunication/UsageReporting.h"
13 #include "WPIErrors.h"
14 #include <stdio.h>
15 #include "LiveWindow/LiveWindow.h"
16 
17 #define swap16(x) ( (((x)>>8) &0x00FF) \
18  | (((x)<<8) &0xFF00) )
19 #define swap32(x) ( (((x)>>24)&0x000000FF) \
20  | (((x)>>8) &0x0000FF00) \
21  | (((x)<<8) &0x00FF0000) \
22  | (((x)<<24)&0xFF000000) )
23 
24 #define kFullMessageIDMask (CAN_MSGID_API_M | CAN_MSGID_MFR_M | CAN_MSGID_DTYPE_M)
25 
26 const int32_t CANJaguar::kControllerRate;
27 constexpr double CANJaguar::kApproxBusVoltage;
28 
32 void CANJaguar::InitCANJaguar()
33 {
34  m_table = NULL;
35  m_transactionSemaphore = semMCreate(SEM_Q_PRIORITY | SEM_INVERSION_SAFE | SEM_DELETE_SAFE);
36  if (m_deviceNumber < 1 || m_deviceNumber > 63)
37  {
38  char buf[256];
39  snprintf(buf, 256, "device number \"%d\" must be between 1 and 63", m_deviceNumber);
40  wpi_setWPIErrorWithContext(ParameterOutOfRange, buf);
41  return;
42  }
43  uint32_t fwVer = GetFirmwareVersion();
44  if (StatusIsFatal())
45  return;
46  // 3330 was the first shipping RDK firmware version for the Jaguar
47  if (fwVer >= 3330 || fwVer < 101)
48  {
49  char buf[256];
50  if (fwVer < 3330)
51  {
52  snprintf(buf, 256, "Jag #%d firmware (%d) is too old (must be at least version 101 of the FIRST approved firmware)", m_deviceNumber, fwVer);
53  }
54  else
55  {
56  snprintf(buf, 256, "Jag #%d firmware (%d) is not FIRST approved (must be at least version 101 of the FIRST approved firmware)", m_deviceNumber, fwVer);
57  }
58  wpi_setWPIErrorWithContext(JaguarVersionError, buf);
59  return;
60  }
61  switch (m_controlMode)
62  {
63  case kPercentVbus:
64  case kVoltage:
65  // No additional configuration required... start enabled.
66  EnableControl();
67  break;
68  default:
69  break;
70  }
71  m_safetyHelper = new MotorSafetyHelper(this);
72 
73  nUsageReporting::report(nUsageReporting::kResourceType_CANJaguar, m_deviceNumber, m_controlMode);
74  LiveWindow::GetInstance()->AddActuator("CANJaguar", m_deviceNumber, 0, this);
75 }
76 
82 CANJaguar::CANJaguar(uint8_t deviceNumber, ControlMode controlMode)
83  : m_deviceNumber (deviceNumber)
84  , m_controlMode (controlMode)
85  , m_transactionSemaphore (NULL)
86  , m_maxOutputVoltage (kApproxBusVoltage)
87  , m_safetyHelper (NULL)
88 {
89  InitCANJaguar();
90 }
91 
92 CANJaguar::~CANJaguar()
93 {
94  delete m_safetyHelper;
95  m_safetyHelper = NULL;
96  semDelete(m_transactionSemaphore);
97  m_transactionSemaphore = NULL;
98 }
99 
113 void CANJaguar::Set(float outputValue, uint8_t syncGroup)
114 {
115  uint32_t messageID;
116  uint8_t dataBuffer[8];
117  uint8_t dataSize;
118 
119  if (m_safetyHelper && !m_safetyHelper->IsAlive())
120  {
121  EnableControl();
122  }
123 
124  switch(m_controlMode)
125  {
126  case kPercentVbus:
127  {
128  messageID = LM_API_VOLT_T_SET;
129  if (outputValue > 1.0) outputValue = 1.0;
130  if (outputValue < -1.0) outputValue = -1.0;
131  dataSize = packPercentage(dataBuffer, outputValue);
132  }
133  break;
134  case kSpeed:
135  {
136  messageID = LM_API_SPD_T_SET;
137  dataSize = packFXP16_16(dataBuffer, outputValue);
138  }
139  break;
140  case kPosition:
141  {
142  messageID = LM_API_POS_T_SET;
143  dataSize = packFXP16_16(dataBuffer, outputValue);
144  }
145  break;
146  case kCurrent:
147  {
148  messageID = LM_API_ICTRL_T_SET;
149  dataSize = packFXP8_8(dataBuffer, outputValue);
150  }
151  break;
152  case kVoltage:
153  {
154  messageID = LM_API_VCOMP_T_SET;
155  dataSize = packFXP8_8(dataBuffer, outputValue);
156  }
157  break;
158  default:
159  return;
160  }
161  if (syncGroup != 0)
162  {
163  dataBuffer[dataSize] = syncGroup;
164  dataSize++;
165  }
166  setTransaction(messageID, dataBuffer, dataSize);
167  if (m_safetyHelper) m_safetyHelper->Feed();
168 }
169 
183 {
184  uint8_t dataBuffer[8];
185  uint8_t dataSize;
186 
187  switch(m_controlMode)
188  {
189  case kPercentVbus:
190  getTransaction(LM_API_VOLT_SET, dataBuffer, &dataSize);
191  if (dataSize == sizeof(int16_t))
192  {
193  return unpackPercentage(dataBuffer);
194  }
195  break;
196  case kSpeed:
197  getTransaction(LM_API_SPD_SET, dataBuffer, &dataSize);
198  if (dataSize == sizeof(int32_t))
199  {
200  return unpackFXP16_16(dataBuffer);
201  }
202  break;
203  case kPosition:
204  getTransaction(LM_API_POS_SET, dataBuffer, &dataSize);
205  if (dataSize == sizeof(int32_t))
206  {
207  return unpackFXP16_16(dataBuffer);
208  }
209  break;
210  case kCurrent:
211  getTransaction(LM_API_ICTRL_SET, dataBuffer, &dataSize);
212  if (dataSize == sizeof(int16_t))
213  {
214  return unpackFXP8_8(dataBuffer);
215  }
216  break;
217  case kVoltage:
218  getTransaction(LM_API_VCOMP_SET, dataBuffer, &dataSize);
219  if (dataSize == sizeof(int16_t))
220  {
221  return unpackFXP8_8(dataBuffer);
222  }
223  break;
224  }
225  return 0.0;
226 }
227 
234 {
235  DisableControl();
236 }
237 
245 void CANJaguar::PIDWrite(float output)
246 {
247  if (m_controlMode == kPercentVbus)
248  {
249  Set(output);
250  }
251  else
252  {
253  wpi_setWPIErrorWithContext(IncompatibleMode, "PID only supported in PercentVbus mode");
254  }
255 }
256 
257 uint8_t CANJaguar::packPercentage(uint8_t *buffer, double value)
258 {
259  int16_t intValue = (int16_t)(value * 32767.0);
260  *((int16_t*)buffer) = swap16(intValue);
261  return sizeof(int16_t);
262 }
263 
264 uint8_t CANJaguar::packFXP8_8(uint8_t *buffer, double value)
265 {
266  int16_t intValue = (int16_t)(value * 256.0);
267  *((int16_t*)buffer) = swap16(intValue);
268  return sizeof(int16_t);
269 }
270 
271 uint8_t CANJaguar::packFXP16_16(uint8_t *buffer, double value)
272 {
273  int32_t intValue = (int32_t)(value * 65536.0);
274  *((int32_t*)buffer) = swap32(intValue);
275  return sizeof(int32_t);
276 }
277 
278 uint8_t CANJaguar::packint16_t(uint8_t *buffer, int16_t value)
279 {
280  *((int16_t*)buffer) = swap16(value);
281  return sizeof(int16_t);
282 }
283 
284 uint8_t CANJaguar::packint32_t(uint8_t *buffer, int32_t value)
285 {
286  *((int32_t*)buffer) = swap32(value);
287  return sizeof(int32_t);
288 }
289 
290 double CANJaguar::unpackPercentage(uint8_t *buffer)
291 {
292  int16_t value = *((int16_t*)buffer);
293  value = swap16(value);
294  return value / 32767.0;
295 }
296 
297 double CANJaguar::unpackFXP8_8(uint8_t *buffer)
298 {
299  int16_t value = *((int16_t*)buffer);
300  value = swap16(value);
301  return value / 256.0;
302 }
303 
304 double CANJaguar::unpackFXP16_16(uint8_t *buffer)
305 {
306  int32_t value = *((int32_t*)buffer);
307  value = swap32(value);
308  return value / 65536.0;
309 }
310 
311 int16_t CANJaguar::unpackint16_t(uint8_t *buffer)
312 {
313  int16_t value = *((int16_t*)buffer);
314  return swap16(value);
315 }
316 
317 int32_t CANJaguar::unpackint32_t(uint8_t *buffer)
318 {
319  int32_t value = *((int32_t*)buffer);
320  return swap32(value);
321 }
322 
334 int32_t CANJaguar::sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize)
335 {
336  static const uint32_t kTrustedMessages[] = {
337  LM_API_VOLT_T_EN, LM_API_VOLT_T_SET, LM_API_SPD_T_EN, LM_API_SPD_T_SET,
338  LM_API_VCOMP_T_EN, LM_API_VCOMP_T_SET, LM_API_POS_T_EN, LM_API_POS_T_SET,
339  LM_API_ICTRL_T_EN, LM_API_ICTRL_T_SET};
340  int32_t status=0;
341 
342  for (uint8_t i=0; i<(sizeof(kTrustedMessages)/sizeof(kTrustedMessages[0])); i++)
343  {
344  if ((kFullMessageIDMask & messageID) == kTrustedMessages[i])
345  {
346  uint8_t dataBuffer[8];
347  dataBuffer[0] = 0;
348  dataBuffer[1] = 0;
349  // Make sure the data will still fit after adjusting for the token.
350  if (dataSize > 6)
351  {
352  // TODO: I would rather this not have to set the global error
353  wpi_setGlobalWPIErrorWithContext(ParameterOutOfRange, "dataSize > 6");
354  return 0;
355  }
356  for (uint8_t j=0; j < dataSize; j++)
357  {
358  dataBuffer[j + 2] = data[j];
359  }
360  FRC_NetworkCommunication_JaguarCANDriver_sendMessage(messageID, dataBuffer, dataSize + 2, &status);
361  return status;
362  }
363  }
364  FRC_NetworkCommunication_JaguarCANDriver_sendMessage(messageID, data, dataSize, &status);
365  return status;
366 }
367 
377 int32_t CANJaguar::receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, float timeout)
378 {
379  int32_t status = 0;
380  FRC_NetworkCommunication_JaguarCANDriver_receiveMessage(messageID, data, dataSize,
381  (uint32_t)(timeout * 1000), &status);
382  return status;
383 }
384 
395 void CANJaguar::setTransaction(uint32_t messageID, const uint8_t *data, uint8_t dataSize)
396 {
397  uint32_t ackMessageID = LM_API_ACK | m_deviceNumber;
398  int32_t localStatus = 0;
399 
400  // If there was an error on this object and it wasn't a timeout, refuse to talk to the device
401  // Call ClearError() on the object to try again
402  if (StatusIsFatal() && GetError().GetCode() != -44087)
403  return;
404 
405  // Make sure we don't have more than one transaction with the same Jaguar outstanding.
406  semTake(m_transactionSemaphore, WAIT_FOREVER);
407 
408  // Throw away any stale acks.
409  receiveMessage(&ackMessageID, NULL, 0, 0.0f);
410  // Send the message with the data.
411  localStatus = sendMessage(messageID | m_deviceNumber, data, dataSize);
412  wpi_setErrorWithContext(localStatus, "sendMessage");
413  // Wait for an ack.
414  localStatus = receiveMessage(&ackMessageID, NULL, 0);
415  wpi_setErrorWithContext(localStatus, "receiveMessage");
416 
417  // Transaction complete.
418  semGive(m_transactionSemaphore);
419 }
420 
430 void CANJaguar::getTransaction(uint32_t messageID, uint8_t *data, uint8_t *dataSize)
431 {
432  uint32_t targetedMessageID = messageID | m_deviceNumber;
433  int32_t localStatus = 0;
434 
435  // If there was an error on this object and it wasn't a timeout, refuse to talk to the device
436  // Call ClearError() on the object to try again
437  if (StatusIsFatal() && GetError().GetCode() != -44087)
438  {
439  if (dataSize != NULL)
440  *dataSize = 0;
441  return;
442  }
443 
444  // Make sure we don't have more than one transaction with the same Jaguar outstanding.
445  semTake(m_transactionSemaphore, WAIT_FOREVER);
446 
447  // Throw away any stale responses.
448  receiveMessage(&targetedMessageID, NULL, 0, 0.0f);
449  // Send the message requesting data.
450  localStatus = sendMessage(targetedMessageID, NULL, 0);
451  wpi_setErrorWithContext(localStatus, "sendMessage");
452  // Caller may have set bit31 for remote frame transmission so clear invalid bits[31-29]
453  targetedMessageID &= 0x1FFFFFFF;
454  // Wait for the data.
455  localStatus = receiveMessage(&targetedMessageID, data, dataSize);
456  wpi_setErrorWithContext(localStatus, "receiveMessage");
457 
458  // Transaction complete.
459  semGive(m_transactionSemaphore);
460 }
461 
469 void CANJaguar::SetSpeedReference(SpeedReference reference)
470 {
471  uint8_t dataBuffer[8];
472 
473  dataBuffer[0] = reference;
474  setTransaction(LM_API_SPD_REF, dataBuffer, sizeof(uint8_t));
475 }
476 
482 CANJaguar::SpeedReference CANJaguar::GetSpeedReference()
483 {
484  uint8_t dataBuffer[8];
485  uint8_t dataSize;
486 
487  getTransaction(LM_API_SPD_REF, dataBuffer, &dataSize);
488  if (dataSize == sizeof(uint8_t))
489  {
490  return (SpeedReference)*dataBuffer;
491  }
492  return kSpeedRef_None;
493 }
494 
503 void CANJaguar::SetPositionReference(PositionReference reference)
504 {
505  uint8_t dataBuffer[8];
506 
507  dataBuffer[0] = reference;
508  setTransaction(LM_API_POS_REF, dataBuffer, sizeof(uint8_t));
509 }
510 
516 CANJaguar::PositionReference CANJaguar::GetPositionReference()
517 {
518  uint8_t dataBuffer[8];
519  uint8_t dataSize;
520 
521  getTransaction(LM_API_POS_REF, dataBuffer, &dataSize);
522  if (dataSize == sizeof(uint8_t))
523  {
524  return (PositionReference)*dataBuffer;
525  }
526  return kPosRef_None;
527 }
528 
536 void CANJaguar::SetPID(double p, double i, double d)
537 {
538  uint8_t dataBuffer[8];
539  uint8_t dataSize;
540 
541  switch(m_controlMode)
542  {
543  case kPercentVbus:
544  case kVoltage:
545  wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
546  break;
547  case kSpeed:
548  dataSize = packFXP16_16(dataBuffer, p);
549  setTransaction(LM_API_SPD_PC, dataBuffer, dataSize);
550  dataSize = packFXP16_16(dataBuffer, i);
551  setTransaction(LM_API_SPD_IC, dataBuffer, dataSize);
552  dataSize = packFXP16_16(dataBuffer, d);
553  setTransaction(LM_API_SPD_DC, dataBuffer, dataSize);
554  break;
555  case kPosition:
556  dataSize = packFXP16_16(dataBuffer, p);
557  setTransaction(LM_API_POS_PC, dataBuffer, dataSize);
558  dataSize = packFXP16_16(dataBuffer, i);
559  setTransaction(LM_API_POS_IC, dataBuffer, dataSize);
560  dataSize = packFXP16_16(dataBuffer, d);
561  setTransaction(LM_API_POS_DC, dataBuffer, dataSize);
562  break;
563  case kCurrent:
564  dataSize = packFXP16_16(dataBuffer, p);
565  setTransaction(LM_API_ICTRL_PC, dataBuffer, dataSize);
566  dataSize = packFXP16_16(dataBuffer, i);
567  setTransaction(LM_API_ICTRL_IC, dataBuffer, dataSize);
568  dataSize = packFXP16_16(dataBuffer, d);
569  setTransaction(LM_API_ICTRL_DC, dataBuffer, dataSize);
570  break;
571  }
572 }
573 
580 {
581  uint8_t dataBuffer[8];
582  uint8_t dataSize;
583 
584  switch(m_controlMode)
585  {
586  case kPercentVbus:
587  case kVoltage:
588  wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
589  break;
590  case kSpeed:
591  getTransaction(LM_API_SPD_PC, dataBuffer, &dataSize);
592  if (dataSize == sizeof(int32_t))
593  {
594  return unpackFXP16_16(dataBuffer);
595  }
596  break;
597  case kPosition:
598  getTransaction(LM_API_POS_PC, dataBuffer, &dataSize);
599  if (dataSize == sizeof(int32_t))
600  {
601  return unpackFXP16_16(dataBuffer);
602  }
603  break;
604  case kCurrent:
605  getTransaction(LM_API_ICTRL_PC, dataBuffer, &dataSize);
606  if (dataSize == sizeof(int32_t))
607  {
608  return unpackFXP16_16(dataBuffer);
609  }
610  break;
611  }
612  return 0.0;
613 }
614 
621 {
622  uint8_t dataBuffer[8];
623  uint8_t dataSize;
624 
625  switch(m_controlMode)
626  {
627  case kPercentVbus:
628  case kVoltage:
629  wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
630  break;
631  case kSpeed:
632  getTransaction(LM_API_SPD_IC, dataBuffer, &dataSize);
633  if (dataSize == sizeof(int32_t))
634  {
635  return unpackFXP16_16(dataBuffer);
636  }
637  break;
638  case kPosition:
639  getTransaction(LM_API_POS_IC, dataBuffer, &dataSize);
640  if (dataSize == sizeof(int32_t))
641  {
642  return unpackFXP16_16(dataBuffer);
643  }
644  break;
645  case kCurrent:
646  getTransaction(LM_API_ICTRL_IC, dataBuffer, &dataSize);
647  if (dataSize == sizeof(int32_t))
648  {
649  return unpackFXP16_16(dataBuffer);
650  }
651  break;
652  }
653  return 0.0;
654 }
655 
662 {
663  uint8_t dataBuffer[8];
664  uint8_t dataSize;
665 
666  switch(m_controlMode)
667  {
668  case kPercentVbus:
669  case kVoltage:
670  wpi_setWPIErrorWithContext(IncompatibleMode, "PID constants only apply in Speed, Position, and Current mode");
671  break;
672  case kSpeed:
673  getTransaction(LM_API_SPD_DC, dataBuffer, &dataSize);
674  if (dataSize == sizeof(int32_t))
675  {
676  return unpackFXP16_16(dataBuffer);
677  }
678  break;
679  case kPosition:
680  getTransaction(LM_API_POS_DC, dataBuffer, &dataSize);
681  if (dataSize == sizeof(int32_t))
682  {
683  return unpackFXP16_16(dataBuffer);
684  }
685  break;
686  case kCurrent:
687  getTransaction(LM_API_ICTRL_DC, dataBuffer, &dataSize);
688  if (dataSize == sizeof(int32_t))
689  {
690  return unpackFXP16_16(dataBuffer);
691  }
692  break;
693  }
694  return 0.0;
695 }
696 
707 void CANJaguar::EnableControl(double encoderInitialPosition)
708 {
709  uint8_t dataBuffer[8];
710  uint8_t dataSize = 0;
711 
712  switch(m_controlMode)
713  {
714  case kPercentVbus:
715  setTransaction(LM_API_VOLT_T_EN, dataBuffer, dataSize);
716  break;
717  case kSpeed:
718  setTransaction(LM_API_SPD_T_EN, dataBuffer, dataSize);
719  break;
720  case kPosition:
721  dataSize = packFXP16_16(dataBuffer, encoderInitialPosition);
722  setTransaction(LM_API_POS_T_EN, dataBuffer, dataSize);
723  break;
724  case kCurrent:
725  setTransaction(LM_API_ICTRL_T_EN, dataBuffer, dataSize);
726  break;
727  case kVoltage:
728  setTransaction(LM_API_VCOMP_T_EN, dataBuffer, dataSize);
729  break;
730  }
731 }
732 
739 {
740  uint8_t dataBuffer[8];
741  uint8_t dataSize = 0;
742 
743  switch(m_controlMode)
744  {
745  case kPercentVbus:
746  setTransaction(LM_API_VOLT_DIS, dataBuffer, dataSize);
747  break;
748  case kSpeed:
749  setTransaction(LM_API_SPD_DIS, dataBuffer, dataSize);
750  break;
751  case kPosition:
752  setTransaction(LM_API_POS_DIS, dataBuffer, dataSize);
753  break;
754  case kCurrent:
755  setTransaction(LM_API_ICTRL_DIS, dataBuffer, dataSize);
756  break;
757  case kVoltage:
758  setTransaction(LM_API_VCOMP_DIS, dataBuffer, dataSize);
759  break;
760  }
761 }
762 
771 void CANJaguar::ChangeControlMode(ControlMode controlMode)
772 {
773  // Disable the previous mode
774  DisableControl();
775 
776  // Update the local mode
777  m_controlMode = controlMode;
778 
779  nUsageReporting::report(nUsageReporting::kResourceType_CANJaguar, m_deviceNumber, m_controlMode);
780 }
781 
789 CANJaguar::ControlMode CANJaguar::GetControlMode()
790 {
791  uint8_t dataBuffer[8];
792  uint8_t dataSize;
793 
794  getTransaction(LM_API_STATUS_CMODE, dataBuffer, &dataSize);
795  if (dataSize == sizeof(int8_t))
796  {
797  return (ControlMode)dataBuffer[0];
798  }
799  return kPercentVbus;
800 }
801 
808 {
809  uint8_t dataBuffer[8];
810  uint8_t dataSize;
811 
812  getTransaction(LM_API_STATUS_VOLTBUS, dataBuffer, &dataSize);
813  if (dataSize == sizeof(int16_t))
814  {
815  return unpackFXP8_8(dataBuffer);
816  }
817  return 0.0;
818 }
819 
826 {
827  uint8_t dataBuffer[8];
828  uint8_t dataSize;
829 
830  // Read the volt out which is in Volts units.
831  getTransaction(LM_API_STATUS_VOUT, dataBuffer, &dataSize);
832  if (dataSize == sizeof(int16_t))
833  {
834  return unpackFXP8_8(dataBuffer);
835  }
836  return 0.0;
837 }
838 
845 {
846  uint8_t dataBuffer[8];
847  uint8_t dataSize;
848 
849  getTransaction(LM_API_STATUS_CURRENT, dataBuffer, &dataSize);
850  if (dataSize == sizeof(int16_t))
851  {
852  return unpackFXP8_8(dataBuffer);
853  }
854  return 0.0;
855 }
856 
863 {
864  uint8_t dataBuffer[8];
865  uint8_t dataSize;
866 
867  getTransaction(LM_API_STATUS_TEMP, dataBuffer, &dataSize);
868  if (dataSize == sizeof(int16_t))
869  {
870  return unpackFXP8_8(dataBuffer);
871  }
872  return 0.0;
873 }
874 
881 {
882  uint8_t dataBuffer[8];
883  uint8_t dataSize;
884 
885  getTransaction(LM_API_STATUS_POS, dataBuffer, &dataSize);
886  if (dataSize == sizeof(int32_t))
887  {
888  return unpackFXP16_16(dataBuffer);
889  }
890  return 0.0;
891 }
892 
899 {
900  uint8_t dataBuffer[8];
901  uint8_t dataSize;
902 
903  getTransaction(LM_API_STATUS_SPD, dataBuffer, &dataSize);
904  if (dataSize == sizeof(int32_t))
905  {
906  return unpackFXP16_16(dataBuffer);
907  }
908  return 0.0;
909 }
910 
917 {
918  uint8_t dataBuffer[8];
919  uint8_t dataSize;
920 
921  getTransaction(LM_API_STATUS_LIMIT, dataBuffer, &dataSize);
922  if (dataSize == sizeof(uint8_t))
923  {
924  return (*dataBuffer & kForwardLimit) != 0;
925  }
926  return 0;
927 }
928 
935 {
936  uint8_t dataBuffer[8];
937  uint8_t dataSize;
938 
939  getTransaction(LM_API_STATUS_LIMIT, dataBuffer, &dataSize);
940  if (dataSize == sizeof(uint8_t))
941  {
942  return (*dataBuffer & kReverseLimit) != 0;
943  }
944  return 0;
945 }
946 
953 {
954  uint8_t dataBuffer[8];
955  uint8_t dataSize;
956 
957  getTransaction(LM_API_STATUS_FAULT, dataBuffer, &dataSize);
958  if (dataSize == sizeof(uint16_t))
959  {
960  return unpackint16_t(dataBuffer);
961  }
962  return 0;
963 }
964 
974 {
975  uint8_t dataBuffer[8];
976  uint8_t dataSize;
977 
978  getTransaction(LM_API_STATUS_POWER, dataBuffer, &dataSize);
979  if (dataSize == sizeof(uint8_t))
980  {
981  bool powerCycled = (*dataBuffer != 0);
982 
983  // Clear the power cycled bit now that we've accessed it
984  if (powerCycled)
985  {
986  dataBuffer[0] = 1;
987  setTransaction(LM_API_STATUS_POWER, dataBuffer, sizeof(uint8_t));
988  }
989 
990  return powerCycled;
991  }
992  return 0;
993 }
994 
1003 void CANJaguar::SetVoltageRampRate(double rampRate)
1004 {
1005  uint8_t dataBuffer[8];
1006  uint8_t dataSize;
1007 
1008  switch(m_controlMode)
1009  {
1010  case kPercentVbus:
1011  dataSize = packPercentage(dataBuffer, rampRate / (m_maxOutputVoltage * kControllerRate));
1012  setTransaction(LM_API_VOLT_SET_RAMP, dataBuffer, dataSize);
1013  break;
1014  case kVoltage:
1015  dataSize = packFXP8_8(dataBuffer, rampRate / kControllerRate);
1016  setTransaction(LM_API_VCOMP_IN_RAMP, dataBuffer, dataSize);
1017  break;
1018  default:
1019  return;
1020  }
1021 }
1022 
1029 {
1030  uint8_t dataBuffer[8];
1031  uint8_t dataSize;
1032 
1033  // Set the MSB to tell the 2CAN that this is a remote message.
1034  getTransaction(0x80000000 | CAN_MSGID_API_FIRMVER, dataBuffer, &dataSize);
1035  if (dataSize == sizeof(uint32_t))
1036  {
1037  return unpackint32_t(dataBuffer);
1038  }
1039  return 0;
1040 }
1041 
1048 {
1049  uint8_t dataBuffer[8];
1050  uint8_t dataSize;
1051 
1052  getTransaction(LM_API_HWVER, dataBuffer, &dataSize);
1053  if (dataSize == sizeof(uint8_t)+sizeof(uint8_t))
1054  {
1055  if (*dataBuffer == m_deviceNumber)
1056  {
1057  return *(dataBuffer+1);
1058  }
1059  }
1060  // Assume Gray Jag if there is no response
1061  return LM_HWVER_JAG_1_0;
1062 }
1063 
1071 void CANJaguar::ConfigNeutralMode(NeutralMode mode)
1072 {
1073  uint8_t dataBuffer[8];
1074 
1075  dataBuffer[0] = mode;
1076  setTransaction(LM_API_CFG_BRAKE_COAST, dataBuffer, sizeof(uint8_t));
1077 }
1078 
1084 void CANJaguar::ConfigEncoderCodesPerRev(uint16_t codesPerRev)
1085 {
1086  uint8_t dataBuffer[8];
1087  uint8_t dataSize;
1088 
1089  dataSize = packint16_t(dataBuffer, codesPerRev);
1090  setTransaction(LM_API_CFG_ENC_LINES, dataBuffer, dataSize);
1091 }
1092 
1102 {
1103  uint8_t dataBuffer[8];
1104  uint8_t dataSize;
1105 
1106  dataSize = packint16_t(dataBuffer, turns);
1107  setTransaction(LM_API_CFG_POT_TURNS, dataBuffer, dataSize);
1108 }
1109 
1120 void CANJaguar::ConfigSoftPositionLimits(double forwardLimitPosition, double reverseLimitPosition)
1121 {
1122  uint8_t dataBuffer[8];
1123  uint8_t dataSize;
1124 
1125  dataSize = packFXP16_16(dataBuffer, forwardLimitPosition);
1126  dataBuffer[dataSize++] = forwardLimitPosition > reverseLimitPosition;
1127  setTransaction(LM_API_CFG_LIMIT_FWD, dataBuffer, dataSize);
1128 
1129  dataSize = packFXP16_16(dataBuffer, reverseLimitPosition);
1130  dataBuffer[dataSize++] = forwardLimitPosition <= reverseLimitPosition;
1131  setTransaction(LM_API_CFG_LIMIT_REV, dataBuffer, dataSize);
1132 
1133  dataBuffer[0] = kLimitMode_SoftPositionLimits;
1134  setTransaction(LM_API_CFG_LIMIT_MODE, dataBuffer, sizeof(uint8_t));
1135 }
1136 
1143 {
1144  uint8_t dataBuffer[8];
1145 
1146  dataBuffer[0] = kLimitMode_SwitchInputsOnly;
1147  setTransaction(LM_API_CFG_LIMIT_MODE, dataBuffer, sizeof(uint8_t));
1148 }
1149 
1159 {
1160  uint8_t dataBuffer[8];
1161  uint8_t dataSize;
1162 
1163  m_maxOutputVoltage = voltage;
1164  dataSize = packFXP8_8(dataBuffer, voltage);
1165  setTransaction(LM_API_CFG_MAX_VOUT, dataBuffer, dataSize);
1166 }
1167 
1176 void CANJaguar::ConfigFaultTime(float faultTime)
1177 {
1178  uint8_t dataBuffer[8];
1179  uint8_t dataSize;
1180 
1181  // Message takes ms
1182  dataSize = packint16_t(dataBuffer, (int16_t)(faultTime * 1000.0));
1183  setTransaction(LM_API_CFG_FAULT_TIME, dataBuffer, dataSize);
1184 }
1185 
1191 void CANJaguar::UpdateSyncGroup(uint8_t syncGroup)
1192 {
1193  sendMessage(CAN_MSGID_API_SYNC, &syncGroup, sizeof(syncGroup));
1194 }
1195 
1196 
1197 void CANJaguar::SetExpiration(float timeout)
1198 {
1199  if (m_safetyHelper) m_safetyHelper->SetExpiration(timeout);
1200 }
1201 
1202 float CANJaguar::GetExpiration()
1203 {
1204  if (!m_safetyHelper) return 0.0;
1205  return m_safetyHelper->GetExpiration();
1206 }
1207 
1208 bool CANJaguar::IsAlive()
1209 {
1210  if (!m_safetyHelper) return false;
1211  return m_safetyHelper->IsAlive();
1212 }
1213 
1214 bool CANJaguar::IsSafetyEnabled()
1215 {
1216  if (!m_safetyHelper) return false;
1217  return m_safetyHelper->IsSafetyEnabled();
1218 }
1219 
1220 void CANJaguar::SetSafetyEnabled(bool enabled)
1221 {
1222  if (m_safetyHelper) m_safetyHelper->SetSafetyEnabled(enabled);
1223 }
1224 
1225 void CANJaguar::GetDescription(char *desc)
1226 {
1227  sprintf(desc, "CANJaguar ID %d", m_deviceNumber);
1228 }
1229 
1237 {
1238  DisableControl();
1239 }
1240 
1241 void CANJaguar::ValueChanged(ITable* source, const std::string& key, EntryValue value, bool isNew) {
1242  Set(value.f);
1243 }
1244 
1246  if (m_table != NULL) {
1247  m_table->PutNumber("Value", Get());
1248  }
1249 }
1250 
1252  if (m_table != NULL) {
1253  m_table->AddTableListener("Value", this, true);
1254  }
1255 }
1256 
1258  if (m_table != NULL) {
1259  m_table->RemoveTableListener(this);
1260  }
1261 }
1262 
1264  return "Speed Controller";
1265 }
1266 
1267 void CANJaguar::InitTable(ITable *subTable) {
1268  m_table = subTable;
1269  UpdateTable();
1270 }
1271 
1273  return m_table;
1274 }
1275 
1276 
void SetSpeedReference(SpeedReference reference)
Definition: CANJaguar.cpp:469
void InitTable(ITable *subTable)
Definition: CANJaguar.cpp:1267
virtual void RemoveTableListener(ITableListener *listener)=0
void ConfigFaultTime(float faultTime)
Definition: CANJaguar.cpp:1176
void AddActuator(const char *subsystem, const char *name, LiveWindowSendable *component)
Definition: LiveWindow.cpp:96
float GetOutputCurrent()
Definition: CANJaguar.cpp:844
virtual float Get()
Definition: CANJaguar.cpp:182
virtual void PutNumber(std::string key, double value)=0
void SetPID(double p, double i, double d)
Definition: CANJaguar.cpp:536
void ValueChanged(ITable *source, const std::string &key, EntryValue value, bool isNew)
Definition: CANJaguar.cpp:1241
static int32_t sendMessage(uint32_t messageID, const uint8_t *data, uint8_t dataSize)
Definition: CANJaguar.cpp:334
bool GetForwardLimitOK()
Definition: CANJaguar.cpp:916
Definition: ITable.h:26
virtual void AddTableListener(ITableListener *listener)=0
void ConfigNeutralMode(NeutralMode mode)
Definition: CANJaguar.cpp:1071
void ConfigPotentiometerTurns(uint16_t turns)
Definition: CANJaguar.cpp:1101
void SetSafetyEnabled(bool enabled)
void SetVoltageRampRate(double rampRate)
Definition: CANJaguar.cpp:1003
double GetSpeed()
Definition: CANJaguar.cpp:898
virtual void getTransaction(uint32_t messageID, uint8_t *data, uint8_t *dataSize)
Definition: CANJaguar.cpp:430
SpeedReference GetSpeedReference()
Definition: CANJaguar.cpp:482
virtual Error & GetError()
Retrieve the current error. Get the current error information associated with this sensor...
Definition: ErrorBase.cpp:33
void ConfigMaxOutputVoltage(double voltage)
Definition: CANJaguar.cpp:1158
void ConfigSoftPositionLimits(double forwardLimitPosition, double reverseLimitPosition)
Definition: CANJaguar.cpp:1120
float GetBusVoltage()
Definition: CANJaguar.cpp:807
double GetI()
Definition: CANJaguar.cpp:620
void SetPositionReference(PositionReference reference)
Definition: CANJaguar.cpp:503
void DisableControl()
Definition: CANJaguar.cpp:738
void StopLiveWindowMode()
Definition: CANJaguar.cpp:1257
float GetTemperature()
Definition: CANJaguar.cpp:862
CANJaguar(uint8_t deviceNumber, ControlMode controlMode=kPercentVbus)
Definition: CANJaguar.cpp:82
uint16_t GetFaults()
Definition: CANJaguar.cpp:952
bool GetReverseLimitOK()
Definition: CANJaguar.cpp:934
static LiveWindow * GetInstance()
Definition: LiveWindow.cpp:13
ControlMode GetControlMode()
Definition: CANJaguar.cpp:789
static int32_t receiveMessage(uint32_t *messageID, uint8_t *data, uint8_t *dataSize, float timeout=0.02)
Definition: CANJaguar.cpp:377
virtual void Set(float value, uint8_t syncGroup=0)
Definition: CANJaguar.cpp:113
void ChangeControlMode(ControlMode controlMode)
Definition: CANJaguar.cpp:771
virtual void PIDWrite(float output)
Definition: CANJaguar.cpp:245
virtual bool StatusIsFatal() const
Check if the current error code represents a fatal error.
Definition: ErrorBase.cpp:178
ITable * GetTable()
Definition: CANJaguar.cpp:1272
double GetPosition()
Definition: CANJaguar.cpp:880
void ConfigEncoderCodesPerRev(uint16_t codesPerRev)
Definition: CANJaguar.cpp:1084
virtual void setTransaction(uint32_t messageID, const uint8_t *data, uint8_t dataSize)
Definition: CANJaguar.cpp:395
virtual uint32_t GetFirmwareVersion()
Definition: CANJaguar.cpp:1028
float GetOutputVoltage()
Definition: CANJaguar.cpp:825
void StopMotor()
Definition: CANJaguar.cpp:1236
virtual void Disable()
Definition: CANJaguar.cpp:233
uint8_t GetHardwareVersion()
Definition: CANJaguar.cpp:1047
std::string GetSmartDashboardType()
Definition: CANJaguar.cpp:1263
PositionReference GetPositionReference()
Definition: CANJaguar.cpp:516
double GetD()
Definition: CANJaguar.cpp:661
Definition: ITable.h:13
double GetP()
Definition: CANJaguar.cpp:579
void StartLiveWindowMode()
Definition: CANJaguar.cpp:1251
static void UpdateSyncGroup(uint8_t syncGroup)
Definition: CANJaguar.cpp:1191
void UpdateTable()
Definition: CANJaguar.cpp:1245
void EnableControl(double encoderInitialPosition=0.0)
Definition: CANJaguar.cpp:707
void DisableSoftPositionLimits()
Definition: CANJaguar.cpp:1142
bool GetPowerCycled()
Definition: CANJaguar.cpp:973

Generated on Sat Apr 26 2014 12:26:45 for WPILibC++ by doxygen 1.8.6