shithub: m8c

Download patch

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/b
     memcpy(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:
--