OSDN Git Service

[IO] Use bitfield on scanning key, to save program-memory.
[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
32
33 const char charcodemap[] = {charcode_0,
34                             charcode_1,
35                             charcode_4,
36                             charcode_7,
37
38                             charcode_f,
39                             charcode_2,
40                             charcode_5,
41                             charcode_8,
42
43                             charcode_e,
44                             charcode_3,
45                             charcode_6,
46                             charcode_9,
47
48                             charcode_d,
49                             charcode_c,
50                             charcode_b,
51                             charcode_a,
52 };
53
54 extern unsigned char pollkeybuf[32];
55
56 keyin_defs keyin_old[2];
57 keyin_defs keyin_now;
58 char keyin_fifo[32];
59 char keyin_nowp;
60 char keyin_readp;
61 char keyin_counter;
62
63 unsigned char cold;
64
65 void keyin_init(void)
66 {
67     char i;
68     /* Initialize vars*/
69     for(i = 0; i < 2; i++) {
70         keyin_old[0].byte[i] = 0x00;
71         keyin_old[1].byte[i] = 0x00;
72         keyin_now.byte[i] = 0x00;
73     }
74     for(i = 0; i < 32; i++) keyin_fifo[i] = 0x00;
75     keyin_nowp = 0;
76     keyin_readp = 0;
77     keyin_counter = 0;
78     cold = charcode_null;
79 }
80 /*
81  * Push to keyin fifo; not used atomic-writing.
82  */
83 void push_keyinfifo(char b) __critical
84 {
85     if(keyin_counter >= 31) {
86         keyin_counter = 31;
87         keyin_readp++; // Discard data
88 //        return;
89         if((keyin_readp > 31) || (keyin_readp < 0)) keyin_readp = 0;
90     }
91     keyin_fifo[keyin_nowp] = b;
92     keyin_nowp++;
93     keyin_counter++;
94     if((keyin_nowp > 31) || (keyin_nowp < 0))keyin_nowp = 0;
95 }
96
97 /*
98  * Pop from keyin fifo; not used atomic-reading.
99  */
100 char pop_keyinfifo(void) __critical
101 {
102     char c;
103     if(keyin_counter <= 0) {
104         keyin_counter = 0;
105         return charcode_null ;
106     }
107     c = keyin_fifo[keyin_readp];
108     keyin_readp++;
109     keyin_counter--;
110     if((keyin_readp > 31) || (keyin_readp < 0)) keyin_readp = 0;
111     return c;
112 }
113
114 void printstr(char *s)
115 {
116     int p = 0;
117     _CURSOR_RIGHT();
118     if(s == NULL) return;
119     do {
120         if(s[p] == '\0') break;
121         _PUTCHAR(s[p]);
122         p++;
123     } while(p < 255);
124 }
125
126 void print_numeric_nosupress(unsigned int data, unsigned char digit)
127 {
128     unsigned int i;
129     int ref = 10;
130     int div = 1;
131
132     if(digit == 0) return;
133     if(digit >= 5) digit = 5;
134     if(digit == 5){
135         i = data / 10000;
136         data = data % 10000;
137         _PUTCHAR(i + '0');
138         digit--;
139     }
140     if(digit == 4){
141         i = data / 1000;
142         data = data % 1000;
143         _PUTCHAR(i + '0');
144         digit--;
145     }
146     if(digit == 3){
147         i = data / 100;
148         data = data % 100;
149         _PUTCHAR(i + '0');
150         digit--;
151     }
152     if(digit == 2){
153         i = data / 10;
154         data = data % 10;
155         _PUTCHAR(i + '0');
156         digit--;
157     }
158     if(digit == 1){
159         i = data;
160         _PUTCHAR(i + '0');
161         digit--;
162     }
163 }
164 /*
165  * Read Numeric(int)
166  */
167 unsigned int subst_numeric(unsigned int start, unsigned char pos, unsigned int c)
168 {
169     unsigned int val;
170     char i;
171     unsigned int fact;
172     unsigned char bcd[5];
173
174     if(pos > 4) pos = 4;
175     if((pos == 4) && (c > 6)) return start;
176     val = start;
177     // binary to BCD
178     fact = 10000;
179     for(i = 4; i >= 0; i--){
180         bcd[i] = val / fact;
181         val = val % fact;
182         fact = fact / 10;
183     }
184     // subst
185     bcd[pos] = c;
186     val = 0;
187     for(i = 3; i >= 0; i--){
188         val = val * 10;
189         val = val + bcd[i];
190     }
191     if((bcd[4] == 6) && (val > 5535)) return val;
192     val = val + bcd[4] * 10000;
193     return val;
194 }
195
196 unsigned int read_numeric(unsigned int initial, unsigned char digit,
197         char startx, char starty)
198 {
199     unsigned char c;
200     unsigned char n;
201     char i;
202     unsigned int val;
203     char d;
204
205     d = digit - 1;
206     val = initial;
207     i = d;
208     do {
209         _LOCATE(startx, starty);
210         print_numeric_nosupress(val, digit);
211         
212        do {
213            n = pollkeys(pollkeybuf, 60, 0);
214        } while(n == 0);
215        c = pollkeybuf[0];
216
217         if(c == charcode_0){
218             val = subst_numeric(val, i, 0);
219             i--;
220         } else if((c >= charcode_1) && (c <= charcode_9)) {
221             val = subst_numeric(val, i, c - charcode_1 + 1);
222             i--;
223         } else if(c == charcode_f) {
224             // Enter
225             break;
226         } else if(c == charcode_a) {
227             // Del
228             val = val / 10;
229             i++;
230         } else if(c == charcode_b) {
231             // cancel
232             val = initial;
233             i = d;
234             break;
235         }  else if(c == charcode_e) {
236             i++;
237         } else if(c == charcode_d) {
238             i--;
239         }
240        if(i <= 0) i = 0;
241        if(i > d) i = d;
242     } while(1);
243     return val;
244 }
245
246 unsigned char readkey_compare(void)
247 {
248     char b;
249     char c;
250     char d;
251     char e;
252     unsigned char shift;
253     unsigned char f;
254     f = 0;
255     e = 0;
256     for(d = 0; d < 2; d++) {
257         shift = 0x01;
258         for(b = 0; b < 8; b++){
259             c = 0;
260             if((keyin_now.byte[d] & shift) != 0) c++;
261             if((keyin_old[0].byte[d] & shift) != 0) c++;
262             if((keyin_old[1].byte[d] & shift) != 0) c++;
263             if(c >= 2) {
264             /*
265              * Clear older-inputs on .
266              */
267                 f |= 1;
268                 keyin_old[0].byte[d] &= ~shift;
269                 keyin_old[1].byte[d] &= ~shift;
270                 keyin_now.byte[d] &= ~shift;
271                 push_keyinfifo(charcodemap[e]);
272             }
273             shift <<= 1;
274             e++;
275         }
276     }
277     /**/
278     return f;
279 }
280
281 unsigned char readkey(void)
282 {
283     unsigned char i;
284     for(i = 0; i < 9; i++) {
285         idle_time_ms(2); // 2ms
286         readkey_io(i);
287     }
288     readkey_compare();
289     return pop_keyinfifo();
290 }
291
292 /*
293  * Polling key
294  * Max = 32bytes;
295  * 0 = Timeout
296  * 1~32 = Received.
297  * if((limit * 19.6ms) elapsed), break;
298  */
299 unsigned char pollkeys(unsigned char *p, unsigned int limit, unsigned char repeat)
300 {
301     unsigned int count = 0;
302     unsigned int lifetime = 0;
303     unsigned int penalty = 0;
304     unsigned char c;
305
306     do {
307         idle_time_ms(10); // 0.78*20 = 15.6ms.
308         c = readkey(); //
309         ClrWdt();
310         if(c != charcode_null) {
311             push_keyinfifo(c);
312             do {
313                 c = pop_keyinfifo();
314                 if(c == charcode_null) {
315                     break;
316                 }
317                 if(c != cold) {
318                     p[count++] = c;
319                     cold = c;
320                 }
321             } while(count < 32);
322             penalty = 0;
323         } else {
324             penalty++;
325             if((limit > 3) && (penalty > limit / 4)){
326                 penalty = 0;
327                 cold = charcode_null;
328             }
329         }
330         if(limit != 0) lifetime++;
331         if(lifetime > limit) break;
332     } while(count < 32);
333     if(repeat != 0) cold = charcode_null;
334     return count;
335 }
336
337 unsigned char pollkey_single(void)
338 {
339     unsigned int count = 0;
340     unsigned int lifetime = 0;
341     unsigned int penalty = 0;
342     unsigned char c;
343
344     do {
345         idle_time_ms(10); // 0.125 * 4 * 20 = 10ms.
346         c = readkey(); // 2 * 9 = 16ms
347         ClrWdt();
348         if(c != charcode_null) {
349             if(cold != c){
350                 cold = c;
351                 return c;
352             }
353         }
354         penalty++;
355         if(penalty > 20) cold = charcode_null;
356     } while(1);
357 }
358
359 /*
360  * Notes:
361  * Initialize sequence:
362  * keyin_init();
363  * keyin_ioinit();
364  * 
365  * Read-key-sequence:
366  * In interrupt/unsleep hook(call per Nms):
367  * readkey_io();
368  * readkey_compare();
369  *
370  * In application handler:
371  * c = pop_keyinfifo();
372  * if(c != 0) do(c);
373  */