From e991f970a81876c6c306b0c27c1fb27e1b321836 Mon Sep 17 00:00:00 2001 From: Arti Zirk Date: Thu, 1 Dec 2016 16:19:28 +0200 Subject: [PATCH] lab05 ready --- src/cli_microrl.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++ src/cli_microrl.h | 19 ++++++ src/hmi_msg.c | 11 +++- src/hmi_msg.h | 23 ++++++- src/main.c | 60 +++++++------------ src/uart_wrap.c | 4 +- 6 files changed, 223 insertions(+), 43 deletions(-) create mode 100644 src/cli_microrl.c create mode 100644 src/cli_microrl.h diff --git a/src/cli_microrl.c b/src/cli_microrl.c new file mode 100644 index 0000000..110a582 --- /dev/null +++ b/src/cli_microrl.c @@ -0,0 +1,149 @@ +#include +#include +#include +#include "../lib/hd44780_111/hd44780.h" +#include "../lib/andygock_avr-uart/uart.h" +#include "hmi_msg.h" +#include "print_helper.h" +#include "cli_microrl.h" + +typedef struct cli_cmd { + PGM_P cmd; + PGM_P help; + void (*func_p)(); + const uint8_t func_argc; +} cli_cmd_t; + + +const cli_cmd_t cli_cmds[] = { + {help_cmd, help_help, cli_print_help, 0}, + {ver_cmd, ver_help, cli_print_ver, 0}, + {ascii_cmd, ascii_help, cli_print_ascii_tbls, 0}, + {month_cmd, month_help, cli_handle_month, 1} +}; + + +void cli_print(const char *str) +{ + printf("%s", str); +} + + +char cli_get_char(void) +{ + if (uart0_peek() != UART_NO_DATA) { + return uart0_getc() & UART_STATUS_MASK; + } else { + return 0x00; + } +} + + +void cli_print_help(const char *const *argv) +{ + (void) argv; + putc('\n', stdout); + printf_P(PSTR(CLI_HELP_MSG "\n")); + + for (uint8_t i = 0; i < NUM_ELEMS(cli_cmds); i++) { + printf_P(cli_cmds[i].cmd); + printf_P(PSTR(" : ")); + printf_P(cli_cmds[i].help); + putc('\n', stdout); + } +} + + +void print_version(FILE *stream) +{ + // Print program and libc versions + fprintf_P(stream, PSTR(PROG_VERSION "\n"), + PSTR(GIT_DESCR), PSTR(__DATE__), PSTR(__TIME__)); + fprintf_P(stream, PSTR(LIBC_VERSION "\n"), + PSTR(__AVR_LIBC_VERSION_STRING__), + PSTR(__VERSION__)); +} + + +void cli_print_ver(const char *const *argv) +{ + (void) argv; + putc('\n', stdout); + print_version(stdout); +} + + +void cli_print_ascii_tbls(const char *const *argv) +{ + (void) argv; + putc('\n', stdout); + // ASCII table print + print_ascii_tbl(stdout); + unsigned char ascii[128]; + for (unsigned char i = 0; i < sizeof(ascii); i++) { + ascii[i] = i; + } + print_for_human(stdout, ascii, sizeof(ascii)); +} + + +void cli_handle_month(const char *const *argv) +{ + putc('\n', stdout); + lcd_goto(0x40); // Got to the beginning of the next line + char spaces_to_print = 16; + fprintf(stderr, "arg: %s\n", argv[1]); + for (int i = 0; i < 6; i++) { + if (!strncmp_P(argv[1], + (PGM_P)pgm_read_word(&months[i]), + strlen(argv[1]))) { + char printed_count; + printed_count = fprintf_P(stdout, (PGM_P)pgm_read_word(&months[i])); + fputc('\n', stdout); + lcd_puts_P((PGM_P)pgm_read_word(&months[i])); + lcd_putc(' '); + spaces_to_print -= (printed_count + 1); + } + } + // Clear the end of the line + for (; spaces_to_print > -1; spaces_to_print--) { + lcd_putc(' '); + } +} + + +void cli_print_cmd_error(void) +{ + putc('\n', stdout); + printf_P(PSTR(CLI_NO_CMD "\n")); +} + + +void cli_print_cmd_arg_error(void) +{ + putc('\n', stdout); + printf_P(PSTR(CLI_ARGS_MSG "\n")); +} + + +int cli_execute(int argc, const char *const *argv) +{ + for (uint8_t i = 0; i < NUM_ELEMS(cli_cmds); i++) { + if (!strcmp_P(argv[0], cli_cmds[i].cmd)) { + // Test do we have correct arguments to run command + // Function arguments count shall be defined in struct + if ((argc - 1) != cli_cmds[i].func_argc) { + cli_print_cmd_arg_error(); + return 0; + } + + // Hand argv over to function pointer, + // cross fingers and hope that funcion handles it properly + cli_cmds[i].func_p (argv); + return 0; + } + } + + cli_print_cmd_error(); + return 0; +} diff --git a/src/cli_microrl.h b/src/cli_microrl.h new file mode 100644 index 0000000..528ca58 --- /dev/null +++ b/src/cli_microrl.h @@ -0,0 +1,19 @@ +#ifndef _CLI_MICRORL_H_ +#define _CLI_MICRORL_H_ + +#define NUM_ELEMS(x) (sizeof(x) / sizeof((x)[0])) +#define UART_STATUS_MASK 0x00FF + +void cli_print(const char * str); +char cli_get_char(void); +void cli_print_help(const char *const *argv); +void print_version(FILE *stream); +void cli_print_ver(const char *const *argv); +void cli_print_ascii_tbls(const char *const *argv); +void cli_handle_month(const char *const *argv); +void cli_print_cmd_error(void); +void cli_print_cmd_arg_error(void); +int cli_execute(int argc, const char *const *argv); + + +#endif /* _CLI_MICRORL_H_ */ diff --git a/src/hmi_msg.c b/src/hmi_msg.c index eeeedd1..5a8bb55 100644 --- a/src/hmi_msg.c +++ b/src/hmi_msg.c @@ -8,4 +8,13 @@ static const char m4[] PROGMEM = "April"; static const char m5[] PROGMEM = "May"; static const char m6[] PROGMEM = "June"; -PGM_P const months[] PROGMEM = {m1,m2,m3,m4,m5,m6}; +PGM_P const months[] PROGMEM = {m1, m2, m3, m4, m5, m6}; + +const char help_cmd[] PROGMEM = HELP_CMD; +const char help_help[] PROGMEM = HELP_HELP; +const char ver_cmd[] PROGMEM = VER_CMD; +const char ver_help[] PROGMEM = VER_HELP; +const char ascii_cmd[] PROGMEM = ASCII_CMD; +const char ascii_help[] PROGMEM = ASCII_HELP; +const char month_cmd[] PROGMEM = MONTH_CMD; +const char month_help[] PROGMEM = MONTH_HELP; diff --git a/src/hmi_msg.h b/src/hmi_msg.h index 1106eb0..f498a42 100644 --- a/src/hmi_msg.h +++ b/src/hmi_msg.h @@ -2,11 +2,32 @@ #define _HMI_MSG_H_ #define PROG_VERSION "Version: %S built on: %S %S" -#define LIBC_VERSION "avr-libc version: %S" +#define LIBC_VERSION "avr-libc version: %S avr-gcc version: %S" #define STUD_NAME "Arti Zirk" #define GET_MONTH_MSG "Enter Month name first letter >" #define UPTIME_MSG "Uptime: %lu s" +#define HELP_CMD "help" +#define HELP_HELP "Get help" +#define VER_CMD "version" +#define VER_HELP "Print FW version" +#define ASCII_CMD "ascii" +#define ASCII_HELP "print ASCII tables" +#define MONTH_CMD "month" +#define MONTH_HELP "Find matching month from lookup list. Usage: month " +#define CLI_HELP_MSG "Implemented commands:" +#define CLI_NO_CMD "Command not implemented.\n Use to get help." +#define CLI_ARGS_MSG "To few or to many arguments for this command\nUse " + extern PGM_P const months[]; +extern const char help_cmd[]; +extern const char help_help[]; +extern const char ver_cmd[]; +extern const char ver_help[]; +extern const char ascii_cmd[]; +extern const char ascii_help[]; +extern const char month_cmd[]; +extern const char month_help[]; + #endif /* _HMI_MSG_H_ */ diff --git a/src/main.c b/src/main.c index d73e3a6..3b7091c 100644 --- a/src/main.c +++ b/src/main.c @@ -10,12 +10,20 @@ #include "uart_wrap.h" #include "print_helper.h" #include "../lib/hd44780_111/hd44780.h" +#include "../lib/helius_microrl/microrl.h" +#include "cli_microrl.h" + #define BAUDRATE 9600 // For configuring arduino mega pin 25 #define LED_INIT DDRA |= _BV(DDA3); #define LED_TOGGLE PORTA ^= _BV(PORTA3) +#define UART_STATUS_MASK 0x00FF + +// Create microrl object and pointer on it +static microrl_t rl; +static microrl_t *prl = &rl; static inline void init_system_clock(void) { @@ -26,6 +34,7 @@ static inline void init_system_clock(void) TIMSK5 |= _BV(OCIE5A); // Output Compare A Match Interrupt Enable } + static inline void init_hw (void) { // IO init @@ -51,51 +60,20 @@ static inline void init_hw (void) static inline void start_ui (void) { - // Print program and libc versions - fprintf_P(stderr, PSTR(PROG_VERSION "\n"), - PSTR(GIT_DESCR), PSTR(__DATE__), PSTR(__TIME__)); - fprintf_P(stderr, PSTR(LIBC_VERSION "\n"), PSTR(__AVR_LIBC_VERSION_STRING__)); + print_version(stderr); // print student name fprintf_P(stdout, PSTR(STUD_NAME)); fputc('\n', stdout); // Add a new line to the uart printout lcd_puts_P(PSTR(STUD_NAME)); - - // ASCII table print - print_ascii_tbl(stdout); - unsigned char ascii[128]; - for (unsigned char i = 0; i < sizeof(ascii); i++) { - ascii[i] = i; - } - print_for_human(stdout, ascii, sizeof(ascii)); - - // Bootstrap search_month message - fprintf_P(stdout, PSTR(GET_MONTH_MSG)); } -static inline void search_month (void) +static inline void start_cli(void) { - char letter; - - fscanf(stdin, "%c", &letter); - fprintf(stdout, "%c\n", letter); - lcd_goto(0x40); // Got to the beginning of the next line - char spaces_to_print = 16; - for (int i = 0; i < 6; i++) { - if (!strncmp_P(&letter, (PGM_P)pgm_read_word(&months[i]), 1)) { - char printed_count; - printed_count = fprintf_P(stdout, (PGM_P)pgm_read_word(&months[i])); - fputc('\n', stdout); - lcd_puts_P((PGM_P)pgm_read_word(&months[i])); - lcd_putc(' '); - spaces_to_print -= (printed_count + 1); - } - } - // Clear the end of the line - for (; spaces_to_print > -1; spaces_to_print--) { - lcd_putc(' '); - } - fprintf_P(stdout, PSTR(GET_MONTH_MSG)); + // Call init with ptr to microrl instance and print callback + microrl_init (prl, cli_print); + // Set callback for execute + microrl_set_execute_callback (prl, cli_execute); } static inline void heartbeat (void) @@ -110,19 +88,21 @@ static inline void heartbeat (void) LED_TOGGLE; } + int main (void) { init_hw(); start_ui(); + start_cli(); while (1) { heartbeat(); - if (uart0_available()) { - search_month(); - } + // CLI commands are handled in cli_execute() + microrl_insert_char (prl, cli_get_char()); } } + // System clock ISR(TIMER5_COMPA_vect) { diff --git a/src/uart_wrap.c b/src/uart_wrap.c index e9414e4..0d64960 100644 --- a/src/uart_wrap.c +++ b/src/uart_wrap.c @@ -2,6 +2,8 @@ #include #include "../lib/andygock_avr-uart/uart.h" +#define UART_STATUS_MASK 0x00FF + int uart0_putc_wrap(char c, FILE *stream) { (void) stream; @@ -21,7 +23,7 @@ int uart0_getc_wrap(FILE *stream) // this function is only called out when there is at least one character // available in the input buffer (see main.c line 114) then error checking // is not currently necessary. - return uart0_getc() & 0xff; + return uart0_getc() & UART_STATUS_MASK; } int uart3_putc_wrap(char c, FILE *stream)