(transfer clock)
This page contains information about scanners using RealTek chips. The purpose is to gather sufficient information to write a SANE backend for these scanners so that they can be used under UNIX and UNIX-like environments.
There is an obsolete working demo program for the HP ScanJet 3500C, HP ScanJet 3530C and HP ScanJet 3570C: http://projects.troy.rollo.name/rt-scanners/rtdemo-1.1.0.tar.bz2. This demo can scan images at resolutions of 1200, 600, 400, 300, 200, 150, 100, 75, 50 and 25 DPI (although 1200 and 400 still have some issues with calibration), in full colour mode, and store the results in a PNM format image file.
Both scanners are based on chips made by RealTek. The way RealTek operate is to provide the scanner chip and the services to produce the drivers for the scanner. This means that there is no documentation for programming the chips. The documentation here has been compiled from the following sources:
An additional consequence of the way RealTek operate is that the Windows driver is bloated with a huge amount of code that is never used for a particular scanner. The driver is based on a general set of code designed to deal with any scanner that utilises the particular RealTek chip. Aside from the HP scanner, the code is capable of dealing with a Toshiba scanner and an NEC scanner that uses the same chip. Some of the unnecessary code is executed, so there is an additional challenge in determining which parts of the Windows driver code actually has relevance to the scanner we are trying to produce a driver for.
This scanner is based on the RTS8801C2 chip. Other chips in the RTS8801 family include the RTS8801B, the RTS8801C1, and the RTS8801D. Unfortunately the data sheet for these chips only contains information suitable for designing hardware to use the chips - not for designing software.
This scanner is also based on the RTS8801C2 chip.
This is the same device as the 3570C, and the model number you get depends on your geographic market.
RealTek is a chip design firm; actual fabrication (along with access to design tools and technical documentation) is handled by other firms, apparently.... the following (edited) paragraphs are from a RealTek press release:
"Hsinchu, Taiwan – May 28, 2004 – Realtek Semiconductor Corp. today announced the release of a series of dual-band (2.4GHz/5GHz) triple-mode (IEEE 802.11a/b/g) all CMOS WLAN chipsets. The new series, coded Realtek RTL8185L, RTL8187L, RTL8225, and RTL8255, utilize the 0.18µm CMOS manufacturing process of Taiwan Semiconductor Manufacturing Company, Ltd. (TSMC), providing customers with more economic and competitive solutions for Wireless LAN applications. With the release of the new products, Realtek ranks among the world's top three IC design houses, providing complete CMOS WLAN solutions and technologies.
TSMC's leading 0.18µm RF CMOS features high stability and low power consumption, and provides complete design tools, services, and support, including command files for EDA, comprehensive technical documents on the manufacturing process, and detailed information on device models.(emphasis added by mwagy)
Perhaps RealTek can't release the documents we need because they don't hold the rights to them...
Each chip has a number of General Purpose I/O lines (GPIO). These lines are believed to be what is used to enable device-specific inputs (buttons) and outputs (LEDs or LCDs). The location of the registers that deal with these GPIO lines varies significantly between the two chips. The 8801C2 has 37 of these GPIO lines, and the 8801C1 has 10 of them. It is unknown how many the 8891 has. Each line corresponds to a single bit of input or output. Many of the GPIO registers also double in other roles.
The 8801C2 can do 8, 10, 12, or 16 bits of colour per channel in full colour mode (for 24-48 bits per pixel), and 1, 8, 10, 12 or 16 bits grayscale. Its vertical resolution can be 1200, 600, 400, 300, 200, 150, 100, 75, 50 or 25 lines per inch. Horizontal resolution depends on the CCD and can go up to 2400dpi for an A4 page (the maximum number of horizontal pixels is 32768).
The chip supports an on-chip compression scheme so that compressed data can be sent over the USB.
The chip can be connected to a CCD (charge coupled device) or a CIS (contact image sensor). Some of the pins have different functions depending on which type of scanning device is present. Since the 3500C uses a CCD, only the CCD functions are listed here.
The following sets of pins exist on the 8801C2:
| Pin set name | Number of Pins | Pin Type | Purpose |
|---|---|---|---|
| GPIO | 37 | Digital | General purpose I/O |
| PSRCS | 1 | Digital Out | Serial EEPROM chip select |
| ASP (Analog Signal Processor) Interface | |||
| AAVSS | 2 | Analog In | Analog VSS |
| AGND | 1 | ||
| AAVDD | 1 | Analog In | Analog VDD |
| AC | 3 | Analog In | Three colour components |
| AVCLPT | 1 | Analog Out | Top clamping voltage reference |
| AVCLPM | 1 | Analog Out | Middle clamping voltage reference |
| AVCLPB | 1 | Analog Out | Bottom clamping voltage reference |
| AITEST | 1 | Analog Out | Band-gap bias current probe |
| AVBGP | 1 | Analog Bidirectional | Band-gap voltage reference |
| AVRB | 1 | Analog Out | Low ADC voltage reference |
| AVRT | 1 | Analog Out | High ADC voltage reference |
| System control | |||
| MID | 4 | Digital In | Model ID and Test mode register |
| TME | 1 | Digital In | Test mode enable |
| PRST | 1 | Digital In | System reset |
| USI | 1 | Digital Out | USB state indicator |
| Power | |||
| DVDD | 5 | Digital In | Digital VDD |
| DVSS | 5 | Digital In | Digital VSS |
| PVSS | 1 | Digital In | Digital VSS |
| Peripheral interface (notably Tranparency Adapter) | |||
| PLED | 1 | Digital Out | Status LED indicator |
| TAD | 1 | Digital In | TA present |
| PHSM | 1 | Digital In | Main home sensor |
| PMM | 6 | Digital Out | Main motor drive |
| PMT | 6 | Digital Bidirectional | TA motor drive (uses GPIO pins) |
| PLLT | 3 | Digital Bidirectional | TA LED (uses GPIO pins) |
| PHST | 1 | Digital Bidirectional | TA home sensor (uses GPIO pins) |
| PLCM | 1 | Digital Out | Main cathode flourescent lamp |
| Memory Access | |||
| MA | 10 | Ditital Out | Address bits |
| MDQ | 16 | Digital Bidirectional | Data bits. High 8 can be used as additioinal address bits |
| MRAS# | 1 | Digital Out | Row address strobe |
| MCAS# | 1 | Digital Out | Column address strobe |
| MWE# | 1 | Digital Out | Write enable |
| MOE# | 1 | Digital Out | Output enable |
| CCD (Charge Coupled Device) Interface | |||
| CCLP | 1 | Digital Out | CCD clamp clock |
| CRS | 1 | Digital Out | Reset CCD clock |
| CSMP | 1 | Digital Out | CCD sample clock |
| CVTR (transfer clock) (transfer clock) | 1 | Digital Out | Line transfer |
| CPH | 2 | Digital Out | CCD shifting clock |
| CSEL | 3 | Digital Out | Colour select |
| USB Interface | |||
| UD+ | 1 | Analog Bidirectional | USB differential |
| UD- | 1 | ||
| UVREF | 1 | Analog Out | USB reference voltage |
| UAVSS | 1 | Analog In | USB transceiver analog VSS |
| UAVDD | 1 | Analog In | USB transceiver analog VDD |
| UBPE | 1 | Digital In | USB bus power enable |
| UEXTRC | 1 | Analog Out | External RC Circuit |
| Clock interface | |||
| XTALI | 1 | Analog In | Crystal (clock) in/out, 6MHz |
| XTALO | 1 | Analog Out | |
The chips each have one configuration (1) with a single interface (0), which in turn has 3 end points:
| ep | Type | Direction |
|---|---|---|
| 0x81 | Bulk | In |
| 0x02 | Bulk | Out |
| 0x83 | Interrupt | ? Possibly used to notify change of GPIO input state |
They do not use control pipes at all - all communications to the device occur using bulk mode. This seems to be fairly standard with USB scanners, and the (deprecated) /dev/usb/scanner* devices on Linux will treat any data written to them as a bulk write, and any data read from them as a bulk read.
The device commands are used to control registers in the chip. The 8891 has 244 registers, and the 8801C has 255. These can be accessed one at the time or a whole sequence of registers may be accessed in a single operation.
The general command sent over the bus has the following format:
| Byte offset | Number of bytes | Meaning | Notes |
|---|---|---|---|
| 00 | 01 | Command | See below |
| 01 | 01 | Register | Zero for commands that do not use registers |
| 02 | 02 | Count |
|
| 03 | |||
| 04- | Variable | Data |
|
All commands are issued with OUT transfers on endpoint 0x81. All data is read with an IN transfer on endpoint 2.
The following commands have been observed:
| Command ID | Read/Write? | Purpose |
|---|---|---|
| 0x80 | Read | Reads one or more registers |
| 0x81 | Read | Read SRAM data |
| 0x88 | Write | Write one or more registers |
| 0x89 | Write | Write SRAM data |
| 0x8a | Write | Write to NVRAM Controller |
| 0x90 | Read | Get count of available data bytes |
| 0x91 | Read | Read data bytes |
Reads the value of one or more registers. The count specifies how may bytes (and hence how many registers) are required to be returned from the device. After issueing the command the host needs to initiate an IN transfer from endpoint 2.
This command reads data from SRAM. See the section Accessing SRAM for information on how the address for the read is determined.
This command sets the register or group of registers specified. Register 0xb3 is a command register and should never be written in the same command as another register. That means if you want to write "all" of the other registers at once you should do so in two blocks - one for 0x00-0xb2 and another for 0xb4-0xfe.
This command writes its data to SRAM. See the section Accessing SRAM for information on how the address for the write is determined.
This command gives instructions to the NVRAM controller. It can be used both to read from and write to NVRAM. When reading, the values are returned one bit at a time through the high bit of register 0x10. The NVRAM controller command path must be enabled by writing 1 to the low bit of register 0x1d before using this command, and disabled by writing 0 to that bit after using this command.
This command reads 3 bytes and its count must always be "3". The return value is the number of bytes of scan data available for retrieval.
This command reads the specified number of bytes of scan data. The count must not be greater than 0xffc0. Additionally, the count should not be an odd number as this will result in data being lost.
The following registers have been identified (In the table, 'R' and/or 'W' or both followed by '?' indicate that the register is read and/or written individually or in a small set (That is, other than when setting all registers as a block), but the purpose of the register is not yet known.
| Register | Purpose |
|---|---|
| 0x00 | Bit 4 (0x10) cleared, possibly enables CCD. If not set, all data is returned as 0x90 |
| 0x02 | DC Offset Item2, Red |
| 0x03 | DC Offset Item2, Green |
| 0x04 | DC Offset Item2, Blue |
| 0x05 | DC Offset Item1, Red |
| 0x06 | DC Offset Item1, Green |
| 0x07 | DC Offset Item1, Blue |
| 0x08 | Bits 0-5: DC Gain, Red |
| 0x09 | Bits 0-5: DC Gain, Green |
| 0x0a | Bits 0-5: DC Gain, Blue |
| 0x0b | ? Only values seen are 0x70 and 0x71. Bit 0 (0x01) may activate the calibration registers 0x02-0x0a |
| 0x10 | Bits 1-5 and bit 7 (0x9f) provide data to be used in the NVRAM control command (0x8a). The other two bits of the NVRAM control commands contain the command sequences. This high bit is used to return data and status information from the NVRAM controller. Bit 0 is also used in conjunction with bit 6 of register 0xd1 for an unknown purpose. Some of these bits are status bits. |
| 0x11 | RW? Contains status information |
| 0x12-0x14 | RW? |
| 0x15-0x19 | RW? |
| 0x1a | RW? |
| 0x1b-0x1c | RW? |
| 0x1d | RW? Contains status information. Bit 0 (0x01) enables the NVRAM controller command path when set. Bit 1 (0x02) is set if the scanner is fully rewound. |
| 0x20-0x22 | |
| 0x25 | |
| 0x28 | Bits 0-4: CDSS1 control. Increasing this value shifts the values returned by the scan further to the high side of the range. |
| Bits 5-7: CVTR (transfer clock)LM1. Always 0xe0 for paper scans. Affects the red channel - possibly controls exposure time | |
| 0x29 | Bits 0-4: CDSC1 control. Always appears to be CDSS1 + 2 |
| Bits 5-7: CVTR (transfer clock)LM2. Always 0xe0 for paper scans. Affects the green channel - possibly controls exposure time | |
| 0x2a | Bits 0-4: CDSS2 control. Always either 0x17 or 0x00. Has something to do with the colour range from the scanner, although it appears to be possible to set this to any value as long as the values of register 0x2c and 0x2d are correctly calculated |
| Bits 5-7: CVTR (transfer clock)LM3. Always 0xe0 for paper scans. Affects the blue channel - possibly controls exposure time | |
| 0x2b | Bits 0-4: CDSC2 control. Always 1. Increasing this value narrows the range of values returned by the scanner |
| Bits 5-7: Unused. Always set to 0x00 | |
| 0x2c | Bits 0-4: Calculated based on the value of CDSS2 - see HP3500C Colour Depth. It seems this register must be written as a single register write (not part of a multiple register write) immediately prior to scanning, otherwise the data returned will be almost all 0xff bytes. |
| Bits 5-7: Always clear | |
| 0x2d | Bits 0-4: Calculated based on the value of CDSS2 - see HP3500C Colour Depth. |
| Bit 5: CPH0S (CCD shifting clock). Varies, purpose unknown. When on, the horizontal co-ordinate space is 1200dpi. When off, the horizontal co-ordinate space is 600dpi | |
| Bit 6: CISCKS (CIS clock). Always clear | |
| Bit 7: CSMPS (CCD sample clock). Always clear | |
| 0x2e | Always set to 0x86, but changing this to 0x00 had no effect. |
| 0x2f | Bit 1 (0x02) turns on colour scanning. Without this bit, all channels return the same value. By instructing the scanner to return only one channel you can get just the greyscale data back. |
| Bit 2 (0x04) is set to merge the channels - the scanner will return lines in the form RGBRGBRGB.... for full colour scanning. There is no point in doing this since there is still the issue of colour displacement to deal with, so you end up shuffling returned data around anyway. | |
| Bit 3 (0x08) has something to do with the lamp. | |
| Bit 4 (0x10) is set to leave channels separate - the scanner will return lines in the form RRR...GGG...BBB... for full colour scanning. | |
| Bit 5 (0x20) appears to be set for single channel scanning | |
| Bits 6-7 (0xc0) selects channel if colour scanning is on - 0x00 = all, 0x40 = red, 0x80 = green, 0xc0 = blue. | |
| 0x30 | Bit 0: Always clear, purpose unknown. Turning it on has no apparent effect |
| Bit 1 (0x02): Always set. Turning it off caused the green and blue channels to be significantly reduced | |
| Bit 2 (0x04): CCLPL (CCD clamp clock). Always clear. Turning it on has no apparent effect | |
| Bit 3 (0x08): CRSL (Reset CCD clock). Always clear. Turning it on caused the values of all channels to shift towards the low end - perhaps disables CDSS1? | |
| Bit 4 (0x10): CSMPL (CCD sample clock). Always clear. Setting it had no apparent effect. | |
| Bit 5 (0x20): CISCKL (CIS clock). Always clear. Setting it had no apparent effect, which is unsurprising since it appears to be CIS related. | |
| Bit 6 (0x40): CVTR (transfer clock)P (CCD line transfer). Always clear. Setting it caused all channels to return very low values | |
| Bit 7 (0x80): RSCLPC. Always clear. Setting it had no apparent effect | |
| 0x31 | Bits 6-7 (0xc0) = CVTR (transfer clock)FPW (CCD line transfer); bits 4-5 (0x30) = CVTR (transfer clock)BPW (CCD line transfer); Bit 0-3 (0x0f) = CVTR (transfer clock)W (CCD line transfer). Setting this to 0x00 and 0xff had no effect |
| 0x32 | W? Bit 6 (0x40) appears to be important - often cleared before (or during) bulk writes of registers to the device, and set afterwards. Possibly controls a double-buffering system on the registers with writes held when the bit is off and writes going through when the bit is on |
| 0x33 | These are normally set to 0, but at some stage they are set to 1 when at the same time the lamp is turned out. This may be part of the calibration sequence |
| 0x34 | |
| 0x35 | |
| 0x36 | |
| 0x37 | |
| 0x38 | |
| 0x39 | Motor resolution divisor. By increasing this value, the CCD moves linearly faster, but also starts returning zeroes for some scan lines. For lower values, the brightness of scan data is reduced. Although this is an 8 bit value, the only values seen are 0x00, 0x01, 0x03, 0x07 and 0x0f. It appears that the value placed in this register is one less than the value used, so that values from 1-256 can be represented by 0-255. Should be set to (1200 / vertical_resolution / step_size - 1) |
| 0x3a | Bit 8 (0x80) controls the lamp status. If on, bit 0 (0x01) in register 0x10 has some effect as well, as does bit 4 (0x10) in register 0x58. Bit 5 (0x20) controls whether the lamp timeout is active. The lamp does not turn on in power save mode if a scan operation is not in progress |
| 0x3b | Lamp duty cycle. Bit 7 (0x80) duty cycle enable. Bits 4-6 (0x70) low 3 bits of frequency. Bits 0-3 (0x0f) Believed to be off duty time, set from byte 0x7B of NVRAM, provided that byte is <= 15 |
| 0x3c | Bits 4-7 (0xf0): CVTR (transfer clock)PMPT2 (CCD line transfer); Bits 0-3 (0x0f): CVTR (transfer clock)PMPT1 (CCD line transfer) |
| 0x3d | Bits 0-3 (0x0f): CVTR (transfer clock)PMPT3 (CCD line transfer); Bits 4-6 (0x70): Maximum exposure time (always 0 for paper scans - may differ for transparency and film scans). Bit 7 (0x80): high bit of lamp duty cycle frequency. Other than bit 7, changing this has no apparent effect. |
| 0x40 | Bits 0-5: Some of these appear to be related to calibration information - perhaps enable various parts of the SRAM based calibration? Bits 0-3 appear to have something to do with the contents of SRAM. |
| Bit 0 (0x01): Enables offsets (that reduce the output value) in SRAM calibration. | |
| Bit 1 (0x02): Involved in SRAM calibration | |
| Bit 2 (0x04): If set, SRAM calibration is signed (it can either increase or decrease the value returned). If clear, SRAM calibration can only decrease the value returned. | |
| Bit 3 (0x08): Enables the gamma table (768 bytes at SRAM address 0) | |
| Bit 4 (0x10): Seems to be related to compression. Setting this bit causes the entire scan to come back as apparently random values | |
| Bit 5 (0x20): Needs to be on for SRAM calibration to be active | |
| Bits 6-7: Motor movement clock multiplier. The driver uses this to create a logical co-ordinate space as follows: 0x00=1000000, 0x40=1500000, 0x80=2000000. Lower values slow down movement without affecting resolution. | |
| 0x50 | ?? |
| 0x51-0x52 | ?? A 16 bit value |
| 0x58 | RW? Contains status information. Bit 4 (0x10) has something to do with the lamp status. Perhaps the scanner sets or clears it when the lamp is warmed up? If so, this requires it to be set to the other value first. |
| 0x60-0x61 | Distance to move before commencing scan |
| 0x62-0x63 | Total distance to move |
| 0x64 | Bits 0-3 (0x0f): scanning frequency. If this is 1, the CCD is read for every unit of movement. If it is 4, the CCD is read for every 4 units of movement. |
| Bit 4 (0x10): When set, the scanner did not stop when it reached the end of the scan range (perhaps disables checking 0x62-0x63) | |
| Bit 5 (0x20): When set, the scanner did not return data and did not stop until it reached the end of the scan range (perhaps disables checking 0x60-0x61) | |
| Bit 6 (0x40): Had the same effect as bit 4 | |
| Bit 7 (0x80): Had the same effect as bit 5 | |
| 0x65 | If bit 7 (0x80) is not set, no data is returned from the scanner. Other bits have no apparent effect |
| 0x66-0x67 | Horizontal start position. Always expressed in terms of 600dpi or 1200dpi according to CPH0S, regardless of scanning resolution |
| 0x68-0x6b | Setting these has no apparent effect |
| 0x6c-0x6d | Horizontal end position. Always expressed in terms of 600dpi or 1200dpi according to CPH0S, regardless of scanning resolution |
| 0x6e-0x6f | Setting these has no apparent effect. Bit 7 (0x80) of 0x6f may contain status information |
| 0x70-0x78 | Setting these had no apparent effect. Bit 7 (0x80) of 0x71, 0x73 and 0x75 were clear even after setting these registers to 0xff, and may contain status information |
| 0x79 | Bits 0-3: These have no apparent effect |
| Bits 4-6 (0x70): At least one bit must be set, otherwise no data is returned from the scanner. If all three are set, register 0x7a is ignored. If any two are set, the horizontal co-ordinate space is 1200 regardless of the value of CPH0S. Normally set to 0x40, and this is the only value used by the Windows driver | |
| Bit 7 (0x80): Appears to contain status information | |
| 0x7a | Horizontal resolution divisor. Divides into co-ordinate space as per CPH0S |
| 0x7b-0x7f | Setting these had no apparent effect, and the value of the registers remained at 0 even when set to 0xff |
| 0x80-0x81 | ?? A 16 bit value, probably an SRAM address |
| 0x82-0x83 | ?? A 16 bit value, probably an SRAM address |
| 0x84 | Together with the high 4 bits of 0x8e, contains the 12 bit byte address in SRAM of the red calibration data. |
| 0x85-0x86 | SRAM address of green calibration data (byte address) |
| 0x87-0x88 | SRAM address of blue calibration data (byte address) |
| 0x89-0x8a | First page in SRAM to use for buffering scan data. Set this to be the first page after the blue calibration data. |
| 0x8b-0x8c | Last page in SRAM to use for buffering scan data. This should be set to the highest page in SRAM - the more SRAM buffer space you allocate to scan data the faster data is returned from the scanner. |
| 0x8d | Movement related. May include compression flags. |
| 0x8e | Bits 0-3 (0x0f): Movement related. May include compression flags |
| Bits 4-7 (0xf0): High 4 bits of byte address of red calibration data in SRAM | |
| 0x8f-0x90 | ?? A 16 bit value, probably an SRAM address |
| 0x91-0x92 | SRAM page number |
| 0x93 | Bits 0-3: SRAM Access Method |
| 0x94 | The Windows driver always sets this to 0x0e - effect of this is unknown. |
| 0xb0 | R? Contains status information. Values seen: 0x12 |
| 0xb1 | Contains status information, but never read by the Windows driver |
| 0xb2 | Bits 0-1 (0x03): No apparent effect |
| Bit 2 (0x04): If set, the scanner will not return image data | |
| Bit 3: (0x08): If set, the scanner will automatically rewind after finishing scanning. Note that it won't stop when it reaches the home position if bit 4 is not set, but if you sest bit 4 and started the scan from the home position, the scanner will not move forwards. | |
| Bit 4 (0x10): If set, the motors will stop when the CCD triggers the "home" switch, otherwise the motor will keep going. Works even if the scanner would be moving forwards (away from the home switch) | |
| Bit 5 (0x20): If set, the scanner will not return data, and appears to ignore the movement destination registers. | |
| Bit 6 (0x40): If set, the scanner keeps moving forward even after it has finished returning data | |
| Bit 7 (0x80): Setting this has no apparent effect | |
| 0xb3 | Bit 3 (0x08): Start/stop movement, test if moving. Bit 2 (0x04): Set/test power-saving mode. It appears this register must be written twice for the change to take effect |
| 0xc0-0xc2 | Normally only one bit set at a time. Stored low byte first. Only value I have seen is 0x800000 Movement pattern multiplier? |
| 0xc3 | Bits 0-4: Coordinate space denominator |
| Bit 5: Unknown | |
| Bit 6: Unknown. The Windows driver sometimes sets it, after clearing bit 7 of this register and setting bit 3 of register 0x1d, but the purpose of this is unclear. | |
| Bit 7: Motor enable - if this is not set, the CCD will not move, but the device will behave in most respects as if it did. This will include returning scan data. | |
| 0xc4 | Bit 4-7 (0xf0) have something to do with "MSI" |
| 0xc6 | Bits 0-2 (0x07): Step size: 0x3 = 1, 0x1 = 0.5, 0x4 = 0.25. With a value of 0x01 the CCD moves twice as far as with a value of 0x04 (and scans at half the vertical resolution). Other values don't appear to work at all |
| Bit 3 (0x08): sets the movement direction (1 = forward, 0 = rewind). | |
| Bits 4-5: Seen with values 0x00, 0x20 and 0x30. Purpose unknown. Changing this appears to do nothing | |
| Bit 6: Apparently unused | |
| Bit 7: Seen both set and cleared, purpose unknown. Changing it appears to do nothing | |
| 0xc7-0xc8 | Motor watchdog timeout |
| 0xc9 | Bits 0-2: Motor type (Always 2) |
| Bits 3-5: Purpose unknown. Always 0x38 | |
| Bits 6-7: Appear to be unused. Always 0 | |
| 0xd0 | Contains status information: HP3500C button state (also indicates if the transparency adapter is present). Appears to also have another purpose. If a value is written to 0xd2, this register will contain the same value |
| 0xd1 | R? Contains status information. Values seen: 0x40, 0x4c, 0x0c. Bit 6 (0x40) is set if power save mode is on (presumably this requires that some other condition be satisfied too otherwise the bit would merely echo information in 0xb3). Bit 6 is used in conjunction with bit 0 of register 0x10 for an unknown purpose. Also has another purpose. If a value is written to register 0xd3, it can be read back from this register |
| 0xd2 | A value written to this register can be read back from register 0xd0 |
| 0xd3 | Bits 0-2: Purpose unknown. Always set by the Windows driver. |
| Bit 3 (0x08): If this bit is cleared, the horizontal resolution is halved and the image gets substantially darker | |
| Bit 4 (0x10): Purpose unknown. Always set by the Windows driver. | |
| Bits 5-7: Purpose unknown. Always cleared by the Windows driver | |
| 0xd9 | |
| 0xda | Sticky state of buttons (see 0xd0) |
| 0xe0-0xe1 | 3Bounds of movement range 1 |
| 0xe2 | Step size for movement range 0 |
| 0xe3 | |
| 0xe4-0xe5 | Bounds of movement range 0 |
| 0xe6 | Step size for movement range 1 |
| 0xe7-0xe8 | Bounds of movement range 2 |
| 0xe9 | Step size for movement range 2 |
| 0xea-0xeb | Bounds of movement range 3 |
| 0xec | Step size for movement range 3 |
| 0xed-0xee | Bounds of movement range 4 |
| 0xef | Step size for movement range 4 |
| 0xf0-0xf2 | CPH0 (CCD shifting clock) control (Only values seen are 0x1ffe0 and 0x7ff800) |
| 0xf3-0xf5 | CISCK (CIS clock) control (Always 0 for 3500C) |
| 0xf6-0xf8 | CSMP (CCD sample clock) control (Always 0) |
| 0xf9-0xfb | CRS (Reset CCD clock) control (Only values seen are 0x3c0000 and 0x300000) |
| 0xfc-0xfe | CCLP (CCD clamp clock) control (Only values seen are 0x003000 and 0x060000) |
Registers just after power on:
00: f5 41 00 00 00 00 00 00 00 00 00 70 00 00 00 00 10: e1 fc ff ff 00 00 00 fc 00 00 00 00 00 02 00 00 20: 00 00 00 00 00 00 00 00 00 00 00 00 00 01 06 19 30: d0 7a 00 00 00 00 00 00 00 00 a0 37 ff 0f 00 00 40: 80 00 00 00 24 0c 00 00 00 00 00 00 00 00 00 00 50: 20 02 00 00 00 00 00 00 1d 1f 00 1f 00 00 00 00 60: 10 00 00 00 00 00 0b 08 00 08 10 10 00 01 01 0c 70: 00 20 00 00 00 00 40 00 20 08 00 00 00 00 00 00 80: 00 00 00 01 00 08 00 40 00 00 00 04 00 50 00 00 90: 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 a0: 00 00 00 0c 27 64 00 00 00 00 00 00 00 00 00 00 b0: 12 08 06 04 00 00 00 00 00 00 00 00 00 00 00 00 c0: 04 40 00 00 10 00 00 00 00 00 00 00 00 00 00 00 d0: ff bf ff ff 00 00 ff ff 00 00 00 00 00 00 00 00 e0: 00 00 0f 00 00 00 00 00 00 00 00 00 00 00 00 00 f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
The NVRAM associated with an RTS8801C will normally be either 128 bytes, 512 bytes or 2048 bytes. In the HP 3500C it is 128 bytes.
Before writing to the NVRAM, an NVRAM write enable command must be issued. This is presumably to protect the NVRAM from being inadvertently overwritten by a malfunctioning program. After writing the NVRAM, a write disable command should be written.
Before issuing, and after completing, a sequence of NVRAM commands effecting a read or write of one byte, the NVRAM controller should be enabled/disabled by setting/clearing the low bit of register 0x1d.
Additionally, the changes to registers 0x12 and 0x14 need to be made as described elsewhere.
Before reading or writing, an NVRAM command needs to be issued to select the addressing block size (which may select among three available blocks of NVRAM).
NVRAM write and read commands are issued by the 0x8a command. When reading, data and status codes are read back through the high bit of register 0x10 one bit at a time, with an NVRAM command issued for each bit to be read.
The "register" byte of the NVRAM command is normally 0x00, but is 0x1d when issuing a "read data" or "read bit" command to the NVRAM controller.
For the SANE driver, hopefully we can avoid writing to NVRAM at all.
The device also has SRAM. It has been suggested that this is used for calibration, which may or may not be true, but it may be used for something other than calibration. The log files list the SRAM commands as "WCAL" and "RCAL", reflecting an earlier belief that these were calibration commands rather than SRAM access commands.
The amount of SRAM will be between 128KB and 2MB, and will always be a multiple of 128KB. The values stored by the driver in 0x8b-0x8c suggest that the 3500c has 512KB of SRAM. Our own tests confirm this.
Registers 0x91-0x92 set the "page" to access. A page is 32 bytes long. You can then read or write using the SRAM read or write commands. The first access after setting the page will be to or from the start of the page. The next access will be to the first byte after the end of the last read - effectively there is a file pointer for SRAM. A read or write can cross a page boundary. If you have crossed a page boundary you can read registers 0x91-0x92 to see what page you are now in, but you cannot tell what position in the page you are at. This scheme gives the maximum addressable SRAM size of 2MB (65536 pages of 32 bytes each).
Register 0x93 appears to tell the scanner how to access SRAM - it seems that only the low 4 bits are significant, as the high 4 bits are always zero, and the Windows driver only adjusts the low 4 bits. Early on in the scan sequence the Windows driver writes a 2072 (0x818) byte long cycle of 0x00-0x61 to SRAM page 0x81 (129, SRAM address 0x120) a number of times. This data is not used by the scanner - this is the driver trying to figure out what settings to use in register 0x93 to access the SRAM. It tries the values: 0x06, 0x02, 0x01.
The SRAM write commands will not work in power save mode, so turn that off before attempting a write.
There appear to be some bugs when writing large amounts of data to SRAM in one go. If you attempt to write 512 bytes or 768 bytes, it appears something never returns. If you attempt to write 2048 bytes, the next attempt to set the page will have no effect. The bug may be in the chip, or may be in libusb, or in the Linux kernel. Regardless, we should try to limit writes to SRAM to 256 bytes except where absolutely necessary to emulate the behaviour of the Windows driver.
In the control panel, the driver can be configured to dump logging information to a file.
Also, you can set up logging by editing/adding values to the registry:
[HKEY_LOCAL_MACHINE\Software\Hewlett-Packard\ScanJet\Tulip\{75D4D64E-B90B-4247-B6F9-E6794EFCE90E}]
"LogEnabled"=dword:00000001
"LogLevel"=dword:ffffffff
"LogDestination"=dword:ffffffff
"LogFile"="C:\\Log\\scanjet1.log"
[HKEY_LOCAL_MACHINE\Software\Hewlett-Packard\ScanJet\Tulip\{30200BA3-B35B- 11D5-B019-0001022D4135}]
"LogEnabled"=dword:00000001
"LogLevel"=dword:ffffffff
"LogDestination"=dword:ffffffff
"LogFile"="C:\\Log\\scanjet2.log"
It also appears to be possible to get the driver to write the settings it is using to an INI file called "rtscan.ini", which should be placed in the same directory as hpgt35.dll. To get it to write settings to that file, create the file with contents as follows:
[PLATFORM] WriteIniFile=1
When you have finished generating the file you should rename it, otherwise the driver will then use some of the settings found in that file in future scans, which may prevent it from calculating more appropriate values.
There are a number of processed USB logs of scans showing the changes in values of registers here.
Take care with these logs - it seems that sometimes the snoop programs drop bytes here and there (and sometimes even insert some) so the log will get out of sync (for example, by showing values going into different registers than they are really going into).
Additionally, large SRAM writes are truncated due to limitations in the USB snooping tools, and the truncated data is replaced with NUL bytes (zeroes).
The reads and writes of 13 registers in a single block beginning at 0x10 are only used to modify the values of registers 0x12 and 0x14. Bits 4-7 (0xf0) of 0x12 are set. Bits 5-6 (0x60) of 0x14 are set, and bit 7 (0x80) of 0x14 is cleared. No other changes are made in this sequence, and none of the values tested or used. The Windows driver code actually does a lot more, but everything else turns out to be a no-op when the values are traced.
When register 0xb3 is read, it is used to test one bit. This is why the register is read twice in the initialisation sequence - once to test bit 3 (0x08) and once to test bit 2 (0x04).
Don't bother looking for information for 200dpi, 100dpi or 400dpi scans - the Windows driver doesn't scan at these resolutions, despite what the user interface tells you. If you select these resolutions in the UI, the driver scans at the next highest resolution in its list and discards every third line returned from the scanner. The only resolutions that the Windows driver will actually scan at are: 75, 150, 300, 600 and 1200.
The scan area is 0.5 inches (12.7mm) from the home position. There is a 4mm calibration strip starting at the home position. The calibration strip is light grey (70%-80% in al three channels). The CCD begins approximately 5mm before the starting edge of the glass area.
There are (at least) six rows of elements in the CCD - two for each channel. Each row has 600 elements per inch. The red, green and blue components of a scan are therefore offset from eachother by a fixed amount ("color displacement", approximately, 0.45mm), and the two rows for each colour are offset from eachother such that they scan areas approximately 0.085mm apart (intra-channel displacement). The driver will need to compensate for this. In a 1200dpi scan the colour displacement is approximately 22 pixels, and the intra-channel displacement is approximately 4 pixels.
Intra-channel displacement is only likely to be an issue in 1200dpi and 400dpi scans. The Windows driver software appears to avoid this for 400dpi scans by not allowing the user to select that resolution.
There may be two additional rows that are used when performing black & white scanning.
The following registers are known to be involved in movement: 0x39, 0x40, 0x2f, 0x60-0x63, 0x64, 0x66, 0x67, 0x6c, 0x6d, 0x7a, 0xb2, 0xc3, 0xc6, 0xe0-0xef. Movement is complex. The 0x32 "locking" bit is also involved in the register writes.
The range at 0xe0-0xef appears to provide for setting up a table to be used by the chip for accelerated scanning. It appears the scanner starts with range 0, and when the remaining distance to be travelled drops below the distance covered by range 0, proceeds to range 1, and so on.
When reading scan data you must read an even number of bytes - if you read an odd number there will be a byte in the data stream immediately after your read that will get dropped entirely. The result of this is that the image appears to shift to the lefts if the edges are mostly grey. By putting a black sheet of paper and red sheet side-by-side (overlapping a little), you can see that when retrieving in RRRRRR...GGGGGG...BBBBBB... format, a red pixel shifts into the blue, a blue into the green, and a green into the red, each time this happens.. The frequency with which bytes are lost seems to vary with the value in registers 0x8b/0x8c, with lower values down to 0x2ff (linearly from 0x7fff) causing more frequent losses, and values higher between 0x8000 and 0x1ff causing less frequent losses.
To turn the lamp on, bit 7 (0x80) must be set in register 0x3a, as well as bit 0 (0x01) in register 0x10, and it seems bits 4-7 (0xf0) in register 0x58 must be cleared.
The intensity of the lamp can be controlled by activating the duty cycle and setting the duty cycle frequency (DCFQ), together with the off duty time (ODT). If MAXV is the maximum voltage applied to the lamp, and MINV is the minimum voltage (provided the lamp is on) it appears that this causes the voltage to the lamp to be approximately MINV + (MAXV - MINV) * (DCFQ - ODT) / DCFQ. It appears that the default settings used by the driver are DCFQ = 10, ODT = 6, thus setting the voltage to near the middle of the available range.
The vertical resolution is controlled by the values in the low 3 bits of each of register 0xc3 and 0xc6, and the value in register 0x39. The following table shows the available resolutions. Note that resolutions of 4800lpi and 9600lpi are somewhat theoretical (they don't work, and nobody ever claimed they would), but 2400 and below work. Where there are multiple combinations, the preferred combination is determined according to the following priorities:
| Resolution | 0x39 | 0xc3[0-2] | 0xc6[0-2] |
|---|---|---|---|
| 25 | 15 | 1 | 3 |
| 50 | 15 | 1 | 1 |
| 50 | 7 | 1 | 3 |
| 75 | 15 | 3 | 3 |
| 100 | 15 | 1 | 4 |
| 100 | 3 | 1 | 3 |
| 100 | 7 | 1 | 1 |
| 150 | 15 | 3 | 1 |
| 150 | 15 | 6 | 3 |
| 150 | 7 | 3 | 3 |
| 200 | 1 | 1 | 3 |
| 200 | 3 | 1 | 1 |
| 200 | 7 | 1 | 4 |
| 300 | 15 | 3 | 4 |
| 300 | 15 | 6 | 1 |
| 300 | 3 | 3 | 3 |
| 300 | 7 | 3 | 1 |
| 300 | 7 | 6 | 3 |
| 400 | 0 | 1 | 3 |
| 400 | 1 | 1 | 1 |
| 400 | 3 | 1 | 4 |
| 600 | 1 | 3 | 3 |
| 600 | 15 | 6 | 4 |
| 600 | 3 | 3 | 1 |
| 600 | 3 | 6 | 3 |
| 600 | 7 | 3 | 4 |
| 600 | 7 | 6 | 1 |
| 800 | 0 | 1 | 1 |
| 800 | 1 | 1 | 4 |
| 1200 | 0 | 3 | 3 |
| 1200 | 1 | 3 | 1 |
| 1200 | 1 | 6 | 3 |
| 1200 | 3 | 3 | 4 |
| 1200 | 3 | 6 | 1 |
| 1200 | 7 | 6 | 4 |
| 1600 | 0 | 1 | 4 |
| 2400 | 0 | 3 | 1 |
| 2400 | 0 | 6 | 3 |
| 2400 | 1 | 3 | 4 |
| 2400 | 1 | 6 | 1 |
| 2400 | 3 | 6 | 4 |
| 4800 | 0 | 3 | 4 |
| 4800 | 0 | 6 | 1 |
| 4800 | 1 | 6 | 4 |
| 9600 | 0 | 6 | 4 |
Register 0x7a controls horizontal resolution - the resolution is based on the co-ordinate space as defined by CPH0S (see register 0x2d) divided by the value in 0x7a. The sensible values returned by this calculation are as shown in the table below. If you use a resolution with fractional amounts, the number of pixels returned for any particular scan range is rounded up.
| Resolution | Register 0x7a (CPH0S = 0) | Register 0x7a (CPH0S = 1) |
|---|---|---|
| 25dpi | 0x18 | 0x30 |
| 50dpi | 0x0c | 0x18 |
| 60dpi | 0x0a | 0x14 |
| 75dpi | 0x08 | 0x10 |
| 100dpi | 0x06 | 0x0c |
| 120dpi | 0x05 | 0x0a |
| 150dpi | 0x04 | 0x08 |
| 200dpi | 0x03 | 0x06 |
| 240dpi | 0x05 | |
| 300dpi | 0x02 | 0x04 |
| 400dpi | 0x03 | |
| 600dpi | 0x01 | 0x02 |
| 1200dpi | 0x01 |
There appear to be two ways to calibrate the scanner - the "new" method, and the "old" method. One of these uses the 9 registers starting at register 0x02 to calibrate the entire CCD. The other one is believed to be able to calibrate each element of the CCD individually.
With the 9 registers, there are two sets of three "offset" registers (zero may be represented by 128, with lower values being negative offsets, and the second set appears to always be the same as the first), followed by one set of three "gain" registers.
When using the 9 registers, the first two sets of three almost always have identical values.
It seems that either the simple calibration methods will not calculate the second set of CCDs, or the second set reacts differently to the first set. This means that for 1200dpi scanning you cannot just rely on the simple calibration registers, otherwise you end up with alternating lighter and darker pixels across a row.
In addition to the calibration records a gamma table can be stored in SRAM at address zero. The table is 768 bytes - 512 for each channel. It seems each pair of bytes applies to one input value and supplies the output value. It looks like the gamma table is applied after detailed calibration. This table is enabled by bit 3 in register 0x40;
As a non-technical matter - when scanning at 1200dpi, make sure the glass is very clean. At that resolution, dust will show up clearly in the scan data, as will any stray hairs that found their way onto the glass.
(The description here is definitely preliminary, and subject to change as more is understood - the reverse engineering involved here is complex).
The Windows driver reads 20 scanlines worth of data from a grey (approximately 70-80% white - #b2b2b2-#cccccc) strip inside the scanner 4mm wide. These calibrations are done after disabling the motor so that any resolution can be calibrated using this strip.
The scanner then attempts to remove outlying points from the sample, although it does this in an inconsistent manner. It generally tries, for each CCD element, to find the most frequently occurring value (mode) and take values from 30 points around it. There's several bugs in this code in the Windows driver, hence the inconsistencies.
Having taken its sample, it enters into a calculation that is equivalent to taking half the average of the values kept in the sample, rounding up to the nearest integer. We will call this value "x".
Each channel (R, G, B) has a "target code". The default target code is 0xe0, but the target code can vary depending on type of scan (paper, transparency, negative), resolution, and whether the scan is monochrome or colour. We will call this value "t".
It is also possible to scan with 8 bits per channel or 10 (for 256 or 1024 values respectively). We will call the number of bits per channel "b".
The calibration value for a given CCD element on a given channel is:
65536 * t / (x << (16 - b)) [This is not quite right]
Calibration values are stored as 10 bit values. Each pixel's calibration data takes up two bytes, with the low 2 bits of the data in the high two bits of the first byte, and the high 8 bits in the second byte. The low bit of the first byte appears to have some significance too - the Windows driver always sets that bit.
Once the calibration values have been calculated for a whole scan line of CCD elements (the width of the scan line varies with the width of the horizontal area to be scanned), they are stored in SRAM as one array for each channel at the full resolution adjusted for CPH0S (that is, either 600dpi or 1200dpi).
The SRAM address of the red channel calibration data goes into registers 0x84/0x8e (see the register table above). The SRAM address of the green channel calibration data goes into registers 0x85/0x86. The SRAM address of the blue channel calibration data goes into registers 0x87/0x88. Because there are only 112 bits to represent the address of the red channel calibration data, this should appear first - data for one channel can easily exceed the 4096 bytes that are the maximum value that can be represented by the 12 bits (on the 3500C, the calibration data can be approximately 20K long for a single scan line).
The SRAM calibration information needs to be enabled by appropriate settings in register 0x40.
Note that the logs of SRAM writes are not particularly helpful here since the writes of calibration data exceed a limit in the USB snoop programs and are padded with zeroes (newer versions of the snoop programs on more modern systems seem to have avoided this problem).