OSDN Git Service

[UI] Using key is only keypad; '0' to 'F'.
[openi2cradio/OpenI2CRadio.git] / main.c
1 /*
2  * OpenI2CRADIO
3  * Config & Main routine.
4  * Copyright (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
5  * License: GPL2+LE
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License as published by
9  *  the Free Software Foundation; either version 2,
10  *  or (at your option) any later version.
11  *  This library / program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14  *  See the GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this library; see the file COPYING. If not, write to the
18  *  Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
19  *  MA 02110-1301, USA.
20  *
21  *  As a special exception, if you link this(includeed from sdcc) library
22  *  with other files, some of which are compiled with SDCC,
23  *  to produce an executable, this library does not by itself cause
24  *  the resulting executable to be covered by the GNU General Public License.
25  *  This exception does not however invalidate any other reasons why
26  *  the executable file might be covered by the GNU General Public License.
27  */
28
29 #include <stdarg.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sdcc-lib.h>
34 #include <pic18fregs.h> /* ONLY FOR PIC18x */
35 #include <signal.h>
36 #include <delay.h>
37
38 #include "iodef.h"
39 #include "idle.h"
40 #include "i2c_io.h"
41 #include "akc6955.h"
42 #include "lcd_acm1602.h"
43 #include "ui.h"
44
45 /*
46  * Config words.
47  */
48 #if defined(pic18f23k22) || defined(pic18f24k22) || defined(pic18f25k22) || defined(pic18f26k22)
49 #pragma stack 0x200 256 // Set stack size to 256bytes.
50 #pragma config FOSC=INTIO67,BORV=190,BOREN=ON,PWRTEN=ON
51 #pragma config WDTEN=ON,WDTPS=32768
52 #pragma config PBADEN=OFF,MCLRE=EXTMCLR,STVREN=ON,LVP=OFF,DEBUG=ON//,XINST=ON
53 #pragma config CP0=OFF,CP1=OFF,CPB=OFF,CPD=OFF
54 #pragma config WRT0=OFF,WRT1=OFF,WRTB=OFF,WRTC=OFF,WRTD=OFF
55 #pragma config EBTR0=OFF,EBTR1=OFF,EBTRB=OFF
56 #endif
57 // For 4xK20 or 2xK20 Series
58 #if defined(pic18f43k20) || defined(pic18f44k20) || defined(pic18f45k20) || defined(pic18f46k20) || \
59     defined(pic18f23k20) || defined(pic18f24k20) || defined(pic18f25k20) || defined(pic18f26k20)
60 #pragma stack 0x200 256
61 #pragma config FOSC=INTIO67,FCMEN=ON,PWRT=ON,BOREN=ON,BORV=22
62 #pragma config WDTEN=ON,WDTPS=32768,PBADEN=OFF,LPT1OSC=ON,MCLRE=ON
63 #pragma config STVREN=ON,DEBUG=ON
64 #pragma config CP0=OFF,CP1=OFF,CP2=OFF,CP3=OFF
65 #pragma config CPB=OFF,CPD=OFF
66 #pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF,WRT3=OFF
67 #pragma config WRTC=OFF,WRTB=OFF,WRTD=OFF
68 #pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTR3=OFF,EBTRB=OFF
69 #endif
70
71 //#define _LCD_DEBUG 1
72
73 SIGHANDLER(TMR0_handler)
74 {
75    unsigned char tmr0f;
76    unsigned char t0con;
77
78    // Stop timer0
79    t0con = T0CON;
80    t0con &= ~_IDLEN;
81    T0CON = t0con;
82
83    // Read IOKEYS
84    readkey_io();
85
86    // Clear interrupt flag
87    tmr0f = INTCON;
88    tmr0f &= ~(_TMR0IF);
89    INTCON = tmr0f;
90
91    return;
92 }
93
94
95 DEF_INTLOW(intlow_handler)
96   DEF_HANDLER(SIG_TMR0, TMR0_handler)
97 END_DEF
98
99
100 unsigned int amfreq;
101 unsigned int fmfreq;
102 unsigned char amband;
103 unsigned char fmband;
104 unsigned char fm;
105 unsigned char am_mode3k;
106 unsigned char am_userbandnum;
107 unsigned char fm_userbandnum;
108 typedef struct {
109     unsigned char mode3k; // mode3k if am
110     unsigned char start;
111     unsigned char stop;
112     unsigned int freq;
113 } _userband_t;
114 #define USER_BAND_NUM 4
115 _userband_t am_usrbands[USER_BAND_NUM];
116 _userband_t fm_usrbands[USER_BAND_NUM];
117
118 unsigned char enter_mode;
119 unsigned char numeric_mode;
120 unsigned char menu_node;
121 int backlight_long;
122 unsigned char help_flag;
123 int help_line;
124 int help_section;
125 int ui_language;
126 unsigned int ui_idlecount;
127
128 int recv_signal;
129 int backlight_counter;
130 unsigned char backlight_level;
131
132
133
134 void toggle_amfm(void)
135 {
136     if(fm != 0){
137         fm = 0;
138 #ifndef _LCD_DEBUG
139         akc6955_chg_fm(fm);
140         akc6955_set_amband(amband);
141         akc6955_set_freq(amfreq);
142 #endif
143     } else {
144         fm = 0xff;
145 #ifndef _LCD_DEBUG
146         akc6955_chg_fm(fm);
147         akc6955_set_fmband(fmband);
148         akc6955_set_freq(fmfreq);
149 #endif
150     }
151 }
152
153 void update_display(void)
154 {
155     if(fm != 0){ // FM
156         _LOCATE(0,0);
157         if(fmband < AKC6955_BAND_TV1) {
158             printstr("FM");
159             _PUTCHAR('1' + (fmband & 7));
160         } else if(fmband < AKC6955_BAND_FMUSER){
161             printstr("TV");
162             _PUTCHAR('1' + fmband - AKC6955_BAND_TV1);
163         } else { // USER
164             printstr("FMUSR");
165         }
166     } else { // AM
167         _LOCATE(0,1);
168         if(amband == AKC6955_BAND_LW) {
169             printstr("LW");
170         } else if(amband <AKC6955_BAND_SW1) { //MW
171             printstr("MW");
172             _PUTCHAR('1' + amband - AKC6955_BAND_MW1);
173         } else if(amband < AKC6955_BAND_AMUSER) { //MW
174             printstr("SW");
175             _PUTCHAR('1' + amband - AKC6955_BAND_SW1);
176         } else if(amband == AKC6955_BAND_MW4){
177             printstr("MW4");
178         } else {
179             printstr("AMUSR");
180         }
181      }
182      _LOCATE(16-4 ,1);
183      if(fm != 0){
184          printstr("MHz");
185      } else {
186          printstr("KHz");
187      }
188      _LOCATE(16-5, 1);
189      if(fm != 0){
190          int freq_lo = fmfreq % 100;
191          int freq_hi = fmfreq / 100;
192          print_numeric(freq_hi, 0xff);
193          _PUTCHAR('.');
194          print_numeric(freq_lo, 0xff);
195      } else {
196          print_numeric(amfreq, 0xff);
197      }
198      // Signal
199      _LOCATE(0, 0);
200      printstr("S=");
201      print_numeric(recv_signal, 0xff);
202 }
203
204
205 void setfreq_direct(void)
206 {
207     unsigned int val;
208     _CLS();
209     if(fm != 0){
210         // FM
211         _LOCATE(0,0);
212         printstr("Set Freq:FM");
213         val = fmfreq;
214         val = read_numeric(val, 5, 7, 1);
215         fmfreq = val;
216         akc6955_set_freq(val);
217         idle(0xff00);
218         fmfreq = akc6955_get_freq();
219     } else {
220         // FM
221         _LOCATE(0,0);
222         printstr("Set Freq:AM");
223         val = amfreq;
224         val = read_numeric(val, 5, 7, 1);
225         amfreq = val;
226         akc6955_set_freq(val);
227         idle(0xff00);
228         amfreq = akc6955_get_freq();
229     }
230 }
231
232 void setband_direct(void)
233 {
234     unsigned int band;
235     _CLS();
236     _LOCATE(0,0);
237     if(fm != 0){
238         printstr("Set Band:FM");
239         band = fmband & 7;
240         band = read_numeric(band, 2, 7, 1);
241         akc6955_set_fmband(band);
242         akc6955_do_tune();
243         idle(0xff00);
244         fmfreq = akc6955_get_freq();
245     } else {
246         printstr("Set Band:AM");
247         band = amband & 0x1f;
248         band = read_numeric(band, 2, 7, 1);
249         akc6955_set_amband(band);
250         akc6955_do_tune();
251         idle(0xff00);
252         amfreq = akc6955_get_freq();
253     }
254 }
255
256 void call_userband(unsigned char num)
257 {
258     unsigned int freq;
259     unsigned int ch;
260     if(num >= USER_BAND_NUM) return;
261     if(fm != 0){
262         freq = fm_usrbands[num].freq;
263         ch = ((freq - 3000) / 25) * 10;
264         akc6955_set_userband(fm_usrbands[num].start, fm_usrbands[num].stop, ch,
265                             fm_usrbands[num].mode3k);
266     } else {
267         unsigned int p = 5;
268         if(am_usrbands[num].mode3k != 0) p = 3;
269         freq = am_usrbands[num].freq;
270         ch = freq / p;
271         akc6955_set_userband(am_usrbands[num].start, am_usrbands[num].stop, ch,
272                             am_usrbands[num].mode3k);
273     }
274 }
275
276 void set_userband(void)
277 {
278     unsigned int from,to;
279     unsigned char c;
280     unsigned char p;
281     unsigned char mode3k;
282     unsigned int input_flag;
283     char cc;
284
285     _CLS();
286     _LOCATE(0,0);
287     printstr("User ch:");
288     do {
289         input_flag = readkey_compare();
290         idle(0xff80);
291     } while(input_flag == 0);
292     c = pop_keyinfifo();
293
294     if(c > charcode_0) return;
295     if(c < charcode_1) return;
296     if(c == charcode_0) {
297         c = 0;
298     } else {
299         c = c - charcode_1 + 1;
300     }
301     if(c >= USER_BAND_NUM) return;
302     if(fm != 0){
303         from = fm_usrbands[c].start * 80 + 3000; // 32*25/10
304         to = fm_usrbands[c].stop * 80 + 3000;
305         _CLS();
306         _LOCATE(0,0);
307         printstr("FM #");
308         print_numeric_nosupress(c, 1);
309         printstr(" From:");
310         from = read_numeric(from, 5, 7, 1);
311         _CLS();
312         _LOCATE(0,0);
313         printstr("FM #");
314         print_numeric_nosupress(c, 1);
315         printstr(" To:");
316         to = read_numeric(to, 5, 7, 1);
317         fm_usrbands[c].start = (from - 3000) / 80;
318         fm_usrbands[c].stop = (to - 3000) / 80;
319         fm_usrbands[c].freq = from * 80 + 3000;
320         fm_userbandnum = c;
321     } else {
322         mode3k = am_usrbands[c].mode3k;
323         p = 96; // 3*32
324         if(mode3k == 0) p = 160; // 5*32
325         from = am_usrbands[c].start * p; 
326         to = am_usrbands[c].stop * p;
327         _CLS();
328         _LOCATE(0,0);
329         printstr("AM #");
330         print_numeric_nosupress(c, 1);
331         printstr(" Step:");
332         _LOCATE(0,1);
333         printstr("0=3k 1=5k");
334         do {
335             input_flag = readkey_compare();
336             idle(0xff80);
337         } while(input_flag == 0);
338         cc = pop_keyinfifo();
339
340         if(cc == charcode_0){
341             p = 96;
342             mode3k = 0xff;
343         } else if(cc = charcode_1) {
344             p = 160;
345             mode3k = 0;
346         }
347         _CLS();
348         _LOCATE(0,0);
349         printstr("AM #");
350         print_numeric_nosupress(c, 1);
351         printstr(" From:");
352         from = read_numeric(from, 5, 7, 1);
353         _CLS();
354         _LOCATE(0,0);
355         printstr("AM #");
356         print_numeric_nosupress(c, 1);
357         printstr(" To:");
358         to = read_numeric(to, 5, 7, 1);
359         am_usrbands[c].start = from / p;
360         am_usrbands[c].stop = to  / p;
361         am_usrbands[c].mode3k = mode3k;
362         am_usrbands[c].freq = from * p;
363         am_userbandnum = c;
364     }
365     call_userband(c);
366 }
367
368 void input_userband(void)
369 {
370     unsigned char c;
371     unsigned char input_flag;
372     do{
373     _CLS();
374     _LOCATE(0,0);
375     printstr("User Band");
376     _LOCATE(0,1);
377     printstr("   #");
378     do {
379         input_flag = readkey_compare();
380         idle(0xff80);
381     } while(input_flag == 0);
382     c = pop_keyinfifo();
383
384     if((c >= charcode_a) && (c <= charcode_f)){
385         break;
386     }
387     if(c == charcode_0) {
388         _PUTCHAR('0');
389         if(fm != 0){
390            fm_userbandnum = 0;
391         } else {
392            am_userbandnum = 0;
393         }
394         call_userband(0);
395     } else {
396         c = c - charcode_1 + 1;
397         if(c < USER_BAND_NUM) {
398             _PUTCHAR(c + '0');
399             if(fm != 0){
400                fm_userbandnum = c;
401             } else {
402                 am_userbandnum = c;
403             }
404             call_userband(c);
405         }
406     }
407     idle(0xff00);
408     } while(1);
409     _CLS();
410 }
411
412
413 void main_menu(void)
414 {
415     unsigned char c;
416     unsigned int input_flag;
417     _CLS();
418     _LOCATE(0,0);
419     printstr("Menu:F=HELP");
420     _LOCATE(1,0);
421     printstr("A=CANCEL");
422     do{
423         do {
424             input_flag = readkey_compare();
425             idle(0xff80);
426         } while(input_flag == 0);
427
428         c = pop_keyinfifo();
429         if((c < charcode_1) || ( c >charcode_s3)) {
430             idle(0xff00);
431             continue; // Error
432         }
433         if(c == charcode_f){
434             // HELP
435         } else if(c == charcode_a){
436             // Cancel
437             break;
438         } else if(c == charcode_1){
439             // AM
440             fm = 0;
441             akc6955_chg_fm(fm);
442             akc6955_set_amband(amband);
443             akc6955_set_freq(amfreq);
444             break;
445         } else if(c == charcode_2){
446             // Band
447             setband_direct();
448             break;
449         } else if(c == charcode_3){
450             // Band
451             setfreq_direct();
452             break;
453         } else if(c == charcode_4){
454             // fm
455             fm = 0xff;
456             akc6955_chg_fm(fm);
457             akc6955_set_fmband(fmband);
458             akc6955_set_freq(fmfreq);
459             break;
460         } else if(c == charcode_5){
461             // Scan
462             break;
463         } else if(c == charcode_6){
464             // Set gain
465             break;
466         } else if(c == charcode_7){
467             // Set volume
468             break;
469         } else if(c == charcode_8){
470             // Set sensitivity
471             break;
472         } else if(c == charcode_9){
473             // Set NF
474             break;
475         } else if(c == charcode_0){
476             // Setup Menu
477             break;
478         } else if(c == charcode_b){
479             // Call userband
480             input_userband();
481             break;
482         } else if(c == charcode_c){
483             // Set userband
484             set_userband();
485             break;
486         } else if(c == charcode_d){
487             // Reserve
488             break;
489         } else if(c == charcode_e){
490             // Reserve
491             break;
492         }
493         idle(0xff00);
494     } while(1);
495 }
496
497 void setfreq_updown(unsigned char ctlword)
498 {
499     unsigned char c;
500 #ifndef _LCD_DEBUG
501     switch(ctlword){
502         case charcode_8: // Change band
503             if(fm != 0){
504                 amband++;
505                 if(amband > 18) amband = 0;
506 //                amfreq = akc6955_setfreq(amfreq)
507                 akc6955_set_amband(amband);
508                 _AKC6955_WAIT_62_5MS(); // 62.5ms
509                 amband = akc6955_get_amband();
510                 amfreq = akc6955_get_freq();
511             } else {
512                 fmband++;
513                 if(fmband > 7) fmband = 0;
514 //                amfreq = akc6955_setfreq(amfreq)
515                 akc6955_set_fmband(fmband);
516                 _AKC6955_WAIT_62_5MS(); // 62.5ms
517                 fmband = akc6955_get_fmband();
518                 fmfreq = akc6955_get_freq();
519             }
520             break;
521         case charcode_2: // Change band
522             if(fm != 0){
523                 amband--;
524                 if(amband == 0) amband = 18;
525                 if(amband >= 18) amband = 18;
526 //                amfreq = akc6955_setfreq(amfreq)
527                 akc6955_set_amband(amband);
528                 _AKC6955_WAIT_62_5MS(); // 62.5ms
529                 amband = akc6955_get_amband();
530                 amfreq = akc6955_get_freq();
531             } else {
532                 fmband--;
533                 if(fmband == 0) fmband = 7;
534                 if(fmband >= 7) fmband = 7;
535 //                amfreq = akc6955_setfreq(amfreq)
536                 akc6955_set_fmband(fmband);
537                 _AKC6955_WAIT_62_5MS(); // 62.5ms
538                 fmband = akc6955_get_fmband();
539                 fmfreq = akc6955_get_freq();
540             }
541             break;
542         case charcode_4: // Down Freq;
543             if(fm != 0){
544                 fmfreq = akc6955_down_freq(10); // DOWN 100KHz
545             } else {
546                 amfreq = akc6955_down_freq(10); // DOWN 10KHz
547             }
548             break;
549         case charcode_6: // Down Freq;
550             if(fm != 0){
551                 fmfreq = akc6955_up_freq(10); // UP 100KHz
552             } else {
553                 amfreq = akc6955_up_freq(10); // UP 10KHz
554             }
555             break;
556         case charcode_7: // Down Fast;
557             if(fm != 0){
558                 fmfreq = akc6955_down_freq(50); // DOWN 500KHz
559             } else {
560                 amfreq = akc6955_down_freq(50); // DOWN 50KHz
561             }
562             break;
563         case charcode_9: // Down Fast;
564             if(fm != 0){
565                 fmfreq = akc6955_up_freq(50); // UP 100KHz
566             } else {
567                 amfreq = akc6955_up_freq(50); // UP 10KHz
568             }
569             break;
570         case charcode_1: // Down Slow;
571             if(fm != 0){
572                 fmfreq = akc6955_down_freq(5); // DOWN 50KHz
573             } else {
574                 amfreq = akc6955_down_freq(5); // DOWN 50KHz
575             }
576             break;
577         case charcode_3: // Down Slow;
578             if(fm != 0){
579                 fmfreq = akc6955_up_freq(5); // UP 50KHz
580             } else {
581                 amfreq = akc6955_up_freq(5); // UP 5KHz
582             }
583             break;
584         case charcode_0: // Step
585             if(fm == 0){
586                 if(am_mode3k == 0) {
587                     am_mode3k = 0xff;
588                 } else {
589                     am_mode3k = 0;
590                 }
591                 amfreq = akc6955_mode3k(am_mode3k);
592             }
593             break;
594         case charcode_a: // Toggle FM
595             toggle_amfm();
596             break;
597         case charcode_b:
598             // Userband
599             break;
600         case charcode_c:
601             break;
602         case charcode_d:
603             // Delete
604             break;
605         case charcode_e: // Backlight ON
606             backlight_counter = backlight_long;
607             break;
608         case charcode_f:
609             main_menu();
610             break;
611         default:
612             break;
613     }
614 #endif
615 }
616 /*
617  * 
618  */
619 int main(void)
620 {
621     char readchar;
622     unsigned char input_flag;
623     char i;
624 #ifdef _LCD_DEBUG
625     unsigned char power_flag;
626 #endif
627     keyin_init();
628     keyin_ioinit();
629     idle_init();
630
631     i2c1_init();
632
633     _AKC6955_WAIT_125_0MS(); // Wait 125ms
634 #ifdef _LCD_DEBUG
635     power_flag = 0xff;
636 #endif
637     backlight_long = 256;
638     backlight_counter = backlight_long;
639     backlight_level = 255;
640     ui_idlecount = 0xf800;
641
642     acm1602_init(0xa0, 1); //Init LCD
643 //    _AKC6955_WAIT_125_0MS(); // Wait 125ms
644     _LOCATE(0,0);
645     printstr("Hello;-)");
646
647     
648     // Init AKC6955
649     amfreq = 954;
650     fmfreq = 8000; // 10KHz order.
651     amband = AKC6955_BAND_MW2;
652     fmband = AKC6955_BAND_FM2;
653     am_mode3k = 0xff;
654     fm = 0;
655     recv_signal = 0;
656     am_userbandnum = 0;
657     fm_userbandnum = 0;
658     for(i = 0; i < 4; i++){
659         am_usrbands[i].start = 0x19;
660         am_usrbands[i].stop  = 0x32;
661     }
662     for(i = 0; i < 4; i++){
663         fm_usrbands[i].start = 0x19;
664         fm_usrbands[i].stop  = 0x32;
665     }
666
667     /* Check EEPROM */
668     /* Push default parameters to AKC6955*/
669
670 #ifndef _LCD_DEBUG
671     akc6955_chg_fm(fm); // Set to AM
672     akc6955_set_amband(amband);
673     akc6955_set_freq(amfreq); // Dummy, TBS (954KHz)
674     akc6955_set_power(0xff); // Power ON
675 #endif
676
677 #ifdef _LCD_DEBUG
678     idle(0xf000);
679 #else
680     idle(0xff00);
681 #endif
682     do {
683         /* Main routine*/
684         input_flag = readkey_compare();
685         if(input_flag != 0){
686             readchar = pop_keyinfifo();
687             if((readchar >= charcode_1) && (readchar <= charcode_f)) {
688                     setfreq_updown(readchar);
689             } else {
690                 // Other is skip
691             }
692         }
693 #ifndef _LCD_DEBUG
694         recv_signal = akc6955_read_level();
695         if(fm != 0){
696             fmfreq = akc6955_get_freq();
697         } else {
698             amfreq = akc6955_get_freq();
699         }
700 #endif
701         // Check battery (include idle?)
702         // Read AKJC6955's status
703         // Putstring to LCD.
704
705         update_display();
706         if(backlight_counter > 0) {
707             backlight_counter--;
708             set_backlight(0xff, backlight_level); // Turn ON
709         } else {
710             set_backlight(0x00, 0); // Turn OFF
711         }
712 #ifdef _LCD_DEBUG
713         if(power_flag != 0x00) {
714             power_flag = 0x00;
715         } else {
716             power_flag = 0xff;
717         }
718         setsignal_tune(power_flag);
719 #endif
720         idle(ui_idlecount);
721     } while(1);
722 }
723