fremoclock  1_3A01
FREMO Clock - Software for UTG
PushButton.c
Go to the documentation of this file.
1 
23 #include <stdbool.h> // typedef bool, const true, const false
24 #include <stdint.h> // typedef uint8_t, typedef uint16_t
25 #include <util/atomic.h> // #define ATOMIC_BLOCK(), ATOMIC_RESTORESTATE
26 #include "PushButton.h" // Prototypes of this module
27 #include "sysdef.h" // BUTTON_PORT, BUTTON_PINS, BUTTON_BACK_PIN,
28  // BUTTON_DOWN_PIN, BUTTON_ENTER_PIN, BUTTON_UP_PIN
29 #include "Timer.h" // WaitTimer()
30 
31 /* -- Constants and types --------------------------------------------------- */
32 
37 typedef enum {
40  BUTTON_UP = 2,
43 } button_t;
44 
46 static const uint16_t BUTTON_PRESSED_VALUE = 5;
47 
49 static const uint16_t BUTTON_REPEAT_VALUE = 50;
50 
52 static const uint16_t UP_DOWN_WAIT = 250;
53 
54 /*
55  * Bit values (flag) for push buttons (see ucButtonStatus).
56  * Used with _BV() to set or test the flags.
57  * 0 = pressed, 1 = repeat, 2-6 = reserved, 7 = served
58  */
59 
61 #define BUTTON_PRESSED 0
62 
64 #define BUTTON_REPEAT 1
65 
67 #define BUTTON_SERVED 7
68 
69 /* -- Variable for buttons -------------------------------------------------- */
70 
75 static volatile uint16_t uiButtonDebounce[NUM_BUTTONS];
76 
83 static volatile uint8_t ucButtonStatus[NUM_BUTTONS];
84 
85 /* -- Function prototypes for push buttons ---------------------------------- */
86 
87 static bool PushButtonSingleShotAction(button_t ucButton);
88 
92 void PushButtonInit(void)
93 {
94  // Initialize Portbits
95  // set DDRx: Done by reset
96  // Pullup on
98  | _BV(BUTTON_UP_PIN) | _BV(BUTTON_DOWN_PIN) );
99 
100  // Initialize variables
101  for (button_t i = 0; i < NUM_BUTTONS; i++)
102  {
103  uiButtonDebounce[i] = 0;
104  ucButtonStatus[i] = 0;
105  }
106 }
107 
114 #pragma GCC diagnostic push // avoid false positive on gcc 4.9.2
115 #pragma GCC diagnostic ignored "-Wreturn-type"
116 static uint8_t PushButtonReadStatus(button_t buttonIdx)
117 {
118  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) // save SREG, cli() and restore SREG
119  {
120  return ucButtonStatus[buttonIdx];
121  }
122 }
123 #pragma GCC diagnostic pop
124 
130 static void PushButtonSetStatusServed(button_t ucButton)
131 {
132  ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
133  {
134  if (ucButtonStatus[ucButton] != 0)
135  {
136  ucButtonStatus[ucButton] |= _BV(BUTTON_SERVED);
137  }
138  }
139 }
140 
148 {
150 }
151 
159 {
161 }
162 
170 {
172 }
173 
181 {
183 }
184 
193 {
194  uint8_t ucbut0;
195 
196  // single shot
197  ucbut0 = PushButtonReadStatus(ucButton); //atomic read!!
198  if ((ucbut0 >= _BV(BUTTON_PRESSED)) && ((ucbut0 & _BV(BUTTON_SERVED)) == 0))
199  {
200  PushButtonSetStatusServed(ucButton);
201  return true;
202  }
203  else
204  {
205  return false;
206  }
207 }
208 
217 uint8_t PushButtonGetUpDownValue(uint8_t ucbut, uint8_t ucmin, uint8_t ucmax)
218 {
219  //TODO: ist hier UP/DOWN getauscht?
220  // DOWN: NmUhr -> ShutD -> Progr -> NmZZt -> NmAZt -> NmSZt -> NmVkz -> NmSvr -> NmUhr
221  // Nein: bei numerischen Werten ist es richtig
222  uint8_t ucbut0 = 0;
223  uint8_t ucbut1 = 0;
224 
225  ucbut1 = ucbut;
226  // repeated action up
227  ucbut0 = PushButtonReadStatus(BUTTON_UP);
228  if ((ucbut0 & _BV(BUTTON_REPEAT)) != 0)
229  {
231  ucbut1++;
232  if (ucbut1 > ucmax) ucbut1 = ucmin;
233  }
234  else if ((ucbut0 >= 1) && ((ucbut0 & _BV(BUTTON_SERVED)) == 0))
235  {
237  ucbut1++;
238  if (ucbut1 > ucmax) ucbut1 = ucmin;
239  }
240  // repeated action down
242  if ((ucbut0 & _BV(BUTTON_REPEAT)) != 0)
243  {
245  ucbut1--;
246  if ((ucbut1 > ucmax) || (ucbut1 < ucmin)) ucbut1 = ucmax;
247  }
248  else if ((ucbut0 >= 1) && ((ucbut0 & _BV(BUTTON_SERVED)) == 0))
249  {
251  ucbut1--;
252  if ((ucbut1 > ucmax) || (ucbut1 < ucmin)) ucbut1 = ucmax;
253  }
254  return ucbut1;
255 }
256 
261 static inline void PushButtonPressed(button_t ucButton)
262 {
263  uiButtonDebounce[ucButton]++; // will overflow after 10 minutes
264  if (uiButtonDebounce[ucButton] == BUTTON_PRESSED_VALUE)
265  {
266  ucButtonStatus[ucButton] |= _BV(BUTTON_PRESSED);
267  }
268  if (uiButtonDebounce[ucButton] == BUTTON_REPEAT_VALUE)
269  {
270  ucButtonStatus[ucButton] |= _BV(BUTTON_REPEAT);
271  }
272 }
273 
278 static inline void PushButtonRelease(button_t ucButton)
279 {
280  uiButtonDebounce[ucButton] = 0;
281  ucButtonStatus[ucButton] = 0;
282 }
283 
293 {
294  // Enter
295  if ((BUTTON_PINS & _BV(BUTTON_ENTER_PIN)) == 0)
296  {
298  }
299  else
300  {
302  }
303 
304  // Back
305  if ((BUTTON_PINS & _BV(BUTTON_BACK_PIN)) == 0)
306  {
308  }
309  else
310  {
312  }
313 
314  // Up
315  if ((BUTTON_PINS & _BV(BUTTON_UP_PIN)) == 0)
316  {
318  }
319  else
320  {
322  }
323 
324  // Down
325  if ((BUTTON_PINS & _BV(BUTTON_DOWN_PIN)) == 0)
326  {
328  }
329  else
330  {
332  }
333 }
bool PushButtonSingleShotBack(void)
Test if button back is pressed.
Definition: PushButton.c:158
#define BUTTON_ENTER_PIN
Pin used for enter button.
Definition: sysdef.h:139
"DOWN" button (down arrow)
Definition: PushButton.c:41
#define BUTTON_PINS
Input register used for buttons.
Definition: sysdef.h:137
#define BUTTON_BACK_PIN
Pin used for back button.
Definition: sysdef.h:140
Number of push buttons (used for array size)
Definition: PushButton.c:42
static const uint16_t BUTTON_PRESSED_VALUE
time in 10ms for button recognized as pressed
Definition: PushButton.c:46
#define BUTTON_SERVED
Button handled.
Definition: PushButton.c:67
void PushButtonInit(void)
Initialization of module.
Definition: PushButton.c:92
#define BUTTON_PRESSED
Button pressed.
Definition: PushButton.c:61
void PushButtonInterrupt(void)
Called by timer interrupt every 10ms.
Definition: PushButton.c:292
static volatile uint8_t ucButtonStatus[NUM_BUTTONS]
Status of the Buttons.
Definition: PushButton.c:83
static void PushButtonRelease(button_t ucButton)
Used by PushButtonInterrupt during interrupt service when button is up.
Definition: PushButton.c:278
button_t
Enum for buttons used.
Definition: PushButton.c:37
void WaitTimer(uint16_t usValue)
Wait for usValue milliseconds.
Definition: Timer.c:121
#define BUTTON_DOWN_PIN
Pin used for down button.
Definition: sysdef.h:142
static const uint16_t UP_DOWN_WAIT
Value to wait in milliseconds.
Definition: PushButton.c:52
"ENTER" button
Definition: PushButton.c:38
bool PushButtonSingleShotUp(void)
Test if button up is pressed.
Definition: PushButton.c:169
Push button debouncing module for Atmel AVR.
A timer module.
static const uint16_t BUTTON_REPEAT_VALUE
time in 10ms for button recognized as repeated
Definition: PushButton.c:49
bool PushButtonSingleShotDown(void)
Test if button down is pressed.
Definition: PushButton.c:180
uint8_t PushButtonGetUpDownValue(uint8_t ucbut, uint8_t ucmin, uint8_t ucmax)
Get selection value by up and down button.
Definition: PushButton.c:217
static volatile uint16_t uiButtonDebounce[NUM_BUTTONS]
Incremented every 10 mS as long as button is pushed.
Definition: PushButton.c:75
"BACK" button (left arrow)
Definition: PushButton.c:39
#define BUTTON_UP_PIN
Pin used for up button.
Definition: sysdef.h:141
#define BUTTON_REPEAT
Button autorepeat.
Definition: PushButton.c:64
System wide Definitions for FREMO Clock.
#define BUTTON_PORT
Port used for buttons.
Definition: sysdef.h:135
bool PushButtonSingleShotEnter(void)
Test if button enter is pressed.
Definition: PushButton.c:147
static bool PushButtonSingleShotAction(button_t ucButton)
Test if button is pressed.
Definition: PushButton.c:192
static void PushButtonPressed(button_t ucButton)
Used by PushButtonInterrupt during interrupt service when button is down.
Definition: PushButton.c:261
static void PushButtonSetStatusServed(button_t ucButton)
Set that button has already been handled.
Definition: PushButton.c:130
"UP" button (up arrow)
Definition: PushButton.c:40
static uint8_t PushButtonReadStatus(button_t buttonIdx)
Read status bits for the button.
Definition: PushButton.c:116