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.
Diff: main.cpp
- Revision:
- 0:785739d5a30a
- Child:
- 1:af81e02b8c7b
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Apr 13 11:14:58 2016 +0000 @@ -0,0 +1,224 @@ +/* + 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 D8 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); + } +} \ No newline at end of file