SSB_Radio_Control/Encoder.cpp

244 wiersze
6.6 KiB
C++

//
// Encoder fuctions
//
#include "RadioControl.h"
//#DEFINE DEBUG_ENC
//////////////////////////////////////////////////////////////////////
// Rotary Enconder //
//////////////////////////////////////////////////////////////////////
Rotary encoder = Rotary(ENCODER_A, ENCODER_B, ENCODER_BTN); // Setup Encoder
//////////////////////////////////////////////////////////////////////
// //
// Rotary Encoder Variables //
// Number of clockwise and counterclockwise ticks //
// Delta between successive measurements //
// //
//////////////////////////////////////////////////////////////////////
volatile int encoder_count = 0; // count of encoder clicks +1 for CW, -1 for CCW (volatile since used in ISR)
int prev_encoder_count = 0; // used to measure changes over time
int encoder_delta = 0; // differrnce between successive checks of encoder count
bool incrementChanged = false;
// when multiplied by tuning increment tells what the frequency change on
// on the active VFO will be
// Encoder button control
extern byte EncButtonState;
extern byte lastEncButtonState;
///////////////////////////////////////////////////////////
// ************* ISR **************** //
// Interrupt service routine, called on encoder movement //
// Only interested in completed clicks //
// +1 for Clocwwise //
// -1 for Counter Clockwise //
// Ignore intermediate values //
///////////////////////////////////////////////////////////
#if _BOARDTYPE != Every
ISR(PCINT2_vect) {
unsigned char result = encoder.process();
if (result == DIR_CW) {
encoder_count++;
} else if (result == DIR_CCW) {
encoder_count--;
}
}
#else
#define PA0_INTERRUPT PORTA.INTFLAGS & PIN0_bm
#define PA0_CLEAR_INTERRUPT_FLAG PORTA.INTFLAGS &= PIN0_bm
#define PF5_INTERRUPT PORTF.INTFLAGS & PIN5_bm
#define PF5_CLEAR_INTERRUPT_FLAG PORTF.INTFLAGS &= PIN5_bm
ISR(PORTA_PORT_vect) {
unsigned char result = encoder.process();
if (PA0_INTERRUPT)
PA0_CLEAR_INTERRUPT_FLAG;
if (result == DIR_CW) {
encoder_count++;
} else if (result == DIR_CCW) {
encoder_count--;
}
}
ISR(PORTF_PORT_vect) {
unsigned char result = encoder.process();
if (PF5_INTERRUPT)
PF5_CLEAR_INTERRUPT_FLAG;
if (result == DIR_CW) {
encoder_count++;
} else if (result == DIR_CCW) {
encoder_count--;
}
}
#endif
//*******************Setup Interrupt Service Routine********************
void setupEncoderISR() {
cli();
// Set up for the rotary encoder interrupts
#if _BOARDTYPE != Every
PCICR |= (1 << PCIE2);
PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
#endif
#if _BOARDTYPE == Every
PORTA.PIN0CTRL |= PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc;
PORTF.PIN5CTRL |= PORT_PULLUPEN_bm | PORT_ISC_BOTHEDGES_gc;
#endif
sei();
}
//********************CheckEncoder*******************************************
// roundedF - Calculates new frequency
// After an increment change rounds up or down to the next even increment
// Otherwise just changes increments or decrements the frequency
//
uint32_t roundedF(uint32_t freq, int32_t delta) {
uint32_t f = freq;
/* if (incrementChanged) {
if (f % increment) {
if (delta > 0 ) {
f = f + increment - (f % increment);
} else {
f = f - (f % increment);
}
}
incrementChanged = false;
} else {
f = f + delta;
}
*/
if (f % increment) {
if (delta > 0 ) {
f = f + increment - (f % increment);
} else {
f = f - (f % increment);
}
} else {
f = f + delta;
}
return f;
}
void AdjustVFO(long delta) {
switch (active_vfo) {
case VFOA:
// vfoAfreq = vfoAfreq + delta;
vfoAfreq = roundedF(vfoAfreq, delta);
setVFO(vfoAfreq);
displayActVFO(vfoAfreq);
break;
case VFOB:
// vfoBfreq = vfoBfreq + delta;
vfoBfreq = roundedF(vfoBfreq, delta);
setVFO(vfoBfreq);
displayActVFO(vfoBfreq);
break;
}
startSettingsTimer();
}
void CheckEncoder() {
int current_count = encoder_count; // grab the current encoder_count
int32_t encoder_delta = 0;
if (current_count != prev_encoder_count) { // if there is any change in the encoder coount
#ifdef DEBUG_ENC
sprintf(debugmsg, "VFOA: %ld", vfoAfreq);
Serial.println(debugmsg);
#endif
//
// Calculate the delta (how many click positive or negaitve)
//
encoder_delta = current_count - prev_encoder_count;
//
// Adjust the currently selected VFO
//
AdjustVFO(encoder_delta * increment);
#ifdef DEBUG
sprintf(debugmsg, "current_count: %d, New VFOA: %ld", current_count, vfoAfreq);
Serial.println(debugmsg);
#endif
prev_encoder_count = current_count; // save the current_count for next time around
}
}
//********************CheckIncrement*******************************************
// Cycle through tuning increment values on button press
// 10, 100, 1K, 10K, 100K, 1M
//********************CheckIncrement*******************************************
void AdvanceIncrement() {
if (increment == 10) {
increment = 100;
}
else if (increment == 100) {
increment = 1000;
}
else if (increment == 1000) {
increment = 10000;
}
else if (increment == 10000) {
increment = 100000;
}
else if (increment == 100000) {
increment = 1000000;
}
else {
increment = 10;
}
displayIncr(increment);
incrementChanged = true;
startSettingsTimer();
}
void CheckIncrement () {
EncButtonState = encoder.buttonState();
//EncButtonState = digitalRead(ENCODER_BTN);
#ifdef DEBUG
sprintf(debugmsg, "Encoder button state: %d", EncButtonState);
Serial.println(debugmsg);
Delay(1000);
#endif
if (EncButtonState != lastEncButtonState) {
#ifdef DEBUG
sprintf(debugmsg, "Encoder button state: %d", EncButtonState);
Serial.println(debugmsg);
#endif
if (EncButtonState == LOW) {
AdvanceIncrement();
}
lastEncButtonState = EncButtonState;
Delay(50);
EncButtonState = encoder.buttonState(); //debounce
//EncButtonState = digitalRead(ENCODER_BTN);
}
}
void setupEncoder() {
setupEncoderISR();
}