Procházet zdrojové kódy

Process output changes in a thread.

Aaron Mavrinac před 3 roky
rodič
revize
3484f3f8dc
1 změnil soubory, kde provedl 131 přidání a 33 odebrání
  1. 131 33
      coleco.c

+ 131 - 33
coleco.c

@@ -22,9 +22,21 @@ typedef struct
   InputEvent input;
 } PluginEvent;
 
+typedef enum
+{
+  WorkerEvtStop = (1 << 0),
+  WorkerEvtModeChange = (1 << 1),
+  WorkerEvtUpChange = (1 << 2),
+  WorkerEvtDownChange = (1 << 3),
+  WorkerEvtRightChange = (1 << 4),
+  WorkerEvtLeftChange = (1 << 5),
+  WorkerEvtCodeChange = (1 << 6),
+} WorkerEvtFlags;
+
 typedef struct
 {
-  bool mode;
+  FuriThread* thread;
+  volatile bool mode;
 
   bool button_up;
   bool button_down;
@@ -37,37 +49,92 @@ typedef struct
   bool dpad;
 } Coleco;
 
-static void output_update(Coleco* coleco)
+static void mode_isr(void* context)
 {
-  // TODO: check mode, possibly flipped
-  if (coleco->mode)
-  {
-    furi_hal_gpio_write(pin_up, !coleco->button_up);
-    furi_hal_gpio_write(pin_down, !coleco->button_down);
-    furi_hal_gpio_write(pin_right, !coleco->button_right);
-    furi_hal_gpio_write(pin_left, !coleco->button_left);
-  }
-  else
-  {
-    // TODO: check ordering of bits
-    furi_hal_gpio_write(pin_left, (coleco->button_code & 1));
-    furi_hal_gpio_write(pin_down, (coleco->button_code & 2));
-    furi_hal_gpio_write(pin_right, (coleco->button_code & 4));
-    furi_hal_gpio_write(pin_up, (coleco->button_code & 8));
-  }
-  furi_hal_gpio_write(pin_fire, !coleco->button_fire);
+  Coleco* coleco = (Coleco*)context;
+  coleco->mode = furi_hal_gpio_read(&gpio_ext_pc1);
+  furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtModeChange);
 }
 
-static void mode_isr(void* context)
+static int32_t coleco_output_worker(void* context)
 {
-  Coleco* coleco = acquire_mutex((ValueMutex*)context, 25);
-  if (coleco == NULL)
+  Coleco* coleco = (Coleco*)context;
+
+  furi_hal_gpio_add_int_callback(pin_mode, mode_isr, coleco);
+
+  while(1)
   {
-    return;
+    uint32_t events = furi_thread_flags_wait(0x7F, FuriFlagWaitAny, FuriWaitForever);
+    furi_check((events & FuriFlagError) == 0);
+
+    if (events & WorkerEvtStop)
+    {
+      break;
+    }
+
+    if (events & WorkerEvtModeChange)
+    {
+      if (coleco->mode)
+      {
+        furi_hal_gpio_write(pin_up, !coleco->button_up);
+        furi_hal_gpio_write(pin_down, !coleco->button_down);
+        furi_hal_gpio_write(pin_right, !coleco->button_right);
+        furi_hal_gpio_write(pin_left, !coleco->button_left);
+      }
+      else
+      {
+        furi_hal_gpio_write(pin_left, (coleco->button_code & 1));
+        furi_hal_gpio_write(pin_down, (coleco->button_code & 2));
+        furi_hal_gpio_write(pin_right, (coleco->button_code & 4));
+        furi_hal_gpio_write(pin_up, (coleco->button_code & 8));
+      }
+    }
+
+    if (events & WorkerEvtUpChange)
+    {
+      if (coleco->mode)
+      {
+        furi_hal_gpio_write(pin_up, !coleco->button_up);
+      }
+    }
+
+    if (events & WorkerEvtDownChange)
+    {
+      if (coleco->mode)
+      {
+        furi_hal_gpio_write(pin_down, !coleco->button_down);
+      }
+    }
+
+    if (events & WorkerEvtRightChange)
+    {
+      if (coleco->mode)
+      {
+        furi_hal_gpio_write(pin_right, !coleco->button_right);
+      }
+    }
+
+    if (events & WorkerEvtLeftChange)
+    {
+      if (coleco->mode)
+      {
+        furi_hal_gpio_write(pin_left, !coleco->button_left);
+      }
+    }
+
+    if (events & WorkerEvtCodeChange)
+    {
+      if (!coleco->mode)
+      {
+        furi_hal_gpio_write(pin_left, !(coleco->button_code & 1));
+        furi_hal_gpio_write(pin_down, !(coleco->button_code & 2));
+        furi_hal_gpio_write(pin_right, !(coleco->button_code & 4));
+        furi_hal_gpio_write(pin_up, !(coleco->button_code & 8));
+      }
+    }
   }
 
-  coleco->mode = furi_hal_gpio_read(&gpio_ext_pc1);
-  output_update(coleco);
+  return 0;
 }
 
 static void render_callback(Canvas* const canvas, void* context)
@@ -80,10 +147,16 @@ static void render_callback(Canvas* const canvas, void* context)
 
   canvas_set_font(canvas, FontPrimary);
   canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignBottom, "ColecoVision");
+
+  canvas_set_font(canvas, FontSecondary);
+
   if (coleco->dpad)
   {
-    canvas_set_font(canvas, FontSecondary);
-    canvas_draw_str_aligned(canvas, 64, 18, AlignCenter, AlignBottom, "D-pad");
+    canvas_draw_str_aligned(canvas, 64, 18, AlignCenter, AlignBottom, "d-pad");
+  }
+  else
+  {
+    canvas_draw_str_aligned(canvas, 64, 18, AlignCenter, AlignBottom, "numbers");
   }
 
   release_mutex((ValueMutex*)context, coleco);
@@ -119,11 +192,23 @@ static Coleco* coleco_alloc()
   furi_hal_gpio_init(pin_left, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
   furi_hal_gpio_init(pin_fire, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
 
-  output_update(coleco);
+  furi_hal_gpio_write(pin_up, true);
+  furi_hal_gpio_write(pin_down, true);
+  furi_hal_gpio_write(pin_right, true);
+  furi_hal_gpio_write(pin_left, true);
+  furi_hal_gpio_write(pin_fire, true);
 
   // configure mode pin
   furi_hal_gpio_init(pin_mode, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedVeryHigh);
 
+  // set up output worker thread
+  coleco->thread = furi_thread_alloc();
+  furi_thread_set_name(coleco->thread, "ColecoOutputWorker");
+  furi_thread_set_stack_size(coleco->thread, 1024);
+  furi_thread_set_context(coleco->thread, coleco);
+  furi_thread_set_callback(coleco->thread, coleco_output_worker);
+  furi_thread_start(coleco->thread);
+
   return coleco;
 }
 
@@ -131,6 +216,10 @@ static void coleco_free(Coleco* coleco)
 {
   furi_assert(coleco);
 
+  furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtStop);
+  furi_thread_join(coleco->thread);
+  furi_thread_free(coleco->thread);
+
   button_panel_free(coleco->button_panel);
 
   free(coleco);
@@ -161,9 +250,6 @@ int32_t coleco_app(void* p)
   Gui* gui = furi_record_open("gui");
   gui_add_view_port(gui, view_port, GuiLayerFullscreen);
 
-  // enable mode ISR
-  furi_hal_gpio_add_int_callback(pin_mode, mode_isr, &coleco_mutex);
-
   PluginEvent event;
   for (bool processing = true; processing;)
   {
@@ -184,10 +270,12 @@ int32_t coleco_app(void* p)
               if (event.input.type == InputTypePress)
               {
                 coleco->button_up = true;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtUpChange);
               }
               else if (event.input.type == InputTypeRelease)
               {
                 coleco->button_up = false;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtUpChange);
               }
             }
             else  // FIXME: hack to allow the 1 to be pressed
@@ -195,10 +283,12 @@ int32_t coleco_app(void* p)
               if (event.input.type == InputTypePress)
               {
                 coleco->button_code = 0x0D;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtCodeChange);
               }
               else if (event.input.type == InputTypeRelease)
               {
                 coleco->button_code = 0x0F;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtCodeChange);
               }
             }
             break;
@@ -208,10 +298,12 @@ int32_t coleco_app(void* p)
               if (event.input.type == InputTypePress)
               {
                 coleco->button_down = true;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtDownChange);
               }
               else if (event.input.type == InputTypeRelease)
               {
                 coleco->button_down = false;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtDownChange);
               }
             }
             break;
@@ -221,10 +313,12 @@ int32_t coleco_app(void* p)
               if (event.input.type == InputTypePress)
               {
                 coleco->button_right = true;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtRightChange);
               }
               else if (event.input.type == InputTypeRelease)
               {
                 coleco->button_right = false;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtRightChange);
               }
             }
             break;
@@ -234,10 +328,12 @@ int32_t coleco_app(void* p)
               if (event.input.type == InputTypePress)
               {
                 coleco->button_left = true;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtLeftChange);
               }
               else if (event.input.type == InputTypeRelease)
               {
                 coleco->button_left = false;
+                furi_thread_flags_set(furi_thread_get_id(coleco->thread), WorkerEvtLeftChange);
               }
             }
             break;
@@ -247,10 +343,12 @@ int32_t coleco_app(void* p)
               if (event.input.type == InputTypePress)
               {
                 coleco->button_fire = true;
+                furi_hal_gpio_write(pin_fire, !coleco->button_fire);
               }
               else if (event.input.type == InputTypeRelease)
               {
                 coleco->button_fire = false;
+                furi_hal_gpio_write(pin_fire, !coleco->button_fire);
               }
             }
             else
@@ -274,6 +372,8 @@ int32_t coleco_app(void* p)
           default:
             break;
         }
+
+        view_port_update(view_port);
       }
     }
     else
@@ -281,8 +381,6 @@ int32_t coleco_app(void* p)
       FURI_LOG_D("Coleco", "FuriMessageQueue: event timeout");
     }
 
-    output_update(coleco);
-    view_port_update(view_port);
     release_mutex(&coleco_mutex, coleco);
   }