From e25ff6078d9e0348023098f45905c8fa4f42b16b Mon Sep 17 00:00:00 2001 From: Jonne Kokkonen Date: Fri, 18 Jun 2021 14:32:50 +0300 Subject: [PATCH] add possibility to reset display manually, add automatic display reset on packet errors --- .gitignore | 2 ++ README.md | 1 + command.c | 55 +++++++++++++++++++++++++++++++----------------------- command.h | 2 +- input.c | 29 +++++++++++++++++++++++----- input.h | 3 ++- main.c | 26 +++++++++++++++++++------- slip.c | 4 +++- slip.h | 5 ++--- write.c | 28 +++++++++++++++++++-------- write.h | 1 + 11 files changed, 107 insertions(+), 49 deletions(-) diff --git a/.gitignore b/.gitignore index cf89ac2..86cd7b4 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ m8c .vscode font.c build/ +compile_commands.json +.clangd diff --git a/README.md b/README.md index 2a5826f..e784f0c 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ Additional controls: * Alt + F4 = quit program * Delete = opt+edit (deletes a row) * Esc = toggle keyjazz on/off +* r / select+start+opt+edit = reset display (if glitches appear on the screen, use this) Keyjazz allows to enter notes with keyboard, oldschool tracker-style. The layout is two octaves, starting from keys Z and Q. When keyjazz is active, regular a/s/z/x keys are disabled. diff --git a/command.c b/command.c index 80c5601..adf7a18 100644 --- a/command.c +++ b/command.c @@ -30,7 +30,7 @@ static inline void dump_packet(uint32_t size, uint8_t *recv_buf) { SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "\n"); } -void process_command(uint8_t *data, uint32_t size) { +int process_command(uint8_t *data, uint32_t size) { uint8_t recv_buf[size + 1]; @@ -47,15 +47,18 @@ void process_command(uint8_t *data, uint32_t size) { "Invalid draw rectangle packet: expected length %d, got %d\n", draw_rectangle_command_datalength, size); dump_packet(size, recv_buf); + return 0; break; - } + } else { - struct draw_rectangle_command rectcmd = { - {decodeInt16(recv_buf, 1), decodeInt16(recv_buf, 3)}, // position x/y - {decodeInt16(recv_buf, 5), decodeInt16(recv_buf, 7)}, // size w/h - {recv_buf[9], recv_buf[10], recv_buf[11]}}; // color r/g/b + struct draw_rectangle_command rectcmd = { + {decodeInt16(recv_buf, 1), decodeInt16(recv_buf, 3)}, // position x/y + {decodeInt16(recv_buf, 5), decodeInt16(recv_buf, 7)}, // size w/h + {recv_buf[9], recv_buf[10], recv_buf[11]}}; // color r/g/b - draw_rectangle(&rectcmd); + draw_rectangle(&rectcmd); + return 1; + } break; @@ -67,16 +70,19 @@ void process_command(uint8_t *data, uint32_t size) { "Invalid draw character packet: expected length %d, got %d\n", draw_character_command_datalength, size); dump_packet(size, recv_buf); + return 0; break; + } else { + + struct draw_character_command charcmd = { + recv_buf[1], // char + {decodeInt16(recv_buf, 2), decodeInt16(recv_buf, 4)}, // position x/y + {recv_buf[6], recv_buf[7], recv_buf[8]}, // foreground r/g/b + {recv_buf[9], recv_buf[10], recv_buf[11]}}; // background r/g/b + draw_character(&charcmd); + return 1; } - struct draw_character_command charcmd = { - recv_buf[1], // char - {decodeInt16(recv_buf, 2), decodeInt16(recv_buf, 4)}, // position x/y - {recv_buf[6], recv_buf[7], recv_buf[8]}, // foreground r/g/b - {recv_buf[9], recv_buf[10], recv_buf[11]}}; // background r/g/b - draw_character(&charcmd); - break; case draw_oscilloscope_waveform_command: @@ -91,18 +97,21 @@ void process_command(uint8_t *data, uint32_t size) { draw_oscilloscope_waveform_command_mindatalength, draw_oscilloscope_waveform_command_maxdatalength, size); dump_packet(size, recv_buf); + return 0; break; - } + } else { - struct draw_oscilloscope_waveform_command osccmd; + struct draw_oscilloscope_waveform_command osccmd; - osccmd.color = - (struct color){recv_buf[1], recv_buf[2], recv_buf[3]}; // color r/g/b - memcpy(osccmd.waveform, &recv_buf[4], size - 4); + osccmd.color = + (struct color){recv_buf[1], recv_buf[2], recv_buf[3]}; // color r/g/b + memcpy(osccmd.waveform, &recv_buf[4], size - 4); - osccmd.waveform_size = size - 4; + osccmd.waveform_size = size - 4; - draw_waveform(&osccmd); + draw_waveform(&osccmd); + return 1; + } break; @@ -118,14 +127,14 @@ void process_command(uint8_t *data, uint32_t size) { } */ // nothing is done with joypad key pressed packets for now - + return 1; break; default: SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Invalid packet\n"); dump_packet(size, recv_buf); - + return 1; break; } } diff --git a/command.h b/command.h index b63a89e..32f3816 100644 --- a/command.h +++ b/command.h @@ -51,6 +51,6 @@ struct command_queues { }; -void process_command(uint8_t *data, uint32_t size); +int process_command(uint8_t *data, uint32_t size); #endif \ No newline at end of file diff --git a/input.c b/input.c index 856b966..612a761 100644 --- a/input.c +++ b/input.c @@ -2,8 +2,6 @@ // Released under the MIT licence, https://opensource.org/licenses/MIT #include -#include -#include #include #include "input.h" @@ -44,7 +42,8 @@ int initialize_game_controllers() { int controller_index = 0; SDL_Log("Looking for game controllers\n"); - SDL_Delay(1); // Some controllers like XBone wired need a little while to get ready + SDL_Delay( + 1); // Some controllers like XBone wired need a little while to get ready // Open all available game controllers for (int i = 0; i < num_joysticks; i++) { if (!SDL_IsGameController(i)) @@ -52,7 +51,8 @@ int initialize_game_controllers() { if (controller_index >= MAX_CONTROLLERS) break; game_controllers[controller_index] = SDL_GameControllerOpen(i); - SDL_Log("Controller %d: %s",controller_index+1,SDL_GameControllerName(game_controllers[controller_index])); + SDL_Log("Controller %d: %s", controller_index + 1, + SDL_GameControllerName(game_controllers[controller_index])); controller_index++; } @@ -227,6 +227,10 @@ static input_msg_s handle_normal_keys(SDL_Event *event, uint8_t keyvalue) { key.value = key_opt | key_edit; break; + case SDL_SCANCODE_R: + key = (input_msg_s){special, msg_reset_display}; + break; + default: key.value = 0; break; @@ -288,6 +292,10 @@ void handle_sdl_events() { switch (event.type) { + case SDL_WINDOWEVENT_RESIZED: + key = (input_msg_s){special, msg_reset_display}; + break; + // Reinitialize game controllers on controller add/remove/remap case SDL_CONTROLLERDEVICEADDED: case SDL_CONTROLLERDEVICEREMOVED: @@ -360,5 +368,16 @@ input_msg_s get_input_msg() { // Query for SDL events handle_sdl_events(); - return (input_msg_s){key.type, keycode}; + if (keycode == (key_start|key_select|key_opt|key_edit)){ + key = (input_msg_s){special,msg_reset_display}; + } + + if (key.type == normal) { + /* Normal input keys go through some event-based manipulation in + handle_sdl_events(), the value is stored in keycode variable */ + return (input_msg_s){key.type, keycode}; + } else { + // Special event keys already have the correct keycode baked in + return key; + } } \ No newline at end of file diff --git a/input.h b/input.h index 8998860..f02220c 100644 --- a/input.h +++ b/input.h @@ -13,7 +13,8 @@ typedef enum input_type_t { } input_type_t; typedef enum special_messages_t { - msg_quit + msg_quit = 1, + msg_reset_display = 2 } special_messages_t; typedef struct input_msg_s { diff --git a/main.c b/main.c index aca191a..f993f07 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,7 @@ #define serial_read_size 1024 uint8_t run = 1; +uint8_t need_display_reset = 0; // Handles CTRL+C / SIGINT void intHandler(int dummy) { run = 0; } @@ -81,13 +82,21 @@ int main(int argc, char *argv[]) { } break; case special: - switch (input.value) { - case msg_quit: - run = 0; + if (input.value != prev_input) { + prev_input = input.value; + switch (input.value) { + case msg_quit: + run = 0; + break; + case msg_reset_display: + reset_display(port); + break; + default: + break; + } break; } - break; - } + } // read serial port size_t bytes_read = sp_nonblocking_read(port, serial_buf, serial_read_size); @@ -102,7 +111,11 @@ int main(int argc, char *argv[]) { // process the incoming bytes into commands and draw them int n = slip_read_byte(&slip, rx); if (n != SLIP_NO_ERROR) { - SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", n); + if (n == SLIP_ERROR_INVALID_PACKET) { + reset_display(port); + } else { + SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", n); + } } } usleep(10); @@ -110,7 +123,6 @@ int main(int argc, char *argv[]) { render_screen(); usleep(100); } - } // exit, clean up diff --git a/slip.c b/slip.c index 818db20..87f0e2c 100644 --- a/slip.c +++ b/slip.c @@ -77,7 +77,9 @@ slip_error_t slip_read_byte(slip_handler_s *slip, uint8_t byte) { case SLIP_STATE_NORMAL: switch (byte) { case SLIP_SPECIAL_BYTE_END: - slip->descriptor->recv_message(slip->descriptor->buf, slip->size); + if (!slip->descriptor->recv_message(slip->descriptor->buf, slip->size)){ + error = SLIP_ERROR_INVALID_PACKET; + } reset_rx(slip); break; case SLIP_SPECIAL_BYTE_ESC: diff --git a/slip.h b/slip.h index 4363b78..e1b183b 100644 --- a/slip.h +++ b/slip.h @@ -46,14 +46,12 @@ typedef enum { typedef struct { uint8_t *buf; uint32_t buf_size; - //struct command_queues *command_queues; - void (*recv_message)(uint8_t *data, uint32_t size); + int (*recv_message)(uint8_t *data, uint32_t size); } slip_descriptor_s; typedef struct { slip_state_t state; uint32_t size; - uint16_t crc; const slip_descriptor_s *descriptor; } slip_handler_s; @@ -61,6 +59,7 @@ typedef enum { SLIP_NO_ERROR = 0x00, SLIP_ERROR_BUFFER_OVERFLOW, SLIP_ERROR_UNKNOWN_ESCAPED_BYTE, + SLIP_ERROR_INVALID_PACKET } slip_error_t; slip_error_t slip_init(slip_handler_s *slip, const slip_descriptor_s *descriptor); diff --git a/write.c b/write.c index 2cc80c6..b95f53a 100644 --- a/write.c +++ b/write.c @@ -7,27 +7,39 @@ #include #include -int enable_and_reset_display(struct sp_port *port) { +int reset_display(struct sp_port *port){ + SDL_Log("Reset display\n"); uint8_t buf[2]; int result; + buf[0] = 0x45; + buf[1] = 0x52; + + result = sp_blocking_write(port, buf, 2, 5); + if (result != 2) { + SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result); + return 0; + } + return 1; +} + +int enable_and_reset_display(struct sp_port *port) { + uint8_t buf[1]; + int result; + SDL_Log("Enabling and resetting M8 display\n"); buf[0] = 0x44; result = sp_blocking_write(port, buf, 1, 5); if (result != 1) { SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error enabling M8 display, code %d", result); + return 0; } usleep(500); - buf[0] = 0x45; - buf[1] = 0x52; - result = sp_blocking_write(port, buf, 2, 5); - if (result != 2) { - SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result); + if (!reset_display(port)){ + return 0; } - sleep(1); - return 1; } diff --git a/write.h b/write.h index 2ceb634..40dd8ab 100644 --- a/write.h +++ b/write.h @@ -7,6 +7,7 @@ #include #include +int reset_display(struct sp_port *port); int enable_and_reset_display(struct sp_port *port); int disconnect(struct sp_port *port); int send_msg_controller(struct sp_port *port, uint8_t input);