IR remote test, based on Arduino IRRemote lib.

Dependencies:   mbed

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.

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