Commanders
Arduino buttons/bus library
ButtonsCommanderSwitch.cpp
1 /*************************************************************
2 project: <Commanders>
3 author: <Thierry PARIS>
4 description: <Switch button with debounce.>
5 *************************************************************/
6 
7 #include <Commanders.h>
8 #include <stdint.h>
9 #ifndef NO_BUTTONSCOMMANDER
10 #ifndef NO_BUTTONSCOMMANDERSWITCH
11 
13 {
14  this->debounceDelay = 50;
15  this->lastSelectedPin = DP_INVALID;
16 }
17 
18 void beginItem(EventPin *inpIdPin)
19 {
20  if (inpIdPin->Pin != DP_INVALID)
21  {
22  pinMode2f(inpIdPin->Pin, INPUT_PULLUP);
23  }
24 }
25 
27 {
28 #ifdef COMMANDERS_DEBUG_MODE
29  if (this->EventPins.pFirst == NULL)
30  Serial.println(F("This switch button have no ID defined : begin() must be called AFTER AddEvent !"));
31 #endif
32 
33  CMDRSCHAINEDLISTITEM<EventPin> *pCurr = this->EventPins.pFirst;
34  while (pCurr != NULL)
35  {
36  beginItem(pCurr->Obj);
37 
38  pCurr->Obj->LastButtonState = HIGH;
39  pCurr->Obj->LastDebounceTime = 0;
40 
41  pCurr = pCurr->pNext;
42  }
43 }
44 
45 unsigned long ButtonsCommanderSwitch::GetId(GPIO_pin_t inPin, COMMANDERS_EVENT_TYPE *apEvent, int *apData) const
46 {
47  CMDRSCHAINEDLISTITEM<EventPin> *pCurr = this->EventPins.pFirst;
48  while (pCurr != NULL)
49  {
50  if (inPin == pCurr->Obj->Pin)
51  {
52  if (apEvent != NULL)
53  *apEvent = pCurr->Obj->Event;
54  if (apData != NULL)
55  *apData = pCurr->Obj->Data;
56  return pCurr->Obj->Id;
57  }
58 
59  pCurr = pCurr->pNext;
60  }
61  return UNDEFINED_ID;
62 }
63 
64 // Returns the index of the new added position.
65 EventPin *ButtonsCommanderSwitch::AddEvent(unsigned long inId, int inPin, COMMANDERS_EVENT_TYPE inEvent, int inData)
66 {
67  EventPin *pIdpin = new EventPin();
68  pIdpin->Pin = Arduino_to_GPIO_pin(inPin);
69  pIdpin->Id = inId;
70  pIdpin->Event = inEvent;
71  pIdpin->Data = inData;
72  pIdpin->LastButtonState = HIGH;
73  pIdpin->LastDebounceTime = 0;
74  this->EventPins.AddItem(pIdpin);
75 
76  return pIdpin;
77 }
78 
79 unsigned long ButtonsCommanderSwitch::loopOnePin(unsigned long inId, GPIO_pin_t inPin, unsigned long inPreviousId,unsigned long inDebounceDelay,
80  byte *inpLastPinState, unsigned long *inpLastDebounceTime, bool inSendEvent)
81 {
82  unsigned long haveFound = UNDEFINED_ID;
83 
84  if (inPin != DP_INVALID)
85  {
86  // read the state of the switch into a local variable:
87  int pinState = digitalRead2f(inPin);
88 
89  // check to see if you just pressed the button
90  // (i.e. the input went from HIGH to LOW, inverted by INPUT_PULLUP), and you've waited
91  // long enough since the last press to ignore any noise:
92 
93  // If the switch changed, due to noise or pressing:
94  if (pinState != *inpLastPinState)
95  {
96  // reset the debouncing timer
97 #ifdef COMMANDERS_DEBUG_MODE
98  Serial.print(F("Pin "));
99  Serial.print(inPin);
100  Serial.print(pinState == HIGH ? F(" high") : F(" low"));
101  Serial.println(F(" debounced !"));
102 #endif
103  *inpLastPinState = pinState;
104  *inpLastDebounceTime = millis();
105  return UNDEFINED_ID;
106  }
107 
108  if (*inpLastDebounceTime > 0 && (millis() - *inpLastDebounceTime) > inDebounceDelay)
109  {
110  // whatever the pinState is at, it's been there for longer
111  // than the debounce delay, so take it as the actual current state:
112 
113  if (pinState == LOW)
114  {
115  haveFound = inId;
116 
117  // raise the event for the new pin.
118  if (inSendEvent)
120  }
121  else
122  {
123  // raise the event for the old pin.
124  if (inSendEvent && inPreviousId != UNDEFINED_ID)
126  }
127 
128  *inpLastDebounceTime = 0;
129  }
130 
131  // save the pinState. Next time through the loop,
132  // it'll be the lastButtonState:
133  *inpLastPinState = pinState;
134  }
135 
136  return haveFound;
137 }
138 
140 {
141  CMDRSCHAINEDLISTITEM<EventPin> *pCurr = this->EventPins.pFirst;
142  while (pCurr != NULL)
143  {
144  if (pCurr->Obj->Pin != DP_INVALID)
145  {
146  // Initialize first switch state at start
147  int pinState = digitalRead2f(pCurr->Obj->Pin);
148 
149  if (pinState == LOW)
150  {
151  this->lastSelectedPin = pCurr->Obj->Pin;
152  Commanders::RaiseEvent(pCurr->Obj->Id, pCurr->Obj->Event, pCurr->Obj->Data);
153  }
154  }
155 
156  pCurr = pCurr->pNext;
157  }
158 }
159 
161 {
162  if (this->EventPins.pFirst == NULL)
163  {
164 #ifdef COMMANDERS_DEBUG_MODE
165  if (this->debounceDelay != UINT32_MAX) // If the error message has not been yet shown...
166  {
167  Serial.println(F("This switch button have no ID defined : call AddEvent() and begin() !"));
168  // use it as a debug flag !
169  this->debounceDelay = UINT32_MAX; // The error message has been shown...
170  }
171 #endif
172  return UNDEFINED_ID;
173  }
174 
175  EventPin *pCurr = this->EventPins.pCurrentItem->Obj;
176 
177  unsigned long haveFound = ButtonsCommanderSwitch::loopOnePin(pCurr->Id, pCurr->Pin, UNDEFINED_ID, this->debounceDelay, &pCurr->LastButtonState, &pCurr->LastDebounceTime, false);
178 
179  if (haveFound != UNDEFINED_ID)
180  {
181  this->lastSelectedPin = pCurr->Pin;
182  Commanders::RaiseEvent(haveFound, pCurr->Event, pCurr->Data);
183  }
184 
185  this->EventPins.NextCurrent();
186 
187  return haveFound;
188 }
189 
190 #ifdef COMMANDERS_PRINT_COMMANDERS
191 void ButtonsCommanderSwitch::printCommander()
192 {
193  Serial.println(F(" Switch"));
194 
195  CMDRSCHAINEDLISTITEM<EventPin> *pCurr = this->EventPins.pFirst;
196  while (pCurr != NULL)
197  {
198  Serial.print(F(" Event - Pin: "));
199  Serial.print(GPIO_to_Arduino_pin(pCurr->Obj->Pin));
200  Serial.print(F(" / Id: "));
201  Serial.print(pCurr->Obj->Id);
202  Serial.print(F(" / Event type: "));
203  Commanders::printEventType(pCurr->Obj->Event, true);
204  Commanders::printEventData(pCurr->Obj->Event, pCurr->Obj->Data);
205  Serial.print(F(" / Debounce delay: "));
206  Serial.print(this->debounceDelay);
207  Serial.println(F(""));
208 
209  pCurr = pCurr->pNext;
210  }
211 }
212 #endif
213 #endif
214 #endif
static void printEventType(COMMANDERS_EVENT_TYPE inEventType, bool inDataFollow)
CMDRSCHAINEDLISTITEM< T > * pCurrentItem
Definition: Chain.hpp:39
static unsigned long loopOnePin(unsigned long inId, GPIO_pin_t inPin, unsigned long inPreviousId, unsigned long inDebounceDelay, byte *inpLastPinState, unsigned long *inpLastDebounceTime, bool inSendEvent = true)
void AddItem(T *input)
Definition: Chain.hpp:61
EventPin * AddEvent(unsigned long inId, int inPin, COMMANDERS_EVENT_TYPE inEvent = COMMANDERS_EVENT_MOVEPOSITIONID, int inData = 0)
void NextCurrent()
Definition: Chain.hpp:85
COMMANDERS_EVENT_TYPE Event
COMMANDERS_EVENT_TYPE
Definition: Events.h:25
unsigned long GetId() const
CMDRSCHAINEDLISTITEM * pNext
Definition: Chain.hpp:13
unsigned long LastDebounceTime
static void printEventData(COMMANDERS_EVENT_TYPE inEventType, int inEventData)
CMDRSCHAINEDLISTITEM< T > * pFirst
Definition: Chain.hpp:37
unsigned long Id
static unsigned long RaiseEvent(unsigned long inId, COMMANDERS_EVENT_TYPE inEvent = COMMANDERS_EVENT_MOVEPOSITIONID, int inData = 0)
Definition: Commanders.cpp:27
#define UNDEFINED_ID
Definition: Events.h:38