OSDN Git Service

1e42ec560b5f3e2ca1e8555f48e3b1e2698ccb96
[openi2cradio/OpenI2CRadio.git] / ui.c
1 /*
2  * OpenI2CRADIO
3  * UI Handler
4  * Copyright (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2,
9  *  or (at your option) any later version.
10  *  This library / program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  *  See the GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this library; see the file COPYING. If not, write to the
17  *  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
18  *  MA 02110-1301, USA.
19  *
20  *  As a special exception, if you link this(includeed from sdcc) library
21  *  with other files, some of which are compiled with SDCC,
22  *  to produce an executable, this library does not by itself cause
23  *  the resulting executable to be covered by the GNU General Public License.
24  *  This exception does not however invalidate any other reasons why
25  *  the executable file might be covered by the GNU General Public License.
26  */
27
28 #include "ioports.h"
29 #include "ui.h"
30 #include "idle.h"
31 #include "commondef.h"
32
33
34 const char charcodemap[] = {charcode_0,
35                             charcode_1,
36                             charcode_4,
37                             charcode_7,
38
39                             charcode_f,
40                             charcode_2,
41                             charcode_5,
42                             charcode_8,
43
44                             charcode_e,
45                             charcode_3,
46                             charcode_6,
47                             charcode_9,
48
49                             charcode_d,
50                             charcode_c,
51                             charcode_b,
52                             charcode_a,
53 };
54
55 extern unsigned char pollkeybuf[32];
56
57 keyin_defs keyin_old[2];
58 keyin_defs keyin_now;
59 char keyin_fifo[32];
60 char keyin_nowp;
61 char keyin_readp;
62 char keyin_counter;
63
64 unsigned char cold;
65
66 void keyin_init(void)
67 {
68     char i;
69     /* Initialize vars*/
70     for(i = 0; i < 2; i++) {
71         keyin_old[0].byte[i] = 0x00;
72         keyin_old[1].byte[i] = 0x00;
73         keyin_now.byte[i] = 0x00;
74     }
75     for(i = 0; i < 32; i++) keyin_fifo[i] = 0x00;
76     keyin_nowp = 0;
77     keyin_readp = 0;
78     keyin_counter = 0;
79     cold = charcode_null;
80 }
81 /*
82  * Push to keyin fifo; not used atomic-writing.
83  */
84 #ifdef __SDCC
85 void push_keyinfifo(char b) __critical
86 #else
87 void push_keyinfifo(char b)
88 #endif
89 {
90     if(keyin_counter >= 31) {
91         return; // Discard data.
92     }
93     keyin_fifo[keyin_nowp] = b;
94     keyin_nowp++;
95     keyin_counter++;
96     if((keyin_nowp > 31) || (keyin_nowp < 0)) keyin_nowp = 0;
97 }
98
99 /*
100  * Pop from keyin fifo; not used atomic-reading.
101  */
102 #ifdef __SDCC
103 char pop_keyinfifo(void) __critical
104 #else
105 char pop_keyinfifo(void)
106 #endif
107 {
108     char c;
109     if(keyin_counter <= 0) {
110         keyin_counter = 0;
111         return charcode_null ;
112     }
113     c = keyin_fifo[keyin_readp];
114     keyin_readp++;
115     keyin_counter--;
116     if((keyin_readp > 31) || (keyin_readp < 0)) keyin_readp = 0;
117     return c;
118 }
119
120 void printstr(char *s)
121 {
122     int p = 0;
123     _CURSOR_RIGHT();
124     if(s == NULL) return;
125     do {
126         if(s[p] == '\0') break;
127         _PUTCHAR(s[p]);
128         p++;
129     } while(p < 255);
130 }
131
132
133
134 static void uint2bcd(unsigned long data, unsigned char *bcd)
135 {
136     unsigned char i;
137     unsigned char j;
138
139     for(i = 0; i <= 10; i++){
140         bcd[i] = data % 10;
141         data = data / 10;
142     }
143     bcd[10] = 0;
144 }
145
146 void print_numeric_nosupress(unsigned long data, unsigned char digit)
147 {
148     unsigned char i;
149     unsigned char bcd[11];
150
151
152     if(digit == 0) return;
153     if(digit > 10) digit = 10;
154     uint2bcd(data, bcd);
155     for(i = digit; i > 0; i--){
156         _PUTCHAR('0' + bcd[i - 1]);
157     }
158 }
159 /*
160  * Read Numeric(int)
161  */
162 unsigned long subst_numeric(unsigned long start, unsigned char pos, unsigned char c)
163 {
164     unsigned long val;
165     unsigned char bcd[11];
166     char i;
167     unsigned long fact;
168
169     if(pos > 10) pos = 10;
170     uint2bcd(start, bcd);
171     bcd[pos] = c;
172     
173     fact = 1;
174     val = 0;
175     for(i = 0; i < 11; i++){
176         val = val + (bcd[i] * fact);
177         fact = fact * 10;
178     }
179     return val;
180 }
181
182 unsigned long read_numeric(unsigned int initial, unsigned char digit,
183         char startx, char starty)
184 {
185     unsigned char c;
186     unsigned char n;
187     char i;
188     unsigned long val;
189     unsigned long v;
190     char d;
191
192     d = digit - 1;
193     val =(unsigned long) initial;
194     i = d;
195     do {
196 //        _CURSOR_OFF();
197        ClrWdt();
198         _LOCATE(startx, starty);
199         print_numeric_nosupress(val, digit);
200        ClrWdt();
201         _LOCATE(startx + d -  i, starty);
202        _CURSOR_ON();
203
204         c = pollkey_single();
205         if(c == charcode_0){
206             val = subst_numeric(val, i, 0);
207             i--;
208         } else if((c >= charcode_1) && (c <= charcode_9)) {
209             val = subst_numeric(val, i, c - charcode_1 + 1);
210             i--;
211         } else if(c == charcode_f) {
212             // Enter
213             break;
214         } else if(c == charcode_a) {
215             // Del
216             val = val / 10;
217             i++;
218         } else if(c == charcode_b) {
219             // cancel
220            _CURSOR_OFF();
221             return 0xffffffff;
222         }  else if(c == charcode_e) {
223             i++;
224         } else if(c == charcode_d) {
225             i--;
226         }
227        if(i <= 0) i = 0;
228        if(i > d) i = d;
229     } while(1);
230     _CURSOR_OFF();
231     if(val > 0x7fffffff) val = 0x7fffffff;
232     return val;
233 }
234
235 unsigned char readkey_compare(void)
236 {
237     char b;
238     char c;
239     char d;
240     char e;
241     unsigned char shift;
242     unsigned char f;
243     f = 0;
244     e = 0;
245     for(d = 0; d < 2; d++) {
246         shift = 0x01;
247         for(b = 0; b < 8; b++){
248             c = 0;
249             if((keyin_now.byte[d] & shift) != 0) c++;
250             if((keyin_old[0].byte[d] & shift) != 0) c++;
251             if((keyin_old[1].byte[d] & shift) != 0) c++;
252             if(c >= 2) {
253             /*
254              * Clear older-inputs on .
255              */
256                 f |= 1;
257                 keyin_old[0].byte[d] &= ~shift;
258                 keyin_old[1].byte[d] &= ~shift;
259                 keyin_now.byte[d] &= ~shift;
260                 push_keyinfifo(charcodemap[e]);
261             }
262             shift <<= 1;
263             e++;
264         }
265     }
266     /**/
267     return f;
268 }
269
270 unsigned char readkey(void)
271 {
272     unsigned char i;
273     for(i = 0; i < 9; i++) {
274         idle_time_ms(2); // 2ms
275         readkey_io(i);
276 //        ClrWdt();
277     }
278     readkey_compare();
279     return pop_keyinfifo();
280 }
281
282
283 unsigned char pollkey_single(void)
284 {
285     unsigned int penalty = 0;
286     unsigned char c;
287
288 //    cold = charcode_null;
289     do {
290         idle_time_ms(5); // 5ms.
291         c = readkey(); // 2 * 9 = 18ms
292         ClrWdt();
293         if(c != charcode_null) {
294             if(cold != c){
295                 cold = c;
296                 return c;
297             }
298             penalty = 0;
299         } else {
300             penalty++;
301             if(penalty > 4) {
302                 penalty = 0;
303                 cold = charcode_null; // About 100ms
304             }
305         }
306     } while(1);
307 }
308
309
310 unsigned char pollkey_numeric(unsigned char init)
311 {
312     unsigned char c;
313     c = pollkey_single();
314     if(c == charcode_0) {
315         return 0;
316     } else if((c >= charcode_1) && (c <= charcode_9)){
317         return c;
318     } else {
319         return init;
320     }
321 }
322
323 unsigned char pollkey_single_timeout(unsigned int limit, unsigned char repeat)
324 {
325     unsigned char c;
326     unsigned int ticks = 0;
327     unsigned char penalty = 0;
328     unsigned char count = 0;
329
330
331     cold = charcode_null;
332     pollkeybuf[0] = charcode_null;
333     do {
334         if(limit != 0) {
335             ticks++;
336             if(ticks > limit) {
337                 break;
338             }
339         }
340         idle_time_ms(5); // 5ms.
341         c = readkey(); // 2 * 9 = 18ms
342         ClrWdt();
343         ticks++;
344         if(c != charcode_null){
345             if(cold != c) {
346                 pollkeybuf[count++] = c;
347                 cold = c;
348                 count++;
349                 if(repeat == 0) {
350                         break;
351                 }
352                 penalty = 0;
353             }
354         }  else {
355             penalty++;
356             if(penalty > 4){
357                 penalty = 0;
358                 cold = charcode_null;
359             }
360         }
361     } while(count < 32);
362
363     /*
364      * Set Deadzone.
365      */
366     if(limit == 0) {
367         while(ticks <= limit) {
368             idle_time_ms(5 + 18);
369             ticks++;
370         }
371     }
372     c = pollkeybuf[0];
373     return c;
374 }
375 /*
376  * Notes:
377  * Initialize sequence:
378  * keyin_init();
379  * keyin_ioinit();
380  * 
381  * Read-key-sequence:
382  * In interrupt/unsleep hook(call per Nms):
383  * readkey_io();
384  * readkey_compare();
385  *
386  * In application handler:
387  * c = pop_keyinfifo();
388  * if(c != 0) do(c);
389  */