#include "pic24_all.h"
//clips cntr between 0 and max
uint8_t processRotaryData(volatile uint8_t u8_curr, volatile uint8_t u8_last,
volatile uint8_t *cntr, volatile uint8_t max) {
int8_t delta = 0;
//states listed in Gray code order for clarity
switch (u8_curr) {
case 0:
if (u8_last == 1) delta = 1;
else if (u8_last == 2) delta = -1;
break;
case 1:
if (u8_last == 3) delta = 1;
else if (u8_last == 0) delta = -1;
break;
case 3:
if (u8_last == 2) delta = 1;
else if (u8_last == 1) delta = -1;
break;
case 2:
if (u8_last == 0) delta = 1;
else if (u8_last == 3) delta = -1;
break;
default:
break;
}
if (delta == 0) return(1); //error, illegal state
//clip and update.
if (( *cntr == 0 && delta == -1)
|| (*cntr == max && delta == 1)) return 0; //at limit
(*cntr) = (*cntr) + delta;
return 0;
}
#define ROT1_RAW _RB13
#define ROT0_RAW _RB12
#define GET_ROT_STATE() ((ROT1_RAW << 1) | ROT0_RAW)
/// ROT1 configuration
inline void configRotaryEncoder() {
CONFIG_RB13_AS_DIG_INPUT();
ENABLE_RB13_PULLUP(); //enable the pullup
CONFIG_RB12_AS_DIG_INPUT();
ENABLE_RB12_PULLUP(); //enable the pullup
DELAY_US(1); //wait for pullups to settle
}
#define ROT_MAX 32 //arbitrary limit
volatile uint8_t u8_valueROT = 0;
volatile uint8_t u8_lastvalueROT = 0;
volatile uint8_t u8_errROT = 0;
volatile uint8_t u8_cntrROT = 0;
//Interrupt Service Routine for Timer3
void _ISRFAST _T3Interrupt (void) {
u8_valueROT = GET_ROT_STATE(); //a value between 0 & 3
if (u8_lastvalueROT != u8_valueROT) {
u8_errROT = processRotaryData(u8_valueROT, u8_lastvalueROT, &u8_cntrROT, ROT_MAX);
u8_lastvalueROT = u8_valueROT;
}
_T3IF = 0; //clear the timer interrupt bit
}
#define ISR_PERIOD 15 // in ms
void configTimer3(void) {
//ensure that Timer2,3 configured as separate timers.
T2CONbits.T32 = 0; // 32-bit mode off
//T3CON set like this for documentation purposes.
//could be replaced by T3CON = 0x0020
T3CON = T3_OFF | T3_IDLE_CON | T3_GATE_OFF
| T3_SOURCE_INT
| T3_PS_1_64 ; //results in T3CON= 0x0020
PR3 = msToU16Ticks (ISR_PERIOD, getTimerPrescale(T3CONbits)) - 1;
TMR3 = 0; //clear timer3 value
_T3IF = 0; //clear interrupt flag
_T3IP = 1; //choose a priority
_T3IE = 1; //enable the interrupt
T3CONbits.TON = 1; //turn on the timer
}
int main (void) {
uint8_t u8_lastCnt;
configBasic(HELLO_MSG);
/** PIO config ******/
configRotaryEncoder();
u8_valueROT = GET_ROT_STATE();
u8_lastvalueROT = u8_valueROT;
u8_lastCnt = u8_cntrROT;
/** Configure the Timer */
configTimer3();
while (1) {
if (u8_lastCnt != u8_cntrROT) {
u8_lastCnt = u8_cntrROT;
outUint8(u8_lastCnt);
outString("\n");
if (u8_errROT) {
outString("Rotary state error\n");
u8_errROT = 0;
}
}
doHeartbeat(); //indicate that we are alive
} // end while (1)
}