Przeglądaj źródła

Build message view introduced.

antirez 3 lat temu
rodzic
commit
23a8793616
5 zmienionych plików z 109 dodań i 5 usunięć
  1. 5 0
      app.c
  2. 11 1
      app.h
  3. 12 2
      protocols/b4b1.c
  4. 12 2
      protocols/keeloq.c
  5. 69 0
      view_build.c

+ 5 - 0
app.c

@@ -57,6 +57,7 @@ static void render_callback(Canvas *const canvas, void *ctx) {
     case ViewModulationSettings:
         render_view_settings(canvas,app); break;
     case ViewDirectSampling: render_view_direct_sampling(canvas,app); break;
+    case ViewBuildMessage: render_view_build_message(canvas,app); break;
     default: furi_crash(TAG "Invalid view selected"); break;
     }
 
@@ -97,6 +98,7 @@ static void app_switch_view(ProtoViewApp *app, ProtoViewCurrentView switchto) {
     /* Call the enter/exit view callbacks if needed. */
     if (old == ViewDirectSampling) view_exit_direct_sampling(app);
     if (new == ViewDirectSampling) view_enter_direct_sampling(app);
+    if (old == ViewBuildMessage) view_exit_build_message(app);
     /* The frequency/modulation settings are actually a single view:
      * as long as the user stays between the two modes of this view we
      * don't need to call the exit-view callback. */
@@ -331,6 +333,9 @@ int32_t protoview_app_entry(void* p) {
                 case ViewDirectSampling:
                     process_input_direct_sampling(app,input);
                     break;
+                case ViewBuildMessage:
+                    process_input_build_message(app,input);
+                    break;
                 default: furi_crash(TAG "Invalid view selected"); break;
                 }
             }

+ 11 - 1
app.h

@@ -53,6 +53,7 @@ typedef enum {
     ViewInfo,
     ViewFrequencySettings,
     ViewModulationSettings,
+    ViewBuildMessage,
     ViewDirectSampling,
     ViewLast, /* Just a sentinel to wrap around. */
 
@@ -225,7 +226,13 @@ typedef struct ProtoViewDecoder {
      * functions that perform bit extraction with bound checking, such as
      * bitmap_get() and so forth. */
     bool (*decode)(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoViewMsgInfo *info);
-    void (*get_fields)(ProtoViewMsgInfo *info, ProtoViewFieldSet *fields);
+    /* This method is used by the decoder to return the fields it needs
+     * in order to build a new message. This way the message builder view
+     * can ask the user to fill the right set of fields of the specified
+     * type. */
+    void (*get_fields)(ProtoViewFieldSet *fields);
+    /* This method takes the fields supported by the decoder, and
+     * renders a message in 'samples'. */
     void (*build_message)(RawSamplesBuffer *samples, ProtoViewFieldSet *fields);
 } ProtoViewDecoder;
 
@@ -269,6 +276,9 @@ void render_view_info(Canvas *const canvas, ProtoViewApp *app);
 void process_input_info(ProtoViewApp *app, InputEvent input);
 void render_view_direct_sampling(Canvas *const canvas, ProtoViewApp *app);
 void process_input_direct_sampling(ProtoViewApp *app, InputEvent input);
+void render_view_build_message(Canvas *const canvas, ProtoViewApp *app);
+void process_input_build_message(ProtoViewApp *app, InputEvent input);
+void view_exit_build_message(ProtoViewApp *app);
 void view_enter_direct_sampling(ProtoViewApp *app);
 void view_exit_direct_sampling(ProtoViewApp *app);
 void view_exit_settings(ProtoViewApp *app);

+ 12 - 2
protocols/b4b1.c

@@ -46,9 +46,19 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
     return true;
 }
 
+static void get_fields(ProtoViewFieldSet *fields) {
+    UNUSED(fields);
+}
+
+static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fields)
+{
+    UNUSED(samples);
+    UNUSED(fields);
+}
+
 ProtoViewDecoder B4B1Decoder = {
     .name = "PT/SC remote",
     .decode = decode,
-    .get_fields = NULL,
-    .build_message = NULL 
+    .get_fields = get_fields,
+    .build_message = build_message 
 };

+ 12 - 2
protocols/keeloq.c

@@ -75,9 +75,19 @@ static bool decode(uint8_t *bits, uint32_t numbytes, uint32_t numbits, ProtoView
     return true;
 }
 
+static void get_fields(ProtoViewFieldSet *fields) {
+    UNUSED(fields);
+}
+
+static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fields)
+{
+    UNUSED(samples);
+    UNUSED(fields);
+}
+
 ProtoViewDecoder KeeloqDecoder = {
     .name = "Keeloq",
     .decode = decode,
-    .get_fields = NULL,
-    .build_message = NULL
+    .get_fields = get_fields,
+    .build_message = build_message 
 };

+ 69 - 0
view_build.c

@@ -0,0 +1,69 @@
+/* Copyright (C) 2022-2023 Salvatore Sanfilippo -- All Rights Reserved
+ * See the LICENSE file for information about the license. */
+
+#include "app.h"
+
+extern ProtoViewDecoder *Decoders[];    // Defined in signal.c.
+
+/* Our view private data. */
+typedef struct {
+    ProtoViewDecoder *decoder;      // Decoder we are using to create a message.
+    uint32_t cur_decoder;           // Decoder index when we are yet selecting
+                                    // a decoder. Used when decoder is NULL.
+    ProtoViewFieldSet *fieldset;    // The fields to populate.
+    uint32_t cur_field;             // Field we are editing right now. This
+                                    // is the index inside the 'fieldset'
+                                    // fields.
+} BuildViewPrivData;
+
+/* Render the view to select the decoder, among the ones that
+ * support message building. */
+static void render_view_select_decoder(Canvas *const canvas, ProtoViewApp *app) {
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str(canvas, 0, 9, "Signal builder");
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str(canvas, 0, 19, "up/down: select, ok: choose");
+
+    UNUSED(app); // XXX
+}
+
+/* Render the view that allows the user to populate the fields needed
+ * for the selected decoder to build a message. */
+static void render_view_set_fields(Canvas *const canvas, ProtoViewApp *app) {
+    BuildViewPrivData *privdata = app->view_privdata;
+    char buf[32];
+    snprintf(buf,sizeof(buf), "%s field %d/%d",
+        privdata->decoder->name, (int)privdata->cur_field,
+        (int)privdata->fieldset->numfields);
+    canvas_set_font(canvas, FontPrimary);
+    canvas_draw_str(canvas, 0, 9, buf);
+    canvas_set_font(canvas, FontSecondary);
+    canvas_draw_str(canvas, 0, 19, "up/down: next field, ok: edit");
+}
+
+/* Render the build message view. */
+void render_view_build_message(Canvas *const canvas, ProtoViewApp *app) {
+    BuildViewPrivData *privdata = app->view_privdata;
+
+    if (privdata->decoder == NULL)
+        render_view_select_decoder(canvas,app);
+    else
+        render_view_set_fields(canvas,app);
+}
+
+/* Handle input for the build message view. */
+void process_input_build_message(ProtoViewApp *app, InputEvent input) {
+    UNUSED(app);
+    if (input.type == InputTypeShort) {
+        if (input.key == InputKeyOk) {
+        } else if (input.key == InputKeyDown) {
+        } else if (input.key == InputKeyUp) {
+        }
+    }
+}
+
+/* Called on exit for cleanup. */
+void view_exit_build_message(ProtoViewApp *app) {
+    BuildViewPrivData *privdata = app->view_privdata;
+    if (privdata->fieldset) fieldset_free(privdata->fieldset);
+}