OSDN Git Service

[USART] Add RTS/CTS function (with FT232RL). XON/XOFF is not effectable.
[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 #define SHELL_CMD_NONE -1
57 #define SHELL_CMD_NOTFOUND -2
58 #define SHELL_CMD_ILLTOKEN -3
59 #define SHELL_CMD_TOOLONG -4
60 #define SHELL_CMD_OK 0
61
62 #define SHELL_TOPCMDS 16
63
64 static void shell_printnum(unsigned int v)
65 {
66     char s[32];
67     s[0] = '\0';
68     term_printnum(s, v);
69     uart_term_putstr(s);
70 }
71 /*
72  * Set Frequency: Arg1 = Freq.
73  */
74 static void term_freq(char *p)
75 {
76     unsigned int freq;
77     long l;
78
79     l = term_getuint(p);
80     uart_term_putstr("\nSet Freq:");
81     if((l < 0) || (l > 30000)) {
82         uart_term_putstr("\nE:Illegal freq range.\n");
83         return;
84     }
85     freq = (unsigned int)l;
86     if(setup.fm == 0){
87         shell_printnum(setup.amfreq);
88         // AM
89         setup.amfreq = freq;
90     } else {
91         shell_printnum(setup.fmfreq);
92         // FM
93         setup.fmfreq = freq;
94     }
95     uart_term_putstr("->");
96     shell_printnum(freq);
97
98     akc6955_set_freq(freq);
99     uart_term_putstr("\ndone.\n");
100 }
101
102 /*
103  * Print status
104  * Arg = none.
105  */
106 static void term_printstatus(char *p)
107 {
108     uart_term_putstr("\nStatus:\n");
109     if(setup.fm == 0){
110         uart_term_putstr("AM \nBand = ");
111         shell_printnum(setup.amband);
112         uart_term_putstr("\nFreq = ");
113         shell_printnum(setup.amfreq);
114         uart_term_putstr("\n");
115     } else {
116         uart_term_putstr("FM \nBand = ");
117         shell_printnum(setup.fmband);
118         uart_term_putstr("\nFreq = ");
119         shell_printnum(setup.fmfreq);
120         uart_term_putstr("\n");
121     }
122
123     uart_term_putstr("\n");
124 }
125
126
127 /*
128  * Poweroff.
129  * Arg1: 'N'/'n' : not save.
130  */
131 static void term_poweroff(char *p)
132 {
133     unsigned char s[16];
134     unsigned char slen;
135     unsigned char savef = 0xff;
136     xarg1[0] = '\0';
137     slen = shell_gettok(xarg1, p);
138     if(shell_strlen(xarg1) != 0) {
139         if((xarg1[0] == 'N') || (xarg1[0] == 'n')) savef = 0;
140     }
141     uart_term_putstr("\n*** Power OFF ***\nOK? (Yes = Y)");
142     uart_term_getstr(s, 15, 0xff);
143     if(shell_strlen(s) >= 3) return;
144     if(s[0] == 'Y') shutdown(savef);
145 }
146
147
148 static void term_poweron(char *p)
149 {
150 }
151
152 static unsigned char put_hexline(unsigned char *dat, unsigned long addr, unsigned char len)
153 {
154     unsigned char l;
155     l = str_bin2hex((unsigned char *)shell_strbuf, dat, addr, len);
156     uart_term_putstr(shell_strbuf);
157     return l;
158 }
159
160 static void put_hexheader(char *fname)
161 {
162     uart_term_putstr("Start of save value.\n--- BEGIN ---\n");
163     str_put_shexheader(shell_strbuf, fname);
164     uart_term_putstr(shell_strbuf);
165 }
166
167
168 static void put_hexfooter(void)
169 {
170     str_put_shexfooter(shell_strbuf);
171     uart_term_putstr(shell_strbuf);
172     uart_term_putstr("\n--- END---\n");
173 }
174
175
176
177 static void save_hex_page(unsigned char *p, unsigned int len, unsigned long baseaddr)
178 {
179     unsigned int pp;
180     unsigned int l = len;
181         for(pp = 0; pp < len; pp += 16){
182             if(l > 16) {
183                 put_hexline(&p[pp], pp + baseaddr, 16);
184                 l -= 16;
185             } else {
186                 put_hexline(&p[pp], pp + baseaddr, l);
187                 break;
188             }
189            idle_time_ms(100); // Line wait.
190         }
191 }
192
193
194 void shell_memcpy(unsigned char *to, unsigned char *from, unsigned char len)
195 {
196     unsigned char l;
197     for(l = 0; l < len; l++) to[l] = from[l];
198 }
199
200
201 static char wait_for_sheader(unsigned char *file, unsigned char retry)
202 {
203     unsigned char _try = 0;
204     unsigned char _err = 0;
205     int stat;
206     file[0] = '\0';
207    
208     do {
209         shell_strbuf[0] = '\0';
210         uart_term_getstr(shell_strbuf, 100, 0); // With Echo, timeout=10Sec.
211         stat = search_head_s(shell_strbuf);
212         if(stat < 0) {
213            _err++;
214            if(_err > 100) return -1; // Error 
215            continue;
216         }
217         _err = 0;
218         stat = str_shexheader(&shell_strbuf[stat], file);
219         if(stat == TERM_OK) break;
220         _try++;
221     } while(_try <= retry);
222     return stat;
223 }
224
225 static unsigned long load_hex_page(unsigned char *p, unsigned long *addr, unsigned int len)
226 {
227     int stat;
228     unsigned char l;
229     unsigned long a;
230     unsigned char __err = 0;
231     unsigned long bytes = 0;
232     int pos;
233     unsigned char sbuf[20];
234    
235     while(len > 0){
236 _l0:
237
238         shell_strbuf[0] = '\0';
239         uart_term_getstr(shell_strbuf, 1000, 0); // Without Echo, timeout=100Sec.
240
241         stat = search_head_s(shell_strbuf);
242         if(stat < 0) {
243            __err++;
244            if(__err > 100) {
245               return 0xffffffff; // Error
246            }
247            ClrWdt();
248            idle_time_ms(10);
249            goto _l0;
250         }
251         __err = 0;
252         pos = stat;
253         stat = str_shex2bin(&shell_strbuf[stat], p, &a, &l);
254         if(stat == TERM_SRECEND) {
255            return bytes; // Return head
256         }
257        
258         if(stat != TERM_OK) {
259            return 0xffffffff; // Some error
260         }
261         
262         bytes += l;
263         *addr = a;
264         if(l >= len) break; // End addr
265         p += l;
266         len -= l;
267     }
268     // Check return header
269     shell_strbuf[0] = '\0';
270     uart_term_getstr(shell_strbuf, 1000, 0); // Without Echo, timeout=100Sec.
271     stat = search_head_s(shell_strbuf);
272     if(stat < 0) return 0xffffffff;
273     stat = str_shex2bin(&shell_strbuf[stat], p, &a, &l);
274     if(stat != TERM_SRECEND) return 0xffffffff;
275     return bytes;
276 }
277 /*
278  * Load from S record.
279  */
280 static void load_from_term(unsigned char *p)
281 {
282     unsigned char slen = shell_gettok(xarg1, p);
283     unsigned long addr = 0;
284     unsigned char *pv;
285     unsigned int len;
286     unsigned char fbuf[128];
287     unsigned long l;
288     int stat;
289
290     if(shell_strcmp(xarg1, "INT") > 0) { // Internal EEPROM
291         uart_term_putstr("\nPls. start internal eeprom data...\n");
292
293         stat = wait_for_sheader(fbuf, 10);
294
295         if(stat != TERM_OK) goto _loaderr;
296         if(shell_strcmp(fbuf, "INT_EEPROM") < 0) goto _fileerr;
297         len = sizeof(__radioset_t);
298         pv = tmparea;
299 //        pv = &setup;
300         l = load_hex_page(pv, &addr, len);
301         if(l == 0xffffffff) goto _loaderr;
302         if(addr >= 255) goto _loaderr; // Too large
303        
304         shell_memcpy((unsigned char *)(&setup) , &tmparea, len);
305         setup_akc6955(); // DO!
306     } else if(shell_strcmp(xarg1, "FTBL") > 0) { // External EEPROM, Freq TBL
307     } else if(shell_strcmp(xarg1, "BAND") > 0) { // band
308     }
309 _OK:
310
311     uart_term_putstr("\nOK.\n");
312     return;
313
314 _loaderr:
315     uart_term_putstr("\nERR: LOAD Error\n");
316     return;
317 _addrerr:
318     uart_term_putstr("\nERR: Address Error\n");
319     return;
320 _fileerr:
321     uart_term_putstr("\nERR: Not correct filename\n");
322     return;
323 }
324
325 /*
326  * Save ROM as S record.
327  */
328 static void save_to_term(unsigned char *p)
329 {
330     unsigned char slen;
331     unsigned int len;
332     unsigned int pp;
333     int addr;
334     unsigned char *pv;
335     unsigned long base;
336
337     slen = shell_gettok(xarg1, p);
338     addr = 0;
339
340     if(shell_strcmp(xarg1, "INT") > 0) { // Internal EEPROM
341         put_hexheader("INT_EEPROM");
342         len = sizeof(__radioset_t);
343         pv = &setup;
344         save_hex_page(pv, len,  0);
345         put_hexfooter();
346     } else if(shell_strcmp(xarg1, "FTBL") > 0) { // External EEPROM, Freq TBL
347         put_hexheader("EXT_FREQTBL");
348         base = 0x100000;
349         for(pp = 0; pp < USER_MEMORY_BANKS; pp++) {
350             if(load_frequencies(pp, 0xff) != 0) break; // Error
351             save_hex_page((unsigned char *)(&freqset_temp), sizeof(__freqset_t), base + (pp << 9)) ;
352         }
353         put_hexfooter();
354     } else if(shell_strcmp(xarg1, "BAND") > 0) { // band
355         put_hexheader("EXT_BANDTBL");
356         put_hexfooter();
357     }
358 }
359
360 /*
361  * Open the Shell: Return cmdcode.
362  */
363 const char *cmdstr[SHELL_TOPCMDS] = {
364     "HELP",
365     "FREQ",
366     "STAT",
367     "LOAD",
368     "SAVE",
369     "FM",
370     "AM",
371     "POFF",
372     "PON",
373     "SEQ",
374     "LOG",
375     "SCAN",
376     "BAND",
377     "SET",
378     "PRINT",
379     "EXIT"
380 };
381
382 static void cmd_printhelp(char cmdnum)
383 {
384     uart_term_putstr("\nSynopsys:\n");
385     switch(cmdnum){
386         case 0:
387             uart_term_putstr("HELP [about-command]\n");
388             uart_term_putstr(" -- Online help.\n");
389             break;
390         case 1:
391             uart_term_putstr("FREQ frequency\n");
392             uart_term_putstr(" -- Set frequency.\n");
393             break;
394         case 2:
395             uart_term_putstr("\nSTAT\n");
396             uart_term_putstr(" -- Print status.\n");
397             break;
398         case 3:
399             uart_term_putstr("\nLOAD section [S]\n");
400             uart_term_putstr(" -- Load settings from terminal.\n");
401             uart_term_putstr("      Arg2: if 'S' then Save to internal EEPROM.\n");
402            break;
403         case 4:
404             uart_term_putstr("\nSAVE section\n");
405             uart_term_putstr(" -- Save settings  to terminal.\n");
406             uart_term_putstr("     section :\n");
407             uart_term_putstr("                  INT : Internal EEPROM\n");
408             uart_term_putstr("                  FTBL  : Freq table");
409             uart_term_putstr("                  FREQ num : Save user freq #num.");
410             uart_term_putstr("                  BAND        : Save user band table.");
411             break;
412         case 5:
413             uart_term_putstr("\nFM\n");
414             uart_term_putstr(" -- Change to FM\n");
415             break;
416         case 6:
417             uart_term_putstr("\nAM\n");
418             uart_term_putstr(" -- Change to AM\n");
419             break;
420         case 7:
421             uart_term_putstr("\nPOFF [savef]\n");
422             uart_term_putstr(" -- Power OFF\n");
423             uart_term_putstr("      savef: if 'N' then power-off without saving.\n");
424             break;
425         case 8:
426             uart_term_putstr("\nPON\n");
427             uart_term_putstr(" -- Power ON\n");
428             break;
429         case 9:
430             uart_term_putstr("\nSEQ\n");
431             break;
432         case 10:
433             uart_term_putstr("\nLOG\n");
434             uart_term_putstr(" -- View LOG(Reserved command)\n");
435             break;
436         case 11:
437             uart_term_putstr("\nSCAN [direction]\n");
438             uart_term_putstr(" -- DO Scan\n");
439             uart_term_putstr("    direction : UP / DOWN\n");
440             break;
441         case 12:
442             uart_term_putstr("\nBAND [band-name]\n");
443             uart_term_putstr(" -- Set band\n");
444             break;
445         case 13:
446             uart_term_putstr("\nSET offset value\n");
447             uart_term_putstr(" -- Set system value.\n");
448             break;
449         case 14:
450             uart_term_putstr("\nPRINT offset\n");
451             uart_term_putstr(" -- PRINT system value.\n");
452             break;
453         case 15:
454             uart_term_putstr("\nEXIT\n");
455             uart_term_putstr(" -- EXIT shell\n");
456             break;
457         default:
458             break;
459     }
460 }
461
462 static void cmd_help(char *p)
463 {
464     unsigned char i;
465     unsigned char slen;
466     int f;
467
468     slen = shell_gettok(xarg1, p);
469     if(slen != 0) {
470         for(i = 0; i < SHELL_TOPCMDS; i++){
471             f = shell_strcmp(xarg1, cmdstr[i]);
472             if(f > 0) {
473                 cmd_printhelp(i);
474                 return;
475             }
476         }
477     }
478    uart_term_putstr("\nAvailable commands:\n");
479    for(i = 0; i < SHELL_TOPCMDS; i++){
480        uart_term_putstr(cmdstr[i]);
481        uart_term_putstr("\n");
482     }
483     uart_term_putstr("See Details : HELP [cmd].\n");
484 }
485
486 char term_shell(unsigned int timeout)
487 {
488     unsigned int t;
489     unsigned char pp;
490     unsigned char c;
491     int i;
492     unsigned int ii;
493     char pool[127];
494
495     //cmd_shellstr[0] = '\0';
496     if(timeout != 0) {
497         t = timeout;
498         while((uart_getstat() & UART_WAKEUP) == 0) {
499             if(t == 0) return SHELL_CMD_NONE;
500             t--;
501             idle_time_ms(1);
502         }
503     } else {
504         if((uart_getstat() & UART_WAKEUP) == 0) return SHELL_CMD_NONE;
505     }
506
507     uart_term_putstr("\nOpen I2C Radio v2.0\n(C)2013- Kyuma Ohta\n");
508     uart_term_putstr("\n\nWelcome to shell mode (^^).\nPress help to show usage.\n");
509     do {
510         cmd_shellstr[0] = '\0';
511         uart_term_putstr("\n$>");
512         uart_term_getstr(cmd_shellstr, 100, 1); // With Echo, timeout=10Sec.
513         if(cmd_shellstr[0] == TERM_CHAR_TIMEOUT){
514            uart_term_putstr("\nTimeout.\n");
515            uart_init();
516            return SHELL_CMD_NONE; // TimeOut 
517         }
518
519    
520        
521         ClrWdt();
522         ii = shell_gettok(pool, cmd_shellstr);
523 //        if(ii >= 126) return SHELL_CMD_TOOLONG;
524         if(ii >= 126) continue; // Discard
525         for(t = 0; t < SHELL_TOPCMDS; t++){
526             i = shell_strcmp((char *)cmdstr[t], pool);
527             if(i > 0) break;
528         }
529
530         if(cmd_shellstr[ii] == ' ') {
531            //if(i <= 0) return SHELL_CMD_NOTFOUND;
532            ii = shell_gettok(pool, &cmd_shellstr[ii + 1]);
533         }
534         if(ii >= 126) t = 127; // Error
535         switch(t){
536             case 0:
537                 cmd_help(pool);
538                 break;
539             case 1: // Freq
540                 term_freq(pool);
541                 break;
542             case 2:
543                 term_printstatus(pool);
544                 break;
545             case 3:
546                 load_from_term(pool);
547                 break;
548             case 4:
549                 save_to_term(pool);
550                 break;
551             case 7:
552                 term_poweroff(pool);
553                 break;
554             case 8:
555                 term_poweron(pool);
556                 break;
557             case 15: // Exit
558                 uart_term_putstr("\nBye... (^^)/~~\n");
559                 goto _l0;
560                 break;
561             default:
562                 uart_term_putstr("\n?? CMD Error\n");
563                 break;
564         }
565
566     } while(1);
567 _l0:
568     uart_init();
569     return SHELL_CMD_OK;
570 }