/* Phidget InterfaceKit.c -- A very simple Max external object. Controls the Phidget InterfaceKit */ #include "ext.h" // standard Max include, always required #include "ext_obex.h" // required for new style Max object #ifdef MAC_VERSION #include "phidget21.h" #define CCONV #else #include "windows.h" #include "../phidget21.h" #define CCONV __stdcall #endif ////////////////////////// object struct typedef struct _InterfaceKit { t_object obj; t_atom val; t_symbol *name; void *outlet; CPhidgetInterfaceKitHandle phid; void *clock; long serial; long sample_rate; bool start; int numInputs; int numOutputs; int numSensors; } t_InterfaceKit; static t_class *InterfaceKit_class; // Required. Global pointing to this class // Prototypes for methods: need a method for each incoming message void *InterfaceKit_new(t_symbol *sym, long argc, t_atom *argv); // object creation method void InterfaceKit_free(t_InterfaceKit *InterfaceKit); void InterfaceKit_version(t_InterfaceKit *InterfaceKit); void InterfaceKit_serial(t_InterfaceKit *InterfaceKit); void InterfaceKit_status(t_InterfaceKit *InterfaceKit); void InterfaceKit_set(t_InterfaceKit *InterfaceKit, t_symbol *sym, long argc, t_atom *argv); void InterfaceKit_read(t_InterfaceKit *InterfaceKit); void InterfaceKit_start(t_InterfaceKit *InterfaceKit); void InterfaceKit_stop(t_InterfaceKit *InterfaceKit); void InterfaceKit_setSampleRate(t_InterfaceKit *InterfaceKit, long rate); void clock_tick(t_InterfaceKit *InterfaceKit); void openInterfaceKit(t_InterfaceKit *InterfaceKit, long serial, long remote, char *serverID, char *serverIP, long port, char *password); void outputSensors(t_InterfaceKit *InterfaceKit); void outputInputs(t_InterfaceKit *InterfaceKit); int CCONV SensorChangeHandler(CPhidgetInterfaceKitHandle ifkit, void *userptr, int Index, int Value); int CCONV InputChangeHandler(CPhidgetInterfaceKitHandle ifkit, void *userptr, int Index, int Value); int C74_EXPORT main(void) { t_class *c; c = class_new("PhidgetInterfaceKit", (method)InterfaceKit_new, (method)InterfaceKit_free, sizeof(t_InterfaceKit), NULL /* leave NULL!! */, A_GIMME, 0); class_addmethod(c, (method)InterfaceKit_version, "getVersion", 0); class_addmethod(c, (method)InterfaceKit_serial, "getSerial", 0); class_addmethod(c, (method)InterfaceKit_status, "getStatus", 0); class_addmethod(c, (method)InterfaceKit_set, "setoutput", A_GIMME, 0); class_addmethod(c, (method)InterfaceKit_read, "read", 0); class_addmethod(c, (method)InterfaceKit_start, "start", 0); class_addmethod(c, (method)InterfaceKit_stop, "stop", 0); class_addmethod(c, (method)InterfaceKit_setSampleRate, "setSampleRate", A_LONG, 0); class_register(CLASS_BOX, c); InterfaceKit_class = c; return 0; } void printUsage() { post("Invalid arguments.\n" "Usage: PhidgetInterfaceKit [serial] [remote [\"serverid\" [\"password\"]]] | [remoteip serverip port [\"password\"]]"); } void *InterfaceKit_new(t_symbol *sym, long argc, t_atom *argv) { t_InterfaceKit *InterfaceKit; long serial = -1, port = 0, remote = 0; char *serverID=NULL, *serverIP=NULL, *password=NULL; short i=0; //check for serial if (argc >= i+1 && atom_gettype(argv+i) == A_LONG) { serial = atom_getlong(argv+i); i++; } //if there are more args, check for remote, remoteip if (argc >= i+1 && atom_gettype(argv+i) == A_SYM) { if (atom_getsym(argv+i) == gensym("remote")) { remote = 1; if (argc > i+3) { printUsage(); return 0; } if (argc == i+3) { if (atom_gettype(argv+i+2) == A_SYM) { if (argv[i+2].a_w.w_sym->s_name[0] == '"'){ //handles quotation marks(not required to have a character) char *tempPassword = argv[i+2].a_w.w_sym->s_name; int a, actualLen; actualLen = strlen(tempPassword)-2+1; password = (char *)malloc(actualLen); //not including quotations marks, but including \0 for (a=0; a<(actualLen); a++) { password[a] = tempPassword[a+1]; if (a == (actualLen-1)) { password[a]='\0'; //fill end with \0 } } } else { //handles no quotation marks(but it is required to have a character) password = argv[i+2].a_w.w_sym->s_name; } } else { //not a symbol printUsage(); return 0; } } if (argc >= i+2) { if (atom_gettype(argv+i+1) == A_SYM) { if (argv[i+1].a_w.w_sym->s_name[0] == '"') { //handles quotation marks char *tempServer = argv[i+1].a_w.w_sym->s_name; int a, actualLen; actualLen = strlen(tempServer)-2+1; serverID = (char *)malloc(actualLen); //not including quotations marks, but including \0 for (a=0; a<(actualLen); a++){ serverID[a] = tempServer[a+1]; if (a == (actualLen-1)) { serverID[a] = '\0'; //fill end with \0 } } } else { //handles no quotation marks serverID = argv[i+1].a_w.w_sym->s_name; } } else { //if it not a symbol printUsage(); return 0; } } } else if (atom_getsym(argv+i) == gensym("remoteip")) { remote = 1; if (argc < i+3 || argc > i+4) { printUsage(); return 0; } if (argc == i+4) { if (atom_gettype(argv+i+3) != A_SYM){ printUsage(); return 0; } else { password = argv[i+3].a_w.w_sym->s_name; if (argv[i+3].a_w.w_sym->s_name[0] == '"') { //handles quotation marks(not required to have a character) char *tempPassword = argv[i+3].a_w.w_sym->s_name; int a, actualLen; actualLen = strlen(tempPassword)-2+1; password = (char *)malloc(actualLen); //not including quotations marks, but including \0 for (a=0; a<(actualLen); a++){ password[a] = tempPassword[a+1]; if (a == (actualLen-1)) { password[a] = '\0'; //fill end with \0 } } } else { //handles no quotation marks(but it is required to have a character) password = argv[i+3].a_w.w_sym->s_name; } } } serverIP = argv[i+1].a_w.w_sym->s_name; if (argv[i+2].a_type != A_LONG) { printUsage(); return 0; } else { port = argv[i+2].a_w.w_long; } } else { printUsage(); return 0; } } // create the new instance and return a pointer to it if (!(InterfaceKit = (t_InterfaceKit *)object_alloc(InterfaceKit_class))) { return NULL; } openInterfaceKit(InterfaceKit, serial, remote, serverID, serverIP, port, password); InterfaceKit->serial = serial; InterfaceKit->outlet = outlet_new(InterfaceKit, NULL); return InterfaceKit; // must return a pointer to the new instance } void InterfaceKit_free(t_InterfaceKit *InterfaceKit) { CPhidget_close((CPhidgetHandle)(InterfaceKit->phid)); CPhidget_delete((CPhidgetHandle)InterfaceKit->phid); object_free((t_object *)InterfaceKit->clock); } void InterfaceKit_version(t_InterfaceKit *InterfaceKit) { int ver = 0; CPhidget_getDeviceVersion((CPhidgetHandle)(InterfaceKit->phid), &ver); outlet_int(InterfaceKit->outlet, ver); } void InterfaceKit_serial(t_InterfaceKit *InterfaceKit) { int ser = 0; CPhidget_getSerialNumber((CPhidgetHandle)(InterfaceKit->phid), &ser); outlet_int(InterfaceKit->outlet, ser); } void InterfaceKit_status(t_InterfaceKit *InterfaceKit) { int stat = 0; CPhidget_getDeviceStatus((CPhidgetHandle)(InterfaceKit->phid), &stat); outlet_int(InterfaceKit->outlet, stat); } void InterfaceKit_set(t_InterfaceKit *InterfaceKit, t_symbol *sym, long argc, t_atom *argv) { long i; for (i=0; inumOutputs; i++) { CPhidgetInterfaceKit_setOutputState(InterfaceKit->phid, i, atom_getlong(argv+i)); } } void InterfaceKit_read(t_InterfaceKit *InterfaceKit) { clock_unset(InterfaceKit->clock); InterfaceKit->start = false; outputSensors(InterfaceKit); outputInputs(InterfaceKit); } void InterfaceKit_start(t_InterfaceKit *InterfaceKit) { if (!(InterfaceKit->sample_rate < 0)) { clock_delay(InterfaceKit->clock, InterfaceKit->sample_rate); } InterfaceKit->start = true; } void InterfaceKit_stop(t_InterfaceKit *InterfaceKit) { if (!(InterfaceKit->sample_rate < 0)) { clock_unset(InterfaceKit->clock); } InterfaceKit->start = false; } void InterfaceKit_setSampleRate(t_InterfaceKit *InterfaceKit, long rate) { if (rate < 0) { clock_unset(InterfaceKit->clock); } else { if (InterfaceKit->start == true && InterfaceKit->sample_rate < 0) { clock_delay(InterfaceKit->clock, InterfaceKit->sample_rate); } } InterfaceKit->sample_rate = rate; } void clock_tick(t_InterfaceKit *InterfaceKit) { clock_delay(InterfaceKit->clock, InterfaceKit->sample_rate); outputSensors(InterfaceKit); outputInputs(InterfaceKit); } int CCONV gotAttach(CPhidgetHandle phid, void *userptr) { int i; t_InterfaceKit *InterfaceKit = (t_InterfaceKit *)userptr; CPhidgetInterfaceKit_getOutputCount(InterfaceKit->phid, &(InterfaceKit->numOutputs)); CPhidgetInterfaceKit_getInputCount(InterfaceKit->phid, &(InterfaceKit->numInputs)); CPhidgetInterfaceKit_getSensorCount(InterfaceKit->phid, &(InterfaceKit->numSensors)); for (i=0; i<(InterfaceKit->numSensors); i++) { CPhidgetInterfaceKit_setSensorChangeTrigger(InterfaceKit->phid, i, 1); } return 0; } void openInterfaceKit(t_InterfaceKit *InterfaceKit, long serial, long remote, char *serverID, char *serverIP, long port, char *password) { //setup timing InterfaceKit->sample_rate = 100; //set default sample rate to 100ms InterfaceKit->clock = clock_new(InterfaceKit, (method)clock_tick); InterfaceKit->start = false; CPhidgetInterfaceKit_create(&(InterfaceKit->phid)); CPhidgetInterfaceKit_set_OnInputChange_Handler((InterfaceKit->phid),InputChangeHandler,InterfaceKit); CPhidgetInterfaceKit_set_OnSensorChange_Handler((InterfaceKit->phid),SensorChangeHandler,InterfaceKit); CPhidget_set_OnAttach_Handler((CPhidgetHandle)(InterfaceKit->phid), gotAttach, InterfaceKit); if (remote) { if (serverIP) { CPhidget_openRemoteIP((CPhidgetHandle)(InterfaceKit->phid), serial, serverIP, port, password); } else { CPhidget_openRemote((CPhidgetHandle)(InterfaceKit->phid), serial, serverID, password); } } else { CPhidget_open((CPhidgetHandle)(InterfaceKit->phid), serial); } } int CCONV SensorChangeHandler(CPhidgetInterfaceKitHandle ifkit, void *userptr, int Index, int Value) { t_InterfaceKit *InterfaceKit = (t_InterfaceKit *)userptr; if (InterfaceKit->sample_rate < 0 && InterfaceKit->start) { outputSensors(InterfaceKit); } return 0; } void outputSensors(t_InterfaceKit *InterfaceKit) { t_atom analog[16]; short i; int ai; for (i=0; i < InterfaceKit->numSensors; i++) { if (!CPhidgetInterfaceKit_getSensorValue(InterfaceKit->phid, i, &ai)) { atom_setlong(analog+i, ai); /* macro for setting a t_atom */ } else { atom_setlong(analog+i, 0); /* macro for setting a t_atom */ } } outlet_anything(InterfaceKit->outlet, gensym("ai"), InterfaceKit->numSensors, analog); } int CCONV InputChangeHandler(CPhidgetInterfaceKitHandle ifkit, void *userptr, int Index, int Value) { t_InterfaceKit *InterfaceKit = (t_InterfaceKit *)userptr; if (InterfaceKit->sample_rate < 0 && InterfaceKit->start) { outputInputs(InterfaceKit); } return 0; } void outputInputs(t_InterfaceKit *InterfaceKit) { t_atom digital[16]; short i; int di; for (i=0; inumInputs; i++) { if (!CPhidgetInterfaceKit_getInputState(InterfaceKit->phid, i, &di)) { atom_setlong(digital+i, di); /* macro for setting a t_atom */ } else { atom_setlong(digital+i, 0); /* macro for setting a t_atom */ } } outlet_anything(InterfaceKit->outlet, gensym("di"), InterfaceKit->numInputs, digital); }