ref: 61fa136412fcc4504e198cd6d457a7cb57ed17d1
parent: 9bfe4ddb18ee77192c57b91c4ef305082588d77e
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Wed Nov 24 07:28:06 EST 2021
analog joy support, update readme with faq section
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@
```
cd m8c
-make && sudo make install
+make
```
### Start the program
@@ -57,7 +57,7 @@
Connect the Teensy to your computer and start the program. It should automatically detect your device.
```
-m8c
+./m8c
```
If the stars are aligned correctly, you should see the M8 screen.
@@ -101,16 +101,22 @@
-----------
-### Bonus: improve performance on the Raspberry Pi
-Enabling the experimental GL Driver with Full KMS can boost the program's performance a bit.
+## FAQ
-The driver can be enabled with ```sudo raspi-config``` and selecting "Advanced options" -> "GL Driver" -> "GL (Full KMS)" and rebooting.
+* When starting the program, something like the following appears and the program does not start:
+```
+$ ./m8c
+INFO: Looking for USB serial devices.
+INFO: Found M8 in /dev/ttyACM1.
+INFO: Opening port.
+Aborted (core dumped)
+```
-Please note that with some configurations (for example, composite video) this can lead to not getting video output at all. If that happens, you can delete the row ```dtoverlay=vc4-kms-v3d``` in bottom of /boot/config.txt.
+This is likely an issue with the version of libserialport included in your Linux distribution and you need to build the library yourself. Please see [this issue for a workaround](https://github.com/laamaa/m8c/issues/20).
-Further performance improvement can be achieved by not using X11 and running the program directly in framebuffer console, but this might require doing a custom build of SDL.
+-----------
-### Bonus: quickly install m8c locally with nix
+### Bonus content: quickly install m8c locally with nix
``` sh
nix-env -iA m8c-stable -f https://github.com/laamaa/m8c/archive/refs/heads/main.tar.gz
--- a/config.c
+++ b/config.c
@@ -25,14 +25,15 @@
c.key_delete = SDL_SCANCODE_DELETE;
c.key_reset = SDL_SCANCODE_R;
- c.gamepad_up = SDL_CONTROLLER_BUTTON_DPAD_UP;
- c.gamepad_left = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
- c.gamepad_down = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
- c.gamepad_right = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
- c.gamepad_select = SDL_CONTROLLER_BUTTON_BACK;
- c.gamepad_start = SDL_CONTROLLER_BUTTON_START;
- c.gamepad_opt = SDL_CONTROLLER_BUTTON_B;
- c.gamepad_edit = SDL_CONTROLLER_BUTTON_A;
+ c.gamepad_up = SDL_CONTROLLER_BUTTON_DPAD_UP;
+ c.gamepad_left = SDL_CONTROLLER_BUTTON_DPAD_LEFT;
+ c.gamepad_down = SDL_CONTROLLER_BUTTON_DPAD_DOWN;
+ c.gamepad_right = SDL_CONTROLLER_BUTTON_DPAD_RIGHT;
+ c.gamepad_select = SDL_CONTROLLER_BUTTON_BACK;
+ c.gamepad_start = SDL_CONTROLLER_BUTTON_START;
+ c.gamepad_opt = SDL_CONTROLLER_BUTTON_B;
+ c.gamepad_edit = SDL_CONTROLLER_BUTTON_A;
+ c.gamepad_analog_threshold = 32000;
return c;
}
@@ -98,21 +99,23 @@
void read_gamepad_config(ini_t *ini, config_params_s *conf) {// TODO: Some form of validation
- const char *gamepad_up = ini_get(ini, "gamepad", "gamepad_up");
- const char *gamepad_left = ini_get(ini, "gamepad", "gamepad_left");
- const char *gamepad_down = ini_get(ini, "gamepad", "gamepad_down");
- const char *gamepad_right = ini_get(ini, "gamepad", "gamepad_right");
- const char *gamepad_select = ini_get(ini, "gamepad", "gamepad_select");
- const char *gamepad_start = ini_get(ini, "gamepad", "gamepad_start");
- const char *gamepad_opt = ini_get(ini, "gamepad", "gamepad_opt");
- const char *gamepad_edit = ini_get(ini, "gamepad", "gamepad_edit");
+ const char *gamepad_up = ini_get(ini, "gamepad", "gamepad_up");
+ const char *gamepad_left = ini_get(ini, "gamepad", "gamepad_left");
+ const char *gamepad_down = ini_get(ini, "gamepad", "gamepad_down");
+ const char *gamepad_right = ini_get(ini, "gamepad", "gamepad_right");
+ const char *gamepad_select = ini_get(ini, "gamepad", "gamepad_select");
+ const char *gamepad_start = ini_get(ini, "gamepad", "gamepad_start");
+ const char *gamepad_opt = ini_get(ini, "gamepad", "gamepad_opt");
+ const char *gamepad_edit = ini_get(ini, "gamepad", "gamepad_edit");
+ const char *gamepad_analog_threshold = ini_get(ini, "gamepad", "gamepad_analog_threshold");
- conf->gamepad_up = atoi(gamepad_up);
- conf->gamepad_left = atoi(gamepad_left);
- conf->gamepad_down = atoi(gamepad_down);
- conf->gamepad_right = atoi(gamepad_right);
- conf->gamepad_select = atoi(gamepad_select);
- conf->gamepad_start = atoi(gamepad_start);
- conf->gamepad_opt = atoi(gamepad_opt);
- conf->gamepad_edit = atoi(gamepad_edit);
+ conf->gamepad_up = atoi(gamepad_up);
+ conf->gamepad_left = atoi(gamepad_left);
+ conf->gamepad_down = atoi(gamepad_down);
+ conf->gamepad_right = atoi(gamepad_right);
+ conf->gamepad_select = atoi(gamepad_select);
+ conf->gamepad_start = atoi(gamepad_start);
+ conf->gamepad_opt = atoi(gamepad_opt);
+ conf->gamepad_edit = atoi(gamepad_edit);
+ conf->gamepad_analog_threshold = atoi(gamepad_analog_threshold);
}
\ No newline at end of file
--- a/config.h
+++ b/config.h
@@ -33,6 +33,8 @@
int gamepad_start;
int gamepad_opt;
int gamepad_edit;
+
+ int gamepad_analog_threshold;
} config_params_s;
--- a/config.ini
+++ b/config.ini
@@ -30,4 +30,5 @@
gamepad_select=4
gamepad_start=6
gamepad_opt=1
-gamepad_edit=0
\ No newline at end of file
+gamepad_edit=0
+gamepad_analog_threshold=32767 ;the threshold for analog sticks to trigger cursor movement (range: 1-32767)
\ No newline at end of file
--- a/input.c
+++ b/input.c
@@ -2,6 +2,9 @@
// Released under the MIT licence, https://opensource.org/licenses/MIT
#include <SDL2/SDL.h>
+#include <SDL2/SDL_events.h>
+#include <SDL2/SDL_gamecontroller.h>
+#include <SDL2/SDL_log.h>
#include <stdio.h>
#include "config.h"
@@ -28,7 +31,8 @@
uint8_t keyjazz_enabled = 0;
uint8_t keyjazz_base_octave = 2;
-uint8_t keycode = 0; // value of the pressed key
+uint8_t keycode = 0; // value of the pressed key
+static int controller_axis_released = 1; // is analog axis released
input_msg_s key = {normal, 0}; uint8_t toggle_input_keyjazz() {@@ -184,7 +188,8 @@
return key;
}
-static input_msg_s handle_normal_keys(SDL_Event *event, config_params_s *conf, uint8_t keyvalue) {+static input_msg_s handle_normal_keys(SDL_Event *event, config_params_s *conf,
+ uint8_t keyvalue) { input_msg_s key = {normal, keyvalue}; if (event->key.keysym.scancode == conf->key_up) {@@ -195,13 +200,17 @@
key.value = key_down;
} else if (event->key.keysym.scancode == conf->key_right) {key.value = key_right;
- } else if (event->key.keysym.scancode == conf->key_select || event->key.keysym.scancode == conf->key_select_alt ) {+ } else if (event->key.keysym.scancode == conf->key_select ||
+ event->key.keysym.scancode == conf->key_select_alt) {key.value = key_select;
- } else if (event->key.keysym.scancode == conf->key_start || event->key.keysym.scancode == conf->key_start_alt) {+ } else if (event->key.keysym.scancode == conf->key_start ||
+ event->key.keysym.scancode == conf->key_start_alt) {key.value = key_start;
- } else if (event->key.keysym.scancode == conf->key_opt || event->key.keysym.scancode == conf->key_opt_alt) {+ } else if (event->key.keysym.scancode == conf->key_opt ||
+ event->key.keysym.scancode == conf->key_opt_alt) {key.value = key_opt;
- } else if (event->key.keysym.scancode == conf->key_edit || event->key.keysym.scancode == conf->key_edit_alt) {+ } else if (event->key.keysym.scancode == conf->key_edit ||
+ event->key.keysym.scancode == conf->key_edit_alt) {key.value = key_edit;
} else if (event->key.keysym.scancode == conf->key_delete) {key.value = key_opt | key_edit;
@@ -213,7 +222,9 @@
return key;
}
-static input_msg_s handle_game_controller_buttons(SDL_Event *event, config_params_s *conf, uint8_t keyvalue) {+static input_msg_s handle_game_controller_buttons(SDL_Event *event,
+ config_params_s *conf,
+ uint8_t keyvalue) { input_msg_s key = {normal, keyvalue}; if (event->cbutton.button == conf->gamepad_up) {@@ -238,6 +249,71 @@
return key;
}
+static input_msg_s handle_game_controller_axis(SDL_Event *event,
+ config_params_s *conf,
+ uint8_t keyvalue) {+
+ input_msg_s key = {normal, keyvalue};+
+ // Handle up-down movement
+ if (event->caxis.axis == SDL_CONTROLLER_AXIS_LEFTY ||
+ event->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTY) {+
+ if (event->caxis.value > 0) {+ key.value = key_down;
+ if (event->caxis.value < conf->gamepad_analog_threshold) {+ if (controller_axis_released == 0) {+ controller_axis_released = 1;
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Axis released");
+ }
+ } else {+ controller_axis_released = 0;
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Axis down");
+ }
+ } else {+ key.value = key_up;
+ if (event->caxis.value > 0 - conf->gamepad_analog_threshold) {+ if (controller_axis_released == 0) {+ controller_axis_released = 1;
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Axis released");
+ }
+ } else {+ controller_axis_released = 0;
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Axis up");
+ }
+ }
+ }
+ // Handle left-right movement
+ else if (event->caxis.axis == SDL_CONTROLLER_AXIS_LEFTX ||
+ event->caxis.axis == SDL_CONTROLLER_AXIS_RIGHTX) {+ if (event->caxis.value > 0) {+ key.value = key_right;
+ if (event->caxis.value < conf->gamepad_analog_threshold) {+ if (controller_axis_released == 0) {+ controller_axis_released = 1;
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Axis released");
+ }
+ } else {+ controller_axis_released = 0;
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Axis down");
+ }
+ } else {+ key.value = key_left;
+ if (event->caxis.value > 0 - conf->gamepad_analog_threshold) {+ if (controller_axis_released == 0) {+ controller_axis_released = 1;
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Axis released");
+ }
+ } else {+ controller_axis_released = 0;
+ SDL_LogDebug(SDL_LOG_CATEGORY_INPUT, "Axis up");
+ }
+ }
+ }
+
+ return key;
+}
+
// Handles SDL input events
void handle_sdl_events(config_params_s *conf) {@@ -293,6 +369,10 @@
key = handle_game_controller_buttons(&event, conf, 0);
break;
+ case SDL_CONTROLLERAXISMOTION:
+ key = handle_game_controller_axis(&event, conf, 0);
+ break;
+
default:
break;
}
@@ -299,10 +379,14 @@
// Do not allow pressing multiple keys with keyjazz
if (key.type == normal) {- if (event.type == SDL_KEYDOWN || event.type == SDL_CONTROLLERBUTTONDOWN)
+
+ if (event.type == SDL_KEYDOWN || event.type == SDL_CONTROLLERBUTTONDOWN ||
+ controller_axis_released == 0) {keycode |= key.value;
- else
+ } else {keycode &= ~key.value;
+ }
+
} else {if (event.type == SDL_KEYDOWN)
keycode = key.value;
@@ -319,8 +403,8 @@
// Query for SDL events
handle_sdl_events(conf);
- if (keycode == (key_start|key_select|key_opt|key_edit)){- key = (input_msg_s){special,msg_reset_display};+ if (keycode == (key_start | key_select | key_opt | key_edit)) {+ key = (input_msg_s){special, msg_reset_display};}
if (key.type == normal) {--
⑨