+# 4.2 Receiver platforms
+
+Currently the ESP8266 suffers from [this issue](https://github.com/micropython/micropython/issues/5714).
+Testing was therefore done without WiFi connectivity.
+
+Philips protocols (especially RC-6) have tight timing constraints with short
+pulses whose length must be determined with reasonable accuracy. The Sony 20
+bit protocol also has a timing issue in that the worst case bit pattern takes
+39ms nominal, yet the repeat time is 45ms nominal. These issues can lead to
+errors particularly on slower targets. As discussed above, errors are to be
+expected. It is up to the user to decide if the error rate is acceptable.
+
+Reception was tested using Pyboard D SF2W, ESP8266 and ESP32 with signals from
+remote controls (where available) and from the tranmitter in this repo. Issues
+are listed below.
+
+NEC: No issues.
+Sony 12 and 15 bit: No issues.
+Sony 20 bit: On ESP32 some errors occurred when repeats occurred.
+Philips RC-5: On ESP32 with one remote control many errors occurred, but paired
+with the transmitter in this repo it worked.
+Philips RC-6: No issues. Only tested against the transmitter in this repo.
+
+# 4.3 Principle of operation
+
+Protocol classes inherit from the abstract base class `IR_RX`. This uses a pin
+interrupt to store in an array the start and end times of pulses (in μs).
+Arrival of the first pulse triggers a software timer which runs for the
+expected duration of an IR block (`tblock`). When it times out its callback
+(`.decode`) decodes the data and calls the user callback. The use of a software
+timer ensures that `.decode` and the user callback can allocate.
+
+The size of the array and the duration of the timer are protocol dependent and
+are set by the subclasses. The `.decode` method is provided in the subclass.
+
+CPU times used by `.decode` (not including the user callback) were measured on
+a Pyboard D SF2W at stock frequency. They were: NEC 1ms for normal data, 100μs
+for a repeat code. Philips codes: RC-5 900μs, RC-6 mode 0 5.5ms.
+
+# 5 Transmitter
+
+This is specific to Pyboard D and Pyboard 1.x (not Lite).
+
+It implements a class for each supported protocol, namely `NEC`, `SONY`, `RC5`
+and `RC6_M0`. The application instantiates the appropriate class and calls the
+`transmit` method to send data.
+
+Constructor
+All constructors take the following args:
+ 1. `pin` An initialised `pyb.Pin` instance supporting Timer 2 channel 1: `X1`
+ is employed by the test script. Must be connected to the IR diode as described
+ below.
+ 2. `freq=default` The carrier frequency in Hz. The default for NEC is 38000,
+ Sony is 40000 and Philips is 36000.
+ 3. `verbose=False` If `True` emits debug output.
+
+The `SONY` constructor is of form `pin, bits=12, freq=40000, verbose=False`.
+The `bits` value may be 12, 15 or 20 to set SIRC variant in use. Other args are
+as above.
+
+Method:
+ 1. `transmit(addr, data, toggle=0)` Integer args. `addr` and `data` are
+ normally 8-bit values and `toggle` is normally 0 or 1.
+ In the case of NEC, if an address < 256 is passed, normal mode is assumed and
+ the complementary value is appended. 16-bit values are transmitted as extended
+ addresses.
+ In the case of NEC the `toggle` value is ignored. For Philips protocols it
+ should be toggled each time a button is pressed, and retained if the button is
+ held down. The test program illustrates a way to do this.
+ `SONY` ignores `toggle` unless in 20-bit mode, in which case it is transmitted
+ as the `extended` value and can be any integer in range 0 to 255.
+
+The `transmit` method is synchronous with rapid return. Actual transmission
+occurs as a background process, controlled by timers 2 and 5. Execution times
+on a Pyboard 1.1 were 3.3ms for NEC, 1.5ms for RC5 and 2ms for RC6.
+
+# 5.1 Wiring
+
+I use the following circuit which delivers just under 40mA to the diode. R2 may
+be reduced for higher current.
+
+
+This alternative delivers a constant current of about 53mA if a higher voltage
+than 5V is available. R4 determines the current value and may be reduced to
+increase power.
+
+
+The transistor type is not critical.
+
+The driver assumes circuits as shown. Here the carrier "off" state is 0V,
+which is the driver default. If using a circuit where "off" is required to be
+3.3V, the constant `_SPACE` in `ir_tx.py` should be changed to 100.
+
+# 5.2 Principle of operation
+
+The classes inherit from the abstract base class `IR`. This has an array `.arr`
+to contain the duration (in μs) of each carrier on or off period. The
+`transmit` method calls a `tx` method of the subclass which populates this
+array. On completion `transmit` appends a special `STOP` value and initiates
+physical transmission which occurs in an interrupt context.
+
+This is performed by two hardware timers initiated in the constructor. Timer 2,
+channel 1 is used to configure the output pin as a PWM channel. Its frequency
+is set in the constructor. The OOK is performed by dynamically changing the
+duty ratio using the timer channel's `pulse_width_percent` method: this varies
+the pulse width from 0 to a duty ratio passed to the constructor. The NEC
+protocol defaults to 50%, the Sony and Philips ones to 30%.
+
+The duty ratio is changed by the Timer 5 callback `._cb`. This retrieves the
+next duration from the array. If it is not `STOP` it toggles the duty cycle
+and re-initialises T5 for the new duration.
+
+The `IR.append` enables times to be added to the array, keeping track of the
+notional carrier on/off state for biphase generation. The `IR.add` method
+facilitates lengthening a pulse as required in the biphase sequences used in
+Philips protocols.
+
+# 6. References
+
+[General information about IR](https://www.sbprojects.net/knowledge/ir/)
+
+The NEC protocol:
+[altium](http://techdocs.altium.com/display/FPGA/NEC+Infrared+Transmission+Protocol)
+[circuitvalley](http://www.circuitvalley.com/2013/09/nec-protocol-ir-infrared-remote-control.html)