[linux-dvb] Linux support for the DigiTV PCI remote controller

Mark Weaver mark-clist at npsl.co.uk
Sun Sep 18 07:30:07 CEST 2005

With a friend, we did some poking and proding with a multimeter, and it 
looks like the IR input (we think it's a photo-transistor as it has a 
biasing circuit, didn't have the box to hand) is connected to the 
flip-flop's clock.  The flip-flop ^S reset is connected to GPIO4 (and it 
looks like the ^Q output is connected to GPIO5).  The flip-flop appears 
to be in there to hold the edge from the photo-transistor, and you then 
toggle the reset to get it ready to go again.

I then went at it from the other end, disassembling the Nebula driver. 
This, plus some hints from their 'SDK', indicates that INT_VPRES has 
somehow been co-opted into triggering when GPIO5 becomes set.  Does that 
sound feasible?  I couldn't really figure it out from the bt878 datasheet.

The interrupt handler then uses the timing to work out which 'bit' we 
had and ends up with a 28-bit code (so I guess it's RC5 without decoding 
the bi-phase).  That code looks like what the windows software uses 
internally (i.e. they don't bother to decode it).

The mess below is what I ended up with after reading the disassembly for 
a while.  It's probably feasible to turn that mess into a remote control 
driver, although it looks like bttv-driver.c would have to be hacked up 
a bit to punt the VPRES irq on to a sub-driver.  If anyone has any 
implementation advice, I'd be grateful.

It certainly seems like this card was built with saving cash in mind.



int last_code;	// last good code
int last_bit;	// last code bit seen
int code;	// code under construction
int base_time;	// 100ns units
int remote_gap; // 6,000 for nebula remote/8,850 for the other one ?
int wait_30ms;

void int_remote()
	unsigned int gpio;
	int gap;
	int time;
	// read gpio port
	gpio = read_gpio();
	// get time of code
	time = get_time_100ns();
	gap = time - base_time;
	if (gap > 2000000) // 200ms timeout
		code = 0;
	if (gap > 30000) // wait up to 30ms for entire code
		wait_30ms = 0;
	if (!wait_30ms) {
		if (last_bit < 20) { // Short code??
			last_code = 0;
		} else { // Good code
			last_code = code;
		// Reset for next code
		base_time = time;
		code = 0;
		last_bit = 0;
		wait_30ms = 1;
	} else if (last_bit < 28) {
		// need to be at least 1/2 gap into next interval?
		last_bit = (gap - remote_gap / 2) / remote_gap;
		code |= 1<<last_bit;
	// set bit 4 low
	write_gpio(gpio & ~(1 << 4));
	// set bit 4 high
	read_gpio(gpio | (1 << 4));

More information about the linux-dvb mailing list