ref: cd4a24fc05afaf671ec7287a854d73b20f4fd3e9
parent: 7b749ed1b5949e36bd8ef1609cc5abec68c7df5b
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Fri Jun 18 10:32:50 EDT 2021
add possibility to reset display manually, add automatic display reset on packet errors
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@
.vscode
font.c
build/
+compile_commands.json
+.clangd
--- a/README.md
+++ b/README.md
@@ -82,6 +82,7 @@
* 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.
--- a/command.c
+++ b/command.c
@@ -30,7 +30,7 @@
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 @@
"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 @@
"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 @@
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,7 +127,7 @@
} */
// nothing is done with joypad key pressed packets for now
-
+ return 1;
break;
default:
@@ -125,7 +134,7 @@
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Invalid packet\n");
dump_packet(size, recv_buf);
-
+ return 1;
break;
}
}
--- a/command.h
+++ b/command.h
@@ -51,6 +51,6 @@
};
-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
--- a/input.c
+++ b/input.c
@@ -2,8 +2,6 @@
// Released under the MIT licence, https://opensource.org/licenses/MIT
#include <SDL2/SDL.h>
-#include <SDL2/SDL_events.h>
-#include <SDL2/SDL_gamecontroller.h>
#include <stdio.h>
#include "input.h"
@@ -44,7 +42,8 @@
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 @@
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 @@
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 @@
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 @@
// 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
--- a/input.h
+++ b/input.h
@@ -13,7 +13,8 @@
} 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 {--- 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 @@
}
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 @@
// 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 @@
render_screen();
usleep(100);
}
-
}
// exit, clean up
--- a/slip.c
+++ b/slip.c
@@ -77,7 +77,9 @@
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:
--- a/slip.h
+++ b/slip.h
@@ -46,14 +46,12 @@
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 @@
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);
--- a/write.c
+++ b/write.c
@@ -7,10 +7,26 @@
#include <stdio.h>
#include <unistd.h>
-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;
@@ -17,17 +33,13 @@
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;
}
--- a/write.h
+++ b/write.h
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <libserialport.h>
+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);
--
⑨