The Legacy switch code doesn't work in the latest kernel very well (It
worked once in 12 times or so on my Athlon XP system). Using an idea of
NoOneImportants I hacked it to generate serial data on 8ms + or - 1 ms
boundaries which makes it very reliable. Can you guys role this into the
kernel or do I have to bug the kernel guys?
The way it works is to make sure that the bits are sent out at 8ms
boundaries, and if it misses (because of a non-maskable interrupt) then it
starts over. The code will not exit until it has sent the command with the
correct timing. In reality the timing can be as much as two milliseconds off
in either direction per bit because the target uart doesn't grab until 4ms +
(bit number +1) * 8 ms after the start bit.
This works perfectly on my Athlon XP 2000MHz. I'd like to hear from people
who have P4 systems because I'm not sure jiffies is the same on every
platform. On mine a jiffie is a millisecond, is it that way on all systems?
This is from stv0299.c
static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd)
{
long unsigned int target_jiffies;
int i; // Bit counter
int status=2; // Keep sending until it works
const unsigned int bit_length = 8; // milliseconds
u32 cmd_copy;
u8 last = 1;
unsigned int millisec;
// printk("Entering Send Legacy Command\n");
dprintk("%s switch command: 0x%04x\n",__FUNCTION__, cmd);
while (status)
{
// printk("Starting bit banging sequence.\n");
i = 9; // 8 data bits + start bit
status = 1;
cmd_copy = cmd;
cmd_copy = cmd_copy << 1; // Put in the start bit
stv0299_set_voltage(fe,SEC_VOLTAGE_18);
msleep(32); //Send the reset bits, aka set 18 volts and wait four bits.
target_jiffies = msecs_to_jiffies(bit_length) + jiffies;
while ((status == 1) && i > 0)
{
// printk(".");
if ((cmd_copy & 0x01) != last) {
stv0299_set_voltage(fe,
last ? SEC_VOLTAGE_13 :
SEC_VOLTAGE_18);
last = last ? 0: 1;
}
i--;
cmd_copy = cmd_copy >> 1;
millisec = jiffies_to_msecs(target_jiffies - jiffies);
msleep(millisec);
if (jiffies > target_jiffies + 1) status = 2; // If its off by more than
1ms, start over
target_jiffies += msecs_to_jiffies(bit_length);
}
if (status == 1) status = 0;
// printk(".\n");
if (status == 2) printk("Bit bang failed, starting over.\n");
}
return 0;
}