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.
Rc6.cpp@0:f8e2ed766064, 2011-02-27 (annotated)
- 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?
User | Revision | Line number | New 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 | } |