accumulate-line

gabbapeople/uart-led-control/accumulate-line

Creates a string from a stream of characters by appending each new character to the end of the string until the end od the line escape sequence if found.
accumulate-line
@/accumulate-line
Creates a string from a stream of characters by appending each new character to the end of the string until the end od the line escape sequence if found.
CHARbyte
A new character to be pushed to the end of the string line
PUSHpulse
Push new character
RSTpulse
Empty the accumulated string line and start over
accumulate-line
LINE
DONE
CHAR
PUSH
RST
DONEpulse
Fires on a new accumulated line
LINEstring
Accumulated line
To use the node in your project you should have the gabbapeople/uart-led-control library installed. Use the “File → Add Library” menu item in XOD IDE if you don’t have it yet. See Using libraries for more info.

C++ implementation

/*
 * A list constructor based on double buffering technique. The front buffer
 * is immutable and read-only while an algorithm constructs a new list
 * behind the scenes using the back buffer.
 *
 * Once the back buffer is ready, the algorithm swaps the buffers and starts
 * over: now the buffer that used to be on back plays the role of front buffer
 * and vice versa.
 *
 * Use this class to accumulate some sparse stream of items into a list when
 * presenting an intermediate result to consumers is unacceptable, the
 * consumers will sDoubleBufferee the latest “published” result instead.
 *
 * `CAP` defines the maximal length of the list (in items). An instance of
 * double buffer consumes 2xCAP memory to hold two buffers at a time.
 */

template<size_t CAP>
class DoubleBuffer {
  public:
    DoubleBuffer()
            : _active_buff0(false)
    { }

    void eraseBackBuffer(){
        memset(backBuffer(), '\0', CAP);
    }

    void swap(){
        _active_buff0 = !_active_buff0;
    }

    char* backBuffer() {
        return _active_buff0 ? _buff1 : _buff0;
    }

    const char* frontBuffer() const {
        return _active_buff0 ? _buff0 : _buff1;
    }

  private:
    char _buff0[CAP];
    char _buff1[CAP];
    bool _active_buff0;
};


struct State {
    char* cursor;
    CStringView view;
    DoubleBuffer<16> mbuf;
};

{{ GENERATED_CODE }}

void evaluate(Context ctx) {
    auto state = getState(ctx);

    if (isSettingUp()) {
        state->view = CStringView(state->mbuf.frontBuffer());
    }
    if (isInputDirty<input_RST>(ctx)){
        state->mbuf.eraseBackBuffer();
        state->cursor = state->mbuf.backBuffer();
    }

    if (isInputDirty<input_PUSH>(ctx)) {
        if (getValue<input_CHAR>(ctx) == '\n'){
             state->mbuf.swap();
            emitValue<output_LINE>(ctx, XString(&state->view));
            emitValue<output_DONE>(ctx,1);
        }
        if (getValue<input_CHAR>(ctx) != '\r'){
            *state->cursor = getValue<input_CHAR>(ctx);
            state->cursor++;
        }
    }
}