<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://sigrok.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Seventhguardian</id>
	<title>sigrok - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://sigrok.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Seventhguardian"/>
	<link rel="alternate" type="text/html" href="https://sigrok.org/wiki/Special:Contributions/Seventhguardian"/>
	<updated>2026-05-15T00:04:41Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.37.1</generator>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1453</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1453"/>
		<updated>2012-01-22T13:08:48Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Device reply description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Enable ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the other two bits contain other status info (?)&lt;br /&gt;
** [ (ignored) 0 (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
Bit description:&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Seems to be always set to 1 (?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4): The state of the control bit (1 &amp;lt;&amp;lt; 4): adc enabled (?).&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3): Set to 1 upon successful triggering.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Set to 1 when the trigger block is armed and the adc (1 &amp;lt;&amp;lt; 4) is also enabled (?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Set to 1 when the trigger block is armed but the adc (1 &amp;lt;&amp;lt; 4) is not (?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Seems to be the oposite of bit (1 &amp;lt;&amp;lt; 2) (?)&lt;br /&gt;
&lt;br /&gt;
* Ususal values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Trigger armed&lt;br /&gt;
** 0x3: Someone messed up and armed the trigger without enabling ctl bit (1 &amp;lt;&amp;lt; 4) (???)&lt;br /&gt;
** 0x1: Trigger not armed&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ (ignored) 1 (a5) (a4) (a3) (a2) (a1) (a0) ]&lt;br /&gt;
** (byte 1): [ (ignored) 1 (d1) (d0) (a9) (a8) (a7) (a6) ]&lt;br /&gt;
** (byte 2): [ (ignored) 1 (d7) (d6) (d5) (d4) (d3) (d2) ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1452</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1452"/>
		<updated>2012-01-22T12:53:49Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* STATUS ((1 &amp;lt;&amp;lt; 6) == 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Enable ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the other two bits contain other status info (?)&lt;br /&gt;
** [ (ignored) 0 (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
Bit description:&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Seems to be always set to 1 (?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4): The state of the control bit (1 &amp;lt;&amp;lt; 4): adc enabled (?).&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3): Set to 1 by the trigger block upon successful triggering.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Set to 1 by the trigger block when it is armed.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Rare state, seems to be set to 1 when something is messed up (?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Seems to be the oposite of bit (1 &amp;lt;&amp;lt; 2) (?)&lt;br /&gt;
&lt;br /&gt;
* Ususal values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Trigger armed&lt;br /&gt;
** 0x1: Trigger not armed&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ (ignored) 1 (a5) (a4) (a3) (a2) (a1) (a0) ]&lt;br /&gt;
** (byte 1): [ (ignored) 1 (d1) (d0) (a9) (a8) (a7) (a6) ]&lt;br /&gt;
** (byte 2): [ (ignored) 1 (d7) (d6) (d5) (d4) (d3) (d2) ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1451</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1451"/>
		<updated>2012-01-22T12:53:28Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Device reply description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Enable ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the other two bits contain other status info (?)&lt;br /&gt;
** [ &amp;lt;ignored&amp;gt; 0 (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
Bit description:&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Seems to be always set to 1 (?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4): The state of the control bit (1 &amp;lt;&amp;lt; 4): adc enabled (?).&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3): Set to 1 by the trigger block upon successful triggering.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Set to 1 by the trigger block when it is armed.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Rare state, seems to be set to 1 when something is messed up (?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Seems to be the oposite of bit (1 &amp;lt;&amp;lt; 2) (?)&lt;br /&gt;
&lt;br /&gt;
* Ususal values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Trigger armed&lt;br /&gt;
** 0x1: Trigger not armed&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ (ignored) 1 (a5) (a4) (a3) (a2) (a1) (a0) ]&lt;br /&gt;
** (byte 1): [ (ignored) 1 (d1) (d0) (a9) (a8) (a7) (a6) ]&lt;br /&gt;
** (byte 2): [ (ignored) 1 (d7) (d6) (d5) (d4) (d3) (d2) ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1450</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1450"/>
		<updated>2012-01-22T12:47:27Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers which don&amp;#039;t seem to change purpose (so far) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Enable ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (h)(??):&lt;br /&gt;
** [ (h3) (h2) (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
* Values for h(3:0):&lt;br /&gt;
** 0x2: The normal value upon startup, before any initialization. This is also the end result of reseting the ADC. (?)&lt;br /&gt;
** 0x3: Also accepted upon initialization by the mso19 app. The end result of writing to the DAC or arming the trigger. (?)&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Trigger armed&lt;br /&gt;
** 0x1: Trigger not armed&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ (ignored) 1 (a5) (a4) (a3) (a2) (a1) (a0) ]&lt;br /&gt;
** (byte 1): [ (ignored) 1 (d1) (d0) (a9) (a8) (a7) (a6) ]&lt;br /&gt;
** (byte 2): [ (ignored) 1 (d7) (d6) (d5) (d4) (d3) (d2) ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1449</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1449"/>
		<updated>2012-01-22T12:12:54Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* STATUS ((1 &amp;lt;&amp;lt; 6) == 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (h)(??):&lt;br /&gt;
** [ (h3) (h2) (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
* Values for h(3:0):&lt;br /&gt;
** 0x2: The normal value upon startup, before any initialization. This is also the end result of reseting the ADC. (?)&lt;br /&gt;
** 0x3: Also accepted upon initialization by the mso19 app. The end result of writing to the DAC or arming the trigger. (?)&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Trigger armed&lt;br /&gt;
** 0x1: Trigger not armed&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ (ignored) 1 (a5) (a4) (a3) (a2) (a1) (a0) ]&lt;br /&gt;
** (byte 1): [ (ignored) 1 (d1) (d0) (a9) (a8) (a7) (a6) ]&lt;br /&gt;
** (byte 2): [ (ignored) 1 (d7) (d6) (d5) (d4) (d3) (d2) ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1448</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1448"/>
		<updated>2012-01-22T11:51:16Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* STATUS ((1 &amp;lt;&amp;lt; 6) == 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (h)(??):&lt;br /&gt;
** [ (h3) (h2) (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
* Values for h(3:0):&lt;br /&gt;
** 0x2: The normal value upon startup, before any initialization. (?)&lt;br /&gt;
** 0x3: Also accepted upon initialization by the mso19 app. The common value after the initialization. (?)&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Trigger armed&lt;br /&gt;
** 0x1: Trigger not armed&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ (ignored) 1 (a5) (a4) (a3) (a2) (a1) (a0) ]&lt;br /&gt;
** (byte 1): [ (ignored) 1 (d1) (d0) (a9) (a8) (a7) (a6) ]&lt;br /&gt;
** (byte 2): [ (ignored) 1 (d7) (d6) (d5) (d4) (d3) (d2) ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1447</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1447"/>
		<updated>2012-01-22T00:42:13Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* STATUS ((1 &amp;lt;&amp;lt; 6) == 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (h)(??):&lt;br /&gt;
** [ (h3) (h2) (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
* Values for h(3:0):&lt;br /&gt;
** 0x2: The normal value upon startup, before any initialization. (?)&lt;br /&gt;
** 0x3: Also accepted upon initialization by the mso19 app. The common value after the initialization. (?)&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Armed but not triggered yet (?)&lt;br /&gt;
** 0x1: (?) That should be read on startup.. probably something like &amp;quot;not armed&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ (ignored) 1 (a5) (a4) (a3) (a2) (a1) (a0) ]&lt;br /&gt;
** (byte 1): [ (ignored) 1 (d1) (d0) (a9) (a8) (a7) (a6) ]&lt;br /&gt;
** (byte 2): [ (ignored) 1 (d7) (d6) (d5) (d4) (d3) (d2) ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1446</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1446"/>
		<updated>2012-01-22T00:41:56Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* DATA ((1 &amp;lt;&amp;lt; 6) == 1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (h)(??):&lt;br /&gt;
** (1): [ (h3) (h2) (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
* Values for h(3:0):&lt;br /&gt;
** 0x2: The normal value upon startup, before any initialization. (?)&lt;br /&gt;
** 0x3: Also accepted upon initialization by the mso19 app. The common value after the initialization. (?)&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Armed but not triggered yet (?)&lt;br /&gt;
** 0x1: (?) That should be read on startup.. probably something like &amp;quot;not armed&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ (ignored) 1 (a5) (a4) (a3) (a2) (a1) (a0) ]&lt;br /&gt;
** (byte 1): [ (ignored) 1 (d1) (d0) (a9) (a8) (a7) (a6) ]&lt;br /&gt;
** (byte 2): [ (ignored) 1 (d7) (d6) (d5) (d4) (d3) (d2) ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1445</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1445"/>
		<updated>2012-01-22T00:40:45Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* STATUS ((1 &amp;lt;&amp;lt; 6) == 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (h)(??):&lt;br /&gt;
** (1): [ (h3) (h2) (h1) (h0) (t3) (t2) (t1) (t0) ]&lt;br /&gt;
&lt;br /&gt;
* Values for h(3:0):&lt;br /&gt;
** 0x2: The normal value upon startup, before any initialization. (?)&lt;br /&gt;
** 0x3: Also accepted upon initialization by the mso19 app. The common value after the initialization. (?)&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Armed but not triggered yet (?)&lt;br /&gt;
** 0x1: (?) That should be read on startup.. probably something like &amp;quot;not armed&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;a5&amp;gt; &amp;lt;a4&amp;gt; &amp;lt;a3&amp;gt; &amp;lt;a2&amp;gt; &amp;lt;a1&amp;gt; &amp;lt;a0&amp;gt; ]&lt;br /&gt;
** (byte 1): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d1&amp;gt; &amp;lt;d0&amp;gt; &amp;lt;a9&amp;gt; &amp;lt;a8&amp;gt; &amp;lt;a7&amp;gt; &amp;lt;a6&amp;gt; ]&lt;br /&gt;
** (byte 2): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d7&amp;gt; &amp;lt;d6&amp;gt; &amp;lt;d5&amp;gt; &amp;lt;d4&amp;gt; &amp;lt;d3&amp;gt; &amp;lt;d2&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1444</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1444"/>
		<updated>2012-01-22T00:40:06Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* STATUS ((1 &amp;lt;&amp;lt; 6) == 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (h)(??):&lt;br /&gt;
** (1): [ &amp;lt;h3&amp;gt; &amp;lt;h2&amp;gt; &amp;lt;h1&amp;gt; &amp;lt;h0&amp;gt; &amp;lt;t3&amp;gt; &amp;lt;t2&amp;gt; &amp;lt;t1&amp;gt; &amp;lt;t0&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
* Values for h(3:0):&lt;br /&gt;
** 0x2: The normal value upon startup, before any initialization. (?)&lt;br /&gt;
** 0x3: Also accepted upon initialization by the mso19 app. The common value after the initialization. (?)&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Armed but not triggered yet (?)&lt;br /&gt;
** 0x1: (?) That should be read on startup.. probably something like &amp;quot;not armed&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;a5&amp;gt; &amp;lt;a4&amp;gt; &amp;lt;a3&amp;gt; &amp;lt;a2&amp;gt; &amp;lt;a1&amp;gt; &amp;lt;a0&amp;gt; ]&lt;br /&gt;
** (byte 1): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d1&amp;gt; &amp;lt;d0&amp;gt; &amp;lt;a9&amp;gt; &amp;lt;a8&amp;gt; &amp;lt;a7&amp;gt; &amp;lt;a6&amp;gt; ]&lt;br /&gt;
** (byte 2): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d7&amp;gt; &amp;lt;d6&amp;gt; &amp;lt;d5&amp;gt; &amp;lt;d4&amp;gt; &amp;lt;d3&amp;gt; &amp;lt;d2&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1443</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1443"/>
		<updated>2012-01-22T00:29:23Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* STATUS ((1 &amp;lt;&amp;lt; 6) == 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (??):&lt;br /&gt;
** (1): [ &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;t3&amp;gt; &amp;lt;t2&amp;gt; &amp;lt;t1&amp;gt; &amp;lt;t0&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** 0x4: Armed but not triggered yet (?)&lt;br /&gt;
** 0x1: (?) That should be read on startup..&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;a5&amp;gt; &amp;lt;a4&amp;gt; &amp;lt;a3&amp;gt; &amp;lt;a2&amp;gt; &amp;lt;a1&amp;gt; &amp;lt;a0&amp;gt; ]&lt;br /&gt;
** (byte 1): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d1&amp;gt; &amp;lt;d0&amp;gt; &amp;lt;a9&amp;gt; &amp;lt;a8&amp;gt; &amp;lt;a7&amp;gt; &amp;lt;a6&amp;gt; ]&lt;br /&gt;
** (byte 2): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d7&amp;gt; &amp;lt;d6&amp;gt; &amp;lt;d5&amp;gt; &amp;lt;d4&amp;gt; &amp;lt;d3&amp;gt; &amp;lt;d2&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1442</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1442"/>
		<updated>2012-01-22T00:22:56Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Device reply description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (??):&lt;br /&gt;
** (1): [ &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;t3&amp;gt; &amp;lt;t2&amp;gt; &amp;lt;t1&amp;gt; &amp;lt;t0&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
** (?)&lt;br /&gt;
** 0x1: (?) That should be read on startup..&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;a5&amp;gt; &amp;lt;a4&amp;gt; &amp;lt;a3&amp;gt; &amp;lt;a2&amp;gt; &amp;lt;a1&amp;gt; &amp;lt;a0&amp;gt; ]&lt;br /&gt;
** (byte 1): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d1&amp;gt; &amp;lt;d0&amp;gt; &amp;lt;a9&amp;gt; &amp;lt;a8&amp;gt; &amp;lt;a7&amp;gt; &amp;lt;a6&amp;gt; ]&lt;br /&gt;
** (byte 2): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d7&amp;gt; &amp;lt;d6&amp;gt; &amp;lt;d5&amp;gt; &amp;lt;d4&amp;gt; &amp;lt;d3&amp;gt; &amp;lt;d2&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1441</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1441"/>
		<updated>2012-01-22T00:22:40Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* STATUS ((1 &amp;lt;&amp;lt; 6) == 0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status (t), while the upper nibble contains the hardware status (??):&lt;br /&gt;
** (1): [ &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;?&amp;gt; &amp;lt;t3&amp;gt; &amp;lt;t2&amp;gt; &amp;lt;t1&amp;gt; &amp;lt;t0&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
* Values for t(3:0):&lt;br /&gt;
** 0x6: Triggered (data ready on the samples buffer).&lt;br /&gt;
(?)&lt;br /&gt;
** 0x1: (?) That should be read on startup..&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;a5&amp;gt; &amp;lt;a4&amp;gt; &amp;lt;a3&amp;gt; &amp;lt;a2&amp;gt; &amp;lt;a1&amp;gt; &amp;lt;a0&amp;gt; ]&lt;br /&gt;
** (byte 1): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d1&amp;gt; &amp;lt;d0&amp;gt; &amp;lt;a9&amp;gt; &amp;lt;a8&amp;gt; &amp;lt;a7&amp;gt; &amp;lt;a6&amp;gt; ]&lt;br /&gt;
** (byte 2): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d7&amp;gt; &amp;lt;d6&amp;gt; &amp;lt;d5&amp;gt; &amp;lt;d4&amp;gt; &amp;lt;d3&amp;gt; &amp;lt;d2&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1440</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1440"/>
		<updated>2012-01-22T00:05:24Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device reply description ==&lt;br /&gt;
&lt;br /&gt;
* After writing 0x0 to the registers (1) or (2) of bank 0, the device replies with either 3072 bytes (1), or 1 byte (2).&lt;br /&gt;
* Only 7 bits are used from each byte.&lt;br /&gt;
* Bit (1 &amp;lt;&amp;lt; 6) indicates which type of message this is:&lt;br /&gt;
** 0: This is a &amp;quot;status&amp;quot; message.&lt;br /&gt;
** 1: This is a &amp;quot;data&amp;quot; message.&lt;br /&gt;
&lt;br /&gt;
===== STATUS ((1 &amp;lt;&amp;lt; 6) == 0) =====&lt;br /&gt;
* The reply comprises just one byte. The lower nibble contains the trigger status, while the upper nibble contains the hardware status (??):&lt;br /&gt;
&lt;br /&gt;
** (1): &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== DATA ((1 &amp;lt;&amp;lt; 6) == 1) =====&lt;br /&gt;
* The reply is 24 bit aligned, and contains both the 10 bit analog sample data (a) and the 8 bit digital sample data (d).&lt;br /&gt;
* There&amp;#039;s a total of 3072 bytes, comprising 1024 samples.&lt;br /&gt;
* For each group of 24 bits (a &amp;quot;sample&amp;quot;):&lt;br /&gt;
** (byte 0): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;a5&amp;gt; &amp;lt;a4&amp;gt; &amp;lt;a3&amp;gt; &amp;lt;a2&amp;gt; &amp;lt;a1&amp;gt; &amp;lt;a0&amp;gt; ]&lt;br /&gt;
** (byte 1): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d1&amp;gt; &amp;lt;d0&amp;gt; &amp;lt;a9&amp;gt; &amp;lt;a8&amp;gt; &amp;lt;a7&amp;gt; &amp;lt;a6&amp;gt; ]&lt;br /&gt;
** (byte 2): [ &amp;lt;ignored&amp;gt; 1 &amp;lt;d7&amp;gt; &amp;lt;d6&amp;gt; &amp;lt;d5&amp;gt; &amp;lt;d4&amp;gt; &amp;lt;d3&amp;gt; &amp;lt;d2&amp;gt; ]&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1439</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1439"/>
		<updated>2012-01-21T23:38:42Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Device operation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Status&amp;quot; register (address 0 of bank 0). The returned value indicates the device status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application starts by checking the device status. It accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* It then resets the ADC, and checks for the device status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
(...)&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
Upon starting a capture, by hitting the &amp;quot;Go&amp;quot; button:&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them both.&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register), and waits for the serial reply.&lt;br /&gt;
&lt;br /&gt;
=== Handle Serial Reply ===&lt;br /&gt;
&lt;br /&gt;
* First the app checks how many bytes there are waiting on the serial port buffer. It only accepts two byte lengths, 3072 bytes and 1 byte.&lt;br /&gt;
* The app then checks if the first byte has bit 6 turned off ((byte &amp;amp; (1 &amp;lt;&amp;lt; 6)) == 0), and if it is, it assumes it&amp;#039;s a trigger status. Otherwise it assumes it&amp;#039;s sample data.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1438</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1438"/>
		<updated>2012-01-21T23:04:17Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;br /&gt;
&lt;br /&gt;
== Device operation ==&lt;br /&gt;
&lt;br /&gt;
The trigger status must be checked periodically, by writing 0 to the &amp;quot;Read Trigger Status&amp;quot; register (address 0 of bank 0). The returned value indicates the trigger (device?) status.&lt;br /&gt;
&lt;br /&gt;
=== Startup ===&lt;br /&gt;
&lt;br /&gt;
* The MSO19 application first checks for the trigger (device?) status upon startup, and accepts the values 0x21 or 0x31 as normal, before proceeding.&lt;br /&gt;
* The application then resets the ADC, and checks for the trigger (device?) status again, and also accepts the values 0x21 and 0x31 as normal.&lt;br /&gt;
&lt;br /&gt;
=== Capture Start ===&lt;br /&gt;
&lt;br /&gt;
* If the DSO or the DAC need to be configured, the app resets the FSM (finite state machine), and then configures them (both at the same time).&lt;br /&gt;
* If the PG needs to be configured, the app configures it.&lt;br /&gt;
* The app then arms the trigger system.&lt;br /&gt;
All is ready now.&lt;br /&gt;
* Finally the app issues a trigger check (writing 0 to the register).&lt;br /&gt;
&lt;br /&gt;
=== Capture Loop ===&lt;br /&gt;
&lt;br /&gt;
* Every time there&amp;#039;s data on the serial port, it can only be sampled data (3072 bytes long) or the status data (1 byte long). The app checks which kind of serial data the device sent, and acts appropriately.&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1435</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1435"/>
		<updated>2012-01-20T00:34:45Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for ((R15 &amp;amp; 0x3) == 0x0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 4 | 1 &amp;lt;&amp;lt; 3): Select the purpose of the &amp;quot;Output&amp;quot; connector:&lt;br /&gt;
*** 00 : Trigger pulse output&lt;br /&gt;
*** 01 : PWM DAC from the pattern generator buffer.&lt;br /&gt;
*** 10 : (?) never seen...&lt;br /&gt;
*** 11 : White noise&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1434</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1434"/>
		<updated>2012-01-20T00:21:36Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for ((R15 &amp;amp; 0x3) == 0x1) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 0): Continuous mode ? (only seems to be allowed for the waveform generator, not for the pattern generator. why?)&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1433</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1433"/>
		<updated>2012-01-19T23:16:53Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers which don&amp;#039;t seem to change purpose (so far) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1432</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1432"/>
		<updated>2012-01-19T23:04:17Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers which don&amp;#039;t seem to change purpose (so far) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 3): Force trigger (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1431</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1431"/>
		<updated>2012-01-19T22:59:56Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for ((R15 &amp;amp; 0x3) == 0x0) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 0 matter, those set to 1 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1429</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1429"/>
		<updated>2012-01-19T10:11:59Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* USB protocol */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1428</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1428"/>
		<updated>2012-01-19T10:11:13Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* USB protocol */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux.git;a=blob_plain;f=drivers/usb/serial/cp210x.c;hb=90a4c0f51e8e44111a926be6f4c87af3938a79c3 cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 3.2.1 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1427</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1427"/>
		<updated>2012-01-19T10:06:19Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 13 seems to depend on the value of the 2 lsbs of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x0) =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 6 | 1 &amp;lt;&amp;lt; 5): These hold the DSO/LA trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x1) =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for ((R15 &amp;amp; 0x3) == 0x2) =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL1 (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*CONTROL2 (15):&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1 | 1 &amp;lt;&amp;lt; 0): Control which register bank is selected for writing:&lt;br /&gt;
*** 00: The DSO and LA control bank is selected&lt;br /&gt;
*** 01: The PG (patern generator) control bank is selected&lt;br /&gt;
*** 10: The PT (protocol trigger) control bank is selected&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 5): Slow mode (?) (set for the low clock rates, probably enables a clock divider)&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1426</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1426"/>
		<updated>2012-01-18T00:05:10Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up matching everything (word set to 0x00, mask set to 0xff).&lt;br /&gt;
&lt;br /&gt;
The mask bytes have their bits set to 1 for &amp;quot;ignore&amp;quot;, and 0 for &amp;quot;match&amp;quot;. The protocol matching block simply doing something this for every bit i:&lt;br /&gt;
&lt;br /&gt;
matches[i] = (read[i] ^ word[i]) | mask[i]&lt;br /&gt;
&lt;br /&gt;
The final result is the and&amp;#039;ing of the resulting 32 bits.&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Hold the comparison words for the comparator.&lt;br /&gt;
* TRIG_WORD1 (1): &lt;br /&gt;
* TRIG_WORD2 (2): &lt;br /&gt;
* TRIG_WORD2 (3): &lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the comparator (bits set at 1 always produce a positive match)&lt;br /&gt;
* TRIG_MASK1 (5): &lt;br /&gt;
* TRIG_MASK2 (6): &lt;br /&gt;
* TRIG_MASK3 (7): &lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1425</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1425"/>
		<updated>2012-01-17T23:39:35Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTES:&lt;br /&gt;
* the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
* how does the hardware handle the start/stop conditions or the ack bit??&lt;br /&gt;
&lt;br /&gt;
The protocol matcher seems to be comprised of a 4 byte shift register. The serial bits are shifted in through the last byte comparator (word 3) and exit through the first byte comparator (word 0). This is why if the trigger is set up with less than 3 words, the first bytes are the ones that end up empty (word set to 0x00, mask set to 0xff)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff.&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1396</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1396"/>
		<updated>2012-01-14T11:44:04Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output one, and writing 0x0 makes it an input one (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1395</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1395"/>
		<updated>2012-01-14T01:50:03Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_IO (11):   In pattern write mode, writing 0x1 makes the instant an output moment, and writing 0x0 makes it an input moment (?)&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1394</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1394"/>
		<updated>2012-01-14T01:46:20Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF1 (7):&lt;br /&gt;
* SCOPE_TRIGGER_HOLDOFF2 (8): Store the trigger holdoff (delay between a triggering event and the trigger rearming).&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_NEXT (11): In pattern write mode, writing 0x1 advances the buffer to the next &amp;quot;instant&amp;quot;. After the last word, it is writen 0x0.&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1393</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1393"/>
		<updated>2012-01-14T01:29:09Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together...&lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_NEXT (11): In pattern write mode, writing 0x1 advances the buffer to the next &amp;quot;instant&amp;quot;. After the last word, it is writen 0x0.&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator. Set to 1 for pattern buffer writing mode.&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1392</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1392"/>
		<updated>2012-01-14T01:27:57Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5): The value of the LA byte that generates a trigger event (in that mode).&lt;br /&gt;
* LA_TRIGGER_MASK(6): The mask for the LA_TRIGGER (bits set to 1 matter, those set to 0 are ignored).&lt;br /&gt;
* SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together... &lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_NEXT (11): In pattern write mode, writing 0x1 advances the buffer to the next &amp;quot;instant&amp;quot;. After the last word, it is writen 0x0.&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1391</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1391"/>
		<updated>2012-01-14T01:25:55Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5):&lt;br /&gt;
* LA_TRIGGER_MASK(6):&lt;br /&gt;
* SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together... &lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_NEXT (11): In pattern write mode, writing 0x1 advances the buffer to the next &amp;quot;instant&amp;quot;. After the last word, it is writen 0x0.&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1390</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1390"/>
		<updated>2012-01-14T01:24:55Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5):&lt;br /&gt;
* LA_TRIGGER_MASK(6):&lt;br /&gt;
* SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* REG_PATGEN_CLOCK1 (2) :&lt;br /&gt;
* REG_PATGEN_CLOCK2 (3) : Stores the sample clock configuration. Not sure how these two bytes work together... &lt;br /&gt;
* REG_PATGEN_START_L (4):&lt;br /&gt;
* REG_PATGEN_START_H (5): The start address for the pattern generator buffer (1023 samples long). When writing to the buffer, it is set to 0.&lt;br /&gt;
* REG_PATGEN_END_L (6):&lt;br /&gt;
* REG_PATGEN_END_H (7): The end address for the pattern generator buffer (1023 samples long). When writing the buffer, it is set to 0x3ff. When in normal mode (to set the end of the output) it is writen as the end address minus 2 (probably due to the actual implementation details).&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (starts after a pulse in PATGEN_TRIG)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG (9): writen 0x1 and then 0x0, acts as a manual trigger to activate &amp;quot;stuff&amp;quot;.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, takes the word for the current &amp;quot;instant&amp;quot;.&lt;br /&gt;
* PATGEN_NEXT (11): In pattern write mode, writing 0x1 advances the buffer to the next &amp;quot;instant&amp;quot;. After the last word, it is writen 0x0.&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10): (not used?)&lt;br /&gt;
*TRIGGER_WIDTH(11): (not used?)&lt;br /&gt;
*DAC(12-13): (not used?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1389</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1389"/>
		<updated>2012-01-13T14:34:42Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5):&lt;br /&gt;
* LA_TRIGGER_MASK(6):&lt;br /&gt;
* SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* UNKNOWN (0):&lt;br /&gt;
* UNKNOWN (1):&lt;br /&gt;
* UNKNOWN (2):&lt;br /&gt;
* UNKNOWN (3):&lt;br /&gt;
* UNKNOWN (4):&lt;br /&gt;
* UNKNOWN (5):&lt;br /&gt;
* UNKNOWN (6):&lt;br /&gt;
* UNKNOWN (7):&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (pulse in register 9 (PATGEN_TRIG?)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG? (9): writen 0x1 and then 0x0 in several ocasions, seems to act as a trigger.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, it takes the word for the current sample. Not sure for other modes...&lt;br /&gt;
* TRIGGER_WIDTH (11): ?&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled bits, 0 for disabled bits)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10): (not used?)&lt;br /&gt;
*TRIGGER_WIDTH(11): (not used?)&lt;br /&gt;
*DAC(12-13): (not used?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1388</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1388"/>
		<updated>2012-01-13T14:33:38Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
* Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
* Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
* TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than TRIGGER_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than TRIGGER_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
* LA_TRIGGER(5):&lt;br /&gt;
* LA_TRIGGER_MASK(6):&lt;br /&gt;
* SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
* CLKRATE(9-10):&lt;br /&gt;
* TRIGGER_WIDTH (11): Stores the pulse width for the DSO pulse trigger, in sample units. Forced to be greater than 3 by the mso19 app.&lt;br /&gt;
* DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* UNKNOWN (0):&lt;br /&gt;
* UNKNOWN (1):&lt;br /&gt;
* UNKNOWN (2):&lt;br /&gt;
* UNKNOWN (3):&lt;br /&gt;
* UNKNOWN (4):&lt;br /&gt;
* UNKNOWN (5):&lt;br /&gt;
* UNKNOWN (6):&lt;br /&gt;
* UNKNOWN (7):&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (pulse in register 9 (PATGEN_TRIG?)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG? (9): writen 0x1 and then 0x0 in several ocasions, seems to act as a trigger.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, it takes the word for the current sample. Not sure for other modes...&lt;br /&gt;
* TRIGGER_WIDTH (11): ?&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled, 0 for disabled)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10): (not used?)&lt;br /&gt;
*TRIGGER_WIDTH(11): (not used?)&lt;br /&gt;
*DAC(12-13): (not used?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1387</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1387"/>
		<updated>2012-01-13T14:30:37Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 0 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
** bits [6:5] hold the trigger configuration:&lt;br /&gt;
*** 00 : DSO level trigger&lt;br /&gt;
*** 01 : DSO pulse trigger, width less than PULSE_WIDTH&lt;br /&gt;
*** 10 : DSO pulse trigger, width equal or greater than PULSE_WIDTH&lt;br /&gt;
*** 11 : LA combination trigger&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* UNKNOWN (0):&lt;br /&gt;
* UNKNOWN (1):&lt;br /&gt;
* UNKNOWN (2):&lt;br /&gt;
* UNKNOWN (3):&lt;br /&gt;
* UNKNOWN (4):&lt;br /&gt;
* UNKNOWN (5):&lt;br /&gt;
* UNKNOWN (6):&lt;br /&gt;
* UNKNOWN (7):&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (pulse in register 9 (PATGEN_TRIG?)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG? (9): writen 0x1 and then 0x0 in several ocasions, seems to act as a trigger.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, it takes the word for the current sample. Not sure for other modes...&lt;br /&gt;
* TRIGGER_WIDTH (11): ?&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled, 0 for disabled)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10): (not used?)&lt;br /&gt;
*TRIGGER_WIDTH(11): (not used?)&lt;br /&gt;
*DAC(12-13): (not used?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1386</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1386"/>
		<updated>2012-01-13T14:25:47Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* UNKNOWN (0):&lt;br /&gt;
* UNKNOWN (1):&lt;br /&gt;
* UNKNOWN (2):&lt;br /&gt;
* UNKNOWN (3):&lt;br /&gt;
* UNKNOWN (4):&lt;br /&gt;
* UNKNOWN (5):&lt;br /&gt;
* UNKNOWN (6):&lt;br /&gt;
* UNKNOWN (7):&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 3 | 1 &amp;lt;&amp;lt; 2):&lt;br /&gt;
*** 11 : Manual start (pulse in register 9 (PATGEN_TRIG?)&lt;br /&gt;
*** 10 : Start on MSO trigger&lt;br /&gt;
*** 01 : Start on MSO &amp;quot;Go&amp;quot; (MSO trigger arm)&lt;br /&gt;
*** 00 : Disabled&lt;br /&gt;
* PATGEN_TRIG? (9): writen 0x1 and then 0x0 in several ocasions, seems to act as a trigger.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, it takes the word for the current sample. Not sure for other modes...&lt;br /&gt;
* TRIGGER_WIDTH (11): ?&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled, 0 for disabled)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10): (not used?)&lt;br /&gt;
*TRIGGER_WIDTH(11): (not used?)&lt;br /&gt;
*DAC(12-13): (not used?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1385</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1385"/>
		<updated>2012-01-13T14:14:46Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 1 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* UNKNOWN (0):&lt;br /&gt;
* UNKNOWN (1):&lt;br /&gt;
* UNKNOWN (2):&lt;br /&gt;
* UNKNOWN (3):&lt;br /&gt;
* UNKNOWN (4):&lt;br /&gt;
* UNKNOWN (5):&lt;br /&gt;
* UNKNOWN (6):&lt;br /&gt;
* UNKNOWN (7):&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** other bits also used. Zero when disabled.. ??&lt;br /&gt;
* PATGEN_ARM? (9): writen 0x1 and then 0x0 in several ocasions. Investigate.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, it takes the word for the current sample. Not sure for other modes...&lt;br /&gt;
* TRIGGER_WIDTH (11): ?&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* PATTERN_MASK (13): Stores the output bit mask (1 for enabled, 0 for disabled)&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10): (not used?)&lt;br /&gt;
*TRIGGER_WIDTH(11): (not used?)&lt;br /&gt;
*DAC(12-13): (not used?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1384</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1384"/>
		<updated>2012-01-13T14:03:22Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 1 =====&lt;br /&gt;
&lt;br /&gt;
This mode seems to be used to configure the pattern generator.&lt;br /&gt;
&lt;br /&gt;
* UNKNOWN (0):&lt;br /&gt;
* UNKNOWN (1):&lt;br /&gt;
* UNKNOWN (2):&lt;br /&gt;
* UNKNOWN (3):&lt;br /&gt;
* UNKNOWN (4):&lt;br /&gt;
* UNKNOWN (5):&lt;br /&gt;
* UNKNOWN (6):&lt;br /&gt;
* UNKNOWN (7):&lt;br /&gt;
* PATGEN_CFG (8): Configures the pattern generator.&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 1): Enter pattern write mode.&lt;br /&gt;
** other bits also used. Zero when disabled.. ??&lt;br /&gt;
* PATGEN_ARM? (9): writen 0x1 and then 0x0 in several ocasions. Investigate.&lt;br /&gt;
* PATGEN_WORD (10): In pattern write mode, it takes the word for the current sample. Not sure for other modes...&lt;br /&gt;
* TRIGGER_WIDTH (11): ?&lt;br /&gt;
* PATGEN_LOOPS (12): Stores the number of loops for the pattern generator&lt;br /&gt;
* DAC2 (13): ?&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10): (not used?)&lt;br /&gt;
*TRIGGER_WIDTH(11): (not used?)&lt;br /&gt;
*DAC(12-13): (not used?)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1383</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1383"/>
		<updated>2012-01-13T00:31:09Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers for R15 == 2 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
&lt;br /&gt;
This mode is used to set the i2c or spi triggers.&lt;br /&gt;
NOTE: the difference between i2c and spi capture seems to be the TRIGGER_CFG_H bits (see R15 = 0)&lt;br /&gt;
&lt;br /&gt;
* TRIG_WORD0 (0): Holds the first word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_WORD1 (1): Holds the second word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (2): Holds the third word to be matched. Same as above.&lt;br /&gt;
* TRIG_WORD2 (3): Holds the fourth word to be matched. Same as above.&lt;br /&gt;
* TRIG_MASK0 (4): Holds the mask for the first word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_MASK1 (5): Holds the mask for the 2nd word.&lt;br /&gt;
* TRIG_MASK2 (6): Holds the mask for the 3d word.&lt;br /&gt;
* TRIG_MASK3 (7): Holds the mask for the 4th word.&lt;br /&gt;
* TRIG_SPI_MODE (8): Holds the SPI mode for triggering (valid modes 0, 1, 2, 3). Is set to 0 for I2C (not sure if mandatory)&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*TRIGGER_WIDTH(11): The trigger width in sample units (mso19 app forces the value to be greater than 3)&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1382</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1382"/>
		<updated>2012-01-13T00:15:44Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The purpose of registers 0 to 8 seems to depend on the value of register 15.&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 0 =====&lt;br /&gt;
&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
&lt;br /&gt;
===== Registers for R15 == 2 =====&lt;br /&gt;
* TRIG_I2C_WORD0 (0): Holds the first i2c word to be matched.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0 (match bus idle) and the mask is set to 0xff. See below.&lt;br /&gt;
* TRIG_I2C_WORD1 (1): Holds the second i2c word to be matched. Same as above.&lt;br /&gt;
* TRIG_I2C_WORD2 (2): Holds the third i2c word to be matched. Same as above.&lt;br /&gt;
* TRIG_I2C_WORD2 (3): Holds the fourth i2c word to be matched. Same as above.&lt;br /&gt;
* TRIG_I2C_MASK0 (4): Holds the mask for the first i2c word.&lt;br /&gt;
** If matching less than 4 words, this register is set to 0xff. This forces a match on a &amp;quot;bus idle&amp;quot; state.&lt;br /&gt;
** Could forcing the match to bus idle cause trouble whith packets too close together??&lt;br /&gt;
* TRIG_I2C_MASK1 (5): Holds the mask for the 2nd i2c word.&lt;br /&gt;
* TRIG_I2C_MASK2 (6): Holds the mask for the 3d i2c word.&lt;br /&gt;
* TRIG_I2C_MASK3 (7): Holds the mask for the 4th i2c word.&lt;br /&gt;
* UNKWNOWN_8 (8): This seems to be always set to zero... WHY?&lt;br /&gt;
&lt;br /&gt;
===== Registers which don&amp;#039;t seem to change purpose (so far) =====&lt;br /&gt;
&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*TRIGGER_WIDTH(11): The trigger width in sample units (mso19 app forces the value to be greater than 3)&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15): This should be renamed BANK perhaps!&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1381</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1381"/>
		<updated>2012-01-12T23:15:38Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
&lt;br /&gt;
The register purpose seem to depend upon the value of register 15.&lt;br /&gt;
&lt;br /&gt;
So far it seems that the following is valid for REG15 = 0 (NOTE: only checked for regs 1-4 so far):&lt;br /&gt;
&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4): &lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*TRIGGER_WIDTH(11): The trigger width in sample units (mso19 app forces the value to be greater than 3)&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15):&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1380</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1380"/>
		<updated>2012-01-12T22:42:41Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Serial protocol */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
**** The simplest explanation for the unused bits is that the device bus width is 7 bits (being a CPLD that is very acceptable).&lt;br /&gt;
**** The 2 special bits seem to be synchronization bits. 0x7e violates the conversion (high byte), and that may be used to reset the CPLD parser at the end of the packet.&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4):&lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*TRIGGER_WIDTH(11): The trigger width in sample units (mso19 app forces the value to be greater than 3)&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15):&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1379</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1379"/>
		<updated>2012-01-12T22:31:00Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4):&lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*TRIGGER_WIDTH(11): The trigger width in sample units (mso19 app forces the value to be greater than 3)&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15):&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1378</id>
		<title>Link Instruments MSO-19</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Link_Instruments_MSO-19&amp;diff=1378"/>
		<updated>2012-01-12T19:18:07Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: /* Registers description */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[File:MSO-19.JPG|thumb|right|Link Instruments MSO-19]]&lt;br /&gt;
[[File:MSO-19-naked.jpg|thumb|right|PCB Front]]&lt;br /&gt;
&lt;br /&gt;
The [http://www.linkinstruments.com/mso19.htm Link Instruments MSO-19] is a 2GSa/s oscilloscope, 200MSa/s logic analyzer, 100MSa/s pattern generator and a TDR. It is also extremely portable and is only $249 (including probe, clips, wires and software).&lt;br /&gt;
&lt;br /&gt;
See [[Link Instruments MSO-19/Info]] for more details (such as &amp;#039;&amp;#039;&amp;#039;lsusb -vvv&amp;#039;&amp;#039;&amp;#039; output) about the device.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.latticesemi.com/products/cpld/machxo/index.cfm Lattice MachXO LCMXO2280 PLD]&lt;br /&gt;
* [http://www.intersil.com/products/deviceinfo.asp?pn=KAD2710C-10 Kenet KAD2710C-10 10bit, 105MSPS ADC]&lt;br /&gt;
* [http://www.silabs.com/products/interface/usbtouart/Pages/usb-to-uart-bridge.aspx Silabs CP2103 USB to UART Bridge]&lt;br /&gt;
&lt;br /&gt;
== Original software ==&lt;br /&gt;
&lt;br /&gt;
Link Instruments ships the product with its &amp;#039;&amp;#039;FrontPanelTM Oscilloscope software&amp;#039;&amp;#039;. Software is for Windows only. Written in .NET (C#), without any kind of obfuscation, which makes it a real breeze to reverse engineer.&lt;br /&gt;
&lt;br /&gt;
== USB protocol ==&lt;br /&gt;
&lt;br /&gt;
It&amp;#039;s just serial-over-USB, supported by the Linux kernel through the &amp;#039;&amp;#039;&amp;#039;[http://git.kernel.org/?p=linux/kernel/git/torvalds/linux-2.6.git;a=blob;f=drivers/usb/serial/cp210x.c;h=8d7731dbf478f9592d8dff350374dc6375649c44;hb=HEAD cp210x]&amp;#039;&amp;#039;&amp;#039; driver, though as of Kernel 2.6.37 it needs to be patched to recognize the Link Instruments Vendor/Product ID (&amp;#039;&amp;#039;&amp;#039;3195:f190&amp;#039;&amp;#039;&amp;#039;).&lt;br /&gt;
&lt;br /&gt;
iSerial was exploited by Link Instruments to store hardware type, hardware revision, calibration quirks and the actual serial number.&lt;br /&gt;
*for an iSerial of 4294333650260000000 we have:&lt;br /&gt;
**42943 336 502 6 0 000000&lt;br /&gt;
***vbit = 42943 / 10000&lt;br /&gt;
***dacoffset = 336&lt;br /&gt;
***offsetrange = 502&lt;br /&gt;
***hwmodel = 6&lt;br /&gt;
***hwrev = 0&lt;br /&gt;
***serial number = 000000&lt;br /&gt;
&lt;br /&gt;
== Serial protocol ==&lt;br /&gt;
*Control message&lt;br /&gt;
**Fixed header: 0x40, 0x4c, 0x44, 0x53, 0x7e&lt;br /&gt;
**Variable size payload, 16bit aligned&lt;br /&gt;
***Looks like each 16bits of payload are a register write operation&lt;br /&gt;
***register writes are 4bits for addr, 8 bits for value, 2 unused bits and 2 bits im not sure what they are for :)&lt;br /&gt;
***.?12 AAAA .?34 5678&lt;br /&gt;
***Conversion is: ((v &amp;amp; 0x3f) | ((v &amp;amp; 0xc0) &amp;lt;&amp;lt; 6) | ((a &amp;amp; 0xf) &amp;lt;&amp;lt; 8) | (((v ^ 0x20) &amp;amp; 0x20) &amp;lt;&amp;lt; 1) | (((v ^ 0x80) &amp;amp; 0x80) &amp;lt;&amp;lt; 7))&lt;br /&gt;
***Byte order is big endian&lt;br /&gt;
**Fixed footer: 0x7e&lt;br /&gt;
&lt;br /&gt;
== Registers description ==&lt;br /&gt;
There is no way to read from registers, only write is possible.&lt;br /&gt;
*Read Sample buffer (1): Write 0 to this register to read the samples buffer.&lt;br /&gt;
*Read Trigger status (2): Write 0 to this register to read the trigger status.&lt;br /&gt;
*TRIGGER_CONFIG_L (3):&lt;br /&gt;
** lsbyte of the threshold value.&lt;br /&gt;
* TRIGGER_CONFIG_H (4):&lt;br /&gt;
** bits [1:0] hold the msbits of the threshold value&lt;br /&gt;
** (1 &amp;lt;&amp;lt; 2): Trigger on falling edge&lt;br /&gt;
*LA_TRIGGER(5):&lt;br /&gt;
*LA_TRIGGER_MASK(6):&lt;br /&gt;
*SCOPE_TRIGGER_THRESHOLD(7-8):&lt;br /&gt;
*CLKRATE(9-10):&lt;br /&gt;
*TRIGGER_WIDTH(11):&lt;br /&gt;
*DAC(12-13):&lt;br /&gt;
*CONTROL (14):&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 0): Reset SFM&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 4): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 6): Reset ADC (?)&lt;br /&gt;
**(1 &amp;lt;&amp;lt; 7): Led on/off&lt;br /&gt;
*SLOWMODE(15):&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1345</id>
		<title>Hardware driver API</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1345"/>
		<updated>2012-01-05T15:43:23Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: Fixed typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Every plugin is built as a shared library, dynamically loaded by the backend at startup. The plugin must define a structure as follows:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;sigrok.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 struct sr_device_plugin {&lt;br /&gt;
 	/* plugin-specific */&lt;br /&gt;
 	char *name;&lt;br /&gt;
 	char *longname;&lt;br /&gt;
 	int api_version;&lt;br /&gt;
 	int (*init) (const char *deviceinfo);&lt;br /&gt;
 	void (*cleanup) (void);&lt;br /&gt;
 &lt;br /&gt;
 	/* device-specific */&lt;br /&gt;
 	int (*opendev) (int device_index);&lt;br /&gt;
 	int (*closedev) (int device_index);&lt;br /&gt;
 	void *(*get_device_info) (int device_index, int device_info_id);&lt;br /&gt;
 	int (*get_status) (int device_index);&lt;br /&gt;
 	int *(*get_capabilities) (void);&lt;br /&gt;
 	int (*set_configuration) (int device_index, int capability, char *value);&lt;br /&gt;
 	int (*start_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 	void (*stop_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 #define SIGROK_HARDWARE_PLUGIN   struct device_plugin plugin_info&lt;br /&gt;
&lt;br /&gt;
This structure is the only symbol imported into the backend namespace. The plugin&amp;#039;s variables thus cannot conflict with the global sigrok namespace.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;name&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A short string describing this driver. It will be referenced in saved session files.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;longname&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A long string describing this driver. It will be shown to the user.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;api_version&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Currently defined as 1.&lt;br /&gt;
&lt;br /&gt;
The other members of the structure are pointers to plugin callbacks:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;init(const char *deviceinfo)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called when the plugin is initially loading into sigrok, typically at program start. The parameter refers to a device name or special file, whichever is applicable for the plugin. Devices which don&amp;#039;t need a supplied device, such as USB devices, can simply ignore this parameter. The function returns the number of devices found, and 0 if no suitable device was found. If a device was found, any initialization it needs must be performed here; for example, uploading firmware should be done here.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;cleanup()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called before the plugin is unloaded. Release any resources the plugin might be holding.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;opendev(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Open the specified device. The device index starts at 0. Returns SR_OK if successful, SR_ERR otherwise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;closedev(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Close the specified device. The device index starts at 0. Returns SR_OK if successful, SR_ERR otherwise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_device_info(int device_index, int device_info_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns information about the given device. The type of information is given as device_info_id, one of a set of defined constants. The return value is always a pointer, which points to information specific to the id.&lt;br /&gt;
** SR_DI_INSTANCE: Returns a pointer to a [[Formats_and_structures#device_instances|struct sigrok_device_instance]].&lt;br /&gt;
** SR_DI_NUM_PROBES: The number of probes connected to this device (integer).&lt;br /&gt;
** SR_DI_PROBE_NAMES: The probe names on this device (array of char*).&lt;br /&gt;
** SR_DI_SAMPLERATES: Returns a pointer to a [[Formats_and_structures#Sample_rates|struct samplerates]].&lt;br /&gt;
** SR_DI_TRIGGER_TYPES: Types of trigger supported, out of &amp;quot;01crf&amp;quot; (char *).&lt;br /&gt;
** SR_DI_CUR_SAMPLERATE: The currently set samplerate in Hz (uint64_t).&lt;br /&gt;
** SR_DI_PATTERNMODES: Supported pattern generator modes (array of char*).&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_status(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns an integer describing the status of the plugin&amp;#039;s connection to a device. This may be one of the following:&lt;br /&gt;
** SR_ST_NOT_FOUND: The device was not found.&lt;br /&gt;
** SR_ST_INITIALIZING: The device was found, but is still initializing.&lt;br /&gt;
** SR_ST_INACTIVE: The device is live, but not in use.&lt;br /&gt;
** SR_ST_ACTIVE: The device is currently in use.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_capabilities()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This function returns a zero-terminated integer array with the plugin&amp;#039;s capabilities, in the form of a set of defined constants. Some of these are informative, and some can be used to configure the plugin (or its connected device). The capabilities tables below have an overview of all possible capabilities.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;set_configuration(int device_index, int capability, char *value)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This is used to configure the plugin and/or connected device. The capability is one of the constants returned from the get_capabilities() call. The value depends on the parameter that is to be configured.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;start_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Start acquisition on the specified device. The session_device_id will be passed along with the data feed of this session, as the first parameter to session bus callbacks.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;stop_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Stop acquisition on the specified device. This causes a DF_END packet to be sent to the sesion bus.&lt;br /&gt;
&lt;br /&gt;
== Device classes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LOGIC_ANALYZER&lt;br /&gt;
: This device is a logic analyzer.&lt;br /&gt;
&lt;br /&gt;
== Device options ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_SAMPLERATE&lt;br /&gt;
: The sample rate in Hz (uint64_t *).&lt;br /&gt;
* HWCAP_PROBECONFIG&lt;br /&gt;
: Probe configuration (GSList *probes)&lt;br /&gt;
* HWCAP_CAPTURE_RATIO&lt;br /&gt;
: Pre-trigger capture ratio, as a percentage of the number of samples returned. The default is 0, meaning capturing only starts after the trigger fired  (uint64_t *).&lt;br /&gt;
* HWCAP_PATTERN_MODE&lt;br /&gt;
: Pattern to generate  (char **).&lt;br /&gt;
&lt;br /&gt;
== Acquisition modes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LIMIT_MSEC&lt;br /&gt;
: How long the acquisition should last, in ms (uint64_t).&lt;br /&gt;
* HWCAP_LIMIT_SAMPLES&lt;br /&gt;
: How many samples to acquire in the session (uint64_t).&lt;br /&gt;
* HWCAP_CONTINUOUS&lt;br /&gt;
: Device supports continuous sampling&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1343</id>
		<title>Hardware driver API</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1343"/>
		<updated>2012-01-05T15:41:33Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: Fixed status prefix&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Every plugin is built as a shared library, dynamically loaded by the backend at startup. The plugin must define a structure as follows:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;sigrok.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 struct sr_device_plugin {&lt;br /&gt;
 	/* plugin-specific */&lt;br /&gt;
 	char *name;&lt;br /&gt;
 	char *longname;&lt;br /&gt;
 	int api_version;&lt;br /&gt;
 	int (*init) (const char *deviceinfo);&lt;br /&gt;
 	void (*cleanup) (void);&lt;br /&gt;
 &lt;br /&gt;
 	/* device-specific */&lt;br /&gt;
 	int (*opendev) (int device_index);&lt;br /&gt;
 	int (*closedev) (int device_index);&lt;br /&gt;
 	void *(*get_device_info) (int device_index, int device_info_id);&lt;br /&gt;
 	int (*get_status) (int device_index);&lt;br /&gt;
 	int *(*get_capabilities) (void);&lt;br /&gt;
 	int (*set_configuration) (int device_index, int capability, char *value);&lt;br /&gt;
 	int (*start_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 	void (*stop_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 #define SIGROK_HARDWARE_PLUGIN   struct device_plugin plugin_info&lt;br /&gt;
&lt;br /&gt;
This structure is the only symbol imported into the backend namespace. The plugin&amp;#039;s variables thus cannot conflict with the global sigrok namespace.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;name&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A short string describing this driver. It will be referenced in saved session files.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;longname&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A long string describing this driver. It will be shown to the user.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;api_version&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Currently defined as 1.&lt;br /&gt;
&lt;br /&gt;
The other members of the structure are pointers to plugin callbacks:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;init(const char *deviceinfo)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called when the plugin is initially loading into sigrok, typically at program start. The parameter refers to a device name or special file, whichever is applicable for the plugin. Devices which don&amp;#039;t need a supplied device, such as USB devices, can simply ignore this parameter. The function returns the number of devices found, and 0 if no suitable device was found. If a device was found, any initialization it needs must be performed here; for example, uploading firmware should be done here.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;cleanup()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called before the plugin is unloaded. Release any resources the plugin might be holding.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;opendev(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Open the specified device. The device index starts at 0. Returns SR_OK if successful, SR_ERR otherwise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;closedev(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Close the specified device. The device index starts at 0. Returns SR_OK if successful, SR_ERR otherwise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_device_info(int device_index, int device_info_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns information about the given device. The type of information is given as device_info_id, one of a set of defined constants. The return value is always a pointer, which points to information specific to the id.&lt;br /&gt;
** SR_DI_INSTANCE: Returns a pointer to a [[Formats_and_structures#device_instances|struct sigrok_device_instance]].&lt;br /&gt;
** SR_DI_NUM_PROBES: The number of probes connected to this device (integer).&lt;br /&gt;
** SR_DI_PROBE_NAMES: The probe names on this device (array of char*).&lt;br /&gt;
** SR_DI_SAMPLERATES: Returns a pointer to a [[Formats_and_structures#Sample_rates|struct samplerates]].&lt;br /&gt;
** SR_DI_TRIGGER_TYPES: Types of trigger supported, out of &amp;quot;01crf&amp;quot; (char *).&lt;br /&gt;
** SR_DI_CUR_SAMPLERATE: The currently set samplerate in Hz (uint64_t).&lt;br /&gt;
** SR_DI_PATTERNMODES: Supported pattern generator modes (array ov char*).&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_status(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns an integer describing the status of the plugin&amp;#039;s connection to a device. This may be one of the following:&lt;br /&gt;
** SR_ST_NOT_FOUND: The device was not found.&lt;br /&gt;
** SR_ST_INITIALIZING: The device was found, but is still initializing.&lt;br /&gt;
** SR_ST_INACTIVE: The device is live, but not in use.&lt;br /&gt;
** SR_ST_ACTIVE: The device is currently in use.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_capabilities()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This function returns a zero-terminated integer array with the plugin&amp;#039;s capabilities, in the form of a set of defined constants. Some of these are informative, and some can be used to configure the plugin (or its connected device). The capabilities tables below have an overview of all possible capabilities.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;set_configuration(int device_index, int capability, char *value)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This is used to configure the plugin and/or connected device. The capability is one of the constants returned from the get_capabilities() call. The value depends on the parameter that is to be configured.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;start_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Start acquisition on the specified device. The session_device_id will be passed along with the data feed of this session, as the first parameter to session bus callbacks.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;stop_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Stop acquisition on the specified device. This causes a DF_END packet to be sent to the sesion bus.&lt;br /&gt;
&lt;br /&gt;
== Device classes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LOGIC_ANALYZER&lt;br /&gt;
: This device is a logic analyzer.&lt;br /&gt;
&lt;br /&gt;
== Device options ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_SAMPLERATE&lt;br /&gt;
: The sample rate in Hz (uint64_t *).&lt;br /&gt;
* HWCAP_PROBECONFIG&lt;br /&gt;
: Probe configuration (GSList *probes)&lt;br /&gt;
* HWCAP_CAPTURE_RATIO&lt;br /&gt;
: Pre-trigger capture ratio, as a percentage of the number of samples returned. The default is 0, meaning capturing only starts after the trigger fired  (uint64_t *).&lt;br /&gt;
* HWCAP_PATTERN_MODE&lt;br /&gt;
: Pattern to generate  (char **).&lt;br /&gt;
&lt;br /&gt;
== Acquisition modes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LIMIT_MSEC&lt;br /&gt;
: How long the acquisition should last, in ms (uint64_t).&lt;br /&gt;
* HWCAP_LIMIT_SAMPLES&lt;br /&gt;
: How many samples to acquire in the session (uint64_t).&lt;br /&gt;
* HWCAP_CONTINUOUS&lt;br /&gt;
: Device supports continuous sampling&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1341</id>
		<title>Hardware driver API</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1341"/>
		<updated>2012-01-05T15:38:16Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: Updated get_device_info&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Every plugin is built as a shared library, dynamically loaded by the backend at startup. The plugin must define a structure as follows:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;sigrok.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 struct sr_device_plugin {&lt;br /&gt;
 	/* plugin-specific */&lt;br /&gt;
 	char *name;&lt;br /&gt;
 	char *longname;&lt;br /&gt;
 	int api_version;&lt;br /&gt;
 	int (*init) (const char *deviceinfo);&lt;br /&gt;
 	void (*cleanup) (void);&lt;br /&gt;
 &lt;br /&gt;
 	/* device-specific */&lt;br /&gt;
 	int (*opendev) (int device_index);&lt;br /&gt;
 	int (*closedev) (int device_index);&lt;br /&gt;
 	void *(*get_device_info) (int device_index, int device_info_id);&lt;br /&gt;
 	int (*get_status) (int device_index);&lt;br /&gt;
 	int *(*get_capabilities) (void);&lt;br /&gt;
 	int (*set_configuration) (int device_index, int capability, char *value);&lt;br /&gt;
 	int (*start_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 	void (*stop_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 #define SIGROK_HARDWARE_PLUGIN   struct device_plugin plugin_info&lt;br /&gt;
&lt;br /&gt;
This structure is the only symbol imported into the backend namespace. The plugin&amp;#039;s variables thus cannot conflict with the global sigrok namespace.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;name&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A short string describing this driver. It will be referenced in saved session files.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;longname&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A long string describing this driver. It will be shown to the user.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;api_version&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Currently defined as 1.&lt;br /&gt;
&lt;br /&gt;
The other members of the structure are pointers to plugin callbacks:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;init(const char *deviceinfo)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called when the plugin is initially loading into sigrok, typically at program start. The parameter refers to a device name or special file, whichever is applicable for the plugin. Devices which don&amp;#039;t need a supplied device, such as USB devices, can simply ignore this parameter. The function returns the number of devices found, and 0 if no suitable device was found. If a device was found, any initialization it needs must be performed here; for example, uploading firmware should be done here.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;cleanup()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called before the plugin is unloaded. Release any resources the plugin might be holding.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;opendev(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Open the specified device. The device index starts at 0. Returns SR_OK if successful, SR_ERR otherwise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;closedev(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Close the specified device. The device index starts at 0. Returns SR_OK if successful, SR_ERR otherwise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_device_info(int device_index, int device_info_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns information about the given device. The type of information is given as device_info_id, one of a set of defined constants. The return value is always a pointer, which points to information specific to the id.&lt;br /&gt;
** SR_DI_INSTANCE: Returns a pointer to a [[Formats_and_structures#device_instances|struct sigrok_device_instance]].&lt;br /&gt;
** SR_DI_NUM_PROBES: The number of probes connected to this device (integer).&lt;br /&gt;
** SR_DI_PROBE_NAMES: The probe names on this device (array of char*).&lt;br /&gt;
** SR_DI_SAMPLERATES: Returns a pointer to a [[Formats_and_structures#Sample_rates|struct samplerates]].&lt;br /&gt;
** SR_DI_TRIGGER_TYPES: Types of trigger supported, out of &amp;quot;01crf&amp;quot; (char *).&lt;br /&gt;
** SR_DI_CUR_SAMPLERATE: The currently set samplerate in Hz (uint64_t).&lt;br /&gt;
** SR_DI_PATTERNMODES: Supported pattern generator modes (array ov char*).&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_status(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns an integer describing the status of the plugin&amp;#039;s connection to a device. This may be one of the following:&lt;br /&gt;
** ST_NOT_FOUND: The device was not found.&lt;br /&gt;
** ST_INITIALIZING: The device was found, but is still initializing.&lt;br /&gt;
** ST_INACTIVE: The device is live, but not in use.&lt;br /&gt;
** ST_ACTIVE: The device is currently in use.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_capabilities()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This function returns a zero-terminated integer array with the plugin&amp;#039;s capabilities, in the form of a set of defined constants. Some of these are informative, and some can be used to configure the plugin (or its connected device). The capabilities tables below have an overview of all possible capabilities.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;set_configuration(int device_index, int capability, char *value)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This is used to configure the plugin and/or connected device. The capability is one of the constants returned from the get_capabilities() call. The value depends on the parameter that is to be configured.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;start_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Start acquisition on the specified device. The session_device_id will be passed along with the data feed of this session, as the first parameter to session bus callbacks.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;stop_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Stop acquisition on the specified device. This causes a DF_END packet to be sent to the sesion bus.&lt;br /&gt;
&lt;br /&gt;
== Device classes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LOGIC_ANALYZER&lt;br /&gt;
: This device is a logic analyzer.&lt;br /&gt;
&lt;br /&gt;
== Device options ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_SAMPLERATE&lt;br /&gt;
: The sample rate in Hz (uint64_t *).&lt;br /&gt;
* HWCAP_PROBECONFIG&lt;br /&gt;
: Probe configuration (GSList *probes)&lt;br /&gt;
* HWCAP_CAPTURE_RATIO&lt;br /&gt;
: Pre-trigger capture ratio, as a percentage of the number of samples returned. The default is 0, meaning capturing only starts after the trigger fired  (uint64_t *).&lt;br /&gt;
* HWCAP_PATTERN_MODE&lt;br /&gt;
: Pattern to generate  (char **).&lt;br /&gt;
&lt;br /&gt;
== Acquisition modes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LIMIT_MSEC&lt;br /&gt;
: How long the acquisition should last, in ms (uint64_t).&lt;br /&gt;
* HWCAP_LIMIT_SAMPLES&lt;br /&gt;
: How many samples to acquire in the session (uint64_t).&lt;br /&gt;
* HWCAP_CONTINUOUS&lt;br /&gt;
: Device supports continuous sampling&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1340</id>
		<title>Hardware driver API</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1340"/>
		<updated>2012-01-05T15:25:10Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: Updated opendev/closedev&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Every plugin is built as a shared library, dynamically loaded by the backend at startup. The plugin must define a structure as follows:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;sigrok.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 struct sr_device_plugin {&lt;br /&gt;
 	/* plugin-specific */&lt;br /&gt;
 	char *name;&lt;br /&gt;
 	char *longname;&lt;br /&gt;
 	int api_version;&lt;br /&gt;
 	int (*init) (const char *deviceinfo);&lt;br /&gt;
 	void (*cleanup) (void);&lt;br /&gt;
 &lt;br /&gt;
 	/* device-specific */&lt;br /&gt;
 	int (*opendev) (int device_index);&lt;br /&gt;
 	int (*closedev) (int device_index);&lt;br /&gt;
 	char *(*get_device_info) (int device_index, int device_info_id);&lt;br /&gt;
 	int (*get_status) (int device_index);&lt;br /&gt;
 	int *(*get_capabilities) (void);&lt;br /&gt;
 	int (*set_configuration) (int device_index, int capability, char *value);&lt;br /&gt;
 	int (*start_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 	void (*stop_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 #define SIGROK_HARDWARE_PLUGIN   struct device_plugin plugin_info&lt;br /&gt;
&lt;br /&gt;
This structure is the only symbol imported into the backend namespace. The plugin&amp;#039;s variables thus cannot conflict with the global sigrok namespace.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;name&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A short string describing this driver. It will be referenced in saved session files.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;longname&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A long string describing this driver. It will be shown to the user.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;api_version&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Currently defined as 1.&lt;br /&gt;
&lt;br /&gt;
The other members of the structure are pointers to plugin callbacks:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;init(const char *deviceinfo)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called when the plugin is initially loading into sigrok, typically at program start. The parameter refers to a device name or special file, whichever is applicable for the plugin. Devices which don&amp;#039;t need a supplied device, such as USB devices, can simply ignore this parameter. The function returns the number of devices found, and 0 if no suitable device was found. If a device was found, any initialization it needs must be performed here; for example, uploading firmware should be done here.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;cleanup()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called before the plugin is unloaded. Release any resources the plugin might be holding.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;opendev(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Open the specified device. The device index starts at 0. Returns SR_OK if successful, SR_ERR otherwise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;closedev(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Close the specified device. The device index starts at 0. Returns SR_OK if successful, SR_ERR otherwise.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_device_info(int device_index, int device_info_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns information about the given device. The type of information is given as device_info_id, one of a set of defined constants. The return value is always a pointer, which points to information specific to the id.&lt;br /&gt;
** DI_INSTANCE: Returns a pointer to a [[Formats_and_structures#device_instances|struct sigrok_device_instance]].&lt;br /&gt;
** DI_NUM_PROBES: The number of probes connected to this device (integer).&lt;br /&gt;
** DI_SAMPLERATES: Returns a pointer to a [[Formats_and_structures#Sample_rates|struct samplerates]].&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_status(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns an integer describing the status of the plugin&amp;#039;s connection to a device. This may be one of the following:&lt;br /&gt;
** ST_NOT_FOUND: The device was not found.&lt;br /&gt;
** ST_INITIALIZING: The device was found, but is still initializing.&lt;br /&gt;
** ST_INACTIVE: The device is live, but not in use.&lt;br /&gt;
** ST_ACTIVE: The device is currently in use.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_capabilities()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This function returns a zero-terminated integer array with the plugin&amp;#039;s capabilities, in the form of a set of defined constants. Some of these are informative, and some can be used to configure the plugin (or its connected device). The capabilities tables below have an overview of all possible capabilities.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;set_configuration(int device_index, int capability, char *value)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This is used to configure the plugin and/or connected device. The capability is one of the constants returned from the get_capabilities() call. The value depends on the parameter that is to be configured.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;start_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Start acquisition on the specified device. The session_device_id will be passed along with the data feed of this session, as the first parameter to session bus callbacks.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;stop_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Stop acquisition on the specified device. This causes a DF_END packet to be sent to the sesion bus.&lt;br /&gt;
&lt;br /&gt;
== Device classes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LOGIC_ANALYZER&lt;br /&gt;
: This device is a logic analyzer.&lt;br /&gt;
&lt;br /&gt;
== Device options ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_SAMPLERATE&lt;br /&gt;
: The sample rate in Hz (uint64_t *).&lt;br /&gt;
* HWCAP_PROBECONFIG&lt;br /&gt;
: Probe configuration (GSList *probes)&lt;br /&gt;
* HWCAP_CAPTURE_RATIO&lt;br /&gt;
: Pre-trigger capture ratio, as a percentage of the number of samples returned. The default is 0, meaning capturing only starts after the trigger fired  (uint64_t *).&lt;br /&gt;
* HWCAP_PATTERN_MODE&lt;br /&gt;
: Pattern to generate  (char **).&lt;br /&gt;
&lt;br /&gt;
== Acquisition modes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LIMIT_MSEC&lt;br /&gt;
: How long the acquisition should last, in ms (uint64_t).&lt;br /&gt;
* HWCAP_LIMIT_SAMPLES&lt;br /&gt;
: How many samples to acquire in the session (uint64_t).&lt;br /&gt;
* HWCAP_CONTINUOUS&lt;br /&gt;
: Device supports continuous sampling&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
	<entry>
		<id>https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1339</id>
		<title>Hardware driver API</title>
		<link rel="alternate" type="text/html" href="https://sigrok.org/w/index.php?title=Hardware_driver_API&amp;diff=1339"/>
		<updated>2012-01-05T15:19:20Z</updated>

		<summary type="html">&lt;p&gt;Seventhguardian: Minor fixes&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Every plugin is built as a shared library, dynamically loaded by the backend at startup. The plugin must define a structure as follows:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;quot;sigrok.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 struct sr_device_plugin {&lt;br /&gt;
 	/* plugin-specific */&lt;br /&gt;
 	char *name;&lt;br /&gt;
 	char *longname;&lt;br /&gt;
 	int api_version;&lt;br /&gt;
 	int (*init) (const char *deviceinfo);&lt;br /&gt;
 	void (*cleanup) (void);&lt;br /&gt;
 &lt;br /&gt;
 	/* device-specific */&lt;br /&gt;
 	int (*open) (int device_index);&lt;br /&gt;
 	void (*close) (int device_index);&lt;br /&gt;
 	char *(*get_device_info) (int device_index, int device_info_id);&lt;br /&gt;
 	int (*get_status) (int device_index);&lt;br /&gt;
 	int *(*get_capabilities) (void);&lt;br /&gt;
 	int (*set_configuration) (int device_index, int capability, char *value);&lt;br /&gt;
 	int (*start_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 	void (*stop_acquisition) (int device_index, gpointer session_device_id);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 #define SIGROK_HARDWARE_PLUGIN   struct device_plugin plugin_info&lt;br /&gt;
&lt;br /&gt;
This structure is the only symbol imported into the backend namespace. The plugin&amp;#039;s variables thus cannot conflict with the global sigrok namespace.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;name&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A short string describing this driver. It will be referenced in saved session files.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;longname&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;A long string describing this driver. It will be shown to the user.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;api_version&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Currently defined as 1.&lt;br /&gt;
&lt;br /&gt;
The other members of the structure are pointers to plugin callbacks:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;init(const char *deviceinfo)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called when the plugin is initially loading into sigrok, typically at program start. The parameter refers to a device name or special file, whichever is applicable for the plugin. Devices which don&amp;#039;t need a supplied device, such as USB devices, can simply ignore this parameter. The function returns the number of devices found, and 0 if no suitable device was found. If a device was found, any initialization it needs must be performed here; for example, uploading firmware should be done here.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;cleanup()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Called before the plugin is unloaded. Release any resources the plugin might be holding.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;open(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Open the specified device. The device index starts at 0.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;close(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Close the specified device.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_device_info(int device_index, int device_info_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns information about the given device. The type of information is given as device_info_id, one of a set of defined constants. The return value is always a pointer, which points to information specific to the id.&lt;br /&gt;
** DI_INSTANCE: Returns a pointer to a [[Formats_and_structures#device_instances|struct sigrok_device_instance]].&lt;br /&gt;
** DI_NUM_PROBES: The number of probes connected to this device (integer).&lt;br /&gt;
** DI_SAMPLERATES: Returns a pointer to a [[Formats_and_structures#Sample_rates|struct samplerates]].&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_status(int device_index)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Returns an integer describing the status of the plugin&amp;#039;s connection to a device. This may be one of the following:&lt;br /&gt;
** ST_NOT_FOUND: The device was not found.&lt;br /&gt;
** ST_INITIALIZING: The device was found, but is still initializing.&lt;br /&gt;
** ST_INACTIVE: The device is live, but not in use.&lt;br /&gt;
** ST_ACTIVE: The device is currently in use.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;get_capabilities()&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This function returns a zero-terminated integer array with the plugin&amp;#039;s capabilities, in the form of a set of defined constants. Some of these are informative, and some can be used to configure the plugin (or its connected device). The capabilities tables below have an overview of all possible capabilities.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;set_configuration(int device_index, int capability, char *value)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;This is used to configure the plugin and/or connected device. The capability is one of the constants returned from the get_capabilities() call. The value depends on the parameter that is to be configured.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;start_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Start acquisition on the specified device. The session_device_id will be passed along with the data feed of this session, as the first parameter to session bus callbacks.&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;stop_acquisition(int device_index, gpointer session_device_id)&amp;#039;&amp;#039;&amp;#039;&amp;lt;br /&amp;gt;Stop acquisition on the specified device. This causes a DF_END packet to be sent to the sesion bus.&lt;br /&gt;
&lt;br /&gt;
== Device classes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LOGIC_ANALYZER&lt;br /&gt;
: This device is a logic analyzer.&lt;br /&gt;
&lt;br /&gt;
== Device options ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_SAMPLERATE&lt;br /&gt;
: The sample rate in Hz (uint64_t *).&lt;br /&gt;
* HWCAP_PROBECONFIG&lt;br /&gt;
: Probe configuration (GSList *probes)&lt;br /&gt;
* HWCAP_CAPTURE_RATIO&lt;br /&gt;
: Pre-trigger capture ratio, as a percentage of the number of samples returned. The default is 0, meaning capturing only starts after the trigger fired  (uint64_t *).&lt;br /&gt;
* HWCAP_PATTERN_MODE&lt;br /&gt;
: Pattern to generate  (char **).&lt;br /&gt;
&lt;br /&gt;
== Acquisition modes ==&lt;br /&gt;
&lt;br /&gt;
* HWCAP_LIMIT_MSEC&lt;br /&gt;
: How long the acquisition should last, in ms (uint64_t).&lt;br /&gt;
* HWCAP_LIMIT_SAMPLES&lt;br /&gt;
: How many samples to acquire in the session (uint64_t).&lt;br /&gt;
* HWCAP_CONTINUOUS&lt;br /&gt;
: Device supports continuous sampling&lt;/div&gt;</summary>
		<author><name>Seventhguardian</name></author>
	</entry>
</feed>