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

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

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

John Penfold
Hi All,

I have built a USB infra-red receiver based on ftdi's FT230X chip. For testing
I used a pc that was already set up as a MythTv frontend with LIRC using the
serial port (lirc-serial), running Debian GNU/Linux 9.0 (Stretch), with lirc
version 0.9.4c-7 and libftdi version 1.3-2+b2
After reconfiguring it to use the ftdi driver, mode2 produced output when
buttons on the remote were pressed but there was no output from irw.
Investigation revealed that LIRC could not find a remote control config with
timings that matched the received signal.

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?


       John.


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
Reply | Threaded
Open this post in threaded view
|

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

Alec Leamas
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
Reply | Threaded
Open this post in threaded view
|

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

John Penfold
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