mirror of
https://codeberg.org/mclemens/ubitxv6.git
synced 2024-11-05 12:57:30 -05:00
Merge branch 'master' into morse-menu
This commit is contained in:
commit
6dae08e222
125
encoder.cpp
Normal file
125
encoder.cpp
Normal file
@ -0,0 +1,125 @@
|
||||
#include <Arduino.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "encoder.h"
|
||||
#include "ubitx.h"//Pin definitions
|
||||
|
||||
//Normal encoder state
|
||||
uint8_t prev_enc = 0;
|
||||
int8_t enc_count = 0;
|
||||
|
||||
//Momentum encoder state
|
||||
int16_t enc_count_periodic = 0;
|
||||
int8_t momentum[3] = {0};
|
||||
static const uint16_t CALLBACK_PERIOD_MS = 200;
|
||||
static const uint8_t MOMENTUM_MULTIPLIER = 1;
|
||||
|
||||
uint8_t enc_state (void)
|
||||
{
|
||||
return (digitalRead(ENC_A)?1:0 + digitalRead(ENC_B)?2:0);
|
||||
}
|
||||
|
||||
/*
|
||||
* SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling.
|
||||
* 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;
|
||||
enc_count_periodic -= 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;
|
||||
enc_count_periodic += 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
|
||||
}
|
||||
|
||||
/*
|
||||
* 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);
|
||||
|
||||
//Set up timer interrupt for momentum
|
||||
TCCR1A = 0;//"normal" mode
|
||||
TCCR1B = 3;//clock divider of 64
|
||||
TCNT1 = 0;//start counting at 0
|
||||
OCR1A = F_CPU * CALLBACK_PERIOD_MS / 1000 / 64;//set target number
|
||||
TIMSK1 |= (1 << OCIE1A);//enable interrupt
|
||||
}
|
||||
|
||||
ISR(TIMER1_COMPA_vect)
|
||||
{
|
||||
momentum[2] = momentum[1];
|
||||
momentum[1] = momentum[0];
|
||||
momentum[0] = enc_count_periodic;
|
||||
enc_count_periodic = 0;
|
||||
}
|
||||
|
||||
int8_t min_momentum_mag()
|
||||
{
|
||||
int8_t min_mag = 127;
|
||||
for(uint8_t i = 0; i < sizeof(momentum)/sizeof(momentum[0]); ++i){
|
||||
int8_t mag = abs(momentum[i]);
|
||||
if(mag < min_mag){
|
||||
min_mag = mag;
|
||||
}
|
||||
}
|
||||
return min_mag;
|
||||
}
|
||||
|
||||
int enc_read(void) {
|
||||
if(0 != enc_count){
|
||||
int16_t ret = enc_count;
|
||||
int8_t s = (enc_count < 0) ? -1 : 1;
|
||||
int8_t momentum_mag = min_momentum_mag();
|
||||
if(momentum_mag >= 20){
|
||||
ret += s*40;
|
||||
}
|
||||
else if(momentum_mag >= 5){
|
||||
ret += s*(20 + momentum_mag)/(20 - momentum_mag);
|
||||
}
|
||||
enc_count = 0;
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
4
encoder.h
Normal file
4
encoder.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
void enc_setup(void);
|
||||
int enc_read(void);
|
@ -238,7 +238,7 @@ void displayText(char *text, int x1, int y1, int w, int h, int color, int backgr
|
||||
uint16_t height_out;
|
||||
tft.getTextBounds(text,x1,y1,&x1_out,&y1_out,&width_out,&height_out,w);
|
||||
x1 += (w - ( (int32_t)width_out + (x1_out-x1)))/2;
|
||||
y1 += (ubitx_font->yAdvance + h - ( (int32_t)height_out + (y1_out-y1)))/2;
|
||||
y1 += (ubitx_font->yAdvance + h - ( (int32_t)height_out))/2;
|
||||
displayRawText(text,x1,y1,w,color,background);
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ const SettingScreen_t ssLocalOsc PROGMEM = {
|
||||
SS_LOCAL_OSC_T,
|
||||
SS_LOCAL_OSC_A,
|
||||
1,
|
||||
875,
|
||||
50,
|
||||
ssLocalOscInitialize,
|
||||
ssLocalOscValidate,
|
||||
ssLocalOscChange,
|
||||
@ -254,7 +254,7 @@ const SettingScreen_t ssTone PROGMEM = {
|
||||
SS_CW_TONE_T,
|
||||
SS_CW_TONE_A,
|
||||
1,
|
||||
10,
|
||||
1,
|
||||
ssCwToneInitialize,
|
||||
ssCwToneValidate,
|
||||
ssCwToneChange,
|
||||
@ -289,7 +289,7 @@ const SettingScreen_t ssCwSwitchDelay PROGMEM = {
|
||||
SS_CW_SWITCH_T,
|
||||
SS_CW_SWITCH_A,
|
||||
1,
|
||||
100,
|
||||
10,
|
||||
ssCwSwitchDelayInitialize,
|
||||
ssCwSwitchDelayValidate,
|
||||
ssCwSwitchDelayChange,
|
||||
|
142
ubitx_ui.cpp
142
ubitx_ui.cpp
@ -553,148 +553,6 @@ void updateDisplay() {
|
||||
displayVFO(globalSettings.activeVfo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The A7 And A6 are purely analog lines on the Arduino Nano
|
||||
* These need to be pulled up externally using two 10 K resistors
|
||||
*
|
||||
* There are excellent pages on the Internet about how these encoders work
|
||||
* and how they should be used. We have elected to use the simplest way
|
||||
* to use these encoders without the complexity of interrupts etc to
|
||||
* keep it understandable.
|
||||
*
|
||||
* The enc_state returns a two-bit number such that each bit reflects the current
|
||||
* value of each of the two phases of the encoder
|
||||
*
|
||||
* The enc_read returns the number of net pulses counted over 50 msecs.
|
||||
* If the puluses are -ve, they were anti-clockwise, if they are +ve, the
|
||||
* were in the clockwise directions. Higher the pulses, greater the speed
|
||||
* 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;
|
||||
int enc_speed = 0;
|
||||
|
||||
long stop_by = millis() + 200;
|
||||
|
||||
while (millis() < stop_by) { // check if the previous state was stable
|
||||
newState = enc_state(); // Get current state
|
||||
|
||||
// if (newState != enc_prev_state)
|
||||
// active_delay(20);
|
||||
|
||||
if (enc_state() != newState || newState == enc_prev_state)
|
||||
continue;
|
||||
//these transitions point to the encoder being rotated anti-clockwise
|
||||
if ((enc_prev_state == 0 && newState == 2) ||
|
||||
(enc_prev_state == 2 && newState == 3) ||
|
||||
(enc_prev_state == 3 && newState == 1) ||
|
||||
(enc_prev_state == 1 && newState == 0)){
|
||||
result--;
|
||||
}
|
||||
//these transitions point o the enccoder being rotated clockwise
|
||||
if ((enc_prev_state == 0 && newState == 1) ||
|
||||
(enc_prev_state == 1 && newState == 3) ||
|
||||
(enc_prev_state == 3 && newState == 2) ||
|
||||
(enc_prev_state == 2 && newState == 0)){
|
||||
result++;
|
||||
}
|
||||
enc_prev_state = newState; // Record state for next pulse interpretation
|
||||
enc_speed++;
|
||||
active_delay(1);
|
||||
}
|
||||
//if (result)
|
||||
// Serial.println(result);
|
||||
return(result);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* SmittyHalibut's encoder handling, using interrupts. Should be quicker, smoother handling.
|
||||
*/
|
||||
int8_t 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) {
|
||||
int8_t ret = enc_count;
|
||||
enc_count = 0;
|
||||
return int(ret);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ritToggle(struct Button *button){
|
||||
if(!globalSettings.ritOn){
|
||||
ritEnable(GetActiveVfoFreq());
|
||||
|
Loading…
Reference in New Issue
Block a user