µGFX  2.9
version 2.9
ginput_toggle.c
Go to the documentation of this file.
1 /*
2  * This file is subject to the terms of the GFX License. If a copy of
3  * the license was not distributed with this file, you can obtain one at:
4  *
5  * http://ugfx.io/license.html
6  */
7 
8 /**
9  * @file src/ginput/ginput_toggle.c
10  * @brief GINPUT toggle code.
11  *
12  * @defgroup Toggle Toggle
13  * @ingroup GINPUT
14  * @{
15  */
16 #include "../../gfx.h"
17 
18 #if (GFX_USE_GINPUT && GINPUT_NEED_TOGGLE) || defined(__DOXYGEN__)
19 
20 #include "ginput_driver_toggle.h"
21 
22 #define GINPUT_TOGGLE_ISON 0x01
23 #define GINPUT_TOGGLE_INVERT 0x02
24 
25 static GTIMER_DECL(ToggleTimer);
26 static struct GEventToggleStatus_t {
27  gU8 status;
28 } ToggleStatus[GINPUT_TOGGLE_NUM_PORTS];
29 
30 // Our polling function
31 static void TogglePoll(void *param) {
32  (void) param;
33 
34  const GToggleConfig *ptc;
35  GSourceListener *psl;
36  GEventToggle *pe;
37  unsigned i, bits, mask;
38  gU8 state;
39 
40  // Loop while there are bits to get
41  for(ptc = GInputToggleConfigTable, i=0; i < GINPUT_TOGGLE_NUM_PORTS; ptc++) {
42 
43  // Get the next block of bits
44  bits = ginput_lld_toggle_getbits(ptc) ^ ptc->invert;
45 
46  // Extract the bits of use
47  for(mask = ptc->mask; i < GINPUT_TOGGLE_NUM_PORTS && mask; mask >>= 1, bits >>= 1) {
48  // Ignore bits not in our mask
49  if (!(mask & 1))
50  continue;
51 
52  // Calculate our new state
53  state = ToggleStatus[i].status & ~GINPUT_TOGGLE_ISON;
54  if (state & GINPUT_TOGGLE_INVERT)
55  bits ^= 1;
56  if (bits & 1)
57  state |= GINPUT_TOGGLE_ISON;
58 
59  // Has it changed?
60  if ((state ^ ToggleStatus[i].status) & GINPUT_TOGGLE_ISON) {
61 
62  // Save the new state
63  ToggleStatus[i].status = state;
64 
65  // Send the event to the listeners that are interested.
66  psl = 0;
67  while ((psl = geventGetSourceListener((GSourceHandle)(ToggleStatus+i), psl))) {
68  if (!(pe = (GEventToggle *)geventGetEventBuffer(psl)))
69  continue;
70  if ((state & GINPUT_TOGGLE_ISON)) {
71  if ((psl->listenflags & GLISTEN_TOGGLE_ON)) {
72  pe->type = GEVENT_TOGGLE;
73  pe->instance = i;
74  pe->on = gTrue;
75  geventSendEvent(psl);
76  }
77  } else {
78  if ((psl->listenflags & GLISTEN_TOGGLE_OFF)) {
79  pe->type = GEVENT_TOGGLE;
80  pe->instance = i;
81  pe->on = gFalse;
82  geventSendEvent(psl);
83  }
84  }
85  }
86  }
87 
88  // Next toggle switch
89  i++;
90  }
91  }
92 }
93 
94 /* Hardware Toggle/Switch/Button Functions */
95 GSourceHandle ginputGetToggle(gU16 instance) {
96  const GToggleConfig *ptc;
97 
98  if (instance >= GINPUT_TOGGLE_NUM_PORTS)
99  return 0;
100 
101  // Do we need to initialise the toggle subsystem?
102  if (!gtimerIsActive(&ToggleTimer)) {
103  for(ptc = GInputToggleConfigTable; ptc < GInputToggleConfigTable+sizeof(GInputToggleConfigTable)/sizeof(GInputToggleConfigTable[0]); ptc++)
104  ginput_lld_toggle_init(ptc);
105  gtimerStart(&ToggleTimer, TogglePoll, 0, gTrue, GINPUT_TOGGLE_POLL_PERIOD);
106  }
107 
108  // OK - return this input
109  return (GSourceHandle)(ToggleStatus+instance);
110 }
111 
112 // If invert is true, invert the on/off sense for the toggle
113 void ginputInvertToggle(gU16 instance, gBool invert) {
114  if (instance >= GINPUT_TOGGLE_NUM_PORTS)
115  return;
116  if (invert) {
117  if (!(ToggleStatus[instance].status & GINPUT_TOGGLE_INVERT)) {
118  ToggleStatus[instance].status |= GINPUT_TOGGLE_INVERT;
119  ToggleStatus[instance].status ^= GINPUT_TOGGLE_ISON;
120  }
121  } else {
122  if ((ToggleStatus[instance].status & GINPUT_TOGGLE_INVERT)) {
123  ToggleStatus[instance].status &= ~GINPUT_TOGGLE_INVERT;
124  ToggleStatus[instance].status ^= GINPUT_TOGGLE_ISON;
125  }
126  }
127 }
128 
129 /* Get the current toggle status.
130  * Returns gFalse on error (eg invalid instance)
131  */
132 gBool ginputGetToggleStatus(gU16 instance, GEventToggle *ptoggle) {
133  // Win32 threads don't seem to recognise priority and/or pre-emption
134  // so we add a sleep here to prevent 100% polled applications from locking up.
136 
137  if (instance >= GINPUT_TOGGLE_NUM_PORTS)
138  return gFalse;
139  ptoggle->type = GEVENT_TOGGLE;
140  ptoggle->instance = instance;
141  ptoggle->on = (ToggleStatus[instance].status & GINPUT_TOGGLE_ISON) ? gTrue : gFalse;
142  return gTrue;
143 }
144 
145 /* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
146 void ginputToggleWakeup(void) {
147  gtimerJab(&ToggleTimer);
148 }
149 
150 /* Wake up the mouse driver from an interrupt service routine (there may be new readings available) */
151 void ginputToggleWakeupI(void) {
152  gtimerJabI(&ToggleTimer);
153 }
154 
155 #endif /* GFX_USE_GINPUT && GINPUT_NEED_TOGGLE */
156 /** @} */
GINPUT header file for toggle drivers.
GEvent * geventGetEventBuffer(GSourceListener *psl)
Get the event buffer from the GSourceListener.
Definition: gevent.c:187
void geventSendEvent(GSourceListener *psl)
Called by a source to indicate the listener's event buffer has been filled.
Definition: gevent.c:200
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
Definition: gevent.c:163
void gfxSleepMilliseconds(gDelay ms)
Put the current thread to sleep for the specified period in milliseconds.
void gtimerJabI(GTimer *pt)
Jab a timer causing the current period to immediate expire.
Definition: gtimer.c:223
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, gBool periodic, gDelay millisec)
Set a timer going or alter its properties if it is already going.
Definition: gtimer.c:139
gBool gtimerIsActive(GTimer *pt)
Test if a timer is currently active.
Definition: gtimer.c:208
void gtimerJab(GTimer *pt)
Jab a timer causing the current period to immediate expire.
Definition: gtimer.c:212
void ginputInvertToggle(gU16 instance, gBool invert)
Can be used to invert the sense of a toggle.
gBool ginputGetToggleStatus(gU16 instance, GEventToggle *ptoggle)
Get the current toggle status.
GSourceHandle ginputGetToggle(gU16 instance)
Create a toggle input instance.
Definition: ginput_toggle.c:95