forked RemoteIR

Fork of RemoteIR by Shinichiro Nakamura

Committer:
misodengaku
Date:
Sat Mar 17 14:42:15 2018 +0000
Revision:
12:d86179332137
Parent:
11:268cc2ab63bd
support level inversion

Who changed what in which revision?

UserRevisionLine numberNew contents of line
shintamainjp 0:ec264f4ce158 1 /**
shintamainjp 9:dcfdac59ef74 2 * IR transmitter (Version 0.0.4)
shintamainjp 0:ec264f4ce158 3 *
shintamainjp 0:ec264f4ce158 4 * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems)
shintamainjp 0:ec264f4ce158 5 * http://shinta.main.jp/
shintamainjp 0:ec264f4ce158 6 */
shintamainjp 0:ec264f4ce158 7
shintamainjp 0:ec264f4ce158 8 #include "TransmitterIR.h"
shintamainjp 0:ec264f4ce158 9
shintamainjp 10:c54fb1204d1e 10 #define LOCK()
shintamainjp 10:c54fb1204d1e 11 #define UNLOCK()
shintamainjp 0:ec264f4ce158 12
shintamainjp 11:268cc2ab63bd 13 /**
shintamainjp 11:268cc2ab63bd 14 * Constructor.
shintamainjp 11:268cc2ab63bd 15 *
shintamainjp 11:268cc2ab63bd 16 * @param txpin Pin for transmit IR signal.
shintamainjp 11:268cc2ab63bd 17 */
misodengaku 12:d86179332137 18 TransmitterIR::TransmitterIR(PinName txpin, bool ti = false) : tx(txpin) {
misodengaku 12:d86179332137 19 txInversion = ti;
misodengaku 12:d86179332137 20 setLEDLow();
shintamainjp 0:ec264f4ce158 21 tx.period_us(26.3);
shintamainjp 0:ec264f4ce158 22
shintamainjp 0:ec264f4ce158 23 work.state = Idle;
shintamainjp 0:ec264f4ce158 24 work.bitcount = 0;
shintamainjp 0:ec264f4ce158 25 work.leader = 0;
shintamainjp 0:ec264f4ce158 26 work.data = 0;
shintamainjp 0:ec264f4ce158 27 work.trailer = 0;
shintamainjp 0:ec264f4ce158 28
shintamainjp 0:ec264f4ce158 29 data.format = RemoteIR::UNKNOWN;
shintamainjp 0:ec264f4ce158 30 data.bitlength = 0;
shintamainjp 0:ec264f4ce158 31 }
shintamainjp 0:ec264f4ce158 32
shintamainjp 11:268cc2ab63bd 33 /**
shintamainjp 11:268cc2ab63bd 34 * Destructor.
shintamainjp 11:268cc2ab63bd 35 */
shintamainjp 2:08836610bd4a 36 TransmitterIR::~TransmitterIR() {
shintamainjp 2:08836610bd4a 37 }
shintamainjp 2:08836610bd4a 38
shintamainjp 11:268cc2ab63bd 39 /**
shintamainjp 11:268cc2ab63bd 40 * Get state.
shintamainjp 11:268cc2ab63bd 41 *
shintamainjp 11:268cc2ab63bd 42 * @return Current state.
shintamainjp 11:268cc2ab63bd 43 */
shintamainjp 0:ec264f4ce158 44 TransmitterIR::State TransmitterIR::getState(void) {
shintamainjp 9:dcfdac59ef74 45 LOCK();
shintamainjp 0:ec264f4ce158 46 State s = work.state;
shintamainjp 9:dcfdac59ef74 47 UNLOCK();
shintamainjp 0:ec264f4ce158 48 return s;
shintamainjp 0:ec264f4ce158 49 }
shintamainjp 0:ec264f4ce158 50
shintamainjp 11:268cc2ab63bd 51 /**
shintamainjp 11:268cc2ab63bd 52 * Set data.
shintamainjp 11:268cc2ab63bd 53 *
shintamainjp 11:268cc2ab63bd 54 * @param format Format.
shintamainjp 11:268cc2ab63bd 55 * @param buf Buffer of a data.
shintamainjp 11:268cc2ab63bd 56 * @param bitlength Bit length of the data.
shintamainjp 11:268cc2ab63bd 57 *
shintamainjp 11:268cc2ab63bd 58 * @return Data bit length.
shintamainjp 11:268cc2ab63bd 59 */
shintamainjp 0:ec264f4ce158 60 int TransmitterIR::setData(RemoteIR::Format format, uint8_t *buf, int bitlength) {
shintamainjp 9:dcfdac59ef74 61 LOCK();
shintamainjp 0:ec264f4ce158 62 if (work.state != Idle) {
shintamainjp 9:dcfdac59ef74 63 UNLOCK();
shintamainjp 0:ec264f4ce158 64 return -1;
shintamainjp 0:ec264f4ce158 65 }
shintamainjp 0:ec264f4ce158 66
shintamainjp 0:ec264f4ce158 67 work.state = Leader;
shintamainjp 0:ec264f4ce158 68 work.bitcount = 0;
shintamainjp 0:ec264f4ce158 69 work.leader = 0;
shintamainjp 0:ec264f4ce158 70 work.data = 0;
shintamainjp 0:ec264f4ce158 71 work.trailer = 0;
shintamainjp 0:ec264f4ce158 72
shintamainjp 0:ec264f4ce158 73 data.format = format;
shintamainjp 0:ec264f4ce158 74 data.bitlength = bitlength;
shintamainjp 0:ec264f4ce158 75 const int n = bitlength / 8 + (((bitlength % 8) != 0) ? 1 : 0);
shintamainjp 0:ec264f4ce158 76 for (int i = 0; i < n; i++) {
shintamainjp 0:ec264f4ce158 77 data.buffer[i] = buf[i];
shintamainjp 0:ec264f4ce158 78 }
shintamainjp 0:ec264f4ce158 79
shintamainjp 0:ec264f4ce158 80 switch (format) {
shintamainjp 0:ec264f4ce158 81 case RemoteIR::NEC:
shintamainjp 0:ec264f4ce158 82 ticker.detach();
shintamainjp 11:268cc2ab63bd 83 ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_NEC);
shintamainjp 0:ec264f4ce158 84 break;
shintamainjp 0:ec264f4ce158 85 case RemoteIR::AEHA:
shintamainjp 0:ec264f4ce158 86 ticker.detach();
shintamainjp 11:268cc2ab63bd 87 ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_AEHA);
shintamainjp 0:ec264f4ce158 88 break;
shintamainjp 0:ec264f4ce158 89 case RemoteIR::SONY:
shintamainjp 0:ec264f4ce158 90 ticker.detach();
shintamainjp 11:268cc2ab63bd 91 ticker.attach_us(this, &TransmitterIR::tick, RemoteIR::TUS_SONY);
shintamainjp 0:ec264f4ce158 92 break;
shintamainjp 0:ec264f4ce158 93 }
shintamainjp 0:ec264f4ce158 94
shintamainjp 9:dcfdac59ef74 95 UNLOCK();
shintamainjp 0:ec264f4ce158 96 return bitlength;
shintamainjp 0:ec264f4ce158 97 }
shintamainjp 0:ec264f4ce158 98
shintamainjp 0:ec264f4ce158 99 void TransmitterIR::tick(void) {
shintamainjp 9:dcfdac59ef74 100 LOCK();
shintamainjp 0:ec264f4ce158 101 switch (work.state) {
shintamainjp 0:ec264f4ce158 102 case Idle:
shintamainjp 0:ec264f4ce158 103 work.bitcount = 0;
shintamainjp 0:ec264f4ce158 104 work.leader = 0;
shintamainjp 0:ec264f4ce158 105 work.data = 0;
shintamainjp 0:ec264f4ce158 106 work.trailer = 0;
shintamainjp 0:ec264f4ce158 107 break;
shintamainjp 0:ec264f4ce158 108 case Leader:
shintamainjp 0:ec264f4ce158 109 if (data.format == RemoteIR::NEC) {
shintamainjp 0:ec264f4ce158 110 /*
shintamainjp 0:ec264f4ce158 111 * NEC.
shintamainjp 0:ec264f4ce158 112 */
shintamainjp 0:ec264f4ce158 113 static const int LEADER_NEC_HEAD = 16;
shintamainjp 0:ec264f4ce158 114 static const int LEADER_NEC_TAIL = 8;
shintamainjp 0:ec264f4ce158 115 if (work.leader < LEADER_NEC_HEAD) {
misodengaku 12:d86179332137 116 setLEDHigh();
shintamainjp 0:ec264f4ce158 117 } else {
misodengaku 12:d86179332137 118 setLEDLow();
shintamainjp 0:ec264f4ce158 119 }
shintamainjp 0:ec264f4ce158 120 work.leader++;
shintamainjp 0:ec264f4ce158 121 if ((LEADER_NEC_HEAD + LEADER_NEC_TAIL) <= work.leader) {
shintamainjp 0:ec264f4ce158 122 work.state = Data;
shintamainjp 0:ec264f4ce158 123 }
shintamainjp 0:ec264f4ce158 124 } else if (data.format == RemoteIR::AEHA) {
shintamainjp 0:ec264f4ce158 125 /*
shintamainjp 0:ec264f4ce158 126 * AEHA.
shintamainjp 0:ec264f4ce158 127 */
shintamainjp 0:ec264f4ce158 128 static const int LEADER_AEHA_HEAD = 8;
shintamainjp 0:ec264f4ce158 129 static const int LEADER_AEHA_TAIL = 4;
shintamainjp 0:ec264f4ce158 130 if (work.leader < LEADER_AEHA_HEAD) {
misodengaku 12:d86179332137 131 setLEDHigh();
shintamainjp 0:ec264f4ce158 132 } else {
misodengaku 12:d86179332137 133 setLEDLow();
shintamainjp 0:ec264f4ce158 134 }
shintamainjp 0:ec264f4ce158 135 work.leader++;
shintamainjp 0:ec264f4ce158 136 if ((LEADER_AEHA_HEAD + LEADER_AEHA_TAIL) <= work.leader) {
shintamainjp 0:ec264f4ce158 137 work.state = Data;
shintamainjp 0:ec264f4ce158 138 }
shintamainjp 0:ec264f4ce158 139 } else if (data.format == RemoteIR::SONY) {
shintamainjp 0:ec264f4ce158 140 /*
shintamainjp 0:ec264f4ce158 141 * SONY.
shintamainjp 0:ec264f4ce158 142 */
shintamainjp 0:ec264f4ce158 143 static const int LEADER_SONY_HEAD = 4;
shintamainjp 0:ec264f4ce158 144 static const int LEADER_SONY_TAIL = 0;
shintamainjp 0:ec264f4ce158 145 if (work.leader < LEADER_SONY_HEAD) {
misodengaku 12:d86179332137 146 setLEDHigh();
shintamainjp 0:ec264f4ce158 147 } else {
misodengaku 12:d86179332137 148 setLEDLow();
shintamainjp 0:ec264f4ce158 149 }
shintamainjp 0:ec264f4ce158 150 work.leader++;
shintamainjp 0:ec264f4ce158 151 if ((LEADER_SONY_HEAD + LEADER_SONY_TAIL) <= work.leader) {
shintamainjp 0:ec264f4ce158 152 work.state = Data;
shintamainjp 0:ec264f4ce158 153 }
shintamainjp 0:ec264f4ce158 154 } else {
shintamainjp 0:ec264f4ce158 155 }
shintamainjp 0:ec264f4ce158 156 break;
shintamainjp 0:ec264f4ce158 157 case Data:
shintamainjp 0:ec264f4ce158 158 if (data.format == RemoteIR::NEC) {
shintamainjp 0:ec264f4ce158 159 /*
shintamainjp 0:ec264f4ce158 160 * NEC.
shintamainjp 0:ec264f4ce158 161 */
shintamainjp 0:ec264f4ce158 162 if (work.data == 0) {
misodengaku 12:d86179332137 163 setLEDHigh();
shintamainjp 0:ec264f4ce158 164 work.data++;
shintamainjp 0:ec264f4ce158 165 } else {
misodengaku 12:d86179332137 166 setLEDLow();
shintamainjp 0:ec264f4ce158 167 if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
shintamainjp 0:ec264f4ce158 168 if (3 <= work.data) {
shintamainjp 0:ec264f4ce158 169 work.bitcount++;
shintamainjp 0:ec264f4ce158 170 work.data = 0;
shintamainjp 0:ec264f4ce158 171 } else {
shintamainjp 0:ec264f4ce158 172 work.data++;
shintamainjp 0:ec264f4ce158 173 }
shintamainjp 0:ec264f4ce158 174 } else {
shintamainjp 0:ec264f4ce158 175 if (1 <= work.data) {
shintamainjp 0:ec264f4ce158 176 work.bitcount++;
shintamainjp 0:ec264f4ce158 177 work.data = 0;
shintamainjp 0:ec264f4ce158 178 } else {
shintamainjp 0:ec264f4ce158 179 work.data++;
shintamainjp 0:ec264f4ce158 180 }
shintamainjp 0:ec264f4ce158 181 }
shintamainjp 0:ec264f4ce158 182 }
shintamainjp 0:ec264f4ce158 183 if (data.bitlength <= work.bitcount) {
shintamainjp 0:ec264f4ce158 184 work.state = Trailer;
shintamainjp 0:ec264f4ce158 185 }
shintamainjp 0:ec264f4ce158 186 } else if (data.format == RemoteIR::AEHA) {
shintamainjp 0:ec264f4ce158 187 /*
shintamainjp 0:ec264f4ce158 188 * AEHA.
shintamainjp 0:ec264f4ce158 189 */
shintamainjp 0:ec264f4ce158 190 if (work.data == 0) {
misodengaku 12:d86179332137 191 setLEDHigh();
shintamainjp 0:ec264f4ce158 192 work.data++;
shintamainjp 0:ec264f4ce158 193 } else {
misodengaku 12:d86179332137 194 setLEDLow();
shintamainjp 0:ec264f4ce158 195 if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
shintamainjp 0:ec264f4ce158 196 if (3 <= work.data) {
shintamainjp 0:ec264f4ce158 197 work.bitcount++;
shintamainjp 0:ec264f4ce158 198 work.data = 0;
shintamainjp 0:ec264f4ce158 199 } else {
shintamainjp 0:ec264f4ce158 200 work.data++;
shintamainjp 0:ec264f4ce158 201 }
shintamainjp 0:ec264f4ce158 202 } else {
shintamainjp 0:ec264f4ce158 203 if (1 <= work.data) {
shintamainjp 0:ec264f4ce158 204 work.bitcount++;
shintamainjp 0:ec264f4ce158 205 work.data = 0;
shintamainjp 0:ec264f4ce158 206 } else {
shintamainjp 0:ec264f4ce158 207 work.data++;
shintamainjp 0:ec264f4ce158 208 }
shintamainjp 0:ec264f4ce158 209 }
shintamainjp 0:ec264f4ce158 210 }
shintamainjp 0:ec264f4ce158 211 if (data.bitlength <= work.bitcount) {
shintamainjp 0:ec264f4ce158 212 work.state = Trailer;
shintamainjp 0:ec264f4ce158 213 }
shintamainjp 0:ec264f4ce158 214 } else if (data.format == RemoteIR::SONY) {
shintamainjp 0:ec264f4ce158 215 /*
shintamainjp 0:ec264f4ce158 216 * SONY.
shintamainjp 0:ec264f4ce158 217 */
shintamainjp 0:ec264f4ce158 218 if (work.data == 0) {
misodengaku 12:d86179332137 219 setLEDLow();
shintamainjp 0:ec264f4ce158 220 work.data++;
shintamainjp 0:ec264f4ce158 221 } else {
misodengaku 12:d86179332137 222 setLEDHigh();
shintamainjp 0:ec264f4ce158 223 if (0 != (data.buffer[work.bitcount / 8] & (1 << work.bitcount % 8))) {
shintamainjp 0:ec264f4ce158 224 if (2 <= work.data) {
shintamainjp 0:ec264f4ce158 225 work.bitcount++;
shintamainjp 0:ec264f4ce158 226 work.data = 0;
shintamainjp 0:ec264f4ce158 227 } else {
shintamainjp 0:ec264f4ce158 228 work.data++;
shintamainjp 0:ec264f4ce158 229 }
shintamainjp 0:ec264f4ce158 230 } else {
shintamainjp 0:ec264f4ce158 231 if (1 <= work.data) {
shintamainjp 0:ec264f4ce158 232 work.bitcount++;
shintamainjp 0:ec264f4ce158 233 work.data = 0;
shintamainjp 0:ec264f4ce158 234 } else {
shintamainjp 0:ec264f4ce158 235 work.data++;
shintamainjp 0:ec264f4ce158 236 }
shintamainjp 0:ec264f4ce158 237 }
shintamainjp 0:ec264f4ce158 238 }
shintamainjp 0:ec264f4ce158 239 if (data.bitlength <= work.bitcount) {
shintamainjp 0:ec264f4ce158 240 work.state = Trailer;
shintamainjp 0:ec264f4ce158 241 }
shintamainjp 0:ec264f4ce158 242 } else {
shintamainjp 0:ec264f4ce158 243 }
shintamainjp 0:ec264f4ce158 244 break;
shintamainjp 0:ec264f4ce158 245 case Trailer:
shintamainjp 0:ec264f4ce158 246 if (data.format == RemoteIR::NEC) {
shintamainjp 0:ec264f4ce158 247 /*
shintamainjp 0:ec264f4ce158 248 * NEC.
shintamainjp 0:ec264f4ce158 249 */
shintamainjp 0:ec264f4ce158 250 static const int TRAILER_NEC_HEAD = 1;
shintamainjp 0:ec264f4ce158 251 static const int TRAILER_NEC_TAIL = 2;
shintamainjp 0:ec264f4ce158 252 if (work.trailer < TRAILER_NEC_HEAD) {
misodengaku 12:d86179332137 253 setLEDHigh();
shintamainjp 0:ec264f4ce158 254 } else {
misodengaku 12:d86179332137 255 setLEDLow();
shintamainjp 0:ec264f4ce158 256 }
shintamainjp 0:ec264f4ce158 257 work.trailer++;
shintamainjp 0:ec264f4ce158 258 if ((TRAILER_NEC_HEAD + TRAILER_NEC_TAIL) <= work.trailer) {
shintamainjp 0:ec264f4ce158 259 work.state = Idle;
shintamainjp 0:ec264f4ce158 260 //ticker.detach();
shintamainjp 0:ec264f4ce158 261 }
shintamainjp 0:ec264f4ce158 262 } else if (data.format == RemoteIR::AEHA) {
shintamainjp 0:ec264f4ce158 263 /*
shintamainjp 0:ec264f4ce158 264 * AEHA.
shintamainjp 0:ec264f4ce158 265 */
shintamainjp 0:ec264f4ce158 266 static const int TRAILER_AEHA_HEAD = 1;
shintamainjp 11:268cc2ab63bd 267 static const int TRAILER_AEHA_TAIL = 8000 / RemoteIR::TUS_AEHA;
shintamainjp 0:ec264f4ce158 268 if (work.trailer < TRAILER_AEHA_HEAD) {
misodengaku 12:d86179332137 269 setLEDHigh();
shintamainjp 0:ec264f4ce158 270 } else {
misodengaku 12:d86179332137 271 setLEDLow();
shintamainjp 0:ec264f4ce158 272 }
shintamainjp 0:ec264f4ce158 273 work.trailer++;
shintamainjp 0:ec264f4ce158 274 if ((TRAILER_AEHA_HEAD + TRAILER_AEHA_TAIL) <= work.trailer) {
shintamainjp 0:ec264f4ce158 275 work.state = Idle;
shintamainjp 0:ec264f4ce158 276 //ticker.detach();
shintamainjp 0:ec264f4ce158 277 }
shintamainjp 0:ec264f4ce158 278 } else if (data.format == RemoteIR::SONY) {
shintamainjp 0:ec264f4ce158 279 /*
shintamainjp 0:ec264f4ce158 280 * SONY.
shintamainjp 0:ec264f4ce158 281 */
shintamainjp 0:ec264f4ce158 282 static const int TRAILER_SONY_HEAD = 0;
shintamainjp 0:ec264f4ce158 283 static const int TRAILER_SONY_TAIL = 0;
shintamainjp 0:ec264f4ce158 284 if (work.trailer < TRAILER_SONY_HEAD) {
misodengaku 12:d86179332137 285 setLEDHigh();
shintamainjp 0:ec264f4ce158 286 } else {
misodengaku 12:d86179332137 287 setLEDLow();
shintamainjp 0:ec264f4ce158 288 }
shintamainjp 0:ec264f4ce158 289 work.trailer++;
shintamainjp 0:ec264f4ce158 290 if ((TRAILER_SONY_HEAD + TRAILER_SONY_TAIL) <= work.trailer) {
shintamainjp 0:ec264f4ce158 291 work.state = Idle;
shintamainjp 0:ec264f4ce158 292 //ticker.detach();
shintamainjp 0:ec264f4ce158 293 }
shintamainjp 0:ec264f4ce158 294 } else {
shintamainjp 0:ec264f4ce158 295 }
shintamainjp 0:ec264f4ce158 296 break;
shintamainjp 0:ec264f4ce158 297 default:
shintamainjp 0:ec264f4ce158 298 break;
shintamainjp 0:ec264f4ce158 299 }
shintamainjp 9:dcfdac59ef74 300 UNLOCK();
shintamainjp 0:ec264f4ce158 301 }
misodengaku 12:d86179332137 302
misodengaku 12:d86179332137 303 void TransmitterIR::setLEDHigh(void) {
misodengaku 12:d86179332137 304 if (txInversion)
misodengaku 12:d86179332137 305 {
misodengaku 12:d86179332137 306 tx.write(0.5);
misodengaku 12:d86179332137 307 } else {
misodengaku 12:d86179332137 308 tx.write(0.0);
misodengaku 12:d86179332137 309 }
misodengaku 12:d86179332137 310 }
misodengaku 12:d86179332137 311
misodengaku 12:d86179332137 312 void TransmitterIR::setLEDLow(void) {
misodengaku 12:d86179332137 313 if (txInversion)
misodengaku 12:d86179332137 314 {
misodengaku 12:d86179332137 315 tx.write(1.0);
misodengaku 12:d86179332137 316 } else {
misodengaku 12:d86179332137 317 printf("0.5\n");
misodengaku 12:d86179332137 318 tx.write(0.5);
misodengaku 12:d86179332137 319 }
misodengaku 12:d86179332137 320 }