]> git.zerfleddert.de Git - fnordlicht-mini/blob - firmware/fnordlicht-controller/ir-cluster.c
e4dcb632267becfea3961ff761e59e7c9378d5d4
[fnordlicht-mini] / firmware / fnordlicht-controller / ir-cluster.c
1 /*
2 * ox - infrared to usb keyboard/mouse adapter
3 *
4 * by Alexander Neumann <alexander@lochraster.org>
5 *
6 * inspired by InfraHID by Alex Badea,
7 * see http://vamposdecampos.googlepages.com/infrahid.html
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 * For more information on the GPL, please go to:
23 * http://www.gnu.org/copyleft/gpl.html
24 */
25
26 #include "ir-cluster.h"
27
28 /* return the position of the (first) minimum value within data[],
29 * considering only values at even positions */
30 static uint8_t minimum(uint16_t data[], uint8_t len)
31 {
32 uint8_t min = 0;
33
34 for (uint8_t i = 0; i < 2*len; i += 2) {
35 if (data[i] < data[min])
36 min = i;
37 }
38
39 return min;
40 }
41
42 /* search next bigger value (starting at data[from]) within data[], just
43 * considering the even values, return -1 on error (no bigger value found) */
44 static int8_t next(uint16_t data[], uint8_t len, uint8_t from)
45 {
46 len *= 2;
47
48 uint16_t old = data[from];
49
50 /* test if the same value appears again within data[] after from */
51 for (uint8_t i = from+2; i < len; i += 2) {
52 if (data[i] == old)
53 /* found the same value again, at pos i */
54 return i;
55 }
56
57 /* else search for the next bigger value */
58 int16_t pos = -1;
59 for (uint8_t i = 0; i < len; i += 2) {
60
61 /* if the current value is lower than the old value, try next */
62 if (data[i] <= old)
63 continue;
64
65 /* if we haven't found a bigger value yet, or if the current value
66 * is smaller than the value we looked at before,
67 * consider the current position as the next value */
68 if (pos < 0 || data[i] < data[pos])
69 pos = i;
70 }
71
72 return pos;
73 }
74
75 /* search for (one-dimensional) clusters within data[],
76 * consider only values at even positions */
77 uint8_t ir_cluster(uint16_t data[], uint8_t len, uint16_t cluster[], uint8_t max)
78 {
79 uint8_t cindex = 0;
80
81 /* search minimum within data[] */
82 uint8_t pos = minimum(data, len);
83
84 /* initialize mean value */
85 uint32_t mean = data[pos];
86 uint8_t count = 1;
87
88 /* iterate over data[], processing the values (at even positions) in
89 * ascending order */
90 for (uint8_t i = 0; i < len-1; i++) {
91
92 /* search position of the next element within data[] */
93 uint8_t nextpos = next(data, len, pos);
94
95 /* as a shortcut, name values a and b */
96 uint16_t a = data[pos];
97 uint16_t b = data[nextpos];
98
99 /* check if b > 1.5*a */
100 a += a/2;
101 if (b > a) {
102
103 /* reached a step, found a cluster */
104 mean /= count;
105 cluster[cindex++] = (uint16_t)mean;
106
107 /* stop processing since max cluster values is reached */
108 if (cindex == max)
109 return max;
110
111 /* reset mean value */
112 mean = 0;
113 count = 0;
114 }
115
116 /* add value to mean */
117 mean += b;
118 count++;
119
120 /* advance position */
121 pos = nextpos;
122 }
123
124 /* if there are some values left in mean, this is the last cluster */
125 if (count > 0) {
126 mean /= count;
127 cluster[cindex++] = (uint16_t)mean;
128 }
129
130 return cindex;
131 }
132
133 /* get cluster index belonging to data */
134 uint8_t ir_min_cluster(uint16_t data, uint16_t cluster[], uint8_t len)
135 {
136 uint8_t min = 0;
137 uint16_t diff = 0xffff;
138
139 /* iterate over possible clusters */
140 for (uint8_t i = 0; i < len; i++) {
141 uint16_t curdiff;
142
143 /* get positive difference */
144 if (data < cluster[i])
145 curdiff = cluster[i] - data;
146 else
147 curdiff = data - cluster[i];
148
149 /* if difference is lower, remember this cluster */
150 if (curdiff < diff) {
151 diff = curdiff;
152 min = i;
153 } else
154 /* stop here, since difference is larger than for the last cluster
155 * (cluster[] is ordered ascending */
156 break;
157 }
158
159 return min;
160 }
Impressum, Datenschutz