OSDN Git Service

[DOC] Add one line for donation(^_^;
[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 void uint2bcd(unsigned long data, unsigned char *bcd)
135 {
136     unsigned char i;
137     unsigned char j;
138
139     for(i = 0; i < 5; i++){
140         bcd[i] = data % 10;
141         data = data / 10;
142     }
143     bcd[5] = 0;
144 }
145
146 void print_numeric_nosupress(unsigned long data, unsigned char digit)
147 {
148     unsigned char i;
149     unsigned char bcd[6];
150
151
152     if(digit == 0) return;
153     if(digit >= 5) digit = 5;
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[6];
166     char i;
167
168     if(pos > 4) pos = 4;
169     uint2bcd(start, bcd);
170     bcd[pos] = c;
171     val = bcd[0] + bcd[1] * 10 + bcd[2] * 100 + bcd[3] * 1000 + bcd[4] * 10000;
172     return val;
173 }
174
175 unsigned int read_numeric(unsigned int initial, unsigned char digit,
176         char startx, char starty)
177 {
178     unsigned char c;
179     unsigned char n;
180     char i;
181     unsigned long val;
182     unsigned long v;
183     char d;
184
185     d = digit - 1;
186     val =(unsigned long) initial;
187     i = d;
188     do {
189         _CURSOR_OFF();
190        ClrWdt();
191         _LOCATE(startx, starty);
192         print_numeric_nosupress(val, digit);
193        ClrWdt();
194         _LOCATE(startx + d -  i, starty);
195        _CURSOR_ON();
196
197         c = pollkey_single();
198         if(c == charcode_0){
199             val = subst_numeric(val, i, 0);
200             i--;
201         } else if((c >= charcode_1) && (c <= charcode_9)) {
202             val = subst_numeric(val, i, c - charcode_1 + 1);
203             i--;
204         } else if(c == charcode_f) {
205             // Enter
206             break;
207         } else if(c == charcode_a) {
208             // Del
209             val = val / 10;
210             i++;
211         } else if(c == charcode_b) {
212             // cancel
213             val = initial;
214             i = d;
215             break;
216         }  else if(c == charcode_e) {
217             i++;
218         } else if(c == charcode_d) {
219             i--;
220         }
221        if(i <= 0) i = 0;
222        if(i > d) i = d;
223     } while(1);
224     _CURSOR_OFF();
225     if(val > 65535) val = 65535;
226     return (unsigned int)val;
227 }
228
229 unsigned char readkey_compare(void)
230 {
231     char b;
232     char c;
233     char d;
234     char e;
235     unsigned char shift;
236     unsigned char f;
237     f = 0;
238     e = 0;
239     for(d = 0; d < 2; d++) {
240         shift = 0x01;
241         for(b = 0; b < 8; b++){
242             c = 0;
243             if((keyin_now.byte[d] & shift) != 0) c++;
244             if((keyin_old[0].byte[d] & shift) != 0) c++;
245             if((keyin_old[1].byte[d] & shift) != 0) c++;
246             if(c >= 2) {
247             /*
248              * Clear older-inputs on .
249              */
250                 f |= 1;
251                 keyin_old[0].byte[d] &= ~shift;
252                 keyin_old[1].byte[d] &= ~shift;
253                 keyin_now.byte[d] &= ~shift;
254                 push_keyinfifo(charcodemap[e]);
255             }
256             shift <<= 1;
257             e++;
258         }
259     }
260     /**/
261     return f;
262 }
263
264 unsigned char readkey(void)
265 {
266     unsigned char i;
267     for(i = 0; i < 9; i++) {
268         idle_time_ms(2); // 2ms
269         readkey_io(i);
270 //        ClrWdt();
271     }
272     readkey_compare();
273     return pop_keyinfifo();
274 }
275
276 /*
277  * Polling key
278  * Max = 32bytes;
279  * 0 = Timeout
280  * 1~32 = Received.
281  * if((limit * 23ms) elapsed), break;
282  */
283 unsigned char pollkeys(unsigned char *p, unsigned int limit, unsigned char repeat)
284 {
285     unsigned char count = 0;
286     unsigned int lifetime = 0;
287     unsigned int penalty = 0;
288     unsigned char c;
289     unsigned char i;
290
291     do {
292         idle_time_ms(5); // 5ms.
293         c = readkey(); //18ms
294         ClrWdt();
295         if(c != charcode_null){
296             if(cold != c) {
297                 p[count++] = c;
298                 cold = c;
299                 count++;
300                 if(repeat == 0) {
301                         break;
302                 }
303                 penalty = 0;
304             }
305         }  else {
306             penalty++;
307             if(penalty > 4){
308                 penalty = 0;
309                 cold = charcode_null;
310             }
311         }
312         if(limit != 0) lifetime++;
313         if(lifetime > limit) break;
314     } while(count < 32);
315     p[count] = charcode_null;
316     return count;
317 }
318
319 unsigned char pollkey_single(void)
320 {
321     unsigned int penalty = 0;
322     unsigned char c;
323
324 //    cold = charcode_null;
325     do {
326         idle_time_ms(5); // 5ms.
327         c = readkey(); // 2 * 9 = 18ms
328         ClrWdt();
329         if(c != charcode_null) {
330             if(cold != c){
331                 cold = c;
332                 return c;
333             }
334             penalty = 0;
335         } else {
336             penalty++;
337             if(penalty > 4) {
338                 penalty = 0;
339                 cold = charcode_null; // About 100ms
340             }
341         }
342     } while(1);
343 }
344
345 unsigned char pollkey_single_timeout(unsigned int limit, unsigned char repeat)
346 {
347     unsigned char c;
348     unsigned int ticks = 0;
349     unsigned char penalty = 0;
350     unsigned char count = 0;
351
352
353     cold = charcode_null;
354     pollkeybuf[0] = charcode_null;
355     do {
356         if(limit != 0) {
357             ticks++;
358             if(ticks > limit) {
359                 break;
360             }
361         }
362         idle_time_ms(5); // 5ms.
363         c = readkey(); // 2 * 9 = 18ms
364         ClrWdt();
365         ticks++;
366         if(c != charcode_null){
367             if(cold != c) {
368                 pollkeybuf[count++] = c;
369                 cold = c;
370                 count++;
371                 if(repeat == 0) {
372                         break;
373                 }
374                 penalty = 0;
375             }
376         }  else {
377             penalty++;
378             if(penalty > 4){
379                 penalty = 0;
380                 cold = charcode_null;
381             }
382         }
383     } while(count < 32);
384
385     /*
386      * Set Deadzone.
387      */
388     if(limit == 0) {
389         while(ticks <= limit) {
390             idle_time_ms(5 + 18);
391             ticks++;
392         }
393     }
394     c = pollkeybuf[0];
395     return c;
396 }
397 /*
398  * Notes:
399  * Initialize sequence:
400  * keyin_init();
401  * keyin_ioinit();
402  * 
403  * Read-key-sequence:
404  * In interrupt/unsleep hook(call per Nms):
405  * readkey_io();
406  * readkey_compare();
407  *
408  * In application handler:
409  * c = pop_keyinfifo();
410  * if(c != 0) do(c);
411  */