(main page) Last update Saturday, January 11, 2003 Bertrik Sikken (Updated info for registers 0x27-0x2a)



This page describes the internal registers of the HP3300C USB color scanner.
The information presented here might not necessarily be completely correct, but merely represents my interpretation of it.

A scan generally seems to consist of the following steps: When the windows scanning software has just been started, the scanner waits for the lamp to 'warm up' and it does a more elaborate three-pass calibration.

Scanner initialisation

The following things occur every time before a scan: The information about bit 1 in register 0x03 is later used to determine if the gamma table should be expanded to 16 bits or not.


Simple calibration

Just before every scan, a two-pass calibration is done, scanning a black and a white area inside the scanner to establish the white level and the black level for each pixel in the CCD. This picture shows a scan that includes the calibration area. The black horizontal strip and the light grey area around it, is the calibration area. (The orange line at the top and the pure white area below it are just software artifacts). Somehow the black strip does not completely extend to the left of the scanner bed, so I wonder how calibration is done for the extreme left of the scan.
During the first calibration cycle, the scanner reads a 0.1 mm line in the white part of the calibration area. During the second calibration cycle, it reads a 0.1 mm line in the black part of the calibration area.

Initial calibration

When the windows scanning software has been freshly started, an additional three-pass calibration is done. The coarse brightness information written to registers 0x25 and 0x26 is determined in this initial calibration cycle.

Another thing to note is that just before calibration, register 0x02 is written with value 0x88, while it is written with 0xA8 just before the actual scan. This suggests that bit 5 of register 2 controls whether pixel gain/offset control is used or not.

Gamma, gain, offset

The gamma and gain/offset tables are written using an USB bulk transfer.
Since these are written just after the simple two-pass calibration, but just before the actual scan, it is likely that the gain/offset table is calculated from the calibration data.

Gamma table

One of the sections in the DLL, the .data section, contains the gamma tables for red, green and blue. Each is 4096 bytes long (12 -> 8 bit gamma table apparently). The same section also contains the filenames C:\CCmpBG12.dat, C:\CCmpGG12.dat, C:\CCmpRG12.dat, and the texts 'USB Scanner V1.0' and 'Scanner Centaur'.
Looking at the DLL, it seems that the software will try to read the gamma tables from the files given above (if present), otherwise it will use the built-in tables from the DLL.

If bit 1 of register 3 sticks, the scanner is able to handle 16-bit gamma entries. In that case, the gamma table with 8-bit entries is converted to a gamma table with 16-bit entries, resulting in a 8192 byte table for each of the three color components.

Gain/offset table

The gain/offset table contains a gain and offset coefficient for each color component (red, green and blue) of the 5300 pixels of the CCD (the HP3300c has an optical resolution of 600 DPI). Each coefficient entry is 16 bit, subdivided in a 6-bit part and a 10-bit part. The lower 6 bits contain the pixel offset and the higher 10 bits contain the pixel gain (as in the LM9830 chip). The offset coefficient specifies how much to subtract from raw sample value before further processing. A step of 4 units in the offset coefficient corresponds with 1 unit of intensity in the final image data. A gain coefficient of 256 corresponds to a gain of 1.
The gain/offset table is appended to the gamma table and written using a single USB bulk transfer.

Scanner register summary

Most HP3300c have a NIASH00014 controller chip. The info given in the table below is applicable to this chip, specific properties of other controller chips are given separately.

There seem to be 48 registers, some of which pair up in 2-byte registers and some of which are not used. The HP3400/4300 have more registers than the HP3300C. Most of the registers are write-only.
For the bit-oriented registers (0x01, 0x02, 0x03, 0x05, 0x06) a cached list of values written to these registers is kept in the DLL.
In the table below, the cached values are shown for registers 0x00-0x07. The other registers show the value written during a preview scan.

0x00----Write 0x04 to reset?
0x010x03Scan type register? bit-oriented, bits 2, 3 and 7 are used. 12 bit pixels are used if bit 2 is set
0x020xA0Scan type register? bit-oriented, bits 2, 3, 4, 5, and 7 are used. Bit 2 is set when reading/writing gamma data, bit 3 causes the carriage to move when reading USB bulk data, bit 5 enables the gain/offset table?
0x030x05Status register? bit-oriented, bit 0, 1, 2, 3 and 4 are used. bit 0 controls lamp status, if bit 1 is writable the scanner supports gamma tables with 16-bit entries, bit 3 is set when the carriage is in the home position.
0x04----Not used, but register is readable and writeable
0x050x01Low nibble and high nibble have separate meanings. When set incorrectly causes the carriage to move too far. Bit 0 needs to be set and seems the only relevant bit
0x060x00bit-oriented. When bit 0 is set, the carriage moves twice as far (used for low LPI?). When bit 1 is set, the carriage does not move, but makes a buzzing sound. Readable on a HP3400c.
0x07----HP3400c specific. Writeable on a HP3400c.
0x080x175399. Exposure time? The LPI (lines-per-inch) is determined by the ratio of this register and registers 0x0A/0x0B times 1200 (which also happens to be the hardware resolution). A higher number results in a brighter picture.
0x0A0xA2Motor speed code (lower is faster). Has a value of 674 for 150 lpi, 1349 for 300 lpi and 8099 for 600 lpi. Appears to be related to register 0x1E. I think this value should be an integer sub-multiple of register 0x08/0x09.
0x0C0x96150. DPI code (horizontal resolution)
0x0E0x4A330. Right coordinate of scan area, inches * 1800
0x100xE915593. Left coordinate of scan area, inches * 1800
0x120xF71271. Width of scan area - 1, (number of pixels output)
0x140xF9(x - 1). Maximum buffer level (as read from reg 0x20) before backtracking occurs. Written with 0x24 (=36) when calibrating. Some high values still give a lot of backtracking.
0x170xC4452. Top of scan area, inches * 1200
0x190xC4452. Top of scan area
0x1B0x3C14652. Bottom of scan area. (-> height = 14200 steps = 11.83 inch = 300.6 mm)
This register does not seem to have an effect on the HP3300, it does on the HP3400/4300
0x1D0x60Forward jogging speed. Agfa Touch writes 0x55 here.
0x1E0x15Not written when calibrating. Controls reversing speed when backtracking (lower is faster). Value written to this register is value written to registers 0x0A/0x0B divided by 32.
0x1F0x30Not written when calibrating. Value is either 0x18 or 0x30. Sets the distance to move back when backtracking.
0x20----Scanner buffer level. As data is scanned in but not quickly enough read out, the internal scanner buffer fills up. When the buffer level approaches the level given by register 0x14, the scanner backtracks to rescan part of the image.
0x21----HP3400/4300 specific. RAM data address, low 8 bits
0x22----HP3400/4300 specific. RAM data address, mid 8 bits
0x23----HP3400/4300 specific. RAM data address, high 8 bits
0x24----Data transfer register. This register is selected just before USB bulk transfer
0x25xxxxAnalog front-end control. See also the table below.
0x270x620x62 or 0xD2. Readable on HP3400c.
0x280xC80xC8 or 0x7F. Readable on HP3400c. Another gain register?
On my niash00014 chip, bit7 should always be set, bit 4/5 set the gain, bit 6 set means max gain.
The low nibble represents a FIFO level? A value of 0 means no more garbage in the first few lines.
0x290x530xB853 or 0x6421. Readable on HP3400c. Non-linearity compensation? Each nibble represents a factor, and should be smaller than the preceding one.
0x2B0x15Not written when calibrating. Value is always 0x15. Controls backtracking reversing behaviour.
0x2C0xFFLamp power control
Value between 0 (lamp off) and 0x1FF (full on). The relationship between value and brightness is strongly non-linear, e.g. 0x010 already results in half brightness. See also this graph, which shows the average intensity measured during calibration vs. register value.
0x2E----Button status. Bits 1-4 indicate buttons states. On the HP3300c: bit 2 = left button (scan), bit 4 = right button (print).
On the HP4300c: bit 1 = scan, bit 2 = mail, bit 4 = print
0x2F----Backward jogging speed. Agfa Touch writes 0x55 here.
0x30----???. Agfa Touch writes 0x3F here.
0x38----HP3400/4300 specific. Readable. Eeprom address?
0x39----HP3400/4300 specific. Readable. Eeprom data?
0x3B----HP3400/4300 specific. Readable. Eeprom control?. Bit 3 is status bit.
0x3C----HP3400/4300 specific. Readable. LCD data = Number to write to display (BCD coded). Invalid BCD nibbles show up as 0x09 (0x0B displays 0x09 for example)
0x3D----HP3400/4300 specific. Readable. LED and button control. bit0 = ColorLED, bit1 = BWLED, bit2 = UpDown?, bit3 = button1?, bit5 = (+) button, bit6 = button3?, bit7 = (-) button

Analog front-end

Data written to registers 0x25 and 0x26 controls the analog front-end (AFE) which determines, among other things, the overall brightness (offset) and contrast (gain). Register 0x25 is the index register, register 0x26 is the data register.
The default values used during initial calibration are shown below:

Reg. 0x25Reg 0x26Description
0x040x00Reset the AFE
0x030x12 CDS Mode Reset Timing = normal
Reset Level Clamp Voltage = 3.5V
0x020x04 ADC output = inverting
MUX output mode = 12 bit
0x050x10 ADC output = 12 bit
Offset DAC output range = +/- 1.25V
0x010x03 Mode 4 = off
Mono/colour select = colour
Sampling mode = CDS
ADC standby control = active
0x200xC0Red offset
0x210xC0Green offset
0x220xC0Blue offset
0x280x02Red gain
0x290x02Green gain
0x2A0x02Blue gain

16 units of offset coefficient roughly correspond to 10 unit of brightness in the final image.
The gain (G) can be calculated from the gain coefficient (Cg) by the simple formula:
G = (Cg + 2) / 4, or inversely Cg = 4G - 2
My HP3300c contains an ESIC ES8100QA chip for the analog front-end, while other HP3300/HP3400 scanners contain a WM8143, so those two chips are probably compatible. Fortunately, a datasheet of the WM8143 can be downloaded here.

Image data

Once the scanner has been set up, simply reading the scanner by means of USB bulk reads causes the carriage to move to the starting position of the scan and to start the actual scan. When data is not read out quickly enough, the carriage automatically backtracks and restarts the missing part without software intervention.
Image data is delivered on a line basis, first the red component of the line, then green, then blue. The color components are out of alignment by 1/150 inch. For a resolution of 150 dpi the red frame needs to be shifted up one line and to the blue frame needs to be shifted down one line relative to the green frame. (For a resolution of 300 dpi, the alignment error is two lines, etc.) The first couple of lines (about 14) contain garbage, mostly white pixels. Image data is also delivered mirrored left-to-right.

NIASH00012 chip specifics

Some HP3300c scanners contain a niash00012 chip.
The USB logs suggest the following:

NIASH00013 chip specifics

Some HP3300c scanners contain a niash00013 chip. Obviously a chip version between 00012 and 00014. No logs from a scan using this chip have been analysed.

NIASH00019 chip specifics

The HP3400 has a newer main controller revision, NIASH00019 instead of NIASH00014. More registers are readable (most HP3300 registers are write-only), there are extra registers and also the meaning of some registers seems to have changed slightly.

One of these is register 0x07, which is both readable and writeable on the HP3400 and seems to be used to determine how other the registers operate. If registers 0x07 is writeable, the following is different:
While the HP3300 only writes the gamma/gain/offset table to the scanner, the HP3400 also writes other data to the scanner. The address to write to (minus 1) is set by registers 0x21/0x22/0x23.
The following data blocks are written to the scanner:

0x00000096Stepper motor acceleration profile, used when positioning head
0x00040036Stepper motor acceleration profile, used when actually scanning
0x00200056376Gamma and gain/offser table

The data written to addresses 0x000000 and 0x000400 seems to contain an exponentially decaying series. This picture shows the values that are inside the table (ignoring first 2 values and most significant bits). A good approximation to the graph is y2 = 676 / (2 - e 0.113 * (1 - x)), shown as the continuous curve. This approximation is correct within 1 unit, except for the 2nd and last value.

Given the fact that registers 0x0A/0x0B (motor speed) and 0x17/0x18, 0x19/0x1A (top of scan) are not written directly, it seems plausible that their values are somehow encoded in these data blocks.

Buttons and display on the 4300c

(Contributed by James Paige)
(bit 0 is least significant bit)

NIASH00033 chip specifics

This chip is used in the HP5400c and HP5470c scanners. A short analysis of the USB traffic between the scanner and the Windows driver shows that at least the USB transfer method is completely different. I suspect/hope that these scanners have some kind of microcontroller sitting between USB and the NIASH chip (opposed to just a simple IEEE1284-USB bridge), doing all the complicated stuff. In that case it would be somewhat easier to write a backend, although currently this is all just speculation.

I wrote a simple utility (hp5400.zip) to test communication with the HP5400/5470 under Linux. It requires libusb (and the libusb devel package) for USB access. The 'scanner' kernel module should be unloaded (run 'modprobe -r scanner' as root). You probably also need to be root to run the test utility itself.

HP3300c USB snoopy logs

The following files are HP3300c logs and have been generated by a perl-script from the actual (rather big) USB snoopy logs. This perl-script is an adapted version of the one in the Microtek 3600 SANE backend. Furthermore I used a text-editor to remove all lines with 14->[87] in them and to add white lines for clarity.
(xx->[83] means 'write address xx', yy->[85] means 'write data yy', [84]=zz means that data zz was read.)
All scans were done after a fresh reboot and a preview scan. The initial calibration sequence is not recorded in these logs.