5. DONE Event Polling

CLOSED: [2020-04-05 Sun 22:05] This describes the interface for polling events from the monome (buttons + knobs).

5.1. Opening File Handles

Every peripheral is opened as a file handle. Each knob has a dedicated filehandle. All buttons come from one filehandle.

5.1.1. Opening a Knob

Each knob has their own filehandle for event, so it must be specified which one you want: 1, 2, or 3.

<<norns_funcdefs>>=
int norns_open_knob(int knob);
<<norns_functions>>=
int norns_open_knob(int knob)
{
    char path[256];
    sprintf(path,
            "/dev/input/by-path/platform-soc:knob%d-event",
            knob);
    return open(path, O_RDONLY | O_NONBLOCK);
}

5.1.2. Opening the Keys

The function norns_open_keys returns the output of openfor opening the keys location.

<<norns_funcdefs>>=
int norns_open_keys(void);
<<norns_functions>>=
int norns_open_keys(void)
{
    return open("/dev/input/by-path/platform-keys-event",
        O_RDONLY | O_NONBLOCK);
}

5.1.3. Callbacks

Every knob + button has a callback function with custom user data. These can be overridden by monolith pages.

5.1.3.1. Knobs Callbacks

5.1.3.2. Buttons Callbacks

5.2. Event Polling Data

5.2.1. typedef + struct

<<norns_typedefs>>=
typedef struct norns_poll_d norns_poll_d;
<<norns_structs>>=
typedef struct {
    void *ud;
    void (*fun)(void *, int);
} norns_peripheral;

struct norns_poll_d {
    int knob_fid[3];
    int keys_fid;
    norns_peripheral knob[3];
    norns_peripheral key[3];
    struct input_event evt[8];
};

5.2.2. Allocating/freeing the event poller

Useful when using this as opaque struct.

<<norns_funcdefs>>=
void norns_poll_new(norns_poll_d **poll);
void norns_poll_del(norns_poll_d **poll);
<<norns_functions>>=
void norns_poll_new(norns_poll_d **ppoll)
{
    norns_poll_d *poll;
    poll = calloc(1, sizeof(norns_poll_d));
    *ppoll = poll;
}

void norns_poll_del(norns_poll_d **ppoll)
{
    free(*ppoll);
}

5.2.3. Event Poller Initilization

Opens all the filehandles, zeros out peripheral callbacks.

<<norns_funcdefs>>=
void norns_poll_init(norns_poll_d *poll);
<<norns_functions>>=
void norns_poll_init(norns_poll_d *poll)
{
    int i;
    poll->keys_fid = norns_open_keys();

    for (i = 0; i < 3; i++) {
        poll->knob_fid[i] = norns_open_knob(i+1);

        /* while we're doing things in 3...*/
        poll->knob[i].ud = NULL;
        poll->knob[i].fun = NULL;

        poll->key[i].ud = NULL;
        poll->key[i].fun = NULL;
    }
}

5.2.4. Event Poller Cleanup

Closes the filehandles.

<<norns_funcdefs>>=
void norns_poll_clean(norns_poll_d *poll);
<<norns_functions>>=
void norns_poll_clean(norns_poll_d *poll)
{
    int i;
    close(poll->keys_fid);
    for (i = 0; i < 3; i++) {
        close(poll->knob_fid[i]);
    }
}

5.3. Polling Function

This function polls all the buttons and knobs from monolith. It is mostly meant to be called inside the main monolith event handler thread.

<<norns_funcdefs>>=
void norns_poll(norns_poll_d *poll);
<<norns_functions>>=
void norns_poll(norns_poll_d *poll)
{
    int k, e;
    int nevts;
    int rc;
    struct input_event *evt;

    /* read knobs */

    evt = poll->evt;

    for (k = 0; k < 3; k++) {
        rc = read(poll->knob_fid[k],
                  evt,
                  sizeof(struct input_event) * 8);

        if (rc != -1) {
            nevts = rc / sizeof(struct input_event);
            for (e = 0; e < nevts; e++) {
                if (evt[e].type) {
                    if (poll->knob[k].fun != NULL) {
                        poll->knob[k].fun(poll->knob[k].ud,
                                          evt[e].value);
                    }
                }
            }
        }
    }

    rc = read(poll->keys_fid,
              evt,
              sizeof(struct input_event) * 8);

    /* read keys */

    if (rc != -1) {
        nevts = rc / sizeof(struct input_event);
        for (e = 0; e < nevts; e++) {
            if (evt[e].type) {
                int val;
                int code;
                val = evt[e].value;
                code = evt[e].code - 1;

                if (poll->key[code].fun != NULL) {
                    poll->key[code].fun(poll->key[code].ud,
                                        val);
                }
            }
        }
    }
}

5.4. Setting Event Callbacks

5.4.1. Set Knob

<<norns_funcdefs>>=
void norns_poll_cb_knob(norns_poll_d *poll,
                        int knob,
                        void (*fun)(void *, int),
                        void *ud);
<<norns_functions>>=
void norns_poll_cb_knob(norns_poll_d *poll,
                        int knob,
                        void (*fun)(void *, int),
                        void *ud)
{
    if (knob < 0 || knob >= 3) return;

    poll->knob[knob].fun = fun;
    poll->knob[knob].ud = ud;
}

5.4.2. Set Key

<<norns_funcdefs>>=
void norns_poll_cb_key(norns_poll_d *poll,
                       int key,
                       void (*fun)(void *, int),
                       void *ud);
<<norns_functions>>=
void norns_poll_cb_key(norns_poll_d *poll,
                       int key,
                       void (*fun)(void *, int),
                       void *ud)
{
    if (key < 0 || key >= 3) return;

    poll->key[key].fun = fun;
    poll->key[key].ud = ud;
}



prev | home | next