ref: 7e88427152e91ced54c4a4963b9f281e96527905
parent: 420d2f73094600290eaee2b0d9930c986ca4d04f
parent: e066ceb5c0b61c0766884f2d9d30db57e22d4bdd
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Thu Jun 2 19:32:03 EDT 2022
Merge pull request #72 from laamaa/feature/kiosk add possibility to wait for device insertion and detect disconnetion
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
#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 = main.o serial.o slip.o command.o write.o render.o ini.o config.o input.o font.o
+OBJ = main.o serial.o slip.o command.o write.o render.o ini.o config.o input.o font.o fx_cube.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 = serial.h slip.h command.h write.h render.h ini.h config.h input.h
+DEPS = serial.h slip.h command.h write.h render.h ini.h config.h input.h fx_cube.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 sdl2 libserialport)
--- a/config.c
+++ b/config.c
@@ -22,9 +22,10 @@
c.filename = "config.ini"; // default config file to load
- c.init_fullscreen = 0; // default fullscreen state at load
- c.init_use_gpu = 1; // default to use hardware acceleration
- c.idle_ms = 10; // default to high performance
+ c.init_fullscreen = 0; // default fullscreen state at load
+ c.init_use_gpu = 1; // default to use hardware acceleration
+ c.idle_ms = 10; // default to high performance
+ c.wait_for_device = 0; // default to exit if device disconnected
c.key_up = SDL_SCANCODE_UP;
c.key_left = SDL_SCANCODE_LEFT;
@@ -73,7 +74,7 @@
SDL_Log("Writing config file to %s", config_path);- const unsigned int INI_LINE_COUNT = 36;
+ const unsigned int INI_LINE_COUNT = 37;
const unsigned int LINELEN = 50;
// Entries for the config file
@@ -85,12 +86,14 @@
snprintf(ini_values[initPointer++], LINELEN, "use_gpu=%s\n",
conf->init_use_gpu ? "true" : "false");
snprintf(ini_values[initPointer++], LINELEN, "idle_ms=%d\n", conf->idle_ms);
+ snprintf(ini_values[initPointer++], LINELEN, "wait_for_device=%s\n",
+ conf->wait_for_device ? "true" : "false");
snprintf(ini_values[initPointer++], LINELEN, "[keyboard]\n");
snprintf(ini_values[initPointer++], LINELEN, "key_up=%d\n", conf->key_up);
snprintf(ini_values[initPointer++], LINELEN, "key_left=%d\n", conf->key_left);
snprintf(ini_values[initPointer++], LINELEN, "key_down=%d\n", conf->key_down);
snprintf(ini_values[initPointer++], LINELEN, "key_right=%d\n",
- conf->key_right);
+ conf->key_right);
snprintf(ini_values[initPointer++], LINELEN, "key_select=%d\n",
conf->key_select);
snprintf(ini_values[initPointer++], LINELEN, "key_select_alt=%d\n",
@@ -99,8 +102,7 @@
conf->key_start);
snprintf(ini_values[initPointer++], LINELEN, "key_start_alt=%d\n",
conf->key_start_alt);
- snprintf(ini_values[initPointer++], LINELEN, "key_opt=%d\n",
- conf->key_opt);
+ snprintf(ini_values[initPointer++], LINELEN, "key_opt=%d\n", conf->key_opt);
snprintf(ini_values[initPointer++], LINELEN, "key_opt_alt=%d\n",
conf->key_opt_alt);
snprintf(ini_values[initPointer++], LINELEN, "key_edit=%d\n", conf->key_edit);
@@ -137,14 +139,13 @@
"gamepad_analog_axis_leftright=%d\n",
conf->gamepad_analog_axis_leftright);
snprintf(ini_values[initPointer++], LINELEN,
- "gamepad_analog_axis_select=%d\n",
- conf->gamepad_analog_axis_select);
+ "gamepad_analog_axis_select=%d\n", conf->gamepad_analog_axis_select);
snprintf(ini_values[initPointer++], LINELEN, "gamepad_analog_axis_start=%d\n",
conf->gamepad_analog_axis_start);
snprintf(ini_values[initPointer++], LINELEN, "gamepad_analog_axis_opt=%d\n",
- conf->gamepad_analog_axis_opt);
+ conf->gamepad_analog_axis_opt);
snprintf(ini_values[initPointer++], LINELEN, "gamepad_analog_axis_edit=%d\n",
- conf->gamepad_analog_axis_edit);
+ conf->gamepad_analog_axis_edit);
// Ensure we aren't writing off the end of the array
assert(initPointer == INI_LINE_COUNT);
@@ -188,7 +189,7 @@
// Frees the mem used for the config
ini_free(ini);
- //Write any new default options after loading
+ // Write any new default options after loading
write_config(conf);
}
@@ -196,6 +197,7 @@
const char *param_fs = ini_get(ini, "graphics", "fullscreen");
const char *param_gpu = ini_get(ini, "graphics", "use_gpu");
const char *idle_ms = ini_get(ini, "graphics", "idle_ms");
+ const char *param_wait = ini_get(ini, "graphics", "wait_for_device");
if (strcmpci(param_fs, "true") == 0) {conf->init_fullscreen = 1;
@@ -202,7 +204,7 @@
} else
conf->init_fullscreen = 0;
- if(param_gpu != NULL){+ if (param_gpu != NULL) { if (strcmpci(param_gpu, "true") == 0) {conf->init_use_gpu = 1;
} else
@@ -209,9 +211,16 @@
conf->init_use_gpu = 0;
}
- if (idle_ms)
+ if (idle_ms != NULL)
conf->idle_ms = SDL_atoi(idle_ms);
+ if (param_wait != NULL) {+ if (strcmpci(param_wait, "true") == 0) {+ conf->wait_for_device = 1;
+ } else {+ conf->wait_for_device = 0;
+ }
+ }
}
void read_key_config(ini_t *ini, config_params_s *conf) {@@ -314,10 +323,17 @@
else
conf->gamepad_analog_invert = 0;
- if (gamepad_analog_axis_updown) conf->gamepad_analog_axis_updown = SDL_atoi(gamepad_analog_axis_updown);
- if (gamepad_analog_axis_leftright) conf->gamepad_analog_axis_leftright = SDL_atoi(gamepad_analog_axis_leftright);
- if (gamepad_analog_axis_select) conf->gamepad_analog_axis_select = SDL_atoi(gamepad_analog_axis_select);
- if (gamepad_analog_axis_start) conf->gamepad_analog_axis_start = SDL_atoi(gamepad_analog_axis_start);
- if (gamepad_analog_axis_opt) conf->gamepad_analog_axis_opt = SDL_atoi(gamepad_analog_axis_opt);
- if (gamepad_analog_axis_edit) conf->gamepad_analog_axis_edit = SDL_atoi(gamepad_analog_axis_edit);
+ if (gamepad_analog_axis_updown)
+ conf->gamepad_analog_axis_updown = SDL_atoi(gamepad_analog_axis_updown);
+ if (gamepad_analog_axis_leftright)
+ conf->gamepad_analog_axis_leftright =
+ SDL_atoi(gamepad_analog_axis_leftright);
+ if (gamepad_analog_axis_select)
+ conf->gamepad_analog_axis_select = SDL_atoi(gamepad_analog_axis_select);
+ if (gamepad_analog_axis_start)
+ conf->gamepad_analog_axis_start = SDL_atoi(gamepad_analog_axis_start);
+ if (gamepad_analog_axis_opt)
+ conf->gamepad_analog_axis_opt = SDL_atoi(gamepad_analog_axis_opt);
+ if (gamepad_analog_axis_edit)
+ conf->gamepad_analog_axis_edit = SDL_atoi(gamepad_analog_axis_edit);
}
--- a/config.h
+++ b/config.h
@@ -11,6 +11,7 @@
int init_fullscreen;
int init_use_gpu;
int idle_ms;
+ int wait_for_device;
int key_up;
int key_left;
--- a/config.ini.sample
+++ b/config.ini.sample
@@ -8,6 +8,10 @@
fullscreen=false
; set this to false to run m8c in software rendering mode (may be useful for Raspberry Pi)
use_gpu=true
+; the delay amount in ms in the main loop, decrease value for faster operation, increase value if too much cpu usage
+idle_ms = 10
+; show a spinning cube if device is not inserted
+wait_for_device = true
[keyboard]
; these need to be the decimal value of the SDL scancodes.
--- /dev/null
+++ b/fx_cube.c
@@ -1,0 +1,120 @@
+#include <SDL.h>
+#include "SDL2_inprint.h"
+
+#define target_width 320
+#define target_height 240
+static SDL_Texture *texture_cube;
+static SDL_Texture *texture_text;
+static SDL_Renderer *fx_renderer;
+static SDL_Color line_color;
+
+const char *text_m8c = "M8C";
+const char *text_disconnected = "DEVICE DISCONNECTED";
+
+static const float center_x = (float)target_width / 2;
+static const float center_y = (float)target_height / 2;
+
+static const float default_nodes[8][3] = {+ {-1, -1, -1}, {-1, -1, 1}, {-1, 1, -1}, {-1, 1, 1},+ {1, -1, -1}, {1, -1, 1}, {1, 1, -1}, {1, 1, 1}};+
+static int edges[12][2] = {{0, 1}, {1, 3}, {3, 2}, {2, 0}, {4, 5}, {5, 7},+ {7, 6}, {6, 4}, {0, 4}, {1, 5}, {2, 6}, {3, 7}};+
+static float nodes[8][3];
+
+static void scale(float factor0, float factor1, float factor2) {+ for (int i = 0; i < 8; i++) {+ nodes[i][0] *= factor0;
+ nodes[i][1] *= factor1;
+ nodes[i][2] *= factor2;
+ }
+}
+
+static void rotate_cube(float angle_x, float angle_y) {+ float sin_x = SDL_sin(angle_x);
+ float cos_x = SDL_cos(angle_x);
+ float sin_y = SDL_sin(angle_y);
+ float cos_y = SDL_cos(angle_y);
+ for (int i = 0; i < 8; i++) {+ float x = nodes[i][0];
+ float y = nodes[i][1];
+ float z = nodes[i][2];
+
+ nodes[i][0] = x * cos_x - z * sin_x;
+ nodes[i][2] = z * cos_x + x * sin_x;
+
+ z = nodes[i][2];
+
+ nodes[i][1] = y * cos_y - z * sin_y;
+ nodes[i][2] = z * cos_y + y * sin_y;
+ }
+}
+
+void fx_cube_init(SDL_Renderer *target_renderer, SDL_Color foreground_color) {+
+ fx_renderer = target_renderer;
+ line_color = foreground_color;
+
+ texture_cube =
+ SDL_CreateTexture(fx_renderer, SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_TARGET, target_width, target_height);
+ texture_text =
+ SDL_CreateTexture(fx_renderer, SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_TARGET, target_width, target_height);
+
+ SDL_Texture *og_target = SDL_GetRenderTarget(fx_renderer);
+
+ SDL_SetRenderTarget(fx_renderer, texture_text);
+
+ inprint(fx_renderer, text_disconnected, 168, 230, 0xFFFFFF, 0x000000);
+ inprint(fx_renderer, text_m8c, 2, 2, 0xFFFFFF, 0x000000);
+
+ SDL_SetRenderTarget(fx_renderer, og_target);
+
+ // Initialize default nodes
+ SDL_memcpy(nodes, default_nodes, sizeof(default_nodes));
+
+ scale(50, 50, 50);
+ rotate_cube(M_PI / 4, SDL_atan(SDL_sqrt(2)));
+
+ SDL_SetTextureBlendMode(texture_cube, SDL_BLENDMODE_BLEND);
+ SDL_SetTextureBlendMode(texture_text, SDL_BLENDMODE_BLEND);
+}
+
+void fx_cube_destroy() {+ SDL_DestroyTexture(texture_cube);
+ SDL_DestroyTexture(texture_text);
+}
+
+void fx_cube_update() {+ SDL_Point points[24];
+ int points_counter = 0;
+ SDL_Texture *og_texture = SDL_GetRenderTarget(fx_renderer);
+
+ SDL_SetRenderTarget(fx_renderer, texture_cube);
+ SDL_SetRenderDrawColor(fx_renderer, 0, 0, 0, 200);
+ SDL_RenderClear(fx_renderer);
+
+ int seconds = SDL_GetTicks() / 1000;
+ float scalefactor = 1 + (SDL_sin(seconds) * 0.01);
+
+ scale(scalefactor, scalefactor, scalefactor);
+ rotate_cube(M_PI / 180, M_PI / 270);
+
+ for (int i = 0; i < 12; i++) {+ float *p1 = nodes[edges[i][0]];
+ float *p2 = nodes[edges[i][1]];
+ points[points_counter++] =
+ (SDL_Point){p1[0] + center_x, nodes[edges[i][0]][1] + center_y};+ points[points_counter++] = (SDL_Point){p2[0] + center_x, p2[1] + center_y};+ }
+
+ SDL_RenderCopy(fx_renderer, texture_text, NULL, NULL);
+ SDL_SetRenderDrawColor(fx_renderer, line_color.r, line_color.g, line_color.b,
+ line_color.a);
+ SDL_RenderDrawLines(fx_renderer, points, 24);
+
+ SDL_SetRenderTarget(fx_renderer, og_texture);
+ SDL_RenderCopy(fx_renderer, texture_cube, NULL, NULL);
+}
--- /dev/null
+++ b/fx_cube.h
@@ -1,0 +1,8 @@
+#ifndef FX_CUBE_H_
+#define FX_CUBE_H_
+
+#include "SDL_render.h"
+void fx_cube_init(SDL_Renderer *target_renderer, SDL_Color foreground_color);
+void fx_cube_destroy();
+void fx_cube_update();
+#endif
\ No newline at end of file
--- a/input.c
+++ b/input.c
@@ -394,6 +394,7 @@
if (event.key.keysym.sym == SDLK_F4 &&
(event.key.keysym.mod & KMOD_ALT) > 0) { key = (input_msg_s){special, msg_quit};+ break;
}
// ESC = toggle keyjazz
--- a/main.c
+++ b/main.c
@@ -1,7 +1,8 @@
// Copyright 2021 Jonne Kokkonen
// Released under the MIT licence, https://opensource.org/licenses/MIT
-// Uncomment this line to enable debug messages or call make with `make CFLAGS=-DDEBUG_MSG`
+/* Uncomment this line to enable debug messages or call make with `make
+ CFLAGS=-DDEBUG_MSG` */
// #define DEBUG_MSG
#include <SDL.h>
@@ -21,12 +22,20 @@
// maximum amount of bytes to read from the serial in one read()
#define serial_read_size 324
-uint8_t run = 1;
+enum state { QUIT, WAIT_FOR_DEVICE, RUN };+
+enum state run = WAIT_FOR_DEVICE;
uint8_t need_display_reset = 0;
// Handles CTRL+C / SIGINT
-void intHandler(int dummy) { run = 0; }+void intHandler(int dummy) { run = QUIT; }+void close_serial_port(struct sp_port *port) {+ disconnect(port);
+ sp_close(port);
+ sp_free_port(port);
+}
+
int main(int argc, char *argv[]) {// Initialize the config to defaults read in the params from the
// configfile if present
@@ -49,109 +58,196 @@
};
static slip_handler_s slip;
+ struct sp_port *port = NULL;
+ uint8_t prev_input = 0;
+ uint8_t prev_note = 0;
+ uint16_t zerobyte_packets = 0; // used to detect device disconnection
+
signal(SIGINT, intHandler);
signal(SIGTERM, intHandler);
slip_init(&slip, &slip_descriptor);
- struct sp_port *port;
+ // First device detection to avoid SDL init if it isn't necessary
+ if (conf.wait_for_device == 0) {+ port = init_serial(1);
+ if (port == NULL) {+ free(serial_buf);
+ return -1;
+ }
+ }
- port = init_serial();
- if (port == NULL)
- return -1;
-
+ // initialize all SDL systems
if (initialize_sdl(conf.init_fullscreen, conf.init_use_gpu) == -1)
- run = 0;
+ run = QUIT;
- if (enable_and_reset_display(port) == -1)
- run = 0;
-
- #ifdef DEBUG_MSG
+#ifdef DEBUG_MSG
SDL_LogSetAllPriority(SDL_LOG_PRIORITY_DEBUG);
- #endif
+#endif
- uint8_t prev_input = 0;
- uint8_t prev_note = 0;
+ // main loop begin
+ do {+ if (port == NULL)
+ port = init_serial(1);
+ if (port != NULL) {+ int result;
+ result = enable_and_reset_display(port);
+ if (result == 1) {+ run = RUN;
+ } else {+ run = QUIT;
+ }
+ }
- // main loop
- while (run) {+ // wait until device is connected
+ if (conf.wait_for_device) {+ static uint32_t ticks_poll_device = 0;
+ static uint32_t ticks_update_screen = 0;
- // get current inputs
- input_msg_s input = get_input_msg(&conf);
+ if (port == NULL)
+ screensaver_init();
- switch (input.type) {- case normal:
- if (input.value != prev_input) {- prev_input = input.value;
- send_msg_controller(port, input.value);
- }
- break;
- case keyjazz:
- if (input.value != 0) {- if (input.eventType == SDL_KEYDOWN && input.value != prev_input) {- send_msg_keyjazz(port, input.value, input.value2);
- prev_note = input.value;
- } else if (input.eventType == SDL_KEYUP && input.value == prev_note) {- send_msg_keyjazz(port, 0xFF, 0);
+ while (run == WAIT_FOR_DEVICE) {+ // get current inputs
+ input_msg_s input = get_input_msg(&conf);
+ if (input.type == special && input.value == msg_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 && (SDL_GetTicks() - ticks_poll_device > 1000)) {+ ticks_poll_device = SDL_GetTicks();
+ port = init_serial(0);
+ if (run == WAIT_FOR_DEVICE && port != NULL) {+ int result = enable_and_reset_display(port);
+ SDL_Delay(100);
+ // Device was found; enable display and proceed to the main loop
+ if (result == 1) {+ run = RUN;
+ screensaver_destroy();
+ } else {+ run = QUIT;
+ screensaver_destroy();
+ }
+ }
+ }
+
+ SDL_Delay(conf.idle_ms);
}
- prev_input = input.value;
- break;
- case special:
- if (input.value != prev_input) {+
+ } else {+ // classic startup behaviour, exit if device is not found
+ if (port == NULL) {+ close_game_controllers();
+ close_renderer();
+ SDL_Quit();
+ free(serial_buf);
+ return -1;
+ }
+ }
+
+ // main loop
+ while (run == RUN) {+
+ // get current inputs
+ 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(port, input.value);
+ }
+ break;
+ case keyjazz:
+ if (input.value != 0) {+ if (input.eventType == SDL_KEYDOWN && input.value != prev_input) {+ send_msg_keyjazz(port, input.value, input.value2);
+ prev_note = input.value;
+ } else if (input.eventType == SDL_KEYUP && input.value == prev_note) {+ send_msg_keyjazz(port, 0xFF, 0);
+ }
+ }
prev_input = input.value;
- switch (input.value) {- case msg_quit:
- run = 0;
+ break;
+ case special:
+ if (input.value != prev_input) {+ prev_input = input.value;
+ switch (input.value) {+ case msg_quit:
+ run = 0;
+ break;
+ case msg_reset_display:
+ reset_display(port);
+ break;
+ default:
+ break;
+ }
break;
- case msg_reset_display:
- reset_display(port);
- break;
- default:
- break;
}
- break;
}
- }
- while (1) {- // read serial port
- int bytes_read = sp_nonblocking_read(port, serial_buf, serial_read_size);
- if (bytes_read < 0) {- SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Error %d reading serial. \n",
- (int)bytes_read);
- run = 0;
- break;
- } else if (bytes_read > 0) {- 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
- int n = slip_read_byte(&slip, *(cur++));
- if (n != SLIP_NO_ERROR) {- if (n == SLIP_ERROR_INVALID_PACKET) {- reset_display(port);
+ while (1) {+ // read serial port
+ int bytes_read =
+ sp_nonblocking_read(port, serial_buf, serial_read_size);
+ if (bytes_read < 0) {+ SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "Error %d reading serial. \n",
+ (int)bytes_read);
+ run = QUIT;
+ break;
+ } else if (bytes_read > 0) {+ // input from device: reset the zero byte counter and create a
+ // pointer to the serial buffer
+ zerobyte_packets = 0;
+ 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
+ int n = slip_read_byte(&slip, *(cur++));
+ if (n != SLIP_NO_ERROR) {+ if (n == SLIP_ERROR_INVALID_PACKET) {+ reset_display(port);
+ } else {+ SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", n);
+ }
+ }
+ }
+ } else {+ // zero byte packet, increment counter
+ zerobyte_packets++;
+ if (zerobyte_packets > 128) {+ // i guess it can be assumed that the device has been disconnected
+ if (conf.wait_for_device) {+ run = WAIT_FOR_DEVICE;
+ close_serial_port(port);
+ port = NULL;
+ break;
} else {- SDL_LogError(SDL_LOG_CATEGORY_ERROR, "SLIP error %d\n", n);
+ run = QUIT;
}
}
+ break;
}
- } else {- break;
}
+ render_screen();
+ SDL_Delay(conf.idle_ms);
}
- render_screen();
- SDL_Delay(conf.idle_ms);
- }
+ } while (run > QUIT);
+ // main loop end
// exit, clean up
SDL_Log("Shutting down\n");close_game_controllers();
close_renderer();
- disconnect(port);
- sp_close(port);
- sp_free_port(port);
+ close_serial_port(port);
free(serial_buf);
SDL_Quit();
return 0;
--- a/render.c
+++ b/render.c
@@ -7,15 +7,16 @@
#include <stdio.h>
#include "SDL2_inprint.h"
+#include "SDL_log.h"
+#include "SDL_render.h"
#include "command.h"
+#include "fx_cube.h"
SDL_Window *win;
SDL_Renderer *rend;
SDL_Texture *maintexture;
SDL_Color background_color = (SDL_Color){0, 0, 0, 0};-static uint32_t ticks;
-
static uint32_t ticks_fps;
static int fps;
uint8_t fullscreen = 0;
@@ -24,7 +25,7 @@
// Initializes SDL and creates a renderer and required surfaces
int initialize_sdl(int init_fullscreen, int init_use_gpu) {- ticks = SDL_GetTicks();
+ //ticks = SDL_GetTicks();
const int window_width = 640; // SDL window width
const int window_height = 480; // SDL window height
@@ -33,6 +34,8 @@
SDL_LogCritical(SDL_LOG_CATEGORY_ERROR, "SDL_Init: %s\n", SDL_GetError());
return -1;
}
+ // SDL documentation recommends this
+ atexit(SDL_Quit);
win = SDL_CreateWindow("m8c", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,window_width, window_height,
@@ -39,7 +42,8 @@
SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL |
SDL_WINDOW_RESIZABLE | init_fullscreen);
- rend = SDL_CreateRenderer(win, -1, init_use_gpu ? SDL_RENDERER_ACCELERATED : SDL_RENDERER_SOFTWARE);
+ rend = SDL_CreateRenderer(
+ win, -1, init_use_gpu ? SDL_RENDERER_ACCELERATED : SDL_RENDERER_SOFTWARE);
SDL_RenderSetLogicalSize(rend, 320, 240);
@@ -72,7 +76,8 @@
int fullscreen_state = SDL_GetWindowFlags(win) & SDL_WINDOW_FULLSCREEN;
- SDL_SetWindowFullscreen(win, fullscreen_state ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
+ SDL_SetWindowFullscreen(win,
+ fullscreen_state ? 0 : SDL_WINDOW_FULLSCREEN_DESKTOP);
SDL_ShowCursor(fullscreen_state);
dirty = 1;
@@ -128,23 +133,25 @@
static uint8_t wfm_cleared = 0;
- // If the waveform is not being displayed and it's already been cleared, skip rendering it
- if (! (wfm_cleared && command->waveform_size == 0)) {+ // If the waveform is not being displayed and it's already been cleared, skip
+ // rendering it
+ if (!(wfm_cleared && command->waveform_size == 0)) { const SDL_Rect wf_rect = {0, 0, 320, 21};SDL_SetRenderDrawColor(rend, background_color.r, background_color.g,
- background_color.b, background_color.a);
+ background_color.b, background_color.a);
SDL_RenderFillRect(rend, &wf_rect);
SDL_SetRenderDrawColor(rend, command->color.r, command->color.g,
- command->color.b, 255);
+ command->color.b, 255);
// Create a SDL_Point array of the waveform pixels for batch drawing
SDL_Point waveform_points[command->waveform_size];
for (int i = 0; i < command->waveform_size; i++) {- // Limit value because the oscilloscope commands seem to glitch occasionally
+ // Limit value because the oscilloscope commands seem to glitch
+ // occasionally
if (command->waveform[i] > 20)
command->waveform[i] = 20;
waveform_points[i].x = i;
@@ -156,8 +163,7 @@
// The packet we just drew was an empty waveform
if (command->waveform_size == 0) {wfm_cleared = 1;
- }
- else {+ } else {wfm_cleared = 0;
}
@@ -165,7 +171,8 @@
}
}
-void display_keyjazz_overlay(uint8_t show, uint8_t base_octave, uint8_t velocity) {+void display_keyjazz_overlay(uint8_t show, uint8_t base_octave,
+ uint8_t velocity) { if (show) {struct draw_rectangle_command drc;
@@ -189,7 +196,7 @@
char buf[8];
snprintf(buf, sizeof(buf), "%02X %u", velocity, base_octave);
- for (int i = 3; i >= 0; i--){+ for (int i = 3; i >= 0; i--) {dcc.c = buf[i];
draw_character(&dcc);
dcc.pos.x -= 8;
@@ -213,7 +220,7 @@
void render_screen() { if (dirty) {dirty = 0;
- ticks = SDL_GetTicks();
+ //ticks = SDL_GetTicks();
SDL_SetRenderTarget(rend, NULL);
SDL_SetRenderDrawColor(rend, 0, 0, 0, 0);
SDL_RenderClear(rend);
@@ -229,4 +236,19 @@
fps = 0;
}
}
+}
+
+void screensaver_init() {+ fx_cube_init(rend, (SDL_Color){255, 255, 255, 255});+ SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Screensaver initialized");
+}
+
+void screensaver_draw() {+ fx_cube_update();
+ dirty = 1;
+}
+
+void screensaver_destroy() {+ fx_cube_destroy();
+ SDL_LogDebug(SDL_LOG_CATEGORY_APPLICATION, "Screensaver destroyed");
}
--- a/render.h
+++ b/render.h
@@ -18,4 +18,8 @@
void toggle_fullscreen();
void display_keyjazz_overlay(uint8_t show, uint8_t base_octave, uint8_t velocity);
+void screensaver_init();
+void screensaver_draw();
+void screensaver_destroy();
+
#endif
\ No newline at end of file
--- a/serial.c
+++ b/serial.c
@@ -30,13 +30,14 @@
return 0;
}
-struct sp_port *init_serial() {+struct sp_port *init_serial(int verbose) {/* A pointer to a null-terminated array of pointers to
* struct sp_port, which will contain the ports found.*/
struct sp_port *m8_port = NULL;
struct sp_port **port_list;
- SDL_Log("Looking for USB serial devices.\n");+ 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. */
@@ -61,29 +62,36 @@
sp_free_port_list(port_list);
if (m8_port != NULL) {- // Open the serial port and configure it
- SDL_Log("Opening port.\n");- enum sp_return result;
+ // Open the serial port and configure it
+ SDL_Log("Opening port.\n");+ enum sp_return result;
- result = sp_open(m8_port, SP_MODE_READ_WRITE);
- if (check(result) != SP_OK) return NULL;
-
- result = sp_set_baudrate(m8_port, 115200);
- if (check(result) != SP_OK) return NULL;
-
- result = sp_set_bits(m8_port, 8);
- if (check(result) != SP_OK) return NULL;
-
- result = sp_set_parity(m8_port, SP_PARITY_NONE);
- if (check(result) != SP_OK) return NULL;
-
- result = sp_set_stopbits(m8_port, 1);
- if (check(result) != SP_OK) return NULL;
-
- result = sp_set_flowcontrol(m8_port, SP_FLOWCONTROL_NONE);
- if (check(result) != SP_OK) return NULL;
+ result = sp_open(m8_port, SP_MODE_READ_WRITE);
+ if (check(result) != SP_OK)
+ return NULL;
+
+ result = sp_set_baudrate(m8_port, 115200);
+ if (check(result) != SP_OK)
+ return NULL;
+
+ result = sp_set_bits(m8_port, 8);
+ if (check(result) != SP_OK)
+ return NULL;
+
+ result = sp_set_parity(m8_port, SP_PARITY_NONE);
+ if (check(result) != SP_OK)
+ return NULL;
+
+ result = sp_set_stopbits(m8_port, 1);
+ if (check(result) != SP_OK)
+ return NULL;
+
+ result = sp_set_flowcontrol(m8_port, SP_FLOWCONTROL_NONE);
+ if (check(result) != SP_OK)
+ return NULL;
} else {- SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "Cannot find a M8.\n");
+ if (verbose)
+ SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "Cannot find a M8.\n");
}
return (m8_port);
@@ -100,7 +108,8 @@
break;
case SP_ERR_FAIL:
error_message = sp_last_error_message();
- SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Error: Failed: %s\n", 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:
@@ -107,11 +116,12 @@
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");
+ SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
+ "Error: Couldn't allocate memory.\n");
break;
case SP_OK:
default:
- break;
+ break;
}
return result;
}
--- a/serial.h
+++ b/serial.h
@@ -6,6 +6,6 @@
#include <libserialport.h>
-struct sp_port *init_serial();
+struct sp_port *init_serial(int verbose);
#endif
\ No newline at end of file
--- a/write.c
+++ b/write.c
@@ -1,6 +1,7 @@
// Copyright 2021 Jonne Kokkonen
// Released under the MIT licence, https://opensource.org/licenses/MIT
+#include "SDL_timer.h"
#include <SDL_log.h>
#include <libserialport.h>
#include <stdint.h>
@@ -7,7 +8,7 @@
#include <stdio.h>
#include <unistd.h>
-int reset_display(struct sp_port *port){+int reset_display(struct sp_port *port) { SDL_Log("Reset display\n");uint8_t buf[2];
int result;
@@ -14,10 +15,11 @@
buf[0] = 0x45;
buf[1] = 0x52;
-
+
result = sp_blocking_write(port, buf, 2, 5);
if (result != 2) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d", result);
+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error resetting M8 display, code %d",
+ result);
return 0;
}
return 1;
@@ -32,15 +34,17 @@
buf[0] = 0x44;
result = sp_blocking_write(port, buf, 1, 5);
if (result != 1) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error enabling M8 display, code %d", result);
+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error enabling M8 display, code %d",
+ result);
return 0;
}
- usleep(500);
- if (!reset_display(port)){+ SDL_Delay(5);
+ result = reset_display(port);
+ if (result == 1)
+ return 1;
+ else
return 0;
- }
- return 1;
}
int disconnect(struct sp_port *port) {@@ -51,7 +55,8 @@
result = sp_blocking_write(port, buf, 1, 5);
if (result != 1) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending disconnect, code %d", result);
+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending disconnect, code %d",
+ result);
return -1;
}
return 1;
@@ -58,27 +63,28 @@
}
int send_msg_controller(struct sp_port *port, uint8_t input) {- char buf[2] = {'C',input};+ char buf[2] = {'C', input};size_t nbytes = 2;
int result;
result = sp_blocking_write(port, buf, nbytes, 5);
if (result != nbytes) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending input, code %d", result);
+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending input, code %d",
+ result);
return -1;
}
return 1;
-
}
int send_msg_keyjazz(struct sp_port *port, uint8_t note, uint8_t velocity) {if (velocity > 0x7F)
velocity = 0x7F;
- char buf[3] = {'K',note,velocity};+ char buf[3] = {'K', note, velocity};size_t nbytes = 3;
int result;
- result = sp_blocking_write(port, buf, nbytes,5);
+ result = sp_blocking_write(port, buf, nbytes, 5);
if (result != nbytes) {- SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending keyjazz, code %d", result);
+ SDL_LogError(SDL_LOG_CATEGORY_SYSTEM, "Error sending keyjazz, code %d",
+ result);
return -1;
}
--
⑨