4. Line16 Core Functions

4.1. Draw Point Bank

Given a point and position, will draw the slot on the grid.

In progress. Right now, we just mark if things are active or not.

<<line16_function_declarations>>=
static void line16_draw_point(line16_point *pt,
                              int pos,
                              monolith_page_mstate *m);
<<line16_functions>>=
static void line16_draw_point(line16_point *pt,
                              int pos,
                              monolith_page_mstate *ms)
{
   if(pt->active) {
       monolith_page_mstate_led_set(ms, pos, 1, 1);
   } else {
       monolith_page_mstate_led_set(ms, pos, 1, 0);
   }
   line16_draw_point_type(pt, pos, ms);
}

4.2. Draw Point Type

<<line16_function_declarations>>=
static void line16_draw_point_type(line16_point *pt,
                                   int pos,
                                   monolith_page_mstate *m);

Because the type flag has a special bit reserved for trigger mode, the type needs to be bitmasked in order to work.

<<line16_functions>>=
static void line16_draw_point_type(line16_point *pt,
                                   int pos,
                                   monolith_page_mstate *m)
{
    int y;
    int type;
    type = pt->type & 3;
    for(y = 0; y < 4; y++) {
        if(type == y) {
            monolith_page_mstate_led_set(m, pos, y + 2, 1);
        } else {
            monolith_page_mstate_led_set(m, pos, y + 2, 0);
        }
    }
}

4.3. Draw Point Togmode

<<line16_function_declarations>>=
static void line16_draw_point_togmode(line16_point *pt,
                                      monolith_page_mstate *m);
<<line16_functions>>=
static void line16_draw_point_togmode(line16_point *pt,
                                      monolith_page_mstate *m)
{
    int t;
    t = pt->type & 1<<2;
    monolith_page_mstate_led_set(m, 0, 7, t);
}

4.4. Draw Selected Line

Draws the select line on the control panel, located in the bottom right corner.

<<line16_function_declarations>>=
static void line16_draw_selected_line(int selected,
                                      monolith_page_mstate *m);
<<line16_functions>>=
static void line16_draw_selected_line(int selected,
                                      monolith_page_mstate *m)
{
    int t;
    int s;
    for (t = 0; t < 4; t++) {
        s = (selected & (1 << t)) != 0;
        monolith_page_mstate_led_set(m,
                                     12 + t, 7,
                                     s);
    }
}

4.5. Redraw all points

Will redraw all points on the grid. At the very least, this will be called at creation.

<<line16_function_declarations>>=
static void line16_redraw_points(page_line16_d *l);
<<line16_functions>>=
static void line16_redraw_points(page_line16_d *l)
{
    int pt;
    line16_point *points;

    points = l->lines[l->selected_line].points;

    for(pt = 0; pt < 16; pt++) {
        line16_draw_point(&points[pt],
                          pt,
                          l->mstate);
    }
}

4.6. Display Point Values

Given a point, this will display the point values on the arc.

<<line16_function_declarations>>=
static void line16_display_vals(line16_point *pt,
                                monolith_page_arcstate *as);
<<line16_functions>>=
static void line16_display_vals(line16_point *pt,
                                monolith_page_arcstate *as)
{
    monolith_arcstate_mapval(as, 0, pt->val);
    monolith_arcstate_mapval(as, 1, pt->dur);
    monolith_arcstate_mapval(as, 2, pt->aux[0]);
    monolith_arcstate_mapval(as, 3, pt->aux[1]);
}

4.7. Select a point

This will select a point, and update the UI.

<<line16_function_declarations>>=
static void line16_select_point(page_line16_d *l, int pt);
<<line16_functions>>=
static void line16_select_point(page_line16_d *l, int pt)
{
    line16_line *line;
    if(pt < 0 || pt >= 16) return;
    line = &l->lines[l->selected_line];
    l->selected_point = pt;
    line16_display_vals(&line->points[pt], l->arcstate);
    line16_draw_point_togmode(&line->points[pt], l->mstate);
    monolith_page_mstate_led_row16(l->mstate, 0, 1<<pt);
}

Point can be retrieved using line16_select_point_get.

<<line16_function_declarations>>=
static int line16_select_point_get(page_line16_d *l);
<<line16_functions>>=
static int line16_select_point_get(page_line16_d *l)
{
    return l->selected_point;
}

4.8. Compute a Line

This computes a line segment, which is then written to the internal block.

4.8.1. Main Callback

<<line16_function_declarations>>=
static void line16_compute_line(page_line16_d *l,
                                gf_patch *p,
                                gf_cable *in);

A line is a connection between to points. At the time of writing, this connection is limited to linear interpolation. Exponential mapping could be in the future, but to get things started, linear.

A line has three main components. A point A, a point B, and a duration between the two. A counter keeps tracker of the current line position, which is then used to derive position.

When the position has reached the length of the duration, a new line segment begins! The points, duration, and counter are updated.

<<line16_functions>>=
static void update_counters(page_line16_d *l)
{
    l->timer += l->onedsr * l->rate;
    /* to prevent overflow, circle between values */
    if(l->timer > 10) {
        l->timer = 1; /* low but still slow */
    }

    /* do it again for aux timer */
    l->aux_timer += l->onedsr * l->rate;

    if(l->aux_timer > 10) {
        l->aux_timer = 1;
    }
}

static void line16_compute_line(page_line16_d *l,
                                gf_patch *p,
                                gf_cable *in)
{
    int blksize;
    int s;
    gf_cable *out;
    GFFLT dur;
    GFFLT o;
    line16_point *pt_a;
    line16_point *pt_b;

    blksize = gf_patch_blksize(p);
    line16_state_apply(l);
    out = &l->out;

    if (l->pointpos < 0) {
        line16_start_line(l);
        line16_aux_cache_udpate(l);
        line16_update_pointpos(l);
        if(l->pointpos < 0) {
            for(s = 0; s < blksize; s++) {
                gf_cable_set(out, s, 0);
                update_counters(l);
            }
            return;
        }
    }

    pt_a = line16_get_point(l, l->pointpos);
    pt_b = line16_get_point(l, l->nextpoint);

    if (pt_a == NULL && pt_b == NULL) return;

    for (s = 0; s < blksize; s++) {
        if (gf_cable_get(in, s) != 0) {
            l->trig = 1;
        }
        if (l->pointpos < 0) {
            o = 0;
        } else {
            if (l->pointpos < 0) {
                o = 0;
            } else {
                pt_a = line16_get_point(l, l->pointpos);
                pt_b = line16_get_point(l, l->nextpoint);

                dur = line16_durscale(l, pt_a->dur);

                if (l->counter >= dur) {
                    line16_begin_segment(l);
                    pt_a = line16_get_point(l, l->pointpos);
                    pt_b = line16_get_point(l, l->nextpoint);
                    line16_aux_cache_udpate(l);
                    line16_update_pointpos(l);
                }

                if (l->pointpos >= 0) {
                    /* calculate the line */
                    if ((pt_a->type & 4) && l->trig == 0) {
                        o = pt_a->val;
                    } else {
                        switch (pt_a->type & 3) {
                            case SLOPE_LINEAR:
                                o = line_linear(l,
                                                pt_a, pt_b,
                                                l->counter);
                                break;
                            case SLOPE_EXP_POSITIVE:
                                o = line_exp_pos(l,
                                                 pt_a, pt_b,
                                                 l->counter,
                                                 l->aux_cache[0]);
                                break;
                            case SLOPE_EXP_NEGATIVE:
                                o = line_exp_neg(l,
                                                 pt_a, pt_b,
                                                 l->counter,
                                                 l->aux_cache[0]);
                                break;
                            case SLOPE_BEZIER:
                                o = line_bezier(l,
                                                pt_a, pt_b,
                                                l->counter,
                                                l->aux_cache[0],
                                                l->aux_cache[1]);
                                break;
                            default:
                                o = line_linear(l,
                                                pt_a, pt_b,
                                                l->counter);
                                break;
                        }

                        l->counter += l->onedsr *
                            l->rate *
                            pt_a->rate;
                    }
                } else {
                    o = 0;
                }
            }
        }
        gf_cable_set(out, s, o);
        update_counters(l);
    }
}

4.8.2. Line Slope Functions

4.8.2.1. Linear

<<line16_function_declarations>>=
static GFFLT line_linear(page_line16_d *l,
                         line16_point *pt_a,
                         line16_point *pt_b,
                         GFFLT counter);
<<line16_functions>>=
static GFFLT line_linear(page_line16_d *l,
                         line16_point *pt_a,
                         line16_point *pt_b,
                         GFFLT counter)
{
    GFFLT a, b;
    GFFLT o;
    GFFLT dur;

    a = pt_a->val;
    b = pt_b->val;
    dur = line16_durscale(l, pt_a->dur);

    o = a + (b - a) * (counter / dur);

    return o;
}
4.8.2.2. Exponential Positive

<<line16_function_declarations>>=
static GFFLT line_exp_pos(page_line16_d *l,
                          line16_point *pt_a,
                          line16_point *pt_b,
                          GFFLT counter,
                          GFFLT aux);
<<line16_functions>>=
static GFFLT line_exp_pos(page_line16_d *l,
                          line16_point *pt_a,
                          line16_point *pt_b,
                          GFFLT counter,
                          GFFLT aux)
{
    GFFLT a, b;
    GFFLT o;
    GFFLT slp;
    GFFLT dur;

    a = pt_a->val;
    b = pt_b->val;
    dur = line16_durscale(l, pt_a->dur);

    slp = 1 + (15 * aux);

    o = a + (b - a) *
        (1 - exp(counter * slp / dur)) /
        (1 - exp(slp));

    return o;
}
4.8.2.3. Exponential Negative

<<line16_function_declarations>>=
static GFFLT line_exp_neg(page_line16_d *l,
                          line16_point *pt_a,
                          line16_point *pt_b,
                          GFFLT counter,
                          GFFLT aux);
<<line16_functions>>=
static GFFLT line_exp_neg(page_line16_d *l,
                          line16_point *pt_a,
                          line16_point *pt_b,
                          GFFLT counter,
                          GFFLT aux)
{
    GFFLT a, b;
    GFFLT o;
    GFFLT slp;
    GFFLT dur;

    a = pt_a->val;
    b = pt_b->val;
    dur = line16_durscale(l, pt_a->dur);

    slp = -1 - (15 * aux);

    o = a + (b - a) *
        (1 - exp(counter * slp / dur)) /
        (1 - exp(slp));

    return o;
}
4.8.2.4. Bezier

The reference equation:

B(t) = (1 - t)^2P0 + 2(1 - t)P1 + t^2P2

<<line16_function_declarations>>=
static GFFLT line_bezier(page_line16_d *l,
                         line16_point *pt_a,
                         line16_point *pt_b,
                         GFFLT counter,
                         GFFLT aux1,
                         GFFLT aux2);
<<line16_functions>>=
static GFFLT line_bezier(page_line16_d *l,
                         line16_point *pt_a,
                         line16_point *pt_b,
                         GFFLT counter,
                         GFFLT aux1,
                         GFFLT aux2)
{
    GFFLT a, b;
    GFFLT o;
    GFFLT x[3];
    GFFLT y[3];
    GFFLT dur;
    GFFLT val;
    GFFLT t;

    a = pt_a->val;
    b = pt_b->val;
    dur = line16_durscale(l, pt_a->dur);

    /* some light clamping... in case of weirdness */
    val = aux1;
    if(val < 0.001) val = 0.001;
    if(val > 0.999) val = 0.99;

    x[0] = 0;
    y[0] = a;

    x[1] = (dur * val);
    y[1]= aux2;

    x[2] = dur;
    y[2] = b;

    t = find_t(x[0], x[1], x[2], counter);

    o = (1.0 - t) * (1.0 - t) * y[0] +
        2.0 * (1.0 - t) * t * y[1] +
        t * t * y[2];

    return o;
}
<<line16_function_declarations>>=
static GFFLT find_t(GFFLT x0, GFFLT x1, GFFLT x2, GFFLT x);
<<line16_functions>>=
static GFFLT find_t(GFFLT x0, GFFLT x1, GFFLT x2, GFFLT x)
{
    GFFLT a;
    GFFLT b;
    GFFLT c;
    GFFLT out;
    GFFLT det;

    a = (x0 - 2.0 * x1 + x2);
    b = 2.0 * (-x0 + x1);
    c = x0 - x;

    out = 0;
    if(a) {
        det = b * b - 4 * a * c;
        if(det > 0)
            out = ((-b + sqrt(det))/(2.0 * a));
        else
            out = 0;
    } else {
        if(b != 0) out = (x - x0)/b;
    }
    return out;
}

4.9. DONE Compute a Local Line

CLOSED: [2020-01-03 Fri 14:16] This function is used to compute a single line instance. It will compute once per block.

<<line16_function_declarations>>=
void line16_compute_localline(line16_localline *localline,
                              gf_patch *patch,
                              gf_cable *in,
                              gf_cable *out);
<<line16_functions>>=
void line16_compute_localline(line16_localline *ll,
                              gf_patch *patch,
                              gf_cable *in,
                              gf_cable *out)
{
    int blksize;
    int s;
    /* gf_cable *out; */
    GFFLT dur;
    GFFLT o;
    line16_point *pt_a;
    line16_point *pt_b;
    line16_line *line;
    page_line16_d *pg;

    blksize = gf_patch_blksize(patch);
    /* line16_state_apply(l); */
    /* out = &l->out; */

    line = ll->l;
    pg = ll->pg;

    if (ll->pointpos < 0) {
        line16_start_line_local(ll);
        /* line16_update_pointpos(l); */
        pt_a = line16_line_point(line, ll->pointpos);
        if (pt_a != NULL) {
            ll->aux[0] = pt_a->aux[0];
            ll->aux[1] = pt_a->aux[1];
        }
        if(ll->pointpos < 0) {
            for(s = 0; s < blksize; s++) {
                gf_cable_set(out, s, 0);
                /* update_counters(l); */
            }
            return;
        }
    }

    pt_a = line16_line_point(line, ll->pointpos);
    pt_b = line16_line_point(line, ll->nextpoint);

    if (pt_a == NULL && pt_b == NULL) return;

    for (s = 0; s < blksize; s++) {
        if (gf_cable_get(in, s) != 0) ll->trig = 1;
        if (ll->pointpos < 0) {
            o = 0;
        } else {
            if (ll->pointpos < 0) {
                o = 0;
            } else {
                pt_a = line16_line_point(line, ll->pointpos);
                pt_b = line16_line_point(line, ll->nextpoint);

                dur = line16_durscale(pg, pt_a->dur);

                if (ll->counter >= dur) {
                    line16_begin_local(ll);
                    pt_a = line16_line_point(line, ll->pointpos);
                    pt_b = line16_line_point(line, ll->nextpoint);
                    /* line16_aux_cache_udpate(l); */
                    /* line16_update_pointpos(l); */
                    ll->aux[0] = pt_a->aux[0];
                    ll->aux[1] = pt_a->aux[1];
                }

                if (ll->pointpos >= 0) {
                    /* calculate the line */
                    if ((pt_a->type & 4) && ll->trig == 0) {
                        o = pt_a->val;
                    } else {
                        switch (pt_a->type & 3) {
                            case SLOPE_LINEAR:
                                o = line_linear(pg,
                                                pt_a, pt_b,
                                                ll->counter);
                                break;
                            case SLOPE_EXP_POSITIVE:
                                o = line_exp_pos(pg,
                                                 pt_a, pt_b,
                                                 ll->counter,
                                                 ll->aux[0]);
                                break;
                            case SLOPE_EXP_NEGATIVE:
                                o = line_exp_neg(pg,
                                                 pt_a, pt_b,
                                                 ll->counter,
                                                 ll->aux[0]);
                                break;
                            case SLOPE_BEZIER:
                                o = line_bezier(pg,
                                                pt_a, pt_b,
                                                ll->counter,
                                                ll->aux[0],
                                                ll->aux[1]);
                                break;
                            default:
                                o = line_linear(pg,
                                                pt_a, pt_b,
                                                ll->counter);
                                break;
                        }

                        ll->counter += pg->onedsr *
                            pg->rate *
                            pt_a->rate;
                    }
                } else {
                    o = 0;
                }
            }
        }
        gf_cable_set(out, s, o);
        /* update_counters(l); */
    }
}

This line is self contained and ancillary to the main line sequence. For this reason it is known as "local".

The biggest difference between the local line and the main line is that the local line can only loop between itself.

The local line callback expects an input and output cable. The input cable contains a trigger signal for points that wait. The output cable is where the line will write the signal to.

As the name would suggest, the local line utilizes local variables. Local variables are stored in a struct and are passed to the line callback.

Some Local variables I see here include:

- counter - pointpos - nextpoint - trig - local aux cache

<<line16_typedefs>>=
typedef struct line16_localline line16_localline;
<<line16_struct>>=
struct line16_localline {
    page_line16_d *pg;
    line16_line *l;
    GFFLT counter;
    int pointpos;
    int nextpoint;
    int trig;
    GFFLT aux[2];
};

This struct is initialized with line16_localline_init.

<<line16_function_declarations>>=
void line16_localline_init(line16_localline *l,
                           line16_line *line,
                           page_line16_d *pg);
<<line16_functions>>=
void line16_localline_init(line16_localline *l,
                           line16_line *line,
                           page_line16_d *pg)
{
    l->counter = 0;
    l->pointpos = -1;
    l->nextpoint = -1;
    l->trig = 0;
    l->l = line;
    l->pg = pg;
    l->aux[0] = 0;
    l->aux[1] = 0;
}

4.10. Find Next Point (Main and Local)

This will return the next available point. This will start at the current point, and iterate through the points in ascending order until a point has been found. This can include wrapping back to the beginning, if need be.

If there are no active points to be found, this function will return a negative value. If there is only one active point, it means that the current point will be returned.

4.10.1. Main

<<line16_function_declarations>>=
static int line16_find_next(page_line16_d *l, int after);

In the for loop, n starts on 1 in order to skip the current point position.

<<line16_functions>>=
static int line16_find_next(page_line16_d *l, int after)
{
    line16_line *line;
    line = &l->lines[l->playing_line];
    return line16_line_find_next(line, after);
}

4.10.2. Local

<<line16_function_declarations>>=
static int line16_line_find_next(line16_line *l, int after);

In the for loop, n starts on 1 in order to skip the current point position.

<<line16_functions>>=
static int line16_line_find_next(line16_line *l, int after)
{
    int pp;
    int n;
    int pos;
    line16_point *pt;

    pp = after;

    if(l->nactive == 0) {
        return -1;
    } else if(l->nactive == 1 && pp >= 0) {
        return pp;
    }

    for(n = 0; n < 16; n++) {
        pos = (pp + n + 1) % 16;
        pt = &l->points[pos];
        if(pt->active) return pos;
    }

    return -1;
}

4.11. Increment Value

Increments a value up or down and returns it. This includes clamping value to be in range 0-1.

<<line16_function_declarations>>=
static GFFLT line16_increment(GFFLT val, int delta);
<<line16_functions>>=
static GFFLT line16_increment(GFFLT val, int delta)
{
    val += 0.001 * delta;
    if(val < 0) val = 0;
    else if(val > 1) val = 1;

    return val;
}

4.12. Get Point (Main and Local)

Given an index value, retrieve the point. If point is out of range, return NULL.

4.12.1. Main Point Getter

For use in the main callback.

<<line16_function_declarations>>=
line16_point * line16_get_point(page_line16_d *l, int pt);
<<line16_functions>>=
line16_point * line16_get_point(page_line16_d *l, int pt)
{
    line16_line *line;

    line = &l->lines[l->playing_line];

    return line16_line_point(line, pt);
}

4.12.2. Get Local Point

Get a point from a particular line.

<<line16_function_declarations>>=
line16_point * line16_line_point(line16_line *l, int pt);
<<line16_functions>>=
line16_point * line16_line_point(line16_line *l, int pt)
{
    if(pt < 0 || pt >= 16) return NULL;

    return &l->points[pt];
}

4.13. Point Setters/Getters

Where l is the page data, line is the line number (in case we implement multiple lines), pos is the point position on the line, and val is the value to be set.

4.13.1. line16_point_val_set

<<line16_function_declarations>>=
static void line16_point_val_set(page_line16_d *l,
                                 int linepos,
                                 int pos,
                                 GFFLT val);
<<line16_functions>>=
static void line16_point_val_set(page_line16_d *l,
                                 int linepos,
                                 int pos,
                                 GFFLT val)
{
    line16_line *line;
    int lite;

    if (val < 0) val = 0;
    if (val > 1) val = 1;

    if (pos < 0) pos = 0;
    if (pos > 15) pos = 15;

    if (linepos < 0) linepos = 0;
    if (linepos > 15) linepos = 15;

    line = &l->lines[linepos];
    line->points[pos].val = val;

    lite =
        linepos == l->selected_line &&
        pos == l->selected_point;

    if (lite) {
        monolith_arcstate_mapval(l->arcstate, 0, val);
    }
}

4.13.2. line16_point_val_get

<<line16_function_declarations>>=
static GFFLT line16_point_val_get(page_line16_d *l,
                                  int linepos,
                                  int pos);
<<line16_functions>>=
static GFFLT line16_point_val_get(page_line16_d *l,
                                  int linepos,
                                  int pos)
{
    line16_line *line;

    if(pos < 0) pos = 0;
    if(pos > 15) pos = 15;

    if (linepos < 0) linepos = 0;
    if (linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    return line->points[pos].val;
}

4.13.3. line16_point_dur_set

<<line16_function_declarations>>=
static void line16_point_dur_set(page_line16_d *l,
                                 int linepos,
                                 int pos,
                                 GFFLT dur);
<<line16_functions>>=
static void line16_point_dur_set(page_line16_d *l,
                                 int linepos,
                                 int pos,
                                 GFFLT dur)
{
    line16_line *line;
    int lite;

    if(dur < 0) dur = 0;
    if(dur > 1) dur = 1;

    if(pos < 0) pos = 0;
    if(pos > 15) pos = 15;

    if(linepos < 0) linepos = 0;
    if(linepos > 15) linepos = 15;

    line = &l->lines[linepos];
    line->points[pos].dur = dur;

    lite =
        linepos == l->selected_line &&
        pos == l->selected_point;

    if(lite) {
        monolith_arcstate_mapval(l->arcstate, 1, dur);
    }
}

4.13.4. line16_point_dur_get

<<line16_function_declarations>>=
static GFFLT line16_point_dur_get(page_line16_d *l,
                                  int line,
                                  int pos);
<<line16_functions>>=
static GFFLT line16_point_dur_get(page_line16_d *l,
                                  int linepos,
                                  int pos)
{
    line16_line *line;

    if(pos < 0) pos = 0;
    if(pos > 15) pos = 15;

    if(linepos < 0) linepos = 0;
    if(linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    return line->points[pos].dur;
}

4.13.5. line16_point_aux_set

<<line16_function_declarations>>=
static void line16_point_aux_set(page_line16_d *l,
                                 int linepos,
                                 int pos,
                                 int aux,
                                 GFFLT val);

Because this can set the monome, this function is rate limited. This is especially important for cases when the aux value is being set by a graforge node.

<<line16_functions>>=
static void line16_point_aux_set(page_line16_d *l,
                                 int linepos,
                                 int pos,
                                 int aux,
                                 GFFLT val)
{
    line16_line *line;
    int lite;

    if(val < 0) val = 0;
    if(val > 1) val = 1;

    if(pos < 0) pos = 0;
    if(pos > 15) pos = 15;

    if(aux < 0) aux = 0;
    if(aux > 1) aux = 1;

    if(linepos < 0) linepos = 0;
    if(linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    line->points[pos].aux[aux] = val;

    lite =
        linepos == l->selected_line &&
        pos == l->selected_point;

    if (lite) {
        if(l->aux_timer < AUX_MIN_DUR) return;
        monolith_arcstate_mapval(l->arcstate,
                                 2 + aux,
                                 val);
        l->aux_timer = 0;
    }
}

4.13.6. line16_point_aux_get

<<line16_function_declarations>>=
static GFFLT line16_point_aux_get(page_line16_d *l,
                                  int linepos,
                                  int pos,
                                  int aux);
<<line16_functions>>=
static GFFLT line16_point_aux_get(page_line16_d *l,
                                  int linepos,
                                  int pos,
                                  int aux)
{
    line16_line *line;
    if (pos < 0) pos = 0;
    if (pos > 15) pos = 15;

    if (linepos < 0) linepos = 0;
    if (linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    return line->points[pos].aux[aux];
}

4.13.7. line16_point_status_set

<<line16_function_declarations>>=
static void line16_point_status_set(page_line16_d *l,
                                    int line,
                                    int pos,
                                    int status);
<<line16_functions>>=
static void line16_point_status_set(page_line16_d *l,
                                    int line,
                                    int pos,
                                    int status)
{
    if (pos < 0) pos = 0;
    if (pos > 15) pos = 15;

    if (line == l->selected_line) {
        monolith_page_mstate_led_set(l->mstate,
                                    pos, 1, (status != 0));
        /* TODO state_set should know which line, no? */
        line16_state_set(l, pos, status);
    }
}

4.13.8. line16_point_status_get

<<line16_function_declarations>>=
static int line16_point_status_get(page_line16_d *l,
                                   int linepos,
                                   int pos);
<<line16_functions>>=
static int line16_point_status_get(page_line16_d *l,
                                   int linepos,
                                   int pos)
{
    line16_line *line;

    if (pos < 0) pos = 0;
    if (pos > 15) pos = 15;

    if (linepos < 0) linepos = 0;
    if (linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    return line->points[pos].active;
}

4.13.9. line16_point_type_set

<<line16_function_declarations>>=
static void line16_point_type_set(page_line16_d *l,
                                  int linepos,
                                  int pos,
                                  int type);

Because the type flag stores extra data in the upper bits (like the trigger flag), setting must be done to only change the lower two bits.

<<line16_functions>>=
static void line16_point_type_set(page_line16_d *l,
                                  int linepos,
                                  int pos,
                                  int type)
{
    int tmp;
    line16_line *line;

    if(pos < 0) pos = 0;
    if(pos > 15) pos = 15;

    if (linepos < 0) linepos = 0;
    if (linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    tmp = line->points[pos].type;
    tmp &= ~3; /* clear last two bits */
    tmp |= type & 3; /* mask + set */
    line->points[pos].type = tmp;
}

4.13.10. line16_point_type_get

<<line16_function_declarations>>=
static int line16_point_type_get(page_line16_d *l,
                                   int linepos,
                                   int pos);

The value is AND'd, because other data is stored in the upper bits.

<<line16_functions>>=
static int line16_point_type_get(page_line16_d *l,
                                 int linepos,
                                 int pos)
{
    line16_line *line;

    if (linepos < 0) linepos = 0;
    if (linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    if(pos < 0) pos = 0;
    if(pos > 15) pos = 15;

    return line->points[pos].type & 3;
}

4.13.11. line16_point_rate_set

<<line16_function_declarations>>=
static void line16_point_rate_set(page_line16_d *l,
                                  int linepos,
                                  int pos,
                                  GFFLT rate);
<<line16_functions>>=
static void line16_point_rate_set(page_line16_d *l,
                                  int linepos,
                                  int pos,
                                  GFFLT rate)
{
    line16_line *line;

    if(pos < 0) pos = 0;
    if(pos > 15) pos = 15;

    if (linepos < 0) linepos = 0;
    if (linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    line->points[pos].rate = rate;
}

4.13.12. line16_point_rate_get

<<line16_function_declarations>>=
static GFFLT line16_point_rate_get(page_line16_d *l,
                                   int linepos,
                                   int pos);
<<line16_functions>>=
static GFFLT line16_point_rate_get(page_line16_d *l,
                                   int linepos,
                                   int pos)
{
    line16_line *line;

    if(pos < 0) pos = 0;
    if(pos > 15) pos = 15;

    if (linepos < 0) linepos = 0;
    if (linepos > 15) linepos = 15;

    line = &l->lines[linepos];

    return line->points[pos].rate;
}

4.13.13. line16_point_trigmode_set

<<line16_function_declarations>>=
/* static void line16_point_trigmode_set(page_line16_d *l, */
/*                                       int line, */
/*                                       int pos, */
/*                                       int tog); */

Trigmode is embedded inside of the type variable, so some bit twiddling is needed.

<<line16_functions>>=
/* static void line16_point_trigger_set(page_line16_d *l, */
/*                                      int line, */
/*                                      int pos, */
/*                                      int tog) */
/* { */
/*     int tmp; */
/*     if(pos < 0) pos = 0; */
/*     if(pos > 15) pos = 15; */

/*     tmp = l->points[pos].type; */
/*     tmp &= ~(1<<2); /\* clear bit 3 *\/ */
/*     tmp |= tog & ~(1<<2); /\* mask + set *\/ */
/*     l->points[pos].type = tmp; */
/* } */

4.13.14. line16_point_trigmode_get

<<line16_function_declarations>>=
/* static int line16_point_trigmode_get(page_line16_d *l, */
/*                                      int line, */
/*                                      int pos); */
<<line16_functions>>=
/* static int line16_point_trigmode_get(page_line16_d *l, */
/*                                      int line, */
/*                                      int pos) */
/* { */

/*     if(pos < 0) pos = 0; */
/*     if(pos > 15) pos = 15; */

/*     return l->points[pos].type & (1 << 2); */
/* } */

4.14. Begin New Segment (Main and Local)

4.14.1. Main

Starts a new segment.

<<line16_function_declarations>>=
static void line16_begin_segment(page_line16_d *l);

When a new segment starts:

Find the next point.

Counter reset to be zero.

<<line16_functions>>=
static void line16_begin_segment(page_line16_d *l)
{
    int nextpoint;

    l->counter = 0;
    l->trig = 0;

    nextpoint = line16_find_next(l, l->nextpoint);

    if(nextpoint < 0) return;

    l->pointpos = l->nextpoint;
    l->nextpoint = nextpoint;
}

4.14.2. DONE Local

CLOSED: [2020-01-03 Fri 12:27]

<<line16_function_declarations>>=
static void line16_begin_local(line16_localline *ll);
<<line16_functions>>=
static void line16_begin_local(line16_localline *ll)
{
    int nextpoint;

    ll->counter = 0;
    ll->trig = 0;

    nextpoint = line16_line_find_next(ll->l, ll->nextpoint);

    if(nextpoint < 0) return;

    ll->pointpos = ll->nextpoint;
    ll->nextpoint = nextpoint;
}

4.15. Scale to duration

<<line16_function_declarations>>=
static GFFLT line16_durscale(page_line16_d *l, GFFLT val);
<<line16_functions>>=
static GFFLT line16_durscale(page_line16_d *l, GFFLT val)
{
    GFFLT mn, mx;
    mn = line16_dur_min_get(l);
    mx = line16_dur_max_get(l);
    return val * (mx - mn) + mn;
}

4.16. Start a line (Main + Local)

Called when line is first initialized. This will start the line. It will find first two line segments.

4.16.1. Main

<<line16_function_declarations>>=
static void line16_start_line(page_line16_d *line);

A value of -1 is passed into find_next because this function looks for the next value AFTER the input value. Passing -1 allows the function to start looking AT 0.

<<line16_functions>>=
static void line16_start_line(page_line16_d *line)
{
    line->counter = 0;
    line->pointpos = line16_find_next(line, -1);
    line->nextpoint = line16_find_next(line,
                                       line->pointpos);
}

4.16.2. Local

<<line16_function_declarations>>=
static void line16_start_line_local(line16_localline *line);

A value of -1 is passed into find_next because this function looks for the next value AFTER the input value. Passing -1 allows the function to start looking AT 0.

<<line16_functions>>=
static void line16_start_line_local(line16_localline *line)
{
    line->counter = 0;
    line->pointpos = line16_line_find_next(line->l, -1);
    line->nextpoint = line16_line_find_next(line->l,
                                            line->pointpos);
}

4.17. Update Point Position

This will update the point position on the monome.

<<line16_function_declarations>>=
static void line16_update_pointpos(page_line16_d *l);
<<line16_functions>>=
static void line16_update_pointpos(page_line16_d *l)
{
    unsigned short val;

    if (l->selected_line != l->playing_line) {
        return;
    }

    if (l->timer >= 0 && l->timer < MIN_DUR) return;

    if (l->pointpos < 0) val = 0;
    else val = 1 << l->pointpos;



    if (l->pointpos != l->lpointpos) {
        monolith_page_mstate_led_row16(l->mstate, 6, val);
        l->timer = 0;
        l->lpointpos = l->pointpos;
    }
}



prev | home | next