Letter or number adder

Keyboard/Input node

A node for creating words, strings, etc. using letters and numbers.
Here is a video made for better explanation : https://kapwi.ng/c/tg5zCqPI
(Please watch it till the end)

Inputs

  • IN (string, default=A) — Letter or number input.
  • CLR (pulse, boolean) — Clear the output.
  • BCKS (pulse, boolean) — Backspace, removes one letter, space, number from the output.
  • SPC (pulse, boolean) — Space, creates one blank character (Space)

Outputs

  • OUT (string) — Outputs the combined letter, number.

Is there an easy way to implement this node somehow?

Probably not the most efficient, and for some reason it doesn’t update output when string is empty until new input is started (if you hit clear or BCKS the last character, output does not update [i.e. clear] until you add the 1st char of new string), but it is a start at what you want… It currently takes a byte as input to force a single character. It should probably raise error when SIZE is exceeded, but currently it just ignores input when string has reached max length. Due to XOD not updating without change to input, it is impossible to input double characters (i.e. second X is still an X, so no update is made until IN changes to a new character). The only solution I can think of to resolve that is to add an UPD pin.

image

#pragma XOD dirtieness disable

#define SIZE 16

struct State {
    char str[SIZE];
    int size = 0;
    CStringView view;
    State() : view(str) { }
};


{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    auto state = getState(ctx);
    if (isSettingUp() || isInputDirty<input_CLR>(ctx)) {
        for (int i=0; i<SIZE; ++i) {
            state->str[i] = 0;
        }
        state->size = 0;
    } else if (isInputDirty<input_BCKS>(ctx)) {
        if (state->size > 0) {
            state->str[--state->size] = 0;
        }
    } else if (isInputDirty<input_SPC>(ctx)) {
        if (state->size < SIZE) {
            state->str[state->size++] = ' ';
        }
    } else {
        if (state->size < SIZE) {
            state->str[state->size++] = getValue<input_IN>(ctx);
        }
    }
    emitValue<output_OUT>(ctx, XString(&state->view));
}

You can replace the input_IN line above with the following if you want to use string input instead of byte & ignore all but the 1st character in the string (and NULL string – which provides a way to enter repeat characters if you switch to empty string between the repeats):

            char in = *(getValue<input_IN>(ctx).iterate());
            if (in) { state->str[state->size++] = in; }

I’ve been reading through XOD code trying to figure out strings. Still haven’t found code for view(), but I’m guessing it checks if string isValid() before updating, and the empty string starts with end-of-string (i.e. NULL), which is interpreted as !isValid(), so output doesn’t get updated. If I add code to CLR & BCKS to make str[0] = <space_char>, the watch function clears correctly, but downstream code will see space instead of empty string, which is likely to cause issues…

1 Like

accumlate-string node is a much better starting point for coding this solution than my code above. You could just write a wrapper for accumlate-string to do everything except the BCKS pin; adding BCKS will require adding to accumulate-string code rather than just adding a wrapper node.

1 Like

Thanks as always gweimer! I will test your amazing findings tomorrow! Thanks for taking a look at this!
Also how could I add the space function to accumulate-string node. I can somehow live without the backspace function.
EDIT : I can add a space using the 20h byte, but I can’t seem to grasp the content of using a mini keyboard to drive the accumulate-string node. I can’t connect multiple links to the accumulate-string.
Here is a gif :
test

You can never tie more than one wire to an input pin. XOD would have no way of choosing which input to use. The correct solution will depend on what you are trying to do. To directly map what you are trying to do, you could cascade the if-else nodes; the results of the first if-else become the false input of the next all the way down the stack, then the output of the last if-else become your input for accumulate-string. Gweimer/utils/if-else-v is a variadic version of if-else to do the same thing in one node. Unless you have a separate button for each character, I’m not sure how this really helps, though…

1 Like

Hello again! I am getting the idea of this (I will somehow live without the backspace function) and I created a simple sketch, but I really need the pulse-on-change (byte) version. So when the output changes on if-else-v, the character gets pushed to the string. But XOD fails, and says that pulse-on-change (byte) doesn’t exist. Any help?

pulse-on-change (byte) will be available in the next version … will be out soon

1 Like

That looks like an over-site in XOD. I think you can copy the existing pulse-on-change(number) to pulse-on-change(byte), then change the input-number to input-byte and in the code section, change Number sample = NAN; to unsigned char sample = NAN;

1 Like

Thanks for the solution, will try it out. Just to get the idea, I am trying to make a little keypad out of buttons, that corespond to various number/letters. When I press the buttons, a string is created, and then (for example) “ABC” is equal to “ABC”, it turns on the fan and when “BCA” is equal to “BCA” it turns on the LED.

Latest version of XOD (released today) adds pulse-on-change(byte)

1 Like

Here is some progress. This is closer to what I want. I can add a space using “20h” code. Though I don’t know how to implement the backspace function. But I ran into some issues with the sketch. The string output doesn’t change for some reason. Any ideas?


(The output should’ve been “ABC” and not just “A”)

Something is wrong there, because it only changes if everyone stays in True, pulse-on-false(byte) seems to be too fast and arrives before the change, place a defer

ps: I thought that would work, but no … even a tweak-pulse doesn’t work. It seems to be accumulate-string that does not respond.

1 Like

well it seems that pulse-on-change(byte) sends the pulses but blocks accumulate-string :man_facepalming:

1 Like

Hi everyone!

In addition to what was explained in https://github.com/xodio/xod/issues/1973, I’d like to propose this:

ezgif-3-e49d361b65a1

I think that select will fit a bit better than if-else-v here, and also note that you can bind single characters to byte inputs by surrounding them in single quotes (like this: 'a'), no need to convert to ASCII code.

2 Likes

Oh my god thanks! Will try it out and report!
EDIT : This seems to work great, but the reset function doesn’t work. Am I doing something wrong again here :grimacing:

The little handling I have led me to certain errors and doubts, in the end it was better with select as I thought but I didn’t know why it failed.

The only thing I can think of to clean is with a space or another character.

image

1 Like

This is an issue we’ve been running into. Once a string has been changed from “” after boot, there is no way to change it back to “”. There is a discussion about it here: XOD String bug?