/* bird.c - PD externals, that controls and parses one flock of bird out of a comport Date: 16.01.97 Author: Winfried Ritsch (see LICENCE.txt) Institute for Electronic Music - Graz Desc.: put the object in a correct parse state and send commands first input: where data from bird is thrown in (eg.from comport) first output: a list of data which size is dependen on the parse mode second output: to control the bird eg connect to a comport in */ #ifdef NT #pragma warning( disable : 4244 ) #pragma warning( disable : 4305 ) #endif #include #include /* general I/O */ #include /* for string commands */ #include "m_pd.h" #define B_MAX_DATA 32 /* Maximal awaited data per record */ #define B_MAX_CMDDATA 6 /* Maximum of awaited cmd arguments */ typedef struct { t_object x_obj; t_outlet *x_out2; t_int x_n; t_atom *x_vec; int databytes; /* expected databytes */ int datacount; /* count bytes in record */ int phase_wait; /* wait for phasebit */ int datamode; /* data mode is data or examine*/ /* int flowmode; stream or point mode */ int phase_error; void (*writefun)(void *this,unsigned char c); unsigned char data[B_MAX_DATA]; /* maximal record length */ char *argname; int argc; int argv[B_MAX_DATA]; int verbose; } bird_t; bird_t *bird_init( bird_t *this); int bird_data( bird_t *this, unsigned char data ); void bird_setwritefun(bird_t *this,void (*newwritefun)(void *bird,unsigned char c)); void bird_send(bird_t *this,unsigned char chr); void bird_bang(bird_t *this); void bird_set(bird_t *this,char *cmdname,long *cmddata); typedef struct { char *name; unsigned char cmd; int cmdbytes; /* number of cmd arguments */ int cmdsize; /* size of arguments in bytes (most 2) */ int databytes; /* number of awaited data */ int datamode; /* data mode is ignore, point flow or examine*/ } bird_cmd; /* defines Modes for data receiving */ #define B_MODE_IGNORE 0 #define B_MODE_POINT 1 #define B_MODE_STREAM 2 #define B_MODE_EXAM 3 /*#define B_STREAM_ON 1 #define B_STREAM_OFF 0 */ #define B_WAIT_PHASE 1 #define B_FOUND_PHASE 0 /* definitions */ /* cmds accepted by the flock */ static bird_cmd cmds[]= { /* cmd , value, nr of cmdatabytes, cmddatasize, nr datainbytes data modes, if change always point */ {"ANGLES", 'W', 0, 0, 6, B_MODE_POINT}, {"MATRIX", 'X', 0, 0, 18, B_MODE_POINT}, {"POSITION", 'V', 0, 0, 6, B_MODE_POINT}, {"QUATER", 0x5C, 0, 0, 8, B_MODE_POINT}, {"POSANG", 'Y', 0, 0, 12, B_MODE_POINT}, {"POSMAT", 'Z', 0, 0, 24, B_MODE_POINT}, {"POSQUATER", ']', 0, 0, 14, B_MODE_POINT}, /* output cmd */ {"POINT", 'B', 0, 0, 0, B_MODE_POINT}, {"STREAM", 64, 0, 0, 0, B_MODE_STREAM}, {"RUN", 'F', 0, 0, 0, B_MODE_IGNORE}, {"SLEEP", 'G', 0, 0, 0, B_MODE_IGNORE}, /* set cmds */ {"AngleAlign1", 'J', 6, 2, 0, B_MODE_IGNORE}, {"AngleAlign2", 'q', 3, 2, 0, B_MODE_IGNORE}, {"Hemisphere", 'L', 2, 1, 0, B_MODE_IGNORE}, {"RefFrame1", 'H', 6, 2, 0, B_MODE_IGNORE}, {"RefFrame2", 'r', 3, 2, 0, B_MODE_IGNORE}, {"RepRate1", 'Q', 0, 0, 0, B_MODE_IGNORE}, {"RepRate2", 'R', 0, 0, 0, B_MODE_IGNORE}, {"RepRate8", 'S', 0, 0, 0, B_MODE_IGNORE}, {"RepRate32", 'T', 0, 0, 0, B_MODE_IGNORE}, { NULL, '\0', 0, 0, 0, B_MODE_IGNORE} }; /* -------------------- the serial object methods -------------------- */ bird_t *bird_init( bird_t *this) { if(this == NULL){ this = malloc(sizeof(bird_t)); } if(this == NULL){ post("Could not allocate data for bird_t"); } this->databytes = 0; this->datacount = 0; this->phase_wait = B_WAIT_PHASE; this->datamode = B_MODE_IGNORE; this->phase_error = 0; this->writefun = NULL; this->argname = "STARTUP_MODE"; this->argc = 0; return this; } int bird_data( bird_t *this, unsigned char data ) { int i; if(this->datamode != B_MODE_IGNORE){ /* STREAM or POINT Mode */ /* Phase was detected */ if(this->phase_wait == B_FOUND_PHASE && data < 0x80){ this->data[this->datacount] = data; /* store data */ this->datacount++; /* increment counter */ if(this->databytes <= this->datacount){ /* last byte of record */ this->datacount = 0; this->phase_wait = B_WAIT_PHASE; /* interpret and output */ this->argc = this->databytes / 2; for(i=0;idatabytes;i+=2){ this->argv[i/2] = (this->data[i]<<2)+(this->data[i+1]<<9); /* printf("list[%2d]=%7d (%3d,%3d) ",i, ((this->data[i]<<2)+(this->data[i+1]<<9)), this->data[i],this->data[i+1]); */ } // printf("\n"); return this->argc; }; } else{ /* Phase wait */ if( (data & 0x80) == 0x00 ){ /* phase bit not found */ if(this->phase_error == 0) if(this->verbose)post("phase error:%x",data); this->phase_error++; } else{ this->phase_wait = B_FOUND_PHASE; /* phase found */ this->data[0] = data & 0x7F; /* store first data */ this->datacount = 1; /* wait for next */ this->phase_error = 0; /* phase error reset */ }; }; }; /* stream or point mode */ return 0; } void bird_setwritefun(bird_t *bird,void (*newwritefun)(void *this,unsigned char c)) { //if(bird == NULL) return; better segfault and you find the error... bird->writefun = newwritefun; } void bird_send(bird_t *this,unsigned char chr) { // if(this == NULL)return; better segfault and you find the error... if(this->writefun)this->writefun(this,chr); } /* with bang to trigger a data output (POINT) */ void bird_bang(bird_t *this) { if(this->datamode == B_MODE_POINT) bird_send(this,'B'); } /* set the modes for the bird */ void bird_set(bird_t *this,char *cmdname,long *cmddata) { int i,j; long data; bird_cmd *cmd = cmds; /* search for cmd */ while(cmd->name != (char *) 0l && strcmp(cmd->name,cmdname) != 0)cmd++; if(cmd->name == (char *) 0l){ post("bird:Dont know how to set %s",cmdname); return; } /* CMD found */ if(cmd->databytes > 0){ /* if databytes awaited, else dont change */ this->databytes = cmd->databytes; /* expected databytes per record */ this->datacount = 0; /* start with first */ this->argname = cmd->name; if( cmd->datamode == B_MODE_EXAM) this->phase_wait = B_FOUND_PHASE; /* wait for phase-bit */ else this->phase_wait = B_WAIT_PHASE; /* wait for phase-bit */ } if( cmd->datamode != B_MODE_IGNORE) /* go into data mode */ this->datamode = cmd->datamode; if(cmd->cmdbytes >= 0){ /* is a real cmd for bird */ bird_send(this,cmd->cmd); for(i=0; i < cmd->cmdbytes;i++){ data = cmddata[i]; for(j=0; j < cmd->cmdsize;j++){ /* send it bytewise */ bird_send(this, (unsigned char) (data&0xFF)); data >>= 8; }; }; } if(this->verbose)post("command %s (%c): databytes=%d, mode=%d, phase=%d", cmd->name,cmd->cmd, this->databytes, this->datamode, this->phase_wait); } /* ---------------- pd object bird ----------------- */ /* code for bird pd class */ void bird_float(bird_t *x, t_floatarg f) { int n,i; if((n=bird_data(x,(unsigned char) f)) > 0){ /* make list and output */ for(i=0; i < x->argc ; i++){ x->x_vec[i].a_type = A_FLOAT; x->x_vec[i].a_w.w_float = x->argv[i]; } outlet_list(x->x_obj.ob_outlet, &s_list, x->argc, x->x_vec); } } void bird_setting(bird_t *x, t_symbol *s, int argc, t_atom *argv) { int i; char *cmdnam; long buffer[ B_MAX_CMDDATA ]; if(argc < 1) return; cmdnam = argv[0].a_w.w_symbol->s_name; if(argc > (B_MAX_CMDDATA +1)) argc = B_MAX_CMDDATA +1; for(i=1;i< argc;i++) if(argv[i].a_type != A_FLOAT) post("bird set arg %d no float",i); else buffer[i-1] = argv[i].a_w.w_float; bird_set(x,cmdnam,buffer); } void bird_verbose(bird_t *x, t_floatarg f) { if(f) x->verbose = 1; else x->verbose = 0; } void bird_free(bird_t *x) { freebytes(x->x_vec, x->x_n * sizeof(*x->x_vec)); } t_class *bird_class; void bird_output(void *x,unsigned char c) { outlet_float(((bird_t *)x)->x_out2, (t_float) c); } void *bird_new(void) { bird_t *x; x = (bird_t *)pd_new(bird_class); outlet_new(&x->x_obj, &s_list); x->x_out2 = outlet_new(&x->x_obj, &s_float); x->x_vec = (t_atom *)getbytes((x->x_n=B_MAX_DATA) * sizeof(*x->x_vec)); bird_init(x); bird_setwritefun(x,bird_output); bird_set(x,"RUN",NULL); bird_set(x,"POSANG",NULL); // out_byte('W'); bird_set(x,"POINT",NULL); // out_byte(64); x->verbose = 0; return (void *)x; } void bird_setup(void) { bird_class = class_new(gensym("bird"), (t_newmethod)bird_new, (t_method)bird_free, sizeof(bird_t), 0, 0); /* maximum commandatasize is 6*/ class_addmethod(bird_class, (t_method)bird_setting, gensym("set"), A_GIMME, 0); class_addmethod(bird_class, (t_method)bird_verbose, gensym("verbose"), A_FLOAT, 0); class_addbang(bird_class,bird_bang); class_addfloat(bird_class, bird_float); }