ref: 77d211a56fd2689b5927e1aaa9f316d2d7848f4c
parent: ade0037a6fcb50567e156bf59cdbfb28543de39f
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Mon Mar 17 08:19:50 EDT 2025
refactor serial stuff outside main
--- a/.github/workflows/build-ubuntu.yml
+++ b/.github/workflows/build-ubuntu.yml
@@ -30,7 +30,7 @@
id: cache-x86_64-sdl3-files
uses: actions/cache@v4
with:
- path: 'SDL3-${{ env.SDL_VERSION }}'+ path: 'SDL3-3.2.8'
key: linux-x86_64-sdl3-files
- name: 'Download SDL3 sources'
--- a/.github/workflows/build-windows.yml
+++ b/.github/workflows/build-windows.yml
@@ -43,7 +43,7 @@
id: cache-sdl3-files
uses: actions/cache@v4
with:
- path: 'SDL3-3.2.4'
+ path: 'SDL3-3.2.8'
key: win-sdl3-files-${{ matrix.sys }}- name: 'Download SDL3 sources'
--- a/Makefile
+++ b/Makefile
@@ -8,7 +8,9 @@
INCLUDES = $(shell pkg-config --libs sdl3 libserialport | sed 's/-mwindows//')
#Set any compiler flags you want to use (e.g. -I/usr/include/somefolder `pkg-config --cflags gtk+-3.0` ), or leave blank
-local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 libserialport) -Wall -Wextra -O2 -pipe -I.
+local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 libserialport) -DUSE_LIBSERIALPORT -Wall -Wextra -O2 -pipe -I.
+# local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 libserialport) -DUSE_RTMIDI -Wall -Wextra -O2 -pipe -I.
+
#Set the compiler you are using ( gcc for C or g++ for C++ )
CC = gcc
--- a/src/main.c
+++ b/src/main.c
@@ -24,10 +24,57 @@
uint8_t need_display_reset = 0;
// Handles CTRL+C / SIGINT
-void intHandler() { run = QUIT; }+void signal_handler() { run = QUIT; }-void close_serial_port() { disconnect(); }+int process_inputs(config_params_s conf) {+ static uint8_t prev_input = 0;
+ static uint8_t prev_note = 0;
+ // get current inputs
+ const input_msg_s input = get_input_msg(&conf);
+
+ switch (input.type) {+ case normal:
+ if (input.value != prev_input) {+ prev_input = input.value;
+ send_msg_controller(input.value);
+ }
+ break;
+ case keyjazz:
+ if (input.value != 0) {+ if (input.eventType == SDL_EVENT_KEY_DOWN && input.value != prev_input) {+ send_msg_keyjazz(input.value, input.value2);
+ prev_note = input.value;
+ } else if (input.eventType == SDL_EVENT_KEY_UP && input.value == prev_note) {+ send_msg_keyjazz(0xFF, 0);
+ }
+ }
+ prev_input = input.value;
+ break;
+ case special:
+ if (input.value != prev_input) {+ prev_input = input.value;
+ switch (input.value) {+ case msg_quit:
+ SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Received msg_quit from input device.");
+ run = 0;
+ break;
+ case msg_reset_display:
+ reset_display();
+ break;
+ case msg_toggle_audio:
+ conf.audio_enabled = !conf.audio_enabled;
+ toggle_audio(conf.audio_device_name, conf.audio_buffer_size);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
int main(const int argc, char *argv[]) { if (argc == 2 && SDL_strcmp(argv[1], "--list") == 0) {@@ -35,10 +82,12 @@
}
char *preferred_device = NULL;
+#ifdef USE_LIBSERIALPORT // Device selection should be only available with libserialport
if (argc == 3 && SDL_strcmp(argv[1], "--dev") == 0) {preferred_device = argv[2];
SDL_Log("Using preferred device %s.\n", preferred_device);}
+#endif
char *config_filename = NULL;
if (argc == 3 && SDL_strcmp(argv[1], "--config") == 0) {@@ -51,33 +100,13 @@
config_params_s conf = init_config(config_filename);
read_config(&conf);
- // allocate memory for serial buffer
- uint8_t *serial_buf = SDL_malloc(serial_read_size);
-
- static uint8_t slip_buffer[serial_read_size]; // SLIP command buffer
- SDL_zero(slip_buffer);
-
- // settings for the slip packet handler
- static const slip_descriptor_s slip_descriptor = {- .buf = slip_buffer,
- .buf_size = sizeof(slip_buffer),
- .recv_message = process_command, // the function where complete slip
- // packets are processed further
- };
-
- static slip_handler_s slip;
-
- uint8_t prev_input = 0;
- uint8_t prev_note = 0;
- uint16_t zerobyte_packets = 0; // used to detect device disconnection
uint8_t port_inited = 0;
- signal(SIGINT, intHandler);
- signal(SIGTERM, intHandler);
+ signal(SIGINT, signal_handler);
+ signal(SIGTERM, signal_handler);
#ifdef SIGQUIT
- signal(SIGQUIT, intHandler);
+ signal(SIGQUIT, signal_handler);
#endif
- slip_init(&slip, &slip_descriptor);
// First device detection to avoid SDL init if it isn't necessary. To be run
// only if we shouldn't wait for M8 to be connected.
@@ -84,7 +113,6 @@
if (conf.wait_for_device == 0) {port_inited = init_serial(1, preferred_device);
if (port_inited == 0) {- SDL_free(serial_buf);
return 1;
}
}
@@ -91,7 +119,6 @@
// initialize all SDL systems
if (initialize_sdl(conf.init_fullscreen) == false) {- SDL_free(serial_buf);
SDL_Quit();
return 1;
}
@@ -139,7 +166,7 @@
// get current input
const input_msg_s input = get_input_msg(&conf);
if (input.type == special && input.value == msg_quit) {- SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Input message QUIT.");
+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Input message QUIT.");
run = QUIT;
}
@@ -185,7 +212,6 @@
gamecontrollers_close();
close_renderer();
kill_inline_font();
- SDL_free(serial_buf);
SDL_Quit();
return -1;
}
@@ -193,99 +219,16 @@
// main loop
while (run == RUN) {+ process_inputs(conf);
- // get current inputs
- const input_msg_s input = get_input_msg(&conf);
-
- switch (input.type) {- case normal:
- if (input.value != prev_input) {- prev_input = input.value;
- send_msg_controller(input.value);
- }
- break;
- case keyjazz:
- if (input.value != 0) {- if (input.eventType == SDL_EVENT_KEY_DOWN && input.value != prev_input) {- send_msg_keyjazz(input.value, input.value2);
- prev_note = input.value;
- } else if (input.eventType == SDL_EVENT_KEY_UP && input.value == prev_note) {- send_msg_keyjazz(0xFF, 0);
- }
- }
- prev_input = input.value;
- break;
- case special:
- if (input.value != prev_input) {- prev_input = input.value;
- switch (input.value) {- case msg_quit:
- SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Received msg_quit from input device.");
- run = 0;
- break;
- case msg_reset_display:
- reset_display();
- break;
- case msg_toggle_audio:
- conf.audio_enabled = !conf.audio_enabled;
- toggle_audio(conf.audio_device_name,conf.audio_buffer_size);
- break;
- default:
- break;
- }
- break;
- }
+ const int result = process_serial(conf);
+ if (result == 0) {+ port_inited = 0;
+ run = WAIT_FOR_DEVICE;
+ audio_destroy();
+ } else if (result == -1) {+ run = QUIT;
}
-
- while (1) {- // read serial port
- const int bytes_read = serial_read(serial_buf, serial_read_size);
- if (bytes_read < 0) {- SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Error %d reading serial.", bytes_read);
- run = QUIT;
- break;
- }
- if (bytes_read > 0) {- // input from device: reset the zero byte counter and create a
- // pointer to the serial buffer
- zerobyte_packets = 0;
- const uint8_t *cur = serial_buf;
- const uint8_t *end = serial_buf + bytes_read;
- while (cur < end) {- // process the incoming bytes into commands and draw them
- const int n = slip_read_byte(&slip, *cur++);
- if (n != SLIP_NO_ERROR) {- if (n == SLIP_ERROR_INVALID_PACKET) {- reset_display();
- } else {- SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", n);
- }
- }
- }
- } else {- // zero byte packet, increment counter
- zerobyte_packets++;
- if (zerobyte_packets > conf.wait_packets) {- zerobyte_packets = 0;
-
- // try opening the serial port to check if it's alive
- if (check_serial_port()) {- // the device is still there, carry on
- break;
- }
- port_inited = 0;
- run = WAIT_FOR_DEVICE;
- close_serial_port();
- if (conf.audio_enabled == 1) {- audio_destroy();
- }
- /* we'll make one more loop to see if the device is still there
- * but just sending zero bytes. if it doesn't get detected when
- * resetting the port, it will disconnect */
- }
- break;
- }
- }
render_screen();
SDL_Delay(conf.idle_ms);
}
@@ -294,14 +237,11 @@
// exit, clean up
SDL_Log("Shutting down");- if (conf.audio_enabled == 1) {- audio_destroy();
- }
+ audio_destroy();
gamecontrollers_close();
close_renderer();
if (port_inited == 1)
- close_serial_port();
- SDL_free(serial_buf);
+ destroy_serial();
SDL_Quit();
return 0;
}
--- a/src/serial.c
+++ b/src/serial.c
@@ -4,7 +4,7 @@
// Contains portions of code from libserialport's examples released to the
// public domain
-#ifndef USE_LIBUSB
+#ifdef USE_LIBSERIALPORT
#include <SDL3/SDL.h>
#include <libserialport.h>
#include <stdio.h>
@@ -12,9 +12,17 @@
#include <string.h>
#include <unistd.h>
+#include "command.h"
#include "serial.h"
+#include "slip.h"
+#include "config.h"
struct sp_port *m8_port = NULL;
+// allocate memory for serial buffers
+static uint8_t serial_buffer[serial_read_size] = {0};+static uint8_t slip_buffer[serial_read_size] = {0};+static slip_handler_s slip;
+static uint16_t zero_byte_packets = 0; // used to detect device disconnection
// Helper function for error handling
static int check(enum sp_return result);
@@ -94,6 +102,17 @@
// Port is already initialized
return 1;
}
+
+ // settings for the slip packet handler
+ static const slip_descriptor_s slip_descriptor = {+ .buf = slip_buffer,
+ .buf_size = sizeof(slip_buffer),
+ .recv_message = process_command, // the function where complete slip
+ // packets are processed further
+ };
+
+ slip_init(&slip, &slip_descriptor);
+
/* A pointer to a null-terminated array of pointers to
* struct sp_port, which will contain the ports found.*/
struct sp_port **port_list;
@@ -264,5 +283,56 @@
}
return 1;
+}
+
+int process_serial(config_params_s conf) {+ while (1) {+ // read serial port
+ const int bytes_read = serial_read(serial_buffer, serial_read_size);
+ if (bytes_read < 0) {+ SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Error %d reading serial.", bytes_read);
+ disconnect();
+ return -1;
+ break;
+ }
+ if (bytes_read > 0) {+ // input from device: reset the zero byte counter and create a
+ // pointer to the serial buffer
+ zero_byte_packets = 0;
+ const uint8_t *cur = serial_buffer;
+ const uint8_t *end = serial_buffer + bytes_read;
+ while (cur < end) {+ // process the incoming bytes into commands and draw them
+ const int n = slip_read_byte(&slip, *cur++);
+ if (n != SLIP_NO_ERROR) {+ if (n == SLIP_ERROR_INVALID_PACKET) {+ reset_display();
+ } else {+ SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", n);
+ }
+ }
+ }
+ } else {+ // zero byte packet, increment counter
+ zero_byte_packets++;
+ if (zero_byte_packets > conf.wait_packets) {+ zero_byte_packets = 0;
+
+ // try opening the serial port to check if it's alive
+ if (check_serial_port()) {+ // the device is still there, carry on
+ break;
+ }
+ disconnect();
+ return 0;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
+int destroy_serial() {+ return disconnect();
}
#endif
--- a/src/serial.h
+++ b/src/serial.h
@@ -3,18 +3,16 @@
#ifndef _SERIAL_H_
#define _SERIAL_H_
+#ifdef USE_LIBSERIALPORT
+
#include <stdint.h>
+#include "config.h"
-#ifdef USE_LIBUSB
-// Max packet length of the USB endpoint
-#define serial_read_size 1024
-int init_serial_with_file_descriptor(int file_descriptor);
-#else
// maximum amount of bytes to read from the serial in one read()
#define serial_read_size 1024
-#endif
int init_serial(int verbose, const char *preferred_device);
+int destroy_serial();
int list_devices();
int check_serial_port();
int reset_display();
@@ -23,5 +21,7 @@
int serial_read(uint8_t *serial_buf, int count);
int send_msg_controller(uint8_t input);
int send_msg_keyjazz(uint8_t note, uint8_t velocity);
+int process_serial(config_params_s conf);
+#endif
#endif
--- a/src/usb.h
+++ b/src/usb.h
@@ -4,6 +4,6 @@
#include <libusb.h>
extern libusb_device_handle *devh;
-
+int init_serial_with_file_descriptor(int file_descriptor);
#endif // USE_LIBUSB
#endif // M8C_USB_H_
--
⑨