OSDN Git Service

[SCHEMATIC] Modify SW/MW/LW Preamp, insert galbanic-isolator replace of common-mode...
[openi2cradio/OpenI2CRadio.git] / term_shell.c
1 /*
2  * OpenI2CRADIO
3  * Shell Handler
4  * Copyright (C) 2013-11-07 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 #if defined(__SDCC)
29 #include <sdcc-lib.h>
30 #include <pic18fregs.h> /* ONLY FOR PIC18x */
31 #include <delay.h>
32 #else
33 #include <xc.h>
34 #endif
35 #include <signal.h>
36
37 #include "iodef.h"
38 #include "idle.h"
39 #include "ioports.h"
40 #include "euart.h"
41 #include "menu.h"
42 #include "power.h"
43 #include "shell_strutl.h"
44 #include "uart_termio.h"
45 #include "term_shell.h"
46 #include "eeprom_util.h"
47
48
49 unsigned char cmd_shellstr[130];
50 static char shell_strbuf[130];
51 static char xarg1[66];
52 static char xarg2[66];
53 static char xarg3[66];
54 static unsigned char tmparea[256];
55
56
57 static void shell_printnum(unsigned int v)
58 {
59     char s[32];
60     s[0] = '\0';
61     term_printnum(s, v);
62     uart_term_putstr(s);
63 }
64
65 /*
66  * Set Frequency: Arg1 = Freq.
67  */
68 static void term_freq(char *p)
69 {
70     unsigned int freq;
71     long l;
72
73     l = term_getuint(p);
74     uart_term_putstr("\nSet Freq:");
75     if((l < 100) || (l > 30000)) {
76         uart_term_putstr("\nE:Illegal freq range.\n");
77         return;
78     }
79     freq = (unsigned int)l;
80     if(setup.fm == 0){
81         shell_printnum(setup.amfreq);
82         // AM
83         setup.amfreq = freq;
84     } else {
85         shell_printnum(setup.fmfreq);
86         // FM
87         setup.fmfreq = freq;
88     }
89     uart_term_putstr("->");
90     shell_printnum(freq);
91
92     akc6955_set_freq(freq);
93     uart_term_putstr("\ndone.\n");
94 }
95
96 /*
97  * Print status
98  * Arg = none.
99  */
100 static void term_printstatus(char *p)
101 {
102     update_status();
103     uart_term_putstr("\nStatus:\n");
104     if(setup.fm == 0){
105         uart_term_putstr("AM \nBAND = ");
106         shell_printnum(setup.amband);
107         uart_term_putstr("\nFREQ = ");
108         shell_printnum(setup.amfreq);
109         uart_term_putstr("KHz");
110         uart_term_putstr("\nDIFF = ");
111         shell_printnum(diffstat);
112     } else {
113         uart_term_putstr("FM \nBAND = ");
114         shell_printnum(setup.fmband);
115         uart_term_putstr("\nFREQ = ");
116         shell_printnum(setup.fmfreq / 100);
117         uart_term_putstr(".");
118         shell_printnum(setup.fmfreq % 100);
119         uart_term_putstr("MHz");
120         uart_term_putstr("\nDIFF = ");
121         shell_printnum(diffstat);
122         uart_term_putstr("\nSTEREO = ");
123         if(stereoflag == 0) {
124             uart_term_putstr("NO");
125         } else {
126             uart_term_putstr("YES");
127         }
128     }
129     uart_term_putstr("\nSIGNAL-LEVEL = ");
130     shell_printnum(recv_signal);
131     uart_term_putstr("dB");
132    
133     uart_term_putstr("\nCNR-LEVEL = ");
134     shell_printnum(cnrlevel);
135     uart_term_putstr("dB");
136    
137     uart_term_putstr("\nBATT = ");
138     shell_printnum(battlevel / 100);
139     uart_term_putstr(".");
140     shell_printnum(battlevel % 100);
141     uart_term_putstr("V\n");
142    
143     uart_term_putstr("\n");
144 }
145
146 static void term_fm(char *p)
147 {
148     unsigned int freq;
149     setup.fm = 0xff;
150     setup.amfreq_bank[setup.amband] = setup.amfreq;
151     freq = setup.fmfreq_bank[setup.fmband];
152     akc6955_chg_fm(setup.fm, freq);
153 }
154
155 static void term_am(char *p)
156 {
157     unsigned int freq;
158     setup.fm = 0x00;
159     setup.fmfreq_bank[setup.fmband] = setup.fmfreq;
160     freq = setup.amfreq_bank[setup.amband];
161     akc6955_chg_fm(setup.fm, freq);
162 }
163
164
165 /*
166  * Poweroff.
167  * Arg1: 'N'/'n' : not save.
168  */
169 static void term_poweroff(char *p)
170 {
171     unsigned char s[16];
172     unsigned char slen;
173     unsigned char savef = 0xff;
174     xarg1[0] = '\0';
175     slen = shell_gettok(xarg1, p);
176     if(shell_strlen(xarg1) != 0) {
177         if((xarg1[0] == 'N') || (xarg1[0] == 'n')) savef = 0;
178     }
179     uart_term_putstr("\n*** Power OFF ***\nOK? (Yes = Y)");
180     uart_term_getstr(s, 15, 0xff);
181     if(shell_strlen(s) >= 3) return;
182     if(s[0] == 'Y') shutdown(savef);
183 }
184
185
186 static void term_poweron(char *p)
187 {
188 }
189
190
191 static void term_band(char *p)
192 {
193    unsigned char slen;
194    unsigned char n;
195    unsigned char band;
196    slen = shell_gettok(xarg1, p);
197 }
198
199
200 static unsigned char put_hexline(unsigned char *dat, unsigned long addr, unsigned char len)
201 {
202     unsigned char l;
203     l = str_bin2hex((unsigned char *)shell_strbuf, dat, addr, len);
204     uart_term_putstr(shell_strbuf);
205     return l;
206 }
207
208 static void put_hexheader(char *fname)
209 {
210     uart_term_putstr("Start of save value.\n--- BEGIN ---\n");
211     str_put_shexheader(shell_strbuf, fname);
212     uart_term_putstr(shell_strbuf);
213 }
214
215
216 static void put_hexfooter(void)
217 {
218     str_put_shexfooter(shell_strbuf);
219     uart_term_putstr(shell_strbuf);
220     uart_term_putstr("\n--- END---\n");
221 }
222
223
224
225 static void save_hex_page(unsigned char *p, unsigned int len, unsigned long baseaddr)
226 {
227     unsigned int pp;
228     unsigned int l = len;
229         for(pp = 0; pp < len; pp += 16){
230             if(l > 16) {
231                 put_hexline(&p[pp], pp + baseaddr, 16);
232                 l -= 16;
233             } else {
234                 put_hexline(&p[pp], pp + baseaddr, l);
235                 break;
236             }
237            idle_time_ms(100); // Line wait.
238         }
239 }
240
241
242 void shell_memcpy(unsigned char *to, unsigned char *from, unsigned char len)
243 {
244     unsigned char l;
245     for(l = 0; l < len; l++) to[l] = from[l];
246 }
247
248
249 static char wait_for_sheader(unsigned char *file, unsigned char retry)
250 {
251     unsigned char _try = 0;
252     unsigned char _err = 0;
253     int stat;
254     file[0] = '\0';
255    
256     do {
257         shell_strbuf[0] = '\0';
258         uart_term_getstr(shell_strbuf, 100, 0); // With Echo, timeout=10Sec.
259         stat = search_head_s(shell_strbuf);
260         if(stat < 0) {
261            _err++;
262            if(_err > 100) return -1; // Error 
263            continue;
264         }
265         _err = 0;
266         stat = str_shexheader(&shell_strbuf[stat], file);
267         if(stat == TERM_OK) break;
268         _try++;
269     } while(_try <= retry);
270     return stat;
271 }
272
273 static unsigned long load_hex_page(unsigned char *p, unsigned long *addr, unsigned int len)
274 {
275     int stat;
276     unsigned char l;
277     unsigned long a;
278     unsigned char __err = 0;
279     unsigned long bytes = 0;
280     int pos;
281     unsigned char sbuf[20];
282    
283     while(len > 0){
284 _l0:
285
286         shell_strbuf[0] = '\0';
287         uart_term_getstr(shell_strbuf, 1000, 0); // Without Echo, timeout=100Sec.
288
289         stat = search_head_s(shell_strbuf);
290         if(stat < 0) {
291            __err++;
292            if(__err > 100) {
293               return 0xffffffff; // Error
294            }
295            ClrWdt();
296            idle_time_ms(10);
297            goto _l0;
298         }
299         __err = 0;
300         pos = stat;
301         stat = str_shex2bin(&shell_strbuf[stat], p, &a, &l);
302         if(stat == TERM_SRECEND) {
303            return bytes; // Return head
304         }
305        
306         if(stat != TERM_OK) {
307            return 0xffffffff; // Some error
308         }
309         
310         bytes += l;
311         *addr = a;
312         if(l >= len) break; // End addr
313         p += l;
314         len -= l;
315     }
316     // Check return header
317     shell_strbuf[0] = '\0';
318     uart_term_getstr(shell_strbuf, 1000, 0); // Without Echo, timeout=100Sec.
319     stat = search_head_s(shell_strbuf);
320     if(stat < 0) return 0xffffffff;
321     stat = str_shex2bin(&shell_strbuf[stat], p, &a, &l);
322     if(stat != TERM_SRECEND) return 0xffffffff;
323     return bytes;
324 }
325 /*
326  * Load from S record.
327  */
328 static void load_from_term(unsigned char *p)
329 {
330     unsigned char slen = shell_gettok(xarg1, p);
331     unsigned long addr = 0;
332     unsigned char *pv;
333     unsigned int len;
334     unsigned char fbuf[128];
335     unsigned long l;
336     int stat;
337
338     if(shell_strcmp(xarg1, "INT") > 0) { // Internal EEPROM
339         uart_term_putstr("\nPls. start internal eeprom data...\n");
340
341         stat = wait_for_sheader(fbuf, 10);
342
343         if(stat != TERM_OK) goto _loaderr;
344         if(shell_strcmp(fbuf, "INT_EEPROM") < 0) goto _fileerr;
345         len = sizeof(__radioset_t);
346         pv = tmparea;
347 //        pv = &setup;
348         l = load_hex_page(pv, &addr, len);
349         if(l == 0xffffffff) goto _loaderr;
350         if(addr >= 255) goto _loaderr; // Too large
351        
352         shell_memcpy((unsigned char *)(&setup) , &tmparea, len);
353         setup_akc6955(); // DO!
354     } else if(shell_strcmp(xarg1, "FTBL") > 0) { // External EEPROM, Freq TBL
355     } else if(shell_strcmp(xarg1, "BAND") > 0) { // band
356     }
357 _OK:
358
359     uart_term_putstr("\nOK.\n");
360     return;
361
362 _loaderr:
363     uart_term_putstr("\nERR: LOAD Error\n");
364     return;
365 _addrerr:
366     uart_term_putstr("\nERR: Address Error\n");
367     return;
368 _fileerr:
369     uart_term_putstr("\nERR: Not correct filename\n");
370     return;
371 }
372
373 /*
374  * Save ROM as S record.
375  */
376 static void save_to_term(unsigned char *p)
377 {
378     unsigned char slen;
379     unsigned int len;
380     unsigned int pp;
381     int addr;
382     unsigned char *pv;
383     unsigned long base;
384
385     slen = shell_gettok(xarg1, p);
386     addr = 0;
387
388     if(shell_strcmp(xarg1, "INT") > 0) { // Internal EEPROM
389         put_hexheader("INT_EEPROM");
390         len = sizeof(__radioset_t);
391         pv = &setup;
392         save_hex_page(pv, len,  0);
393         put_hexfooter();
394     } else if(shell_strcmp(xarg1, "FTBL") > 0) { // External EEPROM, Freq TBL
395         put_hexheader("EXT_FREQTBL");
396         base = 0x100000;
397         for(pp = 0; pp < USER_MEMORY_BANKS; pp++) {
398             if(load_frequencies(pp, 0xff) != 0) break; // Error
399             save_hex_page((unsigned char *)(&freqset_temp), sizeof(__freqset_t), base + (pp << 9)) ;
400         }
401         put_hexfooter();
402     } else if(shell_strcmp(xarg1, "BAND") > 0) { // band
403         put_hexheader("EXT_BANDTBL");
404         put_hexfooter();
405     }
406 }
407
408 /*
409  * Open the Shell: Return cmdcode.
410  */
411 const char *cmdstr[SHELL_TOPCMDS] = {
412     "HELP",
413     "FREQ",
414     "STAT",
415     "LOAD",
416     "SAVE",
417     "FM",
418     "AM",
419     "POFF",
420     "PON",
421     "DUMP",
422     "LOG",
423     "SCAN",
424     "BAND",
425     "SET",
426     "PRINT",
427     "EXIT"
428 };
429
430
431 static const char shell_helpstr_help[] = "HELP [about-command]\n -- Online help.\n";
432 static const char shell_helpstr_freq[] = "FREQ frequency\n -- Set frequency.\n";
433 static const char shell_helpstr_stat[] = "STAT\n -- Print status.\n";
434 static const char shell_helpstr_load[] = "LOAD section [S]\n -- Load settings from terminal.\n Arg2: if 'S' then Save to internal EEPROM.\n";
435 static const char shell_helpstr_save[] = "SAVE section\n -- Save settings to terminal.\n";
436 static const char shell_helpstr_fm[] = "FM\n -- Switch to FM.\n";
437 static const char shell_helpstr_am[] = "AM\n -- Switch to AM.\n";
438 static const char shell_helpstr_poff[] = "\nPOFF [savef]\n -- Power OFF.\n  savef: if 'N' then power-off without saving.\n";
439 static const char shell_helpstr_pon[] = "\nPON\n -- Power ON.\n";
440 static const char shell_helpstr_dump[] = "\nDUMP section [number]\n -- Dump section(s).\n";
441 static const char shell_helpstr_log[] = "\nLOG\n -- View Log.\n";
442 static const char shell_helpstr_scan[] = "\nSCAN [direction]\n -- DO Scan.\n    direction : UP / DOWN\n";
443 static const char shell_helpstr_band[] = "\nBAND [band-name]\n -- Set band\n";
444 static const char shell_helpstr_set[] = "\nSET entry [value]\n -- Set setting / viewing value.\n   value : Decimal.\n";
445 static const char shell_helpstr_print[] = "\nPRINT [entry]\n -- Print system value(s).\n";
446 static const char shell_helpstr_exit[] = "\nEXIT\n -- EXIT FROM SHELL.\n";
447
448
449 static const char *shell_helpstr_sections[2] = {
450    "\nsection :\n    INT : Internal EEPROM\n    FTBL : Freq table\n",
451    "\n   FREQ num : Save user freq #num.\n   BAND : Save user band table."
452 };
453
454
455 static void cmd_printhelp(char cmdnum)
456 {
457   const char *p;
458   unsigned char i;
459   unsigned char sectionf = 0;
460    
461    switch(cmdnum) {
462     case 0:
463       p = shell_helpstr_help;
464       break;
465     case 1:
466       p = shell_helpstr_freq;
467       break;
468     case 2:
469       p = shell_helpstr_stat;
470       break;
471     case 3:
472       p = shell_helpstr_load;
473       sectionf = 0xff;
474       break;
475     case 4:
476       p = shell_helpstr_save;
477       sectionf = 0xff;
478       break;
479     case 5:
480       p = shell_helpstr_fm;
481       break;
482     case 6:
483       p = shell_helpstr_am;
484       break;
485     case 7:
486       p = shell_helpstr_poff;
487       break;
488     case 8:
489       p = shell_helpstr_pon;
490       break;
491     case 9:
492       p = shell_helpstr_dump;
493       sectionf = 0xff;
494       break;
495     case 10:
496       p = shell_helpstr_log;
497       break;
498     case 11:
499       p = shell_helpstr_scan;
500       break;
501     case 12:
502       p = shell_helpstr_band;
503       break;
504     case 13:
505       p = shell_helpstr_set;
506       break;
507     case 14:
508       p = shell_helpstr_print;
509       break;
510     case 15:
511       p = shell_helpstr_exit;
512       break;
513     default:
514       return;
515    };
516    uart_term_putstr(p);
517    if(sectionf != 0) {
518        for(i = 0; i < 2; i++) {
519           uart_term_putstr(shell_helpstr_sections[i]);
520        }
521    }
522 }
523
524 static void cmd_help(char *p)
525 {
526     unsigned char i;
527     unsigned char slen;
528     int f;
529
530     slen = shell_gettok(xarg1, p);
531     if(slen > 1) {
532         for(i = 0; i < SHELL_TOPCMDS; i++){
533             f = shell_strcmp(xarg1, cmdstr[i]);
534             if(f > 0) {
535                 cmd_printhelp(i);
536                 return;
537             }
538         }
539     }
540    uart_term_putstr("\nAvailable commands:\n");
541    for(i = 0; i < SHELL_TOPCMDS; i++){
542        uart_term_putstr(cmdstr[i]);
543        uart_term_putstr("\n");
544     }
545     uart_term_putstr("See Details : HELP [cmd].\n");
546 }
547
548 char term_shell(unsigned int timeout)
549 {
550     unsigned int t;
551     unsigned char pp;
552     unsigned char c;
553     int i;
554     unsigned int ii;
555     char pool[127];
556
557     //cmd_shellstr[0] = '\0';
558     if(timeout != 0) {
559         t = timeout;
560         while((uart_getstat() & UART_WAKEUP) == 0) {
561             if(t == 0) return SHELL_CMD_NONE;
562             t--;
563             idle_time_ms(1);
564         }
565     } else {
566         if((uart_getstat() & UART_WAKEUP) == 0) return SHELL_CMD_NONE;
567     }
568
569     uart_term_putstr("\nOpen I2C Radio v2.0\n(C)2013- Kyuma Ohta\n");
570     uart_term_putstr("\n\nWelcome to shell mode (^^).\nPress help to show usage.\n");
571     do {
572         cmd_shellstr[0] = '\0';
573         uart_term_putstr("\n$>");
574         uart_term_getstr(cmd_shellstr, 100, 1); // With Echo, timeout=10Sec.
575         if(cmd_shellstr[0] == TERM_CHAR_TIMEOUT){
576            uart_term_putstr("\nTimeout.\n");
577            uart_init();
578            return SHELL_CMD_NONE; // TimeOut 
579         }
580
581    
582        
583         ClrWdt();
584         ii = shell_gettok(pool, cmd_shellstr);
585 //        if(ii >= 126) return SHELL_CMD_TOOLONG;
586         if(ii >= 126) continue; // Discard
587         for(t = 0; t < SHELL_TOPCMDS; t++){
588             i = shell_strcmp((char *)cmdstr[t], pool);
589             if(i > 0) break;
590         }
591
592         if(cmd_shellstr[ii] == ' ') {
593            //if(i <= 0) return SHELL_CMD_NOTFOUND;
594            ii = shell_gettok(pool, &cmd_shellstr[ii + 1]);
595         }
596         if(ii >= 126) t = 127; // Error
597         switch(t){
598             case 0:
599                 cmd_help(pool);
600                 break;
601             case 1: // Freq
602                 term_freq(pool);
603                 break;
604             case 2:
605                 term_printstatus(pool);
606                 break;
607             case 3:
608                 load_from_term(pool);
609                 break;
610             case 4:
611                 save_to_term(pool);
612                 break;
613             case 5:
614                 term_fm(pool);
615                 break;
616             case 6:
617                 term_am(pool);
618                 break;
619             case 7:
620                 term_poweroff(pool);
621                 break;
622             case 8:
623                 term_poweron(pool);
624                 break;
625             case 12: // BAND
626                 term_band(pool);
627                 break;
628             case 15: // Exit
629                 uart_term_putstr("\nBye... (^^)/~~\n");
630                 goto _l0;
631                 break;
632             default:
633                 uart_term_putstr("\n?? CMD Error\n");
634                 break;
635         }
636
637     } while(1);
638 _l0:
639     uart_init();
640     return SHELL_CMD_OK;
641 }