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