3. The VM

All state data is maintained inside of a struct called trig_vm.

3.1. VM Data

<<typedefs>>=
typedef struct trig_vm trig_vm;
<<structs>>=
<<trig_state>>
struct trig_vm {
<<trig_vm>>
};

A trig_vm is initialized with trig_vm_init.

<<funcdefs>>=
void trig_vm_init(trig_vm *vm);
<<funcs>>=
void trig_vm_init(trig_vm *vm)
{
<<trig_vm_init>>
}

No destroy function needed, as there is no memory allocation.

3.2. VM struct size

<<funcdefs>>=
size_t trig_vm_size(void);
<<funcs>>=
size_t trig_vm_size(void)
{
    return sizeof(trig_vm);
}

3.3. The Cell Pool

Cells are managed in a pool of exactly 32. This fits into a 8x4 rectangle.

<<trig_vm>>=
trig_cell cell[32];
<<trig_vm_init>>=
{
    int i;
    for (i = 0; i < 32; i++) {
        vm->cell[i].cmd = 0;
        vm->cell[i].data = 0;
    }
}

3.4. Internal State

Internal state variables that can be swapped out. Used to have multiple readers happening at once.

<<trig_vm>>=
trig_state *state;
trig_state istate;
<<trig_vm_init>>=
vm->state = &vm->istate;
<<trig_vm_init>>=
trig_state_init(&vm->istate);

3.5. Goto

Sets the cell position of the internal struct.

<<funcdefs>>=
void trig_vm_goto(trig_vm *vm, int pos);
<<funcs>>=
void trig_vm_goto(trig_vm *vm, int pos)
{
    vm->istate.pos = pos;
}

3.5.1. Counter

A global counter is used by certain kinds of cells for performing patterns.

<<funcdefs>>=
void trig_vm_counter_reset(trig_vm *vm);

Just the main counter. Other states will have to be reset another way (inside a graforge node... re-compilation).

<<funcs>>=
void trig_vm_counter_reset(trig_vm *vm)
{
    vm->istate.counter = -1;
}

3.6. Wires

"Wires" are floating point variables that can be used for input or output. The VM doesn't really make a distinction.

The number of wires can be set with the TRIG_NWIRES macro, which for now is set to be 8 by default.

<<trig_vm>>=
#ifndef TRIG_NWIRES
#define TRIG_NWIRES 8
#endif
float wires[TRIG_NWIRES];
<<trig_vm_init>>=
{
    int i;
    for (i = 0; i < TRIG_NWIRES; i++) {
        vm->wires[i] = 0;
    }
}

A value of a wire can be retrieved using the function trig_vm_wire_get.

<<funcdefs>>=
float trig_vm_wire_get(trig_vm *vm, int wire);
<<funcs>>=
float trig_vm_wire_get(trig_vm *vm, int wire)
{
    return vm->wires[wire];
}

A value of a wire can be set using the function trig_vm_wire_set.

<<funcdefs>>=
void trig_vm_wire_set(trig_vm *vm, int wire, float val);
<<funcs>>=
void trig_vm_wire_set(trig_vm *vm, int wire, float val)
{
    vm->wires[wire] = val;
    if (vm->set != NULL) {
        vm->set(vm, vm->ud, wire, val);
    }
}

The pointer reference of the wire can be retrieved with trig_vm_wire_ref

<<funcdefs>>=
float* trig_vm_wire_ref(trig_vm *vm, int wire);
<<funcs>>=
float* trig_vm_wire_ref(trig_vm *vm, int wire)
{
    return &vm->wires[wire];
}

3.7. Wire Callback

In order to integrate wires with Graforge, a callback interface is provided. This gets called anytime a cable value is set.

<<typedefs>>=
typedef void (*trig_setter) (trig_vm *, void *, int, float);
<<trig_vm>>=
trig_setter set;
void *ud;
<<trig_vm_init>>=
vm->set = NULL;
vm->ud = NULL;

It can be set with the callback with trig_vm_setter.

<<funcdefs>>=
void trig_vm_setter(trig_vm *vm, trig_setter fun, void *ud);
<<funcs>>=
void trig_vm_setter(trig_vm *vm, trig_setter fun, void *ud)
{
    vm->set = fun;
    vm->ud = ud;
}

3.8. Run Flag

This flag is set at the beginning of a step, and will cause the program to step through the system until a cell flips it off.

<<trig_vm>>=
int running;
<<trig_vm_init>>=
vm->running = 0;

3.9. Get Cell

<<funcdefs>>=
trig_cell * trig_vm_cell_get(trig_vm *vm, int cell);
<<funcs>>=
trig_cell * trig_vm_cell_get(trig_vm *vm, int cell)
{
    return &vm->cell[cell];
}



prev | home | next