/* Copyright (c) 2009, Pavel Demin All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the SRMlite nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include /* ----------------------------------------------------------------- */ typedef struct UsbDevice { Tcl_Command token; usb_dev_handle *device; } UsbDevice; /* ----------------------------------------------------------------- */ static void UsbDeviceDestroy(ClientData clientData) { UsbDevice *statePtr = (UsbDevice *) clientData; if(statePtr->device != NULL) { usb_close(statePtr->device); } ckfree((char *)statePtr); } /* ----------------------------------------------------------------- */ static int UsbReadRawObjCmd(UsbDevice *statePtr, Tcl_Interp *interp, Tcl_Obj *CONST obj) { unsigned char *data; int read_size, size; Tcl_Obj *result; if(TCL_OK != Tcl_GetIntFromObj(interp, obj, &size)) { Tcl_AppendResult(interp, "Parameter size is not an integer", NULL); return TCL_ERROR; } data = ckalloc((unsigned int)(size + 2)); read_size = usb_bulk_read(statePtr->device, 0x86, data, size + 2, 1000); if(read_size < 0) { ckfree(data); Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } if(data[0] > 0) { ckfree(data); Tcl_AppendResult(interp, "Busy", NULL); return 5; } if(read_size != size + 2) { ckfree(data); Tcl_AppendResult(interp, "Read less than requested", NULL); return TCL_ERROR; } result = Tcl_NewByteArrayObj(data + 2, size); ckfree(data); Tcl_SetObjResult(interp, result); return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbReadHexObjCmd(UsbDevice *statePtr, Tcl_Interp *interp, Tcl_Obj *CONST objv[]) { unsigned char *buffer; unsigned char *data; int word_size, char_size, data_size, read_size, i, j, pos; unsigned char hexval[16] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; Tcl_Obj *result; if(TCL_OK != Tcl_GetIntFromObj(interp, objv[0], &word_size)) { Tcl_AppendResult(interp, "Parameter width is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[1], &data_size)) { Tcl_AppendResult(interp, "Parameter size is not an integer", NULL); return TCL_ERROR; } char_size = 3 + 2*word_size; data = ckalloc((unsigned int)(data_size*word_size + 2)); buffer = ckalloc((unsigned int)(data_size*char_size)); read_size = usb_bulk_read(statePtr->device, 0x86, data, data_size*word_size + 2, 1000); if(read_size < 0) { ckfree(buffer); ckfree(data); Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } if(data[0] > 0) { ckfree(buffer); ckfree(data); Tcl_AppendResult(interp, "Busy", NULL); return 5; } if(read_size != data_size*word_size + 2) { ckfree(buffer); ckfree(data); Tcl_AppendResult(interp, "Read less than requested", NULL); return TCL_ERROR; } for(i = 0; i < data_size; ++i) { buffer[i*char_size + 0] = '0'; buffer[i*char_size + 1] = 'x'; for(j = 1; j <= word_size; ++j) { pos = 2 + i*word_size + word_size - j; buffer[i*char_size + 0 + 2*j] = hexval[(data[pos] >> 4) & 0x0F]; buffer[i*char_size + 1 + 2*j] = hexval[(data[pos]) & 0x0F]; } buffer[i*char_size + 2*word_size + 2] = ' '; } result = Tcl_NewStringObj(buffer, data_size*char_size); ckfree(buffer); ckfree(data); Tcl_SetObjResult(interp, result); return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbReadBltObjCmd(UsbDevice *statePtr, Tcl_Interp *interp, Tcl_Obj *CONST objv[]) { unsigned char *data; int word_size, data_size, read_size, i, j, pos; unsigned long long int value; char *name; Blt_Vector *vec; if(TCL_OK != Tcl_GetIntFromObj(interp, objv[0], &word_size)) { Tcl_AppendResult(interp, "Parameter width is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[1], &data_size)) { Tcl_AppendResult(interp, "Parameter size is not an integer", NULL); return TCL_ERROR; } name = Tcl_GetString(objv[2]); if(TCL_OK != Blt_GetVector(interp, name, &vec)) { Tcl_AppendResult(interp, "Cannot find BLT vector", name, NULL); return TCL_ERROR; } if(Blt_VecSize(vec) < data_size) { Tcl_AppendResult(interp, "BLT vector size is less than the data size", NULL); return TCL_ERROR; } data = ckalloc((unsigned int)(data_size*word_size + 2)); read_size = usb_bulk_read(statePtr->device, 0x86, data, data_size*word_size + 2, 1000); if(read_size < 0) { ckfree(data); Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } if(data[0] > 0) { ckfree(data); Tcl_AppendResult(interp, "Busy", NULL); return 5; } if(read_size != data_size*word_size + 2) { ckfree(data); Tcl_AppendResult(interp, "Read less than requested", NULL); return TCL_ERROR; } for(i = 0; i < data_size; ++i) { value = 0; for(j = 1; j <= word_size; ++j) { pos = 2 + i*word_size + word_size - j; value = (value << 8) | data[pos]; } Blt_VecData(vec)[i] = (double)value; } ckfree(data); Blt_ResetVector(vec, Blt_VecData(vec), data_size, Blt_VecSize(vec), TCL_STATIC); return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbReadOscObjCmd(UsbDevice *statePtr, Tcl_Interp *interp, Tcl_Obj *CONST objv[]) { unsigned char *data; int data_size, read_size, i, j, pos, value; Tcl_DictSearch search; Tcl_Obj *key, *object; int done; char *name; Blt_Vector *vec[15]; if(TCL_OK != Tcl_GetIntFromObj(interp, objv[0], &data_size)) { Tcl_AppendResult(interp, "Parameter size is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_DictObjFirst(interp, objv[1], &search, &key, &object, &done)) { Tcl_AppendResult(interp, "Cannot read dict variable", name, NULL); return TCL_ERROR; } for(i = 0; (i < 15) && (!done) ; ++i, Tcl_DictObjNext(&search, &key, &object, &done)) { name = Tcl_GetString(object); if(TCL_OK != Blt_GetVector(interp, name, &vec[i])) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "Cannot find BLT vector", name, NULL); return TCL_ERROR; } if(Blt_VecSize(vec[i]) < data_size) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "BLT vector size is less than the data size", NULL); return TCL_ERROR; } } Tcl_DictObjDone(&search); data = ckalloc((unsigned int)(data_size * 8 + 2)); read_size = usb_bulk_read(statePtr->device, 0x86, data, data_size * 8 + 2, 1000); if(read_size < 0) { ckfree(data); Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } if(data[0] > 0) { ckfree(data); Tcl_AppendResult(interp, "Busy", NULL); return 5; } if(read_size != data_size * 8 + 2) { ckfree(data); Tcl_AppendResult(interp, "Read less than requested", NULL); return TCL_ERROR; } for(i = 0; i < data_size; ++i) { pos = 2 + i * 8; value = data[pos + 1] & 0x0F; value = (value << 8) | data[pos]; Blt_VecData(vec[0])[i] = (double)value; value = data[pos + 2]; value = (value << 4) | (data[pos + 1] >> 4); Blt_VecData(vec[1])[i] = (double)value; value = data[pos + 4] & 0x0F; value = (value << 8) | data[pos + 3]; Blt_VecData(vec[2])[i] = (double)value; value = data[pos + 5]; value = (value << 4) | (data[pos + 4] >> 4); for(j = 0; j < 12; ++j) { Blt_VecData(vec[j+3])[i] = (double)((value & 1) + (j * 2)); value >>= 1; } } ckfree(data); for(i = 0; i < 15; ++i) { Blt_ResetVector(vec[i], Blt_VecData(vec[i]), data_size, Blt_VecSize(vec[i]), TCL_STATIC); } return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbWriteRawObjCmd(UsbDevice *statePtr, Tcl_Interp *interp, Tcl_Obj *CONST obj) { unsigned char *data; int size, i; Tcl_Obj *result; data = Tcl_GetByteArrayFromObj(obj, &size); /* for(i = 0; i < size; ++i) printf(" %02x", data[i]); printf("\n"); printf("size = %d\n", size); fflush(stdout); */ // size = usb_bulk_write(statePtr->device , 0x06, data, size, 1000); size = usb_bulk_write(statePtr->device , 0x08, data, size, 1000); if(size >= 0) { result = Tcl_NewIntObj(size); Tcl_SetObjResult(interp, result); return TCL_OK; } else { Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } } /* ----------------------------------------------------------------- */ static int UsbControlObjCmd(UsbDevice *statePtr, Tcl_Interp *interp, Tcl_Obj *CONST objv[]) { unsigned char *data; int addr, size, i; Tcl_Obj *result; if(TCL_OK != Tcl_GetIntFromObj(interp, objv[0], &addr)) { Tcl_AppendResult(interp, "Parameter addr is not an integer", NULL); return TCL_ERROR; } data = Tcl_GetByteArrayFromObj(objv[1], &size); size = usb_control_msg(statePtr->device, 0x40, 0xa0, addr, 0, data, size, 1000); if(size >= 0) { result = Tcl_NewIntObj(size); Tcl_SetObjResult(interp, result); return TCL_OK; } else { Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } } /* ----------------------------------------------------------------- */ static int UsbDeviceObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *option; UsbDevice *statePtr = (UsbDevice *) clientData; if(objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?arg?"); return TCL_ERROR; } option = Tcl_GetStringFromObj(objv[1], NULL); if(strcmp(option, "readRaw") == 0) { if(objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "readRaw size"); return TCL_ERROR; } return UsbReadRawObjCmd(statePtr, interp, objv[2]); } else if(strcmp(option, "readHex") == 0) { if(objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "readHex width size"); return TCL_ERROR; } return UsbReadHexObjCmd(statePtr, interp, objv + 2); } else if(strcmp(option, "readBlt") == 0) { if(objc != 5) { Tcl_WrongNumArgs(interp, 1, objv, "readBlt width size vector"); return TCL_ERROR; } return UsbReadBltObjCmd(statePtr, interp, objv + 2); } else if(strcmp(option, "readOsc") == 0) { if(objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "readOsc size dict"); return TCL_ERROR; } return UsbReadOscObjCmd(statePtr, interp, objv + 2); } else if(strcmp(option, "writeRaw") == 0) { if(objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "writeRaw data"); return TCL_ERROR; } return UsbWriteRawObjCmd(statePtr, interp, objv[2]); } else if(strcmp(option, "control") == 0) { if(objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "control addr data"); return TCL_ERROR; } return UsbControlObjCmd(statePtr, interp, objv + 2); } else if(strcmp(option, "disconnect") == 0) { if(objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "disconnect"); return TCL_ERROR; } Tcl_DeleteCommandFromToken(interp, statePtr->token); return TCL_OK; } Tcl_AppendResult(interp, "bad option \"", option, "\": must be read, read8, read16, read32, write, control, convert or disconnect", NULL); return TCL_ERROR; } /* ----------------------------------------------------------------- */ static int UsbConnectObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char cmdName[256]; Tcl_CmdInfo cmdInfo; int cmdCounter; int idVendor, idProduct; int bConfigurationValue, bInterfaceNumber, bAlternateSetting; UsbDevice *statePtr = (UsbDevice *) clientData; struct usb_bus *bus; struct usb_device *dev; struct usb_device *current_device; struct usb_dev_handle *device_handle; int rc; if(objc != 6) { Tcl_WrongNumArgs(interp, 1, objv, "idVendor idProduct bConfigurationValue bInterfaceNumber bAlternateSetting"); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[1], &idVendor)) { Tcl_AppendResult(interp, "Parameter idVendor is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[2], &idProduct)) { Tcl_AppendResult(interp, "Parameter idProduct is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[3], &bConfigurationValue)) { Tcl_AppendResult(interp, "Parameter bConfigurationValue is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[4], &bInterfaceNumber)) { Tcl_AppendResult(interp, "Parameter bInterfaceNumber is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[5], &bAlternateSetting)) { Tcl_AppendResult(interp, "Parameter bAlternateSetting is not an integer", NULL); return TCL_ERROR; } usb_find_busses(); usb_find_devices(); current_device = NULL; for(bus = usb_get_busses(); bus && current_device == NULL; bus = bus->next) { for(dev = bus->devices; dev && current_device == NULL; dev = dev->next) { if((dev->descriptor.idVendor == idVendor) && (dev->descriptor.idProduct == idProduct)) { current_device = dev; } } } if(current_device == NULL) { Tcl_AppendResult(interp, "No CY7C68013 device present", NULL); return TCL_ERROR; } device_handle = usb_open(current_device); if(device_handle == NULL) { Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } rc = usb_set_configuration(device_handle, bConfigurationValue); if(rc != 0) { Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } rc = usb_claim_interface(device_handle, bInterfaceNumber); if(rc != 0) { Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } rc = usb_set_altinterface(device_handle, bAlternateSetting); if(rc != 0) { Tcl_AppendResult(interp, usb_strerror(), NULL); return TCL_ERROR; } statePtr = (UsbDevice *) ckalloc((unsigned int) sizeof(UsbDevice)); memset(statePtr, 0, sizeof(UsbDevice)); statePtr->device = device_handle; cmdCounter = 0; do { sprintf(cmdName, "::usb::device_%d_%d_%d", idVendor, idProduct, cmdCounter); cmdCounter++; } while(Tcl_GetCommandInfo(interp, cmdName, &cmdInfo)); statePtr->token = Tcl_CreateObjCommand(interp, cmdName, UsbDeviceObjCmd, (ClientData) statePtr, UsbDeviceDestroy); Tcl_SetResult(interp, cmdName, TCL_VOLATILE); return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbConvertObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { unsigned char *buffer, tmp[3]; unsigned char *data; int length, size, i; Tcl_Obj *result; if(objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "data"); return TCL_ERROR; } data = Tcl_GetStringFromObj(objv[1], &size); buffer = ckalloc((unsigned int) (size/2)); tmp[2] = 0; length = 0; for(i = 1; i < size; i += 2) { tmp[0] = data[i - 1]; tmp[1] = data[i]; buffer[length++] = strtoul(tmp, 0, 16); } result = Tcl_NewByteArrayObj(buffer, length); ckfree(buffer); Tcl_SetObjResult(interp, result); return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbConvertBltObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { unsigned char *data; int size, width, length, i, j, pos, value; char *name; Blt_Vector *vec; if(objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "data width vector"); return TCL_ERROR; } data = Tcl_GetByteArrayFromObj(objv[1], &size); if(TCL_OK != Tcl_GetIntFromObj(interp, objv[2], &width)) { Tcl_AppendResult(interp, "Parameter width is not an integer", NULL); return TCL_ERROR; } length = size / width; name = Tcl_GetString(objv[3]); if(TCL_OK != Blt_GetVector(interp, name, &vec)) { Tcl_AppendResult(interp, "Cannot find BLT vector", name, NULL); return TCL_ERROR; } if(Blt_VecSize(vec) < length) { Tcl_AppendResult(interp, "BLT vector size is less than the data length", NULL); return TCL_ERROR; } for(i = 0; i < length; ++i) { value = 0; for(j = 1; j <= width; ++j) { pos = i*width + width - j; value = (value << 8) | data[pos]; } Blt_VecData(vec)[i] = (double)value; } Blt_ResetVector(vec, Blt_VecData(vec), length, Blt_VecSize(vec), TCL_STATIC); return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbConvertEptObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { unsigned char *data; int size, length, i, j, pos, value; Tcl_DictSearch search; Tcl_Obj *key, *object; int done; char *name; Blt_Vector *vec[16]; if(objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "data dict"); return TCL_ERROR; } data = Tcl_GetByteArrayFromObj(objv[1], &size); length = size / 8; if(TCL_OK != Tcl_DictObjFirst(interp, objv[2], &search, &key, &object, &done)) { Tcl_AppendResult(interp, "Cannot read dict variable", name, NULL); return TCL_ERROR; } for(i = 0; (i < 16) && (!done) ; ++i, Tcl_DictObjNext(&search, &key, &object, &done)) { name = Tcl_GetString(object); if(TCL_OK != Blt_GetVector(interp, name, &vec[i])) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "Cannot find BLT vector", name, NULL); return TCL_ERROR; } if(Blt_VecSize(vec[i]) < length) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "BLT vector size is less than the data size", NULL); return TCL_ERROR; } } Tcl_DictObjDone(&search); for(i = 0; i < length; ++i) { pos = i * 8; value = data[pos + 1] & 0x0F; value = (value << 8) | data[pos]; Blt_VecData(vec[0])[i] = (double)value; value = data[pos + 2]; value = (value << 4) | (data[pos + 1] >> 4); Blt_VecData(vec[1])[i] = (double)value; value = data[pos + 4] & 0x0F; value = (value << 8) | data[pos + 3]; Blt_VecData(vec[2])[i] = (double)value; value = data[pos + 5]; value = (value << 4) | (data[pos + 4] >> 4); Blt_VecData(vec[3])[i] = (double)value; value = data[pos + 7] & 0x0F; value = (value << 8) | data[pos + 6]; for(j = 0; j < 12; ++j) { Blt_VecData(vec[j+4])[i] = (double)((value & 1) + (j * 2)); value >>= 1; } } for(i = 0; i < 16; ++i) { Blt_ResetVector(vec[i], Blt_VecData(vec[i]), length, Blt_VecSize(vec[i]), TCL_STATIC); } return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbConvertOscObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { unsigned char *data; int size, length, i, j, pos, value; Tcl_DictSearch search; Tcl_Obj *key, *object; int done; char *name; Blt_Vector *vec[16]; if(objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "data dict"); return TCL_ERROR; } data = Tcl_GetByteArrayFromObj(objv[1], &size); length = size / 8; if(TCL_OK != Tcl_DictObjFirst(interp, objv[2], &search, &key, &object, &done)) { Tcl_AppendResult(interp, "Cannot read dict variable", name, NULL); return TCL_ERROR; } for(i = 0; (i < 16) && (!done) ; ++i, Tcl_DictObjNext(&search, &key, &object, &done)) { name = Tcl_GetString(object); if(TCL_OK != Blt_GetVector(interp, name, &vec[i])) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "Cannot find BLT vector", name, NULL); return TCL_ERROR; } if(Blt_VecSize(vec[i]) < length) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "BLT vector size is less than the data size", NULL); return TCL_ERROR; } } Tcl_DictObjDone(&search); for(i = 0; i < length; ++i) { pos = i * 8; value = data[pos + 1] & 0x0F; value = (value << 8) | data[pos]; Blt_VecData(vec[0])[i] = (double)value; value = data[pos + 2]; value = (value << 4) | (data[pos + 1] >> 4); Blt_VecData(vec[1])[i] = (double)value; value = data[pos + 4] & 0x0F; value = (value << 8) | data[pos + 3]; Blt_VecData(vec[2])[i] = (double)value; value = data[pos + 5]; value = (value << 4) | (data[pos + 4] >> 4); Blt_VecData(vec[3])[i] = (double)value; value = data[pos + 7] & 0x0F; value = (value << 8) | data[pos + 6]; Blt_VecData(vec[4])[i] = (double)value; value = data[pos + 7] >> 4; for(j = 0; j < 4; ++j) { Blt_VecData(vec[j+5])[i] = (double)((value & 1) << 8); value >>= 1; } } for(i = 0; i < 9; ++i) { Blt_ResetVector(vec[i], Blt_VecData(vec[i]), length, Blt_VecSize(vec[i]), TCL_STATIC); } return TCL_OK; } /* ----------------------------------------------------------------- */ /* ----------------------------------------------------------------- */ static int UsbConvertOsc16ObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { unsigned char *data; int size, length, i, j, pos, value; Tcl_DictSearch search; Tcl_Obj *key, *object; int done; char *name; Blt_Vector *vec[18]; if(objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "data dict"); return TCL_ERROR; } data = Tcl_GetByteArrayFromObj(objv[1], &size); length = size / 16; if(TCL_OK != Tcl_DictObjFirst(interp, objv[2], &search, &key, &object, &done)) { Tcl_AppendResult(interp, "Cannot read dict variable", name, NULL); return TCL_ERROR; } for(i = 0; (i < 18) && (!done) ; ++i, Tcl_DictObjNext(&search, &key, &object, &done)) { name = Tcl_GetString(object); if(TCL_OK != Blt_GetVector(interp, name, &vec[i])) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "Cannot find BLT vector", name, NULL); return TCL_ERROR; } if(Blt_VecSize(vec[i]) < length) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "BLT vector size is less than the data size", NULL); return TCL_ERROR; } } Tcl_DictObjDone(&search); for(i = 0; i < length; ++i) { pos = i * 16; value = data[pos + 1] & 0x0F; value = (value << 8) | data[pos]; Blt_VecData(vec[0])[i] = (double)value; value = data[pos + 2]; value = (value << 4) | (data[pos + 1] >> 4); Blt_VecData(vec[1])[i] = (double)value; value = data[pos + 4] & 0x0F; value = (value << 8) | data[pos + 3]; Blt_VecData(vec[2])[i] = (double)value; value = data[pos + 5]; value = (value << 4) | (data[pos + 4] >> 4); Blt_VecData(vec[3])[i] = (double)value; value = data[pos + 7] & 0x0F; value = (value << 8) | data[pos + 6]; Blt_VecData(vec[4])[i] = (double)value; value = data[pos + 8]; value = (value << 4) | (data[pos + 7] >> 4); Blt_VecData(vec[5])[i] = (double)value; value = data[pos + 10] & 0x0F; value = (value << 8) | data[pos + 9]; Blt_VecData(vec[6])[i] = (double)value; value = data[pos + 11]; value = (value << 4) | (data[pos + 10] >> 4); Blt_VecData(vec[7])[i] = (double)value; value = data[pos + 13] & 0x0F; value = (value << 8) | data[pos + 12]; Blt_VecData(vec[8])[i] = (double)value; value = data[pos + 14]; value = (value << 4) | (data[pos + 13] >> 4); Blt_VecData(vec[9])[i] = (double)value; value = data[pos + 15]; for(j = 0; j < 8; ++j) { Blt_VecData(vec[j+10])[i] = (double)((value & 1) << 8); value >>= 1; } } for(i = 0; i < 18; ++i) { Blt_ResetVector(vec[i], Blt_VecData(vec[i]), length, Blt_VecSize(vec[i]), TCL_STATIC); } return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbFormatOscCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { char *name; int first, last, done, max, i, j; Tcl_DictSearch search; Tcl_Obj *key, *object, *result, *eol; Blt_Vector *vec[32]; if(objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "dict first last"); return TCL_ERROR; } if(TCL_OK != Tcl_DictObjFirst(interp, objv[1], &search, &key, &object, &done)) { Tcl_AppendResult(interp, "Cannot read dict variable", name, NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[2], &first)) { Tcl_AppendResult(interp, "Parameter first is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[3], &last)) { Tcl_AppendResult(interp, "Parameter last is not an integer", NULL); return TCL_ERROR; } if(last < first) { return TCL_OK; } for(i = 0; (i < 32) && (!done); ++i, Tcl_DictObjNext(&search, &key, &object, &done)) { name = Tcl_GetString(object); if(TCL_OK != Blt_GetVector(interp, name, &vec[i])) { Tcl_DictObjDone(&search); Tcl_AppendResult(interp, "Cannot find BLT vector", name, NULL); return TCL_ERROR; } if(Blt_VecLength(vec[i]) <= last) { last = Blt_VecLength(vec[i]) - 1; } max = i; } Tcl_DictObjDone(&search); if(first < 0) { first = 0; } result = Tcl_NewObj(); eol = Tcl_NewStringObj("\n", -1); Tcl_IncrRefCount(result); Tcl_IncrRefCount(eol); for(i = first; i <= last; ++i) { for(j = 0; j <= max; ++j) { if(j > 0) { Tcl_AppendPrintfToObj(result, "\t%g", Blt_VecData(vec[j])[i]); } else { Tcl_AppendPrintfToObj(result, "%g", Blt_VecData(vec[j])[i]); } } Tcl_AppendObjToObj(result, eol); } Tcl_SetObjResult(interp, result); Tcl_DecrRefCount(eol); Tcl_DecrRefCount(result); return TCL_OK; } /* ----------------------------------------------------------------- */ static int UsbIntegrateBltObjCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { int length, i, xmin, xmax, flag; double entr, mean; char *name; Blt_Vector *vec; Tcl_Obj *result; if(objc != 5) { Tcl_WrongNumArgs(interp, 1, objv, "vector xmin xmax flag"); return TCL_ERROR; } name = Tcl_GetString(objv[1]); if(TCL_OK != Blt_GetVector(interp, name, &vec)) { Tcl_AppendResult(interp, "Cannot find BLT vector", name, NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[2], &xmin)) { Tcl_AppendResult(interp, "Parameter xmin is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[3], &xmax)) { Tcl_AppendResult(interp, "Parameter xmax is not an integer", NULL); return TCL_ERROR; } if(TCL_OK != Tcl_GetIntFromObj(interp, objv[4], &flag)) { Tcl_AppendResult(interp, "Parameter flag is not an integer", NULL); return TCL_ERROR; } length = Blt_VecLength(vec); entr = 0.0; mean = 0.0; if(xmin < 0) xmin = 0; if(xmax >= length) xmax = length - 1; if(xmax < xmin) xmax = xmin; for(i = xmin; i <= xmax; ++i) { entr += Blt_VecData(vec)[i]; mean += i * Blt_VecData(vec)[i]; } if(flag) { result = Tcl_NewDoubleObj(entr > 0.0 ? mean / entr : 0.0); } else { result = Tcl_NewDoubleObj(entr); } Tcl_SetObjResult(interp, result); return TCL_OK; } /* ----------------------------------------------------------------- */ int Usb_Init(Tcl_Interp *interp) { usb_init(); Tcl_CreateObjCommand(interp, "usb::connect", UsbConnectObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "usb::convert", UsbConvertObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "usb::convertBlt", UsbConvertBltObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "usb::convertEpt", UsbConvertOscObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "usb::convertOsc", UsbConvertOscObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "usb::convertOsc16", UsbConvertOsc16ObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "usb::formatOsc", UsbFormatOscCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); Tcl_CreateObjCommand(interp, "usb::integrateBlt", UsbIntegrateBltObjCmd, (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); return Tcl_PkgProvide(interp, "usb", "0.1"); }