| 212 | // DO NOT call update() directly from sketches. |
| 213 | #if defined(IRAM_ATTR) |
| 214 | static IRAM_ATTR void update(Encoder_internal_state_t *arg) { |
| 215 | #else |
| 216 | static void update(Encoder_internal_state_t *arg) { |
| 217 | #endif |
| 218 | #if defined(__AVR__) |
| 219 | // The compiler believes this is just 1 line of code, so |
| 220 | // it will inline this function into each interrupt |
| 221 | // handler. That's a tiny bit faster, but grows the code. |
| 222 | // Especially when used with ENCODER_OPTIMIZE_INTERRUPTS, |
| 223 | // the inline nature allows the ISR prologue and epilogue |
| 224 | // to only save/restore necessary registers, for very nice |
| 225 | // speed increase. |
| 226 | asm volatile ( |
| 227 | "ld r30, X+" "\n\t" |
| 228 | "ld r31, X+" "\n\t" |
| 229 | "ld r24, Z" "\n\t" // r24 = pin1 input |
| 230 | "ld r30, X+" "\n\t" |
| 231 | "ld r31, X+" "\n\t" |
| 232 | "ld r25, Z" "\n\t" // r25 = pin2 input |
| 233 | "ld r30, X+" "\n\t" // r30 = pin1 mask |
| 234 | "ld r31, X+" "\n\t" // r31 = pin2 mask |
| 235 | "ld r22, X" "\n\t" // r22 = state |
| 236 | "andi r22, 3" "\n\t" |
| 237 | "and r24, r30" "\n\t" |
| 238 | "breq L%=1" "\n\t" // if (pin1) |
| 239 | "ori r22, 4" "\n\t" // state |= 4 |
| 240 | "L%=1:" "and r25, r31" "\n\t" |
| 241 | "breq L%=2" "\n\t" // if (pin2) |
| 242 | "ori r22, 8" "\n\t" // state |= 8 |
| 243 | "L%=2:" "ldi r30, lo8(pm(L%=table))" "\n\t" |
| 244 | "ldi r31, hi8(pm(L%=table))" "\n\t" |
| 245 | "add r30, r22" "\n\t" |
| 246 | "adc r31, __zero_reg__" "\n\t" |
| 247 | "asr r22" "\n\t" |
| 248 | "asr r22" "\n\t" |
| 249 | "st X+, r22" "\n\t" // store new state |
| 250 | "ld r22, X+" "\n\t" |
| 251 | "ld r23, X+" "\n\t" |
| 252 | "ld r24, X+" "\n\t" |
| 253 | "ld r25, X+" "\n\t" |
| 254 | "ijmp" "\n\t" // jumps to update_finishup() |
| 255 | // TODO move this table to another static function, |
| 256 | // so it doesn't get needlessly duplicated. Easier |
| 257 | // said than done, due to linker issues and inlining |
| 258 | "L%=table:" "\n\t" |
| 259 | "rjmp L%=end" "\n\t" // 0 |
| 260 | "rjmp L%=plus1" "\n\t" // 1 |
| 261 | "rjmp L%=minus1" "\n\t" // 2 |
| 262 | "rjmp L%=plus2" "\n\t" // 3 |
| 263 | "rjmp L%=minus1" "\n\t" // 4 |
| 264 | "rjmp L%=end" "\n\t" // 5 |
| 265 | "rjmp L%=minus2" "\n\t" // 6 |
| 266 | "rjmp L%=plus1" "\n\t" // 7 |
| 267 | "rjmp L%=plus1" "\n\t" // 8 |
| 268 | "rjmp L%=minus2" "\n\t" // 9 |
| 269 | "rjmp L%=end" "\n\t" // 10 |
| 270 | "rjmp L%=minus1" "\n\t" // 11 |
| 271 | "rjmp L%=plus2" "\n\t" // 12 |
no outgoing calls
no test coverage detected