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
  1. 0x05 (echo)
  2. hardware version
  3. 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:
  1. 2400
  2. 3600
  3. 4800
  4. 7200
  5. 9600
  6. 14400
  7. 19200
  8. 28800
  9. 38400
  10. 57600
  11. 76800
  12. 115200
  13. 153600
  14. 230400
  15. 307200
  16. 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:
  1. Delete all images.
  2. 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();
}