Update 'USB protocol'

Triss 2021-06-23 17:18:49 +00:00
parent bcd746541c
commit 5eb70f0e29
1 changed files with 121 additions and 11 deletions

@ -1,6 +1,6 @@
The USB interface is an FTDI FT240X ([datasheet](https://ftdichip.com/wp-content/uploads/2020/08/DS_FT240X.pdf)). While not explicitely supported by libftdi, you can still use it (libftdi will think it is an FT230X).
### `lsusb` output
## `lsusb` output
```
Bus 001 Device 061: ID 0403:7fd0 Future Technology Devices International, Ltd ScanaQuad SQ50
@ -67,9 +67,9 @@ Device Status: 0x0000
Note: the serial number matches the one on the sticker on the bottom of the plastic shell.
### Protocol
## Protocol
The device operates in two (or three, depending on how you count) operting modes: bootloader mode (and authenticated bootloader mode), and application mode. By default, the device starts in 'unauthenticated' bootloader mode.
The device operates in two (or three, depending on how you count) operting modes: bootloader mode (and authenticated bootloader mode), and application mode. On startup, the device starts in 'unauthenticated' bootloader mode.
In bootloader mode, you first have to send a magic number for the device (stored in the FT240X' EEPROM) to enable some functionality: when authenticated, in bootloader mode, you can access the Spartan-3AN's internal SPI flash, as well as maybe a few extra bits.
@ -77,9 +77,9 @@ You can switch to application mode (and back to bootloader mode) at any time, ho
A log of libftd2xx function calls from ScanaStudio, in various scenarios, is available [here](https://cloud.lain.faith/s/RpcBp89MA2LDqqY).
Commands are typically a one-byte command ID, followed by a variable amount of data bytes.
Commands are typically a one-byte command ID, followed by a variable amount of data bytes. These are sent through the FTDI USB interface (e.g. `ftdi_read_data`/`ftdi_write_data` using libftdi), they are not raw USB packets.
#### Mode-independent
### Mode-independent
* **`0xfd`: Get status/mode**
* Arguments: *fixed* `0x00 0x01 0x02 0xfe`
@ -93,8 +93,9 @@ Commands are typically a one-byte command ID, followed by a variable amount of d
* **`0x94`: Reset to bootloader mode**
* No arguments
* No response
* TODO: does this reset to authenticated or unauthenticated bootloader mode after already having authenticated once? (Doesn't matter that much in the end..)
#### Bootloader mode
### Bootloader mode
* **`0xf1`: Send unlock/authentication code**
* Arguments: 3 bytes from [FT240X EEPROM](FT240X-EEPROM) word locations `0x12:0x13`, followed by a *fixed* 23 zero bytes
@ -110,13 +111,122 @@ Commands are typically a one-byte command ID, followed by a variable amount of d
* Response: single byte result of the SPI operation (garbage if the byte transferred was meant as a write)
* Yes, SPI transfers are done byte-by-byte this way. For details on how to communicate with the Spartan-3AN internal flash, see [Xilinx docs (UG333)](https://www.xilinx.com/support/documentation/user_guides/ug333.pdf). See the "Example transfers" section below.
#### Application mode
### Application mode
TODO lol
* **`0xf0`: Start transaction**
* Arguments: one (sometimes two) transaction type byte(s)
* **`0x00`: Cancel ongoing capture/wait-for-trigger**
* **`0x01`: Start capture/wait for trigger**
* Response:
* 3-byte "trigger instant" (little-endian): this is the point at which the trigger happened, units are `MS1*16`. (That is, if the trigger happened at the very last sample, this value will be `MS1*16`. If it happens right in the middle, it'll be 50% of `MS1*16`.) (For `MS1`: see settings blob.)
* 1 status byte
* **`0x02`: Start generating an uploaded signal indefinitely**
* **`0x03`: Start capture/generate/wait for trigger in mixed mode**
* Response: same as `0xf0 0x01`
* **`0x05 0xf3`: Start uploading signal generator pattern to the logic analyzer**
* This command is immediately followed by the generator pattern data. For the size of this blob, see the description of the Settings blob.
* The extra `0xf3` byte seems to always be sent, so it's probably mandatory.
* **`0x06`: Start downloading captured signal data**
* Response: capture signal data. For the size of this blob, see the description of the Settings blob.
* **`0x07`: Start generating an uploaded signal *once***
* No response unless mentioned otherwise in the subtypes
* **`0xf1`: Send settings blob**
* Arguments: settings blob (see below)
* No response
* **`0xf4`: Send trigger step blobs**
* Arguments: as many trigger step blobs (32 bits each) as specified in the settings blob (see below for both).
* No response
#### Example transfers
#### Blob formats
##### Spartan-3AN internal SPI flash read ID and status
##### Settings
This blob is 24 bytes in size.
* **`0x00`**: Normally `0x01`, `0x09` means "scale trigger pulse widths to microseconds". No other values observed.
* **`0x01..0x02`**: Clock frequency (little-endian). Equal to 100000 divided by the frequency in kHz.
* **`0x03..0x04`**: Trigger pulse width scale (16-bit little-endian). Maximum `0x8008`. This value, multiplied by the minimum/maximum pulse width, should be equal to 4 times the product of the configured pulse width (in seconds) and the sample frequency (in Hz). That is: `settings.trigger_pulse_width * trigstep.pw_min = 4 * pw_in_s * samplefreq_in_hz`.
* **`0x05..0x07`**: Memory setting 1 (MS1): For a description, see below.
* **`0x08..0x0a`**: Memory setting 2 (MS2): For a description, see below.
* **`0x0b..0x0d`**: Memory setting 3 (MS3): For a description, see below.
* **`0x0e`**: Unknown, always zero.
* **`0x0f`**: Number of trigger steps.
* **`0x10`**: Unknown, always `0xf0`.
* **`0x11`**: Unknown, always `0x0f`.
* **`0x12`**: Channel output settings bitmap, see below.
* **`0x13..0x14`**: Voltage settings. See below.
* **`0x15`**: Unknown, always `0x32`.
* **`0x16`**: Capture mode flag. `0x01` in capture and mixed mode, `0x00` in generate mode.
* **`0x17`**: Generate mode flag. `0x01` in generate and mixed mode, `0x00` in capture mode.
__**Memory settings**__: These three fields are each 3-byte little-endian values:
1. `MS1` denotes the memory size used for storing captured signal data.
1. `MS2` denotes the total memory size used.
1. `MS3` configures the pre-trigger sample settings: `MS3 = MS1 * (1 - pre_trigger_samples)`, with `pre_trigger_samples` a float between 0 and 1 (0% pretrigger and 100% pretrigger).
*The most significant nybble of `MS3` is the complement of the high nybble of teh channel output settings bitmap (`0x12`), and should be masked out before doing memory size calculations.*
In capture mode, `MS1` and `MS2` are equal. In generator mode, `MS1` and `MS3` are zero while `MS2` denotes the size of the memory used for storing generator patterns. In mixed mode, `MS2` is the sum of `MS1` (the memory size used for captured data) and the memory size used for generator data.
The number of bytes received as capture data or sent as generator patterns, is equal to the numbers here, multiplied by two. That is, the `MSx` values are (most likely) in 16-bit units.
In 4-channel capture mode, the maximum memory size for the SQ50 seems to be `0x03d090`. This is equal to 1/4th of the sample frequency (in Hz) multiplied by the capture period (in seconds).
__**Channel output settings bitmap**__:
The low nybble of this byte is always `0xf`. For each channel, if the channel is configured as an output, the bit in the high nybble corresponding to the channel is 1, otherwise it is 0.
In other words, the byte value is `(chan-x-is-output ? 1 : 0) << (x+4))` ORed together for each channel `x` (0..3), ORed together with the constant `0x0f`.
__**Voltage settings**__:
| Voltage (V) | Before capturing | During capture |
| -----------:|:---------------- |:-------------- |
| 1.8 | `0x46 0x4b` | `0x46 0x1e` |
| 2.8 | `0x6e 0x4b` | `0x6e 0x2c` |
| 3.3 | `0x81 0x4b` | `0x81 0x46` |
| 3.6 | `0x8d 0x4b` | `0x8d 0x4f` |
| 5.0 | `0xc4 0x4b` | `0xc4 0x72` |
The first byte of the voltage is equal to `floor(voltage * 39.2)`. In idle mode, the second byte is always `0x4b`, but during a capture it varies, with an unknown logic behind it, increments are non-monotonous.
The default settings blob used seems to be `01 04 00 00 00 90 d0 03 90 d0 03 e8 6e f3 00 00 f0 0f 0f 81 4b 32 01 00`.
##### Trigger step
Every trigger step is 32 bits (4 bytes) in size. Unlike the above settings blob, this one does not distinguish different functionalities in different bytes as much. Therefore, we will represent it here as a single 32-bit bitmap. This bitmap is still sent as little-endian over the FTDI serial->FIFO USB protocol!
```
byte: .---------- 3 -----------.---------- 2 ------------.------------ 1 ------------.-------------------- 0 ----------------------.
bit : .31 .30.29 28 27 26 25 24'23 22 21. 20 .19.18 17 16'15 14 13 12 11 10. 9 . 8 . 7 . 6 . 5 . 4 . 3 . 2 . 1 . 0 .
+---+--+-----------------'--------+----+--+--------'-----------------+----+----+----+----+-----+-----+-----+-----+-----+-----+
field: |LVL|0 | pw_max ' |OVRL|0 | ' pw_min |IGN4|IGN3|IGN2|IGN1|NOMAX|NOMIN|HIRI4|HIRI3|HIRI2|HIRI1|
+---+--+-----------------'--------+----+--+--------'-----------------+----+----+----+----+-----+-----+-----+-----+-----+-----+
```
* 31: `LVL`: edge/level flag: edge-triggered (0) or level-triggered (1). Denotes whether this step is using edge-triggering. If so, only one channel may be marked as enabled/non-ignored.
* 30: Unknown, always 0.
* 29..21: `pw_max`: 9-bit (29..21 → 8..0) maximum pulse width setting. Unit configured in settings blob.
* 20: `OVRL`: level trigger override: when this bit is 1, the trigger should still be considered a level trigger, even if bit 31 says otherwise. Used in ScanaStudio for "logic triggers" only.
* 19: Unknown, always 0.
* 18..10: `pw_min`: 9-bit (18..10 → 8..0) minimum pulse width setting. Unit configured in settings blob.
* 9: `IGN4`: set to 1 to ignore channel 4 in this trigger step.
* 8: `IGN3`: set to 1 to ignore channel 3 in this trigger step.
* 7: `IGN2`: set to 1 to ignore channel 2 in this trigger step.
* 6: `IGN1`: set to 1 to ignore channel 1 in this trigger step.
* 5: `NOMAX`: set to 1 to disable/ignore the maximum pulse width setting.
* 4: `NOMIN`: set to 1 to disable/ignore the minimum pulse width setting.
* 3: `HIRI4`: set to 1 trigger on channel 4 high or rising, 0 for low or falling. (Edge or level depends on bits 31 and 20)
* 2: `HIRI3`: set to 1 trigger on channel 3 high or rising, 0 for low or falling. (Edge or level depends on bits 31 and 20)
* 1: `HIRI2`: set to 1 trigger on channel 2 high or rising, 0 for low or falling. (Edge or level depends on bits 31 and 20)
* 0: `HIRI1`: set to 1 trigger on channel 1 high or rising, 0 for low or falling. (Edge or level depends on bits 31 and 20)
```
### Example transfers
#### Spartan-3AN internal SPI flash read ID and status
```
Flash ID:
@ -132,7 +242,7 @@ Status:
Send 0x91,0x00, no read data
```
##### Spartan-3AN internal SPI flash dump
#### Spartan-3AN internal SPI flash dump
```
Send 0x90,0x00, no read data