]> sigrok.org Git - libsigrok.git/blobdiff - src/hardware/kingst-la2016/protocol.c
kingst-la2016: rephrase manufacture date and device type support
[libsigrok.git] / src / hardware / kingst-la2016 / protocol.c
index a0de3be70c0982ea5bc7525a49069dfdc13bab39..609c8aa20517e9d4741134f85cd54f41072ec229 100644 (file)
 #define FPGA_FW_LA1016 "kingst-la1016-fpga.bitstream"
 #define FPGA_FW_LA1016A        "kingst-la1016a1-fpga.bitstream"
 
+/* Maximum device capabilities. May differ between models. */
 #define MAX_SAMPLE_RATE_LA2016 SR_MHZ(200)
 #define MAX_SAMPLE_RATE_LA1016 SR_MHZ(100)
 #define MAX_SAMPLE_DEPTH       10e9
 #define MAX_PWM_FREQ           SR_MHZ(20)
 #define PWM_CLOCK              SR_MHZ(200)     /* 200MHz for both LA2016 and LA1016 */
 
+/*
+ * Default device configuration. Must be applicable to any of the
+ * supported devices (no model specific default values yet). Specific
+ * firmware implementation details unfortunately won't let us detect
+ * and keep using previously configured values.
+ */
+#define LA2016_DFLT_SAMPLERATE SR_MHZ(100)
+#define LA2016_DFLT_SAMPLEDEPTH        (5 * 1000 * 1000)
+#define LA2016_DFLT_CAPT_RATIO 5 /* Capture ratio, in percent. */
+
+/* TODO
+ * What is the origin and motivation of that 128Mi literal? What is its
+ * unit? How does it relate to a device's hardware capabilities? How to
+ * map the 1GiB of RAM of an LA2016 (at 16 channels) to the 128Mi value?
+ * It cannot be sample count. Is it memory size in bytes perhaps?
+ */
+#define LA2016_PRE_MEM_LIMIT_BASE      (128 * 1024 * 1024)
+
 /* USB vendor class control requests, executed by the Cypress FX2 MCU. */
 #define CMD_FPGA_ENABLE        0x10
 #define CMD_FPGA_SPI   0x20    /* R/W access to FPGA registers via SPI. */
 #define REG_PWM1       0x70    /* Write config for user PWM1. */
 #define REG_PWM2       0x78    /* Write config for user PWM2. */
 
+/* Bit patterns to write to REG_RUN, setup run mode. */
+#define RUNMODE_HALT   0x00
+#define RUNMODE_RUN    0x03
+
 static int ctrl_in(const struct sr_dev_inst *sdi,
        uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
        void *data, uint16_t wLength)
@@ -85,8 +108,8 @@ static int ctrl_in(const struct sr_dev_inst *sdi,
 
        usb = sdi->conn;
 
-       if ((ret = libusb_control_transfer(
-                    usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
+       if ((ret = libusb_control_transfer(usb->devhdl,
+                    LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN,
                     bRequest, wValue, wIndex, (unsigned char *)data, wLength,
                     DEFAULT_TIMEOUT_MS)) != wLength) {
                sr_dbg("USB ctrl in: %d bytes, req %d val %#x idx %d: %s.",
@@ -109,8 +132,8 @@ static int ctrl_out(const struct sr_dev_inst *sdi,
 
        usb = sdi->conn;
 
-       if ((ret = libusb_control_transfer(
-                    usb->devhdl, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
+       if ((ret = libusb_control_transfer(usb->devhdl,
+                    LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT,
                     bRequest, wValue, wIndex, (unsigned char*)data, wLength,
                     DEFAULT_TIMEOUT_MS)) != wLength) {
                sr_dbg("USB ctrl out: %d bytes, req %d val %#x idx %d: %s.",
@@ -152,7 +175,7 @@ static int check_fpga_bitstream(const struct sr_dev_inst *sdi)
 
        sr_dbg("Checking operation of the FPGA bitstream.");
 
-       init_rsp = 0xff;
+       init_rsp = ~0;
        ret = ctrl_in(sdi, CMD_FPGA_INIT, 0x00, 0, &init_rsp, sizeof(init_rsp));
        if (ret != SR_OK || init_rsp != 0) {
                sr_dbg("FPGA init query failed, or unexpected response.");
@@ -253,7 +276,7 @@ static int upload_fpga_bitstream(const struct sr_dev_inst *sdi,
                if (len == 0)
                        break;
 
-               ret = libusb_bulk_transfer(usb->devhdl, 2,
+               ret = libusb_bulk_transfer(usb->devhdl, USB_EP_FPGA_BITSTREAM,
                        &block[0], len, &act_len, DEFAULT_TIMEOUT_MS);
                if (ret != 0) {
                        sr_dbg("Cannot write FPGA bitstream, block %#x len %d: %s.",
@@ -292,13 +315,13 @@ static int enable_fpga_bitstream(const struct sr_dev_inst *sdi)
                        cmd_resp);
                return SR_ERR;
        }
-       g_usleep(30000);
+       g_usleep(30 * 1000);
 
        if ((ret = ctrl_out(sdi, CMD_FPGA_ENABLE, 0x01, 0, NULL, 0)) != SR_OK) {
                sr_err("Cannot enable FPGA after bitstream upload.");
                return ret;
        }
-       g_usleep(40000);
+       g_usleep(40 * 1000);
 
        return SR_OK;
 }
@@ -335,12 +358,12 @@ static int set_threshold_voltage(const struct sr_dev_inst *sdi, float voltage)
        if (voltage >= 2.9) {
                duty_R79 = 0;           /* PWM off (0V). */
                duty_R56 = (uint16_t)(302 * voltage - 363);
-       } else if (voltage <= -0.4) {
-               duty_R79 = 0x02d7;      /* 72% duty cycle. */
-               duty_R56 = (uint16_t)(302 * voltage + 1090);
-       } else {
+       } else if (voltage > -0.4) {
                duty_R79 = 0x00f2;      /* 25% duty cycle. */
                duty_R56 = (uint16_t)(302 * voltage + 121);
+       } else {
+               duty_R79 = 0x02d7;      /* 72% duty cycle. */
+               duty_R56 = (uint16_t)(302 * voltage + 1090);
        }
 
        /* Clamp duty register values to sensible limits. */
@@ -404,7 +427,7 @@ static int set_pwm(const struct sr_dev_inst *sdi, uint8_t which,
 
        devc = sdi->priv;
 
-       if (which < 1 || which > 2) {
+       if (which < 1 || which > ARRAY_SIZE(CTRL_PWM)) {
                sr_err("Invalid PWM channel: %d.", which);
                return SR_ERR;
        }
@@ -444,10 +467,10 @@ static int set_defaults(const struct sr_dev_inst *sdi)
 
        devc = sdi->priv;
 
-       devc->capture_ratio = 5; /* percent */
+       devc->capture_ratio = LA2016_DFLT_CAPT_RATIO;
        devc->cur_channels = 0xffff;
-       devc->limit_samples = 5000000;
-       devc->cur_samplerate = SR_MHZ(100);
+       devc->limit_samples = LA2016_DFLT_SAMPLEDEPTH;
+       devc->cur_samplerate = LA2016_DFLT_SAMPLERATE;
 
        ret = set_threshold_voltage(sdi, devc->threshold_voltage);
        if (ret)
@@ -457,11 +480,11 @@ static int set_defaults(const struct sr_dev_inst *sdi)
        if (ret)
                return ret;
 
-       ret = set_pwm(sdi, 1, 1e3, 50);
+       ret = set_pwm(sdi, 1, SR_KHZ(1), 50);
        if (ret)
                return ret;
 
-       ret = set_pwm(sdi, 2, 100e3, 50);
+       ret = set_pwm(sdi, 2, SR_KHZ(100), 50);
        if (ret)
                return ret;
 
@@ -550,6 +573,12 @@ static int set_trigger_config(const struct sr_dev_inst *sdi)
        write_u32le_inc(&wrptr, cfg.enabled);
        write_u32le_inc(&wrptr, cfg.level);
        write_u32le_inc(&wrptr, cfg.high_or_falling);
+       /* TODO
+        * Comment on this literal 16. Origin, meaning? Cannot be the
+        * register offset, nor the transfer length. Is it a channels
+        * count that is relevant for 16 and 32 channel models? Is it
+        * an obsolete experiment?
+        */
        ret = ctrl_out(sdi, CMD_FPGA_SPI, REG_TRIGGER, 16, buf, wrptr - buf);
        if (ret != SR_OK) {
                sr_err("Cannot setup trigger configuration.");
@@ -570,7 +599,7 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
        uint8_t *wrptr;
 
        devc = sdi->priv;
-       total = 128 * 1024 * 1024;
+       total = LA2016_PRE_MEM_LIMIT_BASE;
 
        if (devc->cur_samplerate > devc->max_samplerate) {
                sr_err("Too high a sample rate: %" PRIu64 ".",
@@ -633,14 +662,20 @@ static int set_sample_config(const struct sr_dev_inst *sdi)
  */
 static uint16_t run_state(const struct sr_dev_inst *sdi)
 {
-       uint16_t state;
-       static uint16_t previous_state = 0;
+       static uint16_t previous_state;
+
        int ret;
+       uint16_t state;
+       uint8_t buff[sizeof(state)];
+       const uint8_t *rdptr;
+       const char *label;
 
-       if ((ret = ctrl_in(sdi, CMD_FPGA_SPI, REG_RUN, 0, &state, sizeof(state))) != SR_OK) {
+       if ((ret = ctrl_in(sdi, CMD_FPGA_SPI, REG_RUN, 0, buff, sizeof(state))) != SR_OK) {
                sr_err("Cannot read run state.");
                return ret;
        }
+       rdptr = buff;
+       state = read_u16le_inc(&rdptr);
 
        /*
         * Avoid flooding the log, only dump values as they change.
@@ -648,17 +683,19 @@ static uint16_t run_state(const struct sr_dev_inst *sdi)
         */
        if (state != previous_state) {
                previous_state = state;
-               if ((state & 0x0003) == 0x01) {
-                       sr_dbg("Run state: 0x%04x (%s).", state, "idle");
-               } else if ((state & 0x000f) == 0x02) {
-                       sr_dbg("Run state: 0x%04x (%s).", state,
-                               "pre-trigger sampling");
-               } else if ((state & 0x000f) == 0x0a) {
-                       sr_dbg("Run state: 0x%04x (%s).", state,
-                               "sampling, waiting for trigger");
-               } else if ((state & 0x000f) == 0x0e) {
-                       sr_dbg("Run state: 0x%04x (%s).", state,
-                               "post-trigger sampling");
+               if ((state & 0x3) == 0x1) {
+                       label = "idle";
+               } else if ((state & 0xf) == 0x2) {
+                       label = "pre-trigger sampling";
+               } else if ((state & 0xf) == 0xa) {
+                       label = "sampling, waiting for trigger";
+               } else if ((state & 0xf) == 0xe) {
+                       label = "post-trigger sampling";
+               } else {
+                       label = NULL;
+               }
+               if (label && *label) {
+                       sr_dbg("Run state: 0x%04x (%s).", state, label);
                } else {
                        sr_dbg("Run state: 0x%04x.", state);
                }
@@ -667,12 +704,23 @@ static uint16_t run_state(const struct sr_dev_inst *sdi)
        return state;
 }
 
-static int set_run_mode(const struct sr_dev_inst *sdi, uint8_t fast_blinking)
+static int la2016_has_triggered(const struct sr_dev_inst *sdi)
+{
+       uint16_t state;
+
+       state = run_state(sdi);
+       if ((state & 0x3) == 0x1)
+               return 1;
+
+       return 0;
+}
+
+static int set_run_mode(const struct sr_dev_inst *sdi, uint8_t mode)
 {
        int ret;
 
-       if ((ret = ctrl_out(sdi, CMD_FPGA_SPI, REG_RUN, 0, &fast_blinking, sizeof(fast_blinking))) != SR_OK) {
-               sr_err("Cannot configure run mode %d.", fast_blinking);
+       if ((ret = ctrl_out(sdi, CMD_FPGA_SPI, REG_RUN, 0, &mode, sizeof(mode))) != SR_OK) {
+               sr_err("Cannot configure run mode %d.", mode);
                return ret;
        }
 
@@ -704,9 +752,10 @@ static int get_capture_info(const struct sr_dev_inst *sdi)
                devc->info.n_rep_packets_before_trigger,
                devc->info.write_pos, devc->info.write_pos);
 
-       if (devc->info.n_rep_packets % 5) {
-               sr_warn("Unexpected packets count %lu, not a multiple of 5.",
-                       (unsigned long)devc->info.n_rep_packets);
+       if (devc->info.n_rep_packets % NUM_PACKETS_IN_CHUNK) {
+               sr_warn("Unexpected packets count %lu, not a multiple of %d.",
+                       (unsigned long)devc->info.n_rep_packets,
+                       NUM_PACKETS_IN_CHUNK);
        }
 
        return SR_OK;
@@ -753,7 +802,7 @@ SR_PRIV int la2016_start_acquisition(const struct sr_dev_inst *sdi)
 {
        int ret;
 
-       ret = set_run_mode(sdi, 3);
+       ret = set_run_mode(sdi, RUNMODE_RUN);
        if (ret != SR_OK)
                return ret;
 
@@ -764,7 +813,7 @@ static int la2016_stop_acquisition(const struct sr_dev_inst *sdi)
 {
        int ret;
 
-       ret = set_run_mode(sdi, 0);
+       ret = set_run_mode(sdi, RUNMODE_HALT);
        if (ret != SR_OK)
                return ret;
 
@@ -787,15 +836,6 @@ SR_PRIV int la2016_abort_acquisition(const struct sr_dev_inst *sdi)
        return SR_OK;
 }
 
-static int la2016_has_triggered(const struct sr_dev_inst *sdi)
-{
-       uint16_t state;
-
-       state = run_state(sdi);
-
-       return (state & 0x3) == 1;
-}
-
 static int la2016_start_retrieval(const struct sr_dev_inst *sdi,
        libusb_transfer_cb_fn cb)
 {
@@ -857,9 +897,9 @@ static int la2016_start_retrieval(const struct sr_dev_inst *sdi,
        }
 
        devc->transfer = libusb_alloc_transfer(0);
-       libusb_fill_bulk_transfer(
-               devc->transfer, usb->devhdl,
-               0x86, buffer, to_read,
+       libusb_fill_bulk_transfer(devc->transfer,
+               usb->devhdl, USB_EP_CAPTURE_DATA | LIBUSB_ENDPOINT_IN,
+               buffer, to_read,
                cb, (void *)sdi, DEFAULT_TIMEOUT_MS);
 
        if ((ret = libusb_submit_transfer(devc->transfer)) != 0) {
@@ -882,22 +922,23 @@ static void send_chunk(struct sr_dev_inst *sdi,
        unsigned int max_samples, n_samples, total_samples, free_n_samples;
        unsigned int i, j, k;
        int do_signal_trigger;
-       uint16_t *wp;
+       uint8_t *wp;
        const uint8_t *rp;
        uint16_t state;
        uint8_t repetitions;
+       uint8_t sample_buff[sizeof(state)];
 
        devc = sdi->priv;
 
-       logic.unitsize = 2;
+       logic.unitsize = sizeof(sample_buff);
        logic.data = devc->convbuffer;
 
        sr_packet.type = SR_DF_LOGIC;
        sr_packet.payload = &logic;
 
-       max_samples = devc->convbuffer_size / 2;
+       max_samples = devc->convbuffer_size / sizeof(sample_buff);
        n_samples = 0;
-       wp = (uint16_t *)devc->convbuffer;
+       wp = devc->convbuffer;
        total_samples = 0;
        do_signal_trigger = 0;
 
@@ -914,7 +955,7 @@ static void send_chunk(struct sr_dev_inst *sdi,
                                logic.length = n_samples * 2;
                                sr_session_send(sdi, &sr_packet);
                                n_samples = 0;
-                               wp = (uint16_t *)devc->convbuffer;
+                               wp = devc->convbuffer;
                                if (do_signal_trigger) {
                                        std_session_send_df_trigger(sdi);
                                        do_signal_trigger = 0;
@@ -923,8 +964,11 @@ static void send_chunk(struct sr_dev_inst *sdi,
 
                        state = read_u16le_inc(&rp);
                        repetitions = read_u8_inc(&rp);
-                       for (j = 0; j < repetitions; j++)
-                               *wp++ = state;
+                       write_u16le((void *)&sample_buff, state);
+                       for (j = 0; j < repetitions; j++) {
+                               memcpy(wp, sample_buff, logic.unitsize);
+                               wp += logic.unitsize;
+                       }
 
                        n_samples += repetitions;
                        total_samples += repetitions;
@@ -943,7 +987,7 @@ static void send_chunk(struct sr_dev_inst *sdi,
                (void)read_u8_inc(&rp); /* Skip sequence number. */
        }
        if (n_samples) {
-               logic.length = n_samples * 2;
+               logic.length = n_samples * logic.unitsize;
                sr_session_send(sdi, &sr_packet);
                if (do_signal_trigger) {
                        std_session_send_df_trigger(sdi);
@@ -984,9 +1028,9 @@ static void LIBUSB_CALL receive_transfer(struct libusb_transfer *transfer)
                        to_read = LA2016_USB_BUFSZ;
                else
                        to_read = (to_read + (LA2016_EP6_PKTSZ-1)) & ~(LA2016_EP6_PKTSZ-1);
-               libusb_fill_bulk_transfer(
-                       transfer, usb->devhdl,
-                       0x86, transfer->buffer, to_read,
+               libusb_fill_bulk_transfer(transfer,
+                       usb->devhdl, USB_EP_CAPTURE_DATA | LIBUSB_ENDPOINT_IN,
+                       transfer->buffer, to_read,
                        receive_transfer, (void *)sdi, DEFAULT_TIMEOUT_MS);
 
                if ((ret = libusb_submit_transfer(transfer)) == 0)
@@ -1062,7 +1106,9 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
        struct dev_context *devc;
        uint16_t state;
        uint8_t buf[8];
-       int16_t purchase_date_bcd[2];
+       const uint8_t *rdptr;
+       uint8_t date_yy, date_mm;
+       uint8_t dinv_yy, dinv_mm;
        uint8_t magic;
        const char *bitstream_fn;
        int ret;
@@ -1070,20 +1116,24 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
        devc = sdi->priv;
 
        /*
-        * Four EEPROM bytes at offset 0x20 are purchase year and month
-        * in BCD format, with 16bit complemented checksum. For example
-        * 20 04 df fb translates to 2020-04. This can help identify the
-        * age of devices when unknown magic numbers are seen.
+        * Four EEPROM bytes at offset 0x20 are the manufacturing date,
+        * year and month in BCD format, followed by inverted values for
+        * consistency checks. For example bytes 20 04 df fb translate
+        * to 2020-04. This information can help identify the vintage of
+        * devices when unknown magic numbers are seen.
         */
-       if ((ret = ctrl_in(sdi, CMD_EEPROM, 0x20, 0, purchase_date_bcd, sizeof(purchase_date_bcd))) != SR_OK) {
-               sr_err("Cannot read purchase date in EEPROM.");
+       ret = ctrl_in(sdi, CMD_EEPROM, 0x20, 0, buf, 4 * sizeof(uint8_t));
+       if (ret != SR_OK) {
+               sr_err("Cannot read manufacture date in EEPROM.");
        } else {
-               sr_dbg("Purchase date: 20%02hx-%02hx.",
-                       (purchase_date_bcd[0]) & 0xff,
-                       (purchase_date_bcd[0] >> 8) & 0xff);
-               if (purchase_date_bcd[0] != (0x0ffff & ~purchase_date_bcd[1])) {
-                       sr_err("Purchase date fails checksum test.");
-               }
+               rdptr = &buf[0];
+               date_yy = read_u8_inc(&rdptr);
+               date_mm = read_u8_inc(&rdptr);
+               dinv_yy = read_u8_inc(&rdptr);
+               dinv_mm = read_u8_inc(&rdptr);
+               sr_info("Manufacture date: 20%02hx-%02hx.", date_yy, date_mm);
+               if ((date_mm ^ dinv_mm) != 0xff || (date_yy ^ dinv_yy) != 0xff)
+                       sr_warn("Manufacture date fails checksum test.");
        }
 
        /*
@@ -1128,17 +1178,18 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
                sr_err("Cannot read EEPROM device identifier bytes.");
                return ret;
        }
-
-       magic = 0;
-       if (buf[0] == (0xff & ~buf[1])) {
+       if ((buf[0] ^ buf[1]) == 0xff) {
                /* Primary copy of magic passes complement check. */
+               sr_dbg("Using primary copy of device type magic number.");
                magic = buf[0];
-       } else if (buf[4] == (0xff & ~buf[5])) {
+       } else if ((buf[4] ^ buf[5]) == 0xff) {
                /* Backup copy of magic passes complement check. */
                sr_dbg("Using backup copy of device type magic number.");
                magic = buf[4];
+       } else {
+               sr_err("Cannot find consistent device type identification.");
+               magic = 0;
        }
-
        sr_dbg("Device type: magic number is %hhu.", magic);
 
        /* Select the FPGA bitstream depending on the model. */
@@ -1193,7 +1244,11 @@ SR_PRIV int la2016_init_device(const struct sr_dev_inst *sdi)
 
        sr_dbg("Device should be initialized.");
 
-       return set_defaults(sdi);
+       ret = set_defaults(sdi);
+       if (ret != SR_OK)
+               return ret;
+
+       return SR_OK;
 }
 
 SR_PRIV int la2016_deinit_device(const struct sr_dev_inst *sdi)