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
- Committer:
- manitou
- Date:
- 2016-04-13
- Revision:
- 1:af81e02b8c7b
- Parent:
- 0:785739d5a30a
File content as of revision 1:af81e02b8c7b:
/* IRtest hack of maple version http://www.arcfn.com/2009/08/multi-protocol-infrared-remote-library.html use PWM to generate mark/space at 38Khz IR LED xmit pin to 100ohm to +IR - to grnd (short/flat) use timer 50us to count mark/space on input is it possible to run both xmit and recv? */ #include "mbed.h" #include "IRremote.h" Ticker ticker; // K64F pins #define RecvPin D7 #define PWMPin D6 #define TestPin D13 PwmOut pwm(PWMPin); DigitalIn recvpin(RecvPin); DigitalOut testpin(TestPin); // jumper to RecvPin for test DigitalOut myled(LED1); volatile unsigned long myticks; int rawbuf[RAWBUF], rawlen; uint8_t rcvstate; int results_decode_type; // NEC, SONY, RC5, UNKNOWN unsigned long results_value; int results_bits; // Number of bits in decoded value void timer_ISR() { // interrupt every 50us uint8_t irdata = recvpin; // read IR sensor myticks++; if (rawlen >= RAWBUF) { // Buffer overflow rcvstate = STATE_STOP; } switch(rcvstate) { case STATE_IDLE: // In the middle of a gap if (irdata == MARK) { if (myticks < GAP_TICKS) { // Not big enough to be a gap. myticks = 0; } else { // gap just ended, record duration and start recording transmission rawlen = 0; rawbuf[rawlen++] = myticks; myticks = 0; rcvstate = STATE_MARK; } } break; case STATE_MARK: // timing MARK if (irdata == SPACE) { // MARK ended, record time rawbuf[rawlen++] = myticks; myticks = 0; rcvstate = STATE_SPACE; } break; case STATE_SPACE: // timing SPACE if (irdata == MARK) { // SPACE just ended, record it rawbuf[rawlen++] = myticks; myticks = 0; rcvstate = STATE_MARK; } else { // SPACE if (myticks > GAP_TICKS) { // big SPACE, indicates gap between codes // Mark current code as ready for processing // Switch to STOP // Don't reset timer; keep counting space width rcvstate = STATE_STOP; } } break; case STATE_STOP: // waiting, measuring gap if (irdata == MARK) { // reset gap timer myticks = 0; } break; } } // set up recv timer void enableIRIn(){ ticker.attach_us(&timer_ISR,50); rcvstate = STATE_IDLE; rawlen = 0; } void irrecv_resume() { rcvstate = STATE_IDLE; rawlen = 0; } long decodeSony() { long data = 0; if (rawlen < 2 * SONY_BITS + 2) { return ERR; } int offset = 1; // Skip first space // Initial mark if (!MATCH_MARK(rawbuf[offset], SONY_HDR_MARK)) { return ERR; } offset++; while (offset + 1 < rawlen) { if (!MATCH_SPACE(rawbuf[offset], SONY_HDR_SPACE)) { break; } offset++; if (MATCH_MARK(rawbuf[offset], SONY_ONE_MARK)) { data = (data << 1) | 1; } else if (MATCH_MARK(rawbuf[offset], SONY_ZERO_MARK)) { data <<= 1; } else { return ERR; } offset++; } // Success results_bits = (offset - 1) / 2; if (results_bits < 12) { results_bits = 0; return ERR; } results_value = data; results_decode_type = SONY; return DECODED; } void enableIROut(int khz) { int freq = 1000 * khz; pwm.period(1./freq); pwm.write(0); // start PWM with low } void mark(int time) { pwm.write(0.5); // PWM on testpin=0; // test invert wait_us(time); } void space(int time) { pwm.write(0); // off testpin=1; wait_us(time); } void sendSony(unsigned long data, int nbits) { enableIROut(40); mark(SONY_HDR_MARK); space(SONY_HDR_SPACE); data = data << (32 - nbits); for (int i = 0; i < nbits; i++) { if (data & TOPBIT) { mark(SONY_ONE_MARK); space(SONY_HDR_SPACE); } else { mark(SONY_ZERO_MARK); space(SONY_HDR_SPACE); } data <<= 1; } } void sendRaw(unsigned int buf[], int len, int khz) { enableIROut(khz); for (int i = 0; i < len; i++) { if (i & 1) { space(buf[i]); } else { mark(buf[i]); } } space(0); // Just to be sure } main() { long sonycmd[] = {0xA9A,0x91A,0x61A}; // power 0 7 pwm.period(1.); pwm.write(0); // when no PWM, want pin low enableIRIn(); while(true) { printf("xmit\n"); myled=1; sendSony(sonycmd[0],SONY_BITS); myled=0; wait(.006); // let gap time grow if (rcvstate == STATE_STOP) { if (decodeSony() ) { printf("sony decoded. value %0x %d bits\n",results_value, results_bits); } printf("rawlen %d\n",rawlen); for (int i=0; i < rawlen; i++) { if (i%2) printf(" "); printf("%d\n",rawbuf[i]*USECPERTICK); } irrecv_resume(); } wait(2.0); } }