OSDN Git Service

[USERBAND][v2.0] Save userbands on poweroff/save.
[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 // LCD Routines
67 void _PUTCHAR(unsigned char c)
68 {
69     acm1602_putchar(LCD_I2CADDR , c);
70 }
71
72 void _LOCATE(unsigned char x, unsigned char y)
73 {
74     acm1602_locate_16x2(LCD_I2CADDR , x, y);
75 }
76
77 void _CLS(void)
78 {
79     acm1602_cls(LCD_I2CADDR);
80 }
81 void _HOME(void)
82 {
83     acm1602_home(LCD_I2CADDR);
84 }
85
86 void _CURSOR_ON(void)
87 {
88     acm1602_dispcursor(LCD_I2CADDR, 0xff);
89 }
90
91
92 void _CURSOR_OFF(void)
93 {
94     acm1602_dispcursor(LCD_I2CADDR, 0x00);
95 }
96
97 void _CURSOR_LEFT(void)
98 {
99     acm1602_cursordir(LCD_I2CADDR , 0x00);
100 }
101
102 void _CURSOR_RIGHT(void)
103 {
104     acm1602_cursordir(LCD_I2CADDR , 0xff);
105 }
106
107
108 void keyin_init(void)
109 {
110     char i;
111     /* Initialize vars*/
112     for(i = 0; i < 2; i++) {
113         keyin_old[0].byte[i] = 0x00;
114         keyin_old[1].byte[i] = 0x00;
115         keyin_now.byte[i] = 0x00;
116     }
117     for(i = 0; i < 32; i++) keyin_fifo[i] = 0x00;
118     keyin_nowp = 0;
119     keyin_readp = 0;
120     keyin_counter = 0;
121     cold = charcode_null;
122 }
123 /*
124  * Push to keyin fifo; not used atomic-writing.
125  */
126 #ifdef __SDCC
127 void push_keyinfifo(char b) __critical
128 #else
129 void push_keyinfifo(char b)
130 #endif
131 {
132     if(keyin_counter >= 31) {
133         return; // Discard data.
134     }
135     keyin_fifo[keyin_nowp] = b;
136     keyin_nowp++;
137     keyin_counter++;
138     if((keyin_nowp > 31) || (keyin_nowp < 0)) keyin_nowp = 0;
139 }
140
141 /*
142  * Pop from keyin fifo; not used atomic-reading.
143  */
144 #ifdef __SDCC
145 char pop_keyinfifo(void) __critical
146 #else
147 char pop_keyinfifo(void)
148 #endif
149 {
150     char c;
151     if(keyin_counter <= 0) {
152         keyin_counter = 0;
153         return charcode_null ;
154     }
155     c = keyin_fifo[keyin_readp];
156     keyin_readp++;
157     keyin_counter--;
158     if((keyin_readp > 31) || (keyin_readp < 0)) keyin_readp = 0;
159     return c;
160 }
161
162 void printstr(char *s)
163 {
164     int p = 0;
165 //    _CURSOR_RIGHT();
166     if(s == NULL) return;
167     do {
168         if(s[p] == '\0') break;
169         _PUTCHAR(s[p]);
170         p++;
171     } while(p < 32);
172 }
173
174
175
176 static void uint2bcd(unsigned long data, unsigned char *bcd)
177 {
178     unsigned char i;
179     unsigned char j;
180
181     for(i = 0; i <= 10; i++){
182         bcd[i] = data % 10;
183         data = data / 10;
184     }
185     bcd[10] = 0;
186 }
187
188 void print_numeric_nosupress(unsigned long data, unsigned char digit)
189 {
190     unsigned char i;
191     unsigned char bcd[11];
192
193     if(digit == 0) return;
194     if(digit > 10) digit = 10;
195     uint2bcd(data, bcd);
196     for(i = digit; i > 0; i--){
197         _PUTCHAR('0' + bcd[i - 1]);
198     }
199 }
200 /*
201  * Read Numeric(int)
202  */
203 unsigned long subst_numeric(unsigned long start, unsigned char pos, unsigned char c)
204 {
205     unsigned long val;
206     unsigned char bcd[11];
207     char i;
208     unsigned long fact;
209
210     if(pos > 10) pos = 10;
211     uint2bcd(start, bcd);
212     bcd[pos] = c;
213     
214     fact = 1;
215     val = 0;
216     for(i = 0; i < 11; i++){
217         val = val + (bcd[i] * fact);
218         fact = fact * 10;
219     }
220     return val;
221 }
222
223 unsigned long read_numeric(unsigned int initial, unsigned char digit,
224         char startx, char starty)
225 {
226     unsigned char c;
227     unsigned char n;
228     char i;
229     unsigned long val;
230     unsigned long v;
231     char d;
232
233     d = digit - 1;
234     val =(unsigned long) initial;
235     i = d;
236     do {
237 //        _CURSOR_OFF();
238        ClrWdt();
239         _LOCATE(startx, starty);
240         print_numeric_nosupress(val, digit);
241        ClrWdt();
242         _LOCATE(startx + d -  i, starty);
243        _CURSOR_ON();
244
245         c = pollkey_single();
246         if(c == charcode_0){
247             val = subst_numeric(val, i, 0);
248             i--;
249         } else if((c >= charcode_1) && (c <= charcode_9)) {
250             val = subst_numeric(val, i, c - charcode_1 + 1);
251             i--;
252         } else if(c == charcode_f) {
253             // Enter
254             break;
255         } else if(c == charcode_a) {
256             // Del
257             val = val / 10;
258             i++;
259         } else if(c == charcode_b) {
260             // cancel
261            _CURSOR_OFF();
262             return 0xffffffff;
263         }  else if(c == charcode_e) {
264             i++;
265         } else if(c == charcode_d) {
266             i--;
267         }
268        if(i <= 0) i = 0;
269        if(i > d) i = d;
270     } while(1);
271     _CURSOR_OFF();
272     if(val > 0x7fffffff) val = 0x7fffffff;
273     return val;
274 }
275
276 unsigned char readkey_compare(void)
277 {
278     char b;
279     char c;
280     char d;
281     char e;
282     unsigned char shift;
283     unsigned char f;
284     f = 0;
285     e = 0;
286     for(d = 0; d < 2; d++) {
287         shift = 0x01;
288         for(b = 0; b < 8; b++){
289             c = 0;
290             if((keyin_now.byte[d] & shift) != 0) c++;
291             if((keyin_old[0].byte[d] & shift) != 0) c++;
292             if((keyin_old[1].byte[d] & shift) != 0) c++;
293             if(c >= 2) {
294             /*
295              * Clear older-inputs on .
296              */
297                 f |= 1;
298                 keyin_old[0].byte[d] &= ~shift;
299                 keyin_old[1].byte[d] &= ~shift;
300                 keyin_now.byte[d] &= ~shift;
301                 push_keyinfifo(charcodemap[e]);
302             }
303             shift <<= 1;
304             e++;
305         }
306     }
307     /**/
308     return f;
309 }
310
311 unsigned char readkey(void)
312 {
313     unsigned char i;
314     for(i = 0; i < 9; i++) {
315         idle_time_ms(2); // 2ms
316         readkey_io(i);
317 //        ClrWdt();
318     }
319     readkey_compare();
320     return pop_keyinfifo();
321 }
322
323
324 unsigned char pollkey_single(void)
325 {
326     unsigned int penalty = 0;
327     unsigned char c;
328
329 //    cold = charcode_null;
330     do {
331         idle_time_ms(5); // 5ms.
332         c = readkey(); // 2 * 9 = 18ms
333         ClrWdt();
334         if(c != charcode_null) {
335             if(cold != c){
336                 cold = c;
337                 return c;
338             }
339             penalty = 0;
340         } else {
341             penalty++;
342             if(penalty > 4) {
343                 penalty = 0;
344                 cold = charcode_null; // About 100ms
345             }
346         }
347     } while(1);
348 }
349
350
351 unsigned char pollkey_numeric(unsigned char init)
352 {
353     unsigned char c;
354     c = pollkey_single();
355     if(c == charcode_0) {
356         return 0;
357     } else if((c >= charcode_1) && (c <= charcode_9)){
358         return c;
359     } else {
360         return init;
361     }
362 }
363
364 unsigned char pollkey_single_timeout(unsigned int limit, unsigned char repeat)
365 {
366     unsigned char c;
367     unsigned int ticks = 0;
368     unsigned char penalty = 0;
369     unsigned char count = 0;
370
371
372     cold = charcode_null;
373     pollkeybuf[0] = charcode_null;
374     do {
375         if(limit != 0) {
376             ticks++;
377             if(ticks > limit) {
378                 break;
379             }
380         }
381         idle_time_ms(5); // 5ms.
382         c = readkey(); // 2 * 9 = 18ms
383         ClrWdt();
384         ticks++;
385         if(c != charcode_null){
386             if(cold != c) {
387                 pollkeybuf[count++] = c;
388                 cold = c;
389                 count++;
390                 if(repeat == 0) {
391                         break;
392                 }
393                 penalty = 0;
394             }
395         }  else {
396             penalty++;
397             if(penalty > 4){
398                 penalty = 0;
399                 cold = charcode_null;
400             }
401         }
402     } while(count < 32);
403
404     /*
405      * Set Deadzone.
406      */
407     if(limit == 0) {
408         while(ticks <= limit) {
409             idle_time_ms(5 + 18);
410             ticks++;
411         }
412     }
413     c = pollkeybuf[0];
414     return c;
415 }
416 /*
417  * Notes:
418  * Initialize sequence:
419  * keyin_init();
420  * keyin_ioinit();
421  * 
422  * Read-key-sequence:
423  * In interrupt/unsleep hook(call per Nms):
424  * readkey_io();
425  * readkey_compare();
426  *
427  * In application handler:
428  * c = pop_keyinfifo();
429  * if(c != 0) do(c);
430  */