IR remote test, based on Arduino IRRemote lib.
IR remote test, based on Arduino IRremote lib.
https://www.pjrc.com/teensy/td_libs_IRremote.html
Uses PWM for carrier and timer for 50us sensor reads. for k64f, one could use CMT.
main.cpp@1:af81e02b8c7b, 2016-04-13 (annotated)
- Committer:
- manitou
- Date:
- Wed Apr 13 11:18:39 2016 +0000
- Revision:
- 1:af81e02b8c7b
- Parent:
- 0:785739d5a30a
edit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
manitou | 0:785739d5a30a | 1 | /* |
manitou | 0:785739d5a30a | 2 | IRtest |
manitou | 0:785739d5a30a | 3 | hack of maple version |
manitou | 0:785739d5a30a | 4 | http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html |
manitou | 0:785739d5a30a | 5 | use PWM to generate mark/space at 38Khz |
manitou | 0:785739d5a30a | 6 | IR LED xmit pin to 100ohm to +IR - to grnd (short/flat) |
manitou | 0:785739d5a30a | 7 | use timer 50us to count mark/space on input |
manitou | 0:785739d5a30a | 8 | is it possible to run both xmit and recv? |
manitou | 0:785739d5a30a | 9 | */ |
manitou | 0:785739d5a30a | 10 | #include "mbed.h" |
manitou | 0:785739d5a30a | 11 | #include "IRremote.h" |
manitou | 0:785739d5a30a | 12 | |
manitou | 0:785739d5a30a | 13 | Ticker ticker; |
manitou | 0:785739d5a30a | 14 | |
manitou | 0:785739d5a30a | 15 | // K64F pins |
manitou | 0:785739d5a30a | 16 | #define RecvPin D7 |
manitou | 0:785739d5a30a | 17 | #define PWMPin D6 |
manitou | 0:785739d5a30a | 18 | #define TestPin D13 |
manitou | 0:785739d5a30a | 19 | |
manitou | 0:785739d5a30a | 20 | PwmOut pwm(PWMPin); |
manitou | 0:785739d5a30a | 21 | DigitalIn recvpin(RecvPin); |
manitou | 1:af81e02b8c7b | 22 | DigitalOut testpin(TestPin); // jumper to RecvPin for test |
manitou | 0:785739d5a30a | 23 | DigitalOut myled(LED1); |
manitou | 0:785739d5a30a | 24 | |
manitou | 0:785739d5a30a | 25 | volatile unsigned long myticks; |
manitou | 0:785739d5a30a | 26 | int rawbuf[RAWBUF], rawlen; |
manitou | 0:785739d5a30a | 27 | uint8_t rcvstate; |
manitou | 0:785739d5a30a | 28 | int results_decode_type; // NEC, SONY, RC5, UNKNOWN |
manitou | 0:785739d5a30a | 29 | unsigned long results_value; |
manitou | 0:785739d5a30a | 30 | int results_bits; // Number of bits in decoded value |
manitou | 0:785739d5a30a | 31 | |
manitou | 0:785739d5a30a | 32 | |
manitou | 0:785739d5a30a | 33 | void timer_ISR() { |
manitou | 0:785739d5a30a | 34 | // interrupt every 50us |
manitou | 0:785739d5a30a | 35 | uint8_t irdata = recvpin; // read IR sensor |
manitou | 0:785739d5a30a | 36 | myticks++; |
manitou | 0:785739d5a30a | 37 | |
manitou | 0:785739d5a30a | 38 | |
manitou | 0:785739d5a30a | 39 | if (rawlen >= RAWBUF) { |
manitou | 0:785739d5a30a | 40 | // Buffer overflow |
manitou | 0:785739d5a30a | 41 | rcvstate = STATE_STOP; |
manitou | 0:785739d5a30a | 42 | } |
manitou | 0:785739d5a30a | 43 | switch(rcvstate) { |
manitou | 0:785739d5a30a | 44 | case STATE_IDLE: // In the middle of a gap |
manitou | 0:785739d5a30a | 45 | if (irdata == MARK) { |
manitou | 0:785739d5a30a | 46 | if (myticks < GAP_TICKS) { |
manitou | 0:785739d5a30a | 47 | // Not big enough to be a gap. |
manitou | 0:785739d5a30a | 48 | myticks = 0; |
manitou | 0:785739d5a30a | 49 | } |
manitou | 0:785739d5a30a | 50 | else { |
manitou | 0:785739d5a30a | 51 | // gap just ended, record duration and start recording transmission |
manitou | 0:785739d5a30a | 52 | rawlen = 0; |
manitou | 0:785739d5a30a | 53 | rawbuf[rawlen++] = myticks; |
manitou | 0:785739d5a30a | 54 | myticks = 0; |
manitou | 0:785739d5a30a | 55 | rcvstate = STATE_MARK; |
manitou | 0:785739d5a30a | 56 | } |
manitou | 0:785739d5a30a | 57 | } |
manitou | 0:785739d5a30a | 58 | break; |
manitou | 0:785739d5a30a | 59 | case STATE_MARK: // timing MARK |
manitou | 0:785739d5a30a | 60 | if (irdata == SPACE) { // MARK ended, record time |
manitou | 0:785739d5a30a | 61 | rawbuf[rawlen++] = myticks; |
manitou | 0:785739d5a30a | 62 | myticks = 0; |
manitou | 0:785739d5a30a | 63 | rcvstate = STATE_SPACE; |
manitou | 0:785739d5a30a | 64 | } |
manitou | 0:785739d5a30a | 65 | break; |
manitou | 0:785739d5a30a | 66 | case STATE_SPACE: // timing SPACE |
manitou | 0:785739d5a30a | 67 | if (irdata == MARK) { // SPACE just ended, record it |
manitou | 0:785739d5a30a | 68 | rawbuf[rawlen++] = myticks; |
manitou | 0:785739d5a30a | 69 | myticks = 0; |
manitou | 0:785739d5a30a | 70 | rcvstate = STATE_MARK; |
manitou | 0:785739d5a30a | 71 | } |
manitou | 0:785739d5a30a | 72 | else { // SPACE |
manitou | 0:785739d5a30a | 73 | if (myticks > GAP_TICKS) { |
manitou | 0:785739d5a30a | 74 | // big SPACE, indicates gap between codes |
manitou | 0:785739d5a30a | 75 | // Mark current code as ready for processing |
manitou | 0:785739d5a30a | 76 | // Switch to STOP |
manitou | 0:785739d5a30a | 77 | // Don't reset timer; keep counting space width |
manitou | 0:785739d5a30a | 78 | rcvstate = STATE_STOP; |
manitou | 0:785739d5a30a | 79 | } |
manitou | 0:785739d5a30a | 80 | } |
manitou | 0:785739d5a30a | 81 | break; |
manitou | 0:785739d5a30a | 82 | case STATE_STOP: // waiting, measuring gap |
manitou | 0:785739d5a30a | 83 | if (irdata == MARK) { // reset gap timer |
manitou | 0:785739d5a30a | 84 | myticks = 0; |
manitou | 0:785739d5a30a | 85 | } |
manitou | 0:785739d5a30a | 86 | break; |
manitou | 0:785739d5a30a | 87 | } |
manitou | 0:785739d5a30a | 88 | |
manitou | 0:785739d5a30a | 89 | } |
manitou | 0:785739d5a30a | 90 | |
manitou | 0:785739d5a30a | 91 | // set up recv timer |
manitou | 0:785739d5a30a | 92 | void enableIRIn(){ |
manitou | 0:785739d5a30a | 93 | ticker.attach_us(&timer_ISR,50); |
manitou | 0:785739d5a30a | 94 | rcvstate = STATE_IDLE; |
manitou | 0:785739d5a30a | 95 | rawlen = 0; |
manitou | 0:785739d5a30a | 96 | } |
manitou | 0:785739d5a30a | 97 | |
manitou | 0:785739d5a30a | 98 | void irrecv_resume() { |
manitou | 0:785739d5a30a | 99 | rcvstate = STATE_IDLE; |
manitou | 0:785739d5a30a | 100 | rawlen = 0; |
manitou | 0:785739d5a30a | 101 | } |
manitou | 0:785739d5a30a | 102 | |
manitou | 0:785739d5a30a | 103 | long decodeSony() { |
manitou | 0:785739d5a30a | 104 | long data = 0; |
manitou | 0:785739d5a30a | 105 | if (rawlen < 2 * SONY_BITS + 2) { |
manitou | 0:785739d5a30a | 106 | return ERR; |
manitou | 0:785739d5a30a | 107 | } |
manitou | 0:785739d5a30a | 108 | int offset = 1; // Skip first space |
manitou | 0:785739d5a30a | 109 | // Initial mark |
manitou | 0:785739d5a30a | 110 | if (!MATCH_MARK(rawbuf[offset], SONY_HDR_MARK)) { |
manitou | 0:785739d5a30a | 111 | return ERR; |
manitou | 0:785739d5a30a | 112 | } |
manitou | 0:785739d5a30a | 113 | offset++; |
manitou | 0:785739d5a30a | 114 | |
manitou | 0:785739d5a30a | 115 | while (offset + 1 < rawlen) { |
manitou | 0:785739d5a30a | 116 | if (!MATCH_SPACE(rawbuf[offset], SONY_HDR_SPACE)) { |
manitou | 0:785739d5a30a | 117 | break; |
manitou | 0:785739d5a30a | 118 | } |
manitou | 0:785739d5a30a | 119 | offset++; |
manitou | 0:785739d5a30a | 120 | if (MATCH_MARK(rawbuf[offset], SONY_ONE_MARK)) { |
manitou | 0:785739d5a30a | 121 | data = (data << 1) | 1; |
manitou | 0:785739d5a30a | 122 | } |
manitou | 0:785739d5a30a | 123 | else if (MATCH_MARK(rawbuf[offset], SONY_ZERO_MARK)) { |
manitou | 0:785739d5a30a | 124 | data <<= 1; |
manitou | 0:785739d5a30a | 125 | } |
manitou | 0:785739d5a30a | 126 | else { |
manitou | 0:785739d5a30a | 127 | return ERR; |
manitou | 0:785739d5a30a | 128 | } |
manitou | 0:785739d5a30a | 129 | offset++; |
manitou | 0:785739d5a30a | 130 | } |
manitou | 0:785739d5a30a | 131 | |
manitou | 0:785739d5a30a | 132 | // Success |
manitou | 0:785739d5a30a | 133 | results_bits = (offset - 1) / 2; |
manitou | 0:785739d5a30a | 134 | if (results_bits < 12) { |
manitou | 0:785739d5a30a | 135 | results_bits = 0; |
manitou | 0:785739d5a30a | 136 | return ERR; |
manitou | 0:785739d5a30a | 137 | } |
manitou | 0:785739d5a30a | 138 | results_value = data; |
manitou | 0:785739d5a30a | 139 | results_decode_type = SONY; |
manitou | 0:785739d5a30a | 140 | return DECODED; |
manitou | 0:785739d5a30a | 141 | } |
manitou | 0:785739d5a30a | 142 | |
manitou | 0:785739d5a30a | 143 | void enableIROut(int khz) { |
manitou | 0:785739d5a30a | 144 | int freq = 1000 * khz; |
manitou | 0:785739d5a30a | 145 | pwm.period(1./freq); |
manitou | 0:785739d5a30a | 146 | pwm.write(0); // start PWM with low |
manitou | 0:785739d5a30a | 147 | } |
manitou | 0:785739d5a30a | 148 | |
manitou | 0:785739d5a30a | 149 | void mark(int time) { |
manitou | 0:785739d5a30a | 150 | pwm.write(0.5); // PWM on |
manitou | 0:785739d5a30a | 151 | testpin=0; // test invert |
manitou | 0:785739d5a30a | 152 | wait_us(time); |
manitou | 0:785739d5a30a | 153 | } |
manitou | 0:785739d5a30a | 154 | |
manitou | 0:785739d5a30a | 155 | void space(int time) { |
manitou | 0:785739d5a30a | 156 | pwm.write(0); // off |
manitou | 0:785739d5a30a | 157 | testpin=1; |
manitou | 0:785739d5a30a | 158 | wait_us(time); |
manitou | 0:785739d5a30a | 159 | } |
manitou | 0:785739d5a30a | 160 | |
manitou | 0:785739d5a30a | 161 | void sendSony(unsigned long data, int nbits) { |
manitou | 0:785739d5a30a | 162 | enableIROut(40); |
manitou | 0:785739d5a30a | 163 | mark(SONY_HDR_MARK); |
manitou | 0:785739d5a30a | 164 | space(SONY_HDR_SPACE); |
manitou | 0:785739d5a30a | 165 | data = data << (32 - nbits); |
manitou | 0:785739d5a30a | 166 | for (int i = 0; i < nbits; i++) { |
manitou | 0:785739d5a30a | 167 | if (data & TOPBIT) { |
manitou | 0:785739d5a30a | 168 | mark(SONY_ONE_MARK); |
manitou | 0:785739d5a30a | 169 | space(SONY_HDR_SPACE); |
manitou | 0:785739d5a30a | 170 | } |
manitou | 0:785739d5a30a | 171 | else { |
manitou | 0:785739d5a30a | 172 | mark(SONY_ZERO_MARK); |
manitou | 0:785739d5a30a | 173 | space(SONY_HDR_SPACE); |
manitou | 0:785739d5a30a | 174 | } |
manitou | 0:785739d5a30a | 175 | data <<= 1; |
manitou | 0:785739d5a30a | 176 | } |
manitou | 0:785739d5a30a | 177 | } |
manitou | 0:785739d5a30a | 178 | |
manitou | 0:785739d5a30a | 179 | void sendRaw(unsigned int buf[], int len, int khz) |
manitou | 0:785739d5a30a | 180 | { |
manitou | 0:785739d5a30a | 181 | enableIROut(khz); |
manitou | 0:785739d5a30a | 182 | for (int i = 0; i < len; i++) { |
manitou | 0:785739d5a30a | 183 | if (i & 1) { |
manitou | 0:785739d5a30a | 184 | space(buf[i]); |
manitou | 0:785739d5a30a | 185 | } |
manitou | 0:785739d5a30a | 186 | else { |
manitou | 0:785739d5a30a | 187 | mark(buf[i]); |
manitou | 0:785739d5a30a | 188 | } |
manitou | 0:785739d5a30a | 189 | } |
manitou | 0:785739d5a30a | 190 | space(0); // Just to be sure |
manitou | 0:785739d5a30a | 191 | } |
manitou | 0:785739d5a30a | 192 | |
manitou | 0:785739d5a30a | 193 | main() { |
manitou | 0:785739d5a30a | 194 | long sonycmd[] = {0xA9A,0x91A,0x61A}; // power 0 7 |
manitou | 0:785739d5a30a | 195 | |
manitou | 0:785739d5a30a | 196 | |
manitou | 0:785739d5a30a | 197 | pwm.period(1.); |
manitou | 0:785739d5a30a | 198 | pwm.write(0); // when no PWM, want pin low |
manitou | 0:785739d5a30a | 199 | |
manitou | 0:785739d5a30a | 200 | enableIRIn(); |
manitou | 0:785739d5a30a | 201 | while(true) { |
manitou | 0:785739d5a30a | 202 | printf("xmit\n"); |
manitou | 0:785739d5a30a | 203 | myled=1; |
manitou | 0:785739d5a30a | 204 | sendSony(sonycmd[0],SONY_BITS); |
manitou | 0:785739d5a30a | 205 | myled=0; |
manitou | 0:785739d5a30a | 206 | wait(.006); // let gap time grow |
manitou | 0:785739d5a30a | 207 | |
manitou | 0:785739d5a30a | 208 | if (rcvstate == STATE_STOP) { |
manitou | 0:785739d5a30a | 209 | if (decodeSony() ) { |
manitou | 0:785739d5a30a | 210 | printf("sony decoded. value %0x %d bits\n",results_value, results_bits); |
manitou | 0:785739d5a30a | 211 | } |
manitou | 0:785739d5a30a | 212 | printf("rawlen %d\n",rawlen); |
manitou | 0:785739d5a30a | 213 | |
manitou | 0:785739d5a30a | 214 | for (int i=0; i < rawlen; i++) { |
manitou | 0:785739d5a30a | 215 | if (i%2) printf(" "); |
manitou | 0:785739d5a30a | 216 | printf("%d\n",rawbuf[i]*USECPERTICK); |
manitou | 0:785739d5a30a | 217 | } |
manitou | 0:785739d5a30a | 218 | irrecv_resume(); |
manitou | 0:785739d5a30a | 219 | } |
manitou | 0:785739d5a30a | 220 | |
manitou | 0:785739d5a30a | 221 | wait(2.0); |
manitou | 0:785739d5a30a | 222 | } |
manitou | 0:785739d5a30a | 223 | } |