Skip to content

Commit e95f1d1

Browse files
committed
Modify register interface and ft600 driver for oniv2
1 parent 5b7d755 commit e95f1d1

8 files changed

Lines changed: 530 additions & 224 deletions

File tree

api/liboni/drivers/ft600/circbuffer.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,13 @@ int circBufferInit(circ_buffer_t* buffer)
1010
return 1;
1111
}
1212

13-
void circBufferRelease(circ_buffer_t* buffer)
13+
void circBufferRelease(circ_buffer_t *buffer)
1414
{
15-
if (buffer->buffer != NULL) free(buffer->buffer);
15+
if (buffer->buffer != NULL)
16+
{
17+
free(buffer->buffer);
18+
buffer->buffer = NULL;
19+
}
1620
}
1721
int circBufferCanWrite(circ_buffer_t* buffer, size_t size)
1822
{

api/liboni/drivers/ft600/onidriver_ft600.c

Lines changed: 135 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -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

8286
typedef enum
8387
{
@@ -96,6 +100,13 @@ typedef enum
96100
const 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+
99110
struct 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

136145
typedef 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-
293300
inline 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

377387
void 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+
727819
int 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

Comments
 (0)