Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
projects:acb8300 [2016/01/25 22:35] Andreas Böhlerprojects:acb8300 [2016/01/25 23:20] (current) – [Wait for button inpurt] Andreas Böhler
Line 33: Line 33:
 ===== Debugging the LG_ACB8300.dll ===== ===== Debugging the LG_ACB8300.dll =====
  
-I traced parts of the LG_ACB8300.dll with OllyDBG. I built a small C wrapper around the library in order to have access to the funtions and their parameters. The wrapper simply loads the DLL entry points and calls DeviceOpen, Get_ADC, Get_XYZ, etc. in order to reverse engineer the functionality.+I traced parts of the LG_ACB8300.dll with OllyDBG. I built a Python and a small C wrapper around the library in order to have access to the funtions and their parameters. The wrapper simply loads the DLL entry points and calls DeviceOpen, Get_ADC, Get_XYZ, etc. in order to reverse engineer the functionality.
  
 Inside the Get_XYZ function, a lot of floating point magic is going on. After reversing all the floating point assembly, it turns out that the conversion from ADC to XYZ is performing as follows: Inside the Get_XYZ function, a lot of floating point magic is going on. After reversing all the floating point assembly, it turns out that the conversion from ADC to XYZ is performing as follows:
  
   - Read ADC value from device   - Read ADC value from device
-  - Do an offset correction (can be read from calibration) +  - Do an offset correction (can be read from calibration, **subract** A from the USB protocol
-  - Apply a correction matrix (can be read from calibration) +  - Apply a correction matrix (can be read from calibration, **multiply** by M from the USB protocol
-  - Do an offset correction (can be read from calibration) +  - Do an offset correction (can be read from calibration, **add** X from the USB protocol
-  - Apply a monitor correction matrix+  - Apply a monitor correction matrix (**multiply** by matrix from the DLL)
  
 The monitor correction matrix is hardcoded in the DLL. The SetMonitorType() function simply loads a different matrix into memory. The monitor correction matrix is hardcoded in the DLL. The SetMonitorType() function simply loads a different matrix into memory.
Line 62: Line 62:
 ===== Hacking the USB protocol ===== ===== Hacking the USB protocol =====
  
-The USB protocol consists of input reports and output reports, with a fixed length of 43 bytes. The host speaks first, the device responds (most of the time). The first byte is always the command byte, the remaining bytes are either payload or junk.+The USB protocol consists of input reports and output reports, with a fixed length of 43 bytes. The host speaks first, the device responds (most of the time). The first byte is always the command byte, the remaining bytes are either payload or junk. The byte numbers of the table start with the payload, so you have to strip the first byte anyway. 
 + 
 +They seem to not clear the send buffer before responding to a command. Thus, you always get the remaining bytes of the previous commands as well!
  
 ==== Initialisation ==== ==== Initialisation ====
Line 76: Line 78:
  
 Send: ''%%0x51%%''\\ Send: ''%%0x51%%''\\
-Response: ''%%0x53%%'' \\ +Response: ''%%0x53%%'' 
-The bytes are: \\ + 
-0-7 8-15 16-23 ^ 24-31 ^ 32-39 +Bytes Format Description 
-| M[0][0] | M[0][1] | M[0][2] | M[1][0] | M[1][1] |+| 0-7 | double | M[0][0] 
 +| 8-15 | double | M[0][1] 
 +| 16-23 | double | M[0][2] 
 +| 24-31 | double | M[1][0] 
 +| 32-39 | double | M[1][1] | 
  
 Send: ''%%0x52%%''\\ Send: ''%%0x52%%''\\
-Response: ''%%0x53%%'' \\ +Response: ''%%0x53%%'' 
-The bytes are: \\ + 
-0-7 8-15 16-23 ^ 24-31 +Bytes Format Description 
-| M[1][2] | M[2][0] | M[2][1] | M[2][2] |+| 0-7 | double | M[1][2] 
 +| 8-15 | double | M[2][0] 
 +| 16-23 | double | M[2][1] 
 +| 24-31 | double | M[2][2] |
  
 Send: ''%%0x54%%''\\ Send: ''%%0x54%%''\\
-Response: ''%%0x53%%'' \\ +Response: ''%%0x53%%'' 
-The bytes are: \\ + 
-0-7 8-15 16-23 ^ 24-31 ^ 32-39 +Bytes Format Description 
-| A[0] | A[1] | A[2] | X[0] | X[1] |+| 0-7 | double | A[0] 
 +| 8-15 | double | A[1] 
 +| 16-23 | double | A[2] 
 +| 24-31 | double | X[0] 
 +| 32-39 | double | X[1] |
  
 Send: ''%%0x55%%''\\ Send: ''%%0x55%%''\\
-Response: ''%%0x53%%'' \\ +Response: ''%%0x53%%''  
-The bytes are: \\ + 
-^ 0-7 +Bytes ^ Format ^ Description ^ 
-| X[2] |+0-7 | double | X[2] |
  
 ==== Read ADC values ==== ==== Read ADC values ====
Line 122: Line 136:
 In order to derive the firmware version, divide the value by 100. My device reports ''%%100%%'' which corresponds to firmware version ''%%1.0%%''. In order to derive the firmware version, divide the value by 100. My device reports ''%%100%%'' which corresponds to firmware version ''%%1.0%%''.
  
-==== Wait for button inpurt ====+==== Wait for button input ====
  
 Send: ''%%0x05%%'' \\ Send: ''%%0x05%%'' \\
Line 129: Line 143:
 Whenever the button is pressed, the device sends ''%%0x62%%''. Whenever the button is pressed, the device sends ''%%0x62%%''.
  
-===== Conversion from ADC to XYZ ===== +===== ArgyllCMS support =====
- +
-The device requires a conversion from ADC to XYZ values. I reversed the method from the LG DLL and came up with the following algorithm (it's actually quite simple once you've figured out all the floating point magic in assembler). +
- +
-  - Offset +
-  - Matrix multiplication +
-  - Offset +
-  - Display correction matrix +
- +
-The values for both offset corrections and for the first matrix multiplication can be read from the device itself. The display correction +
-matrices are hardcoded in the LG DLL. +
  
 +Although the device will probably be never officially supported by ArgyllCMS, I developed an initial driver for the device. You can find the patch for Argyll 1.8.3 {{:projects:argyll_v1.8.3_1_to_3.diff|here}}. Be aware that it is only tested on **my** colorimeter and only on **Linux**. The patches to the Windows .inf-files are completely untested.