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 | 0x05 (echo) hardware version 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: 2400 3600 4800 7200 9600 14400 19200 28800 38400 57600 76800 115200 153600 230400 307200 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: Delete all images. 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();
    }