Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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