3 * Config & Main routine.
4 * Copyright (C) 2013-06-10 K.Ohta <whatisthis.sowhat ai gmail.com>
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.
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,
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.
34 #include <pic18fregs.h> /* ONLY FOR PIC18x */
42 #include "lcd_acm1602.h"
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
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)
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
75 //#define _LCD_DEBUG 1
77 SIGHANDLER(TMR0_handler)
88 // Clear interrupt flag
90 tmr0f &= ~(_TMR0IF | _TMR0IE);
97 * Interrupt wake up every 1ms.
99 SIGHANDLER(TMR3_Handler)
101 if(statecount >= 8) statecount = 0;
102 readkey_io(statecount);
104 if(statecount > 7) readkey_compare(); // Compare and push to fifo.
110 DEF_INTLOW(intlow_handler)
111 DEF_HANDLER(SIG_TMR0, TMR0_handler)
112 // DEF_HANDLER(SIG_TMR3, TMR3_Handler)
118 unsigned char amband;
119 unsigned char fmband;
121 unsigned char am_mode3k;
122 unsigned char am_userbandnum;
123 unsigned char fm_userbandnum;
125 unsigned char mode3k; // mode3k if am
130 #define USER_BAND_NUM 4
131 _userband_t am_usrbands[USER_BAND_NUM];
132 _userband_t fm_usrbands[USER_BAND_NUM];
134 unsigned char enter_mode;
135 unsigned char numeric_mode;
136 unsigned char menu_node;
138 unsigned char help_flag;
142 unsigned int ui_idlecount;
143 unsigned char scanflag;
146 int backlight_counter;
147 unsigned char backlight_level;
148 unsigned char pollkeybuf[33];
151 unsigned int writeword_eeprom(unsigned int p, unsigned int *sum, unsigned int word)
154 if(eeprom_writebyte(p, word >> 8) == 0) return p; // Error
155 *sum = calcsum_byte(*sum, (word >> 8));
157 if(eeprom_writebyte(p, word & 0xff) == 0) return p+1; // Error
158 *sum = calcsum_byte(*sum, word & 0xff);
162 unsigned int writebyte_eeprom(unsigned int p, unsigned int *sum, unsigned char b)
165 if(eeprom_writebyte(p, b) == 0) return p; // Error
166 *sum = calcsum_byte(*sum, b);
170 void save_eeprom(void)
173 unsigned int sum = 0x0000;
177 writeword_eeprom(p, &sum, 0x1298);
180 writeword_eeprom(p, &sum, amfreq);
183 writeword_eeprom(p, &sum, fmfreq);
186 writebyte_eeprom(p, &sum, amband);
188 writebyte_eeprom(p, &sum, fmband);
190 writebyte_eeprom(p, &sum, fm);
192 writebyte_eeprom(p, &sum, am_mode3k);
194 writebyte_eeprom(p, &sum, am_userbandnum);
196 writebyte_eeprom(p, &sum, fm_userbandnum);
199 for(i = 0 ; i < USER_BAND_NUM; i++){
200 writebyte_eeprom(p, &sum, am_usrbands[i].mode3k);
201 writebyte_eeprom(p + 1, &sum, am_usrbands[i].start);
202 writebyte_eeprom(p + 2, &sum, am_usrbands[i].stop);
203 writeword_eeprom(p + 3, &sum, am_usrbands[i].freq);
206 for(i = 0 ; i < USER_BAND_NUM; i++){
207 writebyte_eeprom(p, &sum, fm_usrbands[i].mode3k);
208 writebyte_eeprom(p + 1, &sum, fm_usrbands[i].start);
209 writebyte_eeprom(p + 2, &sum, fm_usrbands[i].stop);
210 writeword_eeprom(p + 3, &sum, fm_usrbands[i].freq);
214 eeprom_writebyte(p, sum >> 8);
215 eeprom_writebyte(p + 1, sum & 0xff);
219 unsigned int readword_eeprom(unsigned int p, unsigned int *sum)
226 h = eeprom_readbyte(p);
227 *sum = calcsum_byte(*sum, h);
229 l = eeprom_readbyte(p + 1);
230 *sum = calcsum_byte(*sum, l);
236 unsigned char readbyte_eeprom(unsigned int p, unsigned int *sum)
242 b = eeprom_readbyte(p);
243 *sum = calcsum_byte(*sum, b);
249 unsigned char load_eeprom(void)
252 unsigned int sum = 0x0000;
257 magic = readword_eeprom(p, &sum);
258 if(magic != 0x1298) return 0x01; // NO MAGICWORD
261 amfreq = readword_eeprom(p, &sum);
264 fmfreq = readword_eeprom(p, &sum);
267 amband = readbyte_eeprom(p, &sum);
269 fmband = readbyte_eeprom(p, &sum);
271 fm = readbyte_eeprom(p, &sum);
273 am_mode3k = readbyte_eeprom(p, &sum);
275 am_userbandnum = readbyte_eeprom(p, &sum);
277 fm_userbandnum = readbyte_eeprom(p, &sum);
280 for(i = 0 ; i < USER_BAND_NUM; i++){
281 am_usrbands[i].mode3k = readbyte_eeprom(p, &sum);
282 am_usrbands[i].start = readbyte_eeprom(p + 1, &sum);
283 am_usrbands[i].stop = readbyte_eeprom(p + 2, &sum);
284 am_usrbands[i].freq = readword_eeprom(p + 3, &sum);
287 for(i = 0 ; i < USER_BAND_NUM; i++){
288 fm_usrbands[i].mode3k = readbyte_eeprom(p, &sum);
289 fm_usrbands[i].start = readbyte_eeprom(p + 1, &sum);
290 fm_usrbands[i].stop = readbyte_eeprom(p + 2, &sum);
291 fm_usrbands[i].freq = readword_eeprom(p + 3, &sum);
295 magic = (eeprom_readbyte(p) << 8) + eeprom_readbyte(p+1);
298 if(sum != magic) return 0x00;
303 void toggle_amfm(void)
307 // akc6955_chg_fm(fm);
308 // akc6955_set_amband(amband);
309 // akc6955_set_freq(amfreq);
312 // akc6955_chg_fm(fm);
313 // akc6955_set_fmband(fmband);
314 // akc6955_set_freq(fmfreq);
318 static void update_status(void)
321 recv_signal = akc6955_read_level();
323 fmfreq = akc6955_get_freq();
325 amfreq = akc6955_get_freq();
332 void set_volume(void)
336 void update_display(void)
341 print_numeric_nosupress(recv_signal, 3);
345 if(fmband < AKC6955_BAND_TV1) {
347 _PUTCHAR('1' + (fmband & 7));
349 } else if(fmband < AKC6955_BAND_FMUSER){
351 _PUTCHAR('1' + fmband - AKC6955_BAND_TV1);
357 if(amband == AKC6955_BAND_LW) {
359 } else if(amband <AKC6955_BAND_SW1) { //MW
361 _PUTCHAR('1' + amband - AKC6955_BAND_MW1);
363 } else if(amband <AKC6955_BAND_SW10) { //MW
365 _PUTCHAR('1' + amband - AKC6955_BAND_SW1);
367 } else if(amband < AKC6955_BAND_AMUSER) { //MW
369 _PUTCHAR('0' + amband - AKC6955_BAND_SW10);
371 } else if(amband == AKC6955_BAND_MW4){
380 int freq_lo = fmfreq % 100;
381 int freq_hi = fmfreq / 100;
382 print_numeric_nosupress(freq_hi, 3);
384 print_numeric_nosupress(freq_lo, 2);
387 print_numeric_nosupress(amfreq, 5);
401 unsigned char input_flag;
408 printstr("Scan A=ABORT");
410 printstr("U=6, D=4");
412 input_flag = readkey_compare();
414 } while(input_flag == 0);
417 akc6955_do_scan(0xff);
418 } else if(c == charcode_4){
426 input_flag = readkey_compare();
428 } while(input_flag == 0);
432 akc6955_abort_scan();
434 } else if(c == charcode_4){
435 akc6955_abort_scan();
438 } else if(c == charcode_6){
439 akc6955_abort_scan();
440 akc6955_do_scan(0xff);
443 if(akc6955_chk_donescan() != 0) break;
453 void setfreq_direct(void)
460 printstr("Set Freq:FM");
462 val = read_numeric(val, 5, 7, 1);
464 akc6955_set_freq(val);
468 printstr("Set Freq:AM");
470 val = read_numeric(val, 5, 7, 1);
472 akc6955_set_freq(val);
479 void setband_direct(void)
485 printstr("Set Band:FM");
487 band = read_numeric(band, 2, 7, 1);
488 akc6955_set_fmband(band);
492 printstr("Set Band:AM");
493 band = amband & 0x1f;
494 band = read_numeric(band, 2, 7, 1);
495 akc6955_set_amband(band);
503 void call_userband(unsigned char num)
507 if(num >= USER_BAND_NUM) return;
509 freq = fm_usrbands[num].freq;
510 ch = ((freq - 3000) / 25) * 10;
511 akc6955_set_userband(fm_usrbands[num].start, fm_usrbands[num].stop, ch,
512 fm_usrbands[num].mode3k);
515 if(am_usrbands[num].mode3k != 0) p = 3;
516 freq = am_usrbands[num].freq;
518 akc6955_set_userband(am_usrbands[num].start, am_usrbands[num].stop, ch,
519 am_usrbands[num].mode3k);
522 fmband = AKC6955_BAND_AMUSER;
524 amband = AKC6955_BAND_AMUSER;
531 void set_userband(void)
533 unsigned int from,to;
536 unsigned char mode3k;
537 unsigned int input_flag;
542 printstr("User ch:");
544 input_flag = readkey_compare();
546 } while(input_flag == 0);
549 if(c > charcode_0) return;
550 if(c < charcode_1) return;
551 if(c == charcode_0) {
554 c = c - charcode_1 + 1;
556 if(c >= USER_BAND_NUM) return;
558 from = fm_usrbands[c].start * 80 + 3000; // 32*25/10
559 to = fm_usrbands[c].stop * 80 + 3000;
563 print_numeric_nosupress(c, 1);
565 from = read_numeric(from, 5, 7, 1);
569 print_numeric_nosupress(c, 1);
571 to = read_numeric(to, 5, 7, 1);
572 fm_usrbands[c].start = (from - 3000) / 80;
573 fm_usrbands[c].stop = (to - 3000) / 80;
574 fm_usrbands[c].freq = from * 80 + 3000;
577 mode3k = am_usrbands[c].mode3k;
579 if(mode3k == 0) p = 160; // 5*32
580 from = am_usrbands[c].start * p;
581 to = am_usrbands[c].stop * p;
585 print_numeric_nosupress(c, 1);
588 printstr("0=3k 1=5k");
590 input_flag = readkey_compare();
592 } while(input_flag == 0);
593 cc = pop_keyinfifo();
595 if(cc == charcode_0){
598 } else if(cc = charcode_1) {
605 print_numeric_nosupress(c, 1);
607 from = read_numeric(from, 5, 7, 1);
611 print_numeric_nosupress(c, 1);
613 to = read_numeric(to, 5, 7, 1);
614 am_usrbands[c].start = from / p;
615 am_usrbands[c].stop = to / p;
616 am_usrbands[c].mode3k = mode3k;
617 am_usrbands[c].freq = from * p;
623 void input_userband(void)
626 unsigned char input_flag;
630 printstr("User Band");
634 input_flag = readkey_compare();
636 } while(input_flag == 0);
639 if((c >= charcode_a) && (c <= charcode_f)){
642 if(c == charcode_0) {
651 c = c - charcode_1 + 1;
652 if(c < USER_BAND_NUM) {
671 unsigned int input_flag;
674 printstr("Menu:F=HELP");
676 printstr("A=CANCEL");
679 input_flag = readkey_compare();
681 } while(input_flag == 0);
684 if((c < charcode_1) || ( c > charcode_0)) {
690 } else if(c == charcode_a){
693 } else if(c == charcode_1){
697 akc6955_set_amband(amband);
698 akc6955_set_freq(amfreq);
700 } else if(c == charcode_2){
704 } else if(c == charcode_3){
708 } else if(c == charcode_4){
712 akc6955_set_fmband(fmband);
713 akc6955_set_freq(fmfreq);
715 } else if(c == charcode_5){
718 } else if(c == charcode_6){
721 } else if(c == charcode_7){
724 } else if(c == charcode_8){
727 } else if(c == charcode_9){
730 } else if(c == charcode_0){
733 } else if(c == charcode_b){
737 } else if(c == charcode_c){
741 } else if(c == charcode_d){
744 } else if(c == charcode_e){
752 void setfreq_updown(unsigned char ctlword)
755 case charcode_8: // Change band
758 if(amband > 18) amband = 0;
759 // amfreq = akc6955_setfreq(amfreq)
760 // akc6955_set_amband(amband);
761 _AKC6955_WAIT_62_5MS(); // 62.5ms
762 // amband = akc6955_get_amband();
763 // amfreq = akc6955_get_freq();
766 if(fmband > 7) fmband = 0;
767 // amfreq = akc6955_setfreq(amfreq)
768 // akc6955_set_fmband(fmband);
769 _AKC6955_WAIT_62_5MS(); // 62.5ms
770 // fmband = akc6955_get_fmband();
771 // fmfreq = akc6955_get_freq();
774 case charcode_2: // Change band
777 if(amband == 0) amband = 18;
778 if(amband >= 18) amband = 18;
779 // amfreq = akc6955_setfreq(amfreq)
780 // akc6955_set_amband(amband);
781 _AKC6955_WAIT_62_5MS(); // 62.5ms
782 // amband = akc6955_get_amband();
783 // amfreq = akc6955_get_freq();
786 if(fmband == 0) fmband = 7;
787 if(fmband >= 7) fmband = 7;
788 // amfreq = akc6955_setfreq(amfreq)
789 // akc6955_set_fmband(fmband);
790 _AKC6955_WAIT_62_5MS(); // 62.5ms
791 // fmband = akc6955_get_fmband();
792 // fmfreq = akc6955_get_freq();
795 case charcode_4: // Down Freq;
798 // fmfreq = akc6955_down_freq(10); // DOWN 100KHz
801 // amfreq = akc6955_down_freq(10); // DOWN 10KHz
804 case charcode_6: // Down Freq;
807 // fmfreq = akc6955_up_freq(10); // UP 100KHz
811 // amfreq = akc6955_up_freq(10); // UP 10KHz
814 case charcode_7: // Down Fast;
816 // fmfreq = akc6955_down_freq(50); // DOWN 500KHz
818 // amfreq = akc6955_down_freq(50); // DOWN 50KHz
821 case charcode_9: // Down Fast;
823 // fmfreq = akc6955_up_freq(50); // UP 100KHz
825 // amfreq = akc6955_up_freq(50); // UP 10KHz
828 case charcode_1: // Down Slow;
830 // fmfreq = akc6955_down_freq(5); // DOWN 50KHz
832 // amfreq = akc6955_down_freq(5); // DOWN 50KHz
835 case charcode_3: // Down Slow;
837 // fmfreq = akc6955_up_freq(5); // UP 50KHz
839 // amfreq = akc6955_up_freq(5); // UP 5KHz
842 case charcode_0: // Step
849 // amfreq = akc6955_mode3k(am_mode3k);
852 case charcode_a: // Toggle FM
864 case charcode_e: // Backlight ON/OFF
865 if(backlight_counter > 0) {
866 backlight_counter = 0;
868 backlight_counter = backlight_long;
881 static void setdefault(void)
885 fmfreq = 8000; // 10KHz order.
886 amband = AKC6955_BAND_MW2;
887 fmband = AKC6955_BAND_FM2;
893 for(i = 0; i < 4; i++){
894 am_usrbands[i].start = 0x19;
895 am_usrbands[i].stop = 0x32;
897 for(i = 0; i < 4; i++){
898 fm_usrbands[i].start = 0x19;
899 fm_usrbands[i].stop = 0x32;
908 unsigned int sum = 0;
912 unsigned char power_flag;
914 // OSCCON = (_IDLEN & 0b11111100) | 0b00111000;
921 _AKC6955_WAIT_125_0MS(); // Wait 125ms
925 backlight_long = 256;
926 backlight_counter = backlight_long;
927 backlight_level = 255;
928 ui_idlecount = 65535 - 7182/4 + 1; // 0.25Sec
930 acm1602_init(0xa0, 1); //Init LCD
931 _AKC6955_WAIT_125_0MS(); // Wait 125ms
932 _LOCATE(0,0); // It's BAD-KNOWHOW, but needs AKIZUKI'S LCD :(
935 printstr("Hello;-)");
936 lcd_setbacklight(0xff, 100);
937 // PORTD |= _LCDPORT_CONT_RS;
944 set_powerlamp(i & 1);
946 // idle(65536 - 7182/10 + 1);
947 c = pollkeys(pollkeybuf, 60, 1); // Poll about 600ms
951 for(sp = 0; sp < c; sp++) _PUTCHAR(pollkeybuf[sp] + '0');
960 switch(load_eeprom()) {
961 case 0x01: // No magic-word
962 idle(65535-7128*2+1);
966 printstr("EEPROM FORMATTING");
968 printstr("Press any key");
969 c = pollkey_single();
972 printstr("Formatting...");
973 // format_eeprom(2,200);
974 // writeword_eeprom(0, &sum, 0x1298);
978 printstr("Save defaults");
982 case 0x00: // Checksum error
983 idle(65535-7128*2+1);
986 printstr("X-) Sum Error");
988 printstr("Press any key to format");
989 c = pollkey_single();
992 printstr("Formatting...");
993 format_eeprom(2,250);
994 writeword_eeprom(0, &sum, 0x1298);
997 printstr("Save defaults");
1001 case 0xff: // Success
1003 default: // Unknown error
1009 /* Push default parameters to AKC6955*/
1012 akc6955_chg_fm(fm); // Set to AM
1013 akc6955_set_amband(amband);
1014 akc6955_set_freq(amfreq); // Dummy, TBS (954KHz)
1015 akc6955_set_power(0xff); // Power ON
1026 // update_display();
1033 c = pollkeys(pollkeybuf, 60, 1);
1036 setfreq_updown(pollkeybuf[p]);
1040 // Check battery (include idle?)
1041 // Read AKJC6955's status
1043 // Putstring to LCD.
1046 if(backlight_counter > 0) {
1047 backlight_counter--;
1048 lcd_setbacklight(0xff, backlight_level); // Turn ON
1050 lcd_setbacklight(0x00, 0); // Turn OFF
1052 // idle(ui_idlecount);