// Copyright 2018 Mobvoi Inc. All Rights Reserved. #define _BSD_SOURCE #define _DEFAULT_SOURCE #include #include #include #include #include #include #include #include #include #include //#include //#include //#include #include #include "Serial8008.h" enum { CMD_EXIT = 0, CMD_ENABLE_BF = 1, CMD_DISABLE_BF = 2, CMD_GET_BF_STATUS = 3, CMD_SET_BF_DIR = 4, CMD_GET_DOA_DIR = 5, CMD_GET_BF_DIRS = 6, CMD_GET_WAKEUP_WORDS = 7, CMD_SET_LED_ON = 8, CMD_SET_LED_OFF = 9, CMD_DUMP_UART_HEX = 98, CMD_SHOW_UART_LOG = 99, }; //#define SEND_TEST_COMMAND #define LOG_TAG "DEMO" static inline void SerialLog(const char* fmt, ...) { va_list vl; char s[1024] = { 0 }; va_start(vl, fmt); vsprintf(s, fmt, vl); va_end(vl); printf("%s: %s",LOG_TAG, s); } void Usage() { SerialLog( "\nCommand list:\n" "\t0 : Exit\n" "\t1 : Enable beamforming\n" "\t2 : Disable beamforming\n" "\t3 : Get beamforming status\n" "\t4 : Set beamforming direction\n" "\t5 : Get DOA direction\n" "\t6 : Get all beamforming directions\n" "\t7 : Get wakeup words\n" "\t8 : Turn on LED\n" "\t9 : Turn off LED\n" "\t98 : Switch hex dumpping\n" "\t99 : Switch showing log from UART\n" "\tENTER : Repeat last command\n" ); } static int exit_flag = 0; static int show_log = 1; static int dump_hex = 0; static int test_mode = 0; void send_command(void* fd, int argc, int cmd, int param); #ifdef SEND_TEST_COMMAND void* send_test_command(void* fd) { int cmds[] = {4, 5, 6, 7}; while (exit_flag == 0) { int cmd = cmds[rand() % (sizeof(cmds) / sizeof(cmds[0]))]; int argc = 1; if (cmd == 4) { send_command(fd, 2, cmd, rand() % 360); } else { send_command(fd, 1, cmd, 0); } //sleep(rand() % 10 + 1); Sleep(rand() % 10 + 1); } } #endif void* send_commands(void* fd) { char line[64]; int cmd = 0; int param = 0; int argc = 0; while (exit_flag == 0 && fgets(line, sizeof(line), stdin) != NULL) { if (line[0] != '\n' || cmd == 0) { argc = sscanf(line, "%d %d", &cmd, ¶m); if (argc < 1) { Usage(); continue; } } send_command(fd, argc, cmd, param); } return NULL; } void send_command(void* fd, int argc, int cmd, int param) { int msg_len = 0; char msg_buff[MAX_MSG_LEN] = {0}; mob_gs_msg* msg = (mob_gs_msg*) msg_buff; switch (cmd) { case CMD_EXIT: { exit_flag = 1; SerialLog("Exiting\n"); break; } case CMD_ENABLE_BF: { msg->event = EVENT_FROM_HOST_ENABLE_BF; msg->payload_len = 0; msg_len = sizeof(mob_gs_msg); break; } case CMD_DISABLE_BF: { msg->event = EVENT_FROM_HOST_DISABLE_BF; msg->payload_len = 0; msg_len = sizeof(mob_gs_msg); break; } case CMD_GET_BF_STATUS: { msg->event = EVENT_FROM_HOST_GET_BF_STATUS; msg->payload_len = 0; msg_len = sizeof(mob_gs_msg); break; } case CMD_SET_BF_DIR: { if (argc < 2) { SerialLog("Parameter error\n"); Usage(); break; } msg->event = EVENT_FROM_HOST_SET_BF_DIR; msg->payload_len = 2; mob_short2bytes(param, msg->payload_data); msg_len = sizeof(mob_gs_msg) + msg->payload_len; break; } case CMD_GET_DOA_DIR: { msg->event = EVENT_FROM_HOST_GET_DOA_DIR; msg->payload_len = 0; msg_len = sizeof(mob_gs_msg); break; } case CMD_GET_BF_DIRS: { msg->event = EVENT_FROM_HOST_GET_BF_DIR_LIST; msg->payload_len = 0; msg_len = sizeof(mob_gs_msg); break; } case CMD_GET_WAKEUP_WORDS: { msg->event = EVENT_FROM_HOST_GET_WAKEUP_WORD; msg->payload_len = 0; msg_len = sizeof(mob_gs_msg); break; } case CMD_SET_LED_ON: { if (argc < 2) { SerialLog("Parameter error\n"); Usage(); break; } msg->event = EVENT_FROM_HOST_SET_LED; msg->payload_len = 2; short leds = 1 << param; mob_short2bytes(leds, msg->payload_data); msg_len = sizeof(mob_gs_msg) + msg->payload_len; break; } case CMD_SET_LED_OFF: { msg->event = EVENT_FROM_HOST_SET_LED; msg->payload_len = 2; short leds = 0; mob_short2bytes(leds, msg->payload_data); msg_len = sizeof(mob_gs_msg) + msg->payload_len; break; } case CMD_DUMP_UART_HEX: { dump_hex = !dump_hex; SerialLog("Flag of dump is %s\n", dump_hex ? "ON" : "OFF"); break; } case CMD_SHOW_UART_LOG: { show_log = !show_log; SerialLog("Flag of log is %s\n", show_log ? "ON" : "OFF"); break; } default: { Usage(); break; } } if (msg_len > 0) { msg->sync_tag[0] = SYNC_TAG[0]; msg->sync_tag[1] = SYNC_TAG[1]; msg->sync_tag[2] = SYNC_TAG[2]; msg->sync_tag[3] = SYNC_TAG[3]; msg->check_bits = 0; msg->reserved = 0; #ifdef SEND_TEST_COMMAND if (test_mode) { msg_len = 10000; } #endif int ret = write(*(int*)fd, msg, msg_len); if (ret < 0) { SerialLog("Wrote %d %d\n", ret, errno); } } } void process_results(mob_gs_msg* msg) { SerialLog("Event: 0x%02hhX\n", msg->event); switch (msg->event) { case EVENT_TO_HOST_WAKEUP: { SerialLog("Waked up\n"); break; } case EVENT_TO_HOST_WAKEUP_WORDS: { SerialLog("Wake up words: "); char* buff = msg->payload_data; while (buff < (msg->payload_data + msg->payload_len)) { printf("%s ", buff); buff += strlen(buff) + 1; } printf("\n"); break; } case EVENT_TO_HOST_DOA_DIR: { if (msg->payload_len < sizeof(short)) { SerialLog("Invalid payload len %d\n", msg->payload_len); } else { SerialLog("Doa dir: %d\n", mob_bytes2short(msg->payload_data)); } break; } case EVENT_TO_HOST_BF_DIR_LIST: { if (msg->payload_len < sizeof(short)) { SerialLog("Invalid payload len %d\n", msg->payload_len); } else { SerialLog("BF dir list:"); for (int i = 0; i < msg->payload_len / sizeof(short); i++) { printf(" %d", mob_bytes2short(msg->payload_data + i * sizeof(short))); } printf("\n"); } break; } case EVENT_TO_HOST_BF_STATUS: { if (msg->payload_len < sizeof(short)) { SerialLog("Invalid payload len %d\n", msg->payload_len); } else { SerialLog("BF dir: %d, ", mob_bytes2short(msg->payload_data)); printf("%s\n", mob_bytes2short(msg->payload_data + 2) ? "enabled" : "disabled"); } break; } default: { SerialLog("Unknown event: %d\n", msg->event); break; } } } void* recv_results(void* fd) { char msg_buff[MAX_MSG_LEN] = {0}; int last_remain = 0; while (exit_flag == 0) { char* buff = msg_buff + last_remain; int size = read(*(int*)fd, buff, MAX_MSG_LEN - last_remain); // printf("read out %d, %d\n", size, errno); if (size <= 0) { //sleep(1); Sleep(1); continue; } if (size > 0) { if (show_log) printf("%s", buff); if (dump_hex) { SerialLog("Msg arrived(%d):", size); for (int i = 0; i < size; i++) { printf(" %02hhX", buff[i]); } printf("\n"); } } buff = msg_buff; size += last_remain; while (size >= sizeof(mob_gs_msg)) { if (buff[0] != SYNC_TAG[0] || buff[1] != SYNC_TAG[1] || buff[2] != SYNC_TAG[2] || buff[3] != SYNC_TAG[3]) { buff++; size--; // printf("sync failed! discard 1 byte\n"); continue; } mob_gs_msg* msg = (mob_gs_msg*) buff; if ((sizeof(mob_gs_msg) + msg->payload_len) > MAX_MSG_LEN) { size -= sizeof(mob_gs_msg); buff += sizeof(mob_gs_msg); SerialLog("Invalid payload len, discard msg\n"); continue; } if (size < (sizeof(mob_gs_msg) + msg->payload_len)) break; process_results(msg); int processed = sizeof(mob_gs_msg) + msg->payload_len; buff += processed; size -= processed; } last_remain = size; if (size > 0) { memmove(msg_buff, buff, size); if (dump_hex) { SerialLog("Remain data(%d):", size); for(int i = 0; i < size; i++) { printf(" %02hhX", msg_buff[i]); } printf("\n"); } } memset(msg_buff + size, 0, MAX_MSG_LEN - size); } return NULL; } ////// void createCommandMsg(int argc, int cmd, int param, mob_gs_msg * msg, int * msg_len) { //int msg_len = 0; //char msg_buff[MAX_MSG_LEN] = { 0 }; //mob_gs_msg* msg = (mob_gs_msg*)msg_buff; switch (cmd) { case CMD_EXIT: { exit_flag = 1; SerialLog("Exiting\n"); break; } case CMD_ENABLE_BF: { msg->event = EVENT_FROM_HOST_ENABLE_BF; msg->payload_len = 0; *msg_len = sizeof(mob_gs_msg); break; } case CMD_DISABLE_BF: { msg->event = EVENT_FROM_HOST_DISABLE_BF; msg->payload_len = 0; *msg_len = sizeof(mob_gs_msg); break; } case CMD_GET_BF_STATUS: { msg->event = EVENT_FROM_HOST_GET_BF_STATUS; msg->payload_len = 0; *msg_len = sizeof(mob_gs_msg); break; } case CMD_SET_BF_DIR: { if (argc < 2) { SerialLog("Parameter error\n"); Usage(); break; } msg->event = EVENT_FROM_HOST_SET_BF_DIR; msg->payload_len = 2; mob_short2bytes(param, msg->payload_data); *msg_len = sizeof(mob_gs_msg) + msg->payload_len; break; } case CMD_GET_DOA_DIR: { msg->event = EVENT_FROM_HOST_GET_DOA_DIR; msg->payload_len = 0; *msg_len = sizeof(mob_gs_msg); break; } case CMD_GET_BF_DIRS: { msg->event = EVENT_FROM_HOST_GET_BF_DIR_LIST; msg->payload_len = 0; *msg_len = sizeof(mob_gs_msg); break; } default: { Usage(); break; } } if (*msg_len > 0) { msg->sync_tag[0] = SYNC_TAG[0]; msg->sync_tag[1] = SYNC_TAG[1]; msg->sync_tag[2] = SYNC_TAG[2]; msg->sync_tag[3] = SYNC_TAG[3]; msg->check_bits = 0; msg->reserved = 0; #ifdef SEND_TEST_COMMAND if (test_mode) { *msg_len = 10000; } #endif } } void* recv_resultsForTimes(int count, HANDLE hCom ) { char msg_buff[MAX_MSG_LEN] = { 0 }; int last_remain = 0; while (( exit_flag == 0) && (count > 0) ) { count= count-1; char* buff = msg_buff + last_remain; DWORD size = 0; //同步方式 DWORD wCount = MAX_MSG_LEN - last_remain; //成功读取的数据字节数 BOOL bReadStat = ReadFile(hCom, //串口句柄 buff, //数据首地址 wCount, //要读取的数据最大字节数 &size, //DWORD*,用来接收返回成功读取的数据字节数 NULL); //NULL为同步发送,OVERLAPPED*为异步发送 // printf("read out %d, %d\n", size, errno); if (size <= 0) { //sleep(1); Sleep(1); continue; } if (size > 0) { if (show_log) printf("%s", buff); if (dump_hex) { SerialLog("Msg arrived(%d):", size); for (int i = 0; i < size; i++) { printf(" %02hhX", buff[i]); } printf("\n"); } } buff = msg_buff; size += last_remain; while (size >= sizeof(mob_gs_msg)) { if (buff[0] != SYNC_TAG[0] || buff[1] != SYNC_TAG[1] || buff[2] != SYNC_TAG[2] || buff[3] != SYNC_TAG[3]) { buff++; size--; // printf("sync failed! discard 1 byte\n"); continue; } mob_gs_msg* msg = (mob_gs_msg*)buff; if ((sizeof(mob_gs_msg) + msg->payload_len) > MAX_MSG_LEN) { size -= sizeof(mob_gs_msg); buff += sizeof(mob_gs_msg); SerialLog("Invalid payload len, discard msg\n"); continue; } if (size < (sizeof(mob_gs_msg) + msg->payload_len)) break; process_results(msg); int processed = sizeof(mob_gs_msg) + msg->payload_len; buff += processed; size -= processed; } last_remain = size; if (size > 0) { memmove(msg_buff, buff, size); if (dump_hex) { SerialLog("Remain data(%d):", size); for (int i = 0; i < size; i++) { printf(" %02hhX", msg_buff[i]); } printf("\n"); } } memset(msg_buff + size, 0, MAX_MSG_LEN - size); } return NULL; }