Files
mon_PocketVoltex/Firmware/PocketVoltex/Encoder.c
T
2017-01-08 22:09:39 +10:00

74 lines
1.9 KiB
C

#include "Encoder.h"
// SDVX Controller - PD0-3
#define ENCODER_COUNT 2
#define ENCODER_PORT PORTD
#define ENCODER_PIN PIND
#define ENCODER_DDR DDRD
#define GET_ENCODER_0() (ENCODER_PIN & 0b11)
#define GET_ENCODER_1() ((ENCODER_PIN >> 2) & 0b11)
typedef struct {
int8_t position;
uint8_t state;
} encoder_t;
static volatile encoder_t encoders[ENCODER_COUNT] = {};
void encoder_init(void) {
// inputs
ENCODER_DDR &= ~0x0F;
// pullups
ENCODER_PORT |= 0x0F;
encoders[0].state = GET_ENCODER_0();
encoders[1].state = GET_ENCODER_1();
// Edge interrupts on all INT pins
EICRA = _BV(ISC30) | _BV(ISC20) | _BV(ISC10) | _BV(ISC00);
// Enable the interrupts
EIMSK = _BV(INT3) | _BV(INT2) | _BV(INT1) | _BV(INT0);
// Clear interrupt flags
EIFR = _BV(INTF3) | _BV(INTF2) | _BV(INTF1) | _BV(INTF0);
}
int8_t encoder_get(uint8_t num) {
return encoders[num].position;
}
void encoder_set(uint8_t num, int8_t val) {
encoders[num].position = val;
}
// Adapted from the wonderful Encoder.h by PJRC
void update(uint8_t num, uint8_t newState) {
int8_t position = encoders[num].position;
uint8_t state = encoders[num].state | (newState << 2);
encoders[num].state = newState;
switch (state) {
case 1: case 7: case 8: case 14:
if(position < 127)
encoders[num].position++;
return;
case 2: case 4: case 11: case 13:
if(position > -128)
encoders[num].position--;
return;
case 3: case 12:
if(position < 125)
encoders[num].position += 2;
return;
case 6: case 9:
if(position > -126)
encoders[num].position -= 2;
return;
}
}
ISR(INT0_vect) { update(0, GET_ENCODER_0()); }
ISR(INT1_vect) { update(0, GET_ENCODER_0()); }
ISR(INT2_vect) { update(1, GET_ENCODER_1()); }
ISR(INT3_vect) { update(1, GET_ENCODER_1()); }