version 2.8
ginput_dial.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.org/license.html
6  */
7 
8 /**
9  * @file src/ginput/ginput_dial.c
10  * @brief GINPUT dial code.
11  *
12  * @defgroup Dial Dial
13  * @ingroup GINPUT
14  * @{
15  */
16 #include "../../gfx.h"
17 
18 #if GFX_USE_GINPUT && GINPUT_NEED_DIAL
19 
20 #include "ginput_driver_dial.h"
21 
22 static GTIMER_DECL(DialTimer);
23 static struct DialStatus_t {
24  uint16_t sensitivity;
25  uint16_t lastvalue;
26  uint16_t max;
27 } DialStatus[GINPUT_DIAL_NUM_PORTS];
28 
29 // The reading callback function
30 static void DialCallback(uint16_t instance, uint16_t rawvalue) {
31  struct DialStatus_t *pds;
32  GSourceListener *psl;
33  GEventDial *pe;
34 
35  /* Get the information we need */
36  pds = DialStatus+instance;
37 
38  /* Range scale - if needed */
39  if (pds->max != GINPUT_DIAL_MAX_VALUE)
40  rawvalue = (uint16_t)((uint32_t)rawvalue * pds->max / GINPUT_DIAL_MAX_VALUE);
41 
42  /* Forget about changes below our sensitivity threshold */
43  if (rawvalue >= pds->lastvalue) {
44  if (rawvalue - pds->lastvalue < pds->sensitivity) return;
45  } else {
46  if (pds->lastvalue - rawvalue < pds->sensitivity) return;
47  }
48 
49  /* Save the value */
50  pds->lastvalue = rawvalue;
51 
52  // Send the event to the listeners that are interested.
53  psl = 0;
54  while ((psl = geventGetSourceListener((GSourceHandle)(DialStatus+instance), psl))) {
55  if (!(pe = (GEventDial *)geventGetEventBuffer(psl)))
56  continue;
57  pe->type = GEVENT_DIAL;
58  pe->instance = instance;
59  pe->value = pds->lastvalue;
60  pe->maxvalue = pds->max;
61  geventSendEvent(psl);
62  }
63 }
64 
65 GSourceHandle ginputGetDial(uint16_t instance) {
66  struct DialStatus_t *pds;
67 
68  if (instance >= GINPUT_DIAL_NUM_PORTS)
69  return 0;
70 
71  // Do we need to initialise the dial subsystem?
72  if (!gtimerIsActive(&DialTimer)) {
73  for(pds = DialStatus; pds < DialStatus+GINPUT_DIAL_NUM_PORTS; pds++) {
74  pds->max = GINPUT_DIAL_MAX_VALUE;
75 #if GINPUT_DIAL_MAX_VALUE < 100
76  pds->sensitivity = 1;
77 #else
78  pds->sensitivity = GINPUT_DIAL_MAX_VALUE/100;
79 #endif
80  pds->lastvalue = 0;
81  }
82  ginput_lld_dial_init();
83  gtimerStart(&DialTimer, (GTimerFunction)ginput_lld_dial_poll, DialCallback, TRUE, GINPUT_DIAL_POLL_PERIOD);
84  }
85 
86  // OK - return this input
87  return (GSourceHandle)(DialStatus+instance);
88 }
89 
90 void ginputResetDialRange(uint16_t instance) {
91  if (instance >= GINPUT_DIAL_NUM_PORTS)
92  return;
93 
94  ginputSetDialRange(instance, GINPUT_DIAL_MAX_VALUE);
95 }
96 
97 uint16_t ginputGetDialRange(uint16_t instance) {
98  if (instance >= GINPUT_DIAL_NUM_PORTS)
99  return 0;
100 
101  return DialStatus[instance].max;
102 }
103 
104 void ginputSetDialRange(uint16_t instance, uint16_t max) {
105  struct DialStatus_t *pds;
106 
107  if (instance >= GINPUT_DIAL_NUM_PORTS)
108  return;
109 
110  pds = DialStatus+instance;
111 
112  // Rescale the last value and the sensitivity
113  if (max != pds->max) {
114  pds->lastvalue = (uint16_t)((uint32_t)pds->lastvalue * max / pds->max);
115  pds->sensitivity = (uint16_t)((uint32_t)pds->sensitivity * max / pds->max);
116  pds->max = max;
117  }
118 }
119 
120 /**
121  * @brief Set the level change required before a dial even is generated (threshold)
122  * @note This is done after range scaling
123  *
124  * @param[in] instance The ID of the dial input instance
125  * @param[in] diff The amount of level changes
126  */
127 void ginputSetDialSensitivity(uint16_t instance, uint16_t diff) {
128  if (instance >= GINPUT_DIAL_NUM_PORTS)
129  return;
130 
131  DialStatus[instance].sensitivity = diff;
132 }
133 
134 /**
135  * @brief Get the current dial status
136  *
137  * @param[in] instance The ID of the dial input instance
138  * @param[in] pdial The dial event struct
139  *
140  * @return Returns FALSE on an error (eg invalid instance)
141  */
142 bool_t ginputGetDialStatus(uint16_t instance, GEventDial *pdial) {
143  if (instance >= GINPUT_DIAL_NUM_PORTS)
144  return FALSE;
145  pdial->type = GEVENT_DIAL;
146  pdial->instance = instance;
147  pdial->value = DialStatus[instance].lastvalue;
148  pdial->maxvalue = DialStatus[instance].max;
149  return TRUE;
150 }
151 
152 #endif /* GFX_USE_GINPUT && GINPUT_NEED_DIAL */
153 /** @} */
uint16_t ginputGetDialRange(uint16_t instance)
Get the maximum value.
void ginputResetDialRange(uint16_t instance)
Reset the value back to the hardware default.
GEvent * geventGetEventBuffer(GSourceListener *psl)
Get the event buffer from the GSourceListener.
Definition: gevent.c:187
bool_t ginputGetDialStatus(uint16_t instance, GEventDial *pdial)
Get the current dial status.
bool_t gtimerIsActive(GTimer *pt)
Test if a timer is currently active.
Definition: gtimer.c:208
#define FALSE
Generic &#39;false&#39; boolean constant.
Definition: gfx.h:31
void ginputSetDialRange(uint16_t instance, uint16_t max)
Set the maximum value.
void ginputSetDialSensitivity(uint16_t instance, uint16_t diff)
Set the level change required before a dial even is generated (threshold)
GSourceHandle ginputGetDial(uint16_t instance)
Create a dial input instance.
void geventSendEvent(GSourceListener *psl)
Called by a source to indicate the listener&#39;s event buffer has been filled.
Definition: gevent.c:200
void gtimerStart(GTimer *pt, GTimerFunction fn, void *param, bool_t periodic, delaytime_t millisec)
Set a timer going or alter its properties if it is already going.
Definition: gtimer.c:139
#define TRUE
Generic &#39;true&#39; boolean constant.
Definition: gfx.h:38
GINPUT header file for dial drivers.
GSourceListener * geventGetSourceListener(GSourceHandle gsh, GSourceListener *lastlr)
Called by a source with a possible event to get a listener record.
Definition: gevent.c:163