00001
00045 #include "protocol.h"
00046 #include "cmd_ctor.h"
00047 #include "verstag.h"
00048 #include "hw/hw_adc.h"
00049 #include "hw/hw_input.h"
00050
00051 #include <drv/timer.h>
00052 #include <drv/ser.h>
00053 #include <drv/sipo.h>
00054 #include <drv/wdt.h>
00055 #include <drv/buzzer.h>
00056
00057 #include <mware/readline.h>
00058 #include <mware/parser.h>
00059
00060 #include <cfg/compiler.h>
00061 #include <cfg/debug.h>
00062
00063 #include <kern/kfile.h>
00064
00065 #include <stdlib.h>
00066 #include <string.h>
00067
00068
00069 #define ADC_FORMAT_STR "dddd"
00070
00071
00072 #define FORCE_INTERACTIVE 1
00073
00081 static bool interactive;
00082
00084 static struct RLContext rl_ctx;
00085
00086 uint8_t reg_status_dout;
00093 INLINE void NAK(KFile *fd, const char *err)
00094 {
00095 #ifdef _DEBUG
00096 kfile_printf(fd, "NAK \"%s\"\r\n", err);
00097 #else
00098 kfile_printf(fd, "NAK\r\n");
00099 #endif
00100 }
00101
00102 static void protocol_prompt(KFile *fd)
00103 {
00104 kfile_print(fd, ">> ");
00105 }
00106
00107
00108
00109
00110
00111 static bool protocol_reply(KFile *fd, const struct CmdTemplate *t,
00112 const parms *args)
00113 {
00114 unsigned short offset = strlen(t->arg_fmt) + 1;
00115 unsigned short nres = strlen(t->result_fmt);
00116
00117 for (unsigned short i = 0; i < nres; ++i)
00118 {
00119 if (t->result_fmt[i] == 'd')
00120 {
00121 kfile_printf(fd, " %ld", args[offset+i].l);
00122 }
00123 else if (t->result_fmt[i] == 's')
00124 {
00125 kfile_printf(fd, " %s", args[offset+i].s);
00126 }
00127
00128 else
00129 {
00130 abort();
00131 }
00132 }
00133 kfile_printf(fd, "\r\n");
00134 return true;
00135 }
00136
00137 static void protocol_parse(KFile *fd, const char *buf)
00138 {
00139 const struct CmdTemplate *templ;
00140
00141
00142 templ = parser_get_cmd_template(buf);
00143 if (!templ)
00144 {
00145 kfile_print(fd, "-1 Invalid command.\r\n");
00146 protocol_prompt(fd);
00147 return;
00148 }
00149
00150 parms args[PARSER_MAX_ARGS];
00151
00152
00153 if (!parser_get_cmd_arguments(buf, templ, args))
00154 {
00155 kfile_print(fd, "-2 Invalid arguments.\r\n");
00156 protocol_prompt(fd);
00157 return;
00158 }
00159
00160
00161 if(!parser_execute_cmd(templ, args))
00162 {
00163 NAK(fd, "Error in executing command.");
00164 }
00165 if (!protocol_reply(fd, templ, args))
00166 {
00167 NAK(fd, "Invalid return format.");
00168 }
00169
00170 protocol_prompt(fd);
00171 return;
00172 }
00173
00174 void protocol_run(KFile *fd)
00175 {
00180 static char linebuf[80];
00181
00182 if (!interactive)
00183 {
00184 kfile_gets(fd, linebuf, sizeof(linebuf));
00185
00186
00187 kfile_clearerr(fd);
00188
00189
00190 if (linebuf[0])
00191 {
00192
00193
00194 if(linebuf[0] != '#')
00195 {
00196 if (linebuf[0] == 0x1B && linebuf[1] == 0x1B)
00197 {
00198 interactive = true;
00199 kfile_printf(fd, "Entering interactive mode\r\n");
00200 }
00201 else
00202 {
00203 protocol_parse(fd, linebuf);
00204 }
00205 }
00206 }
00207 }
00208 else
00209 {
00210 const char *buf;
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 buf = rl_readline(&rl_ctx);
00221
00222
00223
00224 if(buf && buf[0] != '#')
00225 {
00226 if (buf[0] != '\0')
00227 {
00228
00229 if (!strcmp(buf, "exit") || !strcmp(buf, "quit"))
00230 {
00231 rl_clear_history(&rl_ctx);
00232 kfile_printf(fd, "Leaving interactive mode...\r\n");
00233 interactive = FORCE_INTERACTIVE;
00234 }
00235 else
00236 {
00237
00238 linebuf[0] = '0';
00239 linebuf[1] = ' ';
00240
00241 strncpy(linebuf + 2, buf, sizeof(linebuf) - 3);
00242 linebuf[sizeof(linebuf) - 1] = '\0';
00243 protocol_parse(fd, linebuf);
00244 }
00245 }
00246 }
00247 }
00248 }
00249
00250
00251
00252
00253
00254
00255
00256
00257 MAKE_CMD(ver, "", "ddd",
00258 ({
00259 args[1].l = VERS_MAJOR;
00260 args[2].l = VERS_MINOR;
00261 args[3].l = VERS_REV;
00262 0;
00263 }), 0);
00264
00265
00266 MAKE_CMD(sleep, "d", "",
00267 ({
00268 timer_delay((mtime_t)args[1].l);
00269 0;
00270 }), 0)
00271
00272
00273 MAKE_CMD(ping, "", "",
00274 ({
00275
00276 (void)args;
00277 0;
00278 }), 0)
00279
00280
00281 MAKE_CMD(dout, "d", "",
00282 ({
00283 sipo_putchar((uint8_t)args[1].l);
00284
00285
00286 reg_status_dout = (uint8_t)args[1].l;
00287 0;
00288 }), 0)
00289
00290
00291 MAKE_CMD(rdout, "", "d",
00292 ({
00293 args[1].l = reg_status_dout;
00294 0;
00295 }), 0)
00296
00297
00298
00299 MAKE_CMD(reset, "", "",
00300 ({
00301
00302 (void)args;
00303 wdt_init(7);
00304 wdt_start();
00305
00306
00307
00308
00309 ASSERT(args);
00310 while(args);
00311 0;
00312
00313 }), 0)
00314
00315
00316 MAKE_CMD(din, "", "d",
00317 ({
00318 args[1].l = INPUT_GET();
00319 0;
00320 }), 0)
00321
00322
00323
00324
00325 MAKE_CMD(ain, "", ADC_FORMAT_STR,
00326 ({
00327 STATIC_ASSERT((sizeof(ADC_FORMAT_STR) - 1) == ADC_CHANNEL_NUM);
00328 for(int i = 0; i < ADC_CHANNEL_NUM; i++)
00329 args[i+1].l = adc_read_ai_channel(i);
00330
00331 0;
00332 }), 0)
00333
00334
00335 MAKE_CMD(beep, "d", "",
00336 ({
00337 buz_beep(args[1].l);
00338 0;
00339 }), 0)
00340
00341
00342 static void protocol_registerCmds(void)
00343 {
00344 REGISTER_CMD(ver);
00345 REGISTER_CMD(sleep);
00346 REGISTER_CMD(ping);
00347 REGISTER_CMD(dout);
00348
00349 reg_status_dout = 0;
00350 REGISTER_CMD(rdout);
00351 REGISTER_CMD(reset);
00352 REGISTER_CMD(din);
00353 REGISTER_CMD(ain);
00354 REGISTER_CMD(beep);
00355 }
00356
00357
00358 void protocol_init(KFile *fd)
00359 {
00360 interactive = FORCE_INTERACTIVE;
00361
00362 rl_init_ctx(&rl_ctx);
00363
00364 rl_sethook_get(&rl_ctx, (getc_hook)kfile_getc, fd);
00365 rl_sethook_put(&rl_ctx, (putc_hook)kfile_putc, fd);
00366 rl_sethook_match(&rl_ctx, parser_rl_match, NULL);
00367 rl_sethook_clear(&rl_ctx, (clear_hook)kfile_clearerr,fd);
00368
00369 parser_init();
00370
00371 protocol_registerCmds();
00372
00373 protocol_prompt(fd);
00374 }