8. Pattern Cell

A pattern cell is a kind of cell that plays a rhythmic pattern. It can have a maximum size of 32. When the VM arrives on a pattern cell, it will begin playing the cell pattern. It will remain on this cell until it reaches the end of the pattern, then it will go to the next cell.

A pattern cell can write to any of the 8 wires. It will use the rightmost bit on the second byte to determine which wire to write to. If no bits are turned on, it is assumed to be wire 1.

The counter is used to extract the corresponding bit state in a way you'd typically expect. When the counter reaches the end of pattern, it returns the next position in the series, with loopback if appropriate.

A pattern cell uses the global counter variable to maintain state. If the counter is at -1, it assumed that the VM just arrived at the pattern, and uses this to initialize the counter to be 0.

A bit of bitwise magic is used to determine the rightmost bit of the third byte (x & -x) was retrieved from the book "hackers delight" in the section called "the basics".

Wire number from the byte gets converted to a wire position wp using a sort of log2 while-loop function.

The fourth command byte is used for additional functionality. The byte is divided up into 2 nibbles. The lower nibble determines the command, the upper nibble defines the data. This is done because it will show up command, data on the monome.

If the command nibble is 0, nothing happens.

Nibble command 1 enables switch mode. It will split the pattern into 2 16-bit sections. It will reading from the wire specified in the nibble data. A zero value will' select the lower half pattern. A non-zero value selects the upper half pattern. The wire data is specified as a binary value.

<<exfuncs>>=
static int pattern(trig_vm *vm,
                   int pos,
                   uint32_t cmd,
                   uint32_t data)
{
    int nib;
    int dur;
    uint32_t pat;
    trig_state *ts;

    ts = vm->state;
    dur = (cmd >> 16) & 0xFF;
    dur *= (dur <= 32);
    nib = (cmd >> 24) & 0xFF;
    pat = data;

    if (nib & 0xf) {
        int ncmd;
        int ndat;

        ncmd = nib & 0xf;
        ndat = (nib >> 4) & 0xf;

        if (ncmd == 1) {
            int wire;

            wire = ndat;
            if (wire > 0 && wire <= 8) wire--;
            else wire = 0;

            if (vm->wires[wire] == 0) {
                pat = data & 0xFFFF;
            } else {
                pat = (data >> 16) & 0xFFFF;
            }
        }
    }

    vm->running = 0;

    if (ts->counter == -1) {
        ts->counter = 0;
    } else {
        ts->counter++;
    }

    if (ts->counter == dur || dur == 0) {
        ts->counter = -1;
        vm->running = 1;
        return (pos + 1) % 32;
    } else {
        int wire;
        int s;
        int wp;

        wire = (cmd >> 8) & 0xFF;

        if (wire == 0) {
            wire = 1;
        } else {
            /* only use rightmost bit */
            wire = wire & -wire;
        }

        wp = 0;

        while (wire >>= 1) wp++;


        s = (pat & (1 << ts->counter)) != 0;

        trig_vm_wire_set(vm, wp, s);

        return pos;
    }

    return pos;
}



prev | home | next