diff --git a/app.h b/app.h index 80f537176b4..d3340b04dea 100644 --- a/app.h +++ b/app.h @@ -306,6 +306,7 @@ void fieldset_add_bin(ProtoViewFieldSet *fs, const char *name, uint64_t uval, ui void fieldset_add_str(ProtoViewFieldSet *fs, const char *name, const char *s); void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count); void fieldset_add_float(ProtoViewFieldSet *fs, const char *name, float val, uint32_t digits_after_dot); +const char *field_get_type_name(ProtoViewField *f); /* crc.c */ uint8_t crc8(const uint8_t *data, size_t len, uint8_t init, uint8_t poly); diff --git a/fields.c b/fields.c index f7e9403b8fc..ac18c50edf5 100644 --- a/fields.c +++ b/fields.c @@ -25,6 +25,20 @@ static void field_free(ProtoViewField *f) { free(f); } +/* Return the type of the field as string. */ +const char *field_get_type_name(ProtoViewField *f) { + switch(f->type) { + case FieldTypeStr: return "str"; + case FieldTypeSignedInt: return "int"; + case FieldTypeUnsignedInt: return "uint"; + case FieldTypeBinary: return "bin"; + case FieldTypeHex: return "hex"; + case FieldTypeBytes: return "bytes"; + case FieldTypeFloat: return "float"; + } + return "unknown"; +} + /* Free a field set and its contained fields. */ void fieldset_free(ProtoViewFieldSet *fs) { for (uint32_t j = 0; j < fs->numfields; j++) @@ -93,9 +107,10 @@ void fieldset_add_str(ProtoViewFieldSet *fs, const char *name, const char *s) { /* Allocate and append a bytes field. Note that 'count' is specified in * nibbles (bytes*2). */ void fieldset_add_bytes(ProtoViewFieldSet *fs, const char *name, const uint8_t *bytes, uint32_t count_nibbles) { + uint32_t numbytes = (count_nibbles+count_nibbles%2)/2; ProtoViewField *f = field_new(FieldTypeBytes,name); - f->bytes = malloc(count_nibbles/2); - memcpy(f->bytes,bytes,count_nibbles/2); + f->bytes = malloc(numbytes); + memcpy(f->bytes,bytes,numbytes); f->len = count_nibbles; fieldset_add_field(fs,f); } diff --git a/protocols/b4b1.c b/protocols/b4b1.c index db758dcca49..6c7238dbe3f 100644 --- a/protocols/b4b1.c +++ b/protocols/b4b1.c @@ -46,8 +46,10 @@ 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 get_fields(ProtoViewFieldSet *fieldset) { + uint8_t default_id[3]= {0xAB, 0xCD, 0xE0}; + fieldset_add_bytes(fieldset,"id",default_id,5); + fieldset_add_int(fieldset,"button",1,4); } static void build_message(RawSamplesBuffer *samples, ProtoViewFieldSet *fields) diff --git a/view_build.c b/view_build.c index 5657c16a78f..d79400ad490 100644 --- a/view_build.c +++ b/view_build.c @@ -56,7 +56,7 @@ 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_draw_str_aligned(canvas,64,40,AlignCenter,AlignCenter, + canvas_draw_str_aligned(canvas,64,36,AlignCenter,AlignCenter, Decoders[privdata->cur_decoder]->name); } @@ -66,13 +66,28 @@ 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, + privdata->decoder->name, (int)privdata->cur_field+1, (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"); - canvas_draw_str(canvas, 0, 62, "Long press ok: create signal"); + canvas_draw_str(canvas, 0, 62, "Long ok: create, < > incr/decr"); + + /* Write the field name, type, current content. For this part we + * write white text on black screen, to visually separate the UI + * description part from the UI current field editing part. */ + canvas_set_color(canvas,ColorBlack); + canvas_draw_box(canvas,0,21,128,32); + + canvas_set_color(canvas,ColorWhite); + ProtoViewField *field = privdata->fieldset->fields[privdata->cur_field]; + snprintf(buf,sizeof(buf), "%s %s:%d", field->name, + field_get_type_name(field), (int)field->len); + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas,64,30,AlignCenter,AlignCenter,buf); + canvas_set_font(canvas, FontSecondary); + canvas_draw_str_aligned(canvas,63,45,AlignCenter,AlignCenter,"\"foobar\""); } /* Render the build message view. */ @@ -93,6 +108,12 @@ static void process_input_select_decoder(ProtoViewApp *app, InputEvent input) { privdata->decoder = Decoders[privdata->cur_decoder]; privdata->fieldset = fieldset_new(); privdata->decoder->get_fields(privdata->fieldset); + // Now we use the subview system in order to protect the + // message editing mode from accidental < or > presses. + // Since we are technically into a subview now, we'll have + // control of < and >. + InputEvent ii = {.type = InputTypePress, .key = InputKeyDown}; + ui_process_subview_updown(app,ii,2); } else if (input.key == InputKeyDown) { select_next_decoder(app); } else if (input.key == InputKeyUp) { @@ -103,8 +124,19 @@ static void process_input_select_decoder(ProtoViewApp *app, InputEvent input) { /* Handle input for fields editing mode. */ static void process_input_set_fields(ProtoViewApp *app, InputEvent input) { - UNUSED(app); - UNUSED(input); + BuildViewPrivData *privdata = app->view_privdata; + ProtoViewFieldSet *fs = privdata->fieldset; + if (input.type == InputTypeShort) { + if (input.key == InputKeyOk) { + } else if (input.key == InputKeyDown) { + privdata->cur_field = (privdata->cur_field+1) % fs->numfields; + } else if (input.key == InputKeyUp) { + if (privdata->cur_field == 0) + privdata->cur_field = fs->numfields-1; + else + privdata->cur_field--; + } + } } /* Handle input for the build message view. */