mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
Encoder rotation rate multiplier support (#1876)
This commit is contained in:
parent
367479d163
commit
46d9e02684
@ -3,6 +3,7 @@
|
|||||||
* Copyright (C) 2016 Furrtek
|
* Copyright (C) 2016 Furrtek
|
||||||
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
|
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
|
||||||
* Copyright (C) 2023 Kyle Reed
|
* Copyright (C) 2023 Kyle Reed
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
* Copyleft (ɔ) 2024 zxkmm under GPL license
|
* Copyleft (ɔ) 2024 zxkmm under GPL license
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
@ -680,13 +681,16 @@ void SetQRCodeView::focus() {
|
|||||||
SetEncoderDialView::SetEncoderDialView(NavigationView& nav) {
|
SetEncoderDialView::SetEncoderDialView(NavigationView& nav) {
|
||||||
add_children({&labels,
|
add_children({&labels,
|
||||||
&field_encoder_dial_sensitivity,
|
&field_encoder_dial_sensitivity,
|
||||||
|
&field_encoder_rate_multiplier,
|
||||||
&button_save,
|
&button_save,
|
||||||
&button_cancel});
|
&button_cancel});
|
||||||
|
|
||||||
field_encoder_dial_sensitivity.set_by_value(pmem::config_encoder_dial_sensitivity());
|
field_encoder_dial_sensitivity.set_by_value(pmem::encoder_dial_sensitivity());
|
||||||
|
field_encoder_rate_multiplier.set_value(pmem::encoder_rate_multiplier());
|
||||||
|
|
||||||
button_save.on_select = [&nav, this](Button&) {
|
button_save.on_select = [&nav, this](Button&) {
|
||||||
pmem::set_encoder_dial_sensitivity(field_encoder_dial_sensitivity.selected_index_value());
|
pmem::set_encoder_dial_sensitivity(field_encoder_dial_sensitivity.selected_index_value());
|
||||||
|
pmem::set_encoder_rate_multiplier(field_encoder_rate_multiplier.value());
|
||||||
nav.pop();
|
nav.pop();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
* Copyright (C) 2016 Furrtek
|
* Copyright (C) 2016 Furrtek
|
||||||
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
|
* Copyright (C) 2023 gullradriel, Nilorea Studio Inc.
|
||||||
* Copyright (C) 2023 Kyle Reed
|
* Copyright (C) 2023 Kyle Reed
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
* Copyleft (ɔ) 2024 zxkmm under GPL license
|
* Copyleft (ɔ) 2024 zxkmm under GPL license
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
@ -555,6 +556,7 @@ class SetQRCodeView : public View {
|
|||||||
};
|
};
|
||||||
|
|
||||||
using portapack::persistent_memory::encoder_dial_sensitivity;
|
using portapack::persistent_memory::encoder_dial_sensitivity;
|
||||||
|
using portapack::persistent_memory::encoder_rate_multiplier;
|
||||||
|
|
||||||
class SetEncoderDialView : public View {
|
class SetEncoderDialView : public View {
|
||||||
public:
|
public:
|
||||||
@ -566,18 +568,30 @@ class SetEncoderDialView : public View {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Labels labels{
|
Labels labels{
|
||||||
{{1 * 8, 1 * 16}, "Adjusts how many steps to", Color::light_grey()},
|
{{1 * 8, 1 * 16}, "Adjusts sensitivity to dial", Color::light_grey()},
|
||||||
{{1 * 8, 2 * 16}, "change the encoder value.", Color::light_grey()},
|
{{1 * 8, 2 * 16}, "rotation position (number of", Color::light_grey()},
|
||||||
{{2 * 8, 4 * 16}, "Dial sensitivity:", Color::light_grey()},
|
{{1 * 8, 3 * 16}, "steps per full rotation):", Color::light_grey()},
|
||||||
|
{{2 * 8, 5 * 16}, "Dial sensitivity:", Color::light_grey()},
|
||||||
|
{{1 * 8, 8 * 16}, "Adjusts sensitivity to dial", Color::light_grey()},
|
||||||
|
{{1 * 8, 9 * 16}, "rotation rate (default 1", Color::light_grey()},
|
||||||
|
{{1 * 8, 10 * 16}, "means no rate dependency):", Color::light_grey()},
|
||||||
|
{{3 * 8, 12 * 16}, "Rate multiplier:", Color::light_grey()},
|
||||||
};
|
};
|
||||||
|
|
||||||
OptionsField field_encoder_dial_sensitivity{
|
OptionsField field_encoder_dial_sensitivity{
|
||||||
{20 * 8, 4 * 16},
|
{20 * 8, 5 * 16},
|
||||||
6,
|
6,
|
||||||
{{"LOW", encoder_dial_sensitivity::DIAL_SENSITIVITY_LOW},
|
{{"LOW", encoder_dial_sensitivity::DIAL_SENSITIVITY_LOW},
|
||||||
{"NORMAL", encoder_dial_sensitivity::DIAL_SENSITIVITY_NORMAL},
|
{"NORMAL", encoder_dial_sensitivity::DIAL_SENSITIVITY_NORMAL},
|
||||||
{"HIGH", encoder_dial_sensitivity::DIAL_SENSITIVITY_HIGH}}};
|
{"HIGH", encoder_dial_sensitivity::DIAL_SENSITIVITY_HIGH}}};
|
||||||
|
|
||||||
|
NumberField field_encoder_rate_multiplier{
|
||||||
|
{20 * 8, 12 * 16},
|
||||||
|
2,
|
||||||
|
{1, 10},
|
||||||
|
1,
|
||||||
|
' '};
|
||||||
|
|
||||||
Button button_save{
|
Button button_save{
|
||||||
{2 * 8, 16 * 16, 12 * 8, 32},
|
{2 * 8, 16 * 16, 12 * 8, 32},
|
||||||
"Save"};
|
"Save"};
|
||||||
|
@ -24,6 +24,9 @@
|
|||||||
|
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include "portapack.hpp"
|
||||||
|
#include "portapack_persistent_memory.hpp"
|
||||||
|
|
||||||
uint8_t Debounce::state() {
|
uint8_t Debounce::state() {
|
||||||
uint8_t v = state_to_report_;
|
uint8_t v = state_to_report_;
|
||||||
simulated_pulse_ = false;
|
simulated_pulse_ = false;
|
||||||
@ -154,6 +157,10 @@ uint8_t EncoderDebounce::state() {
|
|||||||
return state_;
|
return state_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t EncoderDebounce::rotation_rate() {
|
||||||
|
return last_rotation_rate_;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns TRUE if encoder position phase bits changed (after debouncing)
|
// Returns TRUE if encoder position phase bits changed (after debouncing)
|
||||||
bool EncoderDebounce::feed(const uint8_t phase_bits) {
|
bool EncoderDebounce::feed(const uint8_t phase_bits) {
|
||||||
history_ = (history_ << 2) | phase_bits;
|
history_ = (history_ << 2) | phase_bits;
|
||||||
@ -164,14 +171,21 @@ bool EncoderDebounce::feed(const uint8_t phase_bits) {
|
|||||||
// But, checking for equal seems to cause issues with at least 1 user's encoder, so we're treating the input
|
// But, checking for equal seems to cause issues with at least 1 user's encoder, so we're treating the input
|
||||||
// as "stable" if at least ONE input bit is consistent for 4 ticks...
|
// as "stable" if at least ONE input bit is consistent for 4 ticks...
|
||||||
uint8_t diff = (history_ ^ expected_stable_history);
|
uint8_t diff = (history_ ^ expected_stable_history);
|
||||||
if ((diff == 0) || ((diff & 0b01010101) == 0) || ((diff & 0b10101010) == 0)) {
|
if (((diff & 0b01010101) == 0) || ((diff & 0b10101010) == 0)) {
|
||||||
// Has the debounced input value changed?
|
// Has the debounced input value changed?
|
||||||
if (state_ != phase_bits) {
|
if (state_ != phase_bits) {
|
||||||
state_ = phase_bits;
|
state_ = phase_bits;
|
||||||
|
|
||||||
|
// Rate multiplier is for larger delta increments when dial is rotated rapidly.
|
||||||
|
last_rotation_rate_ = rotation_rate_downcounter_;
|
||||||
|
rotation_rate_downcounter_ = portapack::persistent_memory::encoder_rate_multiplier();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unstable input, or no change
|
// Unstable input, or no change.
|
||||||
|
// Decrement rotation rate detector once per timer tick.
|
||||||
|
if (rotation_rate_downcounter_ > 1)
|
||||||
|
rotation_rate_downcounter_--;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -70,10 +71,15 @@ class EncoderDebounce {
|
|||||||
|
|
||||||
uint8_t state(); // returns debounced phase bits from encoder
|
uint8_t state(); // returns debounced phase bits from encoder
|
||||||
|
|
||||||
|
uint8_t rotation_rate(); // returns last rotation rate
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t history_{0}; // shift register of previous reads from encoder
|
uint8_t history_{0}; // shift register of previous reads from encoder
|
||||||
|
|
||||||
uint8_t state_{0}; // actual encoder output state (after debounce logic)
|
uint8_t state_{0}; // actual encoder output state (after debounce logic)
|
||||||
|
|
||||||
|
uint8_t last_rotation_rate_{1};
|
||||||
|
uint8_t rotation_rate_downcounter_{1}; // down-counter to estimate rotation speed
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /*__DEBOUNCE_H__*/
|
#endif /*__DEBOUNCE_H__*/
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -63,7 +64,7 @@ int_fast8_t Encoder::update(const uint_fast8_t phase_bits) {
|
|||||||
|
|
||||||
// Require 2 state changes in same direction to register movement -- for additional level of contact switch debouncing
|
// Require 2 state changes in same direction to register movement -- for additional level of contact switch debouncing
|
||||||
if (direction == prev_direction) {
|
if (direction == prev_direction) {
|
||||||
if ((sensitivity_map[portapack::persistent_memory::config_encoder_dial_sensitivity()] & (1 << state)) == 0)
|
if ((sensitivity_map[portapack::persistent_memory::encoder_dial_sensitivity()] & (1 << state)) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
return direction;
|
return direction;
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2014 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -166,7 +167,7 @@ static bool encoder_update(const uint8_t raw) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool encoder_read() {
|
static bool encoder_read() {
|
||||||
auto delta = encoder.update(encoder_debounce.state());
|
auto delta = encoder.update(encoder_debounce.state()) * encoder_debounce.rotation_rate();
|
||||||
|
|
||||||
if (injected_encoder > 0) {
|
if (injected_encoder > 0) {
|
||||||
if (injected_encoder == 1) delta = -1;
|
if (injected_encoder == 1) delta = -1;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
* Copyright (C) 2016 Furrtek
|
* Copyright (C) 2016 Furrtek
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -226,7 +227,9 @@ struct data_t {
|
|||||||
|
|
||||||
// fake brightness level (not switch, switch is in another place)
|
// fake brightness level (not switch, switch is in another place)
|
||||||
uint16_t fake_brightness_level : 4;
|
uint16_t fake_brightness_level : 4;
|
||||||
uint16_t UNUSED_8 : 8;
|
|
||||||
|
// Encoder rotation rate multiplier for larger increments when rotated rapidly
|
||||||
|
uint16_t encoder_rate_multiplier : 8;
|
||||||
|
|
||||||
// Headphone volume in centibels.
|
// Headphone volume in centibels.
|
||||||
int16_t headphone_volume_cb;
|
int16_t headphone_volume_cb;
|
||||||
@ -292,7 +295,7 @@ struct data_t {
|
|||||||
|
|
||||||
encoder_dial_sensitivity(DIAL_SENSITIVITY_NORMAL),
|
encoder_dial_sensitivity(DIAL_SENSITIVITY_NORMAL),
|
||||||
fake_brightness_level(BRIGHTNESS_50),
|
fake_brightness_level(BRIGHTNESS_50),
|
||||||
UNUSED_8(0),
|
encoder_rate_multiplier(1),
|
||||||
headphone_volume_cb(-600),
|
headphone_volume_cb(-600),
|
||||||
misc_config(),
|
misc_config(),
|
||||||
ui_config2(),
|
ui_config2(),
|
||||||
@ -399,6 +402,7 @@ void defaults() {
|
|||||||
cached_backup_ram = backup_ram_t();
|
cached_backup_ram = backup_ram_t();
|
||||||
|
|
||||||
// If the desired default is 0/false, then no need to set it here (buffer is initialized to 0)
|
// If the desired default is 0/false, then no need to set it here (buffer is initialized to 0)
|
||||||
|
// NB: This function is only called when pmem is reset; also see firmware upgrade handling below.
|
||||||
set_config_backlight_timer(backlight_config_t{});
|
set_config_backlight_timer(backlight_config_t{});
|
||||||
set_config_splash(true);
|
set_config_splash(true);
|
||||||
set_config_disable_external_tcxo(false);
|
set_config_disable_external_tcxo(false);
|
||||||
@ -449,9 +453,9 @@ void init() {
|
|||||||
}
|
}
|
||||||
set_config_mode_storage_direct(config_mode_backup);
|
set_config_mode_storage_direct(config_mode_backup);
|
||||||
|
|
||||||
// Firmware upgrade handling - adjust newly defined fields where 0 is an unwanted default
|
// Firmware upgrade handling - adjust newly defined fields where 0 is an invalid default
|
||||||
if (fake_brightness_level() == 0)
|
if (fake_brightness_level() == 0) set_fake_brightness_level(BRIGHTNESS_50);
|
||||||
set_fake_brightness_level(BRIGHTNESS_50);
|
if (encoder_rate_multiplier() == 0) set_encoder_rate_multiplier(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void persist() {
|
void persist() {
|
||||||
@ -976,13 +980,18 @@ void set_config_freq_rx_correction(uint32_t v) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Rotary encoder dial settings
|
// Rotary encoder dial settings
|
||||||
|
uint8_t encoder_dial_sensitivity() {
|
||||||
uint8_t config_encoder_dial_sensitivity() {
|
|
||||||
return data->encoder_dial_sensitivity;
|
return data->encoder_dial_sensitivity;
|
||||||
}
|
}
|
||||||
void set_encoder_dial_sensitivity(uint8_t v) {
|
void set_encoder_dial_sensitivity(uint8_t v) {
|
||||||
data->encoder_dial_sensitivity = v;
|
data->encoder_dial_sensitivity = v;
|
||||||
}
|
}
|
||||||
|
uint8_t encoder_rate_multiplier() {
|
||||||
|
return data->encoder_rate_multiplier;
|
||||||
|
}
|
||||||
|
void set_encoder_rate_multiplier(uint8_t v) {
|
||||||
|
data->encoder_rate_multiplier = v;
|
||||||
|
}
|
||||||
|
|
||||||
// Recovery mode magic value storage
|
// Recovery mode magic value storage
|
||||||
static data_t* data_direct_access = reinterpret_cast<data_t*>(memory::map::backup_ram.base());
|
static data_t* data_direct_access = reinterpret_cast<data_t*>(memory::map::backup_ram.base());
|
||||||
@ -1137,7 +1146,7 @@ bool debug_dump() {
|
|||||||
pmem_dump_file.write_line("frequency_rx_correction: " + to_string_dec_uint(data->frequency_rx_correction));
|
pmem_dump_file.write_line("frequency_rx_correction: " + to_string_dec_uint(data->frequency_rx_correction));
|
||||||
pmem_dump_file.write_line("frequency_tx_correction: " + to_string_dec_uint(data->frequency_tx_correction));
|
pmem_dump_file.write_line("frequency_tx_correction: " + to_string_dec_uint(data->frequency_tx_correction));
|
||||||
pmem_dump_file.write_line("encoder_dial_sensitivity: " + to_string_dec_uint(data->encoder_dial_sensitivity));
|
pmem_dump_file.write_line("encoder_dial_sensitivity: " + to_string_dec_uint(data->encoder_dial_sensitivity));
|
||||||
// pmem_dump_file.write_line("UNUSED_8: " + to_string_dec_uint(data->UNUSED_8));
|
pmem_dump_file.write_line("encoder_rate_multiplier: " + to_string_dec_uint(data->encoder_rate_multiplier));
|
||||||
pmem_dump_file.write_line("headphone_volume_cb: " + to_string_dec_int(data->headphone_volume_cb));
|
pmem_dump_file.write_line("headphone_volume_cb: " + to_string_dec_int(data->headphone_volume_cb));
|
||||||
pmem_dump_file.write_line("config_mode_storage: 0x" + to_string_hex(data->config_mode_storage, 8));
|
pmem_dump_file.write_line("config_mode_storage: 0x" + to_string_hex(data->config_mode_storage, 8));
|
||||||
pmem_dump_file.write_line("dst_config: 0x" + to_string_hex((uint32_t)data->dst_config.v, 8));
|
pmem_dump_file.write_line("dst_config: 0x" + to_string_hex((uint32_t)data->dst_config.v, 8));
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
* Copyright (C) 2015 Jared Boone, ShareBrained Technology, Inc.
|
||||||
* Copyright (C) 2016 Furrtek
|
* Copyright (C) 2016 Furrtek
|
||||||
|
* Copyright (C) 2024 Mark Thompson
|
||||||
*
|
*
|
||||||
* This file is part of PortaPack.
|
* This file is part of PortaPack.
|
||||||
*
|
*
|
||||||
@ -246,8 +247,11 @@ void set_config_audio_mute(bool v);
|
|||||||
void set_config_speaker_disable(bool v);
|
void set_config_speaker_disable(bool v);
|
||||||
void set_config_backlight_timer(const backlight_config_t& new_value);
|
void set_config_backlight_timer(const backlight_config_t& new_value);
|
||||||
void set_disable_touchscreen(bool v);
|
void set_disable_touchscreen(bool v);
|
||||||
uint8_t config_encoder_dial_sensitivity();
|
|
||||||
|
uint8_t encoder_dial_sensitivity();
|
||||||
void set_encoder_dial_sensitivity(uint8_t v);
|
void set_encoder_dial_sensitivity(uint8_t v);
|
||||||
|
uint8_t encoder_rate_multiplier();
|
||||||
|
void set_encoder_rate_multiplier(uint8_t v);
|
||||||
|
|
||||||
uint32_t config_mode_storage_direct();
|
uint32_t config_mode_storage_direct();
|
||||||
void set_config_mode_storage_direct(uint32_t v);
|
void set_config_mode_storage_direct(uint32_t v);
|
||||||
|
Loading…
Reference in New Issue
Block a user