Shinichiro Nakamura
/
StarBoardOrangeExample2
StarBoard Orange - Example application No.2 (Version 0.0.4)
RemoteIR/ReceiverIR.cpp@1:9370008ac96b, 2010-08-15 (annotated)
- Committer:
- shintamainjp
- Date:
- Sun Aug 15 00:27:30 2010 +0000
- Revision:
- 1:9370008ac96b
- Parent:
- 0:5d79cd4ac81d
- Child:
- 2:d4625043c895
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 | 0:5d79cd4ac81d | 148 | } |
shintamainjp | 0:5d79cd4ac81d | 149 | } else if (AEHA == data.format) { |
shintamainjp | 0:5d79cd4ac81d | 150 | work.d2 = timer.read_us(); |
shintamainjp | 0:5d79cd4ac81d | 151 | int a = work.d2 - work.d1; |
shintamainjp | 0:5d79cd4ac81d | 152 | if (InRange(a, TUS_AEHA * 3)) { |
shintamainjp | 0:5d79cd4ac81d | 153 | data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); |
shintamainjp | 0:5d79cd4ac81d | 154 | } else if (InRange(a, TUS_AEHA * 1)) { |
shintamainjp | 0:5d79cd4ac81d | 155 | data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); |
shintamainjp | 0:5d79cd4ac81d | 156 | } |
shintamainjp | 0:5d79cd4ac81d | 157 | data.bitcount++; |
shintamainjp | 0:5d79cd4ac81d | 158 | /* |
shintamainjp | 0:5d79cd4ac81d | 159 | * Typical length of AEHA is 48 bits. |
shintamainjp | 0:5d79cd4ac81d | 160 | * Please check a specification of your remote controller if you find a problem. |
shintamainjp | 1:9370008ac96b | 161 | */ |
shintamainjp | 0:5d79cd4ac81d | 162 | if (48 <= data.bitcount) { |
shintamainjp | 0:5d79cd4ac81d | 163 | data.state = Received; |
shintamainjp | 1:9370008ac96b | 164 | work.c1 = -1; |
shintamainjp | 1:9370008ac96b | 165 | work.c2 = -1; |
shintamainjp | 1:9370008ac96b | 166 | work.c3 = -1; |
shintamainjp | 1:9370008ac96b | 167 | work.d1 = -1; |
shintamainjp | 1:9370008ac96b | 168 | work.d2 = -1; |
shintamainjp | 0:5d79cd4ac81d | 169 | } |
shintamainjp | 0:5d79cd4ac81d | 170 | } else if (SONY == data.format) { |
shintamainjp | 0:5d79cd4ac81d | 171 | work.d1 = timer.read_us(); |
shintamainjp | 0:5d79cd4ac81d | 172 | } |
shintamainjp | 0:5d79cd4ac81d | 173 | break; |
shintamainjp | 0:5d79cd4ac81d | 174 | case Received: |
shintamainjp | 0:5d79cd4ac81d | 175 | break; |
shintamainjp | 0:5d79cd4ac81d | 176 | default: |
shintamainjp | 0:5d79cd4ac81d | 177 | break; |
shintamainjp | 0:5d79cd4ac81d | 178 | } |
shintamainjp | 0:5d79cd4ac81d | 179 | IRQ_ENABLE(); |
shintamainjp | 0:5d79cd4ac81d | 180 | } |
shintamainjp | 0:5d79cd4ac81d | 181 | |
shintamainjp | 0:5d79cd4ac81d | 182 | void ReceiverIR::isr_rise(void) { |
shintamainjp | 0:5d79cd4ac81d | 183 | IRQ_DISABLE(); |
shintamainjp | 0:5d79cd4ac81d | 184 | switch (data.state) { |
shintamainjp | 0:5d79cd4ac81d | 185 | case Idle: |
shintamainjp | 0:5d79cd4ac81d | 186 | if (0 <= work.c1) { |
shintamainjp | 0:5d79cd4ac81d | 187 | work.c2 = timer.read_us(); |
shintamainjp | 0:5d79cd4ac81d | 188 | int a = work.c2 - work.c1; |
shintamainjp | 0:5d79cd4ac81d | 189 | if (InRange(a, TUS_SONY * 4)) { |
shintamainjp | 0:5d79cd4ac81d | 190 | data.format = SONY; |
shintamainjp | 0:5d79cd4ac81d | 191 | data.state = Receiving; |
shintamainjp | 0:5d79cd4ac81d | 192 | data.bitcount = 0; |
shintamainjp | 0:5d79cd4ac81d | 193 | } else { |
shintamainjp | 0:5d79cd4ac81d | 194 | static const int MINIMUM_LEADER_WIDTH = 150; |
shintamainjp | 0:5d79cd4ac81d | 195 | if (a < MINIMUM_LEADER_WIDTH) { |
shintamainjp | 0:5d79cd4ac81d | 196 | init_state(); |
shintamainjp | 0:5d79cd4ac81d | 197 | } |
shintamainjp | 0:5d79cd4ac81d | 198 | } |
shintamainjp | 0:5d79cd4ac81d | 199 | } else { |
shintamainjp | 0:5d79cd4ac81d | 200 | init_state(); |
shintamainjp | 0:5d79cd4ac81d | 201 | } |
shintamainjp | 0:5d79cd4ac81d | 202 | break; |
shintamainjp | 0:5d79cd4ac81d | 203 | case Receiving: |
shintamainjp | 0:5d79cd4ac81d | 204 | if (NEC == data.format) { |
shintamainjp | 0:5d79cd4ac81d | 205 | work.d1 = timer.read_us(); |
shintamainjp | 0:5d79cd4ac81d | 206 | } else if (AEHA == data.format) { |
shintamainjp | 0:5d79cd4ac81d | 207 | work.d1 = timer.read_us(); |
shintamainjp | 0:5d79cd4ac81d | 208 | } else if (SONY == data.format) { |
shintamainjp | 0:5d79cd4ac81d | 209 | work.d2 = timer.read_us(); |
shintamainjp | 0:5d79cd4ac81d | 210 | int a = work.d2 - work.d1; |
shintamainjp | 0:5d79cd4ac81d | 211 | if (InRange(a, TUS_SONY * 2)) { |
shintamainjp | 0:5d79cd4ac81d | 212 | data.buffer[data.bitcount / 8] |= (1 << (data.bitcount % 8)); |
shintamainjp | 0:5d79cd4ac81d | 213 | } else if (InRange(a, TUS_SONY * 1)) { |
shintamainjp | 0:5d79cd4ac81d | 214 | data.buffer[data.bitcount / 8] &= ~(1 << (data.bitcount % 8)); |
shintamainjp | 0:5d79cd4ac81d | 215 | } |
shintamainjp | 0:5d79cd4ac81d | 216 | data.bitcount++; |
shintamainjp | 0:5d79cd4ac81d | 217 | /* |
shintamainjp | 1:9370008ac96b | 218 | * How do we get the correct length? (12bits, 15bits, 20bits...) |
shintamainjp | 0:5d79cd4ac81d | 219 | * By a model only? |
shintamainjp | 0:5d79cd4ac81d | 220 | * Please check a specification of your remote controller if you find a problem. |
shintamainjp | 0:5d79cd4ac81d | 221 | */ |
shintamainjp | 0:5d79cd4ac81d | 222 | if (12 <= data.bitcount) { |
shintamainjp | 0:5d79cd4ac81d | 223 | data.state = Received; |
shintamainjp | 1:9370008ac96b | 224 | work.c1 = -1; |
shintamainjp | 1:9370008ac96b | 225 | work.c2 = -1; |
shintamainjp | 1:9370008ac96b | 226 | work.c3 = -1; |
shintamainjp | 1:9370008ac96b | 227 | work.d1 = -1; |
shintamainjp | 1:9370008ac96b | 228 | work.d2 = -1; |
shintamainjp | 0:5d79cd4ac81d | 229 | } |
shintamainjp | 0:5d79cd4ac81d | 230 | } |
shintamainjp | 0:5d79cd4ac81d | 231 | break; |
shintamainjp | 0:5d79cd4ac81d | 232 | case Received: |
shintamainjp | 0:5d79cd4ac81d | 233 | break; |
shintamainjp | 0:5d79cd4ac81d | 234 | default: |
shintamainjp | 0:5d79cd4ac81d | 235 | break; |
shintamainjp | 0:5d79cd4ac81d | 236 | } |
shintamainjp | 0:5d79cd4ac81d | 237 | IRQ_ENABLE(); |
shintamainjp | 0:5d79cd4ac81d | 238 | } |