ref: 8d03da9b86beac6175cf139b4270c5b711f49e90
parent: c0fa529f359e5cb21a2b3f37fe5b641714b3e2ed
author: Jonne Kokkonen <jonne.kokkonen@gmail.com>
date: Sun Apr 18 09:42:17 EDT 2021
limit oscilloscope values, clean up stuff a bit
--- a/Makefile
+++ b/Makefile
@@ -11,7 +11,7 @@
INCLUDES = -lSDL2_ttf
#Set any compiler flags you want to use (e.g. -I/usr/include/somefolder `pkg-config --cflags gtk+-3.0` ), or leave blank
-CFLAGS = `sdl2-config --libs --cflags` -march=native -Wall -O2 -pipe -I. -g
+CFLAGS = `sdl2-config --libs --cflags` -march=native -Wall -O2 -pipe -I.
#Set the compiler you are using ( gcc for C or g++ for C++ )
CC = gcc
--- a/command.c
+++ b/command.c
@@ -1,4 +1,4 @@
-#include <stdint.h>
+
#include <stdio.h>
#include <string.h>
@@ -12,7 +12,7 @@
return data[start] | (uint16_t)data[start + 1] << 8;
}
-enum {+enum m8_command_bytes {draw_rectangle_command = 0xFE,
draw_rectangle_command_datalength = 12,
draw_character_command = 0xFD,
@@ -24,6 +24,13 @@
joypad_keypressedstate_command_datalength = 2
};
+static inline void dump_packet(uint32_t size, uint8_t *recv_buf) {+ for (uint16_t a = 0; a < size; a++) {+ fprintf(stderr, "0x%02X ", recv_buf[a]);
+ }
+ fprintf(stderr, "\n");
+}
+
void process_command(uint8_t *data, uint32_t size,
struct command_queues *command_queues) {@@ -31,136 +38,93 @@
memcpy(recv_buf, data, size);
recv_buf[size] = 0;
-#if DEBUG > 2
- fprintf(stderr, "RECV size %d: ", size);
- for (int i = 0; i < size; i++) {- fprintf(stderr, "0x%02X ", recv_buf[i]);
- }
- fprintf(stderr, "\n");
-#endif
switch (recv_buf[0]) {case draw_rectangle_command:
+
if (size != draw_rectangle_command_datalength) {-#if DEBUG > 0
fprintf(stderr,
"Invalid draw rectangle packet: expected length %d, got %d\n",
draw_rectangle_command_datalength, size);
- for (uint16_t a = 0; a < size; a++) {- fprintf(stderr, "0x%02X ", recv_buf[a]);
- }
- fprintf(stderr, "\n");
-#endif
+ dump_packet(size, recv_buf);
break;
}
+
struct draw_rectangle_command rectcmd = { {decodeInt16(recv_buf, 1), decodeInt16(recv_buf, 3)}, // position x/y {decodeInt16(recv_buf, 5), decodeInt16(recv_buf, 7)}, // size w/h {recv_buf[9], recv_buf[10], recv_buf[11]}}; // color r/g/b- draw_rectangle(&rectcmd);
- // command_queues->rectangles[command_queues->rectangles_queue_size++] =
- // rectcmd;
-#if DEBUG > 1
- fprintf(
- stderr, "Rectangle: x: %d, y: %d, w: %d, h: %d, r: %d, g: %d, b: %d\n",
- rectcmd.pos.x, rectcmd.pos.y, rectcmd.size.width, rectcmd.size.height,
- rectcmd.color.r, rectcmd.color.g, rectcmd.color.b);
-#endif
+ draw_rectangle(&rectcmd);
+
break;
case draw_character_command:
+
if (size != draw_character_command_datalength) {-#if DEBUG > 0
fprintf(stderr,
"Invalid draw character packet: expected length %d, got %d\n",
draw_character_command_datalength, size);
- for (uint16_t a = 0; a < size; a++) {- fprintf(stderr, "0x%02X ", recv_buf[a]);
- }
- fprintf(stderr, "\n");
+ dump_packet(size, recv_buf);
break;
-#endif
}
+
struct draw_character_command charcmd = {recv_buf[1], // char
{decodeInt16(recv_buf, 2), decodeInt16(recv_buf, 4)}, // position x/y {recv_buf[6], recv_buf[7], recv_buf[8]}, // foreground r/g/b {recv_buf[9], recv_buf[10], recv_buf[11]}}; // background r/g/b- draw_character(&charcmd);
- // command_queues->characters[command_queues->characters_queue_size++] =
- // charcmd;
+ draw_character(&charcmd);
+
break;
case draw_oscilloscope_waveform_command:
- if (size < draw_oscilloscope_waveform_command_mindatalength) {-#if DEBUG > 0
+
+ if (size < draw_oscilloscope_waveform_command_mindatalength ||
+ size > draw_oscilloscope_waveform_command_maxdatalength) {fprintf(stderr,
- "Invalid draw oscilloscope packet: expected min length %d, got "
+ "Invalid draw oscilloscope packet: expected length between %d "
+ "and %d, got "
"%d\n",
- draw_oscilloscope_waveform_command_mindatalength, size);
- for (uint16_t a = 0; a < size; a++) {- fprintf(stderr, "0x%02X ", recv_buf[a]);
- }
- fprintf(stderr, "\n");
-#endif
- break;
- }
- if (size > draw_oscilloscope_waveform_command_maxdatalength) {-#if DEBUG > 0
- fprintf(stderr,
- "Invalid draw oscilloscope packet: expected max length %d, got "
- "%d\n",
+ draw_oscilloscope_waveform_command_mindatalength,
draw_oscilloscope_waveform_command_maxdatalength, size);
- for (uint16_t a = 0; a < size; a++) {- fprintf(stderr, "0x%02X ", recv_buf[a]);
- }
- fprintf(stderr, "\n");
-#endif
+ dump_packet(size, recv_buf);
break;
}
+
struct draw_oscilloscope_waveform_command osccmd;
+
osccmd.color =
(struct color){recv_buf[1], recv_buf[2], recv_buf[3]}; // color r/g/bmemcpy(osccmd.waveform, &recv_buf[4], size - 4);
+
osccmd.waveform_size = size - 4;
+
draw_waveform(&osccmd);
- // // only 1 oscilloscope command gets queued for now
- // command_queues->waveform = osccmd;
- // command_queues->waveforms_queue_size = 1;
-#if DEBUG > 1
- fprintf(stderr, "Oscilloscope: r: %d, g: %d, b: %d, data: ", osccmd.color.r,
- osccmd.color.g, osccmd.color.b);
- if (osccmd.waveform_size == 0) {- fprintf(stderr, "-");
- } else {- for (int w = 0; w < osccmd.waveform_size; w++) {- fprintf(stderr, "0x%02X", osccmd.waveform[w]);
- }
- }
- fprintf(stderr, "\n");
-#endif
+
break;
case joypad_keypressedstate_command:
+
if (size != joypad_keypressedstate_command_datalength) {-#if DEBUG > 0
fprintf(stderr,
"Invalid joypad keypressed state packet: expected length %d, "
"got %d\n",
joypad_keypressedstate_command_datalength, size);
+ dump_packet(size, recv_buf);
break;
-#endif
}
+
+ // nothing is done with joypad key pressed packets for now
+
break;
default:
+
fprintf(stderr, "Invalid packet\n");
- for (uint16_t a = 0; a < size; a++) {- fprintf(stderr, "0x%02X ", recv_buf[a]);
- }
- fprintf(stderr, "\n");
+ dump_packet(size, recv_buf);
+
break;
}
}
\ No newline at end of file
--- a/input.c
+++ b/input.c
@@ -21,12 +21,15 @@
};
int initialize_input() {+
int num_joysticks = SDL_NumJoysticks();
+
if (num_joysticks > 0) {js = SDL_JoystickOpen(0);
SDL_JoystickEventState(SDL_ENABLE);
fprintf(stderr, "Opened Joystick 0");
}
+
return num_joysticks;
}
@@ -33,11 +36,13 @@
void close_input() { SDL_JoystickClose(js); } uint8_t process_input() {+
SDL_Event event;
uint8_t key = 0;
static uint8_t input = 0;
SDL_PollEvent(&event);
+
switch (event.type) {case SDL_QUIT:
@@ -46,7 +51,9 @@
case SDL_JOYAXISMOTION:
switch (event.jaxis.axis) {+
case 0:
+
if (event.jaxis.value < 0) {input |= key_left;
break;
@@ -60,15 +67,19 @@
input &= ~key_right;
break;
}
+
case 1:
+
if (event.jaxis.value < 0) {input |= key_up;
break;
}
+
if (event.jaxis.value > 0) {input |= key_down;
break;
}
+
if (event.jaxis.value == 0) {input &= ~key_up;
input &= ~key_down;
@@ -75,11 +86,14 @@
break;
}
}
+
break;
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
+
switch (event.jbutton.button) {+
case 1:
key = key_edit;
break;
@@ -94,72 +108,84 @@
break;
}
- if (event.type == SDL_JOYBUTTONDOWN) {+ if (event.type == SDL_JOYBUTTONDOWN)
input |= key;
- } else {+ else
input &= ~key;
- }
+
return input;
+
break;
case SDL_KEYDOWN:
- //ALT+ENTER toggles fullscreen
+ // ALT+ENTER toggles fullscreen
if (event.key.keysym.sym == SDLK_RETURN &&
(event.key.keysym.mod & KMOD_ALT) > 0) {toggle_fullscreen();
}
- //CTRL+q quits program
- if (event.key.keysym.sym == SDLK_q && (event.key.keysym.mod & KMOD_CTRL) > 0){- return 21; //arbitary quit code for main loop
+ // CTRL+q quits program
+ if (event.key.keysym.sym == SDLK_q &&
+ (event.key.keysym.mod & KMOD_CTRL) > 0) {+ return 21; // arbitary quit code for main loop
}
case SDL_KEYUP:
switch (event.key.keysym.scancode) {+
case SDL_SCANCODE_I:
case SDL_SCANCODE_UP:
key = key_up;
break;
+
case SDL_SCANCODE_J:
case SDL_SCANCODE_LEFT:
key = key_left;
break;
+
case SDL_SCANCODE_K:
case SDL_SCANCODE_DOWN:
key = key_down;
break;
+
case SDL_SCANCODE_L:
case SDL_SCANCODE_RIGHT:
key = key_right;
break;
+
case SDL_SCANCODE_A:
key = key_select;
break;
+
case SDL_SCANCODE_S:
key = key_start;
break;
+
case SDL_SCANCODE_Z:
key = key_opt;
break;
+
case SDL_SCANCODE_X:
key = key_edit;
break;
+
default:
key = 0;
break;
}
+
break;
+
default:
break;
}
- if (event.type == SDL_KEYDOWN) {+ if (event.type == SDL_KEYDOWN)
input |= key;
- } else {+ else
input &= ~key;
- }
return input;
}
\ No newline at end of file
--- a/main.c
+++ b/main.c
@@ -3,7 +3,6 @@
#include <errno.h>
#include <signal.h>
#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
#include <unistd.h>
@@ -76,6 +75,7 @@
size_t bytes_read = read(port, &serial_buf, sizeof(serial_buf));
if (bytes_read == -1) {fprintf(stderr, "Error %d reading serial: %s\n", errno, strerror(errno));
+ run = 0;
}
if (bytes_read > 0) { for (int i = 0; i < bytes_read; i++) {--- a/render.c
+++ b/render.c
@@ -3,18 +3,7 @@
#include "command.h"
#include <SDL2/SDL.h>
-#include <SDL2/SDL_blendmode.h>
-#include <SDL2/SDL_joystick.h>
-#include <SDL2/SDL_mouse.h>
-#include <SDL2/SDL_pixels.h>
-#include <SDL2/SDL_rect.h>
-#include <SDL2/SDL_render.h>
-#include <SDL2/SDL_surface.h>
-#include <SDL2/SDL_timer.h>
#include <SDL2/SDL_ttf.h>
-#include <SDL2/SDL_video.h>
-#include <bits/stdint-intn.h>
-#include <stdio.h>
SDL_Window *win;
SDL_Renderer *rend;
@@ -23,9 +12,10 @@
SDL_Texture *background;
SDL_Surface *surface;
static uint32_t ticks;
+#ifdef SHOW_FPS
static uint32_t ticks_fps;
-int updates;
-int fps;
+static int fps;
+#endif
const int font_size = 8;
uint8_t fullscreen = 0;
@@ -57,8 +47,8 @@
font = TTF_OpenFont("stealth57.ttf", font_size);- surface = SDL_CreateRGBSurfaceWithFormat(0, 320, 240, 8,
- SDL_PIXELFORMAT_ARGB8888);
+ surface =
+ SDL_CreateRGBSurfaceWithFormat(0, 320, 240, 8, SDL_PIXELFORMAT_ARGB8888);
if (surface == NULL) { SDL_Log("SDL_CreateRGBSurfaceWithFormat() failed: %s", SDL_GetError());exit(1);
@@ -70,6 +60,7 @@
}
void close_renderer() {+
SDL_FreeSurface(surface);
SDL_DestroyTexture(glyph_texture);
SDL_DestroyTexture(background);
@@ -78,8 +69,10 @@
SDL_DestroyWindow(win);
}
-void toggle_fullscreen(){+void toggle_fullscreen() {+
int fullscreen_state = SDL_GetWindowFlags(win) & SDL_WINDOW_FULLSCREEN;
+
SDL_SetWindowFullscreen(win, fullscreen_state ? 0 : SDL_WINDOW_FULLSCREEN);
SDL_ShowCursor(fullscreen_state);
}
@@ -97,12 +90,11 @@
// Trash80: yeah I think I did something silly that if both are the same color
// it means transparent background or something
if (fgcolor.r == bgcolor.r && fgcolor.g == bgcolor.g &&
- fgcolor.b == bgcolor.b) {+ fgcolor.b == bgcolor.b)
char_surface = TTF_RenderUTF8_Solid(font, (char *)&command->c, fgcolor);
- } else {+ else
char_surface =
TTF_RenderUTF8_Shaded(font, (char *)&command->c, fgcolor, bgcolor);
- }
if (!char_surface) {fprintf(stderr, "TTF_RenderUTF8_Solid error %s\n", TTF_GetError());
@@ -113,7 +105,7 @@
TTF_SizeUTF8(font, (char *)&command->c, &texW, &texH);
SDL_Rect dstrect = {command->pos.x, command->pos.y + 3, texW, texH};- SDL_BlitSurface(char_surface,NULL,surface,&dstrect);
+ SDL_BlitSurface(char_surface, NULL, surface, &dstrect);
SDL_FreeSurface(char_surface);
@@ -121,48 +113,69 @@
}
void draw_rectangle(struct draw_rectangle_command *command) {+
SDL_Rect render_rect;
+
render_rect.x = command->pos.x;
render_rect.y = command->pos.y;
render_rect.h = command->size.height;
render_rect.w = command->size.width;
- uint32_t color = SDL_MapRGBA(surface->format, command->color.r, command->color.g, command->color.b, 255);
+ uint32_t color = SDL_MapRGBA(surface->format, command->color.r,
+ command->color.g, command->color.b, 255);
SDL_FillRect(surface, &render_rect, color);
}
-// Direct pixel writing function by unwind, https://stackoverflow.com/a/20070273 !
-void set_pixel(SDL_Surface *surface, int x, int y, Uint32 pixel)
-{- Uint32 * const target_pixel = (Uint32 *) ((Uint8 *) surface->pixels
- + y * surface->pitch
- + x * surface->format->BytesPerPixel);
+// Direct pixel writing function by unwind, https://stackoverflow.com/a/20070273
+void set_pixel(SDL_Surface *surface, int x, int y, Uint32 pixel) {+
+ Uint32 *const target_pixel =
+ (Uint32 *)((Uint8 *)surface->pixels + y * surface->pitch +
+ x * surface->format->BytesPerPixel);
*target_pixel = pixel;
}
-
void draw_waveform(struct draw_oscilloscope_waveform_command *command) {- memset(surface->pixels,0,surface->w*20*surface->format->BytesPerPixel); // clear the oscilloscope area
- uint32_t color = SDL_MapRGBA(surface->format, command->color.r, command->color.g, command->color.b, 255); // set oscilloscope color
+
+ // clear the oscilloscope area
+ memset(surface->pixels, 0, surface->w * 21 * surface->format->BytesPerPixel);
+
+ // set oscilloscope color
+ uint32_t color = SDL_MapRGBA(surface->format, command->color.r,
+ command->color.g, command->color.b, 255);
+
for (int i = 0; i < command->waveform_size; i++) {- set_pixel(surface, i, command->waveform[i], color); //draw the pixels directly to the surface
+ // limit value because the oscilloscope commands seem to glitch occasionally
+ if (command->waveform[i] > 20)
+ command->waveform[i] = 20;
+ // draw the pixels directly to the surface
+ set_pixel(surface, i, command->waveform[i], color);
}
}
void render_screen() {+
+ // process every 16ms (roughly 60fps)
if (SDL_GetTicks() - ticks > 16) {+
ticks = SDL_GetTicks();
+
SDL_RenderClear(rend);
+
background = SDL_CreateTextureFromSurface(rend, surface);
SDL_RenderCopy(rend, background, NULL, NULL);
SDL_RenderPresent(rend);
SDL_DestroyTexture(background);
+
+#ifdef SHOW_FPS
fps++;
+
if (SDL_GetTicks() - ticks_fps > 5000) {ticks_fps = SDL_GetTicks();
fprintf(stderr, "%d fps\n", fps / 5);
fps = 0;
}
+#endif
}
}
\ No newline at end of file
--- a/serial.c
+++ b/serial.c
@@ -5,6 +5,13 @@
#include <termios.h>
#include <unistd.h>
+#include "serial.h"
+
+/* This code is originally by wallyk,
+https://stackoverflow.com/questions/6947413/how-to-open-read-and-write-from-serial-port-in-c
+with small tweaks to the blocking settings. Big thanks to the
+original author. */
+
static int set_interface_attribs(int fd, int speed, int parity) {struct termios tty;
if (tcgetattr(fd, &tty) != 0) {@@ -50,6 +57,7 @@
return;
}
+ // non-blocking VMIN and VTIME should both be 0
tty.c_cc[VMIN] = should_block ? 1 : 0;
tty.c_cc[VTIME] = should_block ? 5 : 0;
--- a/slip.c
+++ b/slip.c
@@ -4,6 +4,10 @@
#include <assert.h>
#include <stddef.h>
+/* 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. */
+
static void reset_rx(slip_handler_s *slip) {assert(slip != NULL);
@@ -40,7 +44,8 @@
return error;
}
-slip_error_t slip_read_byte(slip_handler_s *slip, uint8_t byte, struct command_queues *command_queues) {+slip_error_t slip_read_byte(slip_handler_s *slip, uint8_t byte,
+ struct command_queues *command_queues) {slip_error_t error = SLIP_NO_ERROR;
assert(slip != NULL);
@@ -49,7 +54,8 @@
case SLIP_STATE_NORMAL:
switch (byte) {case SLIP_SPECIAL_BYTE_END:
- slip->descriptor->recv_message(slip->descriptor->buf, slip->size, command_queues);
+ slip->descriptor->recv_message(slip->descriptor->buf, slip->size,
+ command_queues);
reset_rx(slip);
break;
case SLIP_SPECIAL_BYTE_ESC:
--
⑨