OSDN Git Service

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