const unsigned char startup_regs_0019[] = { 0x4c, /* 0x00 - increment delay (IDEL) = */ 0x3c, /* 0x01 - HSY begin 50 Hz */ 0x0d, /* 0x02 - HSY stop 50 Hz */ 0xef, /* 0x03 - HCL begin 50 Hz */ 0xbd, /* 0x04 - HCL stop 50 Hz */ 0xf0, /* 0x05 - HSY after PHI1 50 Hz */ 0x00, /* 0x06 - luminance control */ 0x00, /* 0x07 - hue control */ 0xf8, /* 0x08 - colour killer threshold QUAM (PAL/NTSC) */ 0xf8, /* 0x09 - colour killer threshold SECAM */ 0x60, /* 0x0A - PAL switch sensitivity */ 0x50, /* 0x0B - SECAM switch sensitivity */ 0x00, /* 0x0C - gain control chrominance */ 0x86, /* 0x0D - standard/mode control */ /* 7 VTRC = 1 (VCR mode, not TV) 6 XXX 5 XXX 4 XXX 3 RTSE = 0 (PLIN switched to output) 2 HRMV = 1 (HREF normal position) 1 SSTB = 1 (status byte = 1) 0 SECS = 0 (other standards, not SECAM) */ 0x18, /* 0x0E - I/O and clock control */ 0x90, /* 0x0F - control #1 */ 0x00, /* 0x10 - control #2 */ 0x2c, /* 0x11 - chrominance gain reference */ 0x7f, /* 0x12 - chrominance saturation */ 0x5e, /* 0x13 - luminance contrast */ 0x42, /* 0x14 - HSY begin 60 Hz */ 0x1a, /* 0x15 - HSY stop 60 Hz */ 0xff, /* 0x16 - HCL begin 60 Hz */ 0xda, /* 0x17 - HCL stop 60 Hz */ 0xf0, /* 0x18 - HSY after PHI1 60 Hz */ 0x9b /* 0x19 - luminance brightness */ }; /* 1A - not used */ /* 1B - not used */ /* 1C - not used */ /* 1D - not used */ /* 1E - not used */ /* 1F - not used */ const unsigned char startup_regs_2034[] = { 0x7c, /* 0x20 - analog control #1 */ 0x03, /* 0x21 - analog control #2 */ 0xd2, /* 0x22 - mixer control #1 */ 0x41, /* 0x23 - clamping level control 21 */ 0x80, /* 0x24 - clamping level control 22 */ 0x41, /* 0x25 - clamping level control 31 */ 0x80, /* 0x26 - clamping level control 32 */ 0x4f, /* 0x27 - gain control #1 */ 0xfe, /* 0x28 - white peak control */ 0x01, /* 0x29 - sync bottom control */ 0xcf, /* 0x2A - gain control analog #2 */ 0x0f, /* 0x2B - gain control analog #3 */ 0x83, /* 0x2C - mixer control #2 */ 0x01, /* 0x2D - integration value gain */ 0x81, /* 0x2E - vertical blanking pulse set */ 0x03, /* 0x2F - vertical blanking pulse reset */ 0x60, /* 0x30 - ADCs gain control */ 0x71, /* 0x31 - mixer control #3 */ 0x02, /* 0x32 - integration value white peak */ 0x8c, /* 0x33 - mixer control #4 */ 0x03 /* 0x34 - gain update level */ }; #define HRT_AD_DEVICE_ID (128+16+8+4) /* the unique I2C buss address of the SAA7110 (A/D) device */ #define HRT_base io_base /* unsigned char *HRT_base = (unsigned char *) 0xdc000; the base address of the HRT512-8 frame grabber This is the default, assuming Jumpers A & B are off. It should be overridden if necessary, after probing to detect jumper state. */ #define HRT_control_offset 0x2000 /* the address of the I2C bus control port on the HRT512-8 0x2000 = 8192 = 2^13 */ #define HRT_control (HRT_base + HRT_control_offset) #define I2C_BUSY (!(readb(HRT_control) & 0x80)) /* bit 7 at 0x2000 (the HRT512-8 control register) tells whether the CPU is sending data across the I2C bus */ #define I2C_control_offset 0x2001 /* 0x2001 = 8193 = 2^13+1 */ #define I2C_control (HRT_base + I2C_control_offset) /* The word at 0x2001 provides access to the I2C bus of the HRT512-8 bit 0 = I2C clock signal ("scl" for short) bit 1 = I2C data/address signal ("sda" for short) bit 2 = "go" signal for hardware to generate a clock pulse, once data is ready This is a write-only bit. It gets cleared by hardware a few microseconds after the software sets it high. */ #define I2C_POKE(data) {writeb(data,I2C_control); wmb();} #define I2C_PEEK (readb(I2C_control)) #define I2C_00 {writeb(0,I2C_control); wmb();} #define I2C_10 {writeb(1,I2C_control); wmb();} #define I2C_01 {writeb(2,I2C_control); wmb();} #define I2C_11 {writeb(3,I2C_control); wmb();} /* I2C_start --------- Send 'start' command onto I2C bus to be recieved by all devices on bus. (The HRT512-8 only has the A/D on the I2C bus) This tells all devices on the I2C bus to prepare for an address phase, i.e., that one of them will be addressed next. */ void I2C_start() { I2C_00; I2C_01; I2C_11; I2C_10; I2C_00; } /* I2C_stop -------- Tell selected device (A/D) that transmission has completed and bus is free. */ void I2C_stop() { I2C_00; I2C_10; I2C_11; I2C_01; I2C_11; } /* I2C_send_byte ------------- Send a byte to the A/D. */ void I2C_send_byte(unsigned char data) { char bitpos; unsigned char sda, sda_slc; /* ...need code to determine timeout value... */ for (bitpos = 7; bitpos >= 0; bitpos--) { /* send a bit to the A/D device; clock must be low at this time */ sda = (data & (1 << bitpos)) >> bitpos; /* get the next bit from data value */ sda_slc = sda << 1; I2C_POKE(sda_slc); /* put data bit on bus and take clock low (b0=0) */ I2C_POKE(sda_slc + 4); /* send the go signal to initiate clock pulse */ while (I2C_BUSY) { /* spin */ /* ...need code here to time out and recover if there is no response... */ }; I2C_01; /* leave the sda line at high impedance (bit0=0 clock, bit1=1 data/high impedance) */ }; /* check for ack from A/D after each byte has been sent */ I2C_11; if (I2C_PEEK & 2) { /* error: no ACK after Data Byte transmision */ /* ...need recovery code here... */ } I2C_01; /* return the bus to high impediance */ } void I2C_init() { int i; I2C_start(); I2C_send_byte(HRT_AD_DEVICE_ID); /* Tell the A/D device it has been selected for data transmission. */ I2C_send_byte(0); /* Set the selected devices (A/D) internal address register pointer to zero. All data writes will autoincrement the A/D's address register pointer. */ for (i = 0; i < sizeof(startup_regs_0019); i++) { I2C_send_byte(startup_regs_0019[i]); } /* The first 26 data bytes have been sent. The next and final 21 bytes must be sent sequentially starting at address 0x20. The A/D has autoincremented its pointer to decimal 26 (0x1A). Now we need to skip up to adress decimal 32 (0x20), so we send a stop, start, address phase, and then the rest of the data. */ I2C_stop(); I2C_start(); I2C_send_byte(HRT_AD_DEVICE_ID); /* send address byte to select A/D, and check for ack */ I2C_send_byte(32); /* set address pointer to 0x20 */ for (i = 0; i < sizeof(startup_regs_2034); i++) { I2C_send_byte(startup_regs_2034[i]); } I2C_stop(); }