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
00001 /* mbed RC6 (Philips remote control protocol) library 00002 * Copyright (c) 2011 Jeroen Hilgers 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 * THE SOFTWARE. 00021 */ 00022 00023 #include "Rc6.h" 00024 00025 Rc6Transmitter::Rc6Transmitter(PinName irPin) : 00026 mOut(irPin) 00027 { 00028 00029 mBusy = false; 00030 } 00031 00032 void Rc6Transmitter::Send(uint32_t code) 00033 { 00034 if(mBusy) 00035 { 00036 printf("Busy"); 00037 return; 00038 } 00039 mBusy = true; 00040 00041 uint8_t index = 0; 00042 uint8_t level; 00043 uint16_t time; 00044 uint8_t bit; 00045 // Leader 00046 mPattern[index++] = 6*16; // Mark 00047 mPattern[index++] = 2*16; // Pause 00048 // Start bit 3. 00049 mPattern[index++] = 16; 00050 mPattern[index++] = 2*16; 00051 // Start bit 2. 00052 mPattern[index++] = 16; 00053 // Start bit 1. 00054 mPattern[index++] = 16; 00055 mPattern[index++] = 16; 00056 // Start bit 0. 00057 mPattern[index++] = 16; 00058 // Toggle bit. 00059 if(code & 0x10000) 00060 { 00061 mPattern[index++] = 3*16; 00062 level = 0; 00063 time = 2*16; 00064 } 00065 else 00066 { 00067 mPattern[index++] = 16; 00068 mPattern[index++] = 2*16; 00069 level = 1; 00070 time = 2*16; 00071 } 00072 for(bit = 0; bit < 16; bit ++) 00073 { 00074 if(code & 0x8000) 00075 { // Send '1' 00076 if(level) 00077 { 00078 mPattern[index++] = 16+time; 00079 } 00080 else 00081 { 00082 mPattern[index++] = time; 00083 mPattern[index++] = 16; 00084 } 00085 level = 0; 00086 time = 16; 00087 } 00088 else 00089 { // Send '0' 00090 if(level) 00091 { 00092 mPattern[index++] = time; 00093 mPattern[index++] = 16; 00094 } 00095 else 00096 { 00097 mPattern[index++] = 16+time; 00098 } 00099 level = 1; 00100 time = 16; 00101 } 00102 code <<= 1; 00103 } 00104 if(level == 1) 00105 { 00106 mPattern[index++] = time; 00107 } 00108 mPattern[index++] = 16; // Teminate with half symbol (not long enough?) 00109 00110 mPattern[index++] = 0; // Mark duration of 0 means end-of-pattern. 00111 mPattern[index++] = 0; 00112 00113 // Setup transmitter variables... 00114 mMark = 0; 00115 mPause = 0; 00116 mPatPtr = mPattern; 00117 00118 // ... and attach ticker. 00119 // mTicker.attach(this, &Rc6Sender::Tick, 1.0/(2.0*36000.0)); // This rounds down to: 00120 // mTicker.attach_us(this, &Rc6Sender::Tick, 13); // Both are noticeable too slow compared to the real remote! 00121 mTicker.attach_us(this, &Rc6Transmitter::Tick, 14); // This does work. 00122 } 00123 00124 bool Rc6Transmitter::IsBusy() 00125 { 00126 return mBusy; 00127 } 00128 00129 void Rc6Transmitter::Tick() 00130 { 00131 if(mMark) 00132 { // Busy sending a mark. Do next part. 00133 mMark--; 00134 if(mMark&1) 00135 { 00136 mOut = 1; 00137 } 00138 else 00139 { 00140 mOut = 0; 00141 } 00142 } 00143 else 00144 { 00145 if(mPause) 00146 { // Need to do some more pause. 00147 mPause--; 00148 } 00149 else 00150 { // Last half cycle of pause. Check next activity. 00151 mMark = (*mPatPtr++)<<1; // Half-cycles of marker. 00152 mPause = (*mPatPtr++)<<1; // half-cycles of pause. 00153 mPause--; // The last half-cycle of puase is spend here setting up next cycle. 00154 if(mMark == 0) 00155 { 00156 // We are done. Stop ticker. 00157 mTicker.detach(); 00158 mBusy = false; 00159 } 00160 } 00161 } 00162 } 00163 00164 Rc6Receiver::Rc6Receiver(PinName irIn) : 00165 irq(irIn) 00166 { 00167 // NOTE: Ir sensor inversion is handled here! 00168 irq.rise(this, &Rc6Receiver::OnFall); 00169 irq.fall(this, &Rc6Receiver::OnRise); 00170 mBusy = false; 00171 mLastCode = 0xFFFFFFFF; 00172 } 00173 00174 uint32_t Rc6Receiver::Receive() 00175 { 00176 // TODO: Disable interrupts to prevent one in a million chance that 00177 // mLastCode gets updated... 00178 uint32_t code = mLastCode; 00179 // ... at exactly this moment, so it will be discarded here: 00180 mLastCode = 0xFFFFFFFF; 00181 return code; 00182 } 00183 00184 void Rc6Receiver::OnRise() 00185 { 00186 if(mBusy) 00187 { 00188 // Rising edges are not interesting; they correspond to '0'. 00189 } 00190 else 00191 { 00192 mBusy = true; 00193 mCode = 0; 00194 mTimer.start(); 00195 mTimeout.attach_us(this, &Rc6Receiver::OnTimeout, 30000); // 52T of 16/36000 sec = 23ms 00196 } 00197 } 00198 00199 void Rc6Receiver::OnFall() 00200 { 00201 if(mBusy) 00202 { 00203 // Express edge location in 'T' (444.444 us) 00204 int32_t edgeId = (mTimer.read_us()*1000 + 222222)/444444; 00205 // printf("%d %d\r\n", mTimer.read_us(), edgeId); // Debug print. Doesn't mess up timing as hard as expected :-) 00206 00207 // Toggle bit is at edge 18. Store it! 00208 if(edgeId == 18) 00209 mCode |= 0x10000; 00210 // Address and data bits. 00211 if((edgeId & 0x01) && (edgeId > 21) && (edgeId < 52)) 00212 { 00213 uint8_t bit = 15 - (edgeId-21)/2; 00214 mCode |= 1<<bit; 00215 } 00216 } 00217 } 00218 00219 void Rc6Receiver::OnTimeout() 00220 { 00221 mTimer.stop(); 00222 mTimer.reset(); 00223 mBusy = false; 00224 mLastCode = mCode; 00225 }
Generated on Fri Aug 5 2022 17:30:03 by
1.7.2