From: Frank Mori Hess Date: Mon, 29 Mar 2004 02:19:38 +0000 (+0000) Subject: scxi convenience library patch from caleb tennis: X-Git-Tag: r0_7_22~57 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=0dbabb2cdd287516afebc0a845ce01c9f479b40b;p=comedilib.git scxi convenience library patch from caleb tennis: This latest patch changes the interface to three functions: comedi_scxi_open comedi_scxi_close comedi_scxi_readwrite With these three functions one can properly interface to all SCXI devices. If you like the latest patch (3/23/04 07:14), please apply and close this bug. Next up will be adding some generic analog and digital IO functions. --- diff --git a/include/comedilib_scxi.h b/include/comedilib_scxi.h index 4af4484..d2cd0e4 100644 --- a/include/comedilib_scxi.h +++ b/include/comedilib_scxi.h @@ -18,6 +18,8 @@ #define SCXI_AIO_AO 1 #define SCXI_AIO_AI 2 +#define REG_PARK 0x0FFFF + struct scxi_board_struct { unsigned int device_id; char name[12]; @@ -55,8 +57,10 @@ typedef struct scxi_module_struct scxi_mod_t; extern "C" { #endif -int comedi_scxi_serial_readwrite(comedi_t *it, unsigned char out_bits, unsigned char *in_bits); -int comedi_scxi_serial_config(comedi_t *it, unsigned int clock_interval); +void comedi_scxi_close(scxi_mod_t *mod); +scxi_mod_t *comedi_scxi_open(comedi_t *dev, unsigned short chassis_address, unsigned short mod_slot); +int comedi_scxi_register_readwrite(scxi_mod_t *mod, unsigned short address, unsigned int num_bytes, + unsigned char *data_out, unsigned char *data_in); #ifdef __cplusplus } diff --git a/scxi/scxi.c b/scxi/scxi.c index 7c47034..3696eda 100644 --- a/scxi/scxi.c +++ b/scxi/scxi.c @@ -1,6 +1,11 @@ #include "comedilib_scxi.h" +#include +#include +#include -int comedi_scxi_serial_config(comedi_t *it, unsigned int clock_interval) +static int scxi_identify(scxi_mod_t *mod); + +static int scxi_serial_config(comedi_t *it, unsigned int clock_interval) { comedi_insn insn; lsampl_t data[2]; @@ -16,7 +21,7 @@ int comedi_scxi_serial_config(comedi_t *it, unsigned int clock_interval) return comedi_do_insn(it,&insn); } -int comedi_scxi_serial_readwrite(comedi_t *it, unsigned char out_bits, unsigned char *in_bits) +static int scxi_serial_readwrite(comedi_t *it, unsigned char out_bits, unsigned char *in_bits) { int ret; comedi_insn insn; @@ -41,3 +46,157 @@ int comedi_scxi_serial_readwrite(comedi_t *it, unsigned char out_bits, unsigned return 0; } + +static int local_serial_readwrite(comedi_t *it, unsigned int subdev, unsigned int num_bits, + unsigned int out_bits, unsigned int *in_bits) +{ + unsigned char byte_out, byte_in; + while(num_bits > 0) { + if(in_bits != NULL) (*in_bits) <<= 8; + byte_out = (out_bits >> (num_bits - 8)) & 0xFF; + scxi_serial_readwrite(it,byte_out, &byte_in); + if(in_bits != NULL) *in_bits |= byte_in; + + num_bits -= 8; + } + return 0; +} + +static int scxi_slot_select(comedi_t *dev, unsigned int dio_subdev, + unsigned int serial_subdev, unsigned short chassis_address, unsigned short module_slot) +{ + const unsigned int ssreg = ((chassis_address & 0x1f) << 4) | (module_slot & 0x0f); + + comedi_dio_write(dev, dio_subdev, SCXI_LINE_SS, 0); + scxi_serial_config(dev, SLOT0_INTERVAL); + local_serial_readwrite(dev, serial_subdev, 16, ssreg, NULL); + comedi_dio_write(dev, dio_subdev, SCXI_LINE_SS, 1); + + return 0; +} + +void comedi_scxi_close(scxi_mod_t *mod) +{ + free(mod); +} + +scxi_mod_t *comedi_scxi_open(comedi_t *dev, unsigned short chassis_address, unsigned short mod_slot) +{ + scxi_mod_t *mod = NULL; + + mod = (scxi_mod_t *) malloc(sizeof(*mod)); + if(mod == NULL) goto Error; + + memset(mod, 0, sizeof(*mod)); + mod->chassis = chassis_address; + mod->slot = mod_slot; + + mod->dev = dev; + if(mod->dev == NULL) goto Error; + + mod->dio_subdev = comedi_find_subdevice_by_type(mod->dev, COMEDI_SUBD_DIO, 0); + mod->ser_subdev = comedi_find_subdevice_by_type(mod->dev, COMEDI_SUBD_SERIAL, 0); + + comedi_dio_config(mod->dev, mod->dio_subdev, SCXI_LINE_MISO, COMEDI_INPUT); + comedi_dio_config(mod->dev, mod->dio_subdev, SCXI_LINE_DA, COMEDI_OUTPUT); + comedi_dio_config(mod->dev, mod->dio_subdev, SCXI_LINE_SS, COMEDI_OUTPUT); + comedi_dio_config(mod->dev, mod->dio_subdev, SCXI_LINE_MOSI, COMEDI_OUTPUT); + + comedi_dio_write(mod->dev, mod->dio_subdev, SCXI_LINE_DA, 1); + comedi_dio_write(mod->dev, mod->dio_subdev, SCXI_LINE_SS, 1); + + scxi_identify(mod); + + return mod; + +Error: + comedi_scxi_close(mod); + return NULL; +} + +static int scxi_module_select(scxi_mod_t *mod, unsigned short address) +{ + scxi_slot_select(mod->dev, mod->dio_subdev, mod->ser_subdev, mod->chassis, mod->slot); + + if(scxi_serial_config(mod->dev, scxi_boards[mod->board].clock_interval) < 0) + return -1; + + if(scxi_boards[mod->board].modclass == 2) + if(local_serial_readwrite(mod->dev, mod->ser_subdev, 16, address, NULL) < 0) return -1; + + if(comedi_dio_write(mod->dev, mod->dio_subdev, SCXI_LINE_DA, 0) < 0) return -1; + + return 0; +} + +static int scxi_module_deselect(scxi_mod_t *mod) +{ + if(comedi_dio_write(mod->dev, mod->dio_subdev, SCXI_LINE_DA, 1) < 0) return -1; + + if(scxi_boards[mod->board].modclass == 2) { + if(local_serial_readwrite(mod->dev, mod->ser_subdev, 16, REG_PARK, NULL) < 0) return -1; + } + + scxi_slot_select(mod->dev, mod->dio_subdev, mod->ser_subdev, mod->chassis, 0); + + return 0; +} + +static int scxi_identify(scxi_mod_t *mod) +{ + unsigned int id, i; + if(mod == NULL || mod->dev == NULL) + return -1; + + scxi_slot_select(mod->dev, mod->dio_subdev, mod->ser_subdev, mod->chassis, mod->slot); + + scxi_serial_config(mod->dev, SLOW_INTERVAL); + local_serial_readwrite(mod->dev, mod->ser_subdev, 32, 0, &id); + + if(id == 0xffffffff) { + comedi_dio_write(mod->dev, mod->dio_subdev, SCXI_LINE_DA, 0); + local_serial_readwrite(mod->dev, mod->ser_subdev, 32, 0, &id); + comedi_dio_write(mod->dev, mod->dio_subdev, SCXI_LINE_DA, 1); + } + + id = bswap_32(id); + + scxi_module_deselect(mod); + + for (i=0;iboard = i; + break; + } + } + + fprintf(stderr, "name=%s, device_id = 0x%x, chassis_ad = %d, mod = %d\n", + scxi_boards[mod->board].name, scxi_boards[mod->board].device_id, mod->chassis, mod->slot); + + return 0; + +} + +int comedi_scxi_register_readwrite(scxi_mod_t *mod, unsigned short address, unsigned int num_bytes, + unsigned char *data_out, unsigned char *data_in) +{ + unsigned int i; + unsigned int tmp_in, tmp_out = 0; + + if(mod == NULL || mod->dev == NULL) return -1; + + scxi_module_select(mod, address); + + for(i = 0; i < num_bytes; ++i) { + if(data_out) tmp_out = data_out[i]; + local_serial_readwrite(mod->dev, mod->ser_subdev, 8, tmp_out, &tmp_in); + if(data_in) data_in[i] = tmp_in; + } + + if(scxi_boards[mod->board].modclass == 1 && address == 0) { + comedi_dio_write(mod->dev, mod->dio_subdev, SCXI_LINE_SS, 1); + } + + scxi_module_deselect(mod); + return 0; +}