Kingst LA2016/Protocol

From sigrok
Jump to navigation Jump to search

Developer notes on internal Kingst LA2016 firmware operation

Developer note: These are details which were observed during protocol research, yet are considered "too deep" for the device page (which users will read to some degree), and neither fit the Info page (which is USB centric, lsusb level, not so much USB requests during firmware operation).

Observations of the LA2016 Internal SPI Bus

The software on the host PC controls the logic analyser capture settings by writing to a set of byte-wide control registers within the FPGA.
It contains around 60 registers which are accessed using the SPI bus between the FX2 MCU and the FPGA (see schematic on sigrok wiki page).
The SPI bus is configured with the FX2 as master and FPGA as slave. Every SPI transaction is two bytes and is framed by SPI CS (active low).
The first byte contains the register address and a READ/write bit. The second byte contains the data, which is either written to the
FPGA or read from it. Note that these transactions are all least significant bit first on the SPI bus, so your LA will need to
reverse the bit order to interpret correctly.

Capture status can be read from register address 0x00 and 0x01. After a capture has completed, information about the data location in SDRAM can
be read from addresses 0x10-0x1B. For other registers, reading is not implemented and they just read as 0xFF. Where reading is implemented, the
same address is used to access different registers based on read/write. For example, FPGA status is read from address 0x00 and 0x01 but writing 0x03
to address 0x00 starts an acquistion.

The FX2 MCU is simply acting as a 'dumb' gateway, translating USB requests for FPGA access into SPI bus requests. USB control OUT vendor class
transfers with bRequest of 0x20 will write to the FPGA registers, whereas IN transfers will read them. For example, a USB request to read two
bytes starting from address 0x00 would cause the FX2 to issue a SPI read for address 0x00 and then a read for address 0x01.

SPI bus activity during OEM software initialisation

   First byte is FPGA register address. The MSbit is set for READ transfers.
   |  Second byte is data being written or read
   |  |
   |  |
   80 FF   <-- Read RUN STATUS
   81 FF
   80 FF   <-- Read RUN STATUS
   81 FF
   68 3F   <-- Write SET INPUT THRESHOLD  
   69 02
   6A F2
   6B 00
   02 00  <-- Halt USER PWM outputs to begin settings change
   70 40  <-- USER PWM1 SETTINGS
   71 0D
   72 03
   73 00
   74 A0
   75 86
   76 01
   77 00
   78 D0  <-- USER PWM2 SETTINGS
   79 07
   7A 00
   7B 00
   7C E8
   7D 03
   7E 00
   7F 00
   02 03  <-- enable USER PWM outputs

SPI bus activity during capture sequence

OEM software with no triggers set does this to FPGA regs:

   First byte is FPGA register address. The MSbit is set for READ transfers.
   |  Second byte is data being written or read
   |  |
   |  |
   03 00  <-- Set capture mode to be "write to SDRAM", rather than stream mode (where reg 03 = 01)
   20 FF  <-- enable all 16 channels (change on any channel will cause new repetition packet)
   21 FF
   22 00  <-- no triggers active
   23 00
   24 00
   25 00
   26 00
   27 00
   28 00
   29 00
   2A 00
   2B 00
   2C 00
   2D 00
   2E 00
   2F 00
   10 40  <-- 32 bit total samples count request
   11 42
   12 0F
   13 00
   14 00  <-- always zero
   15 00  <-- 32 bit pre-trigger samples
   16 00
   17 00
   18 00
   19 00   <- always zero
   1A 00    <--|
   1B 00    <--These 3 bytes are pre_trigger_mem_bytes, see set_sample_config()
   1C 04    <--|
   1D C8  <-- Capture rate   1D is divisor LSbyte   200MHz / divisor - sample rate
   1E 00  <--                1E is divisor MSbyte
   1F 00
   00 03   <--- RUN now running the capture
   80 E2  Reading capture status every 100ms or so from register address 0x00 and 0x01
   81 85  The run_state values in order are:
           0x85E2: Pre-sampling (for samples before trigger position, e.g. half of samples when set at 50% capture ratio)
           0x85EA: Waiting for trigger
           0x85EE: Running
           0x85ED: Done
   80 EE  
   81 85  
   80 EE
   81 85  
   80 ED
   81 85
   Read 12 bytes from the FPGA registers starting at address 0x10 FPGA_REG_CTRL_BULK to get:
           32bit n_rep_packets
           32bit n_rep_packets_before_trigger
           32bit write_pos     
   90 xx
   91 xx
   92 xx
   93 xx
   94 xx     see capture_info() driver function
   95 xx    
   96 xx     xx == value depends on capture data
   97 xx
   98 xx
   99 xx
   9A xx
   9B xx
   FPGA_REG_UPLOAD  Write two 32 bit numbers, SDRAM start address and n bytes for bulk upload
   08 00
   09 00
   0A 00
   0B 00    values written are derived from the above info on capture data
   0C 20
   0D A9
   0E 61
   0F 00
   01 01  Write to start the transfer of capture data from SDRAM to FX2 fifos (issued by FX2 when it receives USB command 0x38 START BULK TRANSFER)
          3ms gap
   00 00  HALT capture engine