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