From: Gerhard Sittig Date: Sat, 16 May 2020 08:23:15 +0000 (+0200) Subject: asix-sigma: rephrase firmware dependent param upload at acquisition start X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=419f10950500d37489db3e3842670ac49e3607e7;p=libsigrok.git asix-sigma: rephrase firmware dependent param upload at acquisition start The 100/200MHz supporting FPGA netlists differ in their register set from 50MHz netlists. Adjust the parameter download at acquisition start. Raise awareness of the "TriggerSelect" and "TriggerSelect2" difference (the former only exists in 50MHz netlists, the latter's meaning differs between firmware variants). "ClockSelect" semantics also differs between netlists. Stop sending four bytes to a register that is just one byte deep, channel selection happened to work by mere coincidence. Eliminate a few more magic numbers, unobfuscate respective code paths. Though some questions remain (trigger related, not a blocker for now, needs to get addressed later). --- diff --git a/src/hardware/asix-sigma/api.c b/src/hardware/asix-sigma/api.c index 140cbd83..2cc50611 100644 --- a/src/hardware/asix-sigma/api.c +++ b/src/hardware/asix-sigma/api.c @@ -380,9 +380,10 @@ static int config_list(uint32_t key, GVariant **data, static int dev_acquisition_start(const struct sr_dev_inst *sdi) { struct dev_context *devc; - struct clockselect_50 clockselect; + uint16_t pindis_mask; + uint8_t async, div; int triggerpin, ret; - uint8_t triggerselect; + uint8_t trigsel2; struct triggerinout triggerinout_conf; struct triggerlut lut; uint8_t regval, trgconf_bytes[2], clock_bytes[4], *wrptr; @@ -417,9 +418,10 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) if (ret != SR_OK) return ret; - triggerselect = 0; + trigsel2 = 0; if (devc->samplerate >= SR_MHZ(100)) { /* 100 and 200 MHz mode. */ + /* TODO Decipher the 0x81 magic number's purpose. */ ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, 0x81); if (ret != SR_OK) return ret; @@ -433,23 +435,28 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) } /* Set trigger pin and light LED on trigger. */ - triggerselect = TRGSEL2_LEDSEL1 | (triggerpin & 0x7); + trigsel2 = triggerpin & TRGSEL2_PINS_MASK; + trigsel2 |= TRGSEL2_LEDSEL1; /* Default rising edge. */ + /* TODO Documentation disagrees, bit set means _rising_ edge. */ if (devc->trigger.fallingmask) - triggerselect |= 1 << 3; + trigsel2 |= TRGSEL2_PINPOL_RISE; } else if (devc->samplerate <= SR_MHZ(50)) { - /* All other modes. */ + /* 50MHz firmware modes. */ + + /* Translate application specs to hardware perspective. */ ret = sigma_build_basic_trigger(devc, &lut); if (ret != SR_OK) return ret; + /* Communicate resulting register values to the device. */ ret = sigma_write_trigger_lut(devc, &lut); if (ret != SR_OK) return ret; - triggerselect = TRGSEL2_LEDSEL1 | TRGSEL2_LEDSEL0; + trigsel2 = TRGSEL2_LEDSEL1 | TRGSEL2_LEDSEL0; } /* Setup trigger in and out pins to default values. */ @@ -481,36 +488,42 @@ static int dev_acquisition_start(const struct sr_dev_inst *sdi) return ret; /* Leave trigger programming mode. */ - ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, triggerselect); + ret = sigma_set_register(devc, WRITE_TRIGGER_SELECT2, trigsel2); if (ret != SR_OK) return ret; - /* Set clock select register. */ - clockselect.async = 0; - clockselect.fraction = 1; /* Divider 1. */ - clockselect.disabled_channels = 0x0000; /* All channels enabled. */ - if (devc->samplerate == SR_MHZ(200)) { - /* Enable 4 channels. */ - clockselect.disabled_channels = 0xfff0; - } else if (devc->samplerate == SR_MHZ(100)) { - /* Enable 8 channels. */ - clockselect.disabled_channels = 0xff00; + /* + * Samplerate dependent clock and channels configuration. Some + * channels by design are not available at higher clock rates. + * Register layout differs between firmware variants (depth 1 + * with LSB channel mask above 50MHz, depth 4 with more details + * up to 50MHz). + * + * Derive a mask where bits are set for unavailable channels. + * Either send the single byte, or the full byte sequence. + */ + pindis_mask = ~((1UL << devc->num_channels) - 1); + if (devc->samplerate > SR_MHZ(50)) { + ret = sigma_set_register(devc, WRITE_CLOCK_SELECT, + pindis_mask & 0xff); } else { + wrptr = clock_bytes; + /* Select 50MHz base clock, and divider. */ + async = 0; + div = SR_MHZ(50) / devc->samplerate - 1; /* - * 50 MHz mode, or fraction thereof. The 50MHz reference - * can get divided by any integer in the range 1 to 256. - * Divider minus 1 gets written to the hardware. - * (The driver lists a discrete set of sample rates, but - * all of them fit the above description.) + * TODO Optionally use external clock. + * async[0] = 1 to enable external clock + * div[5] = 1 to select falling edge + * div[4] = 1 to select rising edge + * div[3:0] = 1..16 to select clock pin */ - clockselect.fraction = SR_MHZ(50) / devc->samplerate; + write_u8_inc(&wrptr, async); + write_u8_inc(&wrptr, div); + write_u16be_inc(&wrptr, pindis_mask); + ret = sigma_write_register(devc, WRITE_CLOCK_SELECT, + clock_bytes, wrptr - clock_bytes); } - wrptr = clock_bytes; - write_u8_inc(&wrptr, clockselect.async); - write_u8_inc(&wrptr, clockselect.fraction - 1); - write_u16be_inc(&wrptr, clockselect.disabled_channels); - count = wrptr - clock_bytes; - ret = sigma_write_register(devc, WRITE_CLOCK_SELECT, clock_bytes, count); if (ret != SR_OK) return ret; diff --git a/src/hardware/asix-sigma/protocol.c b/src/hardware/asix-sigma/protocol.c index d95d95bb..2aec141a 100644 --- a/src/hardware/asix-sigma/protocol.c +++ b/src/hardware/asix-sigma/protocol.c @@ -458,10 +458,13 @@ SR_PRIV int sigma_write_trigger_lut(struct dev_context *devc, 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 | + (i & TRGSEL2_LUT_ADDR_MASK)); if (ret != SR_OK) return ret; } @@ -1799,7 +1802,7 @@ static void add_trigger_function(enum triggerop oper, enum triggerfunc func, 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)); diff --git a/src/hardware/asix-sigma/protocol.h b/src/hardware/asix-sigma/protocol.h index e3a9d512..e017c6b5 100644 --- a/src/hardware/asix-sigma/protocol.h +++ b/src/hardware/asix-sigma/protocol.h @@ -124,6 +124,11 @@ enum sigma_read_register { READ_TEST = 15, }; +#define TRGSEL2_PINS_MASK (0x07 << 0) +#define TRGSEL2_PINPOL_RISE (1 << 3) +#define TRGSEL2_LUT_ADDR_MASK (0x0f << 0) +#define TRGSEL2_LUT_WRITE (1 << 4) +#define TRGSEL2_RESET (1 << 5) #define TRGSEL2_LEDSEL0 (1 << 6) #define TRGSEL2_LEDSEL1 (1 << 7) @@ -211,12 +216,6 @@ struct sigma_dram_line { } cluster[CLUSTERS_PER_ROW]; }; -struct clockselect_50 { - uint8_t async; - uint64_t fraction; - uint16_t disabled_channels; -}; - /* The effect of all these are still a bit unclear. */ struct triggerinout { uint8_t trgout_resistor_enable : 1;