Commanders
Arduino buttons/bus library
DccCommander.cpp
1 /*************************************************************
2 project: <Commanders>
3 author: <Thierry PARIS>
4 description: <Dcc Commander>
5 *************************************************************/
6 
7 #include <Commanders.h>
8 
9 #ifdef NO_DCCCOMMANDER
10 #pragma message ("Commanders : No DCC commander !")
11 #else
12 #ifdef VISUALSTUDIO
13 DCC_Decoder DCC_Decoder::DCCInstance;
14 #endif
15 
16 DccAccDecoderPacket DccCommanderClass::func_AccPacket;
17 DccCommanderClass *DccCommanderClass::pDccCommander;
18 
20 //
21 // DCC accessory packet handler
22 //
23 void DccCommanderClass::DccAccessoryDecoderPacket(int address, boolean activate, uint8_t data)
24 {
25  int realAddress = address;
26 
27 #ifdef COMMANDERS_DEBUG_MODE
28 #ifdef COMMANDERS_DEBUG_VERBOSE_MODE
29  Serial.print(F("Dcc packet found : real data : "));
30  Serial.print(realAddress);
31  Serial.print(F(" / "));
32  Serial.print(data, DEC);
33  Serial.print(F(" / "));
34  Serial.print(activate, DEC);
35 #endif
36 #endif
37 
38  if (!DccCommander.UseRawDccAddresses)
39  {
40  realAddress -= 1;
41  realAddress *= 4;
42  realAddress += 1;
43  realAddress += (data & 0x06) >> 1;
44  data = data % 2;
45  }
46 
47 #ifdef COMMANDERS_DEBUG_MODE
48 #ifdef COMMANDERS_DEBUG_VERBOSE_MODE
49  Serial.print(F(" converted : "));
50  Serial.print(realAddress);
51  Serial.print(F(" / "));
52  Serial.print(data, DEC);
53  Serial.print(F(" / "));
54  Serial.println(activate, DEC);
55 #endif
56 #endif
57 
58  // Sent packets are (on my MS2 !) :
59  // id / data / 1
60  // id / data / 1
61  // id / data / 1
62  // id / data / 0
63  // The last byte is to activate for a while (three times at 1 !) and then deactivate the motor !
64  // DccCommander will react only on the deactivate flag to avoid double events.
65  if (activate == DccCommander.RaiseEventOnActivation)
66  {
67  if (DCCINT(realAddress, data) == DccCommander.LastDccId)
68  if (millis() - DccCommander.LastEventDate < DccCommander.RaiseEventDebounceDelay)
69  {
70 #ifdef COMMANDERS_DEBUG_MODE
71  Serial.print(F("DccCommander packet IGNORED :"));
72  Serial.print(realAddress);
73  Serial.print(F(" / "));
74  Serial.println(data, DEC);
75 #endif
76  return;
77  }
78 
79  DccCommander.LastEventDate = millis();
80 
81 #ifdef COMMANDERS_DEBUG_MODE
82  Serial.print(F("DccCommander packet received :"));
83  Serial.print(realAddress);
84  Serial.print(F(" / "));
85  Serial.println(data, DEC);
86 #endif
87  if (DccCommanderClass::func_AccPacket)
88  (DccCommanderClass::func_AccPacket)(realAddress, activate, data);
89  else
90  {
92 
93  DccCommander.LastDccId = DCCINT(realAddress, data);
94  }
95  }
96 }
97 
98 #ifdef COMMANDERS_DEBUG_MODE
99 #define CHECK(val, text) CheckIndex(val, F(text))
100 #else
101 #define CHECK(val, text)
102 #endif
103 
104 bool status = false;
105 void StatusBlink_handler()
106 {
107  digitalWrite2f(Commanders::StatusLedPin, status ? HIGH : LOW);
108  status = !status;
109 }
110 
111 void DccCommanderClass::begin(int i, int j, int interruptNumber, boolean inInterruptMonitor, boolean inUseRawDccAddresses)
112 {
113  DCC.beginDecoder(i, j, interruptNumber);
114  this->UseRawDccAddresses = inUseRawDccAddresses;
115 #ifdef VISUALSTUDIO
116  // In VS, the exception address is also the pin number.
117  // pinMode() is just here to declare the pin used for the emulator...
118  pinMode(interruptNumber, OUTPUT_INTERRUPT);
119 #endif
120  this->LastDccId = UNDEFINED_ID;
121  this->LastEventDate = 0;
122  this->RaiseEventOnActivation = false;
123  this->RaiseEventDebounceDelay = 200;
124 
125  DCC.SetBasicAccessoryDecoderPacketHandler(DccAccessoryDecoderPacket, true);
126 
127  if (inInterruptMonitor)
128  DCC.SetInterruptMonitor(StatusBlink_handler);
129 
130 #ifdef COMMANDERS_PRINT_COMMANDERS
131  this->Interrupt = interruptNumber;
132 #endif
133 }
134 
135 void DccCommanderClass::RaiseEventWhen(boolean inRaiseEventOnActivation, int inRaiseEventDebounceDelay)
136 {
137  this->RaiseEventOnActivation = inRaiseEventOnActivation;
138  this->RaiseEventDebounceDelay = inRaiseEventDebounceDelay;
139 }
140 
142 {
144 }
145 
146 #define MINTIME 2
147 #ifdef COMMANDERS_DEBUG_MODE
148 #ifdef COMMANDERS_DEBUG_VERBOSE_MODE
149 static int countLoop = 0;
150 #endif
151 #endif
152 
153 static unsigned long start = 0;
154 
155 #define ELAPSEDTIME ((unsigned long) -2)
156 
157 unsigned long DccCommanderClass::loop()
158 {
159  //if (start == 0)
160  //start = millis();
161 
162  DCC.loop();
163 #ifdef COMMANDERS_DEBUG_MODE
164 #ifdef COMMANDERS_DEBUG_VERBOSE_MODE
165  countLoop++;
166 #endif
167 #endif
168 
169  //if (millis() - start > MINTIME)
170  {
171  /*
172 #ifdef COMMANDERS_DEBUG_MODE
173 #ifdef COMMANDERS_DEBUG_VERBOSE_MODE
174  Serial.print(F("DCC commander loop : "));
175  Serial.println(countLoop, DEC);
176  countLoop = 0;
177 #endif
178 #endif
179 */
180  start = 0;
181  if (this->LastDccId != UNDEFINED_ID)
182  {
183  unsigned long last = this->LastDccId;
184  this->LastDccId = UNDEFINED_ID;
187  return last;
188  }
189  }
190 
191  return UNDEFINED_ID;
192 }
193 
194 //DccAccDecoderPacket DccCommanderClass::func_AccPacket = NULL;
195 
197 {
198  DccCommanderClass::func_AccPacket = func;
199 }
200 
201 #ifdef COMMANDERS_DEBUG_MODE
202 void DccCommanderClass::printEvent(unsigned long inId, COMMANDERS_EVENT_TYPE inEventType, int inEventData)
203 {
204  Serial.print(F("DCC Commander event : Address : "));
205  Serial.print(DCCID(inId), DEC);
206  Serial.print(F(" / "));
207  Serial.print(DCCACTIVATION(inId), DEC);
208  Serial.print(F(" / "));
209  switch (inEventType)
210  {
211  case COMMANDERS_EVENT_NONE: Serial.println(F("NONE")); break;
212  case COMMANDERS_EVENT_TOGGLE: Serial.println(F("TOGGLE")); break;
213  case COMMANDERS_EVENT_MOVE:
214  Serial.print(F("MOVE "));
215  switch ((COMMANDERS_MOVE_TYPE)inEventData)
216  {
217  case COMMANDERS_MOVE_MORE: Serial.println(F("MORE")); break;
218  case COMMANDERS_MOVE_LESS: Serial.println(F("LESS")); break;
219  case COMMANDERS_MOVE_STOP: Serial.println(F("STOP")); break;
220  case COMMANDERS_MOVE_LEFT: Serial.println(F("LEFT")); break;
221  case COMMANDERS_MOVE_RIGHT: Serial.println(F("RIGHT")); break;
222  case COMMANDERS_MOVE_CENTER: Serial.println(F("CENTER")); break;
223  case COMMANDERS_MOVE_TOP: Serial.println(F("TOP")); break;
224  case COMMANDERS_MOVE_BOTTOM: Serial.println(F("BOTTOM")); break;
225  case COMMANDERS_MOVE_STRAIGHT: Serial.println(F("STRAIGHT")); break;
226  case COMMANDERS_MOVE_DIVERGE: Serial.println(F("DIVERGE")); break;
227  case COMMANDERS_MOVE_ON: Serial.println(F("ON")); break;
228  case COMMANDERS_MOVE_OFF: Serial.println(F("OFF")); break;
229  }
230  break;
232  Serial.print(F("MOVEPOSITION : "));
233  Serial.println(inEventData, DEC);
234  break;
236  Serial.println(F("MOVEPOSITIONID"));
237  break;
239  Serial.print(F("MOVEPOSITIONINDEX : "));
240  Serial.println(inEventData, DEC);
241  break;
243  Serial.print(F("CONFIG : "));
244  Serial.print(COMMANDERSCONFIGADDRESS(inEventData), DEC);
245  Serial.print(F(" / "));
246  Serial.println(COMMANDERSCONFIGVALUE(inEventData), DEC);
247  break;
248  }
249 }
250 #endif
251 
252 #ifdef COMMANDERS_PRINT_COMMANDERS
254 {
255  Serial.print(F("Commander: DccCommander - Interrupt: "));
256  Serial.println(this->Interrupt);
257 }
258 #endif
259 
260 #endif
COMMANDERS_EVENT_TYPE
Definition: Events.h:25
static void SetAccessoryDecoderPacketHandler(DccAccDecoderPacket func)
static void SetLastEventData(int inData)
Definition: Commanders.hpp:93
static void SetLastEventType(COMMANDERS_EVENT_TYPE inEvent)
Definition: Commanders.hpp:89
unsigned long loop()
COMMANDERS_MOVE_TYPE
Definition: Events.h:8
void RaiseEventWhen(boolean inRaiseEventOnActivation, int inRaiseEventDebounceDelay = 200)
#define UNDEFINED_ID
Definition: Events.h:38
void begin(int i, int j, int interruptNumber, boolean inInterruptMonitor = false, boolean inUseRawDccAddresses = false)
static GPIO_pin_t StatusLedPin
Definition: Commanders.hpp:33
static void printEvent(unsigned long inId, COMMANDERS_EVENT_TYPE inEventType, int inEventData)
static unsigned long RaiseEvent(unsigned long inId, COMMANDERS_EVENT_TYPE inEvent = COMMANDERS_EVENT_MOVEPOSITIONID, int inData = 0)
Definition: Commanders.cpp:27
static void DccAccessoryDecoderPacket(int address, boolean activate, uint8_t data)