This library implements RC6 (protocol used by some philips remotes). It has a receiver class and a transmitter class. Currently, only mode 0 is supported. It is tested with my DVD/HDD recorder.

Revision:
0:f8e2ed766064
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Rc6.cpp	Sun Feb 27 20:28:35 2011 +0000
@@ -0,0 +1,225 @@
+/* mbed RC6 (Philips remote control protocol) library
+ * Copyright (c) 2011 Jeroen Hilgers
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "Rc6.h"
+
+Rc6Transmitter::Rc6Transmitter(PinName irPin) :
+    mOut(irPin)
+{
+
+    mBusy = false;
+}
+
+void Rc6Transmitter::Send(uint32_t code)
+{
+    if(mBusy)
+    {
+        printf("Busy");
+        return;
+    }
+    mBusy = true;        
+        
+    uint8_t index = 0;
+    uint8_t level;
+    uint16_t time;
+    uint8_t bit;
+    // Leader
+    mPattern[index++] = 6*16; // Mark
+    mPattern[index++] = 2*16; // Pause
+    // Start bit 3.
+    mPattern[index++] = 16;
+    mPattern[index++] = 2*16;
+    // Start bit 2.
+    mPattern[index++] = 16;
+    // Start bit 1.
+    mPattern[index++] = 16;
+    mPattern[index++] = 16;
+    // Start bit 0.
+    mPattern[index++] = 16;
+    // Toggle bit.
+    if(code & 0x10000) 
+    {
+        mPattern[index++] = 3*16;
+        level = 0;
+        time = 2*16;
+    }
+    else
+    {
+        mPattern[index++] = 16;
+        mPattern[index++] = 2*16;
+        level = 1;
+        time = 2*16;
+    }
+    for(bit = 0; bit < 16; bit ++)
+    {
+        if(code & 0x8000)
+        {   // Send '1'
+            if(level) 
+            {
+               mPattern[index++] = 16+time;
+            }   
+            else
+            {
+                mPattern[index++] = time;
+                mPattern[index++] = 16;
+            }
+            level = 0;
+            time = 16;
+        }
+        else
+        {   // Send '0'
+            if(level) 
+            {
+               mPattern[index++] = time;
+               mPattern[index++] = 16;
+            }   
+            else
+            {
+               mPattern[index++] = 16+time;
+            }
+            level = 1;
+            time = 16;
+        }
+        code <<= 1;
+    }
+    if(level == 1)
+    {
+        mPattern[index++] = time;
+    }
+    mPattern[index++] = 16; // Teminate with half symbol (not long enough?)
+    
+    mPattern[index++] = 0; // Mark duration of 0 means end-of-pattern.
+    mPattern[index++] = 0;
+ 
+    // Setup transmitter variables...
+    mMark = 0;  
+    mPause = 0;
+    mPatPtr = mPattern;  
+    
+    // ... and attach ticker.
+    // mTicker.attach(this, &Rc6Sender::Tick, 1.0/(2.0*36000.0)); // This rounds down to:
+    // mTicker.attach_us(this, &Rc6Sender::Tick, 13); // Both are noticeable too slow compared to the real remote!
+    mTicker.attach_us(this, &Rc6Transmitter::Tick, 14); // This does work.
+}
+
+bool Rc6Transmitter::IsBusy()
+{
+    return mBusy;
+}
+
+void Rc6Transmitter::Tick()
+{
+    if(mMark)
+    { // Busy sending a mark. Do next part.
+      mMark--;
+      if(mMark&1)
+      {
+        mOut = 1;
+      }
+      else
+      {
+        mOut = 0;
+      }
+    }
+    else
+    { 
+        if(mPause)
+        {  // Need to do some more pause.
+           mPause--;
+        }
+        else
+        { // Last half cycle of pause. Check next activity.
+          mMark = (*mPatPtr++)<<1; // Half-cycles of marker.
+          mPause = (*mPatPtr++)<<1; // half-cycles of pause.
+          mPause--; // The last half-cycle of puase is spend here setting up next cycle.
+          if(mMark == 0)
+          {
+            // We are done. Stop ticker.
+            mTicker.detach();
+            mBusy = false;
+          }
+        }
+    }
+}
+
+Rc6Receiver::Rc6Receiver(PinName irIn) :
+    irq(irIn)
+{
+    // NOTE: Ir sensor inversion is handled here!
+    irq.rise(this, &Rc6Receiver::OnFall);
+    irq.fall(this, &Rc6Receiver::OnRise);
+    mBusy = false;
+    mLastCode = 0xFFFFFFFF;
+}
+
+uint32_t Rc6Receiver::Receive()
+{
+    // TODO: Disable interrupts to prevent one in a million chance that
+    // mLastCode gets updated...
+    uint32_t code = mLastCode;
+    // ... at exactly this moment, so it will be discarded here:
+    mLastCode = 0xFFFFFFFF;
+    return code;
+}
+
+void Rc6Receiver::OnRise()
+{
+    if(mBusy) 
+    {
+        // Rising edges are not interesting; they correspond to '0'.
+    }
+    else
+    {
+        mBusy = true;
+        mCode = 0;
+        mTimer.start();
+        mTimeout.attach_us(this, &Rc6Receiver::OnTimeout, 30000);  // 52T of 16/36000 sec = 23ms
+    }
+}
+
+void Rc6Receiver::OnFall()
+{
+    if(mBusy)
+    {
+        // Express edge location in 'T' (444.444 us)
+        int32_t edgeId = (mTimer.read_us()*1000 + 222222)/444444;
+        // printf("%d %d\r\n", mTimer.read_us(), edgeId); // Debug print. Doesn't mess up timing as hard as expected :-)
+        
+        // Toggle bit is at edge 18. Store it!
+        if(edgeId == 18)
+            mCode |= 0x10000;
+        // Address and data bits.
+        if((edgeId & 0x01) && (edgeId > 21) && (edgeId < 52))
+        {
+            uint8_t bit = 15 - (edgeId-21)/2;
+            mCode |= 1<<bit;
+        }
+    }
+}
+
+void Rc6Receiver::OnTimeout()
+{
+    mTimer.stop();
+    mTimer.reset();
+    mBusy = false;
+    mLastCode = mCode;
+}