RoboAide
Project to improve a DIY robotic arm used for mobility assistance
Encoder.h
Go to the documentation of this file.
1 /* Encoder Library, for measuring quadrature encoded signals
2  * http://www.pjrc.com/teensy/td_libs_Encoder.html
3  * Copyright (c) 2011,2013 PJRC.COM, LLC - Paul Stoffregen <paul@pjrc.com>
4  *
5  * Version 1.2 - fix -2 bug in C-only code
6  * Version 1.1 - expand to support boards with up to 60 interrupts
7  * Version 1.0 - initial release
8  *
9  * Permission is hereby granted, free of charge, to any person obtaining a copy
10  * of this software and associated documentation files (the "Software"), to deal
11  * in the Software without restriction, including without limitation the rights
12  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13  * copies of the Software, and to permit persons to whom the Software is
14  * furnished to do so, subject to the following conditions:
15  *
16  * The above copyright notice and this permission notice shall be included in
17  * all copies or substantial portions of the Software.
18  *
19  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25  * THE SOFTWARE.
26  */
27 
28 
29 #ifndef Encoder_h_
30 #define Encoder_h_
31 
32 #if defined(ARDUINO) && ARDUINO >= 100
33 #include "Arduino.h"
34 #elif defined(WIRING)
35 #include "Wiring.h"
36 #else
37 #include "WProgram.h"
38 #include "pins_arduino.h"
39 #endif
40 
42 
43 #if defined(ENCODER_USE_INTERRUPTS) || !defined(ENCODER_DO_NOT_USE_INTERRUPTS)
44 #define ENCODER_USE_INTERRUPTS
45 #define ENCODER_ARGLIST_SIZE CORE_NUM_INTERRUPT
46 #include "utility/interrupt_pins.h"
47 #ifdef ENCODER_OPTIMIZE_INTERRUPTS
49 #endif
50 #else
51 #define ENCODER_ARGLIST_SIZE 0
52 #endif
53 
54 
55 
56 // All the data needed by interrupts is consolidated into this ugly struct
57 // to facilitate assembly language optimizing of the speed critical update.
58 // The assembly code uses auto-incrementing addressing modes, so the struct
59 // must remain in exactly this order.
60 typedef struct {
61  volatile IO_REG_TYPE * pin1_register;
62  volatile IO_REG_TYPE * pin2_register;
63  IO_REG_TYPE pin1_bitmask;
64  IO_REG_TYPE pin2_bitmask;
65  uint8_t state;
66  int32_t position;
68 
69 class Encoder
70 {
71 public:
72  Encoder(uint8_t pin1, uint8_t pin2) {
73  #ifdef INPUT_PULLUP
74  pinMode(pin1, INPUT_PULLUP);
75  pinMode(pin2, INPUT_PULLUP);
76  #else
77  pinMode(pin1, INPUT);
78  digitalWrite(pin1, HIGH);
79  pinMode(pin2, INPUT);
80  digitalWrite(pin2, HIGH);
81  #endif
82  encoder.pin1_register = PIN_TO_BASEREG(pin1);
83  encoder.pin1_bitmask = PIN_TO_BITMASK(pin1);
84  encoder.pin2_register = PIN_TO_BASEREG(pin2);
85  encoder.pin2_bitmask = PIN_TO_BITMASK(pin2);
86  encoder.position = 0;
87  // allow time for a passive R-C filter to charge
88  // through the pullup resistors, before reading
89  // the initial state
90  delayMicroseconds(2000);
91  uint8_t s = 0;
92  if (DIRECT_PIN_READ(encoder.pin1_register, encoder.pin1_bitmask)) s |= 1;
93  if (DIRECT_PIN_READ(encoder.pin2_register, encoder.pin2_bitmask)) s |= 2;
94  encoder.state = s;
95 #ifdef ENCODER_USE_INTERRUPTS
98 #endif
99  //update_finishup(); // to force linker to include the code (does not work)
100  }
101 
102 
103 #ifdef ENCODER_USE_INTERRUPTS
104  inline int32_t read() {
105  if (interrupts_in_use < 2) {
106  noInterrupts();
107  update(&encoder);
108  } else {
109  noInterrupts();
110  }
111  int32_t ret = encoder.position;
112  interrupts();
113  return ret;
114  }
115  inline int32_t readAndReset() {
116  if (interrupts_in_use < 2) {
117  noInterrupts();
118  update(&encoder);
119  } else {
120  noInterrupts();
121  }
122  int32_t ret = encoder.position;
123  encoder.position = 0;
124  interrupts();
125  return ret;
126  }
127  inline void write(int32_t p) {
128  noInterrupts();
129  encoder.position = p;
130  interrupts();
131  }
132 #else
133  inline int32_t read() {
134  update(&encoder);
135  return encoder.position;
136  }
137  inline int32_t readAndReset() {
138  update(&encoder);
139  int32_t ret = encoder.position;
140  encoder.position = 0;
141  return ret;
142  }
143  inline void write(int32_t p) {
144  encoder.position = p;
145  }
146 #endif
147 private:
149 #ifdef ENCODER_USE_INTERRUPTS
151 #endif
152 public:
154 
155 // _______ _______
156 // Pin1 ______| |_______| |______ Pin1
157 // negative <--- _______ _______ __ --> positive
158 // Pin2 __| |_______| |_______| Pin2
159 
160  // new new old old
161  // pin2 pin1 pin2 pin1 Result
162  // ---- ---- ---- ---- ------
163  // 0 0 0 0 no movement
164  // 0 0 0 1 +1
165  // 0 0 1 0 -1
166  // 0 0 1 1 +2 (assume pin1 edges only)
167  // 0 1 0 0 -1
168  // 0 1 0 1 no movement
169  // 0 1 1 0 -2 (assume pin1 edges only)
170  // 0 1 1 1 +1
171  // 1 0 0 0 +1
172  // 1 0 0 1 -2 (assume pin1 edges only)
173  // 1 0 1 0 no movement
174  // 1 0 1 1 -1
175  // 1 1 0 0 +2 (assume pin1 edges only)
176  // 1 1 0 1 -1
177  // 1 1 1 0 +1
178  // 1 1 1 1 no movement
179 /*
180  // Simple, easy-to-read "documentation" version :-)
181  //
182  void update(void) {
183  uint8_t s = state & 3;
184  if (digitalRead(pin1)) s |= 4;
185  if (digitalRead(pin2)) s |= 8;
186  switch (s) {
187  case 0: case 5: case 10: case 15:
188  break;
189  case 1: case 7: case 8: case 14:
190  position++; break;
191  case 2: case 4: case 11: case 13:
192  position--; break;
193  case 3: case 12:
194  position += 2; break;
195  default:
196  position -= 2; break;
197  }
198  state = (s >> 2);
199  }
200 */
201 
202 public:
203  // update() is not meant to be called from outside Encoder,
204  // but it is public to allow static interrupt routines.
205  // DO NOT call update() directly from sketches.
206  static void update(Encoder_internal_state_t *arg) {
207 #if defined(__AVR__)
208  // The compiler believes this is just 1 line of code, so
209  // it will inline this function into each interrupt
210  // handler. That's a tiny bit faster, but grows the code.
211  // Especially when used with ENCODER_OPTIMIZE_INTERRUPTS,
212  // the inline nature allows the ISR prologue and epilogue
213  // to only save/restore necessary registers, for very nice
214  // speed increase.
215  asm volatile (
216  "ld r30, X+" "\n\t"
217  "ld r31, X+" "\n\t"
218  "ld r24, Z" "\n\t" // r24 = pin1 input
219  "ld r30, X+" "\n\t"
220  "ld r31, X+" "\n\t"
221  "ld r25, Z" "\n\t" // r25 = pin2 input
222  "ld r30, X+" "\n\t" // r30 = pin1 mask
223  "ld r31, X+" "\n\t" // r31 = pin2 mask
224  "ld r22, X" "\n\t" // r22 = state
225  "andi r22, 3" "\n\t"
226  "and r24, r30" "\n\t"
227  "breq L%=1" "\n\t" // if (pin1)
228  "ori r22, 4" "\n\t" // state |= 4
229  "L%=1:" "and r25, r31" "\n\t"
230  "breq L%=2" "\n\t" // if (pin2)
231  "ori r22, 8" "\n\t" // state |= 8
232  "L%=2:" "ldi r30, lo8(pm(L%=table))" "\n\t"
233  "ldi r31, hi8(pm(L%=table))" "\n\t"
234  "add r30, r22" "\n\t"
235  "adc r31, __zero_reg__" "\n\t"
236  "asr r22" "\n\t"
237  "asr r22" "\n\t"
238  "st X+, r22" "\n\t" // store new state
239  "ld r22, X+" "\n\t"
240  "ld r23, X+" "\n\t"
241  "ld r24, X+" "\n\t"
242  "ld r25, X+" "\n\t"
243  "ijmp" "\n\t" // jumps to update_finishup()
244  // TODO move this table to another static function,
245  // so it doesn't get needlessly duplicated. Easier
246  // said than done, due to linker issues and inlining
247  "L%=table:" "\n\t"
248  "rjmp L%=end" "\n\t" // 0
249  "rjmp L%=plus1" "\n\t" // 1
250  "rjmp L%=minus1" "\n\t" // 2
251  "rjmp L%=plus2" "\n\t" // 3
252  "rjmp L%=minus1" "\n\t" // 4
253  "rjmp L%=end" "\n\t" // 5
254  "rjmp L%=minus2" "\n\t" // 6
255  "rjmp L%=plus1" "\n\t" // 7
256  "rjmp L%=plus1" "\n\t" // 8
257  "rjmp L%=minus2" "\n\t" // 9
258  "rjmp L%=end" "\n\t" // 10
259  "rjmp L%=minus1" "\n\t" // 11
260  "rjmp L%=plus2" "\n\t" // 12
261  "rjmp L%=minus1" "\n\t" // 13
262  "rjmp L%=plus1" "\n\t" // 14
263  "rjmp L%=end" "\n\t" // 15
264  "L%=minus2:" "\n\t"
265  "subi r22, 2" "\n\t"
266  "sbci r23, 0" "\n\t"
267  "sbci r24, 0" "\n\t"
268  "sbci r25, 0" "\n\t"
269  "rjmp L%=store" "\n\t"
270  "L%=minus1:" "\n\t"
271  "subi r22, 1" "\n\t"
272  "sbci r23, 0" "\n\t"
273  "sbci r24, 0" "\n\t"
274  "sbci r25, 0" "\n\t"
275  "rjmp L%=store" "\n\t"
276  "L%=plus2:" "\n\t"
277  "subi r22, 254" "\n\t"
278  "rjmp L%=z" "\n\t"
279  "L%=plus1:" "\n\t"
280  "subi r22, 255" "\n\t"
281  "L%=z:" "sbci r23, 255" "\n\t"
282  "sbci r24, 255" "\n\t"
283  "sbci r25, 255" "\n\t"
284  "L%=store:" "\n\t"
285  "st -X, r25" "\n\t"
286  "st -X, r24" "\n\t"
287  "st -X, r23" "\n\t"
288  "st -X, r22" "\n\t"
289  "L%=end:" "\n"
290  : : "x" (arg) : "r22", "r23", "r24", "r25", "r30", "r31");
291 #else
292  uint8_t p1val = DIRECT_PIN_READ(arg->pin1_register, arg->pin1_bitmask);
293  uint8_t p2val = DIRECT_PIN_READ(arg->pin2_register, arg->pin2_bitmask);
294  uint8_t state = arg->state & 3;
295  if (p1val) state |= 4;
296  if (p2val) state |= 8;
297  arg->state = (state >> 2);
298  switch (state) {
299  case 1: case 7: case 8: case 14:
300  arg->position++;
301  return;
302  case 2: case 4: case 11: case 13:
303  arg->position--;
304  return;
305  case 3: case 12:
306  arg->position += 2;
307  return;
308  case 6: case 9:
309  arg->position -= 2;
310  return;
311  }
312 #endif
313  }
314 private:
315 /*
316 #if defined(__AVR__)
317  // TODO: this must be a no inline function
318  // even noinline does not seem to solve difficult
319  // problems with this. Oh well, it was only meant
320  // to shrink code size - there's no performance
321  // improvement in this, only code size reduction.
322  __attribute__((noinline)) void update_finishup(void) {
323  asm volatile (
324  "ldi r30, lo8(pm(Ltable))" "\n\t"
325  "ldi r31, hi8(pm(Ltable))" "\n\t"
326  "Ltable:" "\n\t"
327  "rjmp L%=end" "\n\t" // 0
328  "rjmp L%=plus1" "\n\t" // 1
329  "rjmp L%=minus1" "\n\t" // 2
330  "rjmp L%=plus2" "\n\t" // 3
331  "rjmp L%=minus1" "\n\t" // 4
332  "rjmp L%=end" "\n\t" // 5
333  "rjmp L%=minus2" "\n\t" // 6
334  "rjmp L%=plus1" "\n\t" // 7
335  "rjmp L%=plus1" "\n\t" // 8
336  "rjmp L%=minus2" "\n\t" // 9
337  "rjmp L%=end" "\n\t" // 10
338  "rjmp L%=minus1" "\n\t" // 11
339  "rjmp L%=plus2" "\n\t" // 12
340  "rjmp L%=minus1" "\n\t" // 13
341  "rjmp L%=plus1" "\n\t" // 14
342  "rjmp L%=end" "\n\t" // 15
343  "L%=minus2:" "\n\t"
344  "subi r22, 2" "\n\t"
345  "sbci r23, 0" "\n\t"
346  "sbci r24, 0" "\n\t"
347  "sbci r25, 0" "\n\t"
348  "rjmp L%=store" "\n\t"
349  "L%=minus1:" "\n\t"
350  "subi r22, 1" "\n\t"
351  "sbci r23, 0" "\n\t"
352  "sbci r24, 0" "\n\t"
353  "sbci r25, 0" "\n\t"
354  "rjmp L%=store" "\n\t"
355  "L%=plus2:" "\n\t"
356  "subi r22, 254" "\n\t"
357  "rjmp L%=z" "\n\t"
358  "L%=plus1:" "\n\t"
359  "subi r22, 255" "\n\t"
360  "L%=z:" "sbci r23, 255" "\n\t"
361  "sbci r24, 255" "\n\t"
362  "sbci r25, 255" "\n\t"
363  "L%=store:" "\n\t"
364  "st -X, r25" "\n\t"
365  "st -X, r24" "\n\t"
366  "st -X, r23" "\n\t"
367  "st -X, r22" "\n\t"
368  "L%=end:" "\n"
369  : : : "r22", "r23", "r24", "r25", "r30", "r31");
370  }
371 #endif
372 */
373 
374 
375 #ifdef ENCODER_USE_INTERRUPTS
376  // this giant function is an unfortunate consequence of Arduino's
377  // attachInterrupt function not supporting any way to pass a pointer
378  // or other context to the attached function.
379  static uint8_t attach_interrupt(uint8_t pin, Encoder_internal_state_t *state) {
380  switch (pin) {
381  #ifdef CORE_INT0_PIN
382  case CORE_INT0_PIN:
383  interruptArgs[0] = state;
384  attachInterrupt(0, isr0, CHANGE);
385  break;
386  #endif
387  #ifdef CORE_INT1_PIN
388  case CORE_INT1_PIN:
389  interruptArgs[1] = state;
390  attachInterrupt(1, isr1, CHANGE);
391  break;
392  #endif
393  #ifdef CORE_INT2_PIN
394  case CORE_INT2_PIN:
395  interruptArgs[2] = state;
396  attachInterrupt(2, isr2, CHANGE);
397  break;
398  #endif
399  #ifdef CORE_INT3_PIN
400  case CORE_INT3_PIN:
401  interruptArgs[3] = state;
402  attachInterrupt(3, isr3, CHANGE);
403  break;
404  #endif
405  #ifdef CORE_INT4_PIN
406  case CORE_INT4_PIN:
407  interruptArgs[4] = state;
408  attachInterrupt(4, isr4, CHANGE);
409  break;
410  #endif
411  #ifdef CORE_INT5_PIN
412  case CORE_INT5_PIN:
413  interruptArgs[5] = state;
414  attachInterrupt(5, isr5, CHANGE);
415  break;
416  #endif
417  #ifdef CORE_INT6_PIN
418  case CORE_INT6_PIN:
419  interruptArgs[6] = state;
420  attachInterrupt(6, isr6, CHANGE);
421  break;
422  #endif
423  #ifdef CORE_INT7_PIN
424  case CORE_INT7_PIN:
425  interruptArgs[7] = state;
426  attachInterrupt(7, isr7, CHANGE);
427  break;
428  #endif
429  #ifdef CORE_INT8_PIN
430  case CORE_INT8_PIN:
431  interruptArgs[8] = state;
432  attachInterrupt(8, isr8, CHANGE);
433  break;
434  #endif
435  #ifdef CORE_INT9_PIN
436  case CORE_INT9_PIN:
437  interruptArgs[9] = state;
438  attachInterrupt(9, isr9, CHANGE);
439  break;
440  #endif
441  #ifdef CORE_INT10_PIN
442  case CORE_INT10_PIN:
443  interruptArgs[10] = state;
444  attachInterrupt(10, isr10, CHANGE);
445  break;
446  #endif
447  #ifdef CORE_INT11_PIN
448  case CORE_INT11_PIN:
449  interruptArgs[11] = state;
450  attachInterrupt(11, isr11, CHANGE);
451  break;
452  #endif
453  #ifdef CORE_INT12_PIN
454  case CORE_INT12_PIN:
455  interruptArgs[12] = state;
456  attachInterrupt(12, isr12, CHANGE);
457  break;
458  #endif
459  #ifdef CORE_INT13_PIN
460  case CORE_INT13_PIN:
461  interruptArgs[13] = state;
462  attachInterrupt(13, isr13, CHANGE);
463  break;
464  #endif
465  #ifdef CORE_INT14_PIN
466  case CORE_INT14_PIN:
467  interruptArgs[14] = state;
468  attachInterrupt(14, isr14, CHANGE);
469  break;
470  #endif
471  #ifdef CORE_INT15_PIN
472  case CORE_INT15_PIN:
473  interruptArgs[15] = state;
474  attachInterrupt(15, isr15, CHANGE);
475  break;
476  #endif
477  #ifdef CORE_INT16_PIN
478  case CORE_INT16_PIN:
479  interruptArgs[16] = state;
480  attachInterrupt(16, isr16, CHANGE);
481  break;
482  #endif
483  #ifdef CORE_INT17_PIN
484  case CORE_INT17_PIN:
485  interruptArgs[17] = state;
486  attachInterrupt(17, isr17, CHANGE);
487  break;
488  #endif
489  #ifdef CORE_INT18_PIN
490  case CORE_INT18_PIN:
491  interruptArgs[18] = state;
492  attachInterrupt(18, isr18, CHANGE);
493  break;
494  #endif
495  #ifdef CORE_INT19_PIN
496  case CORE_INT19_PIN:
497  interruptArgs[19] = state;
498  attachInterrupt(19, isr19, CHANGE);
499  break;
500  #endif
501  #ifdef CORE_INT20_PIN
502  case CORE_INT20_PIN:
503  interruptArgs[20] = state;
504  attachInterrupt(20, isr20, CHANGE);
505  break;
506  #endif
507  #ifdef CORE_INT21_PIN
508  case CORE_INT21_PIN:
509  interruptArgs[21] = state;
510  attachInterrupt(21, isr21, CHANGE);
511  break;
512  #endif
513  #ifdef CORE_INT22_PIN
514  case CORE_INT22_PIN:
515  interruptArgs[22] = state;
516  attachInterrupt(22, isr22, CHANGE);
517  break;
518  #endif
519  #ifdef CORE_INT23_PIN
520  case CORE_INT23_PIN:
521  interruptArgs[23] = state;
522  attachInterrupt(23, isr23, CHANGE);
523  break;
524  #endif
525  #ifdef CORE_INT24_PIN
526  case CORE_INT24_PIN:
527  interruptArgs[24] = state;
528  attachInterrupt(24, isr24, CHANGE);
529  break;
530  #endif
531  #ifdef CORE_INT25_PIN
532  case CORE_INT25_PIN:
533  interruptArgs[25] = state;
534  attachInterrupt(25, isr25, CHANGE);
535  break;
536  #endif
537  #ifdef CORE_INT26_PIN
538  case CORE_INT26_PIN:
539  interruptArgs[26] = state;
540  attachInterrupt(26, isr26, CHANGE);
541  break;
542  #endif
543  #ifdef CORE_INT27_PIN
544  case CORE_INT27_PIN:
545  interruptArgs[27] = state;
546  attachInterrupt(27, isr27, CHANGE);
547  break;
548  #endif
549  #ifdef CORE_INT28_PIN
550  case CORE_INT28_PIN:
551  interruptArgs[28] = state;
552  attachInterrupt(28, isr28, CHANGE);
553  break;
554  #endif
555  #ifdef CORE_INT29_PIN
556  case CORE_INT29_PIN:
557  interruptArgs[29] = state;
558  attachInterrupt(29, isr29, CHANGE);
559  break;
560  #endif
561 
562  #ifdef CORE_INT30_PIN
563  case CORE_INT30_PIN:
564  interruptArgs[30] = state;
565  attachInterrupt(30, isr30, CHANGE);
566  break;
567  #endif
568  #ifdef CORE_INT31_PIN
569  case CORE_INT31_PIN:
570  interruptArgs[31] = state;
571  attachInterrupt(31, isr31, CHANGE);
572  break;
573  #endif
574  #ifdef CORE_INT32_PIN
575  case CORE_INT32_PIN:
576  interruptArgs[32] = state;
577  attachInterrupt(32, isr32, CHANGE);
578  break;
579  #endif
580  #ifdef CORE_INT33_PIN
581  case CORE_INT33_PIN:
582  interruptArgs[33] = state;
583  attachInterrupt(33, isr33, CHANGE);
584  break;
585  #endif
586  #ifdef CORE_INT34_PIN
587  case CORE_INT34_PIN:
588  interruptArgs[34] = state;
589  attachInterrupt(34, isr34, CHANGE);
590  break;
591  #endif
592  #ifdef CORE_INT35_PIN
593  case CORE_INT35_PIN:
594  interruptArgs[35] = state;
595  attachInterrupt(35, isr35, CHANGE);
596  break;
597  #endif
598  #ifdef CORE_INT36_PIN
599  case CORE_INT36_PIN:
600  interruptArgs[36] = state;
601  attachInterrupt(36, isr36, CHANGE);
602  break;
603  #endif
604  #ifdef CORE_INT37_PIN
605  case CORE_INT37_PIN:
606  interruptArgs[37] = state;
607  attachInterrupt(37, isr37, CHANGE);
608  break;
609  #endif
610  #ifdef CORE_INT38_PIN
611  case CORE_INT38_PIN:
612  interruptArgs[38] = state;
613  attachInterrupt(38, isr38, CHANGE);
614  break;
615  #endif
616  #ifdef CORE_INT39_PIN
617  case CORE_INT39_PIN:
618  interruptArgs[39] = state;
619  attachInterrupt(39, isr39, CHANGE);
620  break;
621  #endif
622  #ifdef CORE_INT40_PIN
623  case CORE_INT40_PIN:
624  interruptArgs[40] = state;
625  attachInterrupt(40, isr40, CHANGE);
626  break;
627  #endif
628  #ifdef CORE_INT41_PIN
629  case CORE_INT41_PIN:
630  interruptArgs[41] = state;
631  attachInterrupt(41, isr41, CHANGE);
632  break;
633  #endif
634  #ifdef CORE_INT42_PIN
635  case CORE_INT42_PIN:
636  interruptArgs[42] = state;
637  attachInterrupt(42, isr42, CHANGE);
638  break;
639  #endif
640  #ifdef CORE_INT43_PIN
641  case CORE_INT43_PIN:
642  interruptArgs[43] = state;
643  attachInterrupt(43, isr43, CHANGE);
644  break;
645  #endif
646  #ifdef CORE_INT44_PIN
647  case CORE_INT44_PIN:
648  interruptArgs[44] = state;
649  attachInterrupt(44, isr44, CHANGE);
650  break;
651  #endif
652  #ifdef CORE_INT45_PIN
653  case CORE_INT45_PIN:
654  interruptArgs[45] = state;
655  attachInterrupt(45, isr45, CHANGE);
656  break;
657  #endif
658  #ifdef CORE_INT46_PIN
659  case CORE_INT46_PIN:
660  interruptArgs[46] = state;
661  attachInterrupt(46, isr46, CHANGE);
662  break;
663  #endif
664  #ifdef CORE_INT47_PIN
665  case CORE_INT47_PIN:
666  interruptArgs[47] = state;
667  attachInterrupt(47, isr47, CHANGE);
668  break;
669  #endif
670  #ifdef CORE_INT48_PIN
671  case CORE_INT48_PIN:
672  interruptArgs[48] = state;
673  attachInterrupt(48, isr48, CHANGE);
674  break;
675  #endif
676  #ifdef CORE_INT49_PIN
677  case CORE_INT49_PIN:
678  interruptArgs[49] = state;
679  attachInterrupt(49, isr49, CHANGE);
680  break;
681  #endif
682  #ifdef CORE_INT50_PIN
683  case CORE_INT50_PIN:
684  interruptArgs[50] = state;
685  attachInterrupt(50, isr50, CHANGE);
686  break;
687  #endif
688  #ifdef CORE_INT51_PIN
689  case CORE_INT51_PIN:
690  interruptArgs[51] = state;
691  attachInterrupt(51, isr51, CHANGE);
692  break;
693  #endif
694  #ifdef CORE_INT52_PIN
695  case CORE_INT52_PIN:
696  interruptArgs[52] = state;
697  attachInterrupt(52, isr52, CHANGE);
698  break;
699  #endif
700  #ifdef CORE_INT53_PIN
701  case CORE_INT53_PIN:
702  interruptArgs[53] = state;
703  attachInterrupt(53, isr53, CHANGE);
704  break;
705  #endif
706  #ifdef CORE_INT54_PIN
707  case CORE_INT54_PIN:
708  interruptArgs[54] = state;
709  attachInterrupt(54, isr54, CHANGE);
710  break;
711  #endif
712  #ifdef CORE_INT55_PIN
713  case CORE_INT55_PIN:
714  interruptArgs[55] = state;
715  attachInterrupt(55, isr55, CHANGE);
716  break;
717  #endif
718  #ifdef CORE_INT56_PIN
719  case CORE_INT56_PIN:
720  interruptArgs[56] = state;
721  attachInterrupt(56, isr56, CHANGE);
722  break;
723  #endif
724  #ifdef CORE_INT57_PIN
725  case CORE_INT57_PIN:
726  interruptArgs[57] = state;
727  attachInterrupt(57, isr57, CHANGE);
728  break;
729  #endif
730  #ifdef CORE_INT58_PIN
731  case CORE_INT58_PIN:
732  interruptArgs[58] = state;
733  attachInterrupt(58, isr58, CHANGE);
734  break;
735  #endif
736  #ifdef CORE_INT59_PIN
737  case CORE_INT59_PIN:
738  interruptArgs[59] = state;
739  attachInterrupt(59, isr59, CHANGE);
740  break;
741  #endif
742  default:
743  return 0;
744  }
745  return 1;
746  }
747 #endif // ENCODER_USE_INTERRUPTS
748 
749 
750 #if defined(ENCODER_USE_INTERRUPTS) && !defined(ENCODER_OPTIMIZE_INTERRUPTS)
751  #ifdef CORE_INT0_PIN
752  static void isr0(void) { update(interruptArgs[0]); }
753  #endif
754  #ifdef CORE_INT1_PIN
755  static void isr1(void) { update(interruptArgs[1]); }
756  #endif
757  #ifdef CORE_INT2_PIN
758  static void isr2(void) { update(interruptArgs[2]); }
759  #endif
760  #ifdef CORE_INT3_PIN
761  static void isr3(void) { update(interruptArgs[3]); }
762  #endif
763  #ifdef CORE_INT4_PIN
764  static void isr4(void) { update(interruptArgs[4]); }
765  #endif
766  #ifdef CORE_INT5_PIN
767  static void isr5(void) { update(interruptArgs[5]); }
768  #endif
769  #ifdef CORE_INT6_PIN
770  static void isr6(void) { update(interruptArgs[6]); }
771  #endif
772  #ifdef CORE_INT7_PIN
773  static void isr7(void) { update(interruptArgs[7]); }
774  #endif
775  #ifdef CORE_INT8_PIN
776  static void isr8(void) { update(interruptArgs[8]); }
777  #endif
778  #ifdef CORE_INT9_PIN
779  static void isr9(void) { update(interruptArgs[9]); }
780  #endif
781  #ifdef CORE_INT10_PIN
782  static void isr10(void) { update(interruptArgs[10]); }
783  #endif
784  #ifdef CORE_INT11_PIN
785  static void isr11(void) { update(interruptArgs[11]); }
786  #endif
787  #ifdef CORE_INT12_PIN
788  static void isr12(void) { update(interruptArgs[12]); }
789  #endif
790  #ifdef CORE_INT13_PIN
791  static void isr13(void) { update(interruptArgs[13]); }
792  #endif
793  #ifdef CORE_INT14_PIN
794  static void isr14(void) { update(interruptArgs[14]); }
795  #endif
796  #ifdef CORE_INT15_PIN
797  static void isr15(void) { update(interruptArgs[15]); }
798  #endif
799  #ifdef CORE_INT16_PIN
800  static void isr16(void) { update(interruptArgs[16]); }
801  #endif
802  #ifdef CORE_INT17_PIN
803  static void isr17(void) { update(interruptArgs[17]); }
804  #endif
805  #ifdef CORE_INT18_PIN
806  static void isr18(void) { update(interruptArgs[18]); }
807  #endif
808  #ifdef CORE_INT19_PIN
809  static void isr19(void) { update(interruptArgs[19]); }
810  #endif
811  #ifdef CORE_INT20_PIN
812  static void isr20(void) { update(interruptArgs[20]); }
813  #endif
814  #ifdef CORE_INT21_PIN
815  static void isr21(void) { update(interruptArgs[21]); }
816  #endif
817  #ifdef CORE_INT22_PIN
818  static void isr22(void) { update(interruptArgs[22]); }
819  #endif
820  #ifdef CORE_INT23_PIN
821  static void isr23(void) { update(interruptArgs[23]); }
822  #endif
823  #ifdef CORE_INT24_PIN
824  static void isr24(void) { update(interruptArgs[24]); }
825  #endif
826  #ifdef CORE_INT25_PIN
827  static void isr25(void) { update(interruptArgs[25]); }
828  #endif
829  #ifdef CORE_INT26_PIN
830  static void isr26(void) { update(interruptArgs[26]); }
831  #endif
832  #ifdef CORE_INT27_PIN
833  static void isr27(void) { update(interruptArgs[27]); }
834  #endif
835  #ifdef CORE_INT28_PIN
836  static void isr28(void) { update(interruptArgs[28]); }
837  #endif
838  #ifdef CORE_INT29_PIN
839  static void isr29(void) { update(interruptArgs[29]); }
840  #endif
841  #ifdef CORE_INT30_PIN
842  static void isr30(void) { update(interruptArgs[30]); }
843  #endif
844  #ifdef CORE_INT31_PIN
845  static void isr31(void) { update(interruptArgs[31]); }
846  #endif
847  #ifdef CORE_INT32_PIN
848  static void isr32(void) { update(interruptArgs[32]); }
849  #endif
850  #ifdef CORE_INT33_PIN
851  static void isr33(void) { update(interruptArgs[33]); }
852  #endif
853  #ifdef CORE_INT34_PIN
854  static void isr34(void) { update(interruptArgs[34]); }
855  #endif
856  #ifdef CORE_INT35_PIN
857  static void isr35(void) { update(interruptArgs[35]); }
858  #endif
859  #ifdef CORE_INT36_PIN
860  static void isr36(void) { update(interruptArgs[36]); }
861  #endif
862  #ifdef CORE_INT37_PIN
863  static void isr37(void) { update(interruptArgs[37]); }
864  #endif
865  #ifdef CORE_INT38_PIN
866  static void isr38(void) { update(interruptArgs[38]); }
867  #endif
868  #ifdef CORE_INT39_PIN
869  static void isr39(void) { update(interruptArgs[39]); }
870  #endif
871  #ifdef CORE_INT40_PIN
872  static void isr40(void) { update(interruptArgs[40]); }
873  #endif
874  #ifdef CORE_INT41_PIN
875  static void isr41(void) { update(interruptArgs[41]); }
876  #endif
877  #ifdef CORE_INT42_PIN
878  static void isr42(void) { update(interruptArgs[42]); }
879  #endif
880  #ifdef CORE_INT43_PIN
881  static void isr43(void) { update(interruptArgs[43]); }
882  #endif
883  #ifdef CORE_INT44_PIN
884  static void isr44(void) { update(interruptArgs[44]); }
885  #endif
886  #ifdef CORE_INT45_PIN
887  static void isr45(void) { update(interruptArgs[45]); }
888  #endif
889  #ifdef CORE_INT46_PIN
890  static void isr46(void) { update(interruptArgs[46]); }
891  #endif
892  #ifdef CORE_INT47_PIN
893  static void isr47(void) { update(interruptArgs[47]); }
894  #endif
895  #ifdef CORE_INT48_PIN
896  static void isr48(void) { update(interruptArgs[48]); }
897  #endif
898  #ifdef CORE_INT49_PIN
899  static void isr49(void) { update(interruptArgs[49]); }
900  #endif
901  #ifdef CORE_INT50_PIN
902  static void isr50(void) { update(interruptArgs[50]); }
903  #endif
904  #ifdef CORE_INT51_PIN
905  static void isr51(void) { update(interruptArgs[51]); }
906  #endif
907  #ifdef CORE_INT52_PIN
908  static void isr52(void) { update(interruptArgs[52]); }
909  #endif
910  #ifdef CORE_INT53_PIN
911  static void isr53(void) { update(interruptArgs[53]); }
912  #endif
913  #ifdef CORE_INT54_PIN
914  static void isr54(void) { update(interruptArgs[54]); }
915  #endif
916  #ifdef CORE_INT55_PIN
917  static void isr55(void) { update(interruptArgs[55]); }
918  #endif
919  #ifdef CORE_INT56_PIN
920  static void isr56(void) { update(interruptArgs[56]); }
921  #endif
922  #ifdef CORE_INT57_PIN
923  static void isr57(void) { update(interruptArgs[57]); }
924  #endif
925  #ifdef CORE_INT58_PIN
926  static void isr58(void) { update(interruptArgs[58]); }
927  #endif
928  #ifdef CORE_INT59_PIN
929  static void isr59(void) { update(interruptArgs[59]); }
930  #endif
931 #endif
932 };
933 
934 #if defined(ENCODER_USE_INTERRUPTS) && defined(ENCODER_OPTIMIZE_INTERRUPTS)
935 #if defined(__AVR__)
936 #if defined(INT0_vect) && CORE_NUM_INTERRUPT > 0
937 ISR(INT0_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(0)]); }
938 #endif
939 #if defined(INT1_vect) && CORE_NUM_INTERRUPT > 1
940 ISR(INT1_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(1)]); }
941 #endif
942 #if defined(INT2_vect) && CORE_NUM_INTERRUPT > 2
943 ISR(INT2_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(2)]); }
944 #endif
945 #if defined(INT3_vect) && CORE_NUM_INTERRUPT > 3
946 ISR(INT3_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(3)]); }
947 #endif
948 #if defined(INT4_vect) && CORE_NUM_INTERRUPT > 4
949 ISR(INT4_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(4)]); }
950 #endif
951 #if defined(INT5_vect) && CORE_NUM_INTERRUPT > 5
952 ISR(INT5_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(5)]); }
953 #endif
954 #if defined(INT6_vect) && CORE_NUM_INTERRUPT > 6
955 ISR(INT6_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(6)]); }
956 #endif
957 #if defined(INT7_vect) && CORE_NUM_INTERRUPT > 7
958 ISR(INT7_vect) { Encoder::update(Encoder::interruptArgs[SCRAMBLE_INT_ORDER(7)]); }
959 #endif
960 #endif // AVR
961 #if defined(attachInterrupt)
962 // Don't intefere with other libraries or sketch use of attachInterrupt()
963 // https://github.com/PaulStoffregen/Encoder/issues/8
964 #undef attachInterrupt
965 #endif
966 #endif // ENCODER_OPTIMIZE_INTERRUPTS
967 
968 
969 #endif
int32_t readAndReset()
Definition: Encoder.h:115
static uint8_t attach_interrupt(uint8_t pin, Encoder_internal_state_t *state)
Definition: Encoder.h:379
#define ENCODER_ARGLIST_SIZE
Definition: Encoder.h:45
void write(int32_t p)
Definition: Encoder.h:127
static void update(Encoder_internal_state_t *arg)
Definition: Encoder.h:206
Encoder(uint8_t pin1, uint8_t pin2)
Definition: Encoder.h:72
static Encoder_internal_state_t * interruptArgs[ENCODER_ARGLIST_SIZE]
Definition: Encoder.h:153
IO_REG_TYPE pin2_bitmask
Definition: Encoder.h:64
uint8_t interrupts_in_use
Definition: Encoder.h:150
Encoder_internal_state_t encoder
Definition: Encoder.h:148
IO_REG_TYPE pin1_bitmask
Definition: Encoder.h:63
int32_t read()
Definition: Encoder.h:104
volatile IO_REG_TYPE * pin2_register
Definition: Encoder.h:62
volatile IO_REG_TYPE * pin1_register
Definition: Encoder.h:61