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.

Committer:
hilgo
Date:
Sun Feb 27 20:28:35 2011 +0000
Revision:
0:f8e2ed766064
Initial revision: Receiver does not check framing yet (thus other remotes cause junk!)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hilgo 0:f8e2ed766064 1 /* mbed RC6 (Philips remote control protocol) library
hilgo 0:f8e2ed766064 2 * Copyright (c) 2011 Jeroen Hilgers
hilgo 0:f8e2ed766064 3 *
hilgo 0:f8e2ed766064 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
hilgo 0:f8e2ed766064 5 * of this software and associated documentation files (the "Software"), to deal
hilgo 0:f8e2ed766064 6 * in the Software without restriction, including without limitation the rights
hilgo 0:f8e2ed766064 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
hilgo 0:f8e2ed766064 8 * copies of the Software, and to permit persons to whom the Software is
hilgo 0:f8e2ed766064 9 * furnished to do so, subject to the following conditions:
hilgo 0:f8e2ed766064 10 *
hilgo 0:f8e2ed766064 11 * The above copyright notice and this permission notice shall be included in
hilgo 0:f8e2ed766064 12 * all copies or substantial portions of the Software.
hilgo 0:f8e2ed766064 13 *
hilgo 0:f8e2ed766064 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
hilgo 0:f8e2ed766064 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
hilgo 0:f8e2ed766064 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
hilgo 0:f8e2ed766064 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
hilgo 0:f8e2ed766064 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
hilgo 0:f8e2ed766064 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
hilgo 0:f8e2ed766064 20 * THE SOFTWARE.
hilgo 0:f8e2ed766064 21 */
hilgo 0:f8e2ed766064 22
hilgo 0:f8e2ed766064 23 #include "Rc6.h"
hilgo 0:f8e2ed766064 24
hilgo 0:f8e2ed766064 25 Rc6Transmitter::Rc6Transmitter(PinName irPin) :
hilgo 0:f8e2ed766064 26 mOut(irPin)
hilgo 0:f8e2ed766064 27 {
hilgo 0:f8e2ed766064 28
hilgo 0:f8e2ed766064 29 mBusy = false;
hilgo 0:f8e2ed766064 30 }
hilgo 0:f8e2ed766064 31
hilgo 0:f8e2ed766064 32 void Rc6Transmitter::Send(uint32_t code)
hilgo 0:f8e2ed766064 33 {
hilgo 0:f8e2ed766064 34 if(mBusy)
hilgo 0:f8e2ed766064 35 {
hilgo 0:f8e2ed766064 36 printf("Busy");
hilgo 0:f8e2ed766064 37 return;
hilgo 0:f8e2ed766064 38 }
hilgo 0:f8e2ed766064 39 mBusy = true;
hilgo 0:f8e2ed766064 40
hilgo 0:f8e2ed766064 41 uint8_t index = 0;
hilgo 0:f8e2ed766064 42 uint8_t level;
hilgo 0:f8e2ed766064 43 uint16_t time;
hilgo 0:f8e2ed766064 44 uint8_t bit;
hilgo 0:f8e2ed766064 45 // Leader
hilgo 0:f8e2ed766064 46 mPattern[index++] = 6*16; // Mark
hilgo 0:f8e2ed766064 47 mPattern[index++] = 2*16; // Pause
hilgo 0:f8e2ed766064 48 // Start bit 3.
hilgo 0:f8e2ed766064 49 mPattern[index++] = 16;
hilgo 0:f8e2ed766064 50 mPattern[index++] = 2*16;
hilgo 0:f8e2ed766064 51 // Start bit 2.
hilgo 0:f8e2ed766064 52 mPattern[index++] = 16;
hilgo 0:f8e2ed766064 53 // Start bit 1.
hilgo 0:f8e2ed766064 54 mPattern[index++] = 16;
hilgo 0:f8e2ed766064 55 mPattern[index++] = 16;
hilgo 0:f8e2ed766064 56 // Start bit 0.
hilgo 0:f8e2ed766064 57 mPattern[index++] = 16;
hilgo 0:f8e2ed766064 58 // Toggle bit.
hilgo 0:f8e2ed766064 59 if(code & 0x10000)
hilgo 0:f8e2ed766064 60 {
hilgo 0:f8e2ed766064 61 mPattern[index++] = 3*16;
hilgo 0:f8e2ed766064 62 level = 0;
hilgo 0:f8e2ed766064 63 time = 2*16;
hilgo 0:f8e2ed766064 64 }
hilgo 0:f8e2ed766064 65 else
hilgo 0:f8e2ed766064 66 {
hilgo 0:f8e2ed766064 67 mPattern[index++] = 16;
hilgo 0:f8e2ed766064 68 mPattern[index++] = 2*16;
hilgo 0:f8e2ed766064 69 level = 1;
hilgo 0:f8e2ed766064 70 time = 2*16;
hilgo 0:f8e2ed766064 71 }
hilgo 0:f8e2ed766064 72 for(bit = 0; bit < 16; bit ++)
hilgo 0:f8e2ed766064 73 {
hilgo 0:f8e2ed766064 74 if(code & 0x8000)
hilgo 0:f8e2ed766064 75 { // Send '1'
hilgo 0:f8e2ed766064 76 if(level)
hilgo 0:f8e2ed766064 77 {
hilgo 0:f8e2ed766064 78 mPattern[index++] = 16+time;
hilgo 0:f8e2ed766064 79 }
hilgo 0:f8e2ed766064 80 else
hilgo 0:f8e2ed766064 81 {
hilgo 0:f8e2ed766064 82 mPattern[index++] = time;
hilgo 0:f8e2ed766064 83 mPattern[index++] = 16;
hilgo 0:f8e2ed766064 84 }
hilgo 0:f8e2ed766064 85 level = 0;
hilgo 0:f8e2ed766064 86 time = 16;
hilgo 0:f8e2ed766064 87 }
hilgo 0:f8e2ed766064 88 else
hilgo 0:f8e2ed766064 89 { // Send '0'
hilgo 0:f8e2ed766064 90 if(level)
hilgo 0:f8e2ed766064 91 {
hilgo 0:f8e2ed766064 92 mPattern[index++] = time;
hilgo 0:f8e2ed766064 93 mPattern[index++] = 16;
hilgo 0:f8e2ed766064 94 }
hilgo 0:f8e2ed766064 95 else
hilgo 0:f8e2ed766064 96 {
hilgo 0:f8e2ed766064 97 mPattern[index++] = 16+time;
hilgo 0:f8e2ed766064 98 }
hilgo 0:f8e2ed766064 99 level = 1;
hilgo 0:f8e2ed766064 100 time = 16;
hilgo 0:f8e2ed766064 101 }
hilgo 0:f8e2ed766064 102 code <<= 1;
hilgo 0:f8e2ed766064 103 }
hilgo 0:f8e2ed766064 104 if(level == 1)
hilgo 0:f8e2ed766064 105 {
hilgo 0:f8e2ed766064 106 mPattern[index++] = time;
hilgo 0:f8e2ed766064 107 }
hilgo 0:f8e2ed766064 108 mPattern[index++] = 16; // Teminate with half symbol (not long enough?)
hilgo 0:f8e2ed766064 109
hilgo 0:f8e2ed766064 110 mPattern[index++] = 0; // Mark duration of 0 means end-of-pattern.
hilgo 0:f8e2ed766064 111 mPattern[index++] = 0;
hilgo 0:f8e2ed766064 112
hilgo 0:f8e2ed766064 113 // Setup transmitter variables...
hilgo 0:f8e2ed766064 114 mMark = 0;
hilgo 0:f8e2ed766064 115 mPause = 0;
hilgo 0:f8e2ed766064 116 mPatPtr = mPattern;
hilgo 0:f8e2ed766064 117
hilgo 0:f8e2ed766064 118 // ... and attach ticker.
hilgo 0:f8e2ed766064 119 // mTicker.attach(this, &Rc6Sender::Tick, 1.0/(2.0*36000.0)); // This rounds down to:
hilgo 0:f8e2ed766064 120 // mTicker.attach_us(this, &Rc6Sender::Tick, 13); // Both are noticeable too slow compared to the real remote!
hilgo 0:f8e2ed766064 121 mTicker.attach_us(this, &Rc6Transmitter::Tick, 14); // This does work.
hilgo 0:f8e2ed766064 122 }
hilgo 0:f8e2ed766064 123
hilgo 0:f8e2ed766064 124 bool Rc6Transmitter::IsBusy()
hilgo 0:f8e2ed766064 125 {
hilgo 0:f8e2ed766064 126 return mBusy;
hilgo 0:f8e2ed766064 127 }
hilgo 0:f8e2ed766064 128
hilgo 0:f8e2ed766064 129 void Rc6Transmitter::Tick()
hilgo 0:f8e2ed766064 130 {
hilgo 0:f8e2ed766064 131 if(mMark)
hilgo 0:f8e2ed766064 132 { // Busy sending a mark. Do next part.
hilgo 0:f8e2ed766064 133 mMark--;
hilgo 0:f8e2ed766064 134 if(mMark&1)
hilgo 0:f8e2ed766064 135 {
hilgo 0:f8e2ed766064 136 mOut = 1;
hilgo 0:f8e2ed766064 137 }
hilgo 0:f8e2ed766064 138 else
hilgo 0:f8e2ed766064 139 {
hilgo 0:f8e2ed766064 140 mOut = 0;
hilgo 0:f8e2ed766064 141 }
hilgo 0:f8e2ed766064 142 }
hilgo 0:f8e2ed766064 143 else
hilgo 0:f8e2ed766064 144 {
hilgo 0:f8e2ed766064 145 if(mPause)
hilgo 0:f8e2ed766064 146 { // Need to do some more pause.
hilgo 0:f8e2ed766064 147 mPause--;
hilgo 0:f8e2ed766064 148 }
hilgo 0:f8e2ed766064 149 else
hilgo 0:f8e2ed766064 150 { // Last half cycle of pause. Check next activity.
hilgo 0:f8e2ed766064 151 mMark = (*mPatPtr++)<<1; // Half-cycles of marker.
hilgo 0:f8e2ed766064 152 mPause = (*mPatPtr++)<<1; // half-cycles of pause.
hilgo 0:f8e2ed766064 153 mPause--; // The last half-cycle of puase is spend here setting up next cycle.
hilgo 0:f8e2ed766064 154 if(mMark == 0)
hilgo 0:f8e2ed766064 155 {
hilgo 0:f8e2ed766064 156 // We are done. Stop ticker.
hilgo 0:f8e2ed766064 157 mTicker.detach();
hilgo 0:f8e2ed766064 158 mBusy = false;
hilgo 0:f8e2ed766064 159 }
hilgo 0:f8e2ed766064 160 }
hilgo 0:f8e2ed766064 161 }
hilgo 0:f8e2ed766064 162 }
hilgo 0:f8e2ed766064 163
hilgo 0:f8e2ed766064 164 Rc6Receiver::Rc6Receiver(PinName irIn) :
hilgo 0:f8e2ed766064 165 irq(irIn)
hilgo 0:f8e2ed766064 166 {
hilgo 0:f8e2ed766064 167 // NOTE: Ir sensor inversion is handled here!
hilgo 0:f8e2ed766064 168 irq.rise(this, &Rc6Receiver::OnFall);
hilgo 0:f8e2ed766064 169 irq.fall(this, &Rc6Receiver::OnRise);
hilgo 0:f8e2ed766064 170 mBusy = false;
hilgo 0:f8e2ed766064 171 mLastCode = 0xFFFFFFFF;
hilgo 0:f8e2ed766064 172 }
hilgo 0:f8e2ed766064 173
hilgo 0:f8e2ed766064 174 uint32_t Rc6Receiver::Receive()
hilgo 0:f8e2ed766064 175 {
hilgo 0:f8e2ed766064 176 // TODO: Disable interrupts to prevent one in a million chance that
hilgo 0:f8e2ed766064 177 // mLastCode gets updated...
hilgo 0:f8e2ed766064 178 uint32_t code = mLastCode;
hilgo 0:f8e2ed766064 179 // ... at exactly this moment, so it will be discarded here:
hilgo 0:f8e2ed766064 180 mLastCode = 0xFFFFFFFF;
hilgo 0:f8e2ed766064 181 return code;
hilgo 0:f8e2ed766064 182 }
hilgo 0:f8e2ed766064 183
hilgo 0:f8e2ed766064 184 void Rc6Receiver::OnRise()
hilgo 0:f8e2ed766064 185 {
hilgo 0:f8e2ed766064 186 if(mBusy)
hilgo 0:f8e2ed766064 187 {
hilgo 0:f8e2ed766064 188 // Rising edges are not interesting; they correspond to '0'.
hilgo 0:f8e2ed766064 189 }
hilgo 0:f8e2ed766064 190 else
hilgo 0:f8e2ed766064 191 {
hilgo 0:f8e2ed766064 192 mBusy = true;
hilgo 0:f8e2ed766064 193 mCode = 0;
hilgo 0:f8e2ed766064 194 mTimer.start();
hilgo 0:f8e2ed766064 195 mTimeout.attach_us(this, &Rc6Receiver::OnTimeout, 30000); // 52T of 16/36000 sec = 23ms
hilgo 0:f8e2ed766064 196 }
hilgo 0:f8e2ed766064 197 }
hilgo 0:f8e2ed766064 198
hilgo 0:f8e2ed766064 199 void Rc6Receiver::OnFall()
hilgo 0:f8e2ed766064 200 {
hilgo 0:f8e2ed766064 201 if(mBusy)
hilgo 0:f8e2ed766064 202 {
hilgo 0:f8e2ed766064 203 // Express edge location in 'T' (444.444 us)
hilgo 0:f8e2ed766064 204 int32_t edgeId = (mTimer.read_us()*1000 + 222222)/444444;
hilgo 0:f8e2ed766064 205 // printf("%d %d\r\n", mTimer.read_us(), edgeId); // Debug print. Doesn't mess up timing as hard as expected :-)
hilgo 0:f8e2ed766064 206
hilgo 0:f8e2ed766064 207 // Toggle bit is at edge 18. Store it!
hilgo 0:f8e2ed766064 208 if(edgeId == 18)
hilgo 0:f8e2ed766064 209 mCode |= 0x10000;
hilgo 0:f8e2ed766064 210 // Address and data bits.
hilgo 0:f8e2ed766064 211 if((edgeId & 0x01) && (edgeId > 21) && (edgeId < 52))
hilgo 0:f8e2ed766064 212 {
hilgo 0:f8e2ed766064 213 uint8_t bit = 15 - (edgeId-21)/2;
hilgo 0:f8e2ed766064 214 mCode |= 1<<bit;
hilgo 0:f8e2ed766064 215 }
hilgo 0:f8e2ed766064 216 }
hilgo 0:f8e2ed766064 217 }
hilgo 0:f8e2ed766064 218
hilgo 0:f8e2ed766064 219 void Rc6Receiver::OnTimeout()
hilgo 0:f8e2ed766064 220 {
hilgo 0:f8e2ed766064 221 mTimer.stop();
hilgo 0:f8e2ed766064 222 mTimer.reset();
hilgo 0:f8e2ed766064 223 mBusy = false;
hilgo 0:f8e2ed766064 224 mLastCode = mCode;
hilgo 0:f8e2ed766064 225 }