OSDN Git Service

[Backlight][LCD][v1.0] Fix white screen on resume.
[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 void keyin_init(void)
108 {
109     char i;
110     /* Initialize vars*/
111     for(i = 0; i < 2; i++) {
112         keyin_old[0].byte[i] = 0x00;
113         keyin_old[1].byte[i] = 0x00;
114         keyin_now.byte[i] = 0x00;
115     }
116     for(i = 0; i < 32; i++) keyin_fifo[i] = 0x00;
117     keyin_nowp = 0;
118     keyin_readp = 0;
119     keyin_counter = 0;
120     cold = charcode_null;
121 }
122 /*
123  * Push to keyin fifo; not used atomic-writing.
124  */
125 #ifdef __SDCC
126 void push_keyinfifo(char b) __critical
127 #else
128 void push_keyinfifo(char b)
129 #endif
130 {
131     if(keyin_counter >= 31) {
132         return; // Discard data.
133     }
134     keyin_fifo[keyin_nowp] = b;
135     keyin_nowp++;
136     keyin_counter++;
137     if(keyin_nowp > 31) keyin_nowp = 0;
138 }
139
140 /*
141  * Pop from keyin fifo; not used atomic-reading.
142  */
143 #ifdef __SDCC
144 char pop_keyinfifo(void) __critical
145 #else
146 char pop_keyinfifo(void)
147 #endif
148 {
149     char c;
150     if(keyin_counter <= 0) {
151         keyin_counter = 0;
152         return charcode_null ;
153     }
154     c = keyin_fifo[keyin_readp];
155     keyin_readp++;
156     keyin_counter--;
157     if(keyin_readp > 31) keyin_readp = 0;
158     return c;
159 }
160
161 void printstr(char *s)
162 {
163     int p = 0;
164 //    _CURSOR_RIGHT();
165     if(s == NULL) return;
166     do {
167         if(s[p] == '\0') break;
168         _PUTCHAR(s[p]);
169         p++;
170     } while(p < 255);
171 }
172
173
174
175 static void uint2bcd(unsigned long data, unsigned char *bcd)
176 {
177     unsigned char i;
178     unsigned char j;
179
180     for(i = 0; i <= 10; i++){
181         bcd[i] = data % 10;
182         data = data / 10;
183     }
184     bcd[10] = 0;
185 }
186
187 void print_numeric_nosupress(unsigned long data, unsigned char digit)
188 {
189     unsigned char i;
190     unsigned char bcd[11];
191
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             return 0xffffffff;
262         }  else if(c == charcode_e) {
263             i++;
264         } else if(c == charcode_d) {
265             i--;
266         }
267        if(i <= 0) i = 0;
268        if(i > d) i = d;
269     } while(1);
270     _CURSOR_OFF();
271     if(val > 0x7fffffff) val = 0x7fffffff;
272     return val;
273 }
274
275 unsigned char readkey_compare(void)
276 {
277     char b;
278     char c;
279     char d;
280     char e;
281     unsigned char shift;
282     unsigned char f;
283     f = 0;
284     e = 0;
285     for(d = 0; d < 2; d++) {
286         shift = 0x01;
287         for(b = 0; b < 8; b++){
288             c = 0;
289             if((keyin_now.byte[d] & shift) != 0) c++;
290             if((keyin_old[0].byte[d] & shift) != 0) c++;
291             if((keyin_old[1].byte[d] & shift) != 0) c++;
292             if(c >= 2) {
293             /*
294              * Clear older-inputs on .
295              */
296                 f |= 1;
297                 keyin_old[0].byte[d] &= ~shift;
298                 keyin_old[1].byte[d] &= ~shift;
299                 keyin_now.byte[d] &= ~shift;
300                 push_keyinfifo(charcodemap[e]);
301             }
302             shift <<= 1;
303             e++;
304         }
305     }
306     /**/
307     return f;
308 }
309
310 unsigned char readkey(void)
311 {
312     unsigned char i;
313     for(i = 0; i < 9; i++) {
314         idle_time_ms(2); // 2ms
315         readkey_io(i);
316 //        ClrWdt();
317     }
318     readkey_compare();
319     return pop_keyinfifo();
320 }
321
322
323 unsigned char pollkey_single(void)
324 {
325     unsigned int penalty = 0;
326     unsigned char c;
327
328 //    cold = charcode_null;
329     do {
330         idle_time_ms(5); // 5ms.
331         c = readkey(); // 2 * 9 = 18ms
332         ClrWdt();
333         if(c != charcode_null) {
334             if(cold != c){
335                 cold = c;
336                 return c;
337             }
338             penalty = 0;
339         } else {
340             penalty++;
341             if(penalty > 4) {
342                 penalty = 0;
343                 cold = charcode_null; // About 100ms
344             }
345         }
346     } while(1);
347 }
348 unsigned char pollkey_numeric(unsigned char init)
349 {
350     unsigned char c;
351     c = pollkey_single();
352     if(c == charcode_0) {
353         return 0;
354     } else if((c >= charcode_1) && (c <= charcode_9)){
355         return c;
356     } else {
357         return init;
358     }
359 }
360
361 unsigned char pollkey_single_timeout(unsigned int limit, unsigned char repeat)
362 {
363     unsigned char c;
364     unsigned int ticks = 0;
365     unsigned char penalty = 0;
366     unsigned char count = 0;
367
368
369     cold = charcode_null;
370     pollkeybuf[0] = charcode_null;
371     do {
372         if(limit != 0) {
373             ticks++;
374             if(ticks > limit) {
375                 break;
376             }
377         }
378         idle_time_ms(5); // 5ms.
379         c = readkey(); // 2 * 9 = 18ms
380         ClrWdt();
381         ticks++;
382         if(c != charcode_null){
383             if(cold != c) {
384                 pollkeybuf[count++] = c;
385                 cold = c;
386                 count++;
387                 if(repeat == 0) {
388                         break;
389                 }
390                 penalty = 0;
391             }
392         }  else {
393             penalty++;
394             if(penalty > 4){
395                 penalty = 0;
396                 cold = charcode_null;
397             }
398         }
399     } while(count < 32);
400
401     /*
402      * Set Deadzone.
403      */
404     if(limit == 0) {
405         while(ticks <= limit) {
406             idle_time_ms(5 + 18);
407             ticks++;
408         }
409     }
410     c = pollkeybuf[0];
411     return c;
412 }
413 /*
414  * Notes:
415  * Initialize sequence:
416  * keyin_init();
417  * keyin_ioinit();
418  * 
419  * Read-key-sequence:
420  * In interrupt/unsleep hook(call per Nms):
421  * readkey_io();
422  * readkey_compare();
423  *
424  * In application handler:
425  * c = pop_keyinfifo();
426  * if(c != 0) do(c);
427  */