Bump NUM_CMDS to 10
[fw/altos] / ao_cmd.c
index 303f9bc5eaf7021c7552f5170d03a665031ff0bd..7f7865364da5a4a10949a1a5e2d964aeecca1512 100644 (file)
--- a/ao_cmd.c
+++ b/ao_cmd.c
@@ -3,8 +3,7 @@
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
+ * the Free Software Foundation; version 2 of the License.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
 
 #include "ao.h"
 
-#define LEX_ERROR      1
-#define SYNTAX_ERROR   2
-#define SUCCESS                0
-
-static __data uint16_t lex_i;
-static __data uint8_t  lex_c;
-static __data uint8_t  lex_status;
-static __data uint8_t  lex_echo;
+__xdata uint16_t ao_cmd_lex_i;
+__xdata uint8_t        ao_cmd_lex_c;
+__xdata enum ao_cmd_status ao_cmd_status;
+static __xdata uint8_t lex_echo;
 
 #define CMD_LEN        32
 
 static __xdata uint8_t cmd_line[CMD_LEN];
-static __data uint8_t  cmd_len;
-static __data uint8_t  cmd_i;
-
-void
-putchar(char c)
-{
-       if (c == '\n')
-               ao_usb_putchar('\r');
-       ao_usb_putchar((uint8_t) c);
-}
-
-void
-flush(void)
-{
-       ao_usb_flush();
-}
-
-char
-getchar(void)
-{
-       return (char) ao_usb_getchar();
-}
+static __xdata uint8_t cmd_len;
+static __xdata uint8_t cmd_i;
 
 static void
 put_string(char *s)
 {
-       uint8_t c;
+       __xdata uint8_t c;
        while (c = *s++)
                putchar(c);
 }
@@ -64,7 +39,7 @@ put_string(char *s)
 static void
 readline(void)
 {
-       static uint8_t c;
+       __xdata uint8_t c;
        if (lex_echo)
                put_string("> ");
        cmd_len = 0;
@@ -97,7 +72,7 @@ readline(void)
                
                if (c == '\n') {
                        if (lex_echo)
-                               put_string ("\n");
+                               putchar('\n');
                        break;
                }
 
@@ -115,12 +90,12 @@ readline(void)
        cmd_i = 0;
 }
 
-static void
-lex(void)
+void
+ao_cmd_lex(void)
 {
-       lex_c = '\n';
+       ao_cmd_lex_c = '\n';
        if (cmd_i < cmd_len)
-               lex_c = cmd_line[cmd_i++];
+               ao_cmd_lex_c = cmd_line[cmd_i++];
 }
 
 static void
@@ -133,7 +108,7 @@ putnibble(uint8_t v)
 }
 
 void
-put16(uint16_t v)
+ao_cmd_put16(uint16_t v)
 {
        int8_t i;
        for (i = 3; i >= 0; i--)
@@ -141,454 +116,195 @@ put16(uint16_t v)
 }
 
 void
-put8(uint8_t v)
+ao_cmd_put8(uint8_t v)
 {
        putnibble((v >> 4) & 0xf);
        putnibble(v & 0xf);
 }
 
-#define NUM_LEN 7
-
 void
-puti(int i)
+ao_cmd_white(void)
 {
-       static uint8_t __xdata  num_buffer[NUM_LEN];
-       uint8_t __xdata *num_ptr = num_buffer + NUM_LEN;
-       uint8_t neg = 0;
-       
-       *--num_ptr = '\0';
-       if (i < 0) {
-               i = -i;
-               neg = 1;
-       }
-       do {
-               *--num_ptr = '0' + i % 10;
-               i /= 10;
-       } while (i);
-       if (neg)
-               *--num_ptr = '-';
-       while (num_ptr != num_buffer)
-               *--num_ptr = ' ';
-       put_string(num_buffer);
-}
-
-
-static void
-white(void)
-{
-       while (lex_c == ' ' || lex_c == '\t')
-               lex();
+       while (ao_cmd_lex_c == ' ' || ao_cmd_lex_c == '\t')
+               ao_cmd_lex();
 }
 
-static void
-hex(void)
+void
+ao_cmd_hex(void)
 {
-       uint8_t r = LEX_ERROR;
+       __xdata uint8_t r = ao_cmd_lex_error;
        
-       lex_i = 0;
-       white();
+       ao_cmd_lex_i = 0;
+       ao_cmd_white();
        for(;;) {
-               if ('0' <= lex_c && lex_c <= '9')
-                       lex_i = (lex_i << 4) | (lex_c - '0');
-               else if ('a' <= lex_c && lex_c <= 'f')
-                       lex_i = (lex_i << 4) | (lex_c - 'a' + 10);
-               else if ('A' <= lex_c && lex_c <= 'F')
-                       lex_i = (lex_i << 4) | (lex_c - 'A' + 10);
+               if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
+                       ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - '0');
+               else if ('a' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'f')
+                       ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'a' + 10);
+               else if ('A' <= ao_cmd_lex_c && ao_cmd_lex_c <= 'F')
+                       ao_cmd_lex_i = (ao_cmd_lex_i << 4) | (ao_cmd_lex_c - 'A' + 10);
                else
                        break;
-               r = SUCCESS;
-               lex();
+               r = ao_cmd_success;
+               ao_cmd_lex();
        }
-       if (r != SUCCESS)
-               lex_status = r;
+       if (r != ao_cmd_success)
+               ao_cmd_status = r;
 }
 
 #if 0
 static void
 decimal(void)
 {
-       uint8_t r = LEX_ERROR;
+       __xdata uint8_t r = ao_cmd_lex_error;
        
-       lex_i = 0;
-       white();
+       ao_cmd_lex_i = 0;
+       ao_cmd_white();
        for(;;) {
-               if ('0' <= lex_c && lex_c <= '9')
-                       lex_i = (lex_i * 10 ) | (lex_c - '0');
+               if ('0' <= ao_cmd_lex_c && ao_cmd_lex_c <= '9')
+                       ao_cmd_lex_i = (ao_cmd_lex_i * 10 ) | (ao_cmd_lex_c - '0');
                else
                        break;
-               r = SUCCESS;
-               lex();
+               r = ao_cmd_success;
+               ao_cmd_lex();
        }
-       if (r != SUCCESS)
-               lex_status = r;
+       if (r != ao_cmd_success)
+               ao_cmd_status = r;
 }
 #endif
 
 static void
 eol(void)
 {
-       while (lex_c != '\n')
-               lex();
-}
-
-static void
-adc_dump(void)
-{
-       __xdata struct ao_adc   packet;
-       ao_adc_get(&packet);
-       put_string("tick: ");
-       puti(packet.tick);
-       put_string(" accel: ");
-       puti(packet.accel >> 4);
-       put_string(" pres: ");
-       puti(packet.pres >> 4);
-       put_string(" temp: ");
-       puti(packet.temp >> 4);
-       put_string(" batt: ");
-       puti(packet.v_batt >> 4);
-       put_string(" drogue: ");
-       puti(packet.sense_d >> 4);
-       put_string(" main: ");
-       puti(packet.sense_m >> 4);
-       put_string("\n");
+       while (ao_cmd_lex_c != '\n')
+               ao_cmd_lex();
 }
 
 static void
 dump(void)
 {
-       uint16_t c;
-       uint8_t __xdata *start, *end;
-
-       hex();
-       start = (uint8_t __xdata *) lex_i;
-       hex();
-       end = (uint8_t __xdata *) lex_i;
-       if (lex_status != SUCCESS)
+       __xdata uint16_t c;
+       __xdata uint8_t * __xdata start, * __xdata end;
+
+       ao_cmd_hex();
+       start = (uint8_t __xdata *) ao_cmd_lex_i;
+       ao_cmd_hex();
+       end = (uint8_t __xdata *) ao_cmd_lex_i;
+       if (ao_cmd_status != ao_cmd_success)
                return;
        c = 0;
        while (start <= end) {
                if ((c & 7) == 0) {
                        if (c)
-                               put_string("\n");
-                       put16((uint16_t) start);
+                               putchar('\n');
+                       ao_cmd_put16((uint16_t) start);
                }
                putchar(' ');
-               put8(*start);
+               ao_cmd_put8(*start);
                ++c;
                start++;
        }
-       put_string("\n");
-}
-
-static void
-ee_dump(void)
-{
-       uint8_t b;
-       uint16_t block;
-       uint8_t i;
-       
-       hex();
-       block = lex_i;
-       if (lex_status != SUCCESS)
-               return;
-       i = 0;
-       do {
-               if ((i & 7) == 0) {
-                       if (i)
-                               put_string("\n");
-                       put16((uint16_t) i);
-               }
-               putchar(' ');
-               ao_ee_read(((uint32_t) block << 8) | i, &b, 1);
-               put8(b);
-               ++i;
-       } while (i != 0);
-       put_string("\n");
-}
-
-static void
-ee_store(void)
-{
-       uint16_t block;
-       uint8_t i;
-       uint16_t len;
-       uint8_t b;
-       uint32_t addr;
-
-       hex();
-       block = lex_i;
-       hex();
-       i = lex_i;
-       addr = ((uint32_t) block << 8) | i;
-       hex();
-       len = lex_i;
-       if (lex_status != SUCCESS)
-               return;
-       while (len--) {
-               hex();
-               if (lex_status != SUCCESS)
-                       return;
-               b = lex_i;
-               ao_ee_write(addr, &b, 1);
-               addr++;
-       }
-       ao_ee_flush();  
+       putchar('\n');
 }
 
 static void
 echo(void)
 {
-       hex();
-       lex_echo = lex_i != 0;
+       ao_cmd_hex();
+       lex_echo = ao_cmd_lex_i != 0;
 }
 
-#if INCLUDE_REMOTE_DEBUG
-static void
-debug_enable(void)
-{
-       dbg_debug_mode();
-}
+static const uint8_t help_txt[] = "All numbers are in hex";
 
-static void
-debug_reset(void)
-{
-       dbg_reset();
-}
+#define NUM_CMDS       10
 
-static void
-debug_put(void)
-{
-       for (;;) {
-               white ();
-               if (lex_c == '\n')
-                       break;
-               hex();
-               if (lex_status != SUCCESS)
-                       break;
-               dbg_send_byte(lex_i);
-       }
-}
+static __code struct ao_cmds   *__xdata (ao_cmds[NUM_CMDS]);
+static __xdata uint8_t         ao_ncmds;
 
 static void
-debug_get(void)
-{
-       uint16_t count;
-       uint16_t i;
-       uint8_t byte;
-       hex();
-       if (lex_status != SUCCESS)
-               return;
-       count = lex_i;
-       if (count > 256) {
-               lex_status = SYNTAX_ERROR;
-               return;
-       }
-       for (i = 0; i < count; i++) {
-               if (i && (i & 7) == 0)
-                       put_string("\n");
-               byte = dbg_recv_byte();
-               put8(byte);
-               putchar(' ');
-       }
-       put_string("\n");
-}
-
-static uint8_t
-getnibble(void)
-{
-       uint8_t c;
-
-       c = getchar();
-       if ('0' <= c && c <= '9')
-               return c - '0';
-       if ('a' <= c && c <= 'f')
-               return c - ('a' - 10);
-       if ('A' <= c && c <= 'F')
-               return c - ('A' - 10);
-       lex_status = LEX_ERROR;
-       return 0;
-}
-
-static void
-debug_input(void)
-{
-       uint16_t count;
-       uint16_t addr;
-       uint8_t b;
-       uint8_t i;
-
-       hex();
-       count = lex_i;
-       hex();
-       addr = lex_i;
-       if (lex_status != SUCCESS)
-               return;
-       dbg_start_transfer(addr);
-       i = 0;
-       while (count--) {
-               if (!(i++ & 7))
-                       put_string("\n");
-               b = dbg_read_byte();
-               put8(b);
-       }
-       dbg_end_transfer();
-       put_string("\n");
-}
-
-static void
-debug_output(void)
+help(void)
 {
-       uint16_t count;
-       uint16_t addr;
-       uint8_t b;
-
-       hex();
-       count = lex_i;
-       hex();
-       addr = lex_i;
-       if (lex_status != SUCCESS)
-               return;
-       dbg_start_transfer(addr);
-       while (count--) {
-               b = getnibble() << 4;
-               b |= getnibble();
-               if (lex_status != SUCCESS)
-                       return;
-               dbg_write_byte(b);
+       __xdata uint8_t cmds;
+       __xdata uint8_t cmd;
+       __code struct ao_cmds * __xdata cs;
+       puts(help_txt);
+       for (cmds = 0; cmds < ao_ncmds; cmds++) {
+               cs = ao_cmds[cmds];
+               for (cmd = 0; cs[cmd].cmd != '\0'; cmd++)
+                       puts(cs[cmd].help);
        }
-       dbg_end_transfer();
 }
-#endif
 
 static void
-dump_log(void)
+report(void)
 {
-       uint8_t more;
-
-       for (more = ao_log_dump_first(); more; more = ao_log_dump_next()) {
-               putchar(ao_log_dump.type);
-               putchar(' ');
-               put16(ao_log_dump.tick);
-               putchar(' ');
-               put16(ao_log_dump.u.anon.d0);
-               putchar(' ');
-               put16(ao_log_dump.u.anon.d1);
-               putchar('\n');
+       switch(ao_cmd_status) {
+       case ao_cmd_lex_error:
+       case ao_cmd_syntax_error:
+               puts("Syntax error");
+               ao_cmd_status = 0;
+               break;
        }
 }
 
-static const uint8_t help_txt[] = 
-       "All numbers are in hex\n"
-       "?                                  Print this message\n"
-       "a                                  Display current ADC values\n"
-       "d <start> <end>                    Dump memory\n"
-       "e <block>                          Dump a block of EEPROM data\n"
-       "w <block> <start> <len> <data> ... Write data to EEPROM\n"
-       "l                                  Dump last flight log\n"
-       "E <0 off, 1 on>                    Set command echo mode\n"
-#if INCLUDE_REMOTE_DEBUG
-        "\n"
-        "Target debug commands:\n"
-       "D                                  Enable debug mode\n"
-       "R                                  Reset target\n"
-        "P <byte> ...                       Put data to debug port\n"
-       "G <count>                          Get data from debug port\n"
-       "O <count> <addr>                   Output <count> bytes to target at <addr>\n"
-       "I <count> <addr>                   Input <count> bytes to target at <addr>\n"
-#endif
-;
-
-static void
-help(void)
+void
+ao_cmd_register(__code struct ao_cmds *cmds)
 {
-       put_string(help_txt);
-}
-
-static void
-report(void)
-{
-       switch(lex_status) {
-       case LEX_ERROR:
-       case SYNTAX_ERROR:
-               put_string("Syntax error\n");
-               lex_status = 0;
-               break;
-       }
+       if (ao_ncmds >= NUM_CMDS)
+               ao_panic(AO_PANIC_CMD);
+       ao_cmds[ao_ncmds++] = cmds;
 }
 
 void
 ao_cmd(void *parameters)
 {
-       uint8_t c;
+       __xdata uint8_t c;
+       __xdata uint8_t cmd, cmds;
+       __code struct ao_cmds * __xdata cs;
+       void (*__xdata func)(void);
        (void) parameters;
 
-       ao_led_on(AO_LED_GREEN);
-       ao_beep_for(AO_BEEP_MID, AO_MS_TO_TICKS(30));
        lex_echo = 1;
        for (;;) {
                readline();
-               lex();
-               white();
-               c = lex_c;
-               lex();
-               switch (c) {
-               case '?':
-                       help();
-                       break;
-               case 'd':
-                       dump();
-                       break;
-               case 'a':
-                       adc_dump();
-                       break;
-               case 'e':
-                       ee_dump();
-                       break;
-               case 'w':
-                       ee_store();
-                       break;
-               case 'l':
-                       dump_log();
-                       break;
-               case 'E':
-                       echo();
-                       break;
-#if INCLUDE_REMOTE_DEBUG
-               case 'D':
-                       debug_enable();
-                       break;
-               case 'R':
-                       debug_reset();
-                       break;
-               case 'P':
-                       debug_put();
-                       break;
-               case 'G':
-                       debug_get();
-                       break;
-               case 'I':
-                       debug_input();
-                       break;
-               case 'O':
-                       debug_output();
-                       break;
-#endif
-               case '\r':
-               case '\n':
-                       break;
-               default:
-                       lex_status = SYNTAX_ERROR;
-                       break;
+               ao_cmd_lex();
+               ao_cmd_white();
+               c = ao_cmd_lex_c;
+               ao_cmd_lex();
+               if (c == '\r' || c == '\n')
+                       continue;
+               func = (void (*)(void)) NULL;
+               for (cmds = 0; cmds < ao_ncmds; cmds++) {
+                       cs = ao_cmds[cmds];
+                       for (cmd = 0; cs[cmd].cmd != '\0'; cmd++)
+                               if (cs[cmd].cmd == c) {
+                                       func = cs[cmd].func;
+                                       break;
+                               }
+                       if (func)
+                               break;
                }
+               if (func)
+                       (*func)();
+               else
+                       ao_cmd_status = ao_cmd_syntax_error;
                report();
        }
-               
 }
 
-struct ao_task __xdata cmd_task;
+__xdata struct ao_task ao_cmd_task;
+
+__code struct ao_cmds  ao_base_cmds[] = {
+       { '?', help,            "?                                  Print this message" },
+       { 'T', ao_task_info,    "T                                  Show task states" },
+       { 'E', echo,            "E <0 off, 1 on>                    Set command echo mode" },
+       { 'd', dump,            "d <start> <end>                    Dump memory" },
+       { 0,    help,   NULL },
+};
 
 void
 ao_cmd_init(void)
 {
-       ao_add_task(&cmd_task, ao_cmd);
+       ao_cmd_register(&ao_base_cmds[0]);
+       ao_add_task(&ao_cmd_task, ao_cmd, "cmd");
 }