@@ -78,6 +78,10 @@ const char usbdesc[] = "Open Ephys FT600 USB board";
7878#define CHECK_FTERR (exp ) {if(exp!=FT_OK){oni_ft600_free_ctx(ctx);return ONI_EINIT;}}
7979#define CHECK_NULL (exp ) {if(exp==NULL){oni_ft600_free_ctx(ctx);return ONI_EBADALLOC;}}
8080#define CHECK_ERR (exp ) {if(exp==0){oni_ft600_free_ctx(ctx);return ONI_EINIT;}}
81+ #define FREE_AND_RELEASE (exp ) {if (exp != NULL) { free(exp); exp = NULL;} }
82+
83+ // Bytes that a register operation compound comand takes
84+ #define MAX_REG_OP_SIZE 45
8185
8286typedef enum
8387{
@@ -96,6 +100,13 @@ typedef enum
96100const oni_driver_info_t driverInfo
97101 = {.name = "ft600" , .major = 1 , .minor = 0 , .patch = 5 , .pre_release = NULL };
98102
103+ typedef struct {
104+ oni_dev_idx_t dev_idx ;
105+ oni_reg_addr_t dev_addr ;
106+ oni_reg_val_t value ;
107+ oni_reg_val_t rw ;
108+ } oni_ft600_reg_operation_t ;
109+
99110struct oni_ft600_ctx_impl {
100111 oni_size_t inBlockSize ;
101112 oni_size_t outBlockSize ;
@@ -125,12 +136,10 @@ struct oni_ft600_ctx_impl {
125136 OVERLAPPED sigOverlapped ;
126137 OVERLAPPED outOverlapped ;
127138#endif
128- struct {
129- oni_dev_idx_t dev_idx ;
130- oni_reg_addr_t dev_addr ;
131- oni_reg_val_t value ;
132- oni_reg_val_t rw ;
133- } regOperation ;
139+ oni_ft600_reg_operation_t * regOperation ;
140+ size_t regOperationIndex ;
141+ size_t maxRegOperation ;
142+ uint8_t * regOperationBuffer ;
134143};
135144
136145typedef struct oni_ft600_ctx_impl * oni_ft600_ctx ;
@@ -288,8 +297,6 @@ void oni_ft600_update_control(oni_ft600_ctx ctx)
288297}
289298#endif
290299
291- static inline oni_conf_off_t _oni_register_offset (oni_config_t reg );
292-
293300inline void oni_ft600_restart_acq (oni_ft600_ctx ctx )
294301{
295302 ctx -> nextReadIndex = 0 ;
@@ -371,13 +378,18 @@ oni_driver_ctx oni_driver_create_ctx(void)
371378 ctx -> regBuffer .size = DEFAULT_REGSIZE ;
372379 ctx -> signalBuffer .size = DEFAULT_SIGNALSIZE ;
373380 ctx -> numInOverlapped = DEFAULT_OVERLAPPED ;
381+ ctx -> regOperation = NULL ;
382+ ctx -> regOperationBuffer = NULL ;
383+ ctx -> regOperationIndex = 0 ;
374384 return ctx ;
375385}
376386
377387void oni_ft600_free_ctx (oni_ft600_ctx ctx )
378388{
379- if (ctx -> inBuffer != NULL ) free (ctx -> inBuffer );
380- if (ctx -> auxBuffer != NULL ) free (ctx -> auxBuffer );
389+ FREE_AND_RELEASE (ctx -> regOperation );
390+ FREE_AND_RELEASE (ctx -> inBuffer );
391+ FREE_AND_RELEASE (ctx -> auxBuffer );
392+ FREE_AND_RELEASE (ctx -> regOperationBuffer );
381393 circBufferRelease (& ctx -> signalBuffer );
382394 circBufferRelease (& ctx -> regBuffer );
383395 if (ctx -> ftHandle != NULL )
@@ -398,8 +410,9 @@ void oni_ft600_free_ctx(oni_ft600_ctx ctx)
398410 for (unsigned int i = 0 ; i < ctx -> numInOverlapped ; i ++ )
399411 FT_ReleaseOverlapped (ctx -> ftHandle , & ctx -> inOverlapped [i ]);
400412 free (ctx -> inOverlapped );
413+ ctx -> inOverlapped = NULL ;
401414 }
402- if ( ctx -> inTransferred != NULL ) free (ctx -> inTransferred );
415+ FREE_AND_RELEASE (ctx -> inTransferred );
403416#ifdef POLL_CONTROL
404417 mutex_destroy (& ctx -> controlMutex );
405418#endif
@@ -563,6 +576,19 @@ int oni_driver_init(oni_driver_ctx driver_ctx, int host_idx)
563576 oni_ft600_free_ctx (ctx );
564577 return res ;
565578 }
579+ // get maxQ and allocate register buffer
580+ oni_reg_val_t val ;
581+ res = oni_driver_read_config (ctx , ONI_ATTR_MAX_REGISTER_Q_SIZE , & val );
582+ if (res != ONI_ESUCCESS ) {
583+ oni_ft600_free_ctx (ctx );
584+ return res ;
585+ }
586+ ctx -> maxRegOperation = val ;
587+ ctx -> regOperation = malloc (val * sizeof (oni_ft600_reg_operation_t ));
588+ CHECK_NULL (ctx -> regOperation );
589+ ctx -> regOperationBuffer = malloc (val * MAX_REG_OP_SIZE );
590+ CHECK_NULL (ctx -> regOperationBuffer );
591+
566592 ctx -> state = STATE_INIT ;
567593 return ONI_ESUCCESS ;
568594}
@@ -724,73 +750,127 @@ int oni_driver_write_stream(oni_driver_ctx driver_ctx,
724750 return size ;
725751}
726752
753+ int oni_driver_prepare_register_operation (oni_driver_ctx driver_ctx , size_t num )
754+ {
755+ CTX_CAST ;
756+ if (num > ctx -> maxRegOperation )
757+ return ONI_EINVALARG ;
758+ ctx -> regOperationIndex = 0 ;
759+ return ONI_ESUCCESS ;
760+ }
761+
762+ int oni_driver_commit_register_operation (oni_driver_ctx driver_ctx )
763+ {
764+ CTX_CAST ;
765+
766+ if (ctx -> regOperationIndex == 0 )
767+ return ONI_EINVALSTATE ;
768+
769+ size_t i = 0 ;
770+ for (size_t op = 0 ; op < ctx -> regOperationIndex ; op ++ )
771+ {
772+ ctx -> regOperationBuffer [(9 * i )] = CMD_WRITEREG ;
773+ * (uint32_t * )(ctx -> regOperationBuffer + 1 + (9 * i ))
774+ = (uint32_t )ONI_OP_RI_DEV_ADDR ;
775+ * (uint32_t * )(ctx -> regOperationBuffer + 5 + (9 * i ))
776+ = ctx -> regOperation [op ].dev_idx ;
777+ i ++ ;
778+ ctx -> regOperationBuffer [(9 * i )] = CMD_WRITEREG ;
779+ * (uint32_t * )(ctx -> regOperationBuffer + 1 + (9 * i ))
780+ = (uint32_t )ONI_OP_RI_REG_ADDR ;
781+ * (uint32_t * )(ctx -> regOperationBuffer + 5 + (9 * i ))
782+ = ctx -> regOperation [op ].dev_addr ;
783+ i ++ ;
784+ ctx -> regOperationBuffer [(9 * i )] = CMD_WRITEREG ;
785+ * (uint32_t * )(ctx -> regOperationBuffer + 1 + (9 * i ))
786+ = (uint32_t )ONI_OP_RI_RW ;
787+ * (uint32_t * )(ctx -> regOperationBuffer + 5 + (9 * i ))
788+ = ctx -> regOperation [op ].rw ;
789+ i ++ ;
790+ if (ctx -> regOperation [op ].rw ) {
791+ ctx -> regOperationBuffer [(9 * i )] = CMD_WRITEREG ;
792+ * (uint32_t * )(ctx -> regOperationBuffer + 1 + (9 * i ))
793+ = (uint32_t )ONI_OP_RI_REG_VAL ;
794+ * (uint32_t * )(ctx -> regOperationBuffer + 5 + (9 * i ))
795+ = ctx -> regOperation [op ].value ;
796+ i ++ ;
797+ }
798+ ctx -> regOperationBuffer [(9 * i )] = CMD_WRITEREG ;
799+ * (uint32_t * )(ctx -> regOperationBuffer + 1 + (9 * i ))
800+ = (uint32_t )ONI_OP_RI_TRIGGER ;
801+ * (uint32_t * )(ctx -> regOperationBuffer + 5 + (9 * i )) = 1 ;
802+ i ++ ;
803+ }
804+ size_t size = i * 9 ;
805+ ctx -> regOperationIndex = 0 ;
806+ int res = oni_ft600_sendcmd (ctx , ctx -> regOperationBuffer , size );
807+ if (res != ONI_ESUCCESS )
808+ return res ;
809+ return ONI_ESUCCESS ;
810+
811+ }
812+
813+ void oni_driver_cancel_register_operation (oni_driver_ctx driver_ctx )
814+ {
815+ CTX_CAST ;
816+ ctx -> regOperationIndex = 0 ;
817+ }
818+
727819int oni_driver_write_config (oni_driver_ctx driver_ctx ,
728820 oni_config_t reg ,
729821 oni_reg_val_t value )
730822{
731823 CTX_CAST ;
732- uint8_t buffer [45 ];
733- size_t size ;
734- //to avoid cluttering the USB interface will all the operations required for a device
735- //register access, we latch them together and send them in a single USB operation
736- if (reg == ONI_CONFIG_DEV_IDX )
824+ uint8_t buffer [9 ];
825+ size_t size = 9 ;
826+
827+ if (reg == ONI_OP_RI_DEV_ADDR )
737828 {
738- ctx -> regOperation .dev_idx = value ;
829+ if (ctx -> regOperationIndex >= ctx -> maxRegOperation )
830+ return ONI_EBUFFERSIZE ;
831+ ctx -> regOperation [ctx -> regOperationIndex ].dev_idx = value ;
739832 return ONI_ESUCCESS ;
740833 }
741- if (reg == ONI_CONFIG_REG_ADDR )
834+ if (reg == ONI_OP_RI_REG_ADDR )
742835 {
743- ctx -> regOperation .dev_addr = value ;
836+ if (ctx -> regOperationIndex >= ctx -> maxRegOperation )
837+ return ONI_EBUFFERSIZE ;
838+ ctx -> regOperation [ctx -> regOperationIndex ].dev_addr = value ;
744839 return ONI_ESUCCESS ;
745840 }
746- if (reg == ONI_CONFIG_REG_VALUE )
841+ if (reg == ONI_OP_RI_REG_VAL )
747842 {
748- ctx -> regOperation .value = value ;
843+ if (ctx -> regOperationIndex >= ctx -> maxRegOperation )
844+ return ONI_EBUFFERSIZE ;
845+ ctx -> regOperation [ctx -> regOperationIndex ].value = value ;
749846 return ONI_ESUCCESS ;
750847 }
751- if (reg == ONI_CONFIG_RW )
848+ if (reg == ONI_OP_RI_RW )
752849 {
753- ctx -> regOperation .rw = value ;
850+ if (ctx -> regOperationIndex >= ctx -> maxRegOperation )
851+ return ONI_EBUFFERSIZE ;
852+ ctx -> regOperation [ctx -> regOperationIndex ].rw = value ;
754853 return ONI_ESUCCESS ;
755854 }
756- if (reg == ONI_CONFIG_TRIG )
855+ if (reg == ONI_OP_RI_TRIGGER )
757856 {
758- size_t i = 0 ;
759- buffer [(9 * i )] = CMD_WRITEREG ;
760- * (uint32_t * )(buffer + 1 + (9 * i )) = _oni_register_offset (ONI_CONFIG_DEV_IDX );
761- * (uint32_t * )(buffer + 5 + (9 * i )) = ctx -> regOperation .dev_idx ;
762- i ++ ;
763- buffer [(9 * i )] = CMD_WRITEREG ;
764- * (uint32_t * )(buffer + 1 + (9 * i )) = _oni_register_offset (ONI_CONFIG_REG_ADDR );
765- * (uint32_t * )(buffer + 5 + (9 * i )) = ctx -> regOperation .dev_addr ;
766- i ++ ;
767- buffer [(9 * i )] = CMD_WRITEREG ;
768- * (uint32_t * )(buffer + 1 + (9 * i )) = _oni_register_offset (ONI_CONFIG_RW );
769- * (uint32_t * )(buffer + 5 + (9 * i )) = ctx -> regOperation .rw ;
770- i ++ ;
771- if (ctx -> regOperation .rw )
772- {
773- buffer [(9 * i )] = CMD_WRITEREG ;
774- * (uint32_t * )(buffer + 1 + (9 * i )) = _oni_register_offset (ONI_CONFIG_REG_VALUE );
775- * (uint32_t * )(buffer + 5 + (9 * i )) = ctx -> regOperation .value ;
776- i ++ ;
777- }
778- buffer [(9 * i )] = CMD_WRITEREG ;
779- * (uint32_t * )(buffer + 1 + (9 * i )) = _oni_register_offset (ONI_CONFIG_TRIG );
780- * (uint32_t * )(buffer + 5 + (9 * i )) = 1 ;
781- i ++ ;
782- size = i * 9 ;
857+ if (ctx -> regOperationIndex >= ctx -> maxRegOperation )
858+ return ONI_EBUFFERSIZE ;
859+ ctx -> regOperationIndex ++ ;
860+ return ONI_ESUCCESS ;
783861 }
784862 else
785863 {
786864 buffer [0 ] = CMD_WRITEREG ;
787- * (uint32_t * )(buffer + 1 ) = _oni_register_offset ( reg ) ;
865+ * (uint32_t * )(buffer + 1 ) = ( uint32_t ) reg ;
788866 * (uint32_t * )(buffer + 5 ) = value ;
789- size = 9 ;
790867 }
791868
792- if (reg == ONI_CONFIG_RESET && value != 0 )
869+ if (reg == ONI_OP_SOFT_RESET && value != 0 )
793870 {
871+ // NB: this cannot be on the callback because in this case
872+ // we want to stop acquisition on the driver level before
873+ // issuing the soft reset
794874 oni_ft600_stop_acq (ctx );
795875 }
796876 int res = oni_ft600_sendcmd (ctx , buffer , size );
@@ -803,7 +883,7 @@ int oni_driver_read_config(oni_driver_ctx driver_ctx, oni_config_t reg, oni_reg_
803883 CTX_CAST ;
804884 uint8_t buffer [5 ];
805885 buffer [0 ] = CMD_READREG ;
806- * (uint32_t * )(buffer + 1 ) = _oni_register_offset ( reg ) ;
886+ * (uint32_t * )(buffer + 1 ) = ( uint32_t ) reg ;
807887 int res = oni_ft600_sendcmd (ctx , buffer , 5 );
808888 if (res != ONI_ESUCCESS ) return res ;
809889
@@ -935,32 +1015,5 @@ const oni_driver_info_t* oni_driver_info(void)
9351015 return & driverInfo ;
9361016}
9371017
938- static inline oni_conf_off_t _oni_register_offset (oni_config_t reg )
939- {
940- switch (reg ) {
941- case ONI_CONFIG_DEV_IDX :
942- return CONFDEVIDXOFFSET ;
943- case ONI_CONFIG_REG_ADDR :
944- return CONFADDROFFSET ;
945- case ONI_CONFIG_REG_VALUE :
946- return CONFVALUEOFFSET ;
947- case ONI_CONFIG_RW :
948- return CONFRWOFFSET ;
949- case ONI_CONFIG_TRIG :
950- return CONFTRIGOFFSET ;
951- case ONI_CONFIG_RUNNING :
952- return CONFRUNNINGOFFSET ;
953- case ONI_CONFIG_RESET :
954- return CONFRESETOFFSET ;
955- case ONI_CONFIG_SYSCLKHZ :
956- return CONFSYSCLKHZOFFSET ;
957- case ONI_CONFIG_ACQCLKHZ :
958- return CONFACQCLKHZOFFSET ;
959- case ONI_CONFIG_RESETACQCOUNTER :
960- return CONFRESETACQCOUNTER ;
961- case ONI_CONFIG_HWADDRESS :
962- return CONFHWADDRESS ;
963- default :
964- return 0 ;
965- }
966- }
1018+
1019+
0 commit comments