diff --git a/components/C-Linked-List/CMakeLists.txt b/components/C-Linked-List/CMakeLists.txt new file mode 100644 index 0000000..d11d33f --- /dev/null +++ b/components/C-Linked-List/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register( + INCLUDE_DIRS . + SRCS list.c +) diff --git a/components/C-Linked-List/list.c b/components/C-Linked-List/list.c new file mode 100644 index 0000000..c04e328 --- /dev/null +++ b/components/C-Linked-List/list.c @@ -0,0 +1,111 @@ +#ifndef LIST_DEF +#define LIST_DEF 1 + +/* + File: list.c + Description: Implementation of linked list object functionality. + Created: March 21, 2017 + Author: Matt Mumau + */ + +// System dependencies +#include + +// Header +#include "list.h" + +void list_push(List** head, void* data) { + List* node = malloc(sizeof(List)); + if (node == NULL) { + return; + } + + node->data = data; + node->next = NULL; + + if (*head == NULL) { + *head = node; + return; + } + + while ((*head)->next != NULL) { + head = &(*head)->next; + } + + (*head)->next = node; +} + +void* list_pop(List** head) { + void* data = NULL; + + if (*head == NULL) { + return data; + } + + List** last = head; + while ((*head)->next != NULL) { + last = head; + head = &(*head)->next; + } + + data = (void*) (*head)->data; + + (*last)->next = NULL; + + free(*head); + *head = NULL; + + return data; +} + +void list_insert(List** head, void* data) { + List* node = malloc(sizeof(List)); + node->data = data; + node->next = *head; + + *head = node; +} + +unsigned int list_sizeof(List* head) { + if (head == NULL) { + return 0; + } + + unsigned int size = 1; + + while (head->next != NULL) { + size++; + head = head->next; + } + + return size; +} + +List* list_get(List* head, unsigned int index) { + for (unsigned int i = 0; i < index; i++) { + head = head->next; + } + + return head; +} + +void list_remove(List** head, unsigned int index) { + if (!head || !*head || index >= list_sizeof(*head)) return; + + if (index == 0) { + List* prev_head = (*head); + (*head) = (*head)->next; + free(prev_head); + } else { + List* a_cursor = (*head); + for (unsigned int i = 1; i < index; i++) { + a_cursor = a_cursor->next; + } + List* tmp_cursor = a_cursor->next; + tmp_cursor = tmp_cursor->next; + free(a_cursor->next); + a_cursor->next = tmp_cursor; + } +} + +#endif diff --git a/components/C-Linked-List/list.h b/components/C-Linked-List/list.h new file mode 100644 index 0000000..a340eaa --- /dev/null +++ b/components/C-Linked-List/list.h @@ -0,0 +1,46 @@ +#ifndef LIST_H_DEF +#define LIST_H_DEF 1 + +/* + File: list.h + Description: Linked list library definition + Created: March 21, 2017 + Author: Matt Mumau + */ + +typedef struct List { + void* data; + struct List* next; +} List; + +/* + Push data to the end of the list. + */ +void list_push(List** head, void* data); + +/* + Remove the final element of the list and return its data. + */ +void* list_pop(List** head); + +/* + Insert the data object to the beginning of the list. + */ +void list_insert(List** head, void* data); + +/* + Get the size of the list. + */ +unsigned int list_sizeof(List* head); + +/* + Get the data of the node at the given ordinal number in the list. + */ +List* list_get(List* head, unsigned int index); + +/* + Delete the item in the list at the given ordinal location (1 is the first). + */ +void list_remove(List** head, unsigned int index); + +#endif diff --git a/main/can.c b/main/can.c index 7f01d89..e005b00 100644 --- a/main/can.c +++ b/main/can.c @@ -13,7 +13,11 @@ bool is_error_passive = false; bool auto_recovery = false; -bool advanced_filtering = false; +adv_filt_t adv_filters = { + .filters = NULL, + .enabled = false, + .sw_filtering = false, +}; SemaphoreHandle_t can_mutex; volatile can_status_t curr_can_state = { 0 }; @@ -112,7 +116,7 @@ void can_task(void* arg) { sem_res = xSemaphoreTake(can_mutex, 0); if (sem_res == pdTRUE) { while ((ret = twai_receive(&rx_msg, can_task_timeout)) == ESP_OK) { - if (advanced_filtering) { + if (adv_filters.sw_filtering) { if (!matches_filters(&rx_msg)) continue; } can_msg_to_str(&rx_msg, "recv ", data_bytes_str); diff --git a/main/can.h b/main/can.h index 9d558da..5bb8d4d 100644 --- a/main/can.h +++ b/main/can.h @@ -6,6 +6,7 @@ #include "sdkconfig.h" #include "freertos/semphr.h" #include +#include typedef struct { char status[30]; @@ -24,6 +25,12 @@ typedef enum { CAN_RECOVERING = 5, } can_state_e; +typedef struct { + bool enabled; + List* filters; + bool sw_filtering; +} adv_filt_t; + typedef struct { can_state_e state; uint32_t msgs_to_tx; /**< Number of messages queued for transmission or awaiting transmission completion */ @@ -39,10 +46,9 @@ typedef struct { extern SemaphoreHandle_t can_mutex; extern volatile can_status_t curr_can_state; -extern bool timestamp_enabled; extern bool auto_recovery; extern bool is_error_passive; -extern bool advanced_filtering; +extern adv_filt_t adv_filters; // functions diff --git a/main/cmd_can.c b/main/cmd_can.c index ea5b61a..9aa2f3e 100644 --- a/main/cmd_can.c +++ b/main/cmd_can.c @@ -42,7 +42,7 @@ static struct { } cansend_args; static int send_can_frame(int argc, char **argv) { - twai_message_t msg = {.extd = 1}; + twai_message_t msg = { 0 }; char printf_str[70]; int nerrors = arg_parse(argc, argv, (void **) &cansend_args); if (nerrors != 0) { @@ -56,7 +56,7 @@ static int send_can_frame(int argc, char **argv) { if ((id_substr == NULL) || (strtok(NULL, "#") != NULL)) goto invalid_args; int id_l = strlen(id_substr); int dt_l = data_substr == NULL ? 0 : strlen(data_substr); - if ((id_l > 8) || (dt_l > 16) || (id_l % 2) || (dt_l % 2)) goto invalid_args; + if ((id_l > 8) || (dt_l > 16) || (dt_l % 2)) goto invalid_args; for (int i = 0; i < id_l; i++) if(!isxdigit((int) id_substr[i])) goto invalid_args; for (int i = 0; i < dt_l; i++) if(!isxdigit((int) data_substr[i])) goto invalid_args; int msg_id; @@ -72,6 +72,7 @@ static int send_can_frame(int argc, char **argv) { } msg.data_length_code = dt_l / 2; msg.identifier = msg_id; + msg.extd = (id_l > 3); esp_err_t res = twai_transmit(&msg, pdMS_TO_TICKS(1000)); switch(res) { case ESP_OK: @@ -91,7 +92,7 @@ static int send_can_frame(int argc, char **argv) { free(can_msg_str_buf); return 0; invalid_args: - printf("Invalid arguments!\n"); + print_w_clr_time("Invalid arguments!", LOG_COLOR_RED, true); free(can_msg_str_buf); return 1; } @@ -115,7 +116,7 @@ static const char* can_states_str[] = { static int canstats(int argc, char **argv) { if (curr_can_state.state == CAN_NOT_INSTALLED) { - printf("CAN driver is not installed!\n"); + print_w_clr_time("CAN driver is not installed!", LOG_COLOR_RED, true); return 0; } else { const char *state_str = can_states_str[curr_can_state.state]; @@ -156,10 +157,10 @@ static int canup(int argc, char **argv) { } if (canup_args.filters->count) { f_config = my_filters; - print_w_clr_time("Using predefined filters.", LOG_COLOR_GREEN, true); + printf("Using %s filters.\n", adv_filters.enabled ? "smart" : "basic hw"); } else { f_config = (twai_filter_config_t) TWAI_FILTER_CONFIG_ACCEPT_ALL(); - print_w_clr_time("Using accept all filters.", LOG_COLOR_GREEN, true); + printf("Using accept all filters.\n"); } esp_log_level_t prev_gpio_lvl = esp_log_level_get("gpio"); int mode = 0; @@ -360,9 +361,9 @@ static void register_canrecover(void) { } static struct { - struct arg_lit *dual; - struct arg_str *code; - struct arg_str *mask; + struct arg_lit *dual_arg; + struct arg_str *code_arg; + struct arg_str *mask_arg; struct arg_end *end; } canfilter_args; @@ -372,20 +373,40 @@ static int canfilter(int argc, char **argv) { arg_print_errors(stderr, canfilter_args.end, argv[0]); return 1; } - if (canfilter_args.dual->count) { + const char* mask_s = canfilter_args.mask_arg->sval[0]; + const char* code_s = canfilter_args.code_arg->sval[0]; + int m_l = strlen(mask_s); + int c_l = strlen(code_s); + if (m_l != 8 || c_l != 8) goto invalid_args; + for (int i = 0; i < m_l; i++) if(!isxdigit((int) mask_s[i])) goto invalid_args; + for (int i = 0; i < c_l; i++) if(!isxdigit((int) code_s[i])) goto invalid_args; + uint32_t mask = 0; + uint32_t code = 0; + if (sscanf(mask_s, "%" PRIX32, &mask) < 1) goto invalid_args; + if (sscanf(code_s, "%" PRIX32, &code) < 1) goto invalid_args; + if (canfilter_args.dual_arg->count) { my_filters.single_filter = false; - + print_w_clr_time("Setting hw filters in dual mode.", LOG_COLOR_GREEN, true); } else { my_filters.single_filter = true; + print_w_clr_time("Setting hw filters in single mode.", LOG_COLOR_GREEN, true); } + printf("mask: %" PRIX32 ", code: %" PRIX32 "\n", mask, code); + my_filters.acceptance_code = code; + my_filters.acceptance_mask = mask; + adv_filters.enabled = false; + adv_filters.sw_filtering = false; return 0; +invalid_args: + print_w_clr_time("Invalid arguments!", LOG_COLOR_RED, true); + return 1; } static void register_canfilter(void) { - canfilter_args.mask = arg_str1("m", "mask", "", "Acceptance mask (as in esp-idf docs), uint32_t in hex form, 8 symbols."); - canfilter_args.code = arg_str1("c", "code", "", "Acceptance code (as in esp-idf docs), uint32_t in hex form, 8 symbols."); - canfilter_args.dual = arg_lit0("d", NULL, "Use Dual Filter Mode."); + canfilter_args.mask_arg = arg_str1("m", "mask", "", "Acceptance mask (as in esp-idf docs), uint32_t in hex form, 8 symbols."); + canfilter_args.code_arg = arg_str1("c", "code", "", "Acceptance code (as in esp-idf docs), uint32_t in hex form, 8 symbols."); + canfilter_args.dual_arg = arg_lit0("d", NULL, "Use Dual Filter Mode."); const esp_console_cmd_t cmd = { .command = "canfilter",