ref: 42872cf9dd18c5f9d29add8c1b4e3668b90d6ede
parent: ade0037a6fcb50567e156bf59cdbfb28543de39f
parent: dc9503f082e21098218c2657a3a15c32c2d39b76
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Sun Mar 23 12:47:50 EDT 2025
Merge pull request #186 from laamaa/rtmidi Refactor systems that handle device connection related things, add MIDI sysex backend
--- a/.github/workflows/build-macos-arm.yml
+++ b/.github/workflows/build-macos-arm.yml
@@ -28,7 +28,7 @@
id: buildApplication
continue-on-error: true
run: |
- mkdir -p build_arm64 && cd build_arm64 && cmake .. && cpack -V
+ mkdir -p build_arm64 && cd build_arm64 && cmake .. -DCMAKE_BUILD_TYPE=Release && cpack -V
- name: 'View debug log if compilation fails'
if: failure() && steps.buildApplication.outcome == 'failure'
--- a/.github/workflows/build-macos-intel.yml
+++ b/.github/workflows/build-macos-intel.yml
@@ -24,7 +24,7 @@
id: buildApplication
continue-on-error: true
run: |
- mkdir -p build_x86_64 && cd build_x86_64 && cmake .. && cpack -V
+ mkdir -p build_x86_64 && cd build_x86_64 && cmake .. -DCMAKE_BUILD_TYPE=Release && cpack -V
- name: 'View debug log if compilation fails'
if: failure() && steps.buildApplication.outcome == 'failure'
--- 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'
@@ -45,8 +45,13 @@
run: |
pushd SDL3-$SDL_VERSION
mkdir build_x86_64
- cmake -S . -B build_x86_64
+ cmake -S . -B build_x86_64 -DCMAKE_BUILD_TYPE=Release
cmake --build build_x86_64
+ popd
+
+ - name: 'Install SDL3'
+ run: |
+ pushd SDL3-$SDL_VERSION
sudo cmake --install build_x86_64
popd
--- 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'
@@ -95,7 +95,7 @@
- name: 'Build package'
run: |
- cmake . -G Ninja -DCMAKE_PREFIX_PATH=C:/Libraries
+ cmake . -G Ninja -DCMAKE_PREFIX_PATH=C:/Libraries -DCMAKE_BUILD_TYPE=Release
cmake --build .
strip -g m8c.exe
if [ ${{ matrix.win }} == "win32" ]--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,25 +2,35 @@
project(m8c LANGUAGES C)
-set(CMAKE_C_FLAGS "-O2 -Wall -Wextra")
-
set(APP_NAME m8c)
+if (NOT DEFINED USE_LIBSERIALPORT AND NOT DEFINED USE_LIBUSB AND NOT DEFINED USE_RTMIDI)
+ set(USE_LIBSERIALPORT 1)
+endif ()
+
find_package(PkgConfig REQUIRED)
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3)
pkg_check_modules(SDL3 REQUIRED sdl3)
+if (USE_LIBSERIALPORT)
+ pkg_check_modules(LIBSERIALPORT REQUIRED libserialport)
+ link_directories(${SDL3_LIBRARY_DIRS} ${LIBSERIALPORT_LIBRARY_DIRS})+ add_compile_definitions(USE_LIBSERIALPORT)
+endif (USE_LIBSERIALPORT)
if (USE_LIBUSB)
pkg_check_modules(LIBUSB REQUIRED libusb-1.0)
link_directories(${SDL3_LIBRARY_DIRS} ${LIBUSB_LIBRARY_DIRS})add_compile_definitions(USE_LIBUSB)
-else ()
- pkg_check_modules(LIBSERIALPORT REQUIRED libserialport)
- link_directories(${SDL3_LIBRARY_DIRS} ${LIBSERIALPORT_LIBRARY_DIRS})endif (USE_LIBUSB)
+if (USE_RTMIDI)
+ pkg_check_modules(RTMIDI REQUIRED rtmidi)
+ link_directories(${SDL3_LIBRARY_DIRS} ${RTMIDI_LIBRARY_DIRS})+ add_compile_definitions(USE_RTMIDI)
+endif (USE_RTMIDI)
-file(GLOB m8c_SRC "src/*.h" "src/*.c")
+file(GLOB m8c_SRC "src/*.h" "src/*.c" "src/backends/*.h" "src/backends/*.c" "src/fonts/*.h")
+
set(MACOS_CONTENTS "${CMAKE_CURRENT_SOURCE_DIR}/package/macos/m8c.app/Contents") set(APP_ICON ${MACOS_CONTENTS}/Resources/m8c.icns)@@ -29,22 +39,30 @@
add_executable(${APP_NAME} WIN32 MACOSX_BUNDLE ${APP_ICON} ${m8c_SRC})+if (USE_LIBSERIALPORT)
+ target_link_libraries(${APP_NAME} ${SDL3_LIBRARIES} ${LIBSERIALPORT_LIBRARIES})+ target_include_directories(${APP_NAME} PUBLIC ${SDL3_INCLUDE_DIRS} ${LIBSERIALPORT_INCLUDE_DIRS})+ target_compile_options(${APP_NAME} PUBLIC ${SDL3_CFLAGS_OTHER} ${LIBSERIALPORT_CFLAGS_OTHER})+endif ()
+
if (USE_LIBUSB)
target_link_libraries(${APP_NAME} ${SDL3_LIBRARIES} ${LIBUSB_LIBRARIES}) target_include_directories(${APP_NAME} PUBLIC ${SDL3_INCLUDE_DIRS} ${LIBUSB_INCLUDE_DIRS}) target_compile_options(${APP_NAME} PUBLIC ${SDL3_CFLAGS_OTHER} ${LIBUSB_CFLAGS_OTHER})-else ()
- target_link_libraries(${APP_NAME} ${SDL3_LIBRARIES} ${LIBSERIALPORT_LIBRARIES})- target_include_directories(${APP_NAME} PUBLIC ${SDL3_INCLUDE_DIRS} ${LIBSERIALPORT_INCLUDE_DIRS})- target_compile_options(${APP_NAME} PUBLIC ${SDL3_CFLAGS_OTHER} ${LIBSERIALPORT_CFLAGS_OTHER})endif ()
+if (USE_RTMIDI)
+ target_link_libraries(${APP_NAME} ${SDL3_LIBRARIES} ${RTMIDI_LIBRARIES})+ target_include_directories(${APP_NAME} PUBLIC ${SDL3_INCLUDE_DIRS} ${RTMIDI_INCLUDE_DIRS})+ target_compile_options(${APP_NAME} PUBLIC ${SDL3_CFLAGS_OTHER} ${RTMIDI_CFLAGS_OTHER})+endif ()
+
if (APPLE)
# Destination paths below are relative to ${CMAKE_INSTALL_PREFIX} install(TARGETS ${APP_NAME}BUNDLE DESTINATION . COMPONENT Runtime
RUNTIME DESTINATION bin COMPONENT Runtime
- )
+ )
set_target_properties(${APP_NAME} PROPERTIESMACOSX_BUNDLE TRUE
--- a/Makefile
+++ b/Makefile
@@ -1,14 +1,43 @@
#Set all your object files (the object files of all the .c files in your project, e.g. main.o my_sub_functions.o )
-OBJ = src/main.o src/serial.o src/slip.o src/command.o src/render.o src/ini.o src/config.o src/input.o src/gamecontrollers.o src/fx_cube.o src/usb.o src/audio.o src/usb_audio.o src/ringbuffer.o src/inprint2.o
+OBJ = src/main.o \
+src/command.o \
+src/config.o \
+src/fx_cube.o \
+src/gamecontrollers.o \
+src/ini.o \
+src/inprint2.o \
+src/input.o \
+src/backends/queue.o \
+src/render.o \
+src/backends/audio_sdl.o \
+src/backends/audio_libusb.o \
+src/backends/m8_libserialport.o \
+src/backends/m8_libusb.o \
+src/backends/m8_rtmidi.o \
+src/backends/ringbuffer.o \
+src/backends/slip.o \
#Set any dependant header files so that if they are edited they cause a complete re-compile (e.g. main.h some_subfunctions.h some_definitions_file.h ), or leave blank
-DEPS = src/serial.h src/slip.h src/command.h src/render.h src/ini.h src/config.h src/input.h src/gamecontrollers.h src/fx_cube.h src/audio.h src/ringbuffer.h src/inline_font.h
+DEPS = \
+src/command.h \
+src/config.h \
+src/fx_cube.h \
+src/gamecontrollers.h \
+src/ini.h \
+src/input.h \
+src/render.h \
+src/backends/audio.h \
+src/backends/m8.h \
+src/backends/ringbuffer.h \
+src/backends/queue.h \
+src/backends/slip.h \
+src/fonts/inline_font.h
#Any special libraries you are using in your project (e.g. -lbcm2835 -lrt `pkg-config --libs gtk+-3.0` ), or leave blank
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. -DNDEBUG
#Set the compiler you are using ( gcc for C or g++ for C++ )
CC = gcc
@@ -28,14 +57,18 @@
$(CC) -o $@ $^ $(local_CFLAGS) $(INCLUDES)
libusb: INCLUDES = $(shell pkg-config --libs sdl3 libusb-1.0)
-libusb: local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 libusb-1.0) -Wall -O2 -pipe -I. -DUSE_LIBUSB=1
+libusb: local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 libusb-1.0) -Wall -Wextra -O2 -pipe -I. -DUSE_LIBUSB=1 -DNDEBUG
libusb: m8c
+rtmidi: INCLUDES = $(shell pkg-config --libs sdl3 rtmidi)
+rtmidi: local_CFLAGS = $(CFLAGS) $(shell pkg-config --cflags sdl3 rtmidi) -Wall -Wextra -O2 -pipe -I. -DUSE_RTMIDI -DNDEBUG
+rtmidi: m8c
+
#Cleanup
.PHONY: clean
clean:
- rm -f src/*.o *~ m8c
+ rm -f src/*.o src/backends/*.o *~ m8c
# PREFIX is environment variable, but if it is not set, then set default value
ifeq ($(PREFIX),)
--- a/src/SDL2_inprint.h
+++ b/src/SDL2_inprint.h
@@ -4,13 +4,13 @@
#ifndef SDL2_inprint_h
#define SDL2_inprint_h
-#include "inline_font.h"
+#include "fonts/inline_font.h"
#include <SDL3/SDL.h>
-extern void prepare_inline_font(struct inline_font *font);
-extern void kill_inline_font(void);
+extern void inline_font_initialize(struct inline_font *font);
+extern void inline_font_close(void);
-extern void inrenderer(SDL_Renderer *renderer);
+extern void inline_font_set_renderer(SDL_Renderer *renderer);
extern void infont(SDL_Texture *font);
extern void incolor1(const SDL_Color *color);
extern void incolor(Uint32 color); /* Color must be in 0x00RRGGBB format ! */
--- a/src/audio.c
+++ /dev/null
@@ -1,159 +1,0 @@
-// Copyright 2021 Jonne Kokkonen
-// Released under the MIT licence, https://opensource.org/licenses/MIT
-#ifndef USE_LIBUSB
-#include "audio.h"
-#include <SDL3/SDL.h>
-#include <stdint.h>
-
-SDL_AudioStream *audio_stream_in, *audio_stream_out;
-
-static unsigned int audio_paused = 0;
-static unsigned int audio_initialized = 0;
-static SDL_AudioSpec audio_spec_in = {SDL_AUDIO_S16LE, 2, 44100};-static SDL_AudioSpec audio_spec_out = {SDL_AUDIO_S16LE, 2, 44100};-
-static void SDLCALL audio_cb_out(void *userdata, SDL_AudioStream *stream, int length, int unused) {- // suppress compiler warnings
- (void)userdata;
- (void)length;
- (void)unused;
-
- const int bytes_available = SDL_GetAudioStreamAvailable(audio_stream_in);
- if (bytes_available == -1) {- SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
- "Error getting available audio stream bytes: %s, destroying audio",
- SDL_GetError());
- audio_destroy();
- return;
- }
-
- Uint8 *src_audio_data = SDL_malloc(bytes_available);
- const int bytes_read = SDL_GetAudioStreamData(audio_stream_in, src_audio_data, bytes_available);
- if (bytes_read == bytes_available) {- SDL_PutAudioStreamData(stream, src_audio_data, bytes_read);
- } else {- SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
- "Error getting available audio stream bytes: %s, destroying audio",
- SDL_GetError());
- audio_destroy();
- }
- SDL_free(src_audio_data);
-}
-
-void toggle_audio(const char *output_device_name, unsigned int audio_buffer_size) {- if (!audio_initialized) {- audio_init(output_device_name, audio_buffer_size);
- return;
- }
- if (audio_paused) {- SDL_ResumeAudioStreamDevice(audio_stream_out);
- SDL_ResumeAudioStreamDevice(audio_stream_in);
- } else {- SDL_PauseAudioStreamDevice(audio_stream_in);
- SDL_PauseAudioStreamDevice(audio_stream_out);
- }
- audio_paused = !audio_paused;
- SDL_Log(audio_paused ? "Audio paused" : "Audio resumed");
-}
-
-int audio_init(const char *output_device_name, const unsigned int audio_buffer_size) {-
- // wait for system to initialize possible new audio devices
- SDL_Delay(500);
-
- int num_devices_in, num_devices_out;
- SDL_AudioDeviceID m8_device_id = 0;
- SDL_AudioDeviceID output_device_id = 0;
-
- SDL_AudioDeviceID *devices_in = SDL_GetAudioRecordingDevices(&num_devices_in);
- if (!devices_in) {- SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "No audio capture devices, SDL Error: %s", SDL_GetError());
- return 0;
- }
-
- SDL_AudioDeviceID *devices_out = SDL_GetAudioPlaybackDevices(&num_devices_out);
- if (!devices_out) {- SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "No audio playback devices, SDL Error: %s",
- SDL_GetError());
- return 0;
- }
-
- for (int i = 0; i < num_devices_in; i++) {- const SDL_AudioDeviceID instance_id = devices_in[i];
- const char *device_name = SDL_GetAudioDeviceName(instance_id);
- SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "%s", device_name);
- if (SDL_strstr(device_name, "M8") != NULL) {- SDL_Log("M8 Audio Input device found: %s", device_name);- m8_device_id = instance_id;
- }
- }
-
- if (output_device_name != NULL) {- for (int i = 0; i < num_devices_out; i++) {- const SDL_AudioDeviceID instance_id = devices_out[i];
- const char *device_name = SDL_GetAudioDeviceName(instance_id);
- SDL_LogInfo(SDL_LOG_CATEGORY_AUDIO, "%s", device_name);
- if (SDL_strcasestr(device_name, output_device_name) != NULL) {- SDL_Log("Requested output device found: %s", device_name);- output_device_id = instance_id;
- }
- }
- }
-
- SDL_free(devices_in);
- SDL_free(devices_out);
-
- if (!output_device_id) {- output_device_id = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;
- }
-
- if (!m8_device_id) {- // forget about it
- SDL_Log("Cannot find M8 audio input device");- return 0;
- }
-
- char audio_buffer_size_str[256];
- SDL_snprintf(audio_buffer_size_str, sizeof(audio_buffer_size_str), "%d", audio_buffer_size);
- SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, audio_buffer_size_str);
-
- audio_stream_out =
- SDL_OpenAudioDeviceStream(output_device_id, &audio_spec_out, audio_cb_out, NULL);
-
- if (!audio_stream_out) {- SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Error opening audio output device: %s", SDL_GetError());
- return 0;
- }
- SDL_Log("Audiospec Out: format %d, channels %d, rate %d", audio_spec_out.format,- audio_spec_out.channels, audio_spec_out.freq);
-
- audio_stream_in = SDL_OpenAudioDeviceStream(m8_device_id, &audio_spec_in, NULL, NULL);
- if (!audio_stream_in) {- SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Error opening audio input device: %s", SDL_GetError());
- SDL_DestroyAudioStream(audio_stream_out);
- return 0;
- }
- SDL_Log("Audiospec In: format %d, channels %d, rate %d", audio_spec_in.format,- audio_spec_in.channels, audio_spec_in.freq);
-
- SDL_SetAudioStreamFormat(audio_stream_in, &audio_spec_in, &audio_spec_out);
-
- SDL_ResumeAudioStreamDevice(audio_stream_out);
- SDL_ResumeAudioStreamDevice(audio_stream_in);
-
- audio_paused = 0;
- audio_initialized = 1;
-
- return 1;
-}
-
-void audio_destroy() {- if (!audio_initialized)
- return;
- SDL_Log("Closing audio devices");- SDL_DestroyAudioStream(audio_stream_in);
- SDL_DestroyAudioStream(audio_stream_out);
- audio_initialized = 0;
-}
-
-#endif
--- a/src/audio.h
+++ /dev/null
@@ -1,11 +1,0 @@
-// Copyright 2021 Jonne Kokkonen
-// Released under the MIT licence, https://opensource.org/licenses/MIT
-#ifndef AUDIO_H
-#define AUDIO_H
-
-int audio_init(const char *output_device_name, unsigned int audio_buffer_size);
-void toggle_audio(const char *output_device_name, unsigned int audio_buffer_size);
-void process_audio();
-void audio_destroy();
-
-#endif
--- /dev/null
+++ b/src/backends/audio.h
@@ -1,0 +1,11 @@
+// Copyright 2021 Jonne Kokkonen
+// Released under the MIT licence, https://opensource.org/licenses/MIT
+#ifndef AUDIO_H
+#define AUDIO_H
+
+int audio_initialize(const char *output_device_name, unsigned int audio_buffer_size);
+void audio_toggle(const char *output_device_name, unsigned int audio_buffer_size);
+void audio_process(void);
+void audio_close(void);
+
+#endif
--- /dev/null
+++ b/src/backends/audio_libusb.c
@@ -1,0 +1,206 @@
+#ifdef USE_LIBUSB
+
+#include "m8.h"
+#include "ringbuffer.h"
+#include <SDL3/SDL.h>
+#include <errno.h>
+#include <libusb.h>
+
+#define EP_ISO_IN 0x85
+#define IFACE_NUM 4
+
+#define NUM_TRANSFERS 64
+#define PACKET_SIZE 180
+#define NUM_PACKETS 2
+
+extern libusb_device_handle *devh;
+
+SDL_AudioDeviceID sdl_audio_device_id = 0;
+int audio_initialized = 0;
+RingBuffer *audio_buffer = NULL;
+
+static void audio_callback(void *userdata, Uint8 *stream, int len) {+ uint32_t read_len = ring_buffer_pop(audio_buffer, stream, len);
+
+ if (read_len == -1) {+ SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Buffer underflow!");
+ }
+
+ // If we didn't read the full len bytes, fill the rest with zeros
+ if (read_len < len) {+ SDL_memset(&stream[read_len], 0, len - read_len);
+ }
+}
+
+static void cb_xfr(struct libusb_transfer *xfr) {+ unsigned int i;
+
+ for (i = 0; i < xfr->num_iso_packets; i++) {+ struct libusb_iso_packet_descriptor *pack = &xfr->iso_packet_desc[i];
+
+ if (pack->status != LIBUSB_TRANSFER_COMPLETED) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "XFR callback error (status %d: %s)", pack->status,
+ libusb_error_name(pack->status));
+ /* This doesn't happen, so bail out if it does. */
+ return;
+ }
+
+ const uint8_t *data = libusb_get_iso_packet_buffer_simple(xfr, i);
+ if (sdl_audio_device_id != 0) {+ uint32_t actual = ring_buffer_push(audio_buffer, data, pack->actual_length);
+ if (actual == -1) {+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Buffer overflow!");
+ }
+ }
+ }
+
+ if (libusb_submit_transfer(xfr) < 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "error re-submitting URB\n");
+ SDL_free(xfr->buffer);
+ }
+}
+
+static struct libusb_transfer *xfr[NUM_TRANSFERS];
+
+static int benchmark_in() {+ int i;
+
+ for (i = 0; i < NUM_TRANSFERS; i++) {+ xfr[i] = libusb_alloc_transfer(NUM_PACKETS);
+ if (!xfr[i]) {+ SDL_Log("Could not allocate transfer");+ return -ENOMEM;
+ }
+
+ Uint8 *buffer = SDL_malloc(PACKET_SIZE * NUM_PACKETS);
+
+ libusb_fill_iso_transfer(xfr[i], devh, EP_ISO_IN, buffer, PACKET_SIZE * NUM_PACKETS,
+ NUM_PACKETS, cb_xfr, NULL, 0);
+ libusb_set_iso_packet_lengths(xfr[i], PACKET_SIZE);
+
+ libusb_submit_transfer(xfr[i]);
+ }
+
+ return 1;
+}
+
+int audio_initialize(int audio_buffer_size, const char *output_device_name) {+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO,"LIBUSB audio not implemented yet");
+ return -1;
+ /*
+ SDL_Log("USB audio setup");+
+ int rc;
+
+ rc = libusb_kernel_driver_active(devh, IFACE_NUM);
+ if (rc == 1) {+ SDL_Log("Detaching kernel driver");+ rc = libusb_detach_kernel_driver(devh, IFACE_NUM);
+ if (rc < 0) {+ SDL_Log("Could not detach kernel driver: %s\n", libusb_error_name(rc));+ return rc;
+ }
+ }
+
+ rc = libusb_claim_interface(devh, IFACE_NUM);
+ if (rc < 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error claiming interface: %s\n", libusb_error_name(rc));
+ return rc;
+ }
+
+ rc = libusb_set_interface_alt_setting(devh, IFACE_NUM, 1);
+ if (rc < 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error setting alt setting: %s\n", libusb_error_name(rc));
+ return rc;
+ }
+
+ if (!SDL_WasInit(SDL_INIT_AUDIO)) {+ if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Init audio failed %s", SDL_GetError());
+ return -1;
+ }
+ } else {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Audio was already initialised");
+ }
+
+ static SDL_AudioSpec audio_spec;
+ audio_spec.format = SDL_AUDIO_S16;
+ audio_spec.channels = 2;
+ audio_spec.freq = 44100;
+ audio_spec.samples = audio_buffer_size;
+ audio_spec.callback = audio_callback;
+
+ SDL_AudioSpec _obtained;
+ SDL_zero(_obtained);
+
+ SDL_Log("Current audio driver is %s and device %s", SDL_GetCurrentAudioDriver(),+ output_device_name);
+
+ if (SDL_strcasecmp(SDL_GetCurrentAudioDriver(), "openslES") == 0 || output_device_name == NULL) {+ SDL_Log("Using default audio device");+ sdl_audio_device_id = SDL_OpenAudioDevice(NULL, 0, &audio_spec, &_obtained, 0);
+ } else {+ sdl_audio_device_id = SDL_OpenAudioDevice(output_device_name, 0, &audio_spec, &_obtained, 0);
+ }
+
+ audio_buffer = ring_buffer_create(4 * _obtained.size);
+
+ SDL_Log("Obtained audio spec. Sample rate: %d, channels: %d, samples: %d, size: %d",+ _obtained.freq, _obtained.channels, _obtained.samples, +_obtained.size);
+
+ SDL_PauseAudioDevice(sdl_audio_device_id, 0);
+
+ // Good to go
+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Starting capture");
+ if ((rc = benchmark_in()) < 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Capture failed to start: %d", rc);
+ return rc;
+ }
+
+ SDL_Log("Successful init");+ return 1;
+ */
+}
+
+void audio_close() {+ if (devh == NULL || !audio_initialized) {+ return;
+ }
+
+ SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "Closing audio");
+
+ int rc;
+
+ for (int i = 0; i < NUM_TRANSFERS; i++) {+ rc = libusb_cancel_transfer(xfr[i]);
+ if (rc < 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error cancelling transfer: %s\n",
+ libusb_error_name(rc));
+ }
+ }
+
+ SDL_Log("Freeing interface %d", IFACE_NUM);+
+ rc = libusb_release_interface(devh, IFACE_NUM);
+ if (rc < 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error releasing interface: %s\n", libusb_error_name(rc));
+ return;
+ }
+
+ if (sdl_audio_device_id != 0) {+ SDL_Log("Closing audio device %d", sdl_audio_device_id);+ const SDL_AudioDeviceID device = sdl_audio_device_id;
+ sdl_audio_device_id = 0;
+ SDL_CloseAudioDevice(device);
+ }
+
+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Audio closed");
+
+ ring_buffer_free(audio_buffer);
+}
+
+void audio_toggle(unsigned int audio_buffer_size, const char *output_device_name) {+ SDL_Log("Libusb audio toggling not implemented yet");+}
+
+#endif
--- /dev/null
+++ b/src/backends/audio_sdl.c
@@ -1,0 +1,163 @@
+// Copyright 2021 Jonne Kokkonen
+// Released under the MIT licence, https://opensource.org/licenses/MIT
+#ifndef USE_LIBUSB
+#include "audio.h"
+#include <SDL3/SDL.h>
+#include <stdint.h>
+
+SDL_AudioStream *audio_stream_in, *audio_stream_out;
+
+static unsigned int audio_paused = 0;
+static unsigned int audio_initialized = 0;
+static SDL_AudioSpec audio_spec_in = {SDL_AUDIO_S16LE, 2, 44100};+static SDL_AudioSpec audio_spec_out = {SDL_AUDIO_S16LE, 2, 44100};+
+static void SDLCALL audio_cb_out(void *userdata, SDL_AudioStream *stream, int length, int unused) {+ // suppress compiler warnings
+ (void)userdata;
+ (void)length;
+ (void)unused;
+
+ const int bytes_available = SDL_GetAudioStreamAvailable(audio_stream_in);
+ if (bytes_available == -1) {+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
+ "Error getting available audio stream bytes: %s, destroying audio",
+ SDL_GetError());
+ audio_close();
+ return;
+ }
+
+ Uint8 *src_audio_data = SDL_malloc(bytes_available);
+ const int bytes_read = SDL_GetAudioStreamData(audio_stream_in, src_audio_data, bytes_available);
+ if (bytes_read == bytes_available) {+ SDL_PutAudioStreamData(stream, src_audio_data, bytes_read);
+ } else {+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO,
+ "Error getting available audio stream bytes: %s, destroying audio",
+ SDL_GetError());
+ audio_close();
+ }
+ SDL_free(src_audio_data);
+}
+
+void audio_toggle(const char *output_device_name, unsigned int audio_buffer_size) {+ if (!audio_initialized) {+ audio_initialize(output_device_name, audio_buffer_size);
+ return;
+ }
+ if (audio_paused) {+ SDL_ResumeAudioStreamDevice(audio_stream_out);
+ SDL_ResumeAudioStreamDevice(audio_stream_in);
+ } else {+ SDL_PauseAudioStreamDevice(audio_stream_in);
+ SDL_PauseAudioStreamDevice(audio_stream_out);
+ }
+ audio_paused = !audio_paused;
+ SDL_Log(audio_paused ? "Audio paused" : "Audio resumed");
+}
+
+int audio_initialize(const char *output_device_name, const unsigned int audio_buffer_size) {+
+ // wait for system to initialize possible new audio devices
+ SDL_Delay(500);
+
+ int num_devices_in, num_devices_out;
+ SDL_AudioDeviceID m8_device_id = 0;
+ SDL_AudioDeviceID output_device_id = 0;
+
+ SDL_AudioDeviceID *devices_in = SDL_GetAudioRecordingDevices(&num_devices_in);
+ if (!devices_in) {+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "No audio capture devices, SDL Error: %s", SDL_GetError());
+ return 0;
+ }
+
+ SDL_AudioDeviceID *devices_out = SDL_GetAudioPlaybackDevices(&num_devices_out);
+ if (!devices_out) {+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "No audio playback devices, SDL Error: %s",
+ SDL_GetError());
+ return 0;
+ }
+
+ SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "Audio input devices:");
+ for (int i = 0; i < num_devices_in; i++) {+ const SDL_AudioDeviceID instance_id = devices_in[i];
+ const char *device_name = SDL_GetAudioDeviceName(instance_id);
+ SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "%s", device_name);
+ if (SDL_strstr(device_name, "M8") != NULL) {+ SDL_Log("M8 Audio Input device found: %s", device_name);+ m8_device_id = instance_id;
+ }
+ }
+
+ if (output_device_name != NULL) {+ for (int i = 0; i < num_devices_out; i++) {+ const SDL_AudioDeviceID instance_id = devices_out[i];
+ const char *device_name = SDL_GetAudioDeviceName(instance_id);
+ SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "%s", device_name);
+ if (SDL_strcasestr(device_name, output_device_name) != NULL) {+ SDL_Log("Requested output device found: %s", device_name);+ output_device_id = instance_id;
+ }
+ }
+ }
+
+ SDL_free(devices_in);
+ SDL_free(devices_out);
+
+ if (!output_device_id) {+ output_device_id = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK;
+ }
+
+ if (!m8_device_id) {+ // forget about it
+ SDL_Log("Cannot find M8 audio input device");+ return 0;
+ }
+
+ char audio_buffer_size_str[256];
+ SDL_snprintf(audio_buffer_size_str, sizeof(audio_buffer_size_str), "%d", audio_buffer_size);
+ if (audio_buffer_size > 0) {+ SDL_Log("Setting requested audio device sample frames to %d", audio_buffer_size);+ SDL_SetHint(SDL_HINT_AUDIO_DEVICE_SAMPLE_FRAMES, audio_buffer_size_str);
+ }
+
+ audio_stream_out =
+ SDL_OpenAudioDeviceStream(output_device_id, &audio_spec_out, audio_cb_out, NULL);
+
+ if (!audio_stream_out) {+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Error opening audio output device: %s", SDL_GetError());
+ return 0;
+ }
+ SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "Audiospec Out: format %d, channels %d, rate %d",
+ audio_spec_out.format, audio_spec_out.channels, audio_spec_out.freq);
+
+ audio_stream_in = SDL_OpenAudioDeviceStream(m8_device_id, &audio_spec_in, NULL, NULL);
+ if (!audio_stream_in) {+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Error opening audio input device: %s", SDL_GetError());
+ SDL_DestroyAudioStream(audio_stream_out);
+ return 0;
+ }
+ SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "Audiospec In: format %d, channels %d, rate %d",
+ audio_spec_in.format, audio_spec_in.channels, audio_spec_in.freq);
+
+ SDL_SetAudioStreamFormat(audio_stream_in, &audio_spec_in, &audio_spec_out);
+
+ SDL_ResumeAudioStreamDevice(audio_stream_out);
+ SDL_ResumeAudioStreamDevice(audio_stream_in);
+
+ audio_paused = 0;
+ audio_initialized = 1;
+
+ return 1;
+}
+
+void audio_close() {+ if (!audio_initialized)
+ return;
+ SDL_Log("Closing audio devices");+ SDL_DestroyAudioStream(audio_stream_in);
+ SDL_DestroyAudioStream(audio_stream_out);
+ audio_initialized = 0;
+}
+
+#endif
--- /dev/null
+++ b/src/backends/m8.h
@@ -1,0 +1,17 @@
+// Copyright 2021 Jonne Kokkonen
+// Released under the MIT licence, https://opensource.org/licenses/MIT
+#ifndef _M8_H_
+#define _M8_H_
+
+#include "../config.h"
+
+int m8_initialize(int verbose, const char *preferred_device);
+int m8_list_devices(void);
+int m8_reset_display(void);
+int m8_enable_and_reset_display(void);
+int m8_send_msg_controller(const unsigned char input);
+int m8_send_msg_keyjazz(const unsigned char note, unsigned char velocity);
+int m8_process_data(config_params_s conf);
+int m8_close(void);
+
+#endif
\ No newline at end of file
--- /dev/null
+++ b/src/backends/m8_libserialport.c
@@ -1,0 +1,334 @@
+// Copyright 2021 Jonne Kokkonen
+// Released under the MIT licence, https://opensource.org/licenses/MIT
+
+// Contains portions of code from libserialport's examples released to the
+// public domain
+
+#ifdef USE_LIBSERIALPORT
+#include <SDL3/SDL.h>
+#include <libserialport.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../command.h"
+#include "../config.h"
+#include "m8.h"
+#include "slip.h"
+
+// maximum amount of bytes to read from the serial in one read()
+#define serial_read_size 1024
+
+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
+
+SDL_Thread *serial_thread = NULL;
+
+// Helper function for error handling
+static int check(enum sp_return result);
+
+static int detect_m8_serial_device(const struct sp_port *m8_port) {+ // Check the connection method - we want USB serial devices
+ const enum sp_transport transport = sp_get_port_transport(m8_port);
+
+ if (transport == SP_TRANSPORT_USB) {+ // Get the USB vendor and product IDs.
+ int usb_vid, usb_pid;
+ sp_get_port_usb_vid_pid(m8_port, &usb_vid, &usb_pid);
+
+ if (usb_vid == 0x16C0 && usb_pid == 0x048A)
+ return 1;
+ }
+
+ return 0;
+}
+
+int m8_list_devices() {+ struct sp_port **port_list;
+ const enum sp_return result = sp_list_ports(&port_list);
+
+ if (result != SP_OK) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "sp_list_ports() failed!\n");
+ abort();
+ }
+
+ for (int i = 0; port_list[i] != NULL; i++) {+ const struct sp_port *port = port_list[i];
+
+ if (detect_m8_serial_device(port)) {+ SDL_Log("Found M8 device: %s", sp_get_port_name(port));+ }
+ }
+
+ sp_free_port_list(port_list);
+ return 0;
+}
+
+// Checks for connected devices and whether the specified device still exists
+int check_serial_port() {+ int device_found = 0;
+
+ /* A pointer to a null-terminated array of pointers to
+ * struct sp_port, which will contain the ports found.*/
+ struct sp_port **port_list;
+
+ /* Call sp_list_ports() to get the ports. The port_list
+ * pointer will be updated to refer to the array created. */
+ const enum sp_return result = sp_list_ports(&port_list);
+
+ if (result != SP_OK) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "sp_list_ports() failed!\n");
+ abort();
+ }
+
+ /* Iterate through the ports. When port_list[i] is NULL
+ * this indicates the end of the list. */
+ for (int i = 0; port_list[i] != NULL; i++) {+ const struct sp_port *port = port_list[i];
+
+ if (detect_m8_serial_device(port)) {+ if (strcmp(sp_get_port_name(port), sp_get_port_name(m8_port)) == 0)
+ device_found = 1;
+ }
+ }
+
+ sp_free_port_list(port_list);
+ return device_found;
+}
+
+int m8_initialize(const int verbose, const char *preferred_device) {+ if (m8_port != NULL) {+ // 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;
+
+ if (verbose)
+ SDL_Log("Looking for USB serial devices.\n");+
+ /* Call sp_list_ports() to get the ports. The port_list
+ * pointer will be updated to refer to the array created. */
+ enum sp_return result = sp_list_ports(&port_list);
+
+ if (result != SP_OK) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "sp_list_ports() failed!\n");
+ abort();
+ }
+
+ /* Iterate through the ports. When port_list[i] is NULL
+ * this indicates the end of the list. */
+ for (int i = 0; port_list[i] != NULL; i++) {+ const struct sp_port *port = port_list[i];
+
+ if (detect_m8_serial_device(port)) {+ char *port_name = sp_get_port_name(port);
+ SDL_Log("Found M8 in %s.\n", port_name);+ sp_copy_port(port, &m8_port);
+ if (preferred_device != NULL && strcmp(preferred_device, port_name) == 0) {+ SDL_Log("Found preferred device, breaking");+ break;
+ }
+ }
+ }
+
+ sp_free_port_list(port_list);
+
+ if (m8_port != NULL) {+ // Open the serial port and configure it
+ SDL_Log("Opening port.");+
+ result = sp_open(m8_port, SP_MODE_READ_WRITE);
+ if (check(result) != SP_OK)
+ return 0;
+
+ result = sp_set_baudrate(m8_port, 115200);
+ if (check(result) != SP_OK)
+ return 0;
+
+ result = sp_set_bits(m8_port, 8);
+ if (check(result) != SP_OK)
+ return 0;
+
+ result = sp_set_parity(m8_port, SP_PARITY_NONE);
+ if (check(result) != SP_OK)
+ return 0;
+
+ result = sp_set_stopbits(m8_port, 1);
+ if (check(result) != SP_OK)
+ return 0;
+
+ result = sp_set_flowcontrol(m8_port, SP_FLOWCONTROL_NONE);
+ if (check(result) != SP_OK)
+ return 0;
+ } else {+ if (verbose) {+ SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "Cannot find a M8.\n");
+ }
+ return 0;
+ }
+
+ return 1;
+}
+
+// Helper function for error handling.
+static int check(const enum sp_return result) {+ char *error_message;
+
+ switch (result) {+ case SP_ERR_ARG:
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid argument.\n");
+ break;
+ case SP_ERR_FAIL:
+ error_message = sp_last_error_message();
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Failed: %s\n", error_message);
+ sp_free_error_message(error_message);
+ break;
+ case SP_ERR_SUPP:
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Not supported.\n");
+ break;
+ case SP_ERR_MEM:
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Couldn't allocate memory.\n");
+ break;
+ case SP_OK:
+ default:
+ break;
+ }
+ return result;
+}
+
+int m8_reset_display() {+ SDL_Log("Reset display\n");+
+ const char buf[1] = {'R'};+ const int result = sp_blocking_write(m8_port, buf, 1, 5);
+ if (result != 1) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result);
+ return 0;
+ }
+ return 1;
+}
+
+int m8_enable_and_reset_display() {+ SDL_Log("Enabling and resetting M8 display\n");+
+ const char buf[1] = {'E'};+ int result = sp_blocking_write(m8_port, buf, 1, 5);
+ if (result != 1) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error enabling M8 display, code %d", result);
+ return 0;
+ }
+
+ result = m8_reset_display();
+
+ return result;
+}
+
+int disconnect() {+ SDL_Log("Disconnecting M8\n");+
+ const char buf[1] = {'D'};+
+ int result = sp_blocking_write(m8_port, buf, 1, 5);
+ if (result != 1) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending disconnect, code %d", result);
+ result = 0;
+ }
+ sp_close(m8_port);
+ sp_free_port(m8_port);
+ m8_port = NULL;
+ return result;
+}
+
+int serial_read(uint8_t *serial_buf, const int count) {+ return sp_nonblocking_read(m8_port, serial_buf, count);
+}
+
+int m8_send_msg_controller(const uint8_t input) {+ const char buf[2] = {'C', input};+ const size_t nbytes = 2;
+ const int result = sp_blocking_write(m8_port, buf, nbytes, 5);
+ if (result != nbytes) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending input, code %d", result);
+ return -1;
+ }
+ return 1;
+}
+
+int m8_send_msg_keyjazz(const uint8_t note, uint8_t velocity) {+ if (velocity > 0x7F)
+ velocity = 0x7F;
+ const char buf[3] = {'K', note, velocity};+ const size_t nbytes = 3;
+ const int result = sp_blocking_write(m8_port, buf, nbytes, 5);
+ if (result != nbytes) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending keyjazz, code %d", result);
+ return -1;
+ }
+
+ return 1;
+}
+
+int m8_process_data(const 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;
+ }
+ 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) {+ m8_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 m8_close() { return disconnect(); }+#endif
--- /dev/null
+++ b/src/backends/m8_libusb.c
@@ -1,0 +1,367 @@
+// Copyright 2021 Jonne Kokkonen
+// Released under the MIT licence, https://opensource.org/licenses/MIT
+
+// Contains portions of code from libserialport's examples released to the
+// public domain
+#ifdef USE_LIBUSB
+
+#include <SDL3/SDL.h>
+#include <libusb.h>
+#include <stdlib.h>
+#include <string.h>
+
+static int ep_out_addr = 0x03;
+static int ep_in_addr = 0x83;
+
+#define ACM_CTRL_DTR 0x01
+#define ACM_CTRL_RTS 0x02
+
+#define M8_VID 0x16c0
+#define M8_PID 0x048a
+
+libusb_context *ctx = NULL;
+libusb_device_handle *devh = NULL;
+
+static int do_exit = 0;
+
+int m8_list_devices() {+ int r;
+ r = libusb_init(&ctx);
+ if (r < 0) {+ SDL_Log("libusb_init failed: %s", libusb_error_name(r));+ return 0;
+ }
+
+ libusb_device **device_list = NULL;
+ int count = libusb_get_device_list(ctx, &device_list);
+ for (size_t idx = 0; idx < count; ++idx) {+ libusb_device *device = device_list[idx];
+ struct libusb_device_descriptor desc;
+ int rc = libusb_get_device_descriptor(device, &desc);
+ if (rc < 0) {+ SDL_Log("Error");+ libusb_free_device_list(device_list, 1);
+ return rc;
+ }
+
+ if (desc.idVendor == M8_VID && desc.idProduct == M8_PID) {+ SDL_Log("Found M8 device: %d:%d\n", libusb_get_port_number(device),+ libusb_get_bus_number(device));
+ }
+ }
+ libusb_free_device_list(device_list, 1);
+ return 0;
+}
+
+int usb_loop(void *data) {+ SDL_SetCurrentThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
+ while (!do_exit) {+ int rc = libusb_handle_events(ctx);
+ if (rc != LIBUSB_SUCCESS) {+ SDL_Log("Audio loop error: %s\n", libusb_error_name(rc));+ break;
+ }
+ }
+ return 0;
+}
+
+static SDL_Thread *usb_thread;
+
+static void LIBUSB_CALL xfr_cb_in(struct libusb_transfer *transfer) {+ int *completed = transfer->user_data;
+ *completed = 1;
+}
+
+int bulk_transfer(int endpoint, uint8_t *serial_buf, int count, unsigned int timeout_ms) {+ if (devh == NULL) {+ return -1;
+ }
+
+ int completed = 0;
+
+ struct libusb_transfer *transfer;
+ transfer = libusb_alloc_transfer(0);
+ libusb_fill_bulk_transfer(transfer, devh, endpoint, serial_buf, count, xfr_cb_in, &completed,
+ timeout_ms);
+ int r = libusb_submit_transfer(transfer);
+
+ if (r < 0) {+ SDL_Log("Error");+ libusb_free_transfer(transfer);
+ return r;
+ }
+
+retry:
+ libusb_lock_event_waiters(ctx);
+ while (!completed) {+ if (!libusb_event_handler_active(ctx)) {+ libusb_unlock_event_waiters(ctx);
+ goto retry;
+ }
+ libusb_wait_for_event(ctx, NULL);
+ }
+ libusb_unlock_event_waiters(ctx);
+
+ int actual_length = transfer->actual_length;
+
+ libusb_free_transfer(transfer);
+
+ return actual_length;
+}
+
+int blocking_write(void *buf, int count, unsigned int timeout_ms) {+ return bulk_transfer(ep_out_addr, buf, count, timeout_ms);
+}
+
+int m8_process_data(uint8_t *serial_buf, int count) {+ return bulk_transfer(ep_in_addr, serial_buf, count, 1);
+}
+
+int check_serial_port() {+ // Reading will fail anyway when the device is not present anymore
+ return 1;
+}
+
+int init_interface() {+
+ if (devh == NULL) {+ SDL_Log("Device not initialised!");+ return 0;
+ }
+
+ int rc;
+
+ for (int if_num = 0; if_num < 2; if_num++) {+ if (libusb_kernel_driver_active(devh, if_num)) {+ SDL_Log("Detaching kernel driver for interface %d", if_num);+ libusb_detach_kernel_driver(devh, if_num);
+ }
+ rc = libusb_claim_interface(devh, if_num);
+ if (rc < 0) {+ SDL_Log("Error claiming interface: %s", libusb_error_name(rc));+ libusb_close(devh);
+ devh = NULL;
+ return 0;
+ }
+ }
+
+ /* Start configuring the device:
+ * - set line state
+ */
+ SDL_Log("Setting line state");+ rc = libusb_control_transfer(devh, 0x21, 0x22, ACM_CTRL_DTR | ACM_CTRL_RTS, 0, NULL, 0, 0);
+ if (rc < 0) {+ SDL_Log("Error during control transfer: %s", libusb_error_name(rc));+ return 0;
+ }
+
+ /* - set line encoding: here 115200 8N1
+ * 115200 = 0x01C200 ~> 0x00, 0xC2, 0x01, 0x00 in little endian
+ */
+ SDL_Log("Set line encoding");+ unsigned char encoding[] = {0x00, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x08};+ rc = libusb_control_transfer(devh, 0x21, 0x20, 0, 0, encoding, sizeof(encoding), 0);
+ if (rc < 0) {+ SDL_Log("Error during control transfer: %s", libusb_error_name(rc));+ return 0;
+ }
+
+ usb_thread = SDL_CreateThread(&usb_loop, "USB", NULL);
+
+ return 1;
+}
+
+int init_serial_with_file_descriptor(int file_descriptor) {+ SDL_Log("Initialising serial with file descriptor");+
+ if (file_descriptor <= 0) {+ SDL_Log("Invalid file descriptor: %d", file_descriptor);+ return 0;
+ }
+
+ int r;
+ r = libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY, NULL);
+ if (r != LIBUSB_SUCCESS) {+ SDL_Log("libusb_set_option failed: %s", libusb_error_name(r));+ return 0;
+ }
+ r = libusb_init(&ctx);
+ if (r < 0) {+ SDL_Log("libusb_init failed: %s", libusb_error_name(r));+ return 0;
+ }
+ r = libusb_wrap_sys_device(ctx, (intptr_t)file_descriptor, &devh);
+ if (r < 0) {+ SDL_Log("libusb_wrap_sys_device failed: %s", libusb_error_name(r));+ return 0;
+ } else if (devh == NULL) {+ SDL_Log("libusb_wrap_sys_device returned invalid handle");+ return 0;
+ }
+ SDL_Log("USB device init success");+
+ return init_interface();
+}
+
+int m8_initialize(int verbose, char *preferred_device) {+
+ if (devh != NULL) {+ return 1;
+ }
+
+ int r;
+ r = libusb_init(&ctx);
+ if (r < 0) {+ SDL_Log("libusb_init failed: %s", libusb_error_name(r));+ return 0;
+ }
+ if (preferred_device == NULL) {+ devh = libusb_open_device_with_vid_pid(ctx, M8_VID, M8_PID);
+ } else {+ char *port;
+ char *saveptr = NULL;
+ char *bus;
+ port = SDL_strtok_r(preferred_device, ":", &saveptr);
+ bus = SDL_strtok_r(NULL, ":", &saveptr);
+ libusb_device **device_list = NULL;
+ int count = libusb_get_device_list(ctx, &device_list);
+ for (size_t idx = 0; idx < count; ++idx) {+ libusb_device *device = device_list[idx];
+ struct libusb_device_descriptor desc;
+ r = libusb_get_device_descriptor(device, &desc);
+ if (r < 0) {+ SDL_Log("libusb_get_device_descriptor failed: %s", libusb_error_name(r));+ libusb_free_device_list(device_list, 1);
+ return 0;
+ }
+
+ if (desc.idVendor == M8_VID && desc.idProduct == M8_PID) {+ SDL_Log("Searching for port %s and bus %s", port, bus);+ if (libusb_get_port_number(device) == SDL_atoi(port) &&
+ libusb_get_bus_number(device) == SDL_atoi(bus)) {+ SDL_Log("Preferred device found, connecting");+ r = libusb_open(device, &devh);
+ if (r < 0) {+ SDL_Log("libusb_open failed: %s", libusb_error_name(r));+ return 0;
+ }
+ }
+ }
+ }
+ libusb_free_device_list(device_list, 1);
+ if (devh == NULL) {+ SDL_Log("Preferred device %s not found, using first available", preferred_device);+ devh = libusb_open_device_with_vid_pid(ctx, M8_VID, M8_PID);
+ }
+ }
+ if (devh == NULL) {+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM,
+ "libusb_open_device_with_vid_pid returned invalid handle");
+ return 0;
+ }
+ SDL_Log("USB device init success");+
+ return init_interface();
+}
+
+int m8_reset_display() {+ int result;
+
+ SDL_Log("Reset display\n");+
+ char buf[1] = {'R'};+
+ result = blocking_write(buf, 1, 5);
+ if (result != 1) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result);
+ return 0;
+ }
+ return 1;
+}
+
+int m8_enable_and_reset_display() {+ if (devh == NULL) {+ return 0;
+ }
+
+ int result;
+
+ SDL_Log("Enabling and resetting M8 display\n");+
+ char buf[1] = {'E'};+ result = blocking_write(buf, 1, 5);
+ if (result != 1) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error enabling M8 display, code %d", result);
+ return 0;
+ }
+
+ SDL_Delay(5);
+ result = m8_reset_display();
+ return result;
+}
+
+int m8_close() {+
+ char buf[1] = {'D'};+ int result;
+
+ SDL_Log("Disconnecting M8\n");+
+ result = blocking_write(buf, 1, 5);
+ if (result != 1) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending disconnect, code %d", result);
+ return -1;
+ }
+
+ int rc;
+
+ if (devh != NULL) {+
+ for (int if_num = 0; if_num < 2; if_num++) {+ rc = libusb_release_interface(devh, if_num);
+ if (rc < 0) {+ SDL_Log("Error releasing interface: %s", libusb_error_name(rc));+ return 0;
+ }
+ }
+
+ do_exit = 1;
+
+ libusb_close(devh);
+ }
+
+ SDL_WaitThread(usb_thread, NULL);
+
+ libusb_exit(ctx);
+
+ return 1;
+}
+
+int m8_send_msg_controller(uint8_t input) {+ char buf[2] = {'C', input};+ int nbytes = 2;
+ int result;
+ result = blocking_write(buf, nbytes, 5);
+ if (result != nbytes) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending input, code %d", result);
+ return -1;
+ }
+ return 1;
+}
+
+int m8_send_msg_keyjazz(uint8_t note, uint8_t velocity) {+ if (velocity > 0x7F)
+ velocity = 0x7F;
+ char buf[3] = {'K', note, velocity};+ int nbytes = 3;
+ int result;
+ result = blocking_write(buf, nbytes, 5);
+ if (result != nbytes) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending keyjazz, code %d", result);
+ return -1;
+ }
+
+ return 1;
+}
+
+#endif
--- /dev/null
+++ b/src/backends/m8_rtmidi.c
@@ -1,0 +1,293 @@
+// Copyright 2021 Jonne Kokkonen
+// Released under the MIT licence, https://opensource.org/licenses/MIT
+#ifdef USE_RTMIDI
+
+#ifndef NDEBUG
+#define RTMIDI_DEBUG
+#endif
+
+#include "../command.h"
+#include "../config.h"
+#include "m8.h"
+#include "queue.h"
+#include <SDL3/SDL.h>
+#include <rtmidi_c.h>
+#include <stdbool.h>
+#include <string.h>
+
+RtMidiInPtr midi_in;
+RtMidiOutPtr midi_out;
+message_queue_s queue;
+
+const unsigned char m8_sysex_header[5] = {0xF0, 0x00, 0x02, 0x61, 0x00};+const unsigned int m8_sysex_header_size = sizeof(m8_sysex_header);
+const unsigned char sysex_message_end = 0xF7;
+
+bool message_is_m8_sysex(const unsigned char *message) {+ if (memcmp(m8_sysex_header, message, m8_sysex_header_size) == 0) {+ return true;
+ }
+ return false;
+}
+
+void midi_decode(const uint8_t *encoded_data, size_t length, uint8_t **decoded_data,
+ size_t *decoded_length) {+ if (length < m8_sysex_header_size) {+ // Invalid data
+ *decoded_data = NULL;
+ *decoded_length = 0;
+ return;
+ }
+
+ // Skip header "F0 00 02 61" and the first MSB byte
+ size_t pos = m8_sysex_header_size + 1;
+
+ // Calculate expected output size (ignoring EOT if present)
+ const size_t expected_output_size =
+ (length - m8_sysex_header_size) - ((length - m8_sysex_header_size) / 8);
+ if (encoded_data[length - 1] == sysex_message_end) {+ length--; // Ignore the EOT byte
+ }
+
+ // Allocate memory for decoded output
+ *decoded_data = (uint8_t *)SDL_malloc(expected_output_size);
+ if (*decoded_data == NULL) {+ *decoded_length = 0;
+ return;
+ }
+
+ uint8_t bit_counter = 0;
+ uint8_t bit_byte_counter = 0;
+ uint8_t *out = *decoded_data;
+ *decoded_length = 0;
+
+ while (pos < length) {+ // Extract MSB from the "bit field" position
+ uint8_t msb = (encoded_data[bit_byte_counter * 8 + m8_sysex_header_size] >> bit_counter) & 0x01;
+
+ // Extract LSB from data byte
+ uint8_t lsb = encoded_data[pos] & 0x7F;
+
+ // Reconstruct original byte, skipping the MSB bytes in output
+ *out = (msb << 7) | lsb;
+ out++;
+ (*decoded_length)++;
+
+ bit_counter++;
+ pos++;
+
+ if (bit_counter == 7) {+ bit_counter = 0;
+ bit_byte_counter++;
+ pos++; // Skip the MSB byte
+ }
+ }
+}
+
+static void midi_callback(double delta_time, const unsigned char *message, size_t message_size,
+ void *user_data) {+ // Unused variables
+ (void)delta_time;
+ (void)user_data;
+
+ if (message_size < 5 || !message_is_m8_sysex(message))
+ return;
+
+ unsigned char *decoded_data;
+ size_t decoded_length;
+ midi_decode(message, message_size, &decoded_data, &decoded_length);
+
+ // If you need to debug incoming MIDI packets, you can uncomment the lines below:
+
+ /* printf("Original data: ");+ for (size_t i = 0; i < message_size; i++) {+ printf("%02X ", message[i]);+ } */
+
+ if (decoded_data) {+ /* printf("\nDecoded MIDI Data: ");+ for (size_t i = 0; i < decoded_length; i++) {+ printf("%02X ", decoded_data[i]);+ }
+ printf("\n"); */+ push_message(&queue, decoded_data, decoded_length);
+ SDL_free(decoded_data);
+ } else {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Decoding failed.\n");
+ }
+}
+
+int initialize_rtmidi() {+ SDL_Log("Initializing rtmidi");+ midi_in = rtmidi_in_create(RTMIDI_API_UNSPECIFIED, "m8c_in", 1024);
+ midi_out = rtmidi_out_create(RTMIDI_API_UNSPECIFIED, "m8c_out");
+ if (midi_in == NULL || midi_out == NULL) {+ return 0;
+ }
+ return 1;
+}
+
+int detect_m8_midi_device(const int verbose, const char *preferred_device) {+ int m8_midi_port_number = -1;
+ const unsigned int ports_total_in = rtmidi_get_port_count(midi_in);
+ if (verbose)
+ SDL_Log("Number of MIDI in ports: %d", ports_total_in);+ for (unsigned int port_number = 0; port_number < ports_total_in; port_number++) {+ int port_name_length_in;
+ rtmidi_get_port_name(midi_in, port_number, NULL, &port_name_length_in);
+ char port_name[port_name_length_in];
+ rtmidi_get_port_name(midi_in, port_number, &port_name[0], &port_name_length_in);
+ if (verbose)
+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "MIDI IN port %d, name: %s", port_number, port_name);
+ if (SDL_strncmp("M8", port_name, 2) == 0) {+ m8_midi_port_number = port_number;
+ if (verbose)
+ SDL_Log("Found M8 Input in MIDI port %d", port_number);+ if (preferred_device != NULL && SDL_strcmp(preferred_device, port_name) == 0) {+ SDL_Log("Found preferred device, breaking");+ break;
+ }
+ }
+ }
+ return m8_midi_port_number;
+}
+
+int m8_initialize(const int verbose, const char *preferred_device) {+
+ int m8_midi_port_number = 0;
+
+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Initialize M8 via RTMIDI called");
+ if (midi_in == NULL || midi_out == NULL) {+ initialize_rtmidi();
+ };
+ m8_midi_port_number = detect_m8_midi_device(verbose, preferred_device);
+ if (m8_midi_port_number >= 0) {+ rtmidi_in_ignore_types(midi_in, false, true, true); // Allow sysex
+ rtmidi_open_port(midi_in, m8_midi_port_number, "M8");
+ rtmidi_open_port(midi_out, m8_midi_port_number, "M8");
+ init_queue(&queue);
+ return 1;
+ }
+ return 0;
+}
+
+int m8_reset_display(void) {+ SDL_Log("Reset display");+ const unsigned char reset_sysex[8] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'R', 0xF7};+ const int result = rtmidi_out_send_message(midi_out, &reset_sysex[0], sizeof(reset_sysex));
+ if (result != 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, error %s", midi_out->msg);
+ return 0;
+ }
+ return 1;
+}
+
+int m8_enable_and_reset_display(void) {+ rtmidi_in_set_callback(midi_in, midi_callback, NULL);
+ const unsigned char enable_sysex[8] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'E', 0xF7};+ int result = rtmidi_out_send_message(midi_out, &enable_sysex[0], sizeof(enable_sysex));
+ if (result != 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Failed to enable display");
+ return 0;
+ }
+ result = m8_reset_display();
+ return result;
+}
+
+void close_and_free_midi_ports(void) {+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Freeing MIDI ports");
+ rtmidi_close_port(midi_in);
+ rtmidi_close_port(midi_out);
+ rtmidi_in_free(midi_in);
+ rtmidi_out_free(midi_out);
+ midi_in = NULL;
+ midi_out = NULL;
+}
+
+int disconnect(void) {+ const unsigned char disconnect_sysex[8] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'D', 0xF7};+ const int result =
+ rtmidi_out_send_message(midi_out, &disconnect_sysex[0], sizeof(disconnect_sysex));
+ if (result != 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Failed to send disconnect");
+ }
+ close_and_free_midi_ports();
+ return !result;
+}
+
+int m8_send_msg_controller(const unsigned char input) {+ const unsigned char input_sysex[9] = {0xF0, 0x00, 0x02, 0x61, 0x00, 0x00, 'C', input, 0xF7};+ const int result = rtmidi_out_send_message(midi_out, &input_sysex[0], sizeof(input_sysex));
+ if (result != 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Failed to send key input message");
+ return 0;
+ }
+ return 1;
+}
+
+int m8_send_msg_keyjazz(const unsigned char note, unsigned char velocity) {+ if (velocity > 0x7F) {+ velocity = 0x7F;
+ }
+ const unsigned char keyjazz_sysex[10] = {0xF0, 0x00, 0x02, 0x61, 0x00,+ 0x00, 'K', note, velocity, 0xF7};
+ const int result = rtmidi_out_send_message(midi_out, &keyjazz_sysex[0], sizeof(keyjazz_sysex));
+ if (result != 0) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Failed to send keyjazz input message");
+ return 0;
+ }
+ return 1;
+}
+
+int m8_process_data(config_params_s conf) {+
+ (void)conf; // unused parameter
+
+ static unsigned int empty_cycles = 0;
+
+ if (queue_size(&queue) > 0) {+ unsigned char *command;
+ empty_cycles = 0;
+ size_t length = 0;
+ while ((command = pop_message(&queue, &length)) != NULL) {+ process_command(command, length);
+ SDL_free(command);
+ }
+ } else {+ empty_cycles++;
+ if (empty_cycles >= conf.wait_packets) {+ SDL_Log("No messages received for %d cycles, assuming device disconnected", empty_cycles);+ close_and_free_midi_ports();
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int m8_close() {+ if (queue.mutex != NULL) {+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Destroying command queue");
+ SDL_DestroyMutex(queue.mutex);
+ SDL_DestroyCondition(queue.cond);
+ }
+ return disconnect();
+}
+
+int m8_list_devices() {+ if (midi_in == NULL || midi_out == NULL) {+ initialize_rtmidi();
+ };
+ const unsigned int ports_total_in = rtmidi_get_port_count(midi_in);
+ SDL_Log("Number of MIDI in ports: %d", ports_total_in);+ for (unsigned int port_number = 0; port_number < ports_total_in; port_number++) {+ int port_name_length_in;
+ rtmidi_get_port_name(midi_in, port_number, NULL, &port_name_length_in);
+ char port_name[port_name_length_in];
+ rtmidi_get_port_name(midi_in, port_number, &port_name[0], &port_name_length_in);
+ SDL_Log("MIDI IN port %d, name: %s", port_number, port_name);+ }
+ close_and_free_midi_ports();
+ return 1;
+}
+
+#endif
--- /dev/null
+++ b/src/backends/queue.c
@@ -1,0 +1,71 @@
+#include "queue.h"
+#include <SDL3/SDL.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+// Initialize the message queue
+void init_queue(message_queue_s *queue) {+ queue->front = 0;
+ queue->rear = 0;
+ queue->mutex = SDL_CreateMutex();
+ queue->cond = SDL_CreateCondition();
+}
+
+// Free allocated memory and destroy mutex
+void destroy_queue(message_queue_s *queue) {+ SDL_LockMutex(queue->mutex);
+
+ while (queue->front != queue->rear) {+ SDL_free(queue->messages[queue->front]);
+ queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
+ }
+
+ SDL_UnlockMutex(queue->mutex);
+ SDL_DestroyMutex(queue->mutex);
+ SDL_DestroyCondition(queue->cond);
+}
+
+// Push a message to the queue
+void push_message(message_queue_s *queue, const unsigned char *message, size_t length) {+ SDL_LockMutex(queue->mutex);
+
+ if ((queue->rear + 1) % MAX_QUEUE_SIZE == queue->front) {+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM,"Queue is full, cannot add message.");
+ } else {+ // Allocate space for the message and store it
+ queue->messages[queue->rear] = SDL_malloc(length);
+ SDL_memcpy(queue->messages[queue->rear], message, length);
+ queue->lengths[queue->rear] = length;
+ queue->rear = (queue->rear + 1) % MAX_QUEUE_SIZE;
+ SDL_SignalCondition(queue->cond); // Signal consumer thread
+ }
+
+ SDL_UnlockMutex(queue->mutex);
+}
+
+// Pop a message from the queue
+unsigned char *pop_message(message_queue_s *queue, size_t *length) {+ SDL_LockMutex(queue->mutex);
+
+ // Check if the queue is empty
+ if (queue->front == queue->rear) {+ SDL_UnlockMutex(queue->mutex);
+ return NULL; // Return NULL if there are no messages
+ }
+
+ // Otherwise, retrieve the message and its length
+ *length = queue->lengths[queue->front];
+ unsigned char *message = queue->messages[queue->front];
+ queue->front = (queue->front + 1) % MAX_QUEUE_SIZE;
+
+ SDL_UnlockMutex(queue->mutex);
+ return message;
+}
+
+unsigned int queue_size(const message_queue_s *queue) {+ SDL_LockMutex(queue->mutex);
+ const unsigned int size = (queue->rear - queue->front + MAX_QUEUE_SIZE) % MAX_QUEUE_SIZE;
+ SDL_UnlockMutex(queue->mutex);
+ return size;
+}
\ No newline at end of file
--- /dev/null
+++ b/src/backends/queue.h
@@ -1,0 +1,56 @@
+//
+// Created by jonne on 3/17/25.
+//
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include <SDL3/SDL.h>
+
+#define MAX_QUEUE_SIZE 4096
+
+typedef struct {+ unsigned char *messages[MAX_QUEUE_SIZE];
+ size_t lengths[MAX_QUEUE_SIZE]; // Store lengths of each message
+ int front;
+ int rear;
+ SDL_Mutex *mutex;
+ SDL_Condition *cond;
+} message_queue_s;
+
+/**
+ * Initializes the message queue structure.
+ *
+ * @param queue A pointer to the message queue structure to be initialized.
+ */
+void init_queue(message_queue_s *queue);
+
+/**
+ * Retrieves and removes a message from the front of the message queue.
+ * If the queue is empty, the function returns NULL.
+ *
+ * @param queue A pointer to the message queue structure from which the message is to be retrieved.
+ * @param length A pointer to a variable where the length of the retrieved message will be stored.
+ * @return A pointer to the retrieved message, or NULL if the queue is empty.
+ */
+unsigned char *pop_message(message_queue_s *queue, size_t *length);
+
+/**
+ * Adds a new message to the message queue.
+ * If the queue is full, the message will not be added.
+ *
+ * @param queue A pointer to the message queue structure where the message is to be stored.
+ * @param message A pointer to the message data to be added to the queue.
+ * @param length The length of the message in bytes.
+ */
+void push_message(message_queue_s *queue, const unsigned char *message, size_t length);
+
+/**
+ * Calculates the current size of the message queue.
+ *
+ * @param queue A pointer to the message queue structure whose size is to be determined.
+ * @return The number of messages currently in the queue.
+ */
+unsigned int queue_size(const message_queue_s *queue);
+
+#endif // QUEUE_H
--- /dev/null
+++ b/src/backends/ringbuffer.c
@@ -1,0 +1,55 @@
+#include "ringbuffer.h"
+#include <SDL3/SDL.h>
+
+RingBuffer *ring_buffer_create(uint32_t size) {+ RingBuffer *rb = SDL_malloc(sizeof(*rb));
+ rb->buffer = SDL_malloc(sizeof(*rb->buffer) * size);
+ rb->head = 0;
+ rb->tail = 0;
+ rb->max_size = size;
+ rb->size = 0;
+ return rb;
+}
+
+void ring_buffer_free(RingBuffer *rb) {+ SDL_free(rb->buffer);
+ SDL_free(rb);
+}
+
+uint32_t ring_buffer_empty(RingBuffer *rb) { return rb->size == 0; }+
+uint32_t ring_buffer_full(RingBuffer *rb) { return rb->size == rb->max_size; }+
+uint32_t ring_buffer_push(RingBuffer *rb, const uint8_t *data, uint32_t length) {+ if (ring_buffer_full(rb)) {+ return -1; // buffer full, push fails
+ }
+ uint32_t space1 = rb->max_size - rb->tail;
+ uint32_t n = length <= rb->max_size - rb->size ? length : rb->max_size - rb->size;
+ if (n <= space1) {+ SDL_memcpy(rb->buffer + rb->tail, data, n);
+ } else {+ SDL_memcpy(rb->buffer + rb->tail, data, space1);
+ SDL_memcpy(rb->buffer, data + space1, n - space1);
+ }
+ rb->tail = (rb->tail + n) % rb->max_size;
+ rb->size += n;
+ return n; // push successful, returns number of bytes pushed
+}
+
+uint32_t ring_buffer_pop(RingBuffer *rb, uint8_t *data, uint32_t length) {+ if (ring_buffer_empty(rb)) {+ return -1; // buffer empty, pop fails
+ }
+ uint32_t space1 = rb->max_size - rb->head;
+ uint32_t n = length <= rb->size ? length : rb->size;
+ if (n <= space1) {+ SDL_memcpy(data, rb->buffer + rb->head, n);
+ } else {+ SDL_memcpy(data, rb->buffer + rb->head, space1);
+ SDL_memcpy(data + space1, rb->buffer, n - space1);
+ }
+ rb->head = (rb->head + n) % rb->max_size;
+ rb->size -= n;
+ return n; // pop successful, returns number of bytes popped
+}
--- /dev/null
+++ b/src/backends/ringbuffer.h
@@ -1,0 +1,24 @@
+#ifndef M8C_RINGBUFFER_H
+#define M8C_RINGBUFFER_H
+
+#include <stdint.h>
+
+typedef struct {+ uint8_t *buffer;
+ uint32_t head;
+ uint32_t tail;
+ uint32_t max_size;
+ uint32_t size;
+} RingBuffer;
+
+RingBuffer *ring_buffer_create(uint32_t size);
+
+uint32_t ring_buffer_empty(RingBuffer *rb);
+
+uint32_t ring_buffer_pop(RingBuffer *rb, uint8_t *data, uint32_t length);
+
+uint32_t ring_buffer_push(RingBuffer *rb, const uint8_t *data, uint32_t length);
+
+void ring_buffer_free(RingBuffer *rb);
+
+#endif // M8C_RINGBUFFER_H
--- /dev/null
+++ b/src/backends/slip.c
@@ -1,0 +1,114 @@
+/*
+MIT License
+
+Copyright (c) 2018 Marcin Borowicz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/* This code is originally by marcinbor85, https://github.com/marcinbor85/slip
+It has been simplified a bit as CRC checking etc. is not required in this
+program. */
+
+#include "slip.h"
+
+#include <assert.h>
+#include <stddef.h>
+
+static void reset_rx(slip_handler_s *slip) {+ assert(slip != NULL);
+
+ slip->state = SLIP_STATE_NORMAL;
+ slip->size = 0;
+}
+
+slip_error_t slip_init(slip_handler_s *slip, const slip_descriptor_s *descriptor) {+ assert(slip != NULL);
+ assert(descriptor != NULL);
+ assert(descriptor->buf != NULL);
+ assert(descriptor->recv_message != NULL);
+
+ slip->descriptor = descriptor;
+ reset_rx(slip);
+
+ return SLIP_NO_ERROR;
+}
+
+static slip_error_t put_byte_to_buffer(slip_handler_s *slip, const uint8_t byte) {+ slip_error_t error = SLIP_NO_ERROR;
+
+ assert(slip != NULL);
+
+ if (slip->size >= slip->descriptor->buf_size) {+ error = SLIP_ERROR_BUFFER_OVERFLOW;
+ reset_rx(slip);
+ } else {+ slip->descriptor->buf[slip->size++] = byte;
+ slip->state = SLIP_STATE_NORMAL;
+ }
+
+ return error;
+}
+
+slip_error_t slip_read_byte(slip_handler_s *slip, uint8_t byte) {+ slip_error_t error = SLIP_NO_ERROR;
+
+ assert(slip != NULL);
+
+ switch (slip->state) {+ case SLIP_STATE_NORMAL:
+ switch (byte) {+ case SLIP_SPECIAL_BYTE_END:
+ if (!slip->descriptor->recv_message(slip->descriptor->buf, slip->size)) {+ error = SLIP_ERROR_INVALID_PACKET;
+ }
+ reset_rx(slip);
+ break;
+ case SLIP_SPECIAL_BYTE_ESC:
+ slip->state = SLIP_STATE_ESCAPED;
+ break;
+ default:
+ error = put_byte_to_buffer(slip, byte);
+ break;
+ }
+ break;
+
+ case SLIP_STATE_ESCAPED:
+ switch (byte) {+ case SLIP_ESCAPED_BYTE_END:
+ byte = SLIP_SPECIAL_BYTE_END;
+ break;
+ case SLIP_ESCAPED_BYTE_ESC:
+ byte = SLIP_SPECIAL_BYTE_ESC;
+ break;
+ default:
+ error = SLIP_ERROR_UNKNOWN_ESCAPED_BYTE;
+ reset_rx(slip);
+ break;
+ }
+
+ if (error != SLIP_NO_ERROR)
+ break;
+
+ error = put_byte_to_buffer(slip, byte);
+ break;
+ }
+
+ return error;
+}
--- /dev/null
+++ b/src/backends/slip.h
@@ -1,0 +1,67 @@
+/*
+MIT License
+
+Copyright (c) 2018 Marcin Borowicz
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+/* This code is originally by marcinbor85, https://github.com/marcinbor85/slip
+It has been simplified a bit as CRC checking etc. is not required in this
+program. */
+
+#ifndef SLIP_H_
+#define SLIP_H_
+
+#include <stdint.h>
+
+#define SLIP_SPECIAL_BYTE_END 0xC0
+#define SLIP_SPECIAL_BYTE_ESC 0xDB
+
+#define SLIP_ESCAPED_BYTE_END 0xDC
+#define SLIP_ESCAPED_BYTE_ESC 0xDD
+
+typedef enum {+ SLIP_STATE_NORMAL = 0x00,
+ SLIP_STATE_ESCAPED
+} slip_state_t;
+
+typedef struct {+ uint8_t *buf;
+ uint32_t buf_size;
+ int (*recv_message)(uint8_t *data, uint32_t size);
+} slip_descriptor_s;
+
+typedef struct {+ slip_state_t state;
+ uint32_t size;
+ const slip_descriptor_s *descriptor;
+} slip_handler_s;
+
+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);
+slip_error_t slip_read_byte(slip_handler_s *slip, uint8_t byte);
+
+#endif
\ No newline at end of file
--- a/src/command.c
+++ b/src/command.c
@@ -1,7 +1,7 @@
// Copyright 2021 Jonne Kokkonen
// Released under the MIT licence, https://opensource.org/licenses/MIT
-#include <SDL3/SDL_log.h>
+#include <SDL3/SDL.h>
#include "command.h"
#include "render.h"
@@ -168,7 +168,7 @@
set_m8_model(0);
}
- set_font_mode(recv_buf[5]);
+ renderer_set_font_mode(recv_buf[5]);
return 1;
}
--- a/src/config.c
+++ b/src/config.c
@@ -19,7 +19,7 @@
}
}
-config_params_s init_config(char *filename) {+config_params_s config_initialize(char *filename) {config_params_s c;
if (filename == NULL) {@@ -34,7 +34,7 @@
c.wait_packets = 1024; // default zero-byte attempts to disconnect (about 2
// sec for default idle_ms)
c.audio_enabled = 0; // route M8 audio to default output
- c.audio_buffer_size = 1024; // requested audio buffer size in samples
+ c.audio_buffer_size = 0; // requested audio buffer size in samples: 0 = let SDL decide
c.audio_device_name = NULL; // Use this device, leave NULL to use the default output device
c.key_up = SDL_SCANCODE_UP;
@@ -182,7 +182,7 @@
}
// Read config
-void read_config(config_params_s *conf) {+void config_read(config_params_s *conf) { char config_path[1024] = {0}; snprintf(config_path, sizeof(config_path), "%s%s", SDL_GetPrefPath("", "m8c"), conf->filename);--- a/src/config.h
+++ b/src/config.h
@@ -58,8 +58,8 @@
} config_params_s;
-config_params_s init_config(char *filename);
-void read_config(config_params_s *conf);
+config_params_s config_initialize(char *filename);
+void config_read(config_params_s *conf);
void read_audio_config(const ini_t *ini, config_params_s *conf);
void read_graphics_config(const ini_t *ini, config_params_s *conf);
void read_key_config(const ini_t *ini, config_params_s *conf);
--- a/src/font1.h
+++ /dev/null
@@ -1,56 +1,0 @@
-#ifndef FONT1_H_
-#define FONT1_H_
-
-#include "inline_font.h"
-
-struct inline_font font_v1_small = {- 470,
- 7,
- 5,
- 7,
- 0,
- 0,
- 3,
- 24,
- 566,
- {- 0x42, 0x4D, 0x36, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
- 0x00, 0x00, 0x00, 0xD6, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0x00, 0x40, 0x34,
- 0x01, 0x80, 0x00, 0x40, 0x12, 0x1F, 0xFF, 0xFE, 0x1F, 0xFC, 0x9E, 0x08, 0x10, 0x00, 0x00,
- 0x8E, 0x8F, 0x9D, 0xEF, 0xC1, 0xD1, 0xFB, 0xA3, 0xF8, 0xC5, 0xD0, 0x6C, 0x7C, 0x47, 0x12,
- 0x31, 0xF7, 0xC6, 0x1C, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0x93, 0xF1, 0x77, 0x22, 0xEA, 0xC7,
- 0xF0, 0x0C, 0x3E, 0x7F, 0xE3, 0xF1, 0xFF, 0xFE, 0x4F, 0x80, 0x00, 0x00, 0x15, 0xF9, 0xC8,
- 0x02, 0x40, 0x08, 0x40, 0x02, 0x11, 0x24, 0x02, 0x10, 0xC4, 0x91, 0x0A, 0x10, 0x20, 0x20,
- 0x10, 0x8C, 0x63, 0x18, 0x42, 0x31, 0x24, 0x65, 0x08, 0xC6, 0x30, 0x94, 0x42, 0x48, 0xAB,
- 0x71, 0x0C, 0x04, 0x14, 0x00, 0x00, 0x8C, 0x61, 0x18, 0x10, 0x31, 0x20, 0xB4, 0x4A, 0xC6,
- 0x3F, 0xFC, 0x02, 0x48, 0xD2, 0xAA, 0x0A, 0x22, 0x48, 0x80, 0x00, 0x80, 0x3E, 0x55, 0xD4,
- 0x02, 0x40, 0x08, 0x00, 0x01, 0x19, 0x24, 0x02, 0x10, 0xC4, 0x91, 0x08, 0x00, 0x6F, 0xB0,
- 0x97, 0x8C, 0x61, 0x18, 0x42, 0x71, 0x24, 0x69, 0x08, 0xC6, 0x30, 0xAC, 0x82, 0x48, 0xAA,
- 0xAA, 0x0A, 0x04, 0x24, 0x00, 0x00, 0xFC, 0x61, 0x1F, 0x93, 0xF1, 0x20, 0xA8, 0x4A, 0xC6,
- 0x31, 0x8C, 0x3E, 0x48, 0xCA, 0xA4, 0xF9, 0x22, 0x48, 0x80, 0x00, 0x80, 0x15, 0xF2, 0x24,
- 0x02, 0x42, 0xBE, 0x0F, 0x80, 0x95, 0x27, 0xFF, 0xFF, 0xFC, 0x5F, 0xF8, 0x00, 0xE0, 0x38,
- 0x55, 0xFF, 0xA1, 0x1F, 0x7A, 0x1F, 0x20, 0x71, 0x08, 0xCE, 0x3E, 0x8F, 0x9C, 0x48, 0xC6,
- 0x24, 0x79, 0x04, 0x44, 0x00, 0x00, 0x0C, 0x61, 0x18, 0x92, 0x31, 0x20, 0xA4, 0x4A, 0xC6,
- 0x31, 0x8C, 0x20, 0x48, 0xC6, 0xAA, 0x88, 0xA2, 0x4A, 0x80, 0x00, 0x80, 0x3F, 0x4D, 0x50,
- 0x02, 0x41, 0x08, 0x00, 0x00, 0x53, 0x20, 0x43, 0x18, 0x40, 0x31, 0x8A, 0x10, 0x6F, 0xB0,
- 0x37, 0x8C, 0x61, 0x18, 0x42, 0x11, 0x20, 0x69, 0x0A, 0xD6, 0x31, 0x8C, 0x60, 0x48, 0xC6,
- 0x2A, 0x88, 0x84, 0x84, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0xA2, 0x4F, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xF8, 0xC6, 0xB1, 0x8F, 0xE2, 0x48, 0xD8, 0x00, 0x82, 0x95, 0xFC, 0xC8,
- 0x82, 0x42, 0x88, 0x00, 0x00, 0x31, 0xE0, 0x43, 0x18, 0x40, 0x31, 0x88, 0x00, 0x20, 0x22,
- 0x31, 0x8C, 0x63, 0x18, 0x42, 0x31, 0x20, 0x65, 0x0D, 0xE6, 0x31, 0x8C, 0x60, 0x48, 0xC6,
- 0x31, 0x88, 0x45, 0x04, 0x28, 0x04, 0x04, 0x00, 0x10, 0x10, 0x10, 0x00, 0x20, 0x40, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x48, 0xA4, 0x00, 0x82, 0x80, 0x40, 0x30,
- 0x81, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x27, 0xFF, 0x1F, 0xFF, 0xEF, 0xF8, 0x00, 0x00, 0x01,
- 0xCE, 0x77, 0x9D, 0xEF, 0xFD, 0xD1, 0xF8, 0x63, 0x08, 0xC5, 0xDE, 0x77, 0x9F, 0xF8, 0xC6,
- 0x31, 0x8F, 0xC7, 0x0C, 0x10, 0x08, 0x04, 0x00, 0x10, 0x1C, 0x10, 0x20, 0xA0, 0xC0, 0x00,
- 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3E, 0x4F, 0x80, 0x00,
- }};
-#endif // FONT1_H_
\ No newline at end of file
--- a/src/font2.h
+++ /dev/null
@@ -1,85 +1,0 @@
-#ifndef FONT2_H_
-#define FONT2_H_
-#include "inline_font.h"
-
-struct inline_font font_v1_large = {- 752,
- 9,
- 8,
- 9,
- 0,
- -40,
- 4,
- 22,
- 1010,
- {- 0x42, 0x4D, 0xF2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
- 0x00, 0x00, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0xFF, 0xFF, 0xE7,
- 0x7D, 0x84, 0xFF, 0xFC, 0x9F, 0xFF, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0xFC, 0x00, 0x00, 0xE7, 0x01, 0xFC, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xE7, 0x81, 0x3C, 0x01,
- 0x81, 0x03, 0x00, 0x3F, 0x81, 0x3C, 0x00, 0x81, 0x3C, 0x00, 0x3C, 0x3C, 0x81, 0x3F, 0x84,
- 0x3C, 0x81, 0xE7, 0x81, 0xE7, 0x3C, 0x3C, 0xE7, 0x00, 0xF0, 0xFF, 0x0F, 0xFF, 0x80, 0xFF,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x24, 0x3C, 0x00,
- 0x3F, 0xFC, 0x3F, 0x00, 0x80, 0x00, 0x3F, 0x00, 0x3C, 0x00, 0x00, 0x00, 0xE7, 0x00, 0xFF,
- 0x00, 0x00, 0xFF, 0xFF, 0xDB, 0x00, 0x38, 0x39, 0xFF, 0xF9, 0xCF, 0xFF, 0xFF, 0xCF, 0xFF,
- 0xFF, 0x3F, 0x3C, 0xE7, 0x3F, 0xFC, 0xFC, 0xFC, 0x3C, 0xE7, 0x3C, 0xFC, 0xFF, 0x9F, 0xFC,
- 0xFF, 0x9F, 0xFF, 0x3F, 0x3C, 0x3C, 0x3C, 0x39, 0x3F, 0x3F, 0x3C, 0x3C, 0xE7, 0x3C, 0x39,
- 0x3F, 0x3C, 0x3C, 0x3C, 0x3F, 0x39, 0x39, 0x3C, 0xE7, 0x3C, 0xC3, 0x18, 0x3C, 0xE7, 0x3F,
- 0xF3, 0xFC, 0xCF, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0x3F, 0x3C, 0x3F, 0x9F, 0xFC, 0x3C, 0xE7,
- 0xFC, 0x39, 0xCF, 0x24, 0x3C, 0x3C, 0x3F, 0xFC, 0x3F, 0xFC, 0x9F, 0x3C, 0x1F, 0x24, 0x99,
- 0xFC, 0x9F, 0x3C, 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x81, 0xE4, 0x9D, 0x30, 0xFF,
- 0xF3, 0xE7, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0x9F, 0x3C, 0xE7, 0x3F, 0xFC, 0xFC, 0xFC, 0x3C,
- 0xE7, 0x3C, 0xFC, 0xE7, 0x9F, 0xF8, 0x81, 0x8F, 0xE7, 0x21, 0x3C, 0x3C, 0x3F, 0x3C, 0x3F,
- 0x3F, 0x3C, 0x3C, 0xE7, 0x3C, 0x33, 0x3F, 0x3C, 0x3C, 0x3C, 0x3F, 0x32, 0x33, 0xFC, 0xE7,
- 0x3C, 0x99, 0x00, 0x99, 0xE7, 0x9F, 0xF3, 0xF9, 0xCF, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0x3F,
- 0x3C, 0x3F, 0x9F, 0xFC, 0x3C, 0xE7, 0xFC, 0x33, 0xCF, 0x24, 0x3C, 0x3C, 0x3F, 0xFC, 0x3F,
- 0xFC, 0x9F, 0x3C, 0x0F, 0x24, 0xC3, 0xFC, 0xCF, 0x3C, 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xCF,
- 0xFF, 0xDB, 0xE4, 0xCF, 0x87, 0xFF, 0xF3, 0xE7, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xCF, 0x3C,
- 0xE7, 0x3F, 0xFC, 0xFC, 0xFC, 0x3C, 0xE7, 0x3C, 0xFC, 0xFF, 0xFF, 0xF0, 0xFF, 0x87, 0xE7,
- 0x24, 0x3C, 0x3C, 0x3F, 0x3C, 0x3F, 0x3F, 0x3C, 0x3C, 0xE7, 0xFC, 0x27, 0x3F, 0x3C, 0x38,
- 0x3C, 0x3F, 0x24, 0x27, 0xFC, 0xE7, 0x3C, 0x3C, 0x24, 0xC3, 0xE7, 0xCF, 0xF3, 0xF3, 0xCF,
- 0xFF, 0xFF, 0xFF, 0x00, 0x3C, 0x3F, 0x3C, 0x00, 0x9F, 0x00, 0x3C, 0xE7, 0xFC, 0x07, 0xCF,
- 0x24, 0x3C, 0x3C, 0x00, 0x00, 0x3F, 0x00, 0x9F, 0x3C, 0x27, 0x24, 0xE7, 0x00, 0xE7, 0x3C,
- 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xCF, 0xFF, 0xDB, 0x00, 0xE7, 0xC7, 0xFF, 0xF3, 0xE7, 0x33,
- 0x81, 0xFF, 0x81, 0xFF, 0xE7, 0x24, 0xE7, 0x00, 0x80, 0x00, 0x00, 0x00, 0xF3, 0x81, 0x00,
- 0xFF, 0xFF, 0xE0, 0xFF, 0x83, 0xE1, 0x24, 0x00, 0x01, 0x3F, 0x3C, 0x03, 0x03, 0x30, 0x00,
- 0xE7, 0xFC, 0x0F, 0x3F, 0x3C, 0x30, 0x3C, 0x01, 0x3C, 0x01, 0x81, 0xE7, 0x3C, 0x3C, 0x3C,
- 0xE7, 0x81, 0xE7, 0xF3, 0xE7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3C, 0x3F, 0x3C, 0x3C, 0x9F,
- 0x3C, 0x3C, 0xE7, 0xFC, 0x33, 0xCF, 0x24, 0x3C, 0x3C, 0x3C, 0x3C, 0x3F, 0x3F, 0x9F, 0x3C,
- 0x33, 0x24, 0xC3, 0x3C, 0xF3, 0x3C, 0xE7, 0x3C, 0x23, 0x00, 0x00, 0xCF, 0xFF, 0x81, 0x27,
- 0xF3, 0x93, 0xFF, 0xF3, 0xE7, 0x87, 0xE7, 0xFF, 0xFF, 0xFF, 0xF3, 0x3C, 0xE7, 0xFC, 0xFC,
- 0x3C, 0x3F, 0x3F, 0xF9, 0x3C, 0x3C, 0xE7, 0x9F, 0xF0, 0xFF, 0x87, 0xFC, 0x20, 0x3C, 0x3B,
- 0x3F, 0x3C, 0x3F, 0x3F, 0x3F, 0x3C, 0xE7, 0xFC, 0x27, 0x3F, 0x24, 0x24, 0x3C, 0x3C, 0x3C,
- 0x3C, 0x3F, 0xE7, 0x3C, 0x3C, 0x3C, 0xC3, 0x3C, 0xF3, 0xF3, 0xCF, 0xCF, 0xFF, 0xFF, 0xFF,
- 0xFC, 0x3C, 0x3F, 0x3C, 0x3C, 0x00, 0x3C, 0x3C, 0xE7, 0xFC, 0x39, 0xCF, 0x24, 0x3C, 0x3C,
- 0x3C, 0x3C, 0x3F, 0x3F, 0x9F, 0x3C, 0x39, 0x24, 0x99, 0x3C, 0xF9, 0x3C, 0xE7, 0x3C, 0x89,
- 0x00, 0x00, 0xCF, 0xC9, 0xDB, 0x27, 0xB9, 0x93, 0xE7, 0xF3, 0xE7, 0xCF, 0xE7, 0xFF, 0xFF,
- 0xFF, 0xF9, 0x3C, 0xE7, 0xFC, 0xFC, 0x3C, 0x3F, 0x3F, 0xFC, 0x3C, 0x3C, 0xFF, 0xFF, 0xF8,
- 0x81, 0x8F, 0xFC, 0x3C, 0x3C, 0x39, 0x3F, 0x3C, 0x3F, 0x3F, 0x3F, 0x3C, 0xE7, 0xFC, 0x33,
- 0x3F, 0x00, 0x0C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3F, 0xE7, 0x3C, 0x3C, 0x3C, 0x99, 0x3C, 0xF9,
- 0xF3, 0x9F, 0xCF, 0x27, 0xFF, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x87,
- 0x80, 0x3C, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x24, 0x3C,
- 0x3C, 0x00, 0x3C, 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xCF, 0xC9, 0xFF, 0x00, 0x1C, 0xC7, 0xE7,
- 0xF9, 0xCF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3C, 0xE7, 0xFC, 0xFC, 0x3C, 0x3F, 0x3F,
- 0xFC, 0x9C, 0x3C, 0xFF, 0xFF, 0xFC, 0xFF, 0x9F, 0x3C, 0x3C, 0x99, 0x39, 0x3C, 0x39, 0x3F,
- 0x3F, 0x3C, 0x3C, 0xE7, 0xFC, 0x39, 0x3F, 0x18, 0x1C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0xE7,
- 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0xFC, 0xF3, 0x3F, 0xCF, 0x8F, 0xFF, 0x9F, 0xFF, 0x3F, 0xFF,
- 0xFC, 0xFF, 0x9F, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xCF,
- 0xC9, 0xFF, 0xE7, 0xBE, 0xFF, 0xE7, 0xFC, 0x9F, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
- 0x87, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x81,
- 0x81, 0xC3, 0x03, 0x81, 0x03, 0x00, 0x00, 0x81, 0x3C, 0x00, 0x00, 0x3C, 0x3F, 0x3C, 0x3C,
- 0x81, 0x01, 0x81, 0x01, 0x81, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0xF0, 0xFF, 0x0F,
- 0xDF, 0xFF, 0x3F, 0xFF, 0x3F, 0xFF, 0xFC, 0xFF, 0x80, 0xFF, 0x3F, 0xE7, 0xFC, 0x3F, 0x0F,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
- 0xE7, 0x00, 0xFF, 0x00, 0x00,
- }};
-#endif // FONT2_H_
\ No newline at end of file
--- a/src/font3.h
+++ /dev/null
@@ -1,93 +1,0 @@
-#ifndef FONT3_H_
-#define FONT3_H_
-
-#include "inline_font.h"
-
-struct inline_font font_v2_small = {- 846,
- 9,
- 9,
- 9,
- 0,
- -2,
- 5,
- 38,
- 1118,
- {- 0x42, 0x4D, 0x5E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
- 0x00, 0x00, 0x00, 0x4E, 0x03, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xCC, 0x03, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xF7, 0x7E,
- 0xF7, 0xC4, 0x3B, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xEF, 0xFF, 0xFB, 0xFD, 0xFE, 0x00, 0x00,
- 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x03, 0xFC, 0x00, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xDE, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x30, 0x03, 0xFC, 0x00, 0xFE, 0x00, 0x00, 0x1F, 0xC0,
- 0x07, 0xF3, 0xF8, 0x00, 0xFF, 0x01, 0x3F, 0x80, 0x1E, 0xF0, 0x07, 0xBD, 0xFC, 0xFE, 0x00,
- 0x00, 0x3C, 0x7F, 0xEE, 0x3F, 0xFC, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC,
- 0x00, 0xFE, 0x00, 0x00, 0x1F, 0xC0, 0x07, 0x73, 0xF8, 0x00, 0xFF, 0xFF, 0x3F, 0xC0, 0x00,
- 0x00, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x07, 0xFC, 0x00, 0x00, 0xFF,
- 0xFF, 0xF7, 0x60, 0x0B, 0xD3, 0xD7, 0xFF, 0xFD, 0xBF, 0xFF, 0xFD, 0xEF, 0xFF, 0xFF, 0xFE,
- 0xFE, 0xFE, 0xF7, 0xBF, 0xFF, 0xDF, 0xEF, 0xF3, 0xFB, 0xFC, 0xFE, 0xFF, 0x7F, 0xDF, 0xFF,
- 0x3F, 0xFF, 0x3F, 0xFE, 0xFF, 0x7F, 0x3F, 0x9F, 0xEF, 0xD7, 0xFB, 0xFD, 0xFC, 0xFE, 0xF7,
- 0xFF, 0x9F, 0xAF, 0xF7, 0xF3, 0xF1, 0xFC, 0xFF, 0x7E, 0xBF, 0x7F, 0xDE, 0xF7, 0xF7, 0x5C,
- 0xF9, 0x7D, 0xFF, 0x5F, 0xFD, 0xFF, 0xDF, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x9F, 0xEF,
- 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0xF7, 0xFF, 0x9F, 0xAF, 0xF7, 0x73, 0xF9, 0xFC, 0xFF, 0xFF,
- 0x3F, 0xFF, 0xCF, 0xF7, 0xF3, 0x7D, 0xDD, 0x7D, 0xFF, 0x3F, 0xDF, 0xCF, 0xF7, 0xF7, 0xFC,
- 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0x1E, 0xED, 0xC3, 0xEF, 0xFF, 0xFB, 0xDF, 0xFF, 0xFD, 0xFF,
- 0xFF, 0xFF, 0xFF, 0x7E, 0xFE, 0xF7, 0xBF, 0xFF, 0xDF, 0xEF, 0xF3, 0xFB, 0xFC, 0xFE, 0xFF,
- 0x3F, 0xDF, 0xFE, 0x38, 0x0F, 0x1F, 0xDE, 0x80, 0x7F, 0x3F, 0x9F, 0xEF, 0xE7, 0xFB, 0xFD,
- 0xFC, 0xFE, 0xF7, 0xFF, 0x9F, 0x6F, 0xF7, 0xF3, 0xE9, 0xFC, 0xFF, 0x7D, 0x3E, 0xFF, 0xDE,
- 0xF7, 0xF6, 0xED, 0x75, 0xBB, 0xFF, 0x6F, 0xFD, 0xFF, 0xBF, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F,
- 0x3F, 0x9F, 0xEF, 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0xF7, 0xFF, 0x9F, 0x6F, 0xF7, 0x73, 0xF9,
- 0xFC, 0x00, 0x00, 0x3F, 0xFF, 0xCF, 0xF7, 0xF3, 0xBD, 0xDD, 0xBB, 0xFF, 0x4F, 0xDF, 0xCF,
- 0xF7, 0xF7, 0xFC, 0x00, 0x00, 0x7F, 0xFF, 0xF7, 0x7E, 0xEE, 0xFB, 0xD7, 0xFF, 0xFB, 0xDF,
- 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFE, 0xF7, 0xBF, 0xFF, 0xDF, 0xEF, 0xF3, 0xFB,
- 0xFC, 0xFE, 0xFF, 0x7F, 0xFF, 0xFC, 0x3F, 0xFF, 0x0F, 0xDE, 0xBA, 0x7F, 0x3F, 0x9F, 0xEF,
- 0xE7, 0xFB, 0xFD, 0xFC, 0xFE, 0xF7, 0xFF, 0x9E, 0xEF, 0xF7, 0xF3, 0xD9, 0xFC, 0xFF, 0x7B,
- 0x3D, 0xFF, 0xDE, 0xF7, 0xF5, 0xF5, 0xAD, 0xD7, 0xFF, 0x77, 0xFD, 0xFF, 0x7F, 0xBF, 0xFF,
- 0xFF, 0xFF, 0x00, 0x3F, 0x9F, 0xEF, 0xE0, 0x00, 0x0C, 0x00, 0xFE, 0xF7, 0xFF, 0x80, 0xEF,
- 0xF7, 0x73, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0xC0, 0x0F, 0xF7, 0xF3, 0xDD, 0xDD, 0xC7, 0x00,
- 0x71, 0xDF, 0xCF, 0xF7, 0xF7, 0xFC, 0x00, 0x00, 0x7F, 0xFF, 0xF7, 0x60, 0x0F, 0x7D, 0xBB,
- 0xFF, 0xFB, 0xDF, 0xDD, 0xE0, 0x3F, 0xF8, 0x0F, 0xFF, 0xDE, 0xEE, 0xF7, 0x80, 0x00, 0x00,
- 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x7F, 0xFF, 0xF8, 0x3F, 0xFF, 0x07, 0xC0, 0x82, 0x00,
- 0x00, 0x1F, 0xEF, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0xF7, 0xFF, 0x81, 0xEF, 0xF7, 0x73, 0xB9,
- 0xFC, 0x00, 0x7F, 0x00, 0x00, 0x1E, 0xF7, 0xF3, 0xF9, 0xDD, 0xEF, 0x00, 0x7B, 0xFD, 0xFE,
- 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x9F, 0xEF, 0xE7, 0xF3, 0xFD, 0xFC, 0xFE, 0xF7,
- 0xFF, 0x9F, 0x6F, 0xF7, 0x73, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0xDF, 0xEF, 0xF7, 0xF3, 0xED,
- 0xDD, 0xBB, 0x7F, 0x7E, 0x5F, 0xCF, 0xF7, 0xF3, 0x3C, 0x00, 0x00, 0x7F, 0xFF, 0xF7, 0x6E,
- 0xFF, 0xBE, 0x7F, 0xFF, 0xFB, 0xDF, 0xEB, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xFE, 0xF7,
- 0xFF, 0xBF, 0xCF, 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0x7F, 0x7F, 0xFF, 0xFC, 0x3F, 0xFF, 0x0F,
- 0xFC, 0xFA, 0x7F, 0x3E, 0xDF, 0xEF, 0xE7, 0xFB, 0xFD, 0xFE, 0xFE, 0xF7, 0xFF, 0x9E, 0xEF,
- 0xF6, 0xB3, 0x79, 0xFC, 0xFE, 0x7F, 0x3F, 0x9F, 0xFE, 0xF7, 0xF3, 0xF9, 0xFD, 0xD7, 0x7F,
- 0x7D, 0xFD, 0xFD, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x9F, 0xEF, 0xE7, 0xF3, 0xFD,
- 0xFC, 0xFE, 0xF7, 0xFF, 0x9F, 0xAF, 0xF7, 0x73, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0xDF, 0xEF,
- 0xF7, 0xF3, 0xF5, 0xDD, 0x7D, 0x7F, 0x7F, 0x9F, 0xCF, 0xF7, 0xF4, 0xDC, 0x00, 0x00, 0x7F,
- 0xB7, 0xC0, 0x0E, 0xF1, 0xDD, 0xBD, 0xFF, 0xFB, 0xDF, 0xF7, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xF6, 0xFE, 0xF7, 0xFF, 0xBF, 0xCF, 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0x7F, 0x3F, 0xDF, 0xFE,
- 0x38, 0x0F, 0x1F, 0xFC, 0x82, 0x7F, 0x3E, 0xDF, 0xEF, 0xE7, 0xFB, 0xFD, 0xFE, 0xFE, 0xF7,
- 0xFF, 0x9F, 0x6F, 0xF5, 0xD2, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0x9F, 0xFE, 0xF7, 0xF3, 0xF9,
- 0xFD, 0xBB, 0x7F, 0x7E, 0xFD, 0xFB, 0xFF, 0xBB, 0xBF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0xCF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x07, 0xF3, 0xF9, 0xDC, 0xFE, 0x7F, 0x00, 0x1F, 0xCF, 0xF7, 0xF7, 0xFC,
- 0x00, 0x00, 0x7F, 0xB7, 0xF7, 0x60, 0x05, 0xED, 0xBD, 0xFF, 0xFD, 0xBF, 0xEB, 0xFD, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFA, 0xFE, 0xF7, 0xFF, 0xBF, 0xCF, 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0x7F,
- 0x7F, 0xFF, 0xFF, 0x3F, 0xFF, 0x3D, 0xFC, 0xFE, 0x7F, 0x3E, 0xDF, 0xEF, 0xD7, 0xFB, 0xFD,
- 0xFE, 0xFE, 0xF7, 0xFF, 0x9F, 0xAF, 0xF3, 0xE1, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0x9F, 0xFE,
- 0xF7, 0xF3, 0xF9, 0xFD, 0x7D, 0x7F, 0x7F, 0x7D, 0xF7, 0xFF, 0xBD, 0x7F, 0xFF, 0xBF, 0xFF,
- 0xBF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xCF,
- 0xF7, 0xF7, 0xFC, 0x00, 0x00, 0x7F, 0xB7, 0xF7, 0x7E, 0xF1, 0xF6, 0x7D, 0xFF, 0xFE, 0x7F,
- 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x07, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00,
- 0x30, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x7F, 0x9F, 0xCF, 0xF7, 0xF3, 0xF8, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x07, 0xF3, 0xF9, 0xFC, 0xFE, 0x7F, 0x00, 0x3C, 0x6F, 0xFE, 0x3E, 0xFF,
- 0xFF, 0x7F, 0xFF, 0xBF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xC0, 0x0F, 0xF0, 0x07, 0xFC, 0x00, 0x00,
- }};
-#endif // FONT3_H_
\ No newline at end of file
--- a/src/font4.h
+++ /dev/null
@@ -1,108 +1,0 @@
-#ifndef FONT4_H_
-#define FONT4_H_
-
-#include "inline_font.h"
-
-struct inline_font font_v2_large = {- 940,
- 10,
- 10,
- 10,
- 0,
- -2,
- 4,
- 38,
- 1346,
- {- 0x42, 0x4D, 0x42, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
- 0x00, 0x00, 0x00, 0xAC, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0xCF,
- 0xCF, 0x3E, 0x60, 0xCF, 0xFF, 0xF9, 0x3F, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xE7, 0xF3, 0xFC,
- 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x3F, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x03, 0x3F, 0x00, 0x18, 0x00, 0x01, 0x80, 0x0F, 0xF8, 0x04,
- 0xFC, 0x00, 0x00, 0x13, 0xF2, 0x00, 0x3F, 0x0F, 0xC8, 0x04, 0xFF, 0x83, 0x0F, 0xC0, 0x07,
- 0xCF, 0x80, 0x7C, 0xF3, 0xF0, 0xFC, 0x00, 0x40, 0x0F, 0x0F, 0xFC, 0xE1, 0xFF, 0xF0, 0x03,
- 0xFF, 0x80, 0x00, 0x18, 0x02, 0x00, 0x80, 0x33, 0xF0, 0x04, 0xFC, 0x00, 0x00, 0x13, 0xE0,
- 0x00, 0x33, 0x0F, 0xC8, 0x04, 0xFF, 0xFF, 0x0F, 0xF0, 0x07, 0x80, 0x80, 0x43, 0xF8, 0x00,
- 0xFC, 0x00, 0x40, 0x00, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0xCC,
- 0x01, 0x1E, 0x40, 0x0F, 0xFF, 0xF1, 0x1F, 0xFF, 0xFF, 0x3C, 0xFF, 0xFF, 0xE7, 0xF1, 0xFC,
- 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x3F, 0xFC, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0x03, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00,
- 0xFC, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x3F, 0x0F, 0x80, 0x00, 0xFF, 0x06, 0x0F, 0x80, 0x03,
- 0xCF, 0x00, 0x38, 0x71, 0xE0, 0x78, 0x00, 0x00, 0x0F, 0x0F, 0xF8, 0xE1, 0xFF, 0xF0, 0x03,
- 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xF0, 0x00, 0xFC, 0x00, 0x00, 0x03, 0xC4,
- 0x00, 0x33, 0x0F, 0xC0, 0x00, 0xFF, 0xFF, 0x0F, 0xF0, 0x03, 0x00, 0x00, 0x01, 0xF0, 0x00,
- 0x78, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00,
- 0x00, 0x8F, 0xCE, 0x1F, 0xFF, 0xE3, 0x8F, 0xFF, 0xFF, 0x3C, 0xFF, 0xFF, 0xFF, 0xF8, 0xFC,
- 0xFC, 0xF3, 0xCF, 0xFF, 0xF3, 0xFC, 0xFF, 0x0F, 0xCF, 0xF0, 0xFC, 0xFF, 0x33, 0xFC, 0xFF,
- 0xE7, 0x80, 0x79, 0xFF, 0xFC, 0xFF, 0x3F, 0x0F, 0xC3, 0xFC, 0xFC, 0x3F, 0xCF, 0xF3, 0xF0,
- 0xFC, 0xF3, 0xFF, 0xC3, 0xC4, 0xFF, 0x3F, 0x0F, 0x03, 0xF0, 0xFF, 0x3C, 0x0F, 0x1F, 0xF3,
- 0xCF, 0x3F, 0x30, 0x30, 0xC2, 0x31, 0xFF, 0x23, 0xFF, 0x3F, 0xF1, 0xF9, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x3F, 0x0F, 0xC3, 0xFC, 0xFC, 0x3F, 0xF3, 0xFF, 0xF0, 0xFC, 0xF3, 0xFF, 0xC3, 0x8F,
- 0xCF, 0x33, 0x0F, 0xC3, 0xF0, 0x01, 0x80, 0x0F, 0xFF, 0xF3, 0x3F, 0x3F, 0x08, 0xF3, 0x32,
- 0x31, 0xFF, 0x03, 0xF3, 0xF0, 0xFF, 0x3F, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x03,
- 0xCC, 0xC7, 0xCE, 0x1F, 0xFF, 0xE7, 0xCF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C,
- 0xFC, 0xF3, 0xCF, 0xFF, 0xF3, 0xFC, 0xFF, 0x0F, 0xCF, 0xF0, 0xFC, 0xFF, 0x33, 0xFC, 0xFF,
- 0xC7, 0x80, 0x78, 0xFF, 0x3C, 0xC0, 0x3F, 0x0F, 0xC3, 0xFC, 0xFC, 0x3F, 0xCF, 0xF3, 0xF0,
- 0xFC, 0xF3, 0xFF, 0xC3, 0x8C, 0xFF, 0x3F, 0x0E, 0x03, 0xF0, 0xFF, 0x38, 0x0E, 0x3F, 0xF3,
- 0xCF, 0x3F, 0x23, 0x10, 0x03, 0x03, 0xFF, 0x31, 0xFF, 0x3F, 0xE3, 0xF9, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x00, 0x0F, 0xC3, 0xFC, 0xFC, 0x00, 0x33, 0xF8, 0x00, 0xFC, 0xF3, 0xFF, 0xC0, 0x1F,
- 0xCF, 0x33, 0x0F, 0xC3, 0xF0, 0x00, 0x00, 0x0F, 0xF8, 0x03, 0x3F, 0x3F, 0x0C, 0x73, 0x33,
- 0x03, 0x80, 0x20, 0x73, 0xF0, 0xFF, 0x3F, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0xCE,
- 0x00, 0xE3, 0xC0, 0x0F, 0xFF, 0xE7, 0xCF, 0xCE, 0x78, 0x07, 0xFF, 0x80, 0x7F, 0xFE, 0x3C,
- 0xCC, 0xF3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
- 0x87, 0xFF, 0xF8, 0x7F, 0x04, 0xC0, 0x00, 0x00, 0x03, 0xFC, 0xFC, 0x00, 0x00, 0x03, 0x00,
- 0x00, 0xF3, 0xFF, 0xC0, 0x1C, 0xFF, 0x33, 0x0C, 0x43, 0xF0, 0x01, 0x31, 0x00, 0x18, 0x03,
- 0xCF, 0x3F, 0x07, 0x82, 0x13, 0x87, 0x80, 0x38, 0xFF, 0x3F, 0xC7, 0xF9, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x00, 0x0F, 0xC3, 0xFC, 0xFC, 0x00, 0x33, 0xF0, 0x00, 0xFC, 0xF3, 0xFF, 0xC0, 0x3F,
- 0xCF, 0x33, 0x0F, 0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xF0, 0x07, 0x3F, 0x3F, 0x0E, 0x33, 0x33,
- 0x03, 0x00, 0x38, 0x13, 0xF0, 0xFF, 0x3F, 0x08, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0xCC,
- 0x01, 0xF1, 0xE0, 0xCF, 0xFF, 0xE7, 0xCF, 0xC4, 0x78, 0x07, 0xFF, 0x80, 0x7F, 0xFF, 0x1C,
- 0xCC, 0xF3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
- 0x07, 0xFF, 0xF8, 0x3F, 0x00, 0xCC, 0x00, 0x00, 0x33, 0xFC, 0xFC, 0x00, 0x00, 0x03, 0x00,
- 0x00, 0xF3, 0xFF, 0xC0, 0x1C, 0xFF, 0x21, 0x08, 0xC3, 0xF0, 0x00, 0x33, 0x00, 0x00, 0x07,
- 0xCF, 0x3F, 0x0F, 0xC3, 0x33, 0x87, 0x00, 0x3C, 0x7F, 0x3F, 0x8F, 0xF9, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0x0F, 0xC3, 0xFC, 0xFC, 0x3F, 0x00, 0x33, 0xF0, 0xFC, 0xF3, 0xFF, 0xC3, 0x1F,
- 0xCF, 0x33, 0x0F, 0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xF3, 0xFF, 0x3F, 0x3F, 0x0F, 0x13, 0x32,
- 0x31, 0x3F, 0x3F, 0x03, 0xF0, 0xFF, 0x3F, 0x00, 0x70, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00,
- 0xCF, 0xF8, 0xE6, 0x7F, 0xFF, 0xE7, 0xCF, 0xF1, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C,
- 0xFC, 0xF3, 0xFF, 0xCF, 0xF0, 0xFC, 0x3F, 0xCF, 0xFF, 0xF0, 0xFC, 0x3F, 0x33, 0xFC, 0xFF,
- 0x87, 0x80, 0x78, 0x7F, 0xF0, 0xCC, 0x3F, 0x0F, 0x93, 0xFC, 0xFC, 0x3F, 0xCF, 0xF3, 0xFC,
- 0xFC, 0xF3, 0xFF, 0xC3, 0x8C, 0xFF, 0x00, 0x01, 0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xC3, 0xFF,
- 0xCF, 0x3F, 0x0F, 0xC3, 0xF3, 0x03, 0x3F, 0x3E, 0x3F, 0x3F, 0x1F, 0xF9, 0xE6, 0x7F, 0xFF,
- 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC3, 0xFF, 0x03, 0x8F,
- 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x0F, 0x83, 0x30,
- 0x78, 0x3F, 0x00, 0x03, 0xF0, 0xFF, 0x3F, 0x22, 0x70, 0x00, 0x00, 0x3F, 0xC9, 0xF0, 0x00,
- 0x00, 0xFC, 0x66, 0x73, 0xFF, 0xE3, 0x8F, 0xF1, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC4,
- 0xFC, 0xF3, 0xFF, 0xCF, 0xF0, 0xFC, 0x3F, 0xCF, 0xFF, 0xF0, 0xFC, 0x3F, 0x33, 0xFC, 0xFF,
- 0xC7, 0x80, 0x78, 0xF3, 0xF0, 0xFC, 0x3F, 0x0F, 0x93, 0xFC, 0xF8, 0x3F, 0xCF, 0xF3, 0xFC,
- 0xFC, 0xF3, 0xFF, 0xC3, 0xC4, 0xFF, 0x0C, 0x03, 0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xC3, 0xFF,
- 0xCF, 0x3F, 0x0F, 0xC3, 0xF2, 0x31, 0x3F, 0x3F, 0x1F, 0x3E, 0x3F, 0xF9, 0xE0, 0x7F, 0xFF,
- 0x3F, 0x00, 0x40, 0x18, 0x02, 0x00, 0x80, 0x73, 0xF8, 0x00, 0x01, 0xC3, 0xFF, 0x03, 0xC7,
- 0xCF, 0x00, 0x40, 0x18, 0x04, 0x01, 0x80, 0x20, 0x08, 0x00, 0x00, 0x3F, 0x0F, 0xC3, 0x30,
- 0xFC, 0x3F, 0x00, 0x03, 0xF0, 0xFF, 0x3F, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xC9, 0xFC, 0xCE,
- 0x00, 0x9E, 0x20, 0x73, 0xFF, 0xF1, 0x1F, 0xC4, 0x7F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
- 0x00, 0x03, 0xC0, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
- 0xE7, 0xFF, 0xF9, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0xFC, 0x00, 0x3F, 0xC3, 0xE0, 0xFF, 0x1E, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x3F, 0x0F, 0xC3, 0xF0, 0x78, 0x3F, 0x00, 0x0F, 0x0C, 0x7F, 0xE1, 0xF0, 0xFF, 0xFE,
- 0x3F, 0xFF, 0xCF, 0xFF, 0xFF, 0xFC, 0xFF, 0xF0, 0x0F, 0xFC, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF,
- 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xC9, 0xFC, 0xCF,
- 0xCF, 0x9F, 0x30, 0xF3, 0xFF, 0xF9, 0x3F, 0xCE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
- 0x00, 0x03, 0xC0, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xF8, 0x06, 0x01, 0x80, 0x40, 0x38, 0x00, 0x03, 0x80, 0x20, 0x08, 0x00,
- 0xFC, 0x00, 0x3F, 0xC3, 0xF0, 0xFF, 0x3F, 0x0F, 0xC8, 0x04, 0x01, 0x80, 0x40, 0x18, 0x00,
- 0x00, 0x3F, 0x0F, 0xC3, 0xF0, 0xFC, 0x3F, 0x00, 0x0F, 0x0C, 0xFF, 0xE1, 0xF9, 0xFF, 0xFE,
- 0x7F, 0xFF, 0xCF, 0xFF, 0xFF, 0xFC, 0xFF, 0xF8, 0x0F, 0xFC, 0xFF, 0xF3, 0xFF, 0xC3, 0xFF,
- 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x00, 0x00,
- }};
-#endif // FONT4_H_
\ No newline at end of file
--- a/src/font5.h
+++ /dev/null
@@ -1,143 +1,0 @@
-#ifndef FONT5_H_
-#define FONT5_H_
-
-#include "inline_font.h"
-
-struct inline_font font_v2_huge = {- 1128,
- 12,
- 12,
- 12,
- 0,
- -54,
- 4,
- 24,
- 1874,
- {- 0x42, 0x4D, 0x52, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
- 0x00, 0x00, 0x00, 0x68, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xC0, 0x06, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
- 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
- 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF,
- 0xFF, 0x9F, 0xFF, 0xFC, 0x1C, 0xFF, 0xFF, 0xF3, 0xE7, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF,
- 0xF9, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0xFF,
- 0xC0, 0x00, 0xFF, 0xCF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF8, 0x03, 0x3F,
- 0xC0, 0x01, 0x80, 0x00, 0x01, 0x80, 0x03, 0xFF, 0x80, 0x13, 0xFC, 0x00, 0x00, 0x01, 0x3F,
- 0xC8, 0x00, 0x3F, 0xC3, 0xFC, 0x80, 0x13, 0xFF, 0x80, 0xC3, 0xFC, 0x00, 0x1F, 0x9F, 0x80,
- 0x1F, 0x9F, 0x3F, 0xC3, 0xFC, 0x00, 0x10, 0x00, 0xC0, 0xFF, 0xFC, 0xE0, 0x7F, 0xFF, 0x00,
- 0x0F, 0xFF, 0x80, 0x00, 0x01, 0x80, 0x08, 0x00, 0x80, 0x0C, 0xFF, 0x00, 0x13, 0xFC, 0x00,
- 0x00, 0x01, 0x3F, 0x80, 0x00, 0x39, 0xC3, 0xFC, 0x80, 0x13, 0xFF, 0xFF, 0xC3, 0xFF, 0x00,
- 0x1E, 0x00, 0x80, 0x10, 0xFF, 0x80, 0x03, 0xFC, 0x00, 0x10, 0x00, 0x00, 0x03, 0xFF, 0x00,
- 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE6, 0x70, 0x01, 0x9F, 0x18, 0x08, 0xFF,
- 0xFF, 0xE3, 0xE3, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xF9, 0xFF, 0x1F, 0xF0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xCF, 0xFF, 0x8F,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x03, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x03, 0xFF, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xC3, 0xF8, 0x00,
- 0x03, 0xFF, 0x01, 0x83, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0x0F, 0x1F, 0x81, 0xF8, 0x00,
- 0x00, 0x00, 0xC0, 0xFF, 0xF8, 0xE0, 0x7F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0C, 0xFF, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x39,
- 0xC3, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0xC3, 0xFF, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x7F, 0x00,
- 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0xFF,
- 0xFF, 0xFF, 0xE6, 0x70, 0x00, 0x8F, 0x11, 0xC1, 0xFF, 0xFF, 0xC7, 0xF1, 0xFF, 0xFF, 0xF9,
- 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF3, 0xFC, 0xF9, 0xF3, 0xFF, 0xFF, 0xCF, 0xFC, 0xFF,
- 0xC3, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF, 0xCF, 0x9F, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xF3, 0xFF, 0x3F, 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F, 0xC3, 0xFC, 0xF9,
- 0xFF, 0xFC, 0x3F, 0x13, 0xFF, 0x3F, 0xC3, 0xF0, 0x3F, 0xC3, 0xFF, 0x3F, 0x03, 0xF1, 0xFF,
- 0xCF, 0x9F, 0x3F, 0xCE, 0x07, 0x0F, 0x08, 0xF1, 0xFF, 0xC8, 0xFF, 0xCF, 0xFF, 0xF1, 0xFE,
- 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xFC, 0xFF, 0xFF,
- 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3E, 0x3F, 0x9F, 0x39, 0xC3, 0xFC, 0x3F, 0xC3, 0xFF, 0xFF,
- 0xC3, 0xFF, 0xFF, 0xCC, 0xFF, 0x3F, 0xC2, 0x3F, 0x39, 0xC8, 0xF1, 0xFF, 0xCC, 0x7F, 0x3F,
- 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0x9C, 0xC7,
- 0x13, 0xE3, 0xFF, 0xFF, 0xCF, 0xF9, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7,
- 0xF3, 0xFC, 0xF9, 0xF3, 0xFF, 0xFF, 0xCF, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF,
- 0xCF, 0x9F, 0xCF, 0xFF, 0xCF, 0xC0, 0x3F, 0x3F, 0xFF, 0xF3, 0xFF, 0x3F, 0xC3, 0xFC, 0x3F,
- 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F, 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3E, 0x33, 0xFF, 0x3F,
- 0xC3, 0xE0, 0x3F, 0xC3, 0xFF, 0x3E, 0x03, 0xE3, 0xFF, 0xCF, 0x9F, 0x3F, 0xCC, 0x63, 0x06,
- 0x0C, 0x63, 0xFF, 0xCC, 0x7F, 0xCF, 0xFF, 0xE3, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
- 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xFC, 0xFF, 0xFF, 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3C,
- 0x7F, 0x9F, 0x39, 0xC3, 0xFC, 0x3F, 0xC0, 0x01, 0x80, 0x03, 0xFF, 0xFF, 0xCC, 0xFF, 0x3F,
- 0xC3, 0x1F, 0x39, 0xCC, 0x63, 0xFF, 0xCE, 0x3F, 0x3F, 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00,
- 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x1F, 0x9C, 0xE3, 0xF3, 0xC1, 0xFF, 0xFF, 0xCF, 0xF9,
- 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xF3, 0xFC, 0xF9, 0xF3, 0xFF, 0xFF,
- 0xCF, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0x8F, 0xC0,
- 0x3F, 0x1F, 0xF9, 0xF3, 0x80, 0x3F, 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F,
- 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3C, 0x73, 0xFF, 0x3F, 0xC3, 0xC4, 0x3F, 0xC3, 0xFF, 0x3C,
- 0x43, 0xC7, 0xFF, 0xCF, 0x9F, 0x3F, 0xC8, 0xF1, 0x20, 0x4E, 0x07, 0xFF, 0xCE, 0x3F, 0xCF,
- 0xFF, 0xC7, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFC, 0x3F, 0xF3, 0xFC, 0x00,
- 0x00, 0x03, 0x80, 0x03, 0xFC, 0xF9, 0xFF, 0xFC, 0x00, 0xFF, 0x9F, 0x39, 0xC3, 0xFC, 0x3F,
- 0xC0, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x0C, 0xFF, 0x3F, 0xC3, 0x8F, 0x39, 0xCE, 0x07, 0x80,
- 0x0F, 0x1F, 0x3F, 0xC3, 0xFF, 0x3F, 0xC2, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE6,
- 0x78, 0x00, 0xF1, 0xF1, 0x88, 0xFF, 0xFF, 0xCF, 0xF9, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xC0,
- 0x3F, 0xFF, 0xF1, 0xF3, 0x9C, 0xF9, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
- 0xC0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x0F, 0xF8, 0x13, 0x80, 0x00,
- 0x00, 0x00, 0x3F, 0xF3, 0xFC, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF9, 0xFF, 0xFC, 0x00,
- 0xF3, 0xFF, 0x39, 0xC3, 0x8C, 0x3F, 0xC0, 0x01, 0x3C, 0xC0, 0x01, 0x80, 0x0F, 0x9F, 0x3F,
- 0xC1, 0xF8, 0x30, 0xCF, 0x0F, 0x80, 0x0F, 0x1F, 0xCF, 0xFF, 0x8F, 0xFE, 0x7F, 0xFF, 0xFF,
- 0xFF, 0xFF, 0x00, 0x03, 0xFC, 0x3F, 0xF3, 0xFC, 0x00, 0x00, 0x03, 0x00, 0x03, 0xFC, 0xF9,
- 0xFF, 0xFC, 0x01, 0xFF, 0x9F, 0x39, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFF, 0x00,
- 0x1C, 0xFF, 0x3F, 0xC3, 0xC7, 0x39, 0xCE, 0x07, 0x00, 0x0F, 0x8F, 0x3F, 0xC3, 0xFF, 0x3F,
- 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE6, 0x70, 0x01, 0xF8, 0xF8, 0x1C, 0xFF,
- 0xFF, 0xCF, 0xF9, 0xF3, 0x9F, 0xC0, 0x3F, 0xFF, 0xC0, 0x3F, 0xFF, 0xF8, 0xF3, 0x9C, 0xF9,
- 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x0F, 0xFF, 0xCF,
- 0xFE, 0x0F, 0xFF, 0xFF, 0x07, 0xFC, 0x03, 0x9C, 0x00, 0x00, 0x03, 0x3F, 0xF3, 0xFC, 0x00,
- 0x00, 0x00, 0x30, 0x00, 0x00, 0xF9, 0xFF, 0xFC, 0x00, 0xF3, 0xFF, 0x30, 0xC3, 0x1C, 0x3F,
- 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0x9F, 0x3F, 0xC3, 0xFC, 0x39, 0xCF, 0x0F, 0x00,
- 0x0F, 0x8F, 0xCF, 0xFF, 0x1F, 0xFE, 0x79, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F,
- 0xF3, 0xFC, 0x3F, 0xCC, 0xFF, 0x3F, 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x38, 0xFF, 0x9F, 0x39,
- 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFF, 0x3F, 0xFC, 0xFF, 0x3F, 0xC3, 0xE3, 0x39,
- 0xCC, 0x63, 0x3F, 0xCF, 0xC7, 0x3F, 0xC3, 0xFF, 0x3F, 0xC8, 0x9F, 0x00, 0x00, 0x00, 0x3F,
- 0xFF, 0xFF, 0x80, 0x13, 0x9F, 0xFC, 0x7E, 0x0F, 0xFF, 0xFF, 0xCF, 0xF9, 0xF1, 0x1F, 0xF9,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x73, 0xFC, 0xF9, 0xFF, 0xFC, 0xFF, 0xC3, 0xFC, 0x3F,
- 0xF3, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F, 0xCF, 0xFF, 0xCF, 0xFF, 0x0F, 0xC0, 0x3F, 0x0F, 0xFF,
- 0xC3, 0x9C, 0x3F, 0xC3, 0xF9, 0x3F, 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F, 0xF3, 0xFC, 0xF9,
- 0xFF, 0xFC, 0x3C, 0x73, 0xFF, 0x20, 0x42, 0x3C, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F,
- 0xFF, 0x9F, 0x3F, 0xC3, 0xFC, 0x3F, 0xCE, 0x07, 0x3F, 0xCF, 0xC7, 0xCF, 0xFE, 0x3F, 0xFE,
- 0x78, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xCC, 0xFF, 0x3F,
- 0xC0, 0x00, 0xF9, 0xFF, 0xFC, 0x3C, 0x7F, 0x9F, 0x39, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F,
- 0xC3, 0xFF, 0x3F, 0xFC, 0xFF, 0x3F, 0xC3, 0xF1, 0x39, 0xC8, 0xF1, 0x3F, 0xCF, 0xE3, 0x3F,
- 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x13, 0x9F, 0x8E,
- 0x3C, 0xE7, 0xFF, 0xFF, 0xCF, 0xF9, 0xF8, 0x3F, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
- 0x33, 0xFC, 0xF9, 0xFF, 0xFC, 0xFF, 0xC3, 0xFC, 0x3F, 0xF3, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F,
- 0xCF, 0x9F, 0xFF, 0xFF, 0x8F, 0xC0, 0x3F, 0x1F, 0xFF, 0xC3, 0x9C, 0x3F, 0xC3, 0xF9, 0x3F,
- 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F, 0xF3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3E, 0x33, 0xFF, 0x06,
- 0x00, 0x7C, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F, 0xFF, 0x9F, 0x3F, 0xC3, 0xFC, 0x3F,
- 0xCC, 0x63, 0x3F, 0xCF, 0xE3, 0xCF, 0xFC, 0x7F, 0xFE, 0x7C, 0x63, 0xFF, 0xFF, 0xFF, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0x00, 0x00, 0x01, 0xE1, 0xFF, 0xF0, 0x3E,
- 0x3F, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
- 0xC3, 0xF8, 0x39, 0xC1, 0xF8, 0x3F, 0xC0, 0x00, 0x3F, 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00,
- 0x00, 0x00, 0x3F, 0xF3, 0x3F, 0xE6, 0x70, 0x00, 0x8F, 0x1C, 0xE7, 0x3F, 0xFF, 0xC7, 0xF1,
- 0xF8, 0x3F, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0xFC, 0xF9, 0xFF, 0xFC, 0xFF,
- 0xC3, 0xFC, 0x3F, 0xF3, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F, 0xCF, 0x9F, 0xFF, 0xFF, 0xCF, 0xFF,
- 0xFF, 0x3F, 0x3F, 0xC3, 0x9C, 0x3F, 0xC3, 0xF9, 0x3F, 0xF3, 0xF8, 0x3F, 0xF3, 0xFF, 0x3F,
- 0xF3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3F, 0x13, 0xFF, 0x0F, 0x00, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F,
- 0xC3, 0xFC, 0x3F, 0xFF, 0x9F, 0x3F, 0xC3, 0xFC, 0x3F, 0xC8, 0xF1, 0x3F, 0xCF, 0xF1, 0xCF,
- 0xF8, 0xFF, 0xFE, 0x7E, 0x07, 0xFF, 0xFC, 0xFF, 0x00, 0x10, 0x01, 0x80, 0x08, 0x00, 0x80,
- 0x1C, 0xFF, 0x80, 0x03, 0xFF, 0xE1, 0xFF, 0xF0, 0x3F, 0x1F, 0x9F, 0x00, 0x10, 0x01, 0x80,
- 0x10, 0x01, 0x80, 0x08, 0x00, 0x80, 0x00, 0x00, 0x3F, 0xC3, 0xFC, 0x39, 0xC3, 0xFC, 0x3F,
- 0xC0, 0x00, 0x3F, 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xF3, 0x3F, 0xE6,
- 0x78, 0x00, 0x8F, 0x9C, 0x07, 0x3F, 0xFF, 0xE3, 0xE3, 0xF1, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x0F, 0xFC, 0x3F,
- 0x83, 0xFF, 0x1F, 0x81, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
- 0xC3, 0xFC, 0x3F, 0xC1, 0xF8, 0x3F, 0xC0, 0x00, 0xC0, 0xF1, 0xFF, 0xE0, 0x7F, 0x0F, 0xFF,
- 0xF8, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xFF, 0xF3, 0xFF, 0xFF,
- 0xFF, 0xFF, 0x3F, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0x00,
- 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xF3, 0x3F, 0xFF, 0xFF, 0x9F, 0xFF, 0xFE, 0x0F, 0x3F,
- 0xFF, 0xF3, 0xE7, 0xF3, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x01,
- 0xF0, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x18, 0x01, 0x80, 0x10, 0x03, 0x80, 0x00, 0x03, 0x80,
- 0x08, 0x00, 0x80, 0x03, 0xFC, 0x00, 0x0F, 0xFC, 0x3F, 0xC3, 0xFF, 0x3F, 0xC3, 0xFC, 0x80,
- 0x10, 0x01, 0x80, 0x10, 0x01, 0x80, 0x00, 0x00, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F,
- 0xC0, 0x00, 0xC0, 0xF3, 0xFF, 0xE0, 0x7F, 0x9F, 0xFF, 0xF9, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF,
- 0xFF, 0xFC, 0xFF, 0xFE, 0x00, 0xFF, 0xF3, 0xFF, 0xF9, 0xFF, 0xFC, 0x3F, 0xFE, 0x1F, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00,
- }};
-#endif // FONT5_H_
\ No newline at end of file
--- /dev/null
+++ b/src/fonts/font1.h
@@ -1,0 +1,56 @@
+#ifndef FONT1_H_
+#define FONT1_H_
+
+#include "inline_font.h"
+
+struct inline_font font_v1_small = {+ 470,
+ 7,
+ 5,
+ 7,
+ 0,
+ 0,
+ 3,
+ 24,
+ 566,
+ {+ 0x42, 0x4D, 0x36, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
+ 0x00, 0x00, 0x00, 0xD6, 0x01, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xA4, 0x01, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
+ 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x80, 0x00, 0x40, 0x34,
+ 0x01, 0x80, 0x00, 0x40, 0x12, 0x1F, 0xFF, 0xFE, 0x1F, 0xFC, 0x9E, 0x08, 0x10, 0x00, 0x00,
+ 0x8E, 0x8F, 0x9D, 0xEF, 0xC1, 0xD1, 0xFB, 0xA3, 0xF8, 0xC5, 0xD0, 0x6C, 0x7C, 0x47, 0x12,
+ 0x31, 0xF7, 0xC6, 0x1C, 0x03, 0xE0, 0xFF, 0xFF, 0xFF, 0x93, 0xF1, 0x77, 0x22, 0xEA, 0xC7,
+ 0xF0, 0x0C, 0x3E, 0x7F, 0xE3, 0xF1, 0xFF, 0xFE, 0x4F, 0x80, 0x00, 0x00, 0x15, 0xF9, 0xC8,
+ 0x02, 0x40, 0x08, 0x40, 0x02, 0x11, 0x24, 0x02, 0x10, 0xC4, 0x91, 0x0A, 0x10, 0x20, 0x20,
+ 0x10, 0x8C, 0x63, 0x18, 0x42, 0x31, 0x24, 0x65, 0x08, 0xC6, 0x30, 0x94, 0x42, 0x48, 0xAB,
+ 0x71, 0x0C, 0x04, 0x14, 0x00, 0x00, 0x8C, 0x61, 0x18, 0x10, 0x31, 0x20, 0xB4, 0x4A, 0xC6,
+ 0x3F, 0xFC, 0x02, 0x48, 0xD2, 0xAA, 0x0A, 0x22, 0x48, 0x80, 0x00, 0x80, 0x3E, 0x55, 0xD4,
+ 0x02, 0x40, 0x08, 0x00, 0x01, 0x19, 0x24, 0x02, 0x10, 0xC4, 0x91, 0x08, 0x00, 0x6F, 0xB0,
+ 0x97, 0x8C, 0x61, 0x18, 0x42, 0x71, 0x24, 0x69, 0x08, 0xC6, 0x30, 0xAC, 0x82, 0x48, 0xAA,
+ 0xAA, 0x0A, 0x04, 0x24, 0x00, 0x00, 0xFC, 0x61, 0x1F, 0x93, 0xF1, 0x20, 0xA8, 0x4A, 0xC6,
+ 0x31, 0x8C, 0x3E, 0x48, 0xCA, 0xA4, 0xF9, 0x22, 0x48, 0x80, 0x00, 0x80, 0x15, 0xF2, 0x24,
+ 0x02, 0x42, 0xBE, 0x0F, 0x80, 0x95, 0x27, 0xFF, 0xFF, 0xFC, 0x5F, 0xF8, 0x00, 0xE0, 0x38,
+ 0x55, 0xFF, 0xA1, 0x1F, 0x7A, 0x1F, 0x20, 0x71, 0x08, 0xCE, 0x3E, 0x8F, 0x9C, 0x48, 0xC6,
+ 0x24, 0x79, 0x04, 0x44, 0x00, 0x00, 0x0C, 0x61, 0x18, 0x92, 0x31, 0x20, 0xA4, 0x4A, 0xC6,
+ 0x31, 0x8C, 0x20, 0x48, 0xC6, 0xAA, 0x88, 0xA2, 0x4A, 0x80, 0x00, 0x80, 0x3F, 0x4D, 0x50,
+ 0x02, 0x41, 0x08, 0x00, 0x00, 0x53, 0x20, 0x43, 0x18, 0x40, 0x31, 0x8A, 0x10, 0x6F, 0xB0,
+ 0x37, 0x8C, 0x61, 0x18, 0x42, 0x11, 0x20, 0x69, 0x0A, 0xD6, 0x31, 0x8C, 0x60, 0x48, 0xC6,
+ 0x2A, 0x88, 0x84, 0x84, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x60, 0xA2, 0x4F, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xF8, 0xC6, 0xB1, 0x8F, 0xE2, 0x48, 0xD8, 0x00, 0x82, 0x95, 0xFC, 0xC8,
+ 0x82, 0x42, 0x88, 0x00, 0x00, 0x31, 0xE0, 0x43, 0x18, 0x40, 0x31, 0x88, 0x00, 0x20, 0x22,
+ 0x31, 0x8C, 0x63, 0x18, 0x42, 0x31, 0x20, 0x65, 0x0D, 0xE6, 0x31, 0x8C, 0x60, 0x48, 0xC6,
+ 0x31, 0x88, 0x45, 0x04, 0x28, 0x04, 0x04, 0x00, 0x10, 0x10, 0x10, 0x00, 0x20, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x22, 0x48, 0xA4, 0x00, 0x82, 0x80, 0x40, 0x30,
+ 0x81, 0x80, 0x00, 0x00, 0x00, 0x3F, 0x27, 0xFF, 0x1F, 0xFF, 0xEF, 0xF8, 0x00, 0x00, 0x01,
+ 0xCE, 0x77, 0x9D, 0xEF, 0xFD, 0xD1, 0xF8, 0x63, 0x08, 0xC5, 0xDE, 0x77, 0x9F, 0xF8, 0xC6,
+ 0x31, 0x8F, 0xC7, 0x0C, 0x10, 0x08, 0x04, 0x00, 0x10, 0x1C, 0x10, 0x20, 0xA0, 0xC0, 0x00,
+ 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x3E, 0x4F, 0x80, 0x00,
+ }};
+#endif // FONT1_H_
\ No newline at end of file
--- /dev/null
+++ b/src/fonts/font2.h
@@ -1,0 +1,85 @@
+#ifndef FONT2_H_
+#define FONT2_H_
+#include "inline_font.h"
+
+struct inline_font font_v1_large = {+ 752,
+ 9,
+ 8,
+ 9,
+ 0,
+ -40,
+ 4,
+ 22,
+ 1010,
+ {+ 0x42, 0x4D, 0xF2, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
+ 0x00, 0x00, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
+ 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCF, 0xFF, 0xFF, 0xE7,
+ 0x7D, 0x84, 0xFF, 0xFC, 0x9F, 0xFF, 0xFF, 0x9F, 0xFF, 0x9F, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0xFC, 0x00, 0x00, 0xE7, 0x01, 0xFC, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xE7, 0x81, 0x3C, 0x01,
+ 0x81, 0x03, 0x00, 0x3F, 0x81, 0x3C, 0x00, 0x81, 0x3C, 0x00, 0x3C, 0x3C, 0x81, 0x3F, 0x84,
+ 0x3C, 0x81, 0xE7, 0x81, 0xE7, 0x3C, 0x3C, 0xE7, 0x00, 0xF0, 0xFF, 0x0F, 0xFF, 0x80, 0xFF,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x3C, 0x00, 0x00, 0x3C, 0x00, 0x24, 0x3C, 0x00,
+ 0x3F, 0xFC, 0x3F, 0x00, 0x80, 0x00, 0x3F, 0x00, 0x3C, 0x00, 0x00, 0x00, 0xE7, 0x00, 0xFF,
+ 0x00, 0x00, 0xFF, 0xFF, 0xDB, 0x00, 0x38, 0x39, 0xFF, 0xF9, 0xCF, 0xFF, 0xFF, 0xCF, 0xFF,
+ 0xFF, 0x3F, 0x3C, 0xE7, 0x3F, 0xFC, 0xFC, 0xFC, 0x3C, 0xE7, 0x3C, 0xFC, 0xFF, 0x9F, 0xFC,
+ 0xFF, 0x9F, 0xFF, 0x3F, 0x3C, 0x3C, 0x3C, 0x39, 0x3F, 0x3F, 0x3C, 0x3C, 0xE7, 0x3C, 0x39,
+ 0x3F, 0x3C, 0x3C, 0x3C, 0x3F, 0x39, 0x39, 0x3C, 0xE7, 0x3C, 0xC3, 0x18, 0x3C, 0xE7, 0x3F,
+ 0xF3, 0xFC, 0xCF, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0x3F, 0x3C, 0x3F, 0x9F, 0xFC, 0x3C, 0xE7,
+ 0xFC, 0x39, 0xCF, 0x24, 0x3C, 0x3C, 0x3F, 0xFC, 0x3F, 0xFC, 0x9F, 0x3C, 0x1F, 0x24, 0x99,
+ 0xFC, 0x9F, 0x3C, 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0x81, 0xE4, 0x9D, 0x30, 0xFF,
+ 0xF3, 0xE7, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0x9F, 0x3C, 0xE7, 0x3F, 0xFC, 0xFC, 0xFC, 0x3C,
+ 0xE7, 0x3C, 0xFC, 0xE7, 0x9F, 0xF8, 0x81, 0x8F, 0xE7, 0x21, 0x3C, 0x3C, 0x3F, 0x3C, 0x3F,
+ 0x3F, 0x3C, 0x3C, 0xE7, 0x3C, 0x33, 0x3F, 0x3C, 0x3C, 0x3C, 0x3F, 0x32, 0x33, 0xFC, 0xE7,
+ 0x3C, 0x99, 0x00, 0x99, 0xE7, 0x9F, 0xF3, 0xF9, 0xCF, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0x3F,
+ 0x3C, 0x3F, 0x9F, 0xFC, 0x3C, 0xE7, 0xFC, 0x33, 0xCF, 0x24, 0x3C, 0x3C, 0x3F, 0xFC, 0x3F,
+ 0xFC, 0x9F, 0x3C, 0x0F, 0x24, 0xC3, 0xFC, 0xCF, 0x3C, 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xCF,
+ 0xFF, 0xDB, 0xE4, 0xCF, 0x87, 0xFF, 0xF3, 0xE7, 0xFF, 0xE7, 0xFF, 0xFF, 0xFF, 0xCF, 0x3C,
+ 0xE7, 0x3F, 0xFC, 0xFC, 0xFC, 0x3C, 0xE7, 0x3C, 0xFC, 0xFF, 0xFF, 0xF0, 0xFF, 0x87, 0xE7,
+ 0x24, 0x3C, 0x3C, 0x3F, 0x3C, 0x3F, 0x3F, 0x3C, 0x3C, 0xE7, 0xFC, 0x27, 0x3F, 0x3C, 0x38,
+ 0x3C, 0x3F, 0x24, 0x27, 0xFC, 0xE7, 0x3C, 0x3C, 0x24, 0xC3, 0xE7, 0xCF, 0xF3, 0xF3, 0xCF,
+ 0xFF, 0xFF, 0xFF, 0x00, 0x3C, 0x3F, 0x3C, 0x00, 0x9F, 0x00, 0x3C, 0xE7, 0xFC, 0x07, 0xCF,
+ 0x24, 0x3C, 0x3C, 0x00, 0x00, 0x3F, 0x00, 0x9F, 0x3C, 0x27, 0x24, 0xE7, 0x00, 0xE7, 0x3C,
+ 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xCF, 0xFF, 0xDB, 0x00, 0xE7, 0xC7, 0xFF, 0xF3, 0xE7, 0x33,
+ 0x81, 0xFF, 0x81, 0xFF, 0xE7, 0x24, 0xE7, 0x00, 0x80, 0x00, 0x00, 0x00, 0xF3, 0x81, 0x00,
+ 0xFF, 0xFF, 0xE0, 0xFF, 0x83, 0xE1, 0x24, 0x00, 0x01, 0x3F, 0x3C, 0x03, 0x03, 0x30, 0x00,
+ 0xE7, 0xFC, 0x0F, 0x3F, 0x3C, 0x30, 0x3C, 0x01, 0x3C, 0x01, 0x81, 0xE7, 0x3C, 0x3C, 0x3C,
+ 0xE7, 0x81, 0xE7, 0xF3, 0xE7, 0xCF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3C, 0x3F, 0x3C, 0x3C, 0x9F,
+ 0x3C, 0x3C, 0xE7, 0xFC, 0x33, 0xCF, 0x24, 0x3C, 0x3C, 0x3C, 0x3C, 0x3F, 0x3F, 0x9F, 0x3C,
+ 0x33, 0x24, 0xC3, 0x3C, 0xF3, 0x3C, 0xE7, 0x3C, 0x23, 0x00, 0x00, 0xCF, 0xFF, 0x81, 0x27,
+ 0xF3, 0x93, 0xFF, 0xF3, 0xE7, 0x87, 0xE7, 0xFF, 0xFF, 0xFF, 0xF3, 0x3C, 0xE7, 0xFC, 0xFC,
+ 0x3C, 0x3F, 0x3F, 0xF9, 0x3C, 0x3C, 0xE7, 0x9F, 0xF0, 0xFF, 0x87, 0xFC, 0x20, 0x3C, 0x3B,
+ 0x3F, 0x3C, 0x3F, 0x3F, 0x3F, 0x3C, 0xE7, 0xFC, 0x27, 0x3F, 0x24, 0x24, 0x3C, 0x3C, 0x3C,
+ 0x3C, 0x3F, 0xE7, 0x3C, 0x3C, 0x3C, 0xC3, 0x3C, 0xF3, 0xF3, 0xCF, 0xCF, 0xFF, 0xFF, 0xFF,
+ 0xFC, 0x3C, 0x3F, 0x3C, 0x3C, 0x00, 0x3C, 0x3C, 0xE7, 0xFC, 0x39, 0xCF, 0x24, 0x3C, 0x3C,
+ 0x3C, 0x3C, 0x3F, 0x3F, 0x9F, 0x3C, 0x39, 0x24, 0x99, 0x3C, 0xF9, 0x3C, 0xE7, 0x3C, 0x89,
+ 0x00, 0x00, 0xCF, 0xC9, 0xDB, 0x27, 0xB9, 0x93, 0xE7, 0xF3, 0xE7, 0xCF, 0xE7, 0xFF, 0xFF,
+ 0xFF, 0xF9, 0x3C, 0xE7, 0xFC, 0xFC, 0x3C, 0x3F, 0x3F, 0xFC, 0x3C, 0x3C, 0xFF, 0xFF, 0xF8,
+ 0x81, 0x8F, 0xFC, 0x3C, 0x3C, 0x39, 0x3F, 0x3C, 0x3F, 0x3F, 0x3F, 0x3C, 0xE7, 0xFC, 0x33,
+ 0x3F, 0x00, 0x0C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3F, 0xE7, 0x3C, 0x3C, 0x3C, 0x99, 0x3C, 0xF9,
+ 0xF3, 0x9F, 0xCF, 0x27, 0xFF, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9F, 0x00, 0x00, 0x87,
+ 0x80, 0x3C, 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x3C, 0x24, 0x3C,
+ 0x3C, 0x00, 0x3C, 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xCF, 0xC9, 0xFF, 0x00, 0x1C, 0xC7, 0xE7,
+ 0xF9, 0xCF, 0x87, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x3C, 0xE7, 0xFC, 0xFC, 0x3C, 0x3F, 0x3F,
+ 0xFC, 0x9C, 0x3C, 0xFF, 0xFF, 0xFC, 0xFF, 0x9F, 0x3C, 0x3C, 0x99, 0x39, 0x3C, 0x39, 0x3F,
+ 0x3F, 0x3C, 0x3C, 0xE7, 0xFC, 0x39, 0x3F, 0x18, 0x1C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0xE7,
+ 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0xFC, 0xF3, 0x3F, 0xCF, 0x8F, 0xFF, 0x9F, 0xFF, 0x3F, 0xFF,
+ 0xFC, 0xFF, 0x9F, 0xFF, 0x3F, 0xFF, 0xFF, 0x3F, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0xE7, 0x3C, 0xFF, 0x00, 0x00, 0xCF,
+ 0xC9, 0xFF, 0xE7, 0xBE, 0xFF, 0xE7, 0xFC, 0x9F, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+ 0x87, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x81,
+ 0x81, 0xC3, 0x03, 0x81, 0x03, 0x00, 0x00, 0x81, 0x3C, 0x00, 0x00, 0x3C, 0x3F, 0x3C, 0x3C,
+ 0x81, 0x01, 0x81, 0x01, 0x81, 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0xF0, 0xFF, 0x0F,
+ 0xDF, 0xFF, 0x3F, 0xFF, 0x3F, 0xFF, 0xFC, 0xFF, 0x80, 0xFF, 0x3F, 0xE7, 0xFC, 0x3F, 0x0F,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00,
+ 0xE7, 0x00, 0xFF, 0x00, 0x00,
+ }};
+#endif // FONT2_H_
\ No newline at end of file
--- /dev/null
+++ b/src/fonts/font3.h
@@ -1,0 +1,93 @@
+#ifndef FONT3_H_
+#define FONT3_H_
+
+#include "inline_font.h"
+
+struct inline_font font_v2_small = {+ 846,
+ 9,
+ 9,
+ 9,
+ 0,
+ -2,
+ 5,
+ 38,
+ 1118,
+ {+ 0x42, 0x4D, 0x5E, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
+ 0x00, 0x00, 0x00, 0x4E, 0x03, 0x00, 0x00, 0x09, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xCC, 0x03, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
+ 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xF7, 0x7E,
+ 0xF7, 0xC4, 0x3B, 0xFF, 0xFE, 0x7F, 0xFF, 0xFF, 0xEF, 0xFF, 0xFB, 0xFD, 0xFE, 0x00, 0x00,
+ 0x00, 0x00, 0x1F, 0xE0, 0x00, 0x03, 0xFC, 0x00, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xDE, 0x00, 0x7F, 0x00, 0x00, 0x00, 0x30, 0x03, 0xFC, 0x00, 0xFE, 0x00, 0x00, 0x1F, 0xC0,
+ 0x07, 0xF3, 0xF8, 0x00, 0xFF, 0x01, 0x3F, 0x80, 0x1E, 0xF0, 0x07, 0xBD, 0xFC, 0xFE, 0x00,
+ 0x00, 0x3C, 0x7F, 0xEE, 0x3F, 0xFC, 0x01, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC,
+ 0x00, 0xFE, 0x00, 0x00, 0x1F, 0xC0, 0x07, 0x73, 0xF8, 0x00, 0xFF, 0xFF, 0x3F, 0xC0, 0x00,
+ 0x00, 0x00, 0xFC, 0x00, 0xFE, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x07, 0xFC, 0x00, 0x00, 0xFF,
+ 0xFF, 0xF7, 0x60, 0x0B, 0xD3, 0xD7, 0xFF, 0xFD, 0xBF, 0xFF, 0xFD, 0xEF, 0xFF, 0xFF, 0xFE,
+ 0xFE, 0xFE, 0xF7, 0xBF, 0xFF, 0xDF, 0xEF, 0xF3, 0xFB, 0xFC, 0xFE, 0xFF, 0x7F, 0xDF, 0xFF,
+ 0x3F, 0xFF, 0x3F, 0xFE, 0xFF, 0x7F, 0x3F, 0x9F, 0xEF, 0xD7, 0xFB, 0xFD, 0xFC, 0xFE, 0xF7,
+ 0xFF, 0x9F, 0xAF, 0xF7, 0xF3, 0xF1, 0xFC, 0xFF, 0x7E, 0xBF, 0x7F, 0xDE, 0xF7, 0xF7, 0x5C,
+ 0xF9, 0x7D, 0xFF, 0x5F, 0xFD, 0xFF, 0xDF, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x9F, 0xEF,
+ 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0xF7, 0xFF, 0x9F, 0xAF, 0xF7, 0x73, 0xF9, 0xFC, 0xFF, 0xFF,
+ 0x3F, 0xFF, 0xCF, 0xF7, 0xF3, 0x7D, 0xDD, 0x7D, 0xFF, 0x3F, 0xDF, 0xCF, 0xF7, 0xF7, 0xFC,
+ 0x00, 0x00, 0x7F, 0xFF, 0xC0, 0x1E, 0xED, 0xC3, 0xEF, 0xFF, 0xFB, 0xDF, 0xFF, 0xFD, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x7E, 0xFE, 0xF7, 0xBF, 0xFF, 0xDF, 0xEF, 0xF3, 0xFB, 0xFC, 0xFE, 0xFF,
+ 0x3F, 0xDF, 0xFE, 0x38, 0x0F, 0x1F, 0xDE, 0x80, 0x7F, 0x3F, 0x9F, 0xEF, 0xE7, 0xFB, 0xFD,
+ 0xFC, 0xFE, 0xF7, 0xFF, 0x9F, 0x6F, 0xF7, 0xF3, 0xE9, 0xFC, 0xFF, 0x7D, 0x3E, 0xFF, 0xDE,
+ 0xF7, 0xF6, 0xED, 0x75, 0xBB, 0xFF, 0x6F, 0xFD, 0xFF, 0xBF, 0xBF, 0xFF, 0xFF, 0xFF, 0x7F,
+ 0x3F, 0x9F, 0xEF, 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0xF7, 0xFF, 0x9F, 0x6F, 0xF7, 0x73, 0xF9,
+ 0xFC, 0x00, 0x00, 0x3F, 0xFF, 0xCF, 0xF7, 0xF3, 0xBD, 0xDD, 0xBB, 0xFF, 0x4F, 0xDF, 0xCF,
+ 0xF7, 0xF7, 0xFC, 0x00, 0x00, 0x7F, 0xFF, 0xF7, 0x7E, 0xEE, 0xFB, 0xD7, 0xFF, 0xFB, 0xDF,
+ 0xFF, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xBE, 0xFE, 0xF7, 0xBF, 0xFF, 0xDF, 0xEF, 0xF3, 0xFB,
+ 0xFC, 0xFE, 0xFF, 0x7F, 0xFF, 0xFC, 0x3F, 0xFF, 0x0F, 0xDE, 0xBA, 0x7F, 0x3F, 0x9F, 0xEF,
+ 0xE7, 0xFB, 0xFD, 0xFC, 0xFE, 0xF7, 0xFF, 0x9E, 0xEF, 0xF7, 0xF3, 0xD9, 0xFC, 0xFF, 0x7B,
+ 0x3D, 0xFF, 0xDE, 0xF7, 0xF5, 0xF5, 0xAD, 0xD7, 0xFF, 0x77, 0xFD, 0xFF, 0x7F, 0xBF, 0xFF,
+ 0xFF, 0xFF, 0x00, 0x3F, 0x9F, 0xEF, 0xE0, 0x00, 0x0C, 0x00, 0xFE, 0xF7, 0xFF, 0x80, 0xEF,
+ 0xF7, 0x73, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0xC0, 0x0F, 0xF7, 0xF3, 0xDD, 0xDD, 0xC7, 0x00,
+ 0x71, 0xDF, 0xCF, 0xF7, 0xF7, 0xFC, 0x00, 0x00, 0x7F, 0xFF, 0xF7, 0x60, 0x0F, 0x7D, 0xBB,
+ 0xFF, 0xFB, 0xDF, 0xDD, 0xE0, 0x3F, 0xF8, 0x0F, 0xFF, 0xDE, 0xEE, 0xF7, 0x80, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x7F, 0xFF, 0xF8, 0x3F, 0xFF, 0x07, 0xC0, 0x82, 0x00,
+ 0x00, 0x1F, 0xEF, 0xE0, 0x00, 0x01, 0xC0, 0x00, 0xF7, 0xFF, 0x81, 0xEF, 0xF7, 0x73, 0xB9,
+ 0xFC, 0x00, 0x7F, 0x00, 0x00, 0x1E, 0xF7, 0xF3, 0xF9, 0xDD, 0xEF, 0x00, 0x7B, 0xFD, 0xFE,
+ 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x9F, 0xEF, 0xE7, 0xF3, 0xFD, 0xFC, 0xFE, 0xF7,
+ 0xFF, 0x9F, 0x6F, 0xF7, 0x73, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0xDF, 0xEF, 0xF7, 0xF3, 0xED,
+ 0xDD, 0xBB, 0x7F, 0x7E, 0x5F, 0xCF, 0xF7, 0xF3, 0x3C, 0x00, 0x00, 0x7F, 0xFF, 0xF7, 0x6E,
+ 0xFF, 0xBE, 0x7F, 0xFF, 0xFB, 0xDF, 0xEB, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0xFE, 0xF7,
+ 0xFF, 0xBF, 0xCF, 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0x7F, 0x7F, 0xFF, 0xFC, 0x3F, 0xFF, 0x0F,
+ 0xFC, 0xFA, 0x7F, 0x3E, 0xDF, 0xEF, 0xE7, 0xFB, 0xFD, 0xFE, 0xFE, 0xF7, 0xFF, 0x9E, 0xEF,
+ 0xF6, 0xB3, 0x79, 0xFC, 0xFE, 0x7F, 0x3F, 0x9F, 0xFE, 0xF7, 0xF3, 0xF9, 0xFD, 0xD7, 0x7F,
+ 0x7D, 0xFD, 0xFD, 0xFF, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x9F, 0xEF, 0xE7, 0xF3, 0xFD,
+ 0xFC, 0xFE, 0xF7, 0xFF, 0x9F, 0xAF, 0xF7, 0x73, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0xDF, 0xEF,
+ 0xF7, 0xF3, 0xF5, 0xDD, 0x7D, 0x7F, 0x7F, 0x9F, 0xCF, 0xF7, 0xF4, 0xDC, 0x00, 0x00, 0x7F,
+ 0xB7, 0xC0, 0x0E, 0xF1, 0xDD, 0xBD, 0xFF, 0xFB, 0xDF, 0xF7, 0xFD, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF6, 0xFE, 0xF7, 0xFF, 0xBF, 0xCF, 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0x7F, 0x3F, 0xDF, 0xFE,
+ 0x38, 0x0F, 0x1F, 0xFC, 0x82, 0x7F, 0x3E, 0xDF, 0xEF, 0xE7, 0xFB, 0xFD, 0xFE, 0xFE, 0xF7,
+ 0xFF, 0x9F, 0x6F, 0xF5, 0xD2, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0x9F, 0xFE, 0xF7, 0xF3, 0xF9,
+ 0xFD, 0xBB, 0x7F, 0x7E, 0xFD, 0xFB, 0xFF, 0xBB, 0xBF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, 0x1F, 0xCF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0xF3, 0xF9, 0xDC, 0xFE, 0x7F, 0x00, 0x1F, 0xCF, 0xF7, 0xF7, 0xFC,
+ 0x00, 0x00, 0x7F, 0xB7, 0xF7, 0x60, 0x05, 0xED, 0xBD, 0xFF, 0xFD, 0xBF, 0xEB, 0xFD, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFA, 0xFE, 0xF7, 0xFF, 0xBF, 0xCF, 0xE7, 0xFB, 0xFF, 0xFC, 0xFE, 0x7F,
+ 0x7F, 0xFF, 0xFF, 0x3F, 0xFF, 0x3D, 0xFC, 0xFE, 0x7F, 0x3E, 0xDF, 0xEF, 0xD7, 0xFB, 0xFD,
+ 0xFE, 0xFE, 0xF7, 0xFF, 0x9F, 0xAF, 0xF3, 0xE1, 0xF9, 0xFC, 0xFE, 0x7F, 0x3F, 0x9F, 0xFE,
+ 0xF7, 0xF3, 0xF9, 0xFD, 0x7D, 0x7F, 0x7F, 0x7D, 0xF7, 0xFF, 0xBD, 0x7F, 0xFF, 0xBF, 0xFF,
+ 0xBF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDF, 0xCF,
+ 0xF7, 0xF7, 0xFC, 0x00, 0x00, 0x7F, 0xB7, 0xF7, 0x7E, 0xF1, 0xF6, 0x7D, 0xFF, 0xFE, 0x7F,
+ 0xDD, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x07, 0x80, 0x00, 0x0F, 0xE0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x00,
+ 0x30, 0x00, 0x00, 0x00, 0xFE, 0x00, 0x7F, 0x9F, 0xCF, 0xF7, 0xF3, 0xF8, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x07, 0xF3, 0xF9, 0xFC, 0xFE, 0x7F, 0x00, 0x3C, 0x6F, 0xFE, 0x3E, 0xFF,
+ 0xFF, 0x7F, 0xFF, 0xBF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xC0, 0x0F, 0xF0, 0x07, 0xFC, 0x00, 0x00,
+ }};
+#endif // FONT3_H_
\ No newline at end of file
--- /dev/null
+++ b/src/fonts/font4.h
@@ -1,0 +1,108 @@
+#ifndef FONT4_H_
+#define FONT4_H_
+
+#include "inline_font.h"
+
+struct inline_font font_v2_large = {+ 940,
+ 10,
+ 10,
+ 10,
+ 0,
+ -2,
+ 4,
+ 38,
+ 1346,
+ {+ 0x42, 0x4D, 0x42, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
+ 0x00, 0x00, 0x00, 0xAC, 0x03, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xB0, 0x04, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
+ 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0xCF,
+ 0xCF, 0x3E, 0x60, 0xCF, 0xFF, 0xF9, 0x3F, 0xFF, 0xFF, 0xFD, 0xFF, 0xFF, 0xE7, 0xF3, 0xFC,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x3F, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0x03, 0x3F, 0x00, 0x18, 0x00, 0x01, 0x80, 0x0F, 0xF8, 0x04,
+ 0xFC, 0x00, 0x00, 0x13, 0xF2, 0x00, 0x3F, 0x0F, 0xC8, 0x04, 0xFF, 0x83, 0x0F, 0xC0, 0x07,
+ 0xCF, 0x80, 0x7C, 0xF3, 0xF0, 0xFC, 0x00, 0x40, 0x0F, 0x0F, 0xFC, 0xE1, 0xFF, 0xF0, 0x03,
+ 0xFF, 0x80, 0x00, 0x18, 0x02, 0x00, 0x80, 0x33, 0xF0, 0x04, 0xFC, 0x00, 0x00, 0x13, 0xE0,
+ 0x00, 0x33, 0x0F, 0xC8, 0x04, 0xFF, 0xFF, 0x0F, 0xF0, 0x07, 0x80, 0x80, 0x43, 0xF8, 0x00,
+ 0xFC, 0x00, 0x40, 0x00, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0xCC,
+ 0x01, 0x1E, 0x40, 0x0F, 0xFF, 0xF1, 0x1F, 0xFF, 0xFF, 0x3C, 0xFF, 0xFF, 0xE7, 0xF1, 0xFC,
+ 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0xFF, 0x3F, 0xFC, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0x03, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00,
+ 0xFC, 0x00, 0x00, 0x03, 0xE0, 0x00, 0x3F, 0x0F, 0x80, 0x00, 0xFF, 0x06, 0x0F, 0x80, 0x03,
+ 0xCF, 0x00, 0x38, 0x71, 0xE0, 0x78, 0x00, 0x00, 0x0F, 0x0F, 0xF8, 0xE1, 0xFF, 0xF0, 0x03,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0xF0, 0x00, 0xFC, 0x00, 0x00, 0x03, 0xC4,
+ 0x00, 0x33, 0x0F, 0xC0, 0x00, 0xFF, 0xFF, 0x0F, 0xF0, 0x03, 0x00, 0x00, 0x01, 0xF0, 0x00,
+ 0x78, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0xFF, 0xFF, 0xF0, 0x00,
+ 0x00, 0x8F, 0xCE, 0x1F, 0xFF, 0xE3, 0x8F, 0xFF, 0xFF, 0x3C, 0xFF, 0xFF, 0xFF, 0xF8, 0xFC,
+ 0xFC, 0xF3, 0xCF, 0xFF, 0xF3, 0xFC, 0xFF, 0x0F, 0xCF, 0xF0, 0xFC, 0xFF, 0x33, 0xFC, 0xFF,
+ 0xE7, 0x80, 0x79, 0xFF, 0xFC, 0xFF, 0x3F, 0x0F, 0xC3, 0xFC, 0xFC, 0x3F, 0xCF, 0xF3, 0xF0,
+ 0xFC, 0xF3, 0xFF, 0xC3, 0xC4, 0xFF, 0x3F, 0x0F, 0x03, 0xF0, 0xFF, 0x3C, 0x0F, 0x1F, 0xF3,
+ 0xCF, 0x3F, 0x30, 0x30, 0xC2, 0x31, 0xFF, 0x23, 0xFF, 0x3F, 0xF1, 0xF9, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x3F, 0x0F, 0xC3, 0xFC, 0xFC, 0x3F, 0xF3, 0xFF, 0xF0, 0xFC, 0xF3, 0xFF, 0xC3, 0x8F,
+ 0xCF, 0x33, 0x0F, 0xC3, 0xF0, 0x01, 0x80, 0x0F, 0xFF, 0xF3, 0x3F, 0x3F, 0x08, 0xF3, 0x32,
+ 0x31, 0xFF, 0x03, 0xF3, 0xF0, 0xFF, 0x3F, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x03,
+ 0xCC, 0xC7, 0xCE, 0x1F, 0xFF, 0xE7, 0xCF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFC, 0x7C,
+ 0xFC, 0xF3, 0xCF, 0xFF, 0xF3, 0xFC, 0xFF, 0x0F, 0xCF, 0xF0, 0xFC, 0xFF, 0x33, 0xFC, 0xFF,
+ 0xC7, 0x80, 0x78, 0xFF, 0x3C, 0xC0, 0x3F, 0x0F, 0xC3, 0xFC, 0xFC, 0x3F, 0xCF, 0xF3, 0xF0,
+ 0xFC, 0xF3, 0xFF, 0xC3, 0x8C, 0xFF, 0x3F, 0x0E, 0x03, 0xF0, 0xFF, 0x38, 0x0E, 0x3F, 0xF3,
+ 0xCF, 0x3F, 0x23, 0x10, 0x03, 0x03, 0xFF, 0x31, 0xFF, 0x3F, 0xE3, 0xF9, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x0F, 0xC3, 0xFC, 0xFC, 0x00, 0x33, 0xF8, 0x00, 0xFC, 0xF3, 0xFF, 0xC0, 0x1F,
+ 0xCF, 0x33, 0x0F, 0xC3, 0xF0, 0x00, 0x00, 0x0F, 0xF8, 0x03, 0x3F, 0x3F, 0x0C, 0x73, 0x33,
+ 0x03, 0x80, 0x20, 0x73, 0xF0, 0xFF, 0x3F, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0xCE,
+ 0x00, 0xE3, 0xC0, 0x0F, 0xFF, 0xE7, 0xCF, 0xCE, 0x78, 0x07, 0xFF, 0x80, 0x7F, 0xFE, 0x3C,
+ 0xCC, 0xF3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
+ 0x87, 0xFF, 0xF8, 0x7F, 0x04, 0xC0, 0x00, 0x00, 0x03, 0xFC, 0xFC, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0xF3, 0xFF, 0xC0, 0x1C, 0xFF, 0x33, 0x0C, 0x43, 0xF0, 0x01, 0x31, 0x00, 0x18, 0x03,
+ 0xCF, 0x3F, 0x07, 0x82, 0x13, 0x87, 0x80, 0x38, 0xFF, 0x3F, 0xC7, 0xF9, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x00, 0x0F, 0xC3, 0xFC, 0xFC, 0x00, 0x33, 0xF0, 0x00, 0xFC, 0xF3, 0xFF, 0xC0, 0x3F,
+ 0xCF, 0x33, 0x0F, 0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xF0, 0x07, 0x3F, 0x3F, 0x0E, 0x33, 0x33,
+ 0x03, 0x00, 0x38, 0x13, 0xF0, 0xFF, 0x3F, 0x08, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFC, 0xCC,
+ 0x01, 0xF1, 0xE0, 0xCF, 0xFF, 0xE7, 0xCF, 0xC4, 0x78, 0x07, 0xFF, 0x80, 0x7F, 0xFF, 0x1C,
+ 0xCC, 0xF3, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
+ 0x07, 0xFF, 0xF8, 0x3F, 0x00, 0xCC, 0x00, 0x00, 0x33, 0xFC, 0xFC, 0x00, 0x00, 0x03, 0x00,
+ 0x00, 0xF3, 0xFF, 0xC0, 0x1C, 0xFF, 0x21, 0x08, 0xC3, 0xF0, 0x00, 0x33, 0x00, 0x00, 0x07,
+ 0xCF, 0x3F, 0x0F, 0xC3, 0x33, 0x87, 0x00, 0x3C, 0x7F, 0x3F, 0x8F, 0xF9, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x0F, 0xC3, 0xFC, 0xFC, 0x3F, 0x00, 0x33, 0xF0, 0xFC, 0xF3, 0xFF, 0xC3, 0x1F,
+ 0xCF, 0x33, 0x0F, 0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xF3, 0xFF, 0x3F, 0x3F, 0x0F, 0x13, 0x32,
+ 0x31, 0x3F, 0x3F, 0x03, 0xF0, 0xFF, 0x3F, 0x00, 0x70, 0x00, 0x00, 0x3F, 0xFF, 0xF0, 0x00,
+ 0xCF, 0xF8, 0xE6, 0x7F, 0xFF, 0xE7, 0xCF, 0xF1, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0x8C,
+ 0xFC, 0xF3, 0xFF, 0xCF, 0xF0, 0xFC, 0x3F, 0xCF, 0xFF, 0xF0, 0xFC, 0x3F, 0x33, 0xFC, 0xFF,
+ 0x87, 0x80, 0x78, 0x7F, 0xF0, 0xCC, 0x3F, 0x0F, 0x93, 0xFC, 0xFC, 0x3F, 0xCF, 0xF3, 0xFC,
+ 0xFC, 0xF3, 0xFF, 0xC3, 0x8C, 0xFF, 0x00, 0x01, 0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xC3, 0xFF,
+ 0xCF, 0x3F, 0x0F, 0xC3, 0xF3, 0x03, 0x3F, 0x3E, 0x3F, 0x3F, 0x1F, 0xF9, 0xE6, 0x7F, 0xFF,
+ 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0xC3, 0xFF, 0x03, 0x8F,
+ 0xCF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x0F, 0x83, 0x30,
+ 0x78, 0x3F, 0x00, 0x03, 0xF0, 0xFF, 0x3F, 0x22, 0x70, 0x00, 0x00, 0x3F, 0xC9, 0xF0, 0x00,
+ 0x00, 0xFC, 0x66, 0x73, 0xFF, 0xE3, 0x8F, 0xF1, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xC4,
+ 0xFC, 0xF3, 0xFF, 0xCF, 0xF0, 0xFC, 0x3F, 0xCF, 0xFF, 0xF0, 0xFC, 0x3F, 0x33, 0xFC, 0xFF,
+ 0xC7, 0x80, 0x78, 0xF3, 0xF0, 0xFC, 0x3F, 0x0F, 0x93, 0xFC, 0xF8, 0x3F, 0xCF, 0xF3, 0xFC,
+ 0xFC, 0xF3, 0xFF, 0xC3, 0xC4, 0xFF, 0x0C, 0x03, 0xC3, 0xF0, 0xFC, 0x3F, 0x0F, 0xC3, 0xFF,
+ 0xCF, 0x3F, 0x0F, 0xC3, 0xF2, 0x31, 0x3F, 0x3F, 0x1F, 0x3E, 0x3F, 0xF9, 0xE0, 0x7F, 0xFF,
+ 0x3F, 0x00, 0x40, 0x18, 0x02, 0x00, 0x80, 0x73, 0xF8, 0x00, 0x01, 0xC3, 0xFF, 0x03, 0xC7,
+ 0xCF, 0x00, 0x40, 0x18, 0x04, 0x01, 0x80, 0x20, 0x08, 0x00, 0x00, 0x3F, 0x0F, 0xC3, 0x30,
+ 0xFC, 0x3F, 0x00, 0x03, 0xF0, 0xFF, 0x3F, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xC9, 0xFC, 0xCE,
+ 0x00, 0x9E, 0x20, 0x73, 0xFF, 0xF1, 0x1F, 0xC4, 0x7F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0,
+ 0x00, 0x03, 0xC0, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
+ 0xE7, 0xFF, 0xF9, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+ 0xFC, 0x00, 0x3F, 0xC3, 0xE0, 0xFF, 0x1E, 0x07, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3F, 0x0F, 0xC3, 0xF0, 0x78, 0x3F, 0x00, 0x0F, 0x0C, 0x7F, 0xE1, 0xF0, 0xFF, 0xFE,
+ 0x3F, 0xFF, 0xCF, 0xFF, 0xFF, 0xFC, 0xFF, 0xF0, 0x0F, 0xFC, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF,
+ 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x00, 0x00, 0x3F, 0xC9, 0xFC, 0xCF,
+ 0xCF, 0x9F, 0x30, 0xF3, 0xFF, 0xF9, 0x3F, 0xCE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0,
+ 0x00, 0x03, 0xC0, 0x00, 0x00, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xF8, 0x06, 0x01, 0x80, 0x40, 0x38, 0x00, 0x03, 0x80, 0x20, 0x08, 0x00,
+ 0xFC, 0x00, 0x3F, 0xC3, 0xF0, 0xFF, 0x3F, 0x0F, 0xC8, 0x04, 0x01, 0x80, 0x40, 0x18, 0x00,
+ 0x00, 0x3F, 0x0F, 0xC3, 0xF0, 0xFC, 0x3F, 0x00, 0x0F, 0x0C, 0xFF, 0xE1, 0xF9, 0xFF, 0xFE,
+ 0x7F, 0xFF, 0xCF, 0xFF, 0xFF, 0xFC, 0xFF, 0xF8, 0x0F, 0xFC, 0xFF, 0xF3, 0xFF, 0xC3, 0xFF,
+ 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xF0, 0x00, 0xFF, 0x00, 0x3F, 0xF0, 0x00, 0x00,
+ }};
+#endif // FONT4_H_
\ No newline at end of file
--- /dev/null
+++ b/src/fonts/font5.h
@@ -1,0 +1,143 @@
+#ifndef FONT5_H_
+#define FONT5_H_
+
+#include "inline_font.h"
+
+struct inline_font font_v2_huge = {+ 1128,
+ 12,
+ 12,
+ 12,
+ 0,
+ -54,
+ 4,
+ 24,
+ 1874,
+ {+ 0x42, 0x4D, 0x52, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x7C,
+ 0x00, 0x00, 0x00, 0x68, 0x04, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xC0, 0x06, 0x00, 0x00, 0x13, 0x0B, 0x00, 0x00, 0x13, 0x0B, 0x00,
+ 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF,
+ 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x9F, 0xFF, 0xFC, 0x1C, 0xFF, 0xFF, 0xF3, 0xE7, 0xFF, 0xFF, 0xFF, 0xF7, 0xFF, 0xFF,
+ 0xF9, 0xFF, 0x3F, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0xFF,
+ 0xC0, 0x00, 0xFF, 0xCF, 0xFF, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF8, 0x03, 0x3F,
+ 0xC0, 0x01, 0x80, 0x00, 0x01, 0x80, 0x03, 0xFF, 0x80, 0x13, 0xFC, 0x00, 0x00, 0x01, 0x3F,
+ 0xC8, 0x00, 0x3F, 0xC3, 0xFC, 0x80, 0x13, 0xFF, 0x80, 0xC3, 0xFC, 0x00, 0x1F, 0x9F, 0x80,
+ 0x1F, 0x9F, 0x3F, 0xC3, 0xFC, 0x00, 0x10, 0x00, 0xC0, 0xFF, 0xFC, 0xE0, 0x7F, 0xFF, 0x00,
+ 0x0F, 0xFF, 0x80, 0x00, 0x01, 0x80, 0x08, 0x00, 0x80, 0x0C, 0xFF, 0x00, 0x13, 0xFC, 0x00,
+ 0x00, 0x01, 0x3F, 0x80, 0x00, 0x39, 0xC3, 0xFC, 0x80, 0x13, 0xFF, 0xFF, 0xC3, 0xFF, 0x00,
+ 0x1E, 0x00, 0x80, 0x10, 0xFF, 0x80, 0x03, 0xFC, 0x00, 0x10, 0x00, 0x00, 0x03, 0xFF, 0x00,
+ 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE6, 0x70, 0x01, 0x9F, 0x18, 0x08, 0xFF,
+ 0xFF, 0xE3, 0xE3, 0xFF, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xF9, 0xFF, 0x1F, 0xF0, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0F, 0xFC, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0xFF, 0xCF, 0xFF, 0x8F,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF0, 0x03, 0x3F, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0xFF, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0x80, 0x00, 0x3F, 0xC3, 0xF8, 0x00,
+ 0x03, 0xFF, 0x01, 0x83, 0xF8, 0x00, 0x0F, 0x9F, 0x00, 0x0F, 0x0F, 0x1F, 0x81, 0xF8, 0x00,
+ 0x00, 0x00, 0xC0, 0xFF, 0xF8, 0xE0, 0x7F, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0C, 0xFF, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x3F, 0x10, 0x00, 0x39,
+ 0xC3, 0xFC, 0x00, 0x03, 0xFF, 0xFF, 0xC3, 0xFF, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x7F, 0x00,
+ 0x01, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00, 0xFF,
+ 0xFF, 0xFF, 0xE6, 0x70, 0x00, 0x8F, 0x11, 0xC1, 0xFF, 0xFF, 0xC7, 0xF1, 0xFF, 0xFF, 0xF9,
+ 0xF3, 0xFF, 0xFF, 0xFF, 0xFF, 0x8F, 0xF3, 0xFC, 0xF9, 0xF3, 0xFF, 0xFF, 0xCF, 0xFC, 0xFF,
+ 0xC3, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF, 0xCF, 0x9F, 0xCF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xF3, 0xFF, 0x3F, 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F, 0xC3, 0xFC, 0xF9,
+ 0xFF, 0xFC, 0x3F, 0x13, 0xFF, 0x3F, 0xC3, 0xF0, 0x3F, 0xC3, 0xFF, 0x3F, 0x03, 0xF1, 0xFF,
+ 0xCF, 0x9F, 0x3F, 0xCE, 0x07, 0x0F, 0x08, 0xF1, 0xFF, 0xC8, 0xFF, 0xCF, 0xFF, 0xF1, 0xFE,
+ 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xFC, 0xFF, 0xFF,
+ 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3E, 0x3F, 0x9F, 0x39, 0xC3, 0xFC, 0x3F, 0xC3, 0xFF, 0xFF,
+ 0xC3, 0xFF, 0xFF, 0xCC, 0xFF, 0x3F, 0xC2, 0x3F, 0x39, 0xC8, 0xF1, 0xFF, 0xCC, 0x7F, 0x3F,
+ 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x80, 0x1F, 0x9C, 0xC7,
+ 0x13, 0xE3, 0xFF, 0xFF, 0xCF, 0xF9, 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC7,
+ 0xF3, 0xFC, 0xF9, 0xF3, 0xFF, 0xFF, 0xCF, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF,
+ 0xCF, 0x9F, 0xCF, 0xFF, 0xCF, 0xC0, 0x3F, 0x3F, 0xFF, 0xF3, 0xFF, 0x3F, 0xC3, 0xFC, 0x3F,
+ 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F, 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3E, 0x33, 0xFF, 0x3F,
+ 0xC3, 0xE0, 0x3F, 0xC3, 0xFF, 0x3E, 0x03, 0xE3, 0xFF, 0xCF, 0x9F, 0x3F, 0xCC, 0x63, 0x06,
+ 0x0C, 0x63, 0xFF, 0xCC, 0x7F, 0xCF, 0xFF, 0xE3, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F,
+ 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xFC, 0xFF, 0xFF, 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3C,
+ 0x7F, 0x9F, 0x39, 0xC3, 0xFC, 0x3F, 0xC0, 0x01, 0x80, 0x03, 0xFF, 0xFF, 0xCC, 0xFF, 0x3F,
+ 0xC3, 0x1F, 0x39, 0xCC, 0x63, 0xFF, 0xCE, 0x3F, 0x3F, 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00,
+ 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x1F, 0x9C, 0xE3, 0xF3, 0xC1, 0xFF, 0xFF, 0xCF, 0xF9,
+ 0xFF, 0xFF, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE3, 0xF3, 0xFC, 0xF9, 0xF3, 0xFF, 0xFF,
+ 0xCF, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF, 0xC3, 0xFC, 0xFF, 0xCF, 0xFF, 0xFF, 0xFF, 0x8F, 0xC0,
+ 0x3F, 0x1F, 0xF9, 0xF3, 0x80, 0x3F, 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F,
+ 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3C, 0x73, 0xFF, 0x3F, 0xC3, 0xC4, 0x3F, 0xC3, 0xFF, 0x3C,
+ 0x43, 0xC7, 0xFF, 0xCF, 0x9F, 0x3F, 0xC8, 0xF1, 0x20, 0x4E, 0x07, 0xFF, 0xCE, 0x3F, 0xCF,
+ 0xFF, 0xC7, 0xFE, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFC, 0x3F, 0xF3, 0xFC, 0x00,
+ 0x00, 0x03, 0x80, 0x03, 0xFC, 0xF9, 0xFF, 0xFC, 0x00, 0xFF, 0x9F, 0x39, 0xC3, 0xFC, 0x3F,
+ 0xC0, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x0C, 0xFF, 0x3F, 0xC3, 0x8F, 0x39, 0xCE, 0x07, 0x80,
+ 0x0F, 0x1F, 0x3F, 0xC3, 0xFF, 0x3F, 0xC2, 0x3F, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE6,
+ 0x78, 0x00, 0xF1, 0xF1, 0x88, 0xFF, 0xFF, 0xCF, 0xF9, 0xFF, 0xFF, 0xC0, 0x3F, 0xFF, 0xC0,
+ 0x3F, 0xFF, 0xF1, 0xF3, 0x9C, 0xF9, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
+ 0xC0, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0x0F, 0xFF, 0xFF, 0x0F, 0xF8, 0x13, 0x80, 0x00,
+ 0x00, 0x00, 0x3F, 0xF3, 0xFC, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0xF9, 0xFF, 0xFC, 0x00,
+ 0xF3, 0xFF, 0x39, 0xC3, 0x8C, 0x3F, 0xC0, 0x01, 0x3C, 0xC0, 0x01, 0x80, 0x0F, 0x9F, 0x3F,
+ 0xC1, 0xF8, 0x30, 0xCF, 0x0F, 0x80, 0x0F, 0x1F, 0xCF, 0xFF, 0x8F, 0xFE, 0x7F, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x00, 0x03, 0xFC, 0x3F, 0xF3, 0xFC, 0x00, 0x00, 0x03, 0x00, 0x03, 0xFC, 0xF9,
+ 0xFF, 0xFC, 0x01, 0xFF, 0x9F, 0x39, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFF, 0x00,
+ 0x1C, 0xFF, 0x3F, 0xC3, 0xC7, 0x39, 0xCE, 0x07, 0x00, 0x0F, 0x8F, 0x3F, 0xC3, 0xFF, 0x3F,
+ 0xC0, 0x1F, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xE6, 0x70, 0x01, 0xF8, 0xF8, 0x1C, 0xFF,
+ 0xFF, 0xCF, 0xF9, 0xF3, 0x9F, 0xC0, 0x3F, 0xFF, 0xC0, 0x3F, 0xFF, 0xF8, 0xF3, 0x9C, 0xF9,
+ 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xC0, 0x00, 0x00, 0x0F, 0xFF, 0xCF,
+ 0xFE, 0x0F, 0xFF, 0xFF, 0x07, 0xFC, 0x03, 0x9C, 0x00, 0x00, 0x03, 0x3F, 0xF3, 0xFC, 0x00,
+ 0x00, 0x00, 0x30, 0x00, 0x00, 0xF9, 0xFF, 0xFC, 0x00, 0xF3, 0xFF, 0x30, 0xC3, 0x1C, 0x3F,
+ 0xC0, 0x00, 0x3F, 0xC0, 0x00, 0x00, 0x1F, 0x9F, 0x3F, 0xC3, 0xFC, 0x39, 0xCF, 0x0F, 0x00,
+ 0x0F, 0x8F, 0xCF, 0xFF, 0x1F, 0xFE, 0x79, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F,
+ 0xF3, 0xFC, 0x3F, 0xCC, 0xFF, 0x3F, 0xC3, 0xFC, 0xF9, 0xFF, 0xFC, 0x38, 0xFF, 0x9F, 0x39,
+ 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFF, 0x3F, 0xFC, 0xFF, 0x3F, 0xC3, 0xE3, 0x39,
+ 0xCC, 0x63, 0x3F, 0xCF, 0xC7, 0x3F, 0xC3, 0xFF, 0x3F, 0xC8, 0x9F, 0x00, 0x00, 0x00, 0x3F,
+ 0xFF, 0xFF, 0x80, 0x13, 0x9F, 0xFC, 0x7E, 0x0F, 0xFF, 0xFF, 0xCF, 0xF9, 0xF1, 0x1F, 0xF9,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0x73, 0xFC, 0xF9, 0xFF, 0xFC, 0xFF, 0xC3, 0xFC, 0x3F,
+ 0xF3, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F, 0xCF, 0xFF, 0xCF, 0xFF, 0x0F, 0xC0, 0x3F, 0x0F, 0xFF,
+ 0xC3, 0x9C, 0x3F, 0xC3, 0xF9, 0x3F, 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F, 0xF3, 0xFC, 0xF9,
+ 0xFF, 0xFC, 0x3C, 0x73, 0xFF, 0x20, 0x42, 0x3C, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F,
+ 0xFF, 0x9F, 0x3F, 0xC3, 0xFC, 0x3F, 0xCE, 0x07, 0x3F, 0xCF, 0xC7, 0xCF, 0xFE, 0x3F, 0xFE,
+ 0x78, 0xF1, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F, 0xF3, 0xFC, 0x3F, 0xCC, 0xFF, 0x3F,
+ 0xC0, 0x00, 0xF9, 0xFF, 0xFC, 0x3C, 0x7F, 0x9F, 0x39, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F,
+ 0xC3, 0xFF, 0x3F, 0xFC, 0xFF, 0x3F, 0xC3, 0xF1, 0x39, 0xC8, 0xF1, 0x3F, 0xCF, 0xE3, 0x3F,
+ 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0x80, 0x13, 0x9F, 0x8E,
+ 0x3C, 0xE7, 0xFF, 0xFF, 0xCF, 0xF9, 0xF8, 0x3F, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
+ 0x33, 0xFC, 0xF9, 0xFF, 0xFC, 0xFF, 0xC3, 0xFC, 0x3F, 0xF3, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F,
+ 0xCF, 0x9F, 0xFF, 0xFF, 0x8F, 0xC0, 0x3F, 0x1F, 0xFF, 0xC3, 0x9C, 0x3F, 0xC3, 0xF9, 0x3F,
+ 0xF3, 0xFC, 0x3F, 0xF3, 0xFF, 0x3F, 0xF3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3E, 0x33, 0xFF, 0x06,
+ 0x00, 0x7C, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F, 0xFF, 0x9F, 0x3F, 0xC3, 0xFC, 0x3F,
+ 0xCC, 0x63, 0x3F, 0xCF, 0xE3, 0xCF, 0xFC, 0x7F, 0xFE, 0x7C, 0x63, 0xFF, 0xFF, 0xFF, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0xFF, 0x00, 0x00, 0x01, 0xE1, 0xFF, 0xF0, 0x3E,
+ 0x3F, 0x9F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+ 0xC3, 0xF8, 0x39, 0xC1, 0xF8, 0x3F, 0xC0, 0x00, 0x3F, 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00,
+ 0x00, 0x00, 0x3F, 0xF3, 0x3F, 0xE6, 0x70, 0x00, 0x8F, 0x1C, 0xE7, 0x3F, 0xFF, 0xC7, 0xF1,
+ 0xF8, 0x3F, 0xF9, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x13, 0xFC, 0xF9, 0xFF, 0xFC, 0xFF,
+ 0xC3, 0xFC, 0x3F, 0xF3, 0xFF, 0xFF, 0xC3, 0xFC, 0x3F, 0xCF, 0x9F, 0xFF, 0xFF, 0xCF, 0xFF,
+ 0xFF, 0x3F, 0x3F, 0xC3, 0x9C, 0x3F, 0xC3, 0xF9, 0x3F, 0xF3, 0xF8, 0x3F, 0xF3, 0xFF, 0x3F,
+ 0xF3, 0xFC, 0xF9, 0xFF, 0xFC, 0x3F, 0x13, 0xFF, 0x0F, 0x00, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F,
+ 0xC3, 0xFC, 0x3F, 0xFF, 0x9F, 0x3F, 0xC3, 0xFC, 0x3F, 0xC8, 0xF1, 0x3F, 0xCF, 0xF1, 0xCF,
+ 0xF8, 0xFF, 0xFE, 0x7E, 0x07, 0xFF, 0xFC, 0xFF, 0x00, 0x10, 0x01, 0x80, 0x08, 0x00, 0x80,
+ 0x1C, 0xFF, 0x80, 0x03, 0xFF, 0xE1, 0xFF, 0xF0, 0x3F, 0x1F, 0x9F, 0x00, 0x10, 0x01, 0x80,
+ 0x10, 0x01, 0x80, 0x08, 0x00, 0x80, 0x00, 0x00, 0x3F, 0xC3, 0xFC, 0x39, 0xC3, 0xFC, 0x3F,
+ 0xC0, 0x00, 0x3F, 0xC3, 0xFF, 0x3F, 0xCF, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xF3, 0x3F, 0xE6,
+ 0x78, 0x00, 0x8F, 0x9C, 0x07, 0x3F, 0xFF, 0xE3, 0xE3, 0xF1, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0x80, 0x00, 0x01, 0xF0, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x0F, 0xFC, 0x3F,
+ 0x83, 0xFF, 0x1F, 0x81, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F,
+ 0xC3, 0xFC, 0x3F, 0xC1, 0xF8, 0x3F, 0xC0, 0x00, 0xC0, 0xF1, 0xFF, 0xE0, 0x7F, 0x0F, 0xFF,
+ 0xF8, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xFF, 0xF3, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0x3F, 0xFE, 0x1F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0x00,
+ 0x0F, 0xFF, 0x00, 0x00, 0x00, 0x3F, 0xF3, 0x3F, 0xFF, 0xFF, 0x9F, 0xFF, 0xFE, 0x0F, 0x3F,
+ 0xFF, 0xF3, 0xE7, 0xF3, 0x9F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x00, 0x01,
+ 0xF0, 0x00, 0x00, 0x03, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x80, 0x18, 0x01, 0x80, 0x10, 0x03, 0x80, 0x00, 0x03, 0x80,
+ 0x08, 0x00, 0x80, 0x03, 0xFC, 0x00, 0x0F, 0xFC, 0x3F, 0xC3, 0xFF, 0x3F, 0xC3, 0xFC, 0x80,
+ 0x10, 0x01, 0x80, 0x10, 0x01, 0x80, 0x00, 0x00, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC, 0x3F,
+ 0xC0, 0x00, 0xC0, 0xF3, 0xFF, 0xE0, 0x7F, 0x9F, 0xFF, 0xF9, 0xFF, 0xFF, 0xF3, 0xFF, 0xFF,
+ 0xFF, 0xFC, 0xFF, 0xFE, 0x00, 0xFF, 0xF3, 0xFF, 0xF9, 0xFF, 0xFC, 0x3F, 0xFE, 0x1F, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0x00, 0x0F, 0xFF, 0x00, 0x00, 0x00,
+ }};
+#endif // FONT5_H_
\ No newline at end of file
--- /dev/null
+++ b/src/fonts/inline_font.h
@@ -1,0 +1,17 @@
+#ifndef INLINE_FONT_H_
+#define INLINE_FONT_H_
+
+struct inline_font {+ const int width;
+ const int height;
+ const int glyph_x;
+ const int glyph_y;
+ const int screen_offset_x;
+ const int screen_offset_y;
+ const int text_offset_y;
+ const int waveform_max_height;
+ const long image_size;
+ const unsigned char image_data[];
+};
+
+#endif
--- a/src/fx_cube.c
+++ b/src/fx_cube.c
@@ -4,6 +4,8 @@
#include <math.h>
+// Handle screensaver cube effect
+
static SDL_Texture *texture_cube;
static SDL_Texture *texture_text;
static SDL_Renderer *fx_renderer;
--- a/src/inline_font.h
+++ /dev/null
@@ -1,17 +1,0 @@
-#ifndef INLINE_FONT_H_
-#define INLINE_FONT_H_
-
-struct inline_font {- const int width;
- const int height;
- const int glyph_x;
- const int glyph_y;
- const int screen_offset_x;
- const int screen_offset_y;
- const int text_offset_y;
- const int waveform_max_height;
- const long image_size;
- const unsigned char image_data[];
-};
-
-#endif
--- a/src/inprint2.c
+++ b/src/inprint2.c
@@ -2,7 +2,7 @@
// https://github.com/driedfruit/SDL_inprint Released into public domain.
// Modified to support multiple fonts & adding a background to text.
-#include "inline_font.h"
+#include "fonts/inline_font.h"
#include <SDL3/SDL.h>
#define CHARACTERS_PER_ROW 94
@@ -17,7 +17,7 @@
static struct inline_font *selected_inline_font;
static Uint16 selected_font_w, selected_font_h;
-void prepare_inline_font(struct inline_font *font) {+void inline_font_initialize(struct inline_font *font) {selected_font_w = font->width;
selected_font_h = font->height;
@@ -43,12 +43,12 @@
selected_font = inline_font;
}
-void kill_inline_font(void) {+void inline_font_close(void) {SDL_DestroyTexture(inline_font);
inline_font = NULL;
}
-void inrenderer(SDL_Renderer *renderer) { selected_renderer = renderer; }+void inline_font_set_renderer(SDL_Renderer *renderer) { selected_renderer = renderer; } void infont(SDL_Texture *font) {--- a/src/input.c
+++ b/src/input.c
@@ -1,4 +1,6 @@
#include "input.h"
+#include "backends/audio.h"
+#include "backends/m8.h"
#include "config.h"
#include "gamecontrollers.h"
#include "render.h"
@@ -12,6 +14,55 @@
static input_msg_s key = {normal, 0, 0, 0};+int input_process(config_params_s conf, enum app_state *app_state) {+ static uint8_t prev_input = 0;
+ static uint8_t prev_note = 0;
+
+ // get current inputs
+ const input_msg_s input = input_get_msg(&conf);
+
+ switch (input.type) {+ case normal:
+ if (input.value != prev_input) {+ prev_input = input.value;
+ m8_send_msg_controller(input.value);
+ }
+ break;
+ case keyjazz:
+ if (input.value != 0) {+ if (input.eventType == SDL_EVENT_KEY_DOWN && input.value != prev_input) {+ m8_send_msg_keyjazz(input.value, input.value2);
+ prev_note = input.value;
+ } else if (input.eventType == SDL_EVENT_KEY_UP && input.value == prev_note) {+ m8_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.");
+ *app_state = 0;
+ break;
+ case msg_reset_display:
+ m8_reset_display();
+ break;
+ case msg_toggle_audio:
+ conf.audio_enabled = !conf.audio_enabled;
+ audio_toggle(conf.audio_device_name, conf.audio_buffer_size);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+ return 1;
+}
+
uint8_t toggle_input_keyjazz() {keyjazz_enabled = !keyjazz_enabled;
SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, keyjazz_enabled ? "Keyjazz enabled" : "Keyjazz disabled");
@@ -289,7 +340,7 @@
}
// Returns the currently pressed keys to main
-input_msg_s get_input_msg(config_params_s *conf) {+input_msg_s input_get_msg(config_params_s *conf) { key = (input_msg_s){normal, 0, 0, 0};--- a/src/input.h
+++ b/src/input.h
@@ -7,6 +7,8 @@
#include "config.h"
#include <stdint.h>
+enum app_state { QUIT, WAIT_FOR_DEVICE, RUN };+
typedef enum input_buttons_t {INPUT_UP,
INPUT_DOWN,
@@ -46,6 +48,7 @@
uint32_t eventType;
} input_msg_s;
-input_msg_s get_input_msg(config_params_s *conf);
+input_msg_s input_get_msg(config_params_s *conf);
+int input_process(config_params_s conf, enum app_state *app_state);
#endif
--- a/src/main.c
+++ b/src/main.c
@@ -9,32 +9,83 @@
#include <signal.h>
#include "SDL2_inprint.h"
-#include "audio.h"
+#include "backends/audio.h"
+#include "backends/m8.h"
#include "command.h"
#include "config.h"
#include "gamecontrollers.h"
#include "input.h"
#include "render.h"
-#include "serial.h"
-#include "slip.h"
-enum state { QUIT, WAIT_FOR_DEVICE, RUN };+enum app_state app_state = WAIT_FOR_DEVICE;
-enum state run = WAIT_FOR_DEVICE;
-uint8_t need_display_reset = 0;
+// Handle CTRL+C / SIGINT, SIGKILL etc.
+void signal_handler(int unused) {+ (void)unused;
+ app_state = QUIT;
+}
-// Handles CTRL+C / SIGINT
-void intHandler() { run = QUIT; }+void do_wait_for_device(const char *preferred_device, unsigned char *m8_connected,
+ config_params_s *conf) {+ static Uint64 ticks_poll_device = 0;
+ static Uint64 ticks_update_screen = 0;
-void close_serial_port() { disconnect(); }+ if (*m8_connected == 0) {+ screensaver_init();
+ }
+ while (app_state == WAIT_FOR_DEVICE) {+ // get current input
+ const input_msg_s input = input_get_msg(&*conf);
+ if (input.type == special && input.value == msg_quit) {+ SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Input message QUIT.");
+ app_state = QUIT;
+ }
+
+ if (SDL_GetTicks() - ticks_update_screen > 16) {+ ticks_update_screen = SDL_GetTicks();
+ screensaver_draw();
+ render_screen();
+ }
+
+ // Poll for M8 device every second
+ if (*m8_connected == 0 && SDL_GetTicks() - ticks_poll_device > 1000) {+ ticks_poll_device = SDL_GetTicks();
+ if (app_state == WAIT_FOR_DEVICE && m8_initialize(0, preferred_device) == 1) {+
+ if (conf->audio_enabled == 1) {+ if (audio_initialize(conf->audio_device_name, conf->audio_buffer_size) == 0) {+ SDL_LogError(SDL_LOG_CATEGORY_AUDIO, "Cannot initialize audio");
+ conf->audio_enabled = 0;
+ }
+ }
+
+ const int m8_enabled = m8_enable_and_reset_display();
+ // Device was found; enable display and proceed to the main loop
+ if (m8_enabled == 1) {+ app_state = RUN;
+ *m8_connected = 1;
+ screensaver_destroy();
+ } else {+ SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Device not detected.");
+ app_state = QUIT;
+ screensaver_destroy();
+ }
+ }
+ }
+ SDL_Delay(conf->idle_ms);
+ }
+}
+
int main(const int argc, char *argv[]) {+ char *preferred_device = NULL;
+ unsigned char m8_connected = 0;
+
if (argc == 2 && SDL_strcmp(argv[1], "--list") == 0) {- return list_devices();
+ return m8_list_devices();
}
- char *preferred_device = NULL;
if (argc == 3 && SDL_strcmp(argv[1], "--dev") == 0) {preferred_device = argv[2];
SDL_Log("Using preferred device %s.\n", preferred_device);@@ -46,262 +97,104 @@
SDL_Log("Using config file %s.\n", config_filename);}
- // Initialize the config to defaults read in the params from the
- // configfile if present
- config_params_s conf = init_config(config_filename);
- read_config(&conf);
+ // Initialize the config to defaults
+ config_params_s conf = config_initialize(config_filename);
+ // Read in the params from the configfile if present
+ config_read(&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.
if (conf.wait_for_device == 0) {- port_inited = init_serial(1, preferred_device);
- if (port_inited == 0) {- SDL_free(serial_buf);
+ m8_connected = m8_initialize(1, preferred_device);
+ if (m8_connected == 0) {return 1;
}
}
// initialize all SDL systems
- if (initialize_sdl(conf.init_fullscreen) == false) {- SDL_free(serial_buf);
+ if (renderer_initialize(conf.init_fullscreen) == false) {SDL_Quit();
return 1;
}
- run = QUIT;
+ app_state = QUIT;
// initial scan for (existing) gamepads
gamecontrollers_initialize();
-#ifdef DEBUG_MSG
- SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
+#ifndef NDEBUG
+ SDL_SetLogPriorities(SDL_LOG_PRIORITY_DEBUG);
+ SDL_LogDebug(SDL_LOG_CATEGORY_TEST, "Running a Debug build");
#endif
// main loop begin
do {- // try to init serial port
- port_inited = init_serial(1, preferred_device);
- // if port init was successful, try to enable and reset display
- if (port_inited == 1 && enable_and_reset_display() == 1) {- // if audio routing is enabled, try to initialize audio devices
+ // try to init connection to M8
+ m8_connected = m8_initialize(1, preferred_device);
+ if (m8_connected == 1 && m8_enable_and_reset_display() == 1) { if (conf.audio_enabled == 1) {- audio_init(conf.audio_device_name, conf.audio_buffer_size);
+ audio_initialize(conf.audio_device_name, conf.audio_buffer_size);
// if audio is enabled, reset the display for second time to avoid glitches
- reset_display();
+ m8_reset_display();
}
- run = RUN;
+ app_state = RUN;
} else {- SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Device not detected on begin loop.");
+ SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Device not detected on initial check.");
if (conf.wait_for_device == 1) {- run = WAIT_FOR_DEVICE;
+ app_state = WAIT_FOR_DEVICE;
} else {- run = QUIT;
+ app_state = QUIT;
}
}
// wait until device is connected
if (conf.wait_for_device == 1) {- static uint32_t ticks_poll_device = 0;
- static uint32_t ticks_update_screen = 0;
-
- if (port_inited == 0) {- screensaver_init();
- }
-
- while (run == WAIT_FOR_DEVICE) {- // 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.");
- run = QUIT;
- }
-
- if (SDL_GetTicks() - ticks_update_screen > 16) {- ticks_update_screen = SDL_GetTicks();
- screensaver_draw();
- render_screen();
- }
-
- // Poll for M8 device every second
- if (port_inited == 0 && SDL_GetTicks() - ticks_poll_device > 1000) {- ticks_poll_device = SDL_GetTicks();
- if (run == WAIT_FOR_DEVICE && init_serial(0, preferred_device) == 1) {-
- if (conf.audio_enabled == 1) {- if (audio_init(conf.audio_device_name, conf.audio_buffer_size) == 0) {- SDL_Log("Cannot initialize audio");- conf.audio_enabled = 0;
- }
- }
-
- const int result = enable_and_reset_display();
- // Device was found; enable display and proceed to the main loop
- if (result == 1) {- run = RUN;
- port_inited = 1;
- screensaver_destroy();
- } else {- SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Device not detected.");
- run = QUIT;
- screensaver_destroy();
- }
- }
- }
- SDL_Delay(conf.idle_ms);
- }
+ do_wait_for_device(preferred_device, &m8_connected, &conf);
} else {// classic startup behaviour, exit if device is not found
- if (port_inited == 0) {+ if (m8_connected == 0) { if (conf.audio_enabled == 1) {- audio_destroy();
+ audio_close();
}
gamecontrollers_close();
- close_renderer();
- kill_inline_font();
- SDL_free(serial_buf);
+ renderer_close();
+ inline_font_close();
SDL_Quit();
- return -1;
+ return 1;
}
}
// main loop
- while (run == RUN) {-
- // 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;
- }
+ while (app_state == RUN) {+ input_process(conf, &app_state);
+ const int result = m8_process_data(conf);
+ if (result == 0) {+ // Device disconnected
+ m8_connected = 0;
+ app_state = WAIT_FOR_DEVICE;
+ audio_close();
+ } else if (result == -1) {+ // Fatal error
+ app_state = 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);
}
- } while (run > QUIT);
- // main loop end
+ } while (app_state > QUIT);
+ // Main loop end
- // exit, clean up
+ // Exit, clean up
SDL_Log("Shutting down");- if (conf.audio_enabled == 1) {- audio_destroy();
- }
+ audio_close();
gamecontrollers_close();
- close_renderer();
- if (port_inited == 1)
- close_serial_port();
- SDL_free(serial_buf);
+ renderer_close();
+ if (m8_connected == 1)
+ m8_close();
SDL_Quit();
return 0;
}
--- a/src/render.c
+++ b/src/render.c
@@ -4,18 +4,17 @@
#include "render.h"
#include <SDL3/SDL.h>
-#include <stdio.h>
#include "SDL2_inprint.h"
#include "command.h"
#include "fx_cube.h"
-#include "font1.h"
-#include "font2.h"
-#include "font3.h"
-#include "font4.h"
-#include "font5.h"
-#include "inline_font.h"
+#include "fonts/font1.h"
+#include "fonts/font2.h"
+#include "fonts/font3.h"
+#include "fonts/font4.h"
+#include "fonts/font5.h"
+#include "fonts/inline_font.h"
#include <stdlib.h>
@@ -44,7 +43,7 @@
static uint8_t dirty = 0;
// Initializes SDL and creates a renderer and required surfaces
-int initialize_sdl(const unsigned int init_fullscreen) {+int renderer_initialize(const unsigned int init_fullscreen) { if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD) == false) {SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "SDL_Init: %s\n", SDL_GetError());
@@ -74,10 +73,8 @@
SDL_RenderClear(rend);
- set_font_mode(0);
+ renderer_set_font_mode(0);
- SDL_SetLogPriorities(SDL_LOG_PRIORITY_INFO);
-
dirty = 1;
return 1;
@@ -84,9 +81,9 @@
}
static void change_font(struct inline_font *font) {- kill_inline_font();
- inrenderer(rend);
- prepare_inline_font(font);
+ inline_font_close();
+ inline_font_set_renderer(rend);
+ inline_font_initialize(font);
}
static void check_and_adjust_window_and_texture_size(const int new_width, const int new_height) {@@ -126,7 +123,7 @@
}
}
-void set_font_mode(int mode) {+void renderer_set_font_mode(int mode) { if (mode < 0 || mode > 2) {// bad font mode
return;
@@ -146,8 +143,8 @@
SDL_LogDebug(SDL_LOG_CATEGORY_RENDER, "Font mode %i, Screen offset %i", mode, screen_offset_y);
}
-void close_renderer() {- kill_inline_font();
+void renderer_close() {+ inline_font_close();
SDL_DestroyTexture(main_texture);
SDL_DestroyRenderer(rend);
SDL_DestroyWindow(win);
@@ -286,7 +283,7 @@
if (show) {char overlay_text[7];
- snprintf(overlay_text, sizeof(overlay_text), "%02X %u", velocity, base_octave);
+ SDL_snprintf(overlay_text, sizeof(overlay_text), "%02X %u", velocity, base_octave);
inprint(rend, overlay_text, overlay_offset_x, overlay_offset_y, 0xC8C8C8, bg_color);
inprint(rend, "*", overlay_offset_x + (fonts[font_mode]->glyph_x * 5 + 5), overlay_offset_y,
0xFF0000, bg_color);
@@ -321,7 +318,7 @@
}
void screensaver_init() {- set_font_mode(1);
+ renderer_set_font_mode(1);
fx_cube_init(rend, (SDL_Color){255, 255, 255, 255}, texture_width, texture_height,fonts[font_mode]->glyph_x);
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Screensaver initialized");
@@ -334,6 +331,6 @@
void screensaver_destroy() {fx_cube_destroy();
- set_font_mode(0);
+ renderer_set_font_mode(0);
SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Screensaver destroyed");
}
--- a/src/render.h
+++ b/src/render.h
@@ -7,15 +7,14 @@
#include <stdint.h>
#include "command.h"
-int initialize_sdl(unsigned int init_fullscreen);
-void close_renderer();
+int renderer_initialize(unsigned int init_fullscreen);
+void renderer_close();
void draw_waveform(struct draw_oscilloscope_waveform_command *command);
void draw_rectangle(struct draw_rectangle_command *command);
int draw_character(struct draw_character_command *command);
-void set_font_mode(int mode);
+void renderer_set_font_mode(int mode);
void set_m8_model(unsigned int model);
-void view_changed(int view);
void render_screen();
void toggle_fullscreen();
--- a/src/ringbuffer.c
+++ /dev/null
@@ -1,55 +1,0 @@
-#include "ringbuffer.h"
-#include <SDL3/SDL.h>
-
-RingBuffer *ring_buffer_create(uint32_t size) {- RingBuffer *rb = SDL_malloc(sizeof(*rb));
- rb->buffer = SDL_malloc(sizeof(*rb->buffer) * size);
- rb->head = 0;
- rb->tail = 0;
- rb->max_size = size;
- rb->size = 0;
- return rb;
-}
-
-void ring_buffer_free(RingBuffer *rb) {- SDL_free(rb->buffer);
- SDL_free(rb);
-}
-
-uint32_t ring_buffer_empty(RingBuffer *rb) { return rb->size == 0; }-
-uint32_t ring_buffer_full(RingBuffer *rb) { return rb->size == rb->max_size; }-
-uint32_t ring_buffer_push(RingBuffer *rb, const uint8_t *data, uint32_t length) {- if (ring_buffer_full(rb)) {- return -1; // buffer full, push fails
- }
- uint32_t space1 = rb->max_size - rb->tail;
- uint32_t n = length <= rb->max_size - rb->size ? length : rb->max_size - rb->size;
- if (n <= space1) {- SDL_memcpy(rb->buffer + rb->tail, data, n);
- } else {- SDL_memcpy(rb->buffer + rb->tail, data, space1);
- SDL_memcpy(rb->buffer, data + space1, n - space1);
- }
- rb->tail = (rb->tail + n) % rb->max_size;
- rb->size += n;
- return n; // push successful, returns number of bytes pushed
-}
-
-uint32_t ring_buffer_pop(RingBuffer *rb, uint8_t *data, uint32_t length) {- if (ring_buffer_empty(rb)) {- return -1; // buffer empty, pop fails
- }
- uint32_t space1 = rb->max_size - rb->head;
- uint32_t n = length <= rb->size ? length : rb->size;
- if (n <= space1) {- SDL_memcpy(data, rb->buffer + rb->head, n);
- } else {- SDL_memcpy(data, rb->buffer + rb->head, space1);
- SDL_memcpy(data + space1, rb->buffer, n - space1);
- }
- rb->head = (rb->head + n) % rb->max_size;
- rb->size -= n;
- return n; // pop successful, returns number of bytes popped
-}
--- a/src/ringbuffer.h
+++ /dev/null
@@ -1,24 +1,0 @@
-#ifndef M8C_RINGBUFFER_H
-#define M8C_RINGBUFFER_H
-
-#include <stdint.h>
-
-typedef struct {- uint8_t *buffer;
- uint32_t head;
- uint32_t tail;
- uint32_t max_size;
- uint32_t size;
-} RingBuffer;
-
-RingBuffer *ring_buffer_create(uint32_t size);
-
-uint32_t ring_buffer_empty(RingBuffer *rb);
-
-uint32_t ring_buffer_pop(RingBuffer *rb, uint8_t *data, uint32_t length);
-
-uint32_t ring_buffer_push(RingBuffer *rb, const uint8_t *data, uint32_t length);
-
-void ring_buffer_free(RingBuffer *rb);
-
-#endif // M8C_RINGBUFFER_H
--- a/src/serial.c
+++ /dev/null
@@ -1,268 +1,0 @@
-// Copyright 2021 Jonne Kokkonen
-// Released under the MIT licence, https://opensource.org/licenses/MIT
-
-// Contains portions of code from libserialport's examples released to the
-// public domain
-
-#ifndef USE_LIBUSB
-#include <SDL3/SDL.h>
-#include <libserialport.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "serial.h"
-
-struct sp_port *m8_port = NULL;
-
-// Helper function for error handling
-static int check(enum sp_return result);
-
-static int detect_m8_serial_device(const struct sp_port *m8_port) {- // Check the connection method - we want USB serial devices
- const enum sp_transport transport = sp_get_port_transport(m8_port);
-
- if (transport == SP_TRANSPORT_USB) {- // Get the USB vendor and product IDs.
- int usb_vid, usb_pid;
- sp_get_port_usb_vid_pid(m8_port, &usb_vid, &usb_pid);
-
- if (usb_vid == 0x16C0 && usb_pid == 0x048A)
- return 1;
- }
-
- return 0;
-}
-
-int list_devices() {- struct sp_port **port_list;
- const enum sp_return result = sp_list_ports(&port_list);
-
- if (result != SP_OK) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "sp_list_ports() failed!\n");
- abort();
- }
-
- for (int i = 0; port_list[i] != NULL; i++) {- const struct sp_port *port = port_list[i];
-
- if (detect_m8_serial_device(port)) {- SDL_Log("Found M8 device: %s", sp_get_port_name(port));- }
- }
-
- sp_free_port_list(port_list);
- return 0;
-}
-
-// Checks for connected devices and whether the specified device still exists
-int check_serial_port() {-
- int device_found = 0;
-
- /* A pointer to a null-terminated array of pointers to
- * struct sp_port, which will contain the ports found.*/
- struct sp_port **port_list;
-
- /* Call sp_list_ports() to get the ports. The port_list
- * pointer will be updated to refer to the array created. */
- const enum sp_return result = sp_list_ports(&port_list);
-
- if (result != SP_OK) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "sp_list_ports() failed!\n");
- abort();
- }
-
- /* Iterate through the ports. When port_list[i] is NULL
- * this indicates the end of the list. */
- for (int i = 0; port_list[i] != NULL; i++) {- const struct sp_port *port = port_list[i];
-
- if (detect_m8_serial_device(port)) {- if (strcmp(sp_get_port_name(port), sp_get_port_name(m8_port)) == 0)
- device_found = 1;
- }
- }
-
- sp_free_port_list(port_list);
- return device_found;
-}
-
-int init_serial(const int verbose, const char *preferred_device) {- if (m8_port != NULL) {- // Port is already initialized
- return 1;
- }
- /* A pointer to a null-terminated array of pointers to
- * struct sp_port, which will contain the ports found.*/
- struct sp_port **port_list;
-
- if (verbose)
- SDL_Log("Looking for USB serial devices.\n");-
- /* Call sp_list_ports() to get the ports. The port_list
- * pointer will be updated to refer to the array created. */
- enum sp_return result = sp_list_ports(&port_list);
-
- if (result != SP_OK) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "sp_list_ports() failed!\n");
- abort();
- }
-
- /* Iterate through the ports. When port_list[i] is NULL
- * this indicates the end of the list. */
- for (int i = 0; port_list[i] != NULL; i++) {- const struct sp_port *port = port_list[i];
-
- if (detect_m8_serial_device(port)) {- char *port_name = sp_get_port_name(port);
- SDL_Log("Found M8 in %s.\n", port_name);- sp_copy_port(port, &m8_port);
- if (preferred_device != NULL && strcmp(preferred_device, port_name) == 0) {- SDL_Log("Found preferred device, breaking");- break;
- }
- }
- }
-
- sp_free_port_list(port_list);
-
- if (m8_port != NULL) {- // Open the serial port and configure it
- SDL_Log("Opening port.");-
- result = sp_open(m8_port, SP_MODE_READ_WRITE);
- if (check(result) != SP_OK)
- return 0;
-
- result = sp_set_baudrate(m8_port, 115200);
- if (check(result) != SP_OK)
- return 0;
-
- result = sp_set_bits(m8_port, 8);
- if (check(result) != SP_OK)
- return 0;
-
- result = sp_set_parity(m8_port, SP_PARITY_NONE);
- if (check(result) != SP_OK)
- return 0;
-
- result = sp_set_stopbits(m8_port, 1);
- if (check(result) != SP_OK)
- return 0;
-
- result = sp_set_flowcontrol(m8_port, SP_FLOWCONTROL_NONE);
- if (check(result) != SP_OK)
- return 0;
- } else {- if (verbose) {- SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "Cannot find a M8.\n");
- }
- return 0;
- }
-
- return 1;
-}
-
-// Helper function for error handling.
-static int check(const enum sp_return result) {-
- char *error_message;
-
- switch (result) {- case SP_ERR_ARG:
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Invalid argument.\n");
- break;
- case SP_ERR_FAIL:
- error_message = sp_last_error_message();
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Failed: %s\n", error_message);
- sp_free_error_message(error_message);
- break;
- case SP_ERR_SUPP:
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Not supported.\n");
- break;
- case SP_ERR_MEM:
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Couldn't allocate memory.\n");
- break;
- case SP_OK:
- default:
- break;
- }
- return result;
-}
-
-int reset_display() {- SDL_Log("Reset display\n");-
- const char buf[1] = {'R'};- const int result = sp_blocking_write(m8_port, buf, 1, 5);
- if (result != 1) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result);
- return 0;
- }
- return 1;
-}
-
-int enable_and_reset_display() {-
- SDL_Log("Enabling and resetting M8 display\n");-
- const char buf[1] = {'E'};- int result = sp_blocking_write(m8_port, buf, 1, 5);
- if (result != 1) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error enabling M8 display, code %d", result);
- return 0;
- }
-
- result = reset_display();
-
- return result;
-}
-
-int disconnect() {-
- SDL_Log("Disconnecting M8\n");-
- const char buf[1] = {'D'};-
- int result = sp_blocking_write(m8_port, buf, 1, 5);
- if (result != 1) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending disconnect, code %d", result);
- result = 0;
- }
- sp_close(m8_port);
- sp_free_port(m8_port);
- m8_port = NULL;
- return result;
-}
-
-int serial_read(uint8_t *serial_buf, const int count) {- return sp_nonblocking_read(m8_port, serial_buf, count);
-}
-
-int send_msg_controller(const uint8_t input) {- const char buf[2] = {'C', input};- const size_t nbytes = 2;
- const int result = sp_blocking_write(m8_port, buf, nbytes, 5);
- if (result != nbytes) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending input, code %d", result);
- return -1;
- }
- return 1;
-}
-
-int send_msg_keyjazz(const uint8_t note, uint8_t velocity) {- if (velocity > 0x7F)
- velocity = 0x7F;
- const char buf[3] = {'K', note, velocity};- const size_t nbytes = 3;
- const int result = sp_blocking_write(m8_port, buf, nbytes, 5);
- if (result != nbytes) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending keyjazz, code %d", result);
- return -1;
- }
-
- return 1;
-}
-#endif
--- a/src/serial.h
+++ /dev/null
@@ -1,27 +1,0 @@
-// Copyright 2021 Jonne Kokkonen
-// Released under the MIT licence, https://opensource.org/licenses/MIT
-
-#ifndef _SERIAL_H_
-#define _SERIAL_H_
-#include <stdint.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 list_devices();
-int check_serial_port();
-int reset_display();
-int enable_and_reset_display();
-int disconnect();
-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);
-
-#endif
--- a/src/slip.c
+++ /dev/null
@@ -1,114 +1,0 @@
-/*
-MIT License
-
-Copyright (c) 2018 Marcin Borowicz
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-/* This code is originally by marcinbor85, https://github.com/marcinbor85/slip
-It has been simplified a bit as CRC checking etc. is not required in this
-program. */
-
-#include "slip.h"
-
-#include <assert.h>
-#include <stddef.h>
-
-static void reset_rx(slip_handler_s *slip) {- assert(slip != NULL);
-
- slip->state = SLIP_STATE_NORMAL;
- slip->size = 0;
-}
-
-slip_error_t slip_init(slip_handler_s *slip, const slip_descriptor_s *descriptor) {- assert(slip != NULL);
- assert(descriptor != NULL);
- assert(descriptor->buf != NULL);
- assert(descriptor->recv_message != NULL);
-
- slip->descriptor = descriptor;
- reset_rx(slip);
-
- return SLIP_NO_ERROR;
-}
-
-static slip_error_t put_byte_to_buffer(slip_handler_s *slip, const uint8_t byte) {- slip_error_t error = SLIP_NO_ERROR;
-
- assert(slip != NULL);
-
- if (slip->size >= slip->descriptor->buf_size) {- error = SLIP_ERROR_BUFFER_OVERFLOW;
- reset_rx(slip);
- } else {- slip->descriptor->buf[slip->size++] = byte;
- slip->state = SLIP_STATE_NORMAL;
- }
-
- return error;
-}
-
-slip_error_t slip_read_byte(slip_handler_s *slip, uint8_t byte) {- slip_error_t error = SLIP_NO_ERROR;
-
- assert(slip != NULL);
-
- switch (slip->state) {- case SLIP_STATE_NORMAL:
- switch (byte) {- case SLIP_SPECIAL_BYTE_END:
- if (!slip->descriptor->recv_message(slip->descriptor->buf, slip->size)) {- error = SLIP_ERROR_INVALID_PACKET;
- }
- reset_rx(slip);
- break;
- case SLIP_SPECIAL_BYTE_ESC:
- slip->state = SLIP_STATE_ESCAPED;
- break;
- default:
- error = put_byte_to_buffer(slip, byte);
- break;
- }
- break;
-
- case SLIP_STATE_ESCAPED:
- switch (byte) {- case SLIP_ESCAPED_BYTE_END:
- byte = SLIP_SPECIAL_BYTE_END;
- break;
- case SLIP_ESCAPED_BYTE_ESC:
- byte = SLIP_SPECIAL_BYTE_ESC;
- break;
- default:
- error = SLIP_ERROR_UNKNOWN_ESCAPED_BYTE;
- reset_rx(slip);
- break;
- }
-
- if (error != SLIP_NO_ERROR)
- break;
-
- error = put_byte_to_buffer(slip, byte);
- break;
- }
-
- return error;
-}
--- a/src/slip.h
+++ /dev/null
@@ -1,67 +1,0 @@
-/*
-MIT License
-
-Copyright (c) 2018 Marcin Borowicz
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-/* This code is originally by marcinbor85, https://github.com/marcinbor85/slip
-It has been simplified a bit as CRC checking etc. is not required in this
-program. */
-
-#ifndef SLIP_H_
-#define SLIP_H_
-
-#include <stdint.h>
-
-#define SLIP_SPECIAL_BYTE_END 0xC0
-#define SLIP_SPECIAL_BYTE_ESC 0xDB
-
-#define SLIP_ESCAPED_BYTE_END 0xDC
-#define SLIP_ESCAPED_BYTE_ESC 0xDD
-
-typedef enum {- SLIP_STATE_NORMAL = 0x00,
- SLIP_STATE_ESCAPED
-} slip_state_t;
-
-typedef struct {- uint8_t *buf;
- uint32_t buf_size;
- int (*recv_message)(uint8_t *data, uint32_t size);
-} slip_descriptor_s;
-
-typedef struct {- slip_state_t state;
- uint32_t size;
- const slip_descriptor_s *descriptor;
-} slip_handler_s;
-
-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);
-slip_error_t slip_read_byte(slip_handler_s *slip, uint8_t byte);
-
-#endif
\ No newline at end of file
--- a/src/usb.c
+++ /dev/null
@@ -1,363 +1,0 @@
-// Copyright 2021 Jonne Kokkonen
-// Released under the MIT licence, https://opensource.org/licenses/MIT
-
-// Contains portions of code from libserialport's examples released to the
-// public domain
-#ifdef USE_LIBUSB
-
-#include <SDL3/SDL.h>
-#include <libusb.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "usb.h"
-
-static int ep_out_addr = 0x03;
-static int ep_in_addr = 0x83;
-
-#define ACM_CTRL_DTR 0x01
-#define ACM_CTRL_RTS 0x02
-
-#define M8_VID 0x16c0
-#define M8_PID 0x048a
-
-libusb_context *ctx = NULL;
-libusb_device_handle *devh = NULL;
-
-static int do_exit = 0;
-
-int list_devices() {- int r;
- r = libusb_init(&ctx);
- if (r < 0) {- SDL_Log("libusb_init failed: %s", libusb_error_name(r));- return 0;
- }
-
- libusb_device **device_list = NULL;
- int count = libusb_get_device_list(ctx, &device_list);
- for (size_t idx = 0; idx < count; ++idx) {- libusb_device *device = device_list[idx];
- struct libusb_device_descriptor desc;
- int rc = libusb_get_device_descriptor(device, &desc);
- if (rc < 0) {- SDL_Log("Error");- libusb_free_device_list(device_list, 1);
- return rc;
- }
-
- if (desc.idVendor == M8_VID && desc.idProduct == M8_PID) {- SDL_Log("Found M8 device: %d:%d\n", libusb_get_port_number(device),- libusb_get_bus_number(device));
- }
- }
- libusb_free_device_list(device_list, 1);
- return 0;
-}
-
-int usb_loop(void *data) {- SDL_SetThreadPriority(SDL_THREAD_PRIORITY_TIME_CRITICAL);
- while (!do_exit) {- int rc = libusb_handle_events(ctx);
- if (rc != LIBUSB_SUCCESS) {- SDL_Log("Audio loop error: %s\n", libusb_error_name(rc));- break;
- }
- }
- return 0;
-}
-
-static SDL_Thread *usb_thread;
-
-static void LIBUSB_CALL xfr_cb_in(struct libusb_transfer *transfer) {- int *completed = transfer->user_data;
- *completed = 1;
-}
-
-int bulk_transfer(int endpoint, uint8_t *serial_buf, int count, unsigned int timeout_ms) {- if (devh == NULL) {- return -1;
- }
-
- int completed = 0;
-
- struct libusb_transfer *transfer;
- transfer = libusb_alloc_transfer(0);
- libusb_fill_bulk_transfer(transfer, devh, endpoint, serial_buf, count, xfr_cb_in, &completed,
- timeout_ms);
- int r = libusb_submit_transfer(transfer);
-
- if (r < 0) {- SDL_Log("Error");- libusb_free_transfer(transfer);
- return r;
- }
-
-retry:
- libusb_lock_event_waiters(ctx);
- while (!completed) {- if (!libusb_event_handler_active(ctx)) {- libusb_unlock_event_waiters(ctx);
- goto retry;
- }
- libusb_wait_for_event(ctx, NULL);
- }
- libusb_unlock_event_waiters(ctx);
-
- int actual_length = transfer->actual_length;
-
- libusb_free_transfer(transfer);
-
- return actual_length;
-}
-
-int blocking_write(void *buf, int count, unsigned int timeout_ms) {- return bulk_transfer(ep_out_addr, buf, count, timeout_ms);
-}
-
-int serial_read(uint8_t *serial_buf, int count) {- return bulk_transfer(ep_in_addr, serial_buf, count, 1);
-}
-
-int check_serial_port() {- // Reading will fail anyway when the device is not present anymore
- return 1;
-}
-
-int init_interface() {-
- if (devh == NULL) {- SDL_Log("Device not initialised!");- return 0;
- }
-
- int rc;
-
- for (int if_num = 0; if_num < 2; if_num++) {- if (libusb_kernel_driver_active(devh, if_num)) {- SDL_Log("Detaching kernel driver for interface %d", if_num);- libusb_detach_kernel_driver(devh, if_num);
- }
- rc = libusb_claim_interface(devh, if_num);
- if (rc < 0) {- SDL_Log("Error claiming interface: %s", libusb_error_name(rc));- return 0;
- }
- }
-
- /* Start configuring the device:
- * - set line state
- */
- SDL_Log("Setting line state");- rc = libusb_control_transfer(devh, 0x21, 0x22, ACM_CTRL_DTR | ACM_CTRL_RTS, 0, NULL, 0, 0);
- if (rc < 0) {- SDL_Log("Error during control transfer: %s", libusb_error_name(rc));- return 0;
- }
-
- /* - set line encoding: here 115200 8N1
- * 115200 = 0x01C200 ~> 0x00, 0xC2, 0x01, 0x00 in little endian
- */
- SDL_Log("Set line encoding");- unsigned char encoding[] = {0x00, 0xC2, 0x01, 0x00, 0x00, 0x00, 0x08};- rc = libusb_control_transfer(devh, 0x21, 0x20, 0, 0, encoding, sizeof(encoding), 0);
- if (rc < 0) {- SDL_Log("Error during control transfer: %s", libusb_error_name(rc));- return 0;
- }
-
- usb_thread = SDL_CreateThread(&usb_loop, "USB", NULL);
-
- return 1;
-}
-
-int init_serial_with_file_descriptor(int file_descriptor) {- SDL_Log("Initialising serial with file descriptor");-
- if (file_descriptor <= 0) {- SDL_Log("Invalid file descriptor: %d", file_descriptor);- return 0;
- }
-
- int r;
- r = libusb_set_option(NULL, LIBUSB_OPTION_NO_DEVICE_DISCOVERY, NULL);
- if (r != LIBUSB_SUCCESS) {- SDL_Log("libusb_set_option failed: %s", libusb_error_name(r));- return 0;
- }
- r = libusb_init(&ctx);
- if (r < 0) {- SDL_Log("libusb_init failed: %s", libusb_error_name(r));- return 0;
- }
- r = libusb_wrap_sys_device(ctx, (intptr_t)file_descriptor, &devh);
- if (r < 0) {- SDL_Log("libusb_wrap_sys_device failed: %s", libusb_error_name(r));- return 0;
- } else if (devh == NULL) {- SDL_Log("libusb_wrap_sys_device returned invalid handle");- return 0;
- }
- SDL_Log("USB device init success");-
- return init_interface();
-}
-
-int init_serial(int verbose, char *preferred_device) {-
- if (devh != NULL) {- return 1;
- }
-
- int r;
- r = libusb_init(&ctx);
- if (r < 0) {- SDL_Log("libusb_init failed: %s", libusb_error_name(r));- return 0;
- }
- if (preferred_device == NULL) {- devh = libusb_open_device_with_vid_pid(ctx, M8_VID, M8_PID);
- } else {- char *port;
- char *saveptr = NULL;
- char *bus;
- port = SDL_strtokr(preferred_device, ":", &saveptr);
- bus = SDL_strtokr(NULL, ":", &saveptr);
- libusb_device **device_list = NULL;
- int count = libusb_get_device_list(ctx, &device_list);
- for (size_t idx = 0; idx < count; ++idx) {- libusb_device *device = device_list[idx];
- struct libusb_device_descriptor desc;
- r = libusb_get_device_descriptor(device, &desc);
- if (r < 0) {- SDL_Log("libusb_get_device_descriptor failed: %s", libusb_error_name(r));- libusb_free_device_list(device_list, 1);
- return 0;
- }
-
- if (desc.idVendor == M8_VID && desc.idProduct == M8_PID) {- SDL_Log("Searching for port %s and bus %s", port, bus);- if (libusb_get_port_number(device) == SDL_atoi(port) &&
- libusb_get_bus_number(device) == SDL_atoi(bus)) {- SDL_Log("Preferred device found, connecting");- r = libusb_open(device, &devh);
- if (r < 0) {- SDL_Log("libusb_open failed: %s", libusb_error_name(r));- return 0;
- }
- }
- }
- }
- libusb_free_device_list(device_list, 1);
- if (devh == NULL) {- SDL_Log("Preferred device %s not found, using first available", preferred_device);- devh = libusb_open_device_with_vid_pid(ctx, M8_VID, M8_PID);
- }
- }
- if (devh == NULL) {- SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM,
- "libusb_open_device_with_vid_pid returned invalid handle");
- return 0;
- }
- SDL_Log("USB device init success");-
- return init_interface();
-}
-
-int reset_display() {- int result;
-
- SDL_Log("Reset display\n");-
- char buf[1] = {'R'};-
- result = blocking_write(buf, 1, 5);
- if (result != 1) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result);
- return 0;
- }
- return 1;
-}
-
-int enable_and_reset_display() {- int result;
-
- SDL_Log("Enabling and resetting M8 display\n");-
- char buf[1] = {'E'};- result = blocking_write(buf, 1, 5);
- if (result != 1) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error enabling M8 display, code %d", result);
- return 0;
- }
-
- SDL_Delay(5);
- result = reset_display();
- return result;
-}
-
-int disconnect() {-
- char buf[1] = {'D'};- int result;
-
- SDL_Log("Disconnecting M8\n");-
- result = blocking_write(buf, 1, 5);
- if (result != 1) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending disconnect, code %d", result);
- return -1;
- }
-
- int rc;
-
- if (devh != NULL) {-
- for (int if_num = 0; if_num < 2; if_num++) {- rc = libusb_release_interface(devh, if_num);
- if (rc < 0) {- SDL_Log("Error releasing interface: %s", libusb_error_name(rc));- return 0;
- }
- }
-
- do_exit = 1;
-
- libusb_close(devh);
- }
-
- SDL_WaitThread(usb_thread, NULL);
-
- libusb_exit(ctx);
-
- return 1;
-}
-
-int send_msg_controller(uint8_t input) {- char buf[2] = {'C', input};- int nbytes = 2;
- int result;
- result = blocking_write(buf, nbytes, 5);
- if (result != nbytes) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending input, code %d", result);
- return -1;
- }
- return 1;
-}
-
-int send_msg_keyjazz(uint8_t note, uint8_t velocity) {- if (velocity > 0x7F)
- velocity = 0x7F;
- char buf[3] = {'K', note, velocity};- int nbytes = 3;
- int result;
- result = blocking_write(buf, nbytes, 5);
- if (result != nbytes) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending keyjazz, code %d", result);
- return -1;
- }
-
- return 1;
-}
-
-#endif
--- a/src/usb.h
+++ /dev/null
@@ -1,9 +1,0 @@
-#ifndef M8C_USB_H_
-#define M8C_USB_H_
-#ifdef USE_LIBUSB
-
-#include <libusb.h>
-extern libusb_device_handle *devh;
-
-#endif // USE_LIBUSB
-#endif // M8C_USB_H_
--- a/src/usb_audio.c
+++ /dev/null
@@ -1,200 +1,0 @@
-#ifdef USE_LIBUSB
-
-#include "ringbuffer.h"
-#include "usb.h"
-#include <SDL3/SDL.h>
-#include <errno.h>
-#include <libusb.h>
-
-#define EP_ISO_IN 0x85
-#define IFACE_NUM 4
-
-#define NUM_TRANSFERS 64
-#define PACKET_SIZE 180
-#define NUM_PACKETS 2
-
-SDL_AudioDeviceID sdl_audio_device_id = 0;
-RingBuffer *audio_buffer = NULL;
-
-static void audio_callback(void *userdata, Uint8 *stream, int len) {- uint32_t read_len = ring_buffer_pop(audio_buffer, stream, len);
-
- if (read_len == -1) {- SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Buffer underflow!");
- }
-
- // If we didn't read the full len bytes, fill the rest with zeros
- if (read_len < len) {- SDL_memset(&stream[read_len], 0, len - read_len);
- }
-}
-
-static void cb_xfr(struct libusb_transfer *xfr) {- unsigned int i;
-
- for (i = 0; i < xfr->num_iso_packets; i++) {- struct libusb_iso_packet_descriptor *pack = &xfr->iso_packet_desc[i];
-
- if (pack->status != LIBUSB_TRANSFER_COMPLETED) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "XFR callback error (status %d: %s)", pack->status,
- libusb_error_name(pack->status));
- /* This doesn't happen, so bail out if it does. */
- return;
- }
-
- const uint8_t *data = libusb_get_iso_packet_buffer_simple(xfr, i);
- if (sdl_audio_device_id != 0) {- uint32_t actual = ring_buffer_push(audio_buffer, data, pack->actual_length);
- if (actual == -1) {- SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Buffer overflow!");
- }
- }
- }
-
- if (libusb_submit_transfer(xfr) < 0) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "error re-submitting URB\n");
- SDL_free(xfr->buffer);
- }
-}
-
-static struct libusb_transfer *xfr[NUM_TRANSFERS];
-
-static int benchmark_in() {- int i;
-
- for (i = 0; i < NUM_TRANSFERS; i++) {- xfr[i] = libusb_alloc_transfer(NUM_PACKETS);
- if (!xfr[i]) {- SDL_Log("Could not allocate transfer");- return -ENOMEM;
- }
-
- Uint8 *buffer = SDL_malloc(PACKET_SIZE * NUM_PACKETS);
-
- libusb_fill_iso_transfer(xfr[i], devh, EP_ISO_IN, buffer, PACKET_SIZE * NUM_PACKETS,
- NUM_PACKETS, cb_xfr, NULL, 0);
- libusb_set_iso_packet_lengths(xfr[i], PACKET_SIZE);
-
- libusb_submit_transfer(xfr[i]);
- }
-
- return 1;
-}
-
-int audio_init(int audio_buffer_size, const char *output_device_name) {- SDL_Log("USB audio setup");-
- int rc;
-
- rc = libusb_kernel_driver_active(devh, IFACE_NUM);
- if (rc == 1) {- SDL_Log("Detaching kernel driver");- rc = libusb_detach_kernel_driver(devh, IFACE_NUM);
- if (rc < 0) {- SDL_Log("Could not detach kernel driver: %s\n", libusb_error_name(rc));- return rc;
- }
- }
-
- rc = libusb_claim_interface(devh, IFACE_NUM);
- if (rc < 0) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error claiming interface: %s\n", libusb_error_name(rc));
- return rc;
- }
-
- rc = libusb_set_interface_alt_setting(devh, IFACE_NUM, 1);
- if (rc < 0) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error setting alt setting: %s\n", libusb_error_name(rc));
- return rc;
- }
-
- if (!SDL_WasInit(SDL_INIT_AUDIO)) {- if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Init audio failed %s", SDL_GetError());
- return -1;
- }
- } else {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Audio was already initialised");
- }
-
- static SDL_AudioSpec audio_spec;
- audio_spec.format = AUDIO_S16;
- audio_spec.channels = 2;
- audio_spec.freq = 44100;
- audio_spec.samples = audio_buffer_size;
- audio_spec.callback = audio_callback;
-
- SDL_AudioSpec _obtained;
- SDL_zero(_obtained);
-
- SDL_Log("Current audio driver is %s and device %s", SDL_GetCurrentAudioDriver(),- output_device_name);
-
- if (SDL_strcasecmp(SDL_GetCurrentAudioDriver(), "openslES") == 0 || output_device_name == NULL) {- SDL_Log("Using default audio device");- sdl_audio_device_id = SDL_OpenAudioDevice(NULL, 0, &audio_spec, &_obtained, 0);
- } else {- sdl_audio_device_id = SDL_OpenAudioDevice(output_device_name, 0, &audio_spec, &_obtained, 0);
- }
-
- audio_buffer = ring_buffer_create(4 * _obtained.size);
-
- SDL_Log("Obtained audio spec. Sample rate: %d, channels: %d, samples: %d, size: %d",- _obtained.freq, _obtained.channels, _obtained.samples, +_obtained.size);
-
- SDL_PauseAudioDevice(sdl_audio_device_id, 0);
-
- // Good to go
- SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Starting capture");
- if ((rc = benchmark_in()) < 0) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Capture failed to start: %d", rc);
- return rc;
- }
-
- SDL_Log("Successful init");- return 1;
-}
-
-int audio_destroy() {- if (devh == NULL) {- return -1;
- }
-
- SDL_LogDebug(SDL_LOG_CATEGORY_AUDIO, "Closing audio");
-
- int i, rc;
-
- for (i = 0; i < NUM_TRANSFERS; i++) {- rc = libusb_cancel_transfer(xfr[i]);
- if (rc < 0) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error cancelling transfer: %s\n",
- libusb_error_name(rc));
- }
- }
-
- SDL_Log("Freeing interface %d", IFACE_NUM);-
- rc = libusb_release_interface(devh, IFACE_NUM);
- if (rc < 0) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error releasing interface: %s\n", libusb_error_name(rc));
- return rc;
- }
-
- if (sdl_audio_device_id != 0) {- SDL_Log("Closing audio device %d", sdl_audio_device_id);- SDL_AudioDeviceID device = sdl_audio_device_id;
- sdl_audio_device_id = 0;
- SDL_CloseAudioDevice(device);
- }
-
- SDL_LogDebug(SDL_LOG_CATEGORY_SYSTEM, "Audio closed");
-
- ring_buffer_free(audio_buffer);
- return 1;
-}
-
-void toggle_audio(unsigned int audio_buffer_size, const char *output_device_name) {- SDL_Log("Libusb audio toggling not implemented yet");-}
-
-#endif
--
⑨