From 8955d8da9476fa8fa37b0a5a88fa7be10c511b35 Mon Sep 17 00:00:00 2001 From: schodet Date: Sun, 18 Jul 2004 22:03:16 +0000 Subject: Initial revision --- n/avr/proto/proto.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 n/avr/proto/proto.c (limited to 'n/avr/proto/proto.c') diff --git a/n/avr/proto/proto.c b/n/avr/proto/proto.c new file mode 100644 index 0000000..a426c41 --- /dev/null +++ b/n/avr/proto/proto.c @@ -0,0 +1,248 @@ +/* proto.c */ +/* {{{ + * + * Copyright (C) 2004 Nicolas Schodet + * + * 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. + * + * Contact : + * Web: http://perso.efrei.fr/~schodet/ + * Email: + * }}} */ +#include "proto.h" + +#include + +/* +AutoDec */ + +/** Accept a digit to be used for args. */ +static void +proto_accept_digit (uint8_t c); + +/* Send a hex digit. */ +static void +proto_hex (uint8_t h); + +/* Send a arg. */ +inline static void +proto_arg (proto_arg_t a); + +/* -AutoDec */ + +static uint8_t cmd; +static proto_arg_t argv[AC_PROTO_MAX_ARGS]; +static uint8_t argc; + +/** Step of decoding: + * - 0: nothing received. + * - 1: bang received. + * - 2: command received. + * - 3, 4, 5: command received, and processing a number. */ +static uint8_t step; + +static proto_cb_f func_cb; +static proto_putc_f func_putc; + +/** Initialize and set the callback function. */ +void +proto_init (proto_cb_f f_cb, proto_putc_f f_putc) +{ + func_cb = f_cb; + func_putc = f_putc; +} + +/** Accept a new character. */ +void +proto_accept (uint8_t c) +{ + if (c == '!') + { + step = 1; + } + else + { + switch (step) + { + case 0: + /* Nothing received yet. */ + break; + case 1: + /* Bang received yet. */ + if (isalpha (c)) + { + cmd = c; + step = 2; + argc = 0; + } + else + { + func_cb ('?', 0, 0); + step = 0; + } + break; + case 2: + /* Command received yet. */ + if (c == '\r') + { + func_cb (cmd, argc, argv); + step = 0; + } + else if (c == ',') + { + } + else + { + step += sizeof (proto_arg_t) * 2 - 1; + proto_accept_digit (c); + } + break; + case 3: + case 4: + case 5: + step--; + proto_accept_digit (c); + break; + } + } +} + +/** Accept a digit to be used for args. */ +static void +proto_accept_digit (uint8_t c) +{ + /* Test for argument list overflow. */ + if (argc >= AC_PROTO_MAX_ARGS) + { + func_cb ('?', 0, 0); + step = 0; + return; + } + /* Convert from hexa. */ + if ('0' <= c && c <= '9') + c -= '0'; + else if ('a' <= c && c <= 'f') + c -= 'a' - 10; + else if ('A' <= c && c <= 'F') + c -= 'A' - 10; + else + { + func_cb ('?', 0, 0); + return; + } + /* Add digit. */ + argv[argc] <<= 4; + argv[argc] |= c; + if (step == 2) + argc++; +} + +/* Send a hex digit. */ +static void +proto_hex (uint8_t h) +{ + func_putc (h >= 10 ? h - 10 + 'a' : h + '0'); +} + +/* Send a arg. */ +inline static void +proto_arg (proto_arg_t a) +{ + if (sizeof (proto_arg_t) == 2) + { + proto_hex (a >> 12); + proto_hex ((a >> 8) & 0xf); + } + proto_hex ((a >> 4) & 0xf); + proto_hex ((a >> 0) & 0xf); +} + +/** Send a command, generic function. */ +void +proto_send (uint8_t cmd, uint8_t argc, proto_arg_t *argv) +{ + func_putc ('!'); + func_putc (cmd); + while (argc-- > 1) + { + proto_arg (*argv++); + func_putc (','); + } + if (!argc) + proto_arg (*argv); + func_putc ('\r'); +} + +/** Send a command, no arg. */ +void +proto_send0 (uint8_t cmd) +{ + func_putc ('!'); + func_putc (cmd); + func_putc ('\r'); +} + +/** Send a command, one arg. */ +void +proto_send1 (uint8_t cmd, proto_arg_t a0) +{ + func_putc ('!'); + func_putc (cmd); + proto_arg (a0); + func_putc ('\r'); +} + +/** Send a command, two arg. */ +void +proto_send2 (uint8_t cmd, proto_arg_t a0, proto_arg_t a1) +{ + func_putc ('!'); + func_putc (cmd); + proto_arg (a0); + func_putc (','); + proto_arg (a1); + func_putc ('\r'); +} + +/** Send a command, three arg. */ +void +proto_send3 (uint8_t cmd, proto_arg_t a0, proto_arg_t a1, proto_arg_t a2) +{ + func_putc ('!'); + func_putc (cmd); + proto_arg (a0); + func_putc (','); + proto_arg (a1); + func_putc (','); + proto_arg (a2); + func_putc ('\r'); +} + +/** Send a command, four arg. */ +void +proto_send4 (uint8_t cmd, proto_arg_t a0, proto_arg_t a1, proto_arg_t a2, + proto_arg_t a3) +{ + func_putc ('!'); + func_putc (cmd); + proto_arg (a0); + func_putc (','); + proto_arg (a1); + func_putc (','); + proto_arg (a2); + func_putc (','); + proto_arg (a3); + func_putc ('\r'); +} + -- cgit v1.2.3