4 * Copyright (C) 2013-11-07 K.Ohta <whatisthis.sowhat ai gmail.com>
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.
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,
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.
30 #include <pic18fregs.h> /* ONLY FOR PIC18x */
43 #include "shell_strutl.h"
44 #include "uart_termio.h"
45 #include "term_shell.h"
46 #include "eeprom_util.h"
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];
57 static void shell_printnum(unsigned int v)
66 * Set Frequency: Arg1 = Freq.
68 static void term_freq(char *p)
74 uart_term_putstr("\nSet Freq:");
75 if((l < 100) || (l > 30000)) {
76 uart_term_putstr("\nE:Illegal freq range.\n");
79 freq = (unsigned int)l;
81 shell_printnum(setup.amfreq);
85 shell_printnum(setup.fmfreq);
89 uart_term_putstr("->");
92 akc6955_set_freq(freq);
93 uart_term_putstr("\ndone.\n");
100 static void term_printstatus(char *p)
103 uart_term_putstr("\nStatus:\n");
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);
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");
126 uart_term_putstr("YES");
129 uart_term_putstr("\nSIGNAL-LEVEL = ");
130 shell_printnum(recv_signal);
131 uart_term_putstr("dB");
133 uart_term_putstr("\nCNR-LEVEL = ");
134 shell_printnum(cnrlevel);
135 uart_term_putstr("dB");
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");
143 uart_term_putstr("\n");
146 static void term_fm(char *p)
150 setup.amfreq_bank[setup.amband] = setup.amfreq;
151 freq = setup.fmfreq_bank[setup.fmband];
152 akc6955_chg_fm(setup.fm, freq);
155 static void term_am(char *p)
159 setup.fmfreq_bank[setup.fmband] = setup.fmfreq;
160 freq = setup.amfreq_bank[setup.amband];
161 akc6955_chg_fm(setup.fm, freq);
167 * Arg1: 'N'/'n' : not save.
169 static void term_poweroff(char *p)
173 unsigned char savef = 0xff;
175 slen = shell_gettok(xarg1, p);
176 if(shell_strlen(xarg1) != 0) {
177 if((xarg1[0] == 'N') || (xarg1[0] == 'n')) savef = 0;
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);
186 static void term_poweron(char *p)
191 static void term_band(char *p)
196 slen = shell_gettok(xarg1, p);
200 static unsigned char put_hexline(unsigned char *dat, unsigned long addr, unsigned char len)
203 l = str_bin2hex((unsigned char *)shell_strbuf, dat, addr, len);
204 uart_term_putstr(shell_strbuf);
208 static void put_hexheader(char *fname)
210 uart_term_putstr("Start of save value.\n--- BEGIN ---\n");
211 str_put_shexheader(shell_strbuf, fname);
212 uart_term_putstr(shell_strbuf);
216 static void put_hexfooter(void)
218 str_put_shexfooter(shell_strbuf);
219 uart_term_putstr(shell_strbuf);
220 uart_term_putstr("\n--- END---\n");
225 static void save_hex_page(unsigned char *p, unsigned int len, unsigned long baseaddr)
228 unsigned int l = len;
229 for(pp = 0; pp < len; pp += 16){
231 put_hexline(&p[pp], pp + baseaddr, 16);
234 put_hexline(&p[pp], pp + baseaddr, l);
237 idle_time_ms(100); // Line wait.
242 void shell_memcpy(unsigned char *to, unsigned char *from, unsigned char len)
245 for(l = 0; l < len; l++) to[l] = from[l];
249 static char wait_for_sheader(unsigned char *file, unsigned char retry)
251 unsigned char _try = 0;
252 unsigned char _err = 0;
257 shell_strbuf[0] = '\0';
258 uart_term_getstr(shell_strbuf, 100, 0); // With Echo, timeout=10Sec.
259 stat = search_head_s(shell_strbuf);
262 if(_err > 100) return -1; // Error
266 stat = str_shexheader(&shell_strbuf[stat], file);
267 if(stat == TERM_OK) break;
269 } while(_try <= retry);
273 static unsigned long load_hex_page(unsigned char *p, unsigned long *addr, unsigned int len)
278 unsigned char __err = 0;
279 unsigned long bytes = 0;
281 unsigned char sbuf[20];
286 shell_strbuf[0] = '\0';
287 uart_term_getstr(shell_strbuf, 1000, 0); // Without Echo, timeout=100Sec.
289 stat = search_head_s(shell_strbuf);
293 return 0xffffffff; // Error
301 stat = str_shex2bin(&shell_strbuf[stat], p, &a, &l);
302 if(stat == TERM_SRECEND) {
303 return bytes; // Return head
306 if(stat != TERM_OK) {
307 return 0xffffffff; // Some error
312 if(l >= len) break; // End addr
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;
326 * Load from S record.
328 static void load_from_term(unsigned char *p)
330 unsigned char slen = shell_gettok(xarg1, p);
331 unsigned long addr = 0;
334 unsigned char fbuf[128];
338 if(shell_strcmp(xarg1, "INT") > 0) { // Internal EEPROM
339 uart_term_putstr("\nPls. start internal eeprom data...\n");
341 stat = wait_for_sheader(fbuf, 10);
343 if(stat != TERM_OK) goto _loaderr;
344 if(shell_strcmp(fbuf, "INT_EEPROM") < 0) goto _fileerr;
345 len = sizeof(__radioset_t);
348 l = load_hex_page(pv, &addr, len);
349 if(l == 0xffffffff) goto _loaderr;
350 if(addr >= 255) goto _loaderr; // Too large
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
359 uart_term_putstr("\nOK.\n");
363 uart_term_putstr("\nERR: LOAD Error\n");
366 uart_term_putstr("\nERR: Address Error\n");
369 uart_term_putstr("\nERR: Not correct filename\n");
374 * Save ROM as S record.
376 static void save_to_term(unsigned char *p)
385 slen = shell_gettok(xarg1, p);
388 if(shell_strcmp(xarg1, "INT") > 0) { // Internal EEPROM
389 put_hexheader("INT_EEPROM");
390 len = sizeof(__radioset_t);
392 save_hex_page(pv, len, 0);
394 } else if(shell_strcmp(xarg1, "FTBL") > 0) { // External EEPROM, Freq TBL
395 put_hexheader("EXT_FREQTBL");
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)) ;
402 } else if(shell_strcmp(xarg1, "BAND") > 0) { // band
403 put_hexheader("EXT_BANDTBL");
409 * Open the Shell: Return cmdcode.
411 const char *cmdstr[SHELL_TOPCMDS] = {
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";
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."
455 static void cmd_printhelp(char cmdnum)
459 unsigned char sectionf = 0;
463 p = shell_helpstr_help;
466 p = shell_helpstr_freq;
469 p = shell_helpstr_stat;
472 p = shell_helpstr_load;
476 p = shell_helpstr_save;
480 p = shell_helpstr_fm;
483 p = shell_helpstr_am;
486 p = shell_helpstr_poff;
489 p = shell_helpstr_pon;
492 p = shell_helpstr_dump;
496 p = shell_helpstr_log;
499 p = shell_helpstr_scan;
502 p = shell_helpstr_band;
505 p = shell_helpstr_set;
508 p = shell_helpstr_print;
511 p = shell_helpstr_exit;
518 for(i = 0; i < 2; i++) {
519 uart_term_putstr(shell_helpstr_sections[i]);
524 static void cmd_help(char *p)
530 slen = shell_gettok(xarg1, p);
532 for(i = 0; i < SHELL_TOPCMDS; i++){
533 f = shell_strcmp(xarg1, cmdstr[i]);
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");
545 uart_term_putstr("See Details : HELP [cmd].\n");
548 char term_shell(unsigned int timeout)
557 //cmd_shellstr[0] = '\0';
560 while((uart_getstat() & UART_WAKEUP) == 0) {
561 if(t == 0) return SHELL_CMD_NONE;
566 if((uart_getstat() & UART_WAKEUP) == 0) return SHELL_CMD_NONE;
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");
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");
578 return SHELL_CMD_NONE; // TimeOut
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);
592 if(cmd_shellstr[ii] == ' ') {
593 //if(i <= 0) return SHELL_CMD_NOTFOUND;
594 ii = shell_gettok(pool, &cmd_shellstr[ii + 1]);
596 if(ii >= 126) t = 127; // Error
605 term_printstatus(pool);
608 load_from_term(pool);
629 uart_term_putstr("\nBye... (^^)/~~\n");
633 uart_term_putstr("\n?? CMD Error\n");