OSDN Git Service

[UI] Add direct-band set(but not effect :)
[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 #include "eeprom.h"
45 #include "ioports.h"
46 #include "menu.h"
47 /*
48  * Config words.
49  */
50 #if defined(pic18f23k22) || defined(pic18f24k22) || defined(pic18f25k22) || defined(pic18f26k22)
51 //#pragma stack 0x200 256 // Set stack size to 256bytes.
52 #pragma config FOSC=INTIO67,BORV=190,BOREN=ON,PWRTEN=ON
53 #pragma config WDTEN=ON,WDTPS=32768
54 #pragma config PBADEN=OFF,MCLRE=EXTMCLR,STVREN=ON,LVP=OFF,DEBUG=ON//,XINST=ON
55 //#pragma config PBADEN=OFF,MCLRE=EXTMCLR,STVREN=ON,LVP=OFF//,XINST=ON
56 #pragma config CP0=OFF,CP1=OFF,CPB=OFF,CPD=OFF
57 #pragma config WRT0=OFF,WRT1=OFF,WRTB=OFF,WRTC=OFF,WRTD=OFF
58 #pragma config EBTR0=OFF,EBTR1=OFF,EBTRB=OFF
59 #endif
60 // For 4xK20 or 2xK20 Series
61 #if defined(pic18f43k20) || defined(pic18f44k20) || defined(pic18f45k20) || defined(pic18f46k20) || \
62     defined(pic18f23k20) || defined(pic18f24k20) || defined(pic18f25k20) || defined(pic18f26k20)
63
64 #pragma stack 0x200 256
65 #pragma config FOSC=HS,FCMEN=ON,PWRT=ON,BOREN=ON,BORV=22
66 #pragma config WDTEN=ON,WDTPS=32768,PBADEN=OFF,HFOFST=ON,LPT1OSC=OFF,MCLRE=ON
67 #pragma config STVREN=ON,DEBUG=ON
68 //#pragma config CP0=OFF,CP1=OFF,CP2=OFF,CP3=OFF
69 //#pragma config CPB=OFF,CPD=OFF
70 //#pragma config WRT0=OFF,WRT1=OFF,WRT2=OFF,WRT3=OFF
71 //#pragma config WRTC=OFF,WRTB=OFF,WRTD=OFF
72 //#pragma config EBTR0=OFF,EBTR1=OFF,EBTR2=OFF,EBTR3=OFF,EBTRB=OFF
73 #endif
74
75 //#define _LCD_DEBUG 1
76
77 SIGHANDLER(TMR0_handler)
78 {
79    unsigned char tmr0f;
80    unsigned char t0con;
81
82    // Stop timer0
83    t0con = T0CON;
84    t0con &= ~_IDLEN;
85    T0CON = t0con;
86
87
88    // Clear interrupt flag
89    tmr0f = INTCON;
90    tmr0f &= ~(_TMR0IF | _TMR0IE);
91    INTCON = tmr0f;
92
93    return;
94 }
95
96 /*
97  * Interrupt wake up every 1ms.
98  */
99 SIGHANDLER(TMR3_Handler)
100 {
101     if(statecount >= 8) statecount = 0;
102     readkey_io(statecount);
103     statecount++;
104     if(statecount > 7) readkey_compare(); // Compare and push to fifo.
105     PIR2bits.TMR3IF  = 0;
106     PIE2bits.TMR3IE  = 1;
107     TMR3_set();
108 }
109
110 DEF_INTLOW(intlow_handler)
111   DEF_HANDLER(SIG_TMR0, TMR0_handler)
112 //  DEF_HANDLER(SIG_TMR3, TMR3_Handler)
113 END_DEF
114
115
116 unsigned int amfreq;
117 unsigned int fmfreq;
118 unsigned char amband;
119 unsigned char fmband;
120 unsigned char fm;
121 unsigned char am_mode3k;
122 unsigned char am_userbandnum;
123 unsigned char fm_userbandnum;
124 _userband_t am_usrbands[USER_BAND_NUM];
125 _userband_t fm_usrbands[USER_BAND_NUM];
126
127 unsigned char enter_mode;
128 unsigned char numeric_mode;
129 unsigned char menu_node;
130 int backlight_long;
131 unsigned int ui_idlecount;
132 unsigned char scanflag;
133
134 int recv_signal;
135 int backlight_counter;
136 unsigned char backlight_level;
137 unsigned char pollkeybuf[33];
138
139
140 unsigned int writeword_eeprom(unsigned int p, unsigned int *sum, unsigned int word)
141 {
142     ClrWdt();
143     if(eeprom_writebyte(p, word >> 8) == 0) return p; // Error
144     *sum = calcsum_byte(*sum, (word >> 8));
145
146     if(eeprom_writebyte(p, word & 0xff) == 0) return p+1; // Error
147     *sum = calcsum_byte(*sum, word & 0xff);
148     return 0xffff;
149 }
150
151 unsigned int writebyte_eeprom(unsigned int p, unsigned int *sum, unsigned char b)
152 {
153     ClrWdt();
154     if(eeprom_writebyte(p, b) == 0) return p; // Error
155     *sum = calcsum_byte(*sum, b);
156     return 0xffff;
157 }
158
159 void save_eeprom(void)
160 {
161     unsigned int p = 0;
162     unsigned int sum = 0x0000;
163     unsigned char i;
164
165     // Magic word
166     writeword_eeprom(p, &sum, 0x1298);
167     p+= 2;
168     // amfreq
169     writeword_eeprom(p, &sum, amfreq);
170     p+= 2;
171     // amfreq
172     writeword_eeprom(p, &sum, fmfreq);
173     p+= 2;
174
175     writebyte_eeprom(p, &sum, amband);
176     p++;
177     writebyte_eeprom(p, &sum, fmband);
178     p++;
179     writebyte_eeprom(p, &sum, fm);
180     p++;
181     writebyte_eeprom(p, &sum, am_mode3k);
182     p++;
183     writebyte_eeprom(p, &sum, am_userbandnum);
184     p++;
185     writebyte_eeprom(p, &sum, fm_userbandnum);
186     p++;
187
188     for(i = 0 ; i < USER_BAND_NUM; i++){
189         writebyte_eeprom(p, &sum, am_usrbands[i].mode3k);
190         writebyte_eeprom(p + 1, &sum, am_usrbands[i].start);
191         writebyte_eeprom(p + 2, &sum, am_usrbands[i].stop);
192         writeword_eeprom(p + 3, &sum, am_usrbands[i].freq);
193         p += 5;
194     }
195     for(i = 0 ; i < USER_BAND_NUM; i++){
196         writebyte_eeprom(p, &sum, fm_usrbands[i].mode3k);
197         writebyte_eeprom(p + 1, &sum, fm_usrbands[i].start);
198         writebyte_eeprom(p + 2, &sum, fm_usrbands[i].stop);
199         writeword_eeprom(p + 3, &sum, fm_usrbands[i].freq);
200         p += 5;
201     }
202     // Write checksum
203     eeprom_writebyte(p, sum >> 8);
204     eeprom_writebyte(p + 1, sum & 0xff);
205     p+= 2;
206 }
207
208 unsigned int readword_eeprom(unsigned int p, unsigned int *sum)
209 {
210     unsigned char h,l;
211     unsigned int s;
212
213     ClrWdt();
214
215     h = eeprom_readbyte(p);
216     *sum = calcsum_byte(*sum, h);
217
218     l = eeprom_readbyte(p + 1);
219     *sum = calcsum_byte(*sum, l);
220
221     s = (h << 8) + l;
222     return s;
223 }
224
225 unsigned char readbyte_eeprom(unsigned int p, unsigned int *sum)
226 {
227     unsigned char b;
228
229     ClrWdt();
230
231     b = eeprom_readbyte(p);
232     *sum = calcsum_byte(*sum, b);
233
234     return b;
235 }
236
237
238 unsigned char load_eeprom(void)
239 {
240     unsigned int p = 0;
241     unsigned int sum = 0x0000;
242     unsigned char i;
243     unsigned int magic;
244
245     // Magic word
246     magic = readword_eeprom(p, &sum);
247     if(magic != 0x1298) return 0x01; // NO MAGICWORD
248     p+= 2;
249     // amfreq
250     amfreq = readword_eeprom(p, &sum);
251     p+= 2;
252     // fmfreq
253     fmfreq = readword_eeprom(p, &sum);
254     p+= 2;
255
256     amband = readbyte_eeprom(p, &sum);
257     p++;
258     fmband = readbyte_eeprom(p, &sum);
259     p++;
260     fm = readbyte_eeprom(p, &sum);
261     p++;
262     am_mode3k = readbyte_eeprom(p, &sum);
263     p++;
264     am_userbandnum = readbyte_eeprom(p, &sum);
265     p++;
266     fm_userbandnum = readbyte_eeprom(p, &sum);
267     p++;
268
269     for(i = 0 ; i < USER_BAND_NUM; i++){
270         am_usrbands[i].mode3k = readbyte_eeprom(p, &sum);
271         am_usrbands[i].start  = readbyte_eeprom(p + 1, &sum);
272         am_usrbands[i].stop   = readbyte_eeprom(p + 2, &sum);
273         am_usrbands[i].freq   = readword_eeprom(p + 3, &sum);
274         p += 5;
275     }
276     for(i = 0 ; i < USER_BAND_NUM; i++){
277         fm_usrbands[i].mode3k = readbyte_eeprom(p, &sum);
278         fm_usrbands[i].start  = readbyte_eeprom(p + 1, &sum);
279         fm_usrbands[i].stop   = readbyte_eeprom(p + 2, &sum);
280         fm_usrbands[i].freq   = readword_eeprom(p + 3, &sum);
281         p += 5;
282     }
283     // Write checksum
284     magic = (eeprom_readbyte(p) << 8) + eeprom_readbyte(p+1);
285
286     p+= 2;
287     if(sum != magic) return 0x00;
288     return 0xff;
289 }
290
291
292
293 void update_status(void)
294 {
295 #if 0
296         recv_signal = akc6955_read_level();
297         if(fm != 0){
298             fmfreq = akc6955_get_freq();
299         } else {
300             amfreq = akc6955_get_freq();
301         }
302 #endif
303
304 }
305
306
307 void update_display(void)
308 {
309 //    _HOME();
310     _LOCATE(0,0);
311      printstr("S=");
312      print_numeric_nosupress(recv_signal, 3);
313     _LOCATE(0,1);
314 //    _PUTCHAR(' ');
315     if(fm != 0){ // FM
316         if(fmband < AKC6955_BAND_TV1) {
317             printstr("FM");
318             _PUTCHAR('1' + (fmband & 7));
319             printstr("  ");
320         } else if(fmband < AKC6955_BAND_FMUSER){
321             printstr("TV");
322             _PUTCHAR('1' + fmband - AKC6955_BAND_TV1);
323             printstr("  ");
324         } else { // USER
325             printstr("FMUSR");
326         }
327     } else { // AM
328         if(amband == AKC6955_BAND_LW) {
329             printstr("LW   ");
330         } else if(amband <AKC6955_BAND_SW1) { //MW
331             printstr("MW");
332             _PUTCHAR('1' + amband - AKC6955_BAND_MW1);
333             printstr("  ");
334         } else if(amband <AKC6955_BAND_SW10) { //MW
335             printstr("SW");
336             _PUTCHAR('1' + amband - AKC6955_BAND_SW1);
337             printstr("  ");
338         } else if(amband < AKC6955_BAND_AMUSER) { //MW
339             printstr("SW1");
340             _PUTCHAR('0' + amband - AKC6955_BAND_SW10);
341             _PUTCHAR(' ');
342         } else if(amband == AKC6955_BAND_MW4){
343             printstr("MW4  ");
344         } else {
345             printstr("AMUSR");
346         }
347      }
348 //     _LOCATE(15-5 ,1);
349      _LOCATE(15-4-6, 1);
350      if(fm != 0){
351          int freq_lo = fmfreq % 100;
352          int freq_hi = fmfreq / 100;
353          print_numeric_nosupress(freq_hi, 3);
354          _PUTCHAR('.');
355          print_numeric_nosupress(freq_lo, 2);
356      } else {
357          _PUTCHAR(' ');
358          print_numeric_nosupress(amfreq, 5);
359      }
360      // Signal
361      _LOCATE(15-4, 1);
362      if(fm != 0){
363          printstr("MHz");
364      } else {
365          printstr("KHz");
366      }
367     _HOME();
368 }
369
370
371 void setfreq_updown(unsigned char ctlword)
372 {
373     switch(ctlword){
374         case charcode_8: // Change band
375             if(fm == 0){
376                 amband++;
377                 if(amband > 18) amband = 0;
378 //                amfreq = akc6955_setfreq(amfreq)
379 //                akc6955_set_amband(amband);
380                 _AKC6955_WAIT_62_5MS(); // 62.5ms
381 //                amband = akc6955_get_amband();
382 //                amfreq = akc6955_get_freq();
383             } else {
384                 fmband++;
385                 if(fmband > 7) fmband = 0;
386 //                amfreq = akc6955_setfreq(amfreq)
387 //                akc6955_set_fmband(fmband);
388                 _AKC6955_WAIT_62_5MS(); // 62.5ms
389 //                fmband = akc6955_get_fmband();
390 //                fmfreq = akc6955_get_freq();
391             }
392             break;
393         case charcode_2: // Change band
394             if(fm == 0){
395                 amband--;
396                 if(amband == 0) amband = 18;
397                 if(amband >= 18) amband = 18;
398 //                amfreq = akc6955_setfreq(amfreq)
399 //                akc6955_set_amband(amband);
400                 _AKC6955_WAIT_62_5MS(); // 62.5ms
401 //                amband = akc6955_get_amband();
402 //                amfreq = akc6955_get_freq();
403             } else {
404                 fmband--;
405                 if(fmband == 0) fmband = 7;
406                 if(fmband >= 7) fmband = 7;
407 //                amfreq = akc6955_setfreq(amfreq)
408 //                akc6955_set_fmband(fmband);
409                 _AKC6955_WAIT_62_5MS(); // 62.5ms
410 //                fmband = akc6955_get_fmband();
411 //                fmfreq = akc6955_get_freq();
412             }
413             break;
414         case charcode_4: // Down Freq;
415             if(fm != 0){
416                 fmfreq -= 10;
417   //              fmfreq = akc6955_down_freq(10); // DOWN 100KHz
418             } else {
419                 amfreq -= 10;
420   //              amfreq = akc6955_down_freq(10); // DOWN 10KHz
421             }
422             break;
423         case charcode_6: // Down Freq;
424             if(fm != 0){
425                 fmfreq += 10;
426     //            fmfreq = akc6955_up_freq(10); // UP 100KHz
427             } else {
428                 amfreq += 10;
429     //            amfreq = akc6955_up_freq(10); // UP 10KHz
430             }
431             break;
432         case charcode_9: // Down Fast;
433             if(fm != 0){
434                 fmfreq += 50;
435       //          fmfreq = akc6955_down_freq(50); // DOWN 500KHz
436             } else {
437                 amfreq += 50;
438       //          amfreq = akc6955_down_freq(50); // DOWN 50KHz
439             }
440             break;
441         case charcode_7: // Down Fast;
442             if(fm != 0){
443                 fmfreq -= 50;
444         //        fmfreq = akc6955_up_freq(50); // UP 100KHz
445             } else {
446                 amfreq -= 50;
447         //        amfreq = akc6955_up_freq(50); // UP 10KHz
448             }
449             break;
450         case charcode_1: // Down Slow;
451             if(fm != 0){
452                 fmfreq -= 3;
453         //        fmfreq = akc6955_down_freq(5); // DOWN 50KHz
454             } else {
455                 amfreq -= 3;
456           //      amfreq = akc6955_down_freq(5); // DOWN 50KHz
457             }
458             break;
459         case charcode_3: // Down Slow;
460             if(fm != 0){
461                 fmfreq += 3;
462         //        fmfreq = akc6955_up_freq(5); // UP 50KHz
463             } else {
464                 amfreq += 3;
465         //        amfreq = akc6955_up_freq(5); // UP 5KHz
466             }
467             break;
468         case charcode_0: // Step
469             if(fm == 0){
470                 if(am_mode3k == 0) {
471                     am_mode3k = 0xff;
472                 } else {
473                     am_mode3k = 0;
474                 }
475           //      amfreq = akc6955_mode3k(am_mode3k);
476             }
477             break;
478         case charcode_a: // Toggle FM
479             toggle_amfm();
480             break;
481         case charcode_d:
482             //input_userband();
483             break;
484         case charcode_c:
485             //set_userband();
486             break;
487         case charcode_b:
488             //set_volume();
489             break;
490         case charcode_e: // Backlight ON/OFF
491             if(backlight_counter > 0) {
492                backlight_counter = 0;
493             } else {
494                backlight_counter = backlight_long;
495             }
496             break;
497         case charcode_5:
498             main_menu();
499             break;
500         case charcode_f:
501             updown_help();
502             _CLS();
503             _LOCATE(0,0);
504             break;
505         default:
506             break;
507     }
508 }
509 /*
510  * 
511  */
512 static void setdefault(void)
513 {
514     char i;
515     amfreq = 954;
516     fmfreq = 8000; // 10KHz order.
517     amband = AKC6955_BAND_MW2;
518     fmband = AKC6955_BAND_FM2;
519     am_mode3k = 0xff;
520     fm = 0;
521     recv_signal = 0;
522     am_userbandnum = 0;
523     fm_userbandnum = 0;
524     for(i = 0; i < 4; i++){
525         am_usrbands[i].start = 0x19;
526         am_usrbands[i].stop  = 0x32;
527     }
528     for(i = 0; i < 4; i++){
529         fm_usrbands[i].start = 0x19;
530         fm_usrbands[i].stop  = 0x32;
531     }
532
533
534 }
535
536 int main(void)
537 {
538     unsigned char c;
539     unsigned int sum = 0;
540     unsigned char p;
541
542 #ifdef _LCD_DEBUG
543     unsigned char power_flag;
544 #endif
545 //    OSCCON =  (_IDLEN & 0b11111100) | 0b00111000;
546     idle_init();
547     keyin_init();
548     keyin_ioinit();
549
550     //i2c1_init();
551
552     _AKC6955_WAIT_125_0MS(); // Wait 125ms
553 #ifdef _LCD_DEBUG
554     power_flag = 0xff;
555 #endif
556     backlight_long = 256;
557     backlight_counter = backlight_long;
558     backlight_level = 255;
559     ui_idlecount = 65535 - 7182/4 + 1; // 0.25Sec
560
561     acm1602_init(0xa0, 1); //Init LCD
562     _AKC6955_WAIT_125_0MS(); // Wait 125ms
563     _LOCATE(0,0);  // It's BAD-KNOWHOW, but needs AKIZUKI'S LCD :(
564     _PUTCHAR(' '); //
565     _LOCATE(0,1);
566     printstr("Hello;-)");
567     lcd_setbacklight(0xff, 100);
568 //   PORTD |= _LCDPORT_CONT_RS;
569 #if 0
570     i = 10001;
571     do {
572         ClrWdt();
573         set_fmlamp(i & 1);
574         set_amlamp(i & 1);
575         set_powerlamp(i & 1);
576         i = i + 1;
577 //        idle(65536 - 7182/10 + 1);
578         c = pollkeys(pollkeybuf, 60, 1); // Poll about 600ms
579         if(c != 0) {
580             unsigned char sp;
581 //            _LOCATE(0,0);
582             for(sp = 0; sp < c; sp++) _PUTCHAR(pollkeybuf[sp] + '0');
583         } else {
584             _CLS();
585             _LOCATE(0,0);
586             _PUTCHAR(' ');
587         }
588     }while(1);
589 #else
590     idle(0xf800);
591     switch(load_eeprom()) {
592         case 0x01: // No magic-word
593             idle(65535-7128*2+1);
594             _CLS();
595             setdefault();
596             _LOCATE(0,0);
597             printstr("EEPROM FORMATTING");
598             _LOCATE(0,1);
599             printstr("Press any key");
600             c = pollkey_single();
601             _CLS();
602             _LOCATE(0,0);
603             printstr("Formatting...");
604 //            format_eeprom(2,200);
605 //            writeword_eeprom(0, &sum, 0x1298);
606
607   //          _CLS();
608             _LOCATE(0,0);
609             printstr("Save defaults");
610             setdefault();
611 //            save_eeprom();
612             break;
613         case 0x00: // Checksum error
614             idle(65535-7128*2+1);
615             _CLS();
616             _LOCATE(0,0);
617             printstr("X-) Sum Error");
618             _LOCATE(0,1);
619             printstr("Press any key to format");
620             c = pollkey_single();
621             _CLS();
622             _LOCATE(0,0);
623             printstr("Formatting...");
624             format_eeprom(2,250);
625             writeword_eeprom(0, &sum, 0x1298);
626             _CLS();
627             _LOCATE(0,0);
628             printstr("Save defaults");
629             setdefault();
630             save_eeprom();
631             break;
632         case 0xff: // Success
633             break;
634         default: // Unknown error
635             setdefault();
636             break;
637     }
638     // Init AKC6955
639     /* Check EEPROM */
640     /* Push default parameters to AKC6955*/
641     scanflag = 0;
642 #if 0
643     akc6955_chg_fm(fm); // Set to AM
644     akc6955_set_amband(amband);
645     akc6955_set_freq(amfreq); // Dummy, TBS (954KHz)
646     akc6955_set_power(0xff); // Power ON
647 #endif
648 #if 0
649     idle(0xf000);
650 #else
651     idle(0xff00);
652 #endif
653     _CLS();
654     _LOCATE(0,0);
655     _PUTCHAR(' ');
656     //update_status();
657 //    update_display();
658     ClrWdt();
659     idle(ui_idlecount);
660     _LOCATE(0,0);
661     printstr("OK");
662     do {
663         /* Main routine*/
664        c = pollkeys(pollkeybuf, 60, 1);
665        p = 0;
666        while(c > 0) {
667            setfreq_updown(pollkeybuf[p]);
668            c--;
669            p++;
670        }
671         // Check battery (include idle?)
672         // Read AKJC6955's status
673 //      update_status();
674         // Putstring to LCD.
675         _LOCATE(0,0);
676         update_display();
677         if(backlight_counter > 0) {
678             backlight_counter--;
679             lcd_setbacklight(0xff, backlight_level); // Turn ON
680         } else {
681             lcd_setbacklight(0x00, 0); // Turn OFF
682         }
683 //        idle(ui_idlecount);
684     } while(1);
685 #endif
686 }
687