David Grayson / PololuEncoder

Dependents:   LineFollowing DeadReckoning

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PololuEncoder.h Source File

PololuEncoder.h

00001 #pragma once
00002 
00003 #include <mbed.h>
00004 
00005 #define POLOLU_ENCODER_EVENT_INC  0x40
00006 #define POLOLU_ENCODER_EVENT_DEC  0x80
00007 #define POLOLU_ENCODER_EVENT_ERR  0xC0
00008 
00009 #define POLOLU_ENCODER_BUFFER_SIZE 256
00010 
00011 typedef uint8_t PololuEncoderEvent;
00012 
00013 class PololuEncoderBuffer
00014 {
00015     private:
00016     volatile uint32_t consumerIndex;  // The index in the ring buffer that will be consumed next.
00017     volatile uint32_t producerIndex;  // The index in the ring buffer that will be populated next, which is currently empty.
00018     volatile uint8_t buffer[POLOLU_ENCODER_BUFFER_SIZE];
00019 
00020     public:
00021     bool hasEvents() const
00022     {
00023         return consumerIndex != producerIndex;
00024     }
00025     
00026     bool hasSpace() const
00027     {
00028         return ((producerIndex + 1) % POLOLU_ENCODER_BUFFER_SIZE) != consumerIndex;
00029     }
00030     
00031     uint8_t readEvent()
00032     {
00033         uint8_t event = buffer[consumerIndex];
00034         consumerIndex = (consumerIndex + 1) % POLOLU_ENCODER_BUFFER_SIZE;
00035         return event;
00036     }
00037     
00038     void writeEvent(uint8_t event)
00039     {
00040         buffer[producerIndex] = event;
00041         producerIndex = (producerIndex + 1) % POLOLU_ENCODER_BUFFER_SIZE;    
00042     }
00043 };
00044 
00045 class PololuEncoder
00046 {
00047     public:
00048     PololuEncoder(PinName pinNameA, PinName pinNameB, PololuEncoderBuffer * buffer, uint8_t id)
00049       : pinA(pinNameA), pinB(pinNameB), buffer(buffer), id(id)
00050     {
00051     }
00052     
00053     void init()
00054     {
00055         pinA.rise(this, &PololuEncoder::isr);
00056         pinA.fall(this, &PololuEncoder::isr);
00057         pinB.rise(this, &PololuEncoder::isr);
00058         pinB.fall(this, &PololuEncoder::isr);
00059         previousState = readState();
00060         count = 0;
00061     }
00062     
00063     void isr()
00064     {
00065         uint8_t event = 0;
00066         uint8_t newState = readState();
00067         switch((previousState << 2) | newState)
00068         {
00069         case 0x1: // 0b0001
00070         case 0x7: // 0b0111
00071         case 0xE: // 0b1110
00072         case 0x8: // 0b1000
00073             event = id | POLOLU_ENCODER_EVENT_INC;
00074             count += 1;
00075             break;
00076         case 0x2: // 0b0010
00077         case 0xB: // 0b1011
00078         case 0xD: // 0b1101
00079         case 0x4: // 0b0100
00080             event = id | POLOLU_ENCODER_EVENT_DEC;
00081             count -= 1;
00082             break;
00083         case 0x3: // 0b0011
00084         case 0x6: // 0b0110
00085         case 0x9: // 0b1001
00086         case 0xC: // 0b1100
00087             event = id | POLOLU_ENCODER_EVENT_ERR;
00088             break;
00089         }        
00090         previousState = newState;
00091         
00092         if (event != 0 && buffer != NULL && buffer->hasSpace())
00093         {
00094             buffer->writeEvent(event);
00095         }
00096     }
00097     
00098     int32_t getCount()
00099     {
00100         return count;
00101     }
00102     
00103     private:
00104     uint8_t readState()
00105     {
00106         return pinA | (pinB << 1);
00107     }
00108     
00109     InterruptIn pinA;
00110     InterruptIn pinB;
00111     PololuEncoderBuffer * buffer;
00112     uint8_t previousState;
00113     volatile uint8_t id;
00114     volatile int32_t count;
00115 };