Library for decoding quadrature encoders. Uses a ring buffer so you can be sure to process every tick in the order that it happened. This library is not really intended for public use yet and does not have much documentation.

Dependents:   LineFollowing DeadReckoning

Committer:
DavidEGrayson
Date:
Thu Feb 20 20:09:21 2014 +0000
Revision:
2:22ac2b4a8012
Parent:
1:138f5421c287
Child:
3:a2dd8d8bde4c
Don't do any I/O in the constructor; that's a bad idea because then people cannot set up their I/O lines in the right order and with the right delays.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DavidEGrayson 0:82ccff71d12a 1 #include <mbed.h>
DavidEGrayson 0:82ccff71d12a 2
DavidEGrayson 1:138f5421c287 3 #define POLOLU_ENCODER_EVENT_INC 0x40
DavidEGrayson 1:138f5421c287 4 #define POLOLU_ENCODER_EVENT_DEC 0x80
DavidEGrayson 1:138f5421c287 5 #define POLOLU_ENCODER_EVENT_ERR 0xC0
DavidEGrayson 0:82ccff71d12a 6
DavidEGrayson 0:82ccff71d12a 7 #define POLOLU_ENCODER_BUFFER_SIZE 256
DavidEGrayson 0:82ccff71d12a 8
DavidEGrayson 0:82ccff71d12a 9 typedef uint8_t PololuEncoderEvent;
DavidEGrayson 0:82ccff71d12a 10
DavidEGrayson 0:82ccff71d12a 11 class PololuEncoderBuffer
DavidEGrayson 0:82ccff71d12a 12 {
DavidEGrayson 0:82ccff71d12a 13 private:
DavidEGrayson 0:82ccff71d12a 14 volatile uint32_t consumerIndex; // The index in the ring buffer that will be consumed next.
DavidEGrayson 0:82ccff71d12a 15 volatile uint32_t producerIndex; // The index in the ring buffer that will be populated next, which is currently empty.
DavidEGrayson 0:82ccff71d12a 16 volatile uint8_t buffer[POLOLU_ENCODER_BUFFER_SIZE];
DavidEGrayson 0:82ccff71d12a 17
DavidEGrayson 0:82ccff71d12a 18 public:
DavidEGrayson 0:82ccff71d12a 19 bool hasEvents() const
DavidEGrayson 0:82ccff71d12a 20 {
DavidEGrayson 0:82ccff71d12a 21 return consumerIndex != producerIndex;
DavidEGrayson 0:82ccff71d12a 22 }
DavidEGrayson 0:82ccff71d12a 23
DavidEGrayson 0:82ccff71d12a 24 bool hasSpace() const
DavidEGrayson 0:82ccff71d12a 25 {
DavidEGrayson 0:82ccff71d12a 26 return ((producerIndex + 1) % POLOLU_ENCODER_BUFFER_SIZE) != consumerIndex;
DavidEGrayson 0:82ccff71d12a 27 }
DavidEGrayson 0:82ccff71d12a 28
DavidEGrayson 0:82ccff71d12a 29 uint8_t readEvent()
DavidEGrayson 0:82ccff71d12a 30 {
DavidEGrayson 0:82ccff71d12a 31 uint8_t event = buffer[consumerIndex];
DavidEGrayson 0:82ccff71d12a 32 consumerIndex = (consumerIndex + 1) % POLOLU_ENCODER_BUFFER_SIZE;
DavidEGrayson 0:82ccff71d12a 33 return event;
DavidEGrayson 0:82ccff71d12a 34 }
DavidEGrayson 0:82ccff71d12a 35
DavidEGrayson 0:82ccff71d12a 36 void writeEvent(uint8_t event)
DavidEGrayson 0:82ccff71d12a 37 {
DavidEGrayson 0:82ccff71d12a 38 buffer[producerIndex] = event;
DavidEGrayson 0:82ccff71d12a 39 producerIndex = (producerIndex + 1) % POLOLU_ENCODER_BUFFER_SIZE;
DavidEGrayson 0:82ccff71d12a 40 }
DavidEGrayson 0:82ccff71d12a 41 };
DavidEGrayson 0:82ccff71d12a 42
DavidEGrayson 0:82ccff71d12a 43 class PololuEncoder
DavidEGrayson 0:82ccff71d12a 44 {
DavidEGrayson 0:82ccff71d12a 45 public:
DavidEGrayson 0:82ccff71d12a 46 PololuEncoder(PinName pinNameA, PinName pinNameB, PololuEncoderBuffer * buffer, uint8_t id)
DavidEGrayson 0:82ccff71d12a 47 : pinA(pinNameA), pinB(pinNameB), buffer(buffer), id(id)
DavidEGrayson 0:82ccff71d12a 48 {
DavidEGrayson 2:22ac2b4a8012 49 }
DavidEGrayson 2:22ac2b4a8012 50
DavidEGrayson 2:22ac2b4a8012 51 void init()
DavidEGrayson 2:22ac2b4a8012 52 {
DavidEGrayson 0:82ccff71d12a 53 pinA.rise(this, &PololuEncoder::isr);
DavidEGrayson 0:82ccff71d12a 54 pinA.fall(this, &PololuEncoder::isr);
DavidEGrayson 0:82ccff71d12a 55 pinB.rise(this, &PololuEncoder::isr);
DavidEGrayson 0:82ccff71d12a 56 pinB.fall(this, &PololuEncoder::isr);
DavidEGrayson 1:138f5421c287 57 previousState = readState();
DavidEGrayson 2:22ac2b4a8012 58 count = 0;
DavidEGrayson 0:82ccff71d12a 59 }
DavidEGrayson 0:82ccff71d12a 60
DavidEGrayson 0:82ccff71d12a 61 void isr()
DavidEGrayson 0:82ccff71d12a 62 {
DavidEGrayson 1:138f5421c287 63 uint8_t event = 0;
DavidEGrayson 1:138f5421c287 64 uint8_t newState = readState();
DavidEGrayson 1:138f5421c287 65 switch((previousState << 2) | newState)
DavidEGrayson 0:82ccff71d12a 66 {
DavidEGrayson 1:138f5421c287 67 case 0x1: // 0b0001
DavidEGrayson 1:138f5421c287 68 case 0x7: // 0b0111
DavidEGrayson 1:138f5421c287 69 case 0xE: // 0b1110
DavidEGrayson 1:138f5421c287 70 case 0x8: // 0b1000
DavidEGrayson 1:138f5421c287 71 event = id | POLOLU_ENCODER_EVENT_INC;
DavidEGrayson 1:138f5421c287 72 count += 1;
DavidEGrayson 1:138f5421c287 73 break;
DavidEGrayson 1:138f5421c287 74 case 0x2: // 0b0010
DavidEGrayson 1:138f5421c287 75 case 0xB: // 0b1011
DavidEGrayson 1:138f5421c287 76 case 0xD: // 0b1101
DavidEGrayson 1:138f5421c287 77 case 0x4: // 0b0100
DavidEGrayson 1:138f5421c287 78 event = id | POLOLU_ENCODER_EVENT_DEC;
DavidEGrayson 1:138f5421c287 79 count -= 1;
DavidEGrayson 1:138f5421c287 80 break;
DavidEGrayson 1:138f5421c287 81 case 0x3: // 0b0011
DavidEGrayson 1:138f5421c287 82 case 0x6: // 0b0110
DavidEGrayson 1:138f5421c287 83 case 0x9: // 0b1001
DavidEGrayson 1:138f5421c287 84 case 0xC: // 0b1100
DavidEGrayson 1:138f5421c287 85 event = id | POLOLU_ENCODER_EVENT_ERR;
DavidEGrayson 1:138f5421c287 86 break;
DavidEGrayson 1:138f5421c287 87 }
DavidEGrayson 1:138f5421c287 88 previousState = newState;
DavidEGrayson 1:138f5421c287 89
DavidEGrayson 2:22ac2b4a8012 90 if (event != 0 && buffer != NULL && buffer->hasSpace())
DavidEGrayson 1:138f5421c287 91 {
DavidEGrayson 1:138f5421c287 92 buffer->writeEvent(event);
DavidEGrayson 0:82ccff71d12a 93 }
DavidEGrayson 0:82ccff71d12a 94 }
DavidEGrayson 1:138f5421c287 95
DavidEGrayson 1:138f5421c287 96 int32_t getCount()
DavidEGrayson 1:138f5421c287 97 {
DavidEGrayson 1:138f5421c287 98 return count;
DavidEGrayson 1:138f5421c287 99 }
DavidEGrayson 1:138f5421c287 100
DavidEGrayson 1:138f5421c287 101 private:
DavidEGrayson 1:138f5421c287 102 uint8_t readState()
DavidEGrayson 1:138f5421c287 103 {
DavidEGrayson 1:138f5421c287 104 return pinA | (pinB << 1);
DavidEGrayson 1:138f5421c287 105 }
DavidEGrayson 1:138f5421c287 106
DavidEGrayson 1:138f5421c287 107 InterruptIn pinA;
DavidEGrayson 1:138f5421c287 108 InterruptIn pinB;
DavidEGrayson 1:138f5421c287 109 PololuEncoderBuffer * buffer;
DavidEGrayson 1:138f5421c287 110 uint8_t previousState;
DavidEGrayson 1:138f5421c287 111 volatile uint8_t id;
DavidEGrayson 1:138f5421c287 112 volatile int32_t count;
DavidEGrayson 0:82ccff71d12a 113 };