Re: Ftdi FT230X based receiver gives incorrect timings for received IR pulses.

John Penfold <[email protected]>
Newsgroups gmane.comp.hardware.lirc
Message-ID <14755105.7ojQa7gJOF@donibristle>
On Friday 17 Mar 2017 12:35:06 Alec Leamas wrote:
> Hi!
> 
> Thanks for a really qualified message, and sorry for not providing any
> answer until now. I wanted to see if anyone actually using these chips
> would show up first.
> 
> On 15/03/17 14:48, John Penfold wrote:
> > Hi All,
> > 
> > I have built a USB infra-red receiver based on ftdi's FT230X chip.
> > 
> > Comparison between the mode2 outputs when using the ftdi receiver and the
> > serial port receiver showed that the ftdi receiver pulses were twice the
> > width. The signal going into the FT230X was the correct width.
> > 
> > The device was built for receiving only, but I tried sending by connecting
> > the transmit output pin to an oscilloscope, the pulses were half the
> > width they should have been (with discontinuities in the modulation
> > pulses). I tried it with the ftdix driver which gave the correct output.
> > 
> > Looking through the code in ftdi.c i found in parsesamples() the following
> > (from line 151)
> > 
> > 		/* Convert number of samples to us.
> > 		
> > 		 *
> > 		 * The datasheet indicates that the sample rate in
> > 		 * bitbang mode is 16 times the baud rate but 32 seems
> > 		 * to be correct. */
> > 		
> > 		usecs = (rxctr * 1000000LL) / (rx_baud_rate * 32);
> > 
> > I wanted to verify this, and tried using the libftdi python bindings to
> > write a small python program to do it. I found that if you set the
> > baudrate before entering bitbang mode, the bitbang clock will be 16 times
> > the baudrate you set, if you set the baudrate when in bitbang mode the
> > clock will be 64 times the baudrate you set.
> > This is caused by libftdi's ftdi_set_baudrate(), when you are in bitbang
> > mode it multiplies the baudrate by 4 before setting the chip. I could not
> > find any mention of this "feature" in the documentation.:
> > 
> > In lirc the baudrate is set while in bitbang mode, the bitbang clock is
> > therefore 64 times the baudrate you set. This suggests that the 32 in
> > parsesamples() should be 64, which would halve the number of microseconds
> > of the pulse, giving the correct result.
> > 
> > Does the ftdi driver work correctly with any other ftdi chip (e.g.
> > FT232R)? Is it only the FT230X that causes problems?
> 
> Until someone shows up with some data on this we just don't know.
> 
> However, you have verified a patch to apply if the chip actually is
> FT230X. If you could make a patch which tested this in runtime and
> applied the correct divisor for FT230X chips only I would be happy to
> apply this.
> 
> Doing so would leave an open issue for non-FT230X chips. We would have
> to live with that until it's tested.
> 
> An alternative would be to apply the correct divisor unconditionally,
> but add a driver option which makes it possible for users to reset it to
> the original value.
> 
> I would also appreciate if you opened a bug for this - bugs are easier
> to track, and we definitely need to track this.
> 
> Again: thanks for valuable input!
> 
> 
> Cheers,
> 
> --alec
> 
> ----------------------------------------------------------------------------
> -- Check out the vibrant tech community on one of the world's most
> engaging tech sites, Slashdot.org! http://sdm.link/slashdot

Hi,
  I have created a patch to fix the problem, it is likely that it affects all 
the chip types but has not been noticed as using irrecord to create the config 
file covers up the defect. I have taken the second approach, a global fix but 
with an option to revert to previous behaviour.

Please note that I have not done any C programming before, so please check it 
carefully. It compiles and runs but there may be errors in it.

I tried to open a ticket on your Sourceforge page but I need to be authorised 
by the project admin to do this. How do I get to be authorised?


Proposed patch to fix timing errors in the ftdi driver.

Fault description
  On receive the pulsewidths are detected as being twice the value of the 
received pulse. On send the chip outputs pulses half the width specified by the 
config. data.

If the config file for the handset is created using irrecord, then the remote 
will work. When sending, the double size pulse data gets halved and the 
resulting IR output is correct, a case of 2 wrongs making a right!

This was discovered when a receiver using an FT230X chip was used on a system 
that was set up using a serial port receiver. 

Patch description
  Existing lirc installations using ftdi that work will have a config file that 
compensates for the bug, correcting the bug will result in these breaking, so 
I have included an extra option 'old_timings' which when set to 1 results in 
the original behavior of the driver. 
It currently defaults to 0 which will use the correct timings. Existing users 
will need to add old_timings=1 to the 'device' line in lirc_options.conf  (May 
be better to default to 1)

The fixed multipliers of rx_baud_rate in parsesamples() and tx_baud_rate in 
hwftdi_send() are replaced by variables. The variables are set to values 
depending on the value of old_timings.
rx_baud_mult  old value 32, new value 64. (The bitbang clock is 16 * baudrate  
								and  ftdi_set_baudrate() applies an 	
								additional 4 *  to the baudrate in 		
								bitbang mode)
tx_baud_mult  old value 8,  new value 16  (Not sure how this works but had to 	
								be half or  twice original value. 		
								Gives correct result when  doubled)


The patch

----------------------------------------------------------------------------------------

--- lirc-0.9.4c/plugins/ftdi.c	2016-10-22 05:21:56.000000000 +0100
+++ lirc-0.9.4c/plugins/ftdi.c.new	2017-03-18 16:18:42.000000000 +0000
@@ -68,6 +68,9 @@
 static const char* usb_desc = NULL;
 static const char* usb_serial = NULL;
 
+static int tx_baud_mult = 16;
+static int rx_baud_mult = 64;
+
 static int laststate = -1;
 static __u32 rxctr = 0;
 
@@ -153,7 +156,7 @@
 		 * The datasheet indicates that the sample rate in
 		 * bitbang mode is 16 times the baud rate but 32 seems
 		 * to be correct. */
-		usecs = (rxctr * 1000000LL) / (rx_baud_rate * 32);
+		usecs = (rxctr * 1000000LL) / (rx_baud_rate * rx_baud_mult);
 
 		/* Clamp */
 		if (usecs > PULSE_MASK)
@@ -288,6 +291,8 @@
 
 	char* p;
 
+	int old_timings = 0;
+	
 	if (child_pid > 0) {
 		log_info("hwftdi_init: Already initialised");
 		return 1;
@@ -334,6 +339,8 @@
 			output_pin = strtol(value, NULL, 0);
 		} else if (strcmp(p, "txbaud") == 0) {
 			tx_baud_rate = strtol(value, NULL, 0);
+		} else if (strcmp(p, "old_timings") == 0) {
+			old_timings = strtol(value, NULL, 0);
 		} else {
 			log_error("unrecognised device configuration option: '%s'", p);
 			goto fail_start;
@@ -345,6 +352,14 @@
 		p = comma + 1;
 	}
 
+	if (old_timings == 1) {         /* original values */
+		tx_baud_mult = 8;
+		rx_baud_mult = 32;
+	} else {
+		tx_baud_mult = 16;
+		rx_baud_mult = 64;       /* hardware *16, libftdi *4 */
+	}
+	
 	rec_buffer_init();
 
 	/* Allocate a pipe for lircd to read from */
@@ -479,7 +494,7 @@
 
 static int hwftdi_send(struct ir_remote* remote, struct ir_ncode* code)
 {
-	__u32 f_sample = tx_baud_rate * 8;
+	__u32 f_sample = tx_baud_rate * tx_baud_mult;
 	__u32 f_carrier = remote->freq == 0 ? DEFAULT_FREQ : remote->freq;
 	__u32 div_carrier;
 	int val_carrier;

----------------------------------------------------------------------------------------

Results
  Tested using a receiver based on FT230X
  
Receive: using the corrected timings the pulsewidths shown in mode2 were close 
to the correct value but wobbled around a bit. Decoding with irw was erratic. 
I found that reducing the rx baudrate to 4800 improved the stability and irw 
worked normally.

Transmit: an oscilloscope was used to monitor the transmit output pin, with 
the corrected timings the pulsewidths are now correct.

With the option old_timings set to 1 the driver reverted to its original 
behavior.


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.