[sane-devel] Reflecta Crystalscan / ProScan 7200 update

Vleeshouwers, J.M. J.M.Vleeshouwers at tue.nl
Tue Dec 20 22:26:52 UTC 2011

We have a working backend for Reflecta CrystalScan & ProScan 7200, but we
did not succeed in interpreting all the data from the Windows logs. I have
analysed the firmware provided by Reflecta to get a bit further. The firmware
is an older version of the one currently available in the scanners, but
probably not that different. It is regular 8052-code. The disassembly
confirms what we already thought, but there are some new conclusions:

1. There really is no option to download gamma-tables. (However: there is a
call in the firmware that generates 4096 values (from 0 to FFF) for each
color and stores it in RAM. And there is also a command (0x3B) that allows
writing to RAM. So maybe...)

2. MODE SELECT (0x15) has a couple of additional settings, in bytes 10 and
up, mostly still quite mysterious. One of the bits enters a SCAN mode in
which each line is scanned and read individually, by command 0xF4. It also
looks like we have a "fast" scan mode next to the "normal" and "quality"
scan mode.

3. The SET GAIN OFFSET (0xDC) sets gain and offset values for RGBI, and also
has three other bytes (15-17) which are active. But that's about all I can
say about them;)

4. The INQUIRY command returns even more than the 184 bytes specified in its
header. The additional data is the specification of how the scanner scans a
line, with color masks and scan times (see below).

5. The scan frame WRITE (0x0A) and READ (0x08) commands allow to define at
most 8 different windows. It's not clear to me how that might be used or be

6. In the logs, the PARAM (0x15) command only returns 0 for "Period". In the
firmware it is not 0: it is set to something proportional to the total scan
time of a line, but more or less inversely proportional to resolution.
I cannot make sense of this. The "ScsiTransferRate" value is proportional to
line size and inversely proportional to the time it took to scan it.

7. The READ GAIN OFFSET command (0xD7) returns current gain and offset
values, as we already concluded, but also full-scale values resulting from
the auto-calibration performed by the scanner. The strange valued
bytes which puzzled us so far (78-97), appear to be uninitialised RAM.

8. The READ STATUS command (0xDD) contains only a minimal amount of data:
flags for button pushed, warmed up, SCAN executing, motor direction, and
post-warming-up code running (probably).

9. There are 22 commands available which are not used by the Windows driver;
see the list below. Some of them are regular, but most of them I named after
the function I'm more or less guessing they perform. I did not yet give
these new commands a try.

I would like to make more sense of the MODE SELECT scan quality options
("quality", "normal", and possibly also "fast"). These MODE SELECT bits
affect a table which defines how a line is scanned. (From its location in
memory, I'm calling it the BADF-table.) The BADF-table contains a variable
amount of 4-byte entries. Each entry consists of
a) a 2-byte counter value for 8052-timer 1, which determines when the next
interrupt happens, so how long this entry is active;
b) a byte which contains a color mask;
c) a byte which contains a bit indicating the last entry, and another bit
which function is unclear to me.
The Timer-1 interrupt handler accesses 8052-port 1 and several memory
locations which must be ports to hardware. I have probably identified the
external RAM port, the motor control port(s?), the USB-ports, and part of
the scanner controller, but still most of the action remains unclear.

Two questions with respect to that:
a. Would it be possible to identify the scanner controller hardware from
how the ports are used? For example, offset values appear to be set with a
separate sign bit. A GL846 doesn't have that as far as I can see, but are
there any known controllers which do? The controller gain/offset appears to
be set through registers 0x20/0x30/0x40 (red/green/blue gain), 0x50/0x60/0x70
(red/green/blue positive offsets), 0x51/0x61/0x71 (red/green/blue negative
offsets). Might this be an indication?
b. Is there any description available of the scanning process of a CCD-
scanner in full detail? I have seen a couple of data-sheets which give a
rough idea, but I wonder if there is anything more detailed? 

That's it for today - hope some of you experts can help us with this.



Command list - settings & operation commands


WRITE (0x0A/0x01)
(not logged)
Unclear, may initiate post warm-up code

WRITE (0x0A/0x11)
(not logged)
Write custom halftone pattern data

WRITE (0x0A/0x12)
(not logged)
Define up to 8 scan frame windows

WRITE (0x0A/0x13)
Set exposure time (but that setting remains unused)

WRITE (0x0A/0x14)
Set highlight/shadow (but that setting remains unused)

WRITE (0x0A/0x16)
Write 2 x 5430 bytes, for each color

(WRITE can be without data, just a code & X bytes, to set code for subsequent READ)

Sets scan parameters
   0-  1	MODE SELECT data size
   2-  3	Resolution
   4		Bit 0 if set: Neutral (not supported)
		Bit 1 if set: Red
		Bit 2 if set: Green
		Bit 3 if set: Blue
		Bit 4 if set: Infrared
		Bit 5-6: unused
		Bit 7 if set: one pass color (if not one pass color, max 1 col bit may be set)
   5		Bit 0 if set: 1 bit color depth (max res 3600)
		Bit 1 if set: 4 bit color depth
		Bit 2 if set: 8 bit color depth
		Bit 3 if set: 10 bit color depth
		Bit 4 if set: 12 bit color depth
		Bit 5 if set: 16 bit color depth
		Bit 6-7: unused
   6		Bit 0 if set: Pixel color format
		Bit 1 if set: Line color format
		Bit 2 if set: Index color format
		Bit 3-7: unused
   7		(unused)
   8		Bit 0: unused
		Bit 1: byte order (although logged value 0x01)
		Bit 2-7: unused
   9		Bit 0: unused
		Bit 1: “quality” scan flag (adds entry to BADF-table)
		Bit 2: unused
		Bit 3: “normal” scan flag (version dependent if bit should or shouldn't be set together with bit 1)
		Bit 4-6: unused
		Bit 7 if set: possibly a low quality flag (related to infrared)
  10		Bit 0-2: unused
		Bit 3 if set: number of lines = 14
		Bit 4: unused
		Bit 5 if set: single step operation after SCAN command
		Bit 6 if set: use y0 = 3000, y1 = 4000, filter offsets 0
		Bit 7: unused
  11		Bit 1: overrides byte 8 bit 1 (byte order)
  12		Halftone pattern
  13		Line threshold
  14		Bit 0 if set: additional action after READ
		Bit 4-7 if >= 2: skip specific initialisation
  15- 31	unused

(not logged)
Input data to RAM

Several reset actions

(not logged)
Write data to RAM and call ROM routine 014E (unknown)

Set values for gan and offset
   0-  1	Timer 1 count for Red
   2-  3	Timer 1 count for Green
   4-  5	Timer 1 count for Blue
   6		Offset Red
   7		Offset Green
   8		Offset Blue
   9- 11	(unused, 0)
  12		Gain Red
  13		Gain Green
  14		Gain Blue
  15		Port 1 setting (values 0/6/7/other)
  16		Number of entries to add to BADF table (logs show value>0 at higher resolutions)
  17		If set (>0) double T1 count (exposure) - may be a switch between 8 and 16 bit processing
  18- 19	Timer 1 count value Infrared
  20		Infrared offset
  21		(unused)
  22		Infrared gain

(not logged)
Execute Timer 1 interrupt handler functions 0x12 & 0x18 & 0x1B

RESET (0xE1)
(not logged)
Seems to reset the device

(not logged)
Specifies a different default Timer 1 count setting

(not logged)
Enables MAIN section 4

(not logged)
Start warmup sequence

SCAN (0x1B)
SCAN(1) scans, SCAN(0) does nothing

SCAN (0x1B)
Abort SCAN command (if SCAN executing)

(not logged)
In single step mode: exits single step mode


Command list - commands that return data


No data returned, but command response (OK/BUSY/SENSE, as already described)

Regular sense data (14 bytes)
   2		Sense code
  12		Additional sense code
  13		Additional sense code qualifier

INQUIRY (0x12)
Standard and non-standard device data
   0-183	As described already; most of the data is simply copied from memory
 184-185	B4D1/0 = *17/6 a line count during scanning?
 186		Number of entries in BADF-table
 187-214	7 4-byte entries from BADF-table

READ (0x08/0x11)
(not logged)
Read static halftone pattern data from memory
   0-var	Halftone pattern data

READ (0x08/0x12)
(not logged)
Read current scan frame (x0,y0,x1,y1)
   0-  8	Scan frame (x0,y0,x1,y1)

READ (0x08/0x13)
(not logged)
Read exposure times (seems unused, always returns 0x0064)
   0-var	Exposure times

READ (0x08/0x14)
(not logged)
Highlight/shadow settings (seems unused, static, 0x00/0x64)
   0-var	Highlight/shadow settings

READ (0x08/0x15&0x95)
Read calibration data as already described (mostly static data)
   0- 29	Calibration data

READ (in SCAN context)
Read scanned lines (regular scan or calibration data)
   0-var	Scanned data, number of lines as specified 

PARAM (0x0F)
Read current scan parameters
   0-  1	Pixels on a scan line
   2-  3	Number of lines to scan
   4-  5	Bytes on a scan line (=width*depth)
   6		Filter offset 1
   7		Filter offset 2
   8- 11	Period ( 3600*T / n0*res )
  12- 13	ScsiTransferRate ( L / ( delta(T)/1024 ) ), delta taken at each READ
  14- 15	Available lines
  16		Bit 7-1: unused (not initialised)
		Bit 0: motor direction
  17		Unused (0)

CHECK SENSE (0x16, 0x17, 0x1D)
(not logged)
Returns “Check Condition” response if there is a sense

(not logged)
Read current MODE SELECT data (15 bytes)

(not logged)
Seems to read directly from RAM memory (number of bytes as specified, but seems incomplete)

Read data which may be used to determine scanner settings
   0- 53	(unused, all 0)
  54- 55	Auto-tuned full-scale-level for Red
  56- 57	Auto-tuned full-scale-level for Green
  58- 59	Auto-tuned full-scale-level for Red
  60- 61	Timer 1 count for Red
  62- 63	Timer 1 count for Green
  64- 65	Timer 1 count for Blue
  66		Offset Red
  67		Offset Green
  68		Offset Blue
  69- 71	(unused, 0)
  72		Gain Red
  73		Gain Green
  74		Gain Blue
  75		Port 1 setting (values 0/6/7/other), value is set by SET GAIN OFFSET
  76- 77	Fixed 0x0B79 (often used as default or reference)
  78- 97	(unused, uninitialised)
  98- 99	Timer 1 count for Infrared
 100		Offset Infrared
 101		(unused, set to 0 but not immediately)
 102		Gain Infrared

(not logged)
Probably scans a line and presents data to host

Read status data
   0		Bit 0 if set: button pushed
		Bit 1-7: unused
   1		(unused, 0)
   2		(unused, may be unitialised)
   3		(unused, may be unitialised)
   4		(unused, may be unitialised)
   5		Bit 0 if set: unit not warmed up
		Bit 1-7: unused, 0
   6		Bit 0-5: unused, set to 10 00 00
		Bit 6 if set: SCAN command executing
		Bit 7: motor direction
   7		(unused, may be unitialised)
   8		Bit 0 if set: post warming-up code running
		Bit 1-7: unused, 0
   9		(unused, 0)
  10		(unused, 0)

READ RAM DATA 8000	0xF3	
(not logged)
Reads data from 0x8000-port (access to current CCD-mask)

COPY (0x18)
Output CCD-pattern (when SCAN active)

(not logged)
In single step mode: read a line and step

(not logged)
In single step mode: only returns an OK response

More information about the sane-devel mailing list