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