Creating a home-brew IR receiver / transmitter with an FTDI chip
    author: A. J. Huitsing (albert@huitsing.nl)
    date: 6 oct 2008
     last modified: 26 may 2016
    Introduction
    This page documents my hobby project of building a home-brew IR
    receiver/transmitter based on the FTDI chipset. 
    During the past couple of years I've been using several IR receivers
    and transmitters that where based on RS232 connections.
    Unfortunately my newest boxes don't have any legacy RS232
    connections anymore. Googling around for a cheap USB based solution
    didn't give me the results I hoped for.
    
    So I came up with the idea to build one myself.
    
    FTDI bitbang mode
    The FTDI chipset incorporates a 'bitbang' mode in which the chip
    supports writing & reading of it's pin directly without the uart
    functionality. Especially cool is that reading / writing is buffered
    *and* clocked (!) 
    The clock-rate is determined by the baudrate generator, and the FIFO
    buffers are used to buffer.
    
    On the FTDI website there are some documents describing this special
    mode (for example: here)
    
    Together with this cool mode, another cool project makes it possible
    to even use it in real life! The libftdi
    project provides a user-space driver which allows it to use the chip
    in the advanced modus.
    Ubuntu has a nice package for it, so it's easy to install (e.g. apt-get
install
      libftdi0 and apt-get install libftdi-dev for
    developing purposes)
    
    Carrier modulation
    To generate a 36..38 KHz modulated carrier the sender just has to
    generate 'samples' which will be clocked out by the chip with
    desired rate automatically!
    
    For example (Philips RC5 code)
    
      - each bit in RC5 code has same duration (+/- 1.78ms)
- transmission is done via a modulated carrier: either the
        carrier is on (='pulse') or the carrier is off (='space')
- a logical 1 is coded as space,pulse
- a logical 0 is coded as pulse,space
- a button press on a remote contains 28 bits
To transmit for example the logical 0, the transmitter has to
    transmit 888 uS 'on' / 'pulse' carrier, and then 888uS 'off' /
    'space' carrier:
    
    
    
    To let the FTDI generate this pattern in bitbang mode, we simply
    feed it with 64 'samples' which should be clocked out with 72KHz:
1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
    
    The chip does the timing, so we don't have to bother writing a
    kernel driver for timing etc.
    
    Carrier reception
    Receiving is the opposite from transmission, and in this case it's
    'sampling' the pin at a high enough datarate. The chip will simply
    sample all pins and put it in it's fifo buffers. We can read the
    fifos and inspect the samples. 
    To make reception reliable I've choosen to use a chip which already
    is tuned to a specific carrier frequency and which outputs the
    demodulated carrier, so in stead of sampling with 72KHz (see Nyquist: >2x max. freq to be sampled), it
    is possible to sample with a much lower rate. A lower baudrate
    will cause less CPU load during reception.
    
    Decoding of the samples can be done relatively easy in software.
    Detecting a 'pulse' or a 'space' is a matter of evaluating the
    received samples and counting the number of samples in-between to
    get the timing of the pulse and space.
    
    Albert's hardware
    The hardware for my testing device is as easy as it can be: just
    connect a IR diode and an IR receiver directly to the pins of the
    FTDI chip. When you only want transmission or only reception just
    connect one of them:
    
    
       
    
     note: I've used a SFH506-38 IR receiver which just was lying
      around here. It's no longer in production, alternatives are for
      example PNA4602M or TSOP1138
    
    Albert's hardware vs. 2:
    In order to check IR transmission I've built a better transmitter.
    This setup uses a FTDI MM232R prototype module which I pottered to
    some LEDs, a receiver and even a FET to boost the current through
    the LEDs ;-)
    
    
      
        
          |  |  Albert's 2nd prototype: very small with MM232R
 
 |  the MM232R module
 
 | 
        
          |  receiver example with MM232R
 | 
      
    
    
     Inversion of the RTS signal
    When using a N-channel mosfet like the BS170 there is one issue
    which should be noted. After a reset the with default settings of
    the MM232R eeprom, the RTS signal of the MM232R will drive the
    mosfet, possibly overheating the LEDs. This can be easily tweaked by
    altering the EEprom inside the MM232R setting the 'invert RTS'
    option (use the MPROG
    tool provided by FTDI)
    Another solution would be to use a P-channel mosfet which inverts
    the logic, but then the software must be adapted too (and I
      noticed this effect after I muddled my hardware together)
    
     Looking at IR signals
    In order to check your transmitter operation:
    you can use a digital photo camera (CCD) to look at the LEDs. With a
    CCD camera the infra-red LEDs are visibile !
    
    Armin's hardware:
    Armin Schlegel (knallerbse@gmail.com)
    sent me a nice PCB with the bare minimal to build a USB based
    receiver. It uses the FT232RL chip, connected to a TSOP 1836
    receiver: simple and clean, just the way we like it.
    
    
    
    Armin has been so nice to send me the schematics (IR_rec.sch)
    and board design (IR_rec.brd / IR_rec.pdf)
    as EAGLE files. EAGLE can be found in the Ubuntu repositories.
    Furthermore he has created a git repo where these designs can be
    found also: https://github.com/siredmar/ir_rec 
    
    Thanks Armin !
    
    The software
    Current LIRC versions support this FTDI based hardware out of the
    box. So there's no need for patching, just the usual compilation
    steps:
    
    >tar -xzvf lirc-x.x.x.tgz
>./configure
>make
>make install
    
    All the available drivers will be compiled, and can be loaded
    dynamically by configurating the config file.
    
    Configuring the driver 
    The driver is selected at loadtime of lircd (/mode2) by the 'driver'
    argument (-Hftdi) and can be configured using the 'device' argument
    (-dserial=XXXX). The driver is configured using key=val pairs
    (all settings are optional, and have reasonable defaults).
    
    
      
        
          | vendor | vendor code (default 0x0403 for FTDI) | 
        
          | product | product code (default 0x6001 for FT232) | 
        
          | desc | description string (default = not defined) | 
        
          | serial | serial string (default = not defined) | 
        
          | input | input bit number (0..7, default = 1) 0 = TxD
 1 = RxD (default)
 2 = RTS
 3 = CTS
 4 = DTR
 5 = DSR
 6 = DCD
 7 = RI
 | 
        
          | output 
 | see input 
 | 
      
    
    
     example, for Adam's hardware (Receiver on RI pin) 
          lircd -Hftdi -dserial=A4001doI,input=7
    
    The 'serial' argument is needed to uniquely address the FTDI chip
      in use, so please supply at least this argument. The serial number
      of your FTDI chip can be found by looking at the systemlog (dmesg)
      while plugging-in the chip. Here is an excerpt from my system log:
    
    [ 1696.235780] usb 5-1.2: new full-speed USB device number 4 using xhci_hcd
[ 1696.271595] usb 5-1.2: New USB device found, idVendor=0403, idProduct=6001
[ 1696.271600] usb 5-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
....
[ 1696.271607] usb 5-1.2: SerialNumber: FTRVA1T9
    
    So for my receiver I start mode2 with:
    
    mode2 -Hftdi -dserial=FTRVA1T9
    
    When you're not sure about the serial you could try:
    mode2 -Hftdi -dvendor=0x0403
    Which would try to open the first FTDI chip found on the system.
    RC5 transmission testing
    Transmission is integrated in the LIRC driver now, but you can test
    it's proof of concept by a RC5 (36 Khz, Philips code) sender only:
    
      - download rc5.c
- change the serial number 'FTE1G5RU' to your own serial number
        (somewhere near line 49) 
- compile with 'gcc rc5.c -lftdi -o rc5'
- try to transmit some codes:
 ./rc5 12 (switch TV to stdby)
 ./rc5 0(switch to channel '0' on TV)
 ./rc5 32(zap P+ on TV)
 etc.
2-7-2009: transmission to the power of 2
    An important tip from a member on the LIRC mailing list
    (thanks Enrique !) is that the choosen bitrate for the FTDI
    chip should be a power of 2! After a lot of testing
    it seems that when choosing the bitrate to be a power of 2, the
    generated carrier is clean enough to control my test-setup, and the
    scope measurements look fine enough too! : so choose the FTDI
    bitrate to be a power of 2! I've already adapted this
    in hwftdi.c (see tx_baud_rate=65536). This is not updated in rc5.c
    yet.
    
    17-jan-2010: FTDI bitrate
      investigation
    It seems there is something funky going on with the FTDI chips,
    libftdi or both. In the datasheet of the chip it is stated that the
    bitrate used in bitbang mode is 16 times the baudrate setup (at
    least the D2XX function is described that way). But this seems to be
    not correctly. Several people have reported that reception works,
    but seem to have problems with transmission. I'm investigating this,
    and try to find a solution. When you have problems try to alter the
    baudrates (*2, *4 or /2, /4 etc.) and please feed-back your
    experiences.
   26-may-2016: more investigations by Will
    & Dave
    William Manley and his colleague David Röthlisberger did some
    more research regarding the accuracy of the FT232R
    chip, and came to the conclusion that the timing is unreliable. They recommend to use the FT230X series instead.
    
    some tips
    A quick test to verify your hardware can be found in test3.c  (compile with gcc
    -o test3 -lftdi) This app. generates a 'modulated carrier' which
    means that it generates a 38Khz signal which is switched on/off with
    500 Hz continously. This is especially useful for testing your
    hardware setup. You can connect a scope on the sender LED and verify
    if 38Khz signals are generated. Secondly you can connect a scope to
    the receiver and verify if 500 Hz (demodulated) squarewave is
    received: this should work at a distance of several meters at least!
    
    tip from Dave Herman when working with multiple connected chips:
    
    Quick way to lookup serial number:
plug into usb port (only 1 though)
udevadm info -q all -n /dev/ttyUSB0
    Investigating the Sample accuracy
    During testing of the receiver one of my biggest concerns are: "How
      accurate is the sampling? Is the 'stream' we receive from the FTDI
      chip continous? Are there drop-outs due to FIFO buffering or USB
      traffic? "
    To check this I used a test setup which consists of a signal
    generator connected to the RxD pin. The test signal simply contains
    a square-wave generator of known frequency (my generator can only
    generate 480Hz). When sampling this signal we should read a
    consistent # samples before the level of the samples change ('the
    pulse-width') 
    I used the program (see: test2.c)
    for this purpose which samples continously and counts the number of
    samples between level changes of the input signal. The number of
    samples is the pulse-width and these are stored in a file for
    observation (see: pulses.txt)
    which i did by plotting it with OpenOffice Calc:
    
    
    Conclusion: the stream is not really accurate I'd say...
    There is a noise of about 20 'counts' on a value of about 150 (+/-
    13%).. but this seems to be OK for the LIRC reception algorithm to
    deal with.
    
    
    Ideas
    
      - The role pins in bitbang mode are all equal (i.e.: all pins
        can be configured to be input or output) so potentially we have
        a 4x sender or a 4x receiver or any mix of this.
- Adapt the schematic to use a FTDI cable which has
        a on-board RS232 level shifter
Links
    
    
    Changelog
    26 may 2016
    - added link to Will & Dave's blog
    27 may 2015
    - removed manual patching of LIRC sources because FTDI stuff is
    included in LIRC now
    - updated some instructions about -H and -d arguments
    
    22 oct 2014
    - updated Armin's e-mail address 
    
    21 oct 2011
    - added Armin Schlegel's design 
    
    20 nov 2010
    - updated 'bleeding-edge' hw-ftdi.c for deprecated setbitbang and
    static time_left()
    
    17 jan 2010
    - removed the need for patches: LIRC cvs contains sending &
    receiving now
    - added remarks about funky bitrate business
    - added test3.c for testing hardware
    
    7 jul 2009
    - added remarks about bitrate being a power of 2
    
    14 mar 2009
    - added 'receiver with mm232r' image
    - added title 'transmitter' to Albert's hardware vs. 2
    
    12 feb 2009
    - updated link to libftdi
    
    26 jan 2009
    - added LIRC transmission
    - updated RC5.c to accept any FTDI found
    
    31 dec 2008
     - removed manual patching
    
    30 dec 2008
     - added Adam Sampson's patches
     - added a note about alternative IR receivers
    
    23 oct 2008 
     - added sample accuracy
    
    8 oct 2008 
     - added patches
    
    6 oct 2008 
     - initial version