This document describes the protocol used by the Grandtek/Grandtech 980, 981,and 9811 chips, supported by the pdc640 driver.

The chip is serial and USB capable, some cameras have only serial connections, some have only USB connections.

This document describes the USB communication.

The USB command is at most 3 bytes long: A B C and is converted into an USB control message:
0xc0 0x10 <A> <B> <C> <checksum> 0x40

The checksum is calculated by:
(A^0x34)+(B^0xcb)+(C^0x67)+0x14f;

All commands return 8 byte of control data, which contains A at the start of it.

Name | Structure | Arguments | Result buffer

READ VERSION

0x05 x x

arguments are unspecified

0. 0x05 (echo)
1. hardware version
2. firmware version

SELECT PICTURE TYPE

0x61 type 0 0

type can be:

- 0x20: GET CALIBRATION PARAM
...FIXME: Marcus fill in ...

This is followed by a SEND DRAM command and a bulkread usually, depending on type.

NEW BAUD

0x69 baudcode

baudcode:

0. 2400
1. 3600
2. 4800
3. 7200
4. 9600
5. 14400
6. 19200
7. 28800
8. 38400
9. 57600
10. 76800
11. 115200
12. 153600
13. 230400
14. 307200
15. 460800

Set baudrate. Only useful for serial I guess.

AT | 0x41 0x00 0x00 0x00 |  | Appears to be some kind of ping command.
SELECT PICTURE | 0xf6 picnum 0x00 0x00 | picnum is the picture number, starting with 0. | Selects the specified picture. At offset 7 of the return buffer is the new picture.
SICE DOWNLOAD | 0xf2 lsb msb | lsb/msb is the size? offset? of the uploaded firmware. | Function unclear.
QUERY STORAGE FULL | 0x92 |  | Storage card is: 1: Full, otherwise: Empty.
SEND PARAMETER | 0xf8 lsb msb | lsb/msb is the size. This is followed by a USB bulk write. | Unclear.
WRITE REG | 0x81 reg val | Sets register reg to value val | See pseudo function below.
READ REG | 0xf9 reg | Reads register reg | 1: return value (1 byte)
SIMSCANNER | 0x86 0 0 0 |  | Only for serial. Whatever it does.
DUAL CAPTURE | 0x87 0 |  | 0: echo (0x87) 1..4: some values.
PUSH BUTTON | 0xfd 0 0 |  | 0: echo (0xfd) 1: reply value.
SNAP | 0x2d |  | 0: echo (0xfd) 1: reply value.
WAIT EXPOSURE | 0x93 |  | 0: echo (0xfd) 1: return value. Wait for 1.
SEND DRAM | 0x15 lsb1 msb1 lsb2 msb2 |  | Followed by bulk read. parameters are a bit unclear.
LOCK SNAP | 0x90 |  |
FREE SNAP | 0x91 |  |
RS232 INIT | 0x01 |  | Serial only I guess.

ERASE IMAGE

0x59 x

With x:

0. Delete all images.
1. Delete the last image.

NORMAL EXIT | 0xfc |  |
88 Command | 0x88 |  |

    void
    DOWNLOAD_DATA(type, buffer, size) {
    	SELECT_PICTURE_TYPE(type);
    	SEND_DRAM(buffer, size);
    }

    /* Unclear why and how used */
    void
    SEND_USER_COMMAND(cmd, inputbuffer, inputsize, outputbuffer, outputsize) {
    	SEND_PARAMETER(&cmd, 1);
    	if (inputbuffer && inputsize) {
    		SEND_PARAMETER(inputbuffer, inputsize);
    	}
    	if (outputbuffer && outputsize) {
    		SEND_PARAMETER(&outputsize, 4);
    		DOWNLOAD_DATA(0x21, outputbuffer, outputsize);
    	}
    }

    void
    WRITE_REG_Command(byte reg, byte val, int porttype) {
    	// strangely different between USB/SERIAL
    	if (porttype == USB) {
    		byte buf[2];
    		buf[0] = reg;
    		buf[1] = val;
    		SEND_PARAMETERk(buf, 2);
    	} else {
    		call_driver(0x81, reg, val);
    	}
    }

    void
    take_picture(int checkstoragefull, int locksnapflag, int waitforexpflag) {
    	byte val;

    	if (checkstoragefull) QUERY_STORAGE_FULL():
    	if (locksnapflag) LOCK_SNAP();
    	SNAP();
    	if (waitforexpflag) {
    		do {
    			Sleep(500);
    			WAIT_EXPOSURE(&val);
    		} while (val != 1);
    	}
    	if (locksnapflag) FREE_SNAP();
    }