X-Git-Url: http://git.droids-corp.org/?p=protos%2Fimu.git;a=blobdiff_plain;f=cmdline.c;fp=cmdline.c;h=91360a9a5a937eed5535180663afbce01ebeeaa3;hp=0000000000000000000000000000000000000000;hb=84796cd7a01e949167a155ec21f55fd71e788015;hpb=883f5aae494ab066938b0cebb554a1ee13766713 diff --git a/cmdline.c b/cmdline.c new file mode 100644 index 0000000..91360a9 --- /dev/null +++ b/cmdline.c @@ -0,0 +1,236 @@ +/* + * Copyright Droids Corporation + * Olivier Matz + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Revision : $Id: cmdline.c,v 1.7 2009-11-08 17:24:33 zer0 Exp $ + * + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include "callout.h" +#include "main.h" +#include "cmdline.h" + +#define FLUSH_LOGS_MS 1000 /* every second */ +#define LOG_PER_SEC_MAX 10 + +extern const parse_ctx_t PROGMEM main_ctx[]; + +static struct callout flush_log_timer; +static uint8_t log_count; + +int cmdline_dev_send(char c, FILE* f) +{ + (void)f; + uart_send(CMDLINE_UART, c); + return 0; +} + +int cmdline_dev_recv(FILE* f) +{ + int16_t c; + + (void)f; + c = uart_recv_nowait(CMDLINE_UART); + if (c < 0) + return _FDEV_EOF; + + return c; +} + + +int xbee_dev_send(char c, FILE* f) +{ + (void)f; + uart_send(XBEE_UART, c); + return 0; +} + +int xbee_dev_recv(FILE* f) +{ + int16_t c; + + (void)f; + c = uart_recv_nowait(XBEE_UART); + if (c < 0) + return _FDEV_EOF; + + return c; +} + +void cmdline_valid_buffer(const char *buf, uint8_t size) +{ + int8_t ret; + PGM_P ctx = (PGM_P)main_ctx; + + (void)size; + ret = parse(ctx, buf); + if (ret == PARSE_AMBIGUOUS) + printf_P(PSTR("Ambiguous command\r\n")); + else if (ret == PARSE_NOMATCH) + printf_P(PSTR("Command not found\r\n")); + else if (ret == PARSE_BAD_ARGS) + printf_P(PSTR("Bad arguments\r\n")); +} + +static int8_t +complete_buffer(const char *buf, char *dstbuf, uint8_t dstsize, + int16_t *state) +{ + PGM_P ctx = (PGM_P)main_ctx; + return complete(ctx, buf, state, dstbuf, dstsize); +} + + +void cmdline_write_char(char c) +{ + cmdline_dev_send(c, NULL); +} + + +/* sending "pop" on cmdline uart resets the robot */ +void emergency(char c) +{ + static uint8_t i = 0; + + if ((i == 0 && c == 'p') || + (i == 1 && c == 'o') || + (i == 2 && c == 'p')) + i++; + else if ( !(i == 1 && c == 'p') ) + i = 0; + if (i == 3) { + //bootloader(); + reset(); + } +} + +/* log function, configured dynamically */ +void mylog(struct error * e, ...) +{ +#ifndef HOST_VERSION + u16 stream_flags = stdout->flags; +#endif + va_list ap; + uint8_t i, flags; + uint32_t ms; + uint8_t prio; + + /* too many logs */ + if (log_count >= LOG_PER_SEC_MAX) + return; + + /* higher log value means lower criticity */ + if (e->severity > ERROR_SEVERITY_ERROR) { + if (imuboard.log_level < e->severity) + return; + + for (i=0; ierr_num) + break; + if (i == NB_LOGS+1) + return; + } + + /* get time */ + IRQ_LOCK(flags); + ms = global_ms; + IRQ_UNLOCK(flags); + + /* prevent flush log to occur */ + prio = callout_mgr_set_prio(&imuboard.intr_cm, + LOW_PRIO); + + /* display the log */ + va_start(ap, e); + printf_P(PSTR("%d.%.3d: "), (int)(ms/1000UL), (int)(ms%1000UL)); + vfprintf_P(stdout, e->text, ap); + printf_P(PSTR("\r\n")); + va_end(ap); + +#ifndef HOST_VERSION + stdout->flags = stream_flags; +#endif + callout_mgr_restore_prio(&imuboard.intr_cm, prio); +} + +static void flush_logs_cb(struct callout_mgr *cm, struct callout *tim, + void *arg) +{ + (void)cm; + (void)tim; + (void)arg; + + if (log_count == LOG_PER_SEC_MAX) + printf_P("some logs were dropped\n"); + callout_reschedule(&imuboard.intr_cm, &flush_log_timer, + FLUSH_LOGS_MS); +} + + +int cmdline_poll(void) +{ + const char *history, *buffer; + int8_t ret, same = 0; + int16_t c; + + c = cmdline_dev_recv(NULL); + if (c < 0) + return -1; + + ret = rdline_char_in(&imuboard.rdl, c); + if (ret == 1) { + buffer = rdline_get_buffer(&imuboard.rdl); + history = rdline_get_history_item(&imuboard.rdl, 0); + if (history) { + same = !memcmp(buffer, history, strlen(history)) && + buffer[strlen(history)] == '\n'; + } + else + same = 0; + if (strlen(buffer) > 1 && !same) + rdline_add_history(&imuboard.rdl, buffer); + + if (imuboard.rdl.status != RDLINE_STOPPED) + rdline_newline(&imuboard.rdl, imuboard.prompt); + } + + return 0; +} + +void cmdline_init(void) +{ + /* init command line */ + rdline_init(&imuboard.rdl, cmdline_write_char, cmdline_valid_buffer, + complete_buffer); + snprintf_P(imuboard.prompt, sizeof(imuboard.prompt), + PSTR("imu > ")); + + /* load a timer for flushing logs */ + callout_init(&flush_log_timer, flush_logs_cb, NULL, LOW_PRIO); + callout_schedule(&imuboard.intr_cm, &flush_log_timer, FLUSH_LOGS_MS); +}