diff --git a/ubitx.h b/ubitx.h index 15bf3a5..90fa571 100644 --- a/ubitx.h +++ b/ubitx.h @@ -179,6 +179,7 @@ void cwKeyer(void); void switchVFO(int vfoSelect); int enc_read(void); // returns the number of ticks in a short interval, +ve in clockwise, -ve in anti-clockwise +void enc_setup(void); // Setups up initial values and interrupts. int btnDown(); //returns true if the encoder button is pressed /* these functions are called universally to update the display */ diff --git a/ubitx_ui.cpp b/ubitx_ui.cpp index ec29dd3..8501f4d 100644 --- a/ubitx_ui.cpp +++ b/ubitx_ui.cpp @@ -565,7 +565,6 @@ void updateDisplay() { displayVFO(vfoActive); } -int enc_prev_state = 3; /** * The A7 And A6 are purely analog lines on the Arduino Nano @@ -585,11 +584,15 @@ int enc_prev_state = 3; * at which the enccoder was spun */ +/* +int enc_prev_state = 3; + byte enc_state (void) { //Serial.print(digitalRead(ENC_A)); Serial.print(":");Serial.println(digitalRead(ENC_B)); return (digitalRead(ENC_A) == 1 ? 1 : 0) + (digitalRead(ENC_B) == 1 ? 2: 0); } + int enc_read(void) { int result = 0; byte newState; @@ -627,6 +630,91 @@ int enc_read(void) { // Serial.println(result); return(result); } +*/ + +/* + * SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling. + */ +int enc_count; +uint8_t prev_enc; + +uint8_t enc_state (void) { + return (digitalRead(ENC_A)?1:0 + digitalRead(ENC_B)?2:0); +} + +/* + * Setup the encoder interrupts and global variables. + */ +void pci_setup(byte pin) { + *digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin + PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt + PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group +} + +void enc_setup(void) { + enc_count = 0; + // This is already done in setup() ? + //pinMode(ENC_A, INPUT); + //pinMode(ENC_B, INPUT); + prev_enc = enc_state(); + + // Setup Pin Change Interrupts for the encoder inputs + pci_setup(ENC_A); + pci_setup(ENC_B); +} + +/* + * The Interrupt Service Routine for Pin Change Interrupts on A0-A5. + */ +ISR (PCINT1_vect) { + uint8_t cur_enc = enc_state(); + if (prev_enc == cur_enc) { + //Serial.println("unnecessary ISR"); + return; + } + //Serial.print(prev_enc); + //Serial.println(cur_enc); + + //these transitions point to the enccoder being rotated anti-clockwise + if ((prev_enc == 0 && cur_enc == 2) || + (prev_enc == 2 && cur_enc == 3) || + (prev_enc == 3 && cur_enc == 1) || + (prev_enc == 1 && cur_enc == 0)) + { + enc_count-=1; + } + //these transitions point to the enccoder being rotated clockwise + else if ((prev_enc == 0 && cur_enc == 1) || + (prev_enc == 1 && cur_enc == 3) || + (prev_enc == 3 && cur_enc == 2) || + (prev_enc == 2 && cur_enc == 0)) + { + enc_count+=1; + } + else { + // A change to two states, we can't tell whether it was forward or backward, so we skip it. + //Serial.println("skip"); + } + prev_enc = cur_enc; // Record state for next pulse interpretation +} + +int enc_read(void) { + int ret = enc_count; + enc_count = 0; + if (ret == 255 || ret == -256) { + // FIXME I (@SmittyHalibut) can't figure out why we occasionally get + // either a 255 or -256 return value here. It's like it's occasionally + // treating an int as an unsigned value while incrementing or decrementing. + // I can't figure out why, but I can detect it and skip it. So that's + // what we're doing. + //Serial.println("255 error in encoder."); + return 0; + } + return ret; +} + + + void ritToggle(struct Button *button){ if (ritOn == 0){ @@ -1021,4 +1109,3 @@ void doCommands(){ checkCAT(); } - diff --git a/ubitx_v6.3.1_code.ino b/ubitx_v6.3.1_code.ino index d2518d1..3c32faf 100644 --- a/ubitx_v6.3.1_code.ino +++ b/ubitx_v6.3.1_code.ino @@ -522,32 +522,30 @@ void doTuning(){ unsigned long now = millis(); - if (now >= nextFrequencyUpdate && prev_freq != frequency){ - updateDisplay(); - nextFrequencyUpdate = now + 500; - prev_freq = frequency; - } - s = enc_read(); if (!s) return; + //Serial.print(s); + doingCAT = 0; // go back to manual mode if you were doing CAT prev_freq = frequency; - - if (s > 10) - frequency += 200l * s; - else if (s > 5) - frequency += 100l * s; - else if (s > 0) + // TODO With the new more responsive tuning, 5 and 10 are nearly useless + // thresholds for acceleration. I rarely see above 2 or 3 even when turning + // the knob quickly. + if (s < 5 && s > -5) { frequency += 50l * s; - else if (s < -10) - frequency += 200l * s; - else if (s < -5) + //Serial.println(" 5"); + } + else if (s < 10 && s > -10) { frequency += 100l * s; - else if (s < 0) - frequency += 50l * s; + //Serial.println(" 10"); + } + else { // if (s >= 10 || s <= -10) + frequency += 200l * s; + //Serial.println(" <"); + } if (prev_freq < 10000000l && frequency > 10000000l) isUSB = true; @@ -556,6 +554,12 @@ void doTuning(){ isUSB = false; setFrequency(frequency); + + if (now >= nextFrequencyUpdate && prev_freq != frequency){ + updateDisplay(); + nextFrequencyUpdate = now + 100; + prev_freq = frequency; + } } @@ -676,6 +680,7 @@ void initPorts(){ pinMode(ENC_A, INPUT_PULLUP); pinMode(ENC_B, INPUT_PULLUP); pinMode(FBUTTON, INPUT_PULLUP); + enc_setup(); //configure the function button to use the external pull-up // pinMode(FBUTTON, INPUT);