Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
RemoteIR/ReceiverIR.cpp@2:d4625043c895, 2010-08-15 (annotated)
- Committer:
 - shintamainjp
 - Date:
 - Sun Aug 15 10:41:12 2010 +0000
 - Revision:
 - 2:d4625043c895
 - Parent:
 - 1:9370008ac96b
 
Who changed what in which revision?
| User | Revision | Line number | New contents of line | 
|---|---|---|---|
| shintamainjp | 0:5d79cd4ac81d | 1 | /** | 
| shintamainjp | 1:9370008ac96b | 2 | * IR receiver (Version 0.0.2) | 
| shintamainjp | 0:5d79cd4ac81d | 3 | * | 
| shintamainjp | 0:5d79cd4ac81d | 4 | * Copyright (C) 2010 Shinichiro Nakamura (CuBeatSystems) | 
| shintamainjp | 0:5d79cd4ac81d | 5 | * http://shinta.main.jp/ | 
| shintamainjp | 0:5d79cd4ac81d | 6 | */ | 
| shintamainjp | 0:5d79cd4ac81d | 7 | |
| shintamainjp | 0:5d79cd4ac81d | 8 | #include "ReceiverIR.h" | 
| shintamainjp | 0:5d79cd4ac81d | 9 | |
| shintamainjp | 0:5d79cd4ac81d | 10 | #define InRange(x,y) ((((y) * 0.7) < (x)) && ((x) < ((y) * 1.3))) | 
| shintamainjp | 0:5d79cd4ac81d | 11 | #define IRQ_ENABLE() sem.release(); __enable_irq() | 
| shintamainjp | 0:5d79cd4ac81d | 12 | #define IRQ_DISABLE() __disable_irq(); sem.take() | 
| shintamainjp | 0:5d79cd4ac81d | 13 | |
| shintamainjp | 0:5d79cd4ac81d | 14 | ReceiverIR::ReceiverIR(PinName rx) : evt(rx) { | 
| shintamainjp | 0:5d79cd4ac81d | 15 | IRQ_DISABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 16 | evt.fall(this, &ReceiverIR::isr_fall); | 
| shintamainjp | 0:5d79cd4ac81d | 17 | evt.rise(this, &ReceiverIR::isr_rise); | 
| shintamainjp | 0:5d79cd4ac81d | 18 | ticker.attach_us(this, &ReceiverIR::isr_wdt, 1 * 1000); | 
| shintamainjp | 0:5d79cd4ac81d | 19 | init_state(); | 
| shintamainjp | 0:5d79cd4ac81d | 20 | IRQ_ENABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 21 | } | 
| shintamainjp | 0:5d79cd4ac81d | 22 | |
| shintamainjp | 0:5d79cd4ac81d | 23 | ReceiverIR::~ReceiverIR() {} | 
| shintamainjp | 0:5d79cd4ac81d | 24 | |
| shintamainjp | 0:5d79cd4ac81d | 25 | ReceiverIR::State ReceiverIR::getState() { | 
| shintamainjp | 0:5d79cd4ac81d | 26 | IRQ_DISABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 27 | State s = data.state; | 
| shintamainjp | 0:5d79cd4ac81d | 28 | IRQ_ENABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 29 | return s; | 
| shintamainjp | 0:5d79cd4ac81d | 30 | } | 
| shintamainjp | 0:5d79cd4ac81d | 31 | |
| shintamainjp | 0:5d79cd4ac81d | 32 | int ReceiverIR::getData(ReceiverIR::Format *format, uint8_t *buf, int bufsiz) { | 
| shintamainjp | 0:5d79cd4ac81d | 33 | IRQ_DISABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 34 | |
| shintamainjp | 0:5d79cd4ac81d | 35 | const int bc = data.bitcount; | 
| shintamainjp | 0:5d79cd4ac81d | 36 | if (bufsiz < (bc / 8)) { | 
| shintamainjp | 0:5d79cd4ac81d | 37 | IRQ_ENABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 38 | return -1; | 
| shintamainjp | 0:5d79cd4ac81d | 39 | } | 
| shintamainjp | 0:5d79cd4ac81d | 40 | |
| shintamainjp | 0:5d79cd4ac81d | 41 | *format = data.format; | 
| shintamainjp | 0:5d79cd4ac81d | 42 | for (int i = 0; i < (bc / 8); i++) { | 
| shintamainjp | 0:5d79cd4ac81d | 43 | buf[i] = data.buffer[i]; | 
| shintamainjp | 0:5d79cd4ac81d | 44 | } | 
| shintamainjp | 0:5d79cd4ac81d | 45 | |
| shintamainjp | 0:5d79cd4ac81d | 46 | init_state(); | 
| shintamainjp | 0:5d79cd4ac81d | 47 | |
| shintamainjp | 0:5d79cd4ac81d | 48 | IRQ_ENABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 49 | return bc; | 
| shintamainjp | 0:5d79cd4ac81d | 50 | } | 
| shintamainjp | 0:5d79cd4ac81d | 51 | |
| shintamainjp | 0:5d79cd4ac81d | 52 | void ReceiverIR::init_state(void) { | 
| shintamainjp | 0:5d79cd4ac81d | 53 | work.c1 = -1; | 
| shintamainjp | 0:5d79cd4ac81d | 54 | work.c2 = -1; | 
| shintamainjp | 0:5d79cd4ac81d | 55 | work.c3 = -1; | 
| shintamainjp | 0:5d79cd4ac81d | 56 | work.d1 = -1; | 
| shintamainjp | 0:5d79cd4ac81d | 57 | work.d2 = -1; | 
| shintamainjp | 0:5d79cd4ac81d | 58 | data.state = Idle; | 
| shintamainjp | 0:5d79cd4ac81d | 59 | data.format = UNKNOWN; | 
| shintamainjp | 0:5d79cd4ac81d | 60 | data.bitcount = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 61 | timer.stop(); | 
| shintamainjp | 0:5d79cd4ac81d | 62 | timer.reset(); | 
| shintamainjp | 0:5d79cd4ac81d | 63 | for (int i = 0; i < sizeof(data.buffer); i++) { | 
| shintamainjp | 0:5d79cd4ac81d | 64 | data.buffer[i] = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 65 | } | 
| shintamainjp | 0:5d79cd4ac81d | 66 | } | 
| shintamainjp | 0:5d79cd4ac81d | 67 | |
| shintamainjp | 0:5d79cd4ac81d | 68 | void ReceiverIR::isr_wdt(void) { | 
| shintamainjp | 0:5d79cd4ac81d | 69 | IRQ_DISABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 70 | static int cnt = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 71 | if ((Receiving == data.state) || ((0 <= work.c1) || (0 <= work.c2) || (0 <= work.c3))) { | 
| shintamainjp | 0:5d79cd4ac81d | 72 | cnt++; | 
| shintamainjp | 0:5d79cd4ac81d | 73 | if (cnt > 500) { | 
| shintamainjp | 0:5d79cd4ac81d | 74 | printf("# WDT [c1=%d, c2=%d, c3=%d, d1=%d, d2=%d, state=%d, format=%d, bitcount=%d]\n", | 
| shintamainjp | 0:5d79cd4ac81d | 75 | work.c1, | 
| shintamainjp | 0:5d79cd4ac81d | 76 | work.c2, | 
| shintamainjp | 0:5d79cd4ac81d | 77 | work.c3, | 
| shintamainjp | 0:5d79cd4ac81d | 78 | work.d1, | 
| shintamainjp | 0:5d79cd4ac81d | 79 | work.d2, | 
| shintamainjp | 0:5d79cd4ac81d | 80 | data.state, | 
| shintamainjp | 0:5d79cd4ac81d | 81 | data.format, | 
| shintamainjp | 0:5d79cd4ac81d | 82 | data.bitcount); | 
| shintamainjp | 0:5d79cd4ac81d | 83 | init_state(); | 
| shintamainjp | 0:5d79cd4ac81d | 84 | cnt = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 85 | } | 
| shintamainjp | 0:5d79cd4ac81d | 86 | } else { | 
| shintamainjp | 0:5d79cd4ac81d | 87 | cnt = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 88 | } | 
| shintamainjp | 0:5d79cd4ac81d | 89 | IRQ_ENABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 90 | } | 
| shintamainjp | 0:5d79cd4ac81d | 91 | |
| shintamainjp | 0:5d79cd4ac81d | 92 | void ReceiverIR::isr_fall(void) { | 
| shintamainjp | 0:5d79cd4ac81d | 93 | IRQ_DISABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 94 | switch (data.state) { | 
| shintamainjp | 0:5d79cd4ac81d | 95 | case Idle: | 
| shintamainjp | 0:5d79cd4ac81d | 96 | if (work.c1 < 0) { | 
| shintamainjp | 0:5d79cd4ac81d | 97 | timer.start(); | 
| shintamainjp | 0:5d79cd4ac81d | 98 | work.c1 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 99 | } else { | 
| shintamainjp | 0:5d79cd4ac81d | 100 | work.c3 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 101 | int a = work.c2 - work.c1; | 
| shintamainjp | 0:5d79cd4ac81d | 102 | int b = work.c3 - work.c2; | 
| shintamainjp | 0:5d79cd4ac81d | 103 | if (InRange(a, TUS_NEC * 16) && InRange(b, TUS_NEC * 8)) { | 
| shintamainjp | 0:5d79cd4ac81d | 104 | /* | 
| shintamainjp | 0:5d79cd4ac81d | 105 | * NEC. | 
| shintamainjp | 0:5d79cd4ac81d | 106 | */ | 
| shintamainjp | 0:5d79cd4ac81d | 107 | data.format = NEC; | 
| shintamainjp | 0:5d79cd4ac81d | 108 | data.state = Receiving; | 
| shintamainjp | 0:5d79cd4ac81d | 109 | data.bitcount = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 110 | } else if (InRange(a, TUS_NEC * 16) && InRange(b, TUS_NEC * 4)) { | 
| shintamainjp | 0:5d79cd4ac81d | 111 | /* | 
| shintamainjp | 0:5d79cd4ac81d | 112 | * NEC Repeat. | 
| shintamainjp | 0:5d79cd4ac81d | 113 | */ | 
| shintamainjp | 0:5d79cd4ac81d | 114 | data.format = NEC; | 
| shintamainjp | 0:5d79cd4ac81d | 115 | data.state = Received; | 
| shintamainjp | 0:5d79cd4ac81d | 116 | data.bitcount = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 117 | } else if (InRange(a, TUS_AEHA * 8) && InRange(b, TUS_AEHA * 4)) { | 
| shintamainjp | 0:5d79cd4ac81d | 118 | /* | 
| shintamainjp | 0:5d79cd4ac81d | 119 | * AEHA. | 
| shintamainjp | 0:5d79cd4ac81d | 120 | */ | 
| shintamainjp | 0:5d79cd4ac81d | 121 | data.format = AEHA; | 
| shintamainjp | 0:5d79cd4ac81d | 122 | data.state = Receiving; | 
| shintamainjp | 0:5d79cd4ac81d | 123 | data.bitcount = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 124 | } else if (InRange(a, TUS_AEHA * 8) && InRange(b, TUS_AEHA * 8)) { | 
| shintamainjp | 0:5d79cd4ac81d | 125 | /* | 
| shintamainjp | 0:5d79cd4ac81d | 126 | * AEHA Repeat. | 
| shintamainjp | 0:5d79cd4ac81d | 127 | */ | 
| shintamainjp | 0:5d79cd4ac81d | 128 | data.format = AEHA; | 
| shintamainjp | 0:5d79cd4ac81d | 129 | data.state = Received; | 
| shintamainjp | 0:5d79cd4ac81d | 130 | data.bitcount = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 131 | } else { | 
| shintamainjp | 0:5d79cd4ac81d | 132 | init_state(); | 
| shintamainjp | 0:5d79cd4ac81d | 133 | } | 
| shintamainjp | 0:5d79cd4ac81d | 134 | } | 
| shintamainjp | 0:5d79cd4ac81d | 135 | break; | 
| shintamainjp | 0:5d79cd4ac81d | 136 | case Receiving: | 
| shintamainjp | 0:5d79cd4ac81d | 137 | if (NEC == data.format) { | 
| shintamainjp | 0:5d79cd4ac81d | 138 | work.d2 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 139 | int a = work.d2 - work.d1; | 
| shintamainjp | 0:5d79cd4ac81d | 140 | if (InRange(a, TUS_NEC * 3)) { | 
| shintamainjp | 0:5d79cd4ac81d | 141 | data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); | 
| shintamainjp | 0:5d79cd4ac81d | 142 | } else if (InRange(a, TUS_NEC * 1)) { | 
| shintamainjp | 0:5d79cd4ac81d | 143 | data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); | 
| shintamainjp | 0:5d79cd4ac81d | 144 | } | 
| shintamainjp | 0:5d79cd4ac81d | 145 | data.bitcount++; | 
| shintamainjp | 0:5d79cd4ac81d | 146 | if (32 <= data.bitcount) { | 
| shintamainjp | 0:5d79cd4ac81d | 147 | data.state = Received; | 
| shintamainjp | 2:d4625043c895 | 148 | work.c1 = -1; | 
| shintamainjp | 2:d4625043c895 | 149 | work.c2 = -1; | 
| shintamainjp | 2:d4625043c895 | 150 | work.c3 = -1; | 
| shintamainjp | 2:d4625043c895 | 151 | work.d1 = -1; | 
| shintamainjp | 2:d4625043c895 | 152 | work.d2 = -1; | 
| shintamainjp | 0:5d79cd4ac81d | 153 | } | 
| shintamainjp | 0:5d79cd4ac81d | 154 | } else if (AEHA == data.format) { | 
| shintamainjp | 0:5d79cd4ac81d | 155 | work.d2 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 156 | int a = work.d2 - work.d1; | 
| shintamainjp | 0:5d79cd4ac81d | 157 | if (InRange(a, TUS_AEHA * 3)) { | 
| shintamainjp | 0:5d79cd4ac81d | 158 | data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); | 
| shintamainjp | 0:5d79cd4ac81d | 159 | } else if (InRange(a, TUS_AEHA * 1)) { | 
| shintamainjp | 0:5d79cd4ac81d | 160 | data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); | 
| shintamainjp | 0:5d79cd4ac81d | 161 | } | 
| shintamainjp | 0:5d79cd4ac81d | 162 | data.bitcount++; | 
| shintamainjp | 0:5d79cd4ac81d | 163 | /* | 
| shintamainjp | 0:5d79cd4ac81d | 164 | * Typical length of AEHA is 48 bits. | 
| shintamainjp | 0:5d79cd4ac81d | 165 | * Please check a specification of your remote controller if you find a problem. | 
| shintamainjp | 1:9370008ac96b | 166 | */ | 
| shintamainjp | 0:5d79cd4ac81d | 167 | if (48 <= data.bitcount) { | 
| shintamainjp | 0:5d79cd4ac81d | 168 | data.state = Received; | 
| shintamainjp | 1:9370008ac96b | 169 | work.c1 = -1; | 
| shintamainjp | 1:9370008ac96b | 170 | work.c2 = -1; | 
| shintamainjp | 1:9370008ac96b | 171 | work.c3 = -1; | 
| shintamainjp | 1:9370008ac96b | 172 | work.d1 = -1; | 
| shintamainjp | 1:9370008ac96b | 173 | work.d2 = -1; | 
| shintamainjp | 0:5d79cd4ac81d | 174 | } | 
| shintamainjp | 0:5d79cd4ac81d | 175 | } else if (SONY == data.format) { | 
| shintamainjp | 0:5d79cd4ac81d | 176 | work.d1 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 177 | } | 
| shintamainjp | 0:5d79cd4ac81d | 178 | break; | 
| shintamainjp | 0:5d79cd4ac81d | 179 | case Received: | 
| shintamainjp | 0:5d79cd4ac81d | 180 | break; | 
| shintamainjp | 0:5d79cd4ac81d | 181 | default: | 
| shintamainjp | 0:5d79cd4ac81d | 182 | break; | 
| shintamainjp | 0:5d79cd4ac81d | 183 | } | 
| shintamainjp | 0:5d79cd4ac81d | 184 | IRQ_ENABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 185 | } | 
| shintamainjp | 0:5d79cd4ac81d | 186 | |
| shintamainjp | 0:5d79cd4ac81d | 187 | void ReceiverIR::isr_rise(void) { | 
| shintamainjp | 0:5d79cd4ac81d | 188 | IRQ_DISABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 189 | switch (data.state) { | 
| shintamainjp | 0:5d79cd4ac81d | 190 | case Idle: | 
| shintamainjp | 0:5d79cd4ac81d | 191 | if (0 <= work.c1) { | 
| shintamainjp | 0:5d79cd4ac81d | 192 | work.c2 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 193 | int a = work.c2 - work.c1; | 
| shintamainjp | 0:5d79cd4ac81d | 194 | if (InRange(a, TUS_SONY * 4)) { | 
| shintamainjp | 0:5d79cd4ac81d | 195 | data.format = SONY; | 
| shintamainjp | 0:5d79cd4ac81d | 196 | data.state = Receiving; | 
| shintamainjp | 0:5d79cd4ac81d | 197 | data.bitcount = 0; | 
| shintamainjp | 0:5d79cd4ac81d | 198 | } else { | 
| shintamainjp | 0:5d79cd4ac81d | 199 | static const int MINIMUM_LEADER_WIDTH = 150; | 
| shintamainjp | 0:5d79cd4ac81d | 200 | if (a < MINIMUM_LEADER_WIDTH) { | 
| shintamainjp | 0:5d79cd4ac81d | 201 | init_state(); | 
| shintamainjp | 0:5d79cd4ac81d | 202 | } | 
| shintamainjp | 0:5d79cd4ac81d | 203 | } | 
| shintamainjp | 0:5d79cd4ac81d | 204 | } else { | 
| shintamainjp | 0:5d79cd4ac81d | 205 | init_state(); | 
| shintamainjp | 0:5d79cd4ac81d | 206 | } | 
| shintamainjp | 0:5d79cd4ac81d | 207 | break; | 
| shintamainjp | 0:5d79cd4ac81d | 208 | case Receiving: | 
| shintamainjp | 0:5d79cd4ac81d | 209 | if (NEC == data.format) { | 
| shintamainjp | 0:5d79cd4ac81d | 210 | work.d1 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 211 | } else if (AEHA == data.format) { | 
| shintamainjp | 0:5d79cd4ac81d | 212 | work.d1 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 213 | } else if (SONY == data.format) { | 
| shintamainjp | 0:5d79cd4ac81d | 214 | work.d2 = timer.read_us(); | 
| shintamainjp | 0:5d79cd4ac81d | 215 | int a = work.d2 - work.d1; | 
| shintamainjp | 0:5d79cd4ac81d | 216 | if (InRange(a, TUS_SONY * 2)) { | 
| shintamainjp | 0:5d79cd4ac81d | 217 | data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); | 
| shintamainjp | 0:5d79cd4ac81d | 218 | } else if (InRange(a, TUS_SONY * 1)) { | 
| shintamainjp | 0:5d79cd4ac81d | 219 | data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); | 
| shintamainjp | 0:5d79cd4ac81d | 220 | } | 
| shintamainjp | 0:5d79cd4ac81d | 221 | data.bitcount++; | 
| shintamainjp | 0:5d79cd4ac81d | 222 | /* | 
| shintamainjp | 1:9370008ac96b | 223 | * How do we get the correct length? (12bits, 15bits, 20bits...) | 
| shintamainjp | 0:5d79cd4ac81d | 224 | * By a model only? | 
| shintamainjp | 0:5d79cd4ac81d | 225 | * Please check a specification of your remote controller if you find a problem. | 
| shintamainjp | 0:5d79cd4ac81d | 226 | */ | 
| shintamainjp | 0:5d79cd4ac81d | 227 | if (12 <= data.bitcount) { | 
| shintamainjp | 0:5d79cd4ac81d | 228 | data.state = Received; | 
| shintamainjp | 1:9370008ac96b | 229 | work.c1 = -1; | 
| shintamainjp | 1:9370008ac96b | 230 | work.c2 = -1; | 
| shintamainjp | 1:9370008ac96b | 231 | work.c3 = -1; | 
| shintamainjp | 1:9370008ac96b | 232 | work.d1 = -1; | 
| shintamainjp | 1:9370008ac96b | 233 | work.d2 = -1; | 
| shintamainjp | 0:5d79cd4ac81d | 234 | } | 
| shintamainjp | 0:5d79cd4ac81d | 235 | } | 
| shintamainjp | 0:5d79cd4ac81d | 236 | break; | 
| shintamainjp | 0:5d79cd4ac81d | 237 | case Received: | 
| shintamainjp | 0:5d79cd4ac81d | 238 | break; | 
| shintamainjp | 0:5d79cd4ac81d | 239 | default: | 
| shintamainjp | 0:5d79cd4ac81d | 240 | break; | 
| shintamainjp | 0:5d79cd4ac81d | 241 | } | 
| shintamainjp | 0:5d79cd4ac81d | 242 | IRQ_ENABLE(); | 
| shintamainjp | 0:5d79cd4ac81d | 243 | } |