* few discrete values, while setter routines accept any user specified
* rate that is supported by the hardware.
*/
-SR_PRIV const uint64_t samplerates[] = {
+static const uint64_t samplerates[] = {
/* 50MHz and integer divider. 1/2/5 steps (where possible). */
SR_KHZ(200), SR_KHZ(500),
SR_MHZ(1), SR_MHZ(2), SR_MHZ(5),
SR_MHZ(100), SR_MHZ(200),
};
-SR_PRIV const size_t samplerates_count = ARRAY_SIZE(samplerates);
+SR_PRIV GVariant *sigma_get_samplerates_list(void)
+{
+ return std_gvar_samplerates(samplerates, ARRAY_SIZE(samplerates));
+}
static const char *firmware_files[] = {
[SIGMA_FW_50MHZ] = "asix-sigma-50.fw", /* 50MHz, 8bit divider. */
#define SIGMA_FIRMWARE_SIZE_LIMIT (256 * 1024)
+static int sigma_ftdi_open(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ int vid, pid;
+ const char *serno;
+ int ret;
+
+ devc = sdi->priv;
+ if (!devc)
+ return SR_ERR_ARG;
+
+ if (devc->ftdi.is_open)
+ return SR_OK;
+
+ vid = devc->id.vid;
+ pid = devc->id.pid;
+ serno = sdi->serial_num;
+ if (!vid || !pid || !serno || !*serno)
+ return SR_ERR_ARG;
+
+ ret = ftdi_init(&devc->ftdi.ctx);
+ if (ret < 0) {
+ sr_err("Cannot initialize FTDI context (%d): %s.",
+ ret, ftdi_get_error_string(&devc->ftdi.ctx));
+ return SR_ERR_IO;
+ }
+ ret = ftdi_usb_open_desc_index(&devc->ftdi.ctx,
+ vid, pid, NULL, serno, 0);
+ if (ret < 0) {
+ sr_err("Cannot open device (%d): %s.",
+ ret, ftdi_get_error_string(&devc->ftdi.ctx));
+ return SR_ERR_IO;
+ }
+ devc->ftdi.is_open = TRUE;
+
+ return SR_OK;
+}
+
+static int sigma_ftdi_close(struct dev_context *devc)
+{
+ int ret;
+
+ ret = ftdi_usb_close(&devc->ftdi.ctx);
+ devc->ftdi.is_open = FALSE;
+ devc->ftdi.must_close = FALSE;
+ ftdi_deinit(&devc->ftdi.ctx);
+
+ return ret == 0 ? SR_OK : SR_ERR_IO;
+}
+
+SR_PRIV int sigma_check_open(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ int ret;
+
+ if (!sdi)
+ return SR_ERR_ARG;
+ devc = sdi->priv;
+ if (!devc)
+ return SR_ERR_ARG;
+
+ if (devc->ftdi.is_open)
+ return SR_OK;
+
+ ret = sigma_ftdi_open(sdi);
+ if (ret != SR_OK)
+ return ret;
+ devc->ftdi.must_close = TRUE;
+
+ return ret;
+}
+
+SR_PRIV int sigma_check_close(struct dev_context *devc)
+{
+ int ret;
+
+ if (!devc)
+ return SR_ERR_ARG;
+
+ if (devc->ftdi.must_close) {
+ ret = sigma_ftdi_close(devc);
+ if (ret != SR_OK)
+ return ret;
+ devc->ftdi.must_close = FALSE;
+ }
+
+ return SR_OK;
+}
+
+SR_PRIV int sigma_force_open(const struct sr_dev_inst *sdi)
+{
+ struct dev_context *devc;
+ int ret;
+
+ if (!sdi)
+ return SR_ERR_ARG;
+ devc = sdi->priv;
+ if (!devc)
+ return SR_ERR_ARG;
+
+ ret = sigma_ftdi_open(sdi);
+ if (ret != SR_OK)
+ return ret;
+ devc->ftdi.must_close = FALSE;
+
+ return SR_OK;
+}
+
+SR_PRIV int sigma_force_close(struct dev_context *devc)
+{
+ return sigma_ftdi_close(devc);
+}
+
/*
* BEWARE! Error propagation is important, as are kinds of return values.
*
{
int ret;
- ret = ftdi_read_data(&devc->ftdic, (unsigned char *)buf, size);
+ ret = ftdi_read_data(&devc->ftdi.ctx, (unsigned char *)buf, size);
if (ret < 0) {
sr_err("USB data read failed: %s",
- ftdi_get_error_string(&devc->ftdic));
+ ftdi_get_error_string(&devc->ftdi.ctx));
}
return ret;
{
int ret;
- ret = ftdi_write_data(&devc->ftdic, buf, size);
+ ret = ftdi_write_data(&devc->ftdi.ctx, buf, size);
if (ret < 0) {
sr_err("USB data write failed: %s",
- ftdi_get_error_string(&devc->ftdic));
+ ftdi_get_error_string(&devc->ftdi.ctx));
} else if ((size_t)ret != size) {
sr_err("USB data write length mismatch.");
}
* that's a programmer's error and needs adjustment in the complete call
* stack of the respective code path.
*/
+#define SIGMA_MAX_REG_DEPTH 32
+
+/*
+ * Implementor's note: The FPGA command set supports register access
+ * with automatic address adjustment. This operation is documented to
+ * wrap within a 16-address range, it cannot cross boundaries where the
+ * register address' nibble overflows. An internal helper assumes that
+ * callers remain within this auto-adjustment range, and thus multi
+ * register access requests can never exceed that count.
+ */
+#define SIGMA_MAX_REG_COUNT 16
+
SR_PRIV int sigma_write_register(struct dev_context *devc,
uint8_t reg, uint8_t *data, size_t len)
{
- uint8_t buf[80], *wrptr;
+ uint8_t buf[2 + SIGMA_MAX_REG_DEPTH * 2], *wrptr;
size_t idx;
- if (2 + 2 * len > sizeof(buf)) {
+ if (len > SIGMA_MAX_REG_DEPTH) {
sr_err("Short write buffer for %zu bytes to reg %u.", len, reg);
return SR_ERR_BUG;
}
wrptr = buf;
- write_u8_inc(&wrptr, REG_ADDR_LOW | (reg & 0xf));
- write_u8_inc(&wrptr, REG_ADDR_HIGH | (reg >> 4));
+ write_u8_inc(&wrptr, REG_ADDR_LOW | LO4(reg));
+ write_u8_inc(&wrptr, REG_ADDR_HIGH | HI4(reg));
for (idx = 0; idx < len; idx++) {
- write_u8_inc(&wrptr, REG_DATA_LOW | (data[idx] & 0xf));
- write_u8_inc(&wrptr, REG_DATA_HIGH_WRITE | (data[idx] >> 4));
+ write_u8_inc(&wrptr, REG_DATA_LOW | LO4(data[idx]));
+ write_u8_inc(&wrptr, REG_DATA_HIGH_WRITE | HI4(data[idx]));
}
return sigma_write_sr(devc, buf, wrptr - buf);
int ret;
wrptr = buf;
- write_u8_inc(&wrptr, REG_ADDR_LOW | (reg & 0xf));
- write_u8_inc(&wrptr, REG_ADDR_HIGH | (reg >> 4));
+ write_u8_inc(&wrptr, REG_ADDR_LOW | LO4(reg));
+ write_u8_inc(&wrptr, REG_ADDR_HIGH | HI4(reg));
write_u8_inc(&wrptr, REG_READ_ADDR);
ret = sigma_write_sr(devc, buf, wrptr - buf);
if (ret != SR_OK)
return sigma_read_sr(devc, data, len);
}
+static int sigma_get_register(struct dev_context *devc,
+ uint8_t reg, uint8_t *data)
+{
+ return sigma_read_register(devc, reg, data, sizeof(*data));
+}
+
+static int sigma_get_registers(struct dev_context *devc,
+ uint8_t reg, uint8_t *data, size_t count)
+{
+ uint8_t buf[2 + SIGMA_MAX_REG_COUNT], *wrptr;
+ size_t idx;
+ int ret;
+
+ if (count > SIGMA_MAX_REG_COUNT) {
+ sr_err("Short command buffer for %zu reg reads at %u.", count, reg);
+ return SR_ERR_BUG;
+ }
+
+ wrptr = buf;
+ write_u8_inc(&wrptr, REG_ADDR_LOW | LO4(reg));
+ write_u8_inc(&wrptr, REG_ADDR_HIGH | HI4(reg));
+ for (idx = 0; idx < count; idx++)
+ write_u8_inc(&wrptr, REG_READ_ADDR | REG_ADDR_INC);
+ ret = sigma_write_sr(devc, buf, wrptr - buf);
+ if (ret != SR_OK)
+ return ret;
+
+ return sigma_read_sr(devc, data, count);
+}
+
static int sigma_read_pos(struct dev_context *devc,
uint32_t *stoppos, uint32_t *triggerpos, uint8_t *mode)
{
- /*
- * Read 7 registers starting at trigger position LSB.
- * Which yields two 24bit counter values, and mode flags.
- */
- const uint8_t buf[] = {
- /* Setup first register address. */
- REG_ADDR_LOW | READ_TRIGGER_POS_LOW,
- /* Retrieve trigger position. */
- REG_READ_ADDR | REG_ADDR_INC,
- REG_READ_ADDR | REG_ADDR_INC,
- REG_READ_ADDR | REG_ADDR_INC,
- /* Retrieve stop position. */
- REG_READ_ADDR | REG_ADDR_INC,
- REG_READ_ADDR | REG_ADDR_INC,
- REG_READ_ADDR | REG_ADDR_INC,
- /* Retrieve mode register. */
- REG_READ_ADDR | REG_ADDR_INC,
- }, *rdptr;
uint8_t result[7];
+ const uint8_t *rdptr;
uint32_t v32;
uint8_t v8;
int ret;
- ret = sigma_write_sr(devc, buf, sizeof(buf));
- if (ret != SR_OK)
- return ret;
-
- ret = sigma_read_sr(devc, result, sizeof(result));
+ /*
+ * Read 7 registers starting at trigger position LSB.
+ * Which yields two 24bit counter values, and mode flags.
+ */
+ ret = sigma_get_registers(devc, READ_TRIGGER_POS_LOW,
+ result, sizeof(result));
if (ret != SR_OK)
return ret;
static int sigma_read_dram(struct dev_context *devc,
uint16_t startchunk, size_t numchunks, uint8_t *data)
{
- uint8_t buf[128], *wrptr;
+ uint8_t buf[128], *wrptr, regval;
size_t chunk;
int sel, ret;
gboolean is_last;
/* Communicate DRAM start address (memory row, aka samples line). */
wrptr = buf;
- write_u8_inc(&wrptr, startchunk >> 8);
- write_u8_inc(&wrptr, startchunk & 0xff);
+ write_u16be_inc(&wrptr, startchunk);
ret = sigma_write_register(devc, WRITE_MEMROW, buf, wrptr - buf);
if (ret != SR_OK)
return ret;
for (chunk = 0; chunk < numchunks; chunk++) {
sel = chunk % 2;
is_last = chunk == numchunks - 1;
- if (!is_last)
- write_u8_inc(&wrptr, REG_DRAM_BLOCK | REG_DRAM_SEL_BOOL(!sel));
- write_u8_inc(&wrptr, REG_DRAM_BLOCK_DATA | REG_DRAM_SEL_BOOL(sel));
+ if (!is_last) {
+ regval = REG_DRAM_BLOCK | REG_DRAM_SEL_BOOL(!sel);
+ write_u8_inc(&wrptr, regval);
+ }
+ regval = REG_DRAM_BLOCK_DATA | REG_DRAM_SEL_BOOL(sel);
+ write_u8_inc(&wrptr, regval);
if (!is_last)
write_u8_inc(&wrptr, REG_DRAM_WAIT_ACK);
}
SR_PRIV int sigma_write_trigger_lut(struct dev_context *devc,
struct triggerlut *lut)
{
- int i;
+ int lut_addr;
uint8_t tmp[2];
uint16_t bit;
uint8_t buf[6], *wrptr, regval;
int ret;
/* Transpose the table and send to Sigma. */
- for (i = 0; i < 16; i++) {
- bit = 1 << i;
+ for (lut_addr = 0; lut_addr < 16; lut_addr++) {
+ bit = 1 << lut_addr;
tmp[0] = tmp[1] = 0;
wrptr = buf;
write_u8_inc(&wrptr, tmp[0]);
write_u8_inc(&wrptr, tmp[1]);
- ret = sigma_write_register(devc, WRITE_TRIGGER_SELECT, buf, wrptr - buf);
+ ret = sigma_write_register(devc, WRITE_TRIGGER_SELECT,
+ buf, wrptr - buf);
if (ret != SR_OK)
return ret;
- ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, 0x30 | i);
+ ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2,
+ TRGSEL2_RESET | TRGSEL2_LUT_WRITE |
+ (lut_addr & TRGSEL2_LUT_ADDR_MASK));
if (ret != SR_OK)
return ret;
}
/* Send the parameters */
wrptr = buf;
regval = 0;
- regval |= lut->params.selc << 6;
- regval |= lut->params.selpresc << 0;
+ regval |= (lut->params.selc & TRGSEL_SELC_MASK) << TRGSEL_SELC_SHIFT;
+ regval |= (lut->params.selpresc & TRGSEL_SELPRESC_MASK) << TRGSEL_SELPRESC_SHIFT;
write_u8_inc(&wrptr, regval);
regval = 0;
- regval |= lut->params.selinc << 6;
- regval |= lut->params.selres << 4;
- regval |= lut->params.sela << 2;
- regval |= lut->params.selb << 0;
+ regval |= (lut->params.selinc & TRGSEL_SELINC_MASK) << TRGSEL_SELINC_SHIFT;
+ regval |= (lut->params.selres & TRGSEL_SELRES_MASK) << TRGSEL_SELRES_SHIFT;
+ regval |= (lut->params.sela & TRGSEL_SELA_MASK) << TRGSEL_SELA_SHIFT;
+ regval |= (lut->params.selb & TRGSEL_SELB_MASK) << TRGSEL_SELB_SHIFT;
write_u8_inc(&wrptr, regval);
- write_u16le_inc(&wrptr, lut->params.cmpb);
- write_u16le_inc(&wrptr, lut->params.cmpa);
+ write_u16be_inc(&wrptr, lut->params.cmpb);
+ write_u16be_inc(&wrptr, lut->params.cmpa);
ret = sigma_write_register(devc, WRITE_TRIGGER_SELECT, buf, wrptr - buf);
if (ret != SR_OK)
return ret;
if (ret != SR_OK)
return ret;
g_usleep(10 * 1000);
- ftdi_usb_purge_buffers(&devc->ftdic);
+ ftdi_usb_purge_buffers(&devc->ftdi.ctx);
/*
* Wait until the FPGA asserts INIT_B. Check in a maximum number
*/
static int sigma_fpga_init_la(struct dev_context *devc)
{
- uint8_t buf[16], *wrptr;
+ uint8_t buf[20], *wrptr;
uint8_t data_55, data_aa, mode;
uint8_t result[3];
const uint8_t *rdptr;
wrptr = buf;
/* Read ID register. */
- write_u8_inc(&wrptr, REG_ADDR_LOW | (READ_ID & 0xf));
- write_u8_inc(&wrptr, REG_ADDR_HIGH | (READ_ID >> 4));
+ write_u8_inc(&wrptr, REG_ADDR_LOW | LO4(READ_ID));
+ write_u8_inc(&wrptr, REG_ADDR_HIGH | HI4(READ_ID));
write_u8_inc(&wrptr, REG_READ_ADDR);
/* Write 0x55 to scratch register, read back. */
data_55 = 0x55;
- write_u8_inc(&wrptr, REG_ADDR_LOW | (WRITE_TEST & 0xf));
- write_u8_inc(&wrptr, REG_DATA_LOW | (data_55 & 0xf));
- write_u8_inc(&wrptr, REG_DATA_HIGH_WRITE | (data_55 >> 4));
+ write_u8_inc(&wrptr, REG_ADDR_LOW | LO4(WRITE_TEST));
+ write_u8_inc(&wrptr, REG_ADDR_HIGH | HI4(WRITE_TEST));
+ write_u8_inc(&wrptr, REG_DATA_LOW | LO4(data_55));
+ write_u8_inc(&wrptr, REG_DATA_HIGH_WRITE | HI4(data_55));
write_u8_inc(&wrptr, REG_READ_ADDR);
/* Write 0xaa to scratch register, read back. */
data_aa = 0xaa;
- write_u8_inc(&wrptr, REG_ADDR_LOW | (WRITE_TEST & 0xf));
- write_u8_inc(&wrptr, REG_DATA_LOW | (data_aa & 0xf));
- write_u8_inc(&wrptr, REG_DATA_HIGH_WRITE | (data_aa >> 4));
+ write_u8_inc(&wrptr, REG_ADDR_LOW | LO4(WRITE_TEST));
+ write_u8_inc(&wrptr, REG_ADDR_HIGH | HI4(WRITE_TEST));
+ write_u8_inc(&wrptr, REG_DATA_LOW | LO4(data_aa));
+ write_u8_inc(&wrptr, REG_DATA_HIGH_WRITE | HI4(data_aa));
write_u8_inc(&wrptr, REG_READ_ADDR);
/* Initiate SDRAM initialization in mode register. */
mode = WMR_SDRAMINIT;
- write_u8_inc(&wrptr, REG_ADDR_LOW | (WRITE_MODE & 0xf));
- write_u8_inc(&wrptr, REG_DATA_LOW | (mode & 0xf));
- write_u8_inc(&wrptr, REG_DATA_HIGH_WRITE | (mode >> 4));
+ write_u8_inc(&wrptr, REG_ADDR_LOW | LO4(WRITE_MODE));
+ write_u8_inc(&wrptr, REG_ADDR_HIGH | HI4(WRITE_MODE));
+ write_u8_inc(&wrptr, REG_DATA_LOW | LO4(mode));
+ write_u8_inc(&wrptr, REG_DATA_HIGH_WRITE | HI4(mode));
/*
* Send the command sequence which contains 3 READ requests.
devc->state.state = SIGMA_CONFIG;
/* Set the cable to bitbang mode. */
- ret = ftdi_set_bitmode(&devc->ftdic, BB_PINMASK, BITMODE_BITBANG);
+ ret = ftdi_set_bitmode(&devc->ftdi.ctx, BB_PINMASK, BITMODE_BITBANG);
if (ret < 0) {
sr_err("Could not setup cable mode for upload: %s",
- ftdi_get_error_string(&devc->ftdic));
+ ftdi_get_error_string(&devc->ftdi.ctx));
return SR_ERR;
}
- ret = ftdi_set_baudrate(&devc->ftdic, BB_BITRATE);
+ ret = ftdi_set_baudrate(&devc->ftdi.ctx, BB_BITRATE);
if (ret < 0) {
sr_err("Could not setup bitrate for upload: %s",
- ftdi_get_error_string(&devc->ftdic));
+ ftdi_get_error_string(&devc->ftdi.ctx));
return SR_ERR;
}
}
/* Leave bitbang mode and discard pending input data. */
- ret = ftdi_set_bitmode(&devc->ftdic, 0, BITMODE_RESET);
+ ret = ftdi_set_bitmode(&devc->ftdi.ctx, 0, BITMODE_RESET);
if (ret < 0) {
sr_err("Could not setup cable mode after upload: %s",
- ftdi_get_error_string(&devc->ftdic));
+ ftdi_get_error_string(&devc->ftdi.ctx));
return SR_ERR;
}
- ftdi_usb_purge_buffers(&devc->ftdic);
+ ftdi_usb_purge_buffers(&devc->ftdi.ctx);
while (sigma_read_raw(devc, &pins, sizeof(pins)) > 0)
;
return SR_ERR_ARG;
}
+SR_PRIV uint64_t sigma_get_samplerate(const struct sr_dev_inst *sdi)
+{
+ /* TODO Retrieve value from hardware. */
+ (void)sdi;
+ return samplerates[0];
+}
+
SR_PRIV int sigma_set_samplerate(const struct sr_dev_inst *sdi)
{
struct dev_context *devc;
if (ret != SR_OK)
return ret;
do {
- ret = sigma_read_register(devc, READ_MODE,
- &modestatus, sizeof(modestatus));
+ ret = sigma_get_register(devc, READ_MODE, &modestatus);
if (ret != SR_OK) {
sr_err("Could not poll for post-trigger state.");
return FALSE;
SR_PRIV int sigma_build_basic_trigger(struct dev_context *devc,
struct triggerlut *lut)
{
- int i,j;
+ int i, j;
uint16_t masks[2];
memset(lut, 0, sizeof(*lut));