Commanders
Arduino buttons/bus library
CANCommander.cpp
1 /*************************************************************
2 project: <Commanders>
3 author: <Thierry PARIS>
4 description: <CAN Commander>
5 *************************************************************/
6 
7 #include <Commanders.h>
8 
9 #ifdef NO_CANCOMMANDER
10 #pragma message ("Commanders : No CAN commander !")
11 #else
12 #include <mcp_can.h>
13 #include <SPI.h>
14 
15 CANCommanderClass *CANCommanderClass::pCANCommander;
16 
17 volatile uint8_t Flag_Recv = 0; // variable d'�change avec l'interruption IRQ
18 
19 /*
20 * ISR CAN (Routine de Service d'Interruption)
21 * le flag IRQ monte quand au moins un message est re�u
22 * le flag IRQ ne retombe QUE si tous les messages sont lus
23 */
24 
25 void MCP2515_ISR()
26 {
27  Flag_Recv = 1;
28 }
29 
30 void CANCommanderClass::begin(uint8_t inSPIpin, uint8_t inSpeed, uint8_t inInterrupt, uint16_t inId)
31 {
32 #ifdef COMMANDERS_PRINT_COMMANDERS
33  uint8_t SPIpin = inSPIpin;
34  uint8_t Speed = inSpeed;
35  uint8_t Interrupt = inInterrupt;
36  uint16_t Id = inId;
37 #endif
38 
39 #ifdef VISUALSTUDIO
40  pinMode(inSPIpin, OUTPUT_RESERVED);
41  pinMode(inInterrupt, OUTPUT_RESERVED);
42 #endif
43  this->pCan = new MCP_CAN(inSPIpin);
44  while (CAN_OK != this->pCan->begin(inSpeed)) // init can bus with baudrate
45  {
46 #ifdef COMMANDERS_DEBUG_MODE
47  Serial.println(F("CAN BUS Shield init fail"));
48  Serial.println(F("Init CAN BUS Shield again"));
49 #endif
50  delay(100);
51  }
52 #ifdef COMMANDERS_DEBUG_MODE
53  Serial.println(F("CAN BUS Shield init ok!"));
54 #endif
55 
56  /* INTERRUPT values as macro argument :
57  Board int.0 int.1 int.2 int.3 int.4 int.5
58  Uno, Ethernet 2 3
59  Mega2560 2 3 21 20 19 18
60  Leonardo 3 2 0 1 7
61  */
62  attachInterrupt(inInterrupt, MCP2515_ISR, FALLING);
63 
64  /*
65  * set mask & filter
66  */
67 
68  this->pCan->init_Mask(0, 0, 0xFFFF); // All is tested
69  this->pCan->init_Mask(1, 0, 0xFFFF);
70 
71  this->pCan->init_Filt(0, 0, inId);
72  this->pCan->init_Filt(1, 0, 0); // idem
73  this->pCan->init_Filt(2, 0, 0); // Reception possible : Id 40 � 4F (hex)
74  this->pCan->init_Filt(3, 0, 0); // idem
75  this->pCan->init_Filt(4, 0, 0); // Reception possible : Id 00 � 0F
76  this->pCan->init_Filt(5, 0, 0); // Idem
77 }
78 
79 
80 /*
81 * Routine de r�cup�ration des messages CAN dans la m�moire circulaire _Circule
82 * appel�e par LOOP lorsque Flag_Recv = 1;
83 */
84 void CANCommanderClass::CAN_recup()
85 {
86  unsigned char len = 0; // nombre d'octets du message
87  unsigned char buf[8]; // message
88  unsigned char Id; // Id (on devrait plut�t utiliser un int car il y a 11 bits)
89 
90  while (CAN_MSGAVAIL == this->pCan->checkReceive())
91  {
92  this->pCan->readMsgBuf(&len, buf); // read data, len: data length, buf: data buf
93  Id = (unsigned char) this->pCan->getCanId();
94  if ((unsigned int) (this->Ncan + len + 2) < sizeof(this->Circule))
95  { // il reste de la place dans _Circule
96  this->Circule[this->indexW] = Id; // enregistrement de Id
97  this->indexW++;
98  this->Ncan++;
99  if (this->indexW == sizeof(this->Circule))
100  this->indexW = 0;
101  this->Circule[this->indexW] = len; // enregistrement de len
102  this->indexW++;
103  this->Ncan++;
104  if (this->indexW == sizeof(this->Circule))
105  this->indexW = 0;
106  for (uint8_t z = 0; z<len; z++)
107  {
108  this->Circule[this->indexW] = buf[z]; // enregistrement du message
109  this->indexW++;
110  this->Ncan++;
111  if (this->indexW == sizeof(this->Circule))
112  this->indexW = 0;
113  }
114  }
115  else
116  {
117  this->CANoverflow = 1; // d�passement de la capacite de Circule
118  // le message est perdu
119  }
120  }
121 }
122 
123 unsigned long CANCommanderClass::loop()
124 {
125  if (Flag_Recv)
126  {
127  Flag_Recv = 0; // Flag MCP2515 ready for a new IRQ
128  this->CAN_recup(); // Get all the messages
129  }
130 
131  // Handle the first message in the buffer _Circule...
132 #ifdef COMMANDERS_DEBUG_MODE
133  uint8_t RId;
134 #endif
135  uint8_t Rlen;
136  uint8_t Rbuf[8];
137 
138  while (this->Ncan > 2)
139  { // The minimal size of one message is 3 bytes long !
140  this->Ncan--;
141 #ifdef COMMANDERS_DEBUG_MODE
142  RId = this->Circule[this->indexR]; // recup Id
143 
144  Serial.print(F("CAN id "));
145  Serial.print(RId);
146  Serial.print(F(", data "));
147 #endif
148  this->indexR++;
149  if (this->indexR == sizeof(this->Circule))
150  this->indexR = 0;
151  this->Ncan--;
152  Rlen = this->Circule[this->indexR]; // recup length
153  this->indexR++;
154  if (this->indexR == sizeof(this->Circule))
155  this->indexR = 0;
156  for (int k = 0; k < Rlen; k++)
157  {
158  this->Ncan--;
159  Rbuf[k] = this->Circule[this->indexR]; // recup octets message
160  this->indexR++;
161  if (this->indexR == sizeof(this->Circule))
162  this->indexR = 0;
163 #ifdef COMMANDERS_DEBUG_MODE
164  Serial.print(F("0x"));
165  Serial.print(Rbuf[k], HEX);
166 #endif
167  }
168 #ifdef COMMANDERS_DEBUG_MODE
169  Serial.println("");
170 #endif
171  // le message est maintenant dans les globales RId, Rlen et Rbuf[..]
172 
173  long four = Rbuf[0];
174  long three = Rbuf[1];
175  long two = Rbuf[2];
176  long one = Rbuf[3];
177 
178  //Rebuild the recomposed long by using bitshift.
179  unsigned long foundID = ((four << 0) & 0xFF) + ((three << 8) & 0xFFFF) + ((two << 16) & 0xFFFFFF) + ((one << 24) & 0xFFFFFFFF);
180 
181  COMMANDERS_EVENT_TYPE lastEventType = (COMMANDERS_EVENT_TYPE)Rbuf[4];
182 
183  int foundData = Rbuf[6];
184  foundData = foundData << 8;
185  foundData |= Rbuf[5];
186 
187  Commanders::RaiseEvent(foundID, lastEventType, foundData);
188 
189  Commanders::SetLastEventType(lastEventType);
190  Commanders::SetLastEventData(foundData);
191  return foundID;
192  }
193 
194  return UNDEFINED_ID;
195 }
196 
197 #ifdef COMMANDERS_PRINT_COMMANDERS
198 void CANCommanderClass::printCommander()
199 {
200  Serial.print(F("Commander: CANCommander - Pin SPI: "));
201  Serial.print(this->SPIpin);
202  Serial.print(F(" / Speed: "));
203  switch (this->Speed)
204  {
205  case CAN_5KBPS: Serial.print(F("5KBPS")); break;
206  case CAN_10KBPS: Serial.print(F("10KBPS")); break;
207  case CAN_20KBPS: Serial.print(F("20KBPS")); break;
208  case CAN_25KBPS: Serial.print(F("25KBPS")); break;
209  case CAN_31K25BPS: Serial.print(F("31K25BPS")); break;
210  case CAN_33KBPS: Serial.print(F("33KBPS")); break;
211  case CAN_40KBPS: Serial.print(F("40KBPS")); break;
212  case CAN_50KBPS: Serial.print(F("50KBPS")); break;
213  case CAN_80KBPS: Serial.print(F("80KBPS")); break;
214  case CAN_83K3BPS: Serial.print(F("83K3BPS")); break;
215  case CAN_95KBPS: Serial.print(F("95KBPS")); break;
216  case CAN_100KBPS: Serial.print(F("100KBPS")); break;
217  case CAN_125KBPS: Serial.print(F("125KBPS")); break;
218  case CAN_200KBPS: Serial.print(F("200KBPS")); break;
219  case CAN_250KBPS: Serial.print(F("250KBPS")); break;
220  case CAN_500KBPS: Serial.print(F("500KBPS")); break;
221  case CAN_666KBPS: Serial.print(F("666KBPS")); break;
222  case CAN_1000KBPS: Serial.print(F("1000KBPS")); break;
223  }
224  Serial.print(F(" / Interrupt: "));
225  Serial.print(this->Interrupt);
226  Serial.print(F(" / ID: "));
227  Serial.println(this->Id);
228 }
229 #endif
230 #endif
#define UNDEFINED_ID
Definition: Events.h:38
static void SetLastEventData(int inData)
Definition: Commanders.hpp:93
static void SetLastEventType(COMMANDERS_EVENT_TYPE inEvent)
Definition: Commanders.hpp:89
COMMANDERS_EVENT_TYPE
Definition: Events.h:25
unsigned long loop()
static unsigned long RaiseEvent(unsigned long inId, COMMANDERS_EVENT_TYPE inEvent = COMMANDERS_EVENT_MOVEPOSITIONID, int inData = 0)
Definition: Commanders.cpp:27
void begin(uint8_t inSPIpin, uint8_t inSpeed, uint8_t inInterrupt, uint16_t inId)