There is software available, a windows program called FotoBee which is a huge heap of MFC dung. It can be made to run with a small hack under the free Windows Emulator WINE.
WINE was crucial in reverse engineering the camera at all stages of the project.
There is no documenation on the serial protocol in the inlaying documentation.
The FotoBee.exe program uses the Windows serial communications interface, which is fortunately implemented in WINE. By snooping the setup calls, the serial parameters are:
115200 Baud, no parity, 1 stopbit, 8 bit data, no flow control (neither crtscts, nor XON/XOFF)It also setting some large timeouts, since the camera sometimes needs like 2 seconds to think about something.
That was rather trivial.
Luckily the program still uses the standard Win32 serial communication functions for that, so I added some code to the ReadFile and WriteFile functions, which dumps the read/written buffer if it is writing to a serial device.
In general, the program sends a command down the serial line (with optional arguments) and receives data back. Every command starts with a 0xFF character.
Command | Arguments | Returns | Description |
0xff 0x08 | None | 0xff 0xf1 | Ping!s the camera. |
0xff 0xa7 | None | A packet with between 10 and 20 bytes is returned. |
3 float factors are returned, they are calculated:
f1=r[1]+r[2]*0.1+r[3]*0.01; Their use is still unknown to me. Twain calls it 'LoadGRB' |
0xff 0xa4 | None | 0xff 0x01 | Select Index Picture to transfer, is followed by packetreading |
0xff 0xa1 | 0xff picturenr | 0xff 0x01 | Selects Image picturenr to transfer. 3 Bytestreams follow (packetreading has to be called 3 times) |
0xff 0xa8 | 10 bytes of data ... Set floats | 0xff 0x01 | Sets the 3 floats. Sends 10 bytes to the camera. The bytestream looks: 0xFF A B C D E F G H I The floats are: A.BC D.EF G.HI A...I are binary values between 0 and 9. Twain calls it 'SaveGRB'. |
0xff 0xa6 | None | No return expected. | Deletes all images. |
0xff 0xf0 | None | Returns an ASCII hexnumber (starting with two 0x66 ('f')) | Returns the size (in bytes) of the image to transfer next. This command is issued after "select index" or "select image" and is followed by (multiple) packet reads. |
0xff 0xf1 | None | Returns 201 or less bytes |
The packetreader. It is called in a loop after querying the
imagesize. If 201 bytes are read, the 201th byte is the checksum
(sum of 0-199)&0xff, otherwise there is no checksum. Returns the 200 bytes read. |
0xff 0xf3 | None | Returns 201 or less bytes | The packet resend command. Works exactly like the 0xff 0xf1 packetread command, but the last packet is retransmitted. This is useful for corrupted transmissions. |
0xff 0x72 | None | 0xff 0x71 | The TestDRAM command according to the Twain drivers. Gets a bool reply. |
0xff 0x73 | None | 0xff 0x70/0x71 | The TestFLASH command according to the Twain drivers. Gets a bool reply. |
0xff 0x75 | None | 0xff70 or 0xff71 or something else. | The TestADC command according to the Twain drivers. Gets a bool reply. |
0xff 0x78 | None. | Some data. | Appears to take a snapshot and then it should read N packets of
data. Strange. There is some text generated and printed into
a dialog. I only get back 0xff. TWAIN calls it DSC_TestAE. |
0xff 0x79 | None | 0xff 0xXX | Function unknown, seems to open/close the shutter in rapid succession. TWAIN calls it DSC_AjustAGC. Reads reply. |
0xff 0x7a | None. | Some data. | Unclear. GUI enables wait cursor before call and disabled it after. |
0xff 0x7b | 0xff value. | 0xff 0xf1 | Unclear. |
0xff 0xa9 | 0xff value. | 0xff 0xf1 | Set Bulb Mode. Apparently values between 1 and 9. |
Following commands can be used on toplevel:
rawtopgm <index 64 (sizeof_index/64) |pnmflip -tb > index.ppmwe can convert it into a .PPM and convert it further using standard UNIX tools.
The size of the index picture also tells us the number of pictures that are currently stored in the camera. Just divide the size of the indeximage by 64*48.
It is still unclear to me how to detect high/low quality formats, except with the size of the returned image.
At first look the data returned from the camera looks like junknoise. So I had to peek into the diassembly, which shows a slightly inefficient huffman decompressor, with following bitpatterns:
Bits | Value |
00 | -2 |
01 | 6 |
10 | 2 |
110 | 6 |
1110 | 11 |
1111 0 | -11 |
1111 10 | 20 |
1111 110 | -20 |
1111 1110 | 45 |
1111 1111 0 | -45 |
1111 1111 10 | 90 |
1111 1111 110 | -90 |
1111 1111 1110 | 180 |
1111 1111 1111 0 | -180 |
pixel[i] = lastpixel+decompressed_diff;
newpixelvalue = lastvalue + decompressed_diff;
lastvalue = newpixelvalue*0.5 + pixel_lastline[i+1]*0.5;
0 X 0 X N 0The 'X' pixels influence the 'N' pixel (together with the uncompressed diff)
rawtopgm 320 480 <image0 | pnmflip -tb > image0.ppm rawtopgm 320 240 <image1 | pnmflip -tb > image1.ppm rawtopgm 320 240 <image2 | pnmflip -tb > image2.ppmwhere image0 is the first image read, and image1,image2 the next two images.
Both give pretty grayscale pictures, but are not yet in color.
It just compacts all 8bit values to 6bit by shortening out the 2 least significant bits. So we just restore them (AAAA AABB BBBB CCCC CCDD DDDD -> AAAAAA00, BBBBBB00, CCCCCC00, DDDDDD00) and get the same grayscale images as with the lowquality compression.