mirror of
https://github.com/meshcore-dev/MeshCore.git
synced 2026-07-21 11:12:08 +00:00
Add a rotary encoder
This commit is contained in:
@@ -750,6 +750,16 @@ void UITask::loop() {
|
||||
c = handleTripleClick(KEY_SELECT);
|
||||
}
|
||||
#endif
|
||||
#if defined(UI_HAS_ROTARY_INPUT)
|
||||
if (c == 0) {
|
||||
RotaryInputEvent ev = rotary_input.poll();
|
||||
if (ev == RotaryInputEvent::Next) {
|
||||
c = checkDisplayOn(KEY_NEXT);
|
||||
} else if (ev == RotaryInputEvent::Prev) {
|
||||
c = checkDisplayOn(KEY_PREV);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if defined(PIN_USER_BTN_ANA)
|
||||
if (abs(millis() - _analogue_pin_read_millis) > 10) {
|
||||
int ev = analog_btn.check();
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
enum class RotaryInputEvent : uint8_t {
|
||||
None,
|
||||
Next,
|
||||
Prev,
|
||||
};
|
||||
|
||||
class RotaryInput {
|
||||
public:
|
||||
virtual ~RotaryInput() = default;
|
||||
|
||||
virtual bool begin() = 0;
|
||||
virtual RotaryInputEvent poll() = 0;
|
||||
virtual bool isReady() const = 0;
|
||||
};
|
||||
@@ -1,4 +1,14 @@
|
||||
#include "HeltecRC32Board.h"
|
||||
#if defined(UI_HAS_ROTARY_INPUT)
|
||||
#include "HeltecRC32RotaryInput.h"
|
||||
#endif
|
||||
|
||||
#if defined(UI_HAS_ROTARY_INPUT)
|
||||
RotaryInput& HeltecRC32Board::rotaryInput() {
|
||||
static HeltecRC32RotaryInput input(&periph_power);
|
||||
return input;
|
||||
}
|
||||
#endif
|
||||
|
||||
void HeltecRC32Board::begin() {
|
||||
ESP32Board::begin();
|
||||
@@ -17,7 +27,7 @@ void HeltecRC32Board::begin() {
|
||||
#endif
|
||||
|
||||
periph_power.begin();
|
||||
vext_power.begin();
|
||||
periph_power.claim();
|
||||
|
||||
esp_reset_reason_t reason = esp_reset_reason();
|
||||
if (reason == ESP_RST_DEEPSLEEP) {
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <driver/rtc_io.h>
|
||||
#include <helpers/ESP32Board.h>
|
||||
#include <helpers/RefCountedDigitalPin.h>
|
||||
#if defined(UI_HAS_ROTARY_INPUT)
|
||||
#include <helpers/ui/RotaryInput.h>
|
||||
#endif
|
||||
|
||||
#ifndef ADC_MULTIPLIER
|
||||
#define ADC_MULTIPLIER 4.9f
|
||||
@@ -15,13 +18,13 @@ protected:
|
||||
|
||||
public:
|
||||
RefCountedDigitalPin periph_power;
|
||||
RefCountedDigitalPin vext_power;
|
||||
|
||||
HeltecRC32Board() :
|
||||
periph_power(SENSOR_POWER_CTRL_PIN, SENSOR_POWER_ON),
|
||||
vext_power(PIN_VEXT_EN, PIN_VEXT_EN_ACTIVE) { }
|
||||
HeltecRC32Board() : periph_power(SENSOR_POWER_CTRL_PIN, SENSOR_POWER_ON){}
|
||||
|
||||
void begin();
|
||||
#if defined(UI_HAS_ROTARY_INPUT)
|
||||
RotaryInput& rotaryInput();
|
||||
#endif
|
||||
void onBeforeTransmit() override;
|
||||
void onAfterTransmit() override;
|
||||
void powerOff() override;
|
||||
|
||||
@@ -0,0 +1,122 @@
|
||||
#include "HeltecRC32RotaryInput.h"
|
||||
|
||||
#include <Wire.h>
|
||||
|
||||
namespace {
|
||||
constexpr uint8_t TCA6408_ADDR = 0x20;
|
||||
constexpr uint8_t TCA6408_INPUT_REG = 0x00;
|
||||
constexpr uint8_t TCA6408_POLARITY_REG = 0x02;
|
||||
constexpr uint8_t TCA6408_CONFIG_REG = 0x03;
|
||||
constexpr uint8_t TCA6408_ROTARY_A_MASK = 0x01;
|
||||
constexpr uint8_t TCA6408_ROTARY_B_MASK = 0x02;
|
||||
constexpr uint8_t TCA6408_ROTARY_MASK = TCA6408_ROTARY_A_MASK | TCA6408_ROTARY_B_MASK;
|
||||
constexpr uint32_t TCA6408_DEBOUNCE_MS = 5;
|
||||
}
|
||||
|
||||
bool HeltecRC32RotaryInput::begin() {
|
||||
initialized = true;
|
||||
ready = false;
|
||||
input_state = TCA6408_ROTARY_MASK;
|
||||
active_low_phase = false;
|
||||
|
||||
if (periph_power && !power_claimed) {
|
||||
periph_power->claim();
|
||||
power_claimed = true;
|
||||
delay(12);
|
||||
}
|
||||
|
||||
if (!writeRegister(TCA6408_POLARITY_REG, 0x00) || !writeRegister(TCA6408_CONFIG_REG, 0xFF)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t state = 0;
|
||||
if (!readInput(state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
input_state = state & TCA6408_ROTARY_MASK;
|
||||
ready = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
RotaryInputEvent HeltecRC32RotaryInput::poll() {
|
||||
if (!initialized) {
|
||||
begin();
|
||||
return RotaryInputEvent::None;
|
||||
}
|
||||
|
||||
if (!ready) {
|
||||
return RotaryInputEvent::None;
|
||||
}
|
||||
|
||||
uint8_t new_state = 0;
|
||||
if (!readInput(new_state)) {
|
||||
return RotaryInputEvent::None;
|
||||
}
|
||||
|
||||
new_state &= TCA6408_ROTARY_MASK;
|
||||
RotaryInputEvent event = handleTransition(new_state);
|
||||
input_state = new_state;
|
||||
return event;
|
||||
}
|
||||
|
||||
bool HeltecRC32RotaryInput::writeRegister(uint8_t reg, uint8_t value) {
|
||||
Wire.beginTransmission(TCA6408_ADDR);
|
||||
Wire.write(reg);
|
||||
Wire.write(value);
|
||||
return Wire.endTransmission() == 0;
|
||||
}
|
||||
|
||||
bool HeltecRC32RotaryInput::readInput(uint8_t& value) {
|
||||
Wire.beginTransmission(TCA6408_ADDR);
|
||||
Wire.write(TCA6408_INPUT_REG);
|
||||
if (Wire.endTransmission(false) != 0) {
|
||||
return false;
|
||||
}
|
||||
if (Wire.requestFrom(TCA6408_ADDR, static_cast<uint8_t>(1)) != 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
value = Wire.read();
|
||||
return true;
|
||||
}
|
||||
|
||||
RotaryInputEvent HeltecRC32RotaryInput::handleTransition(uint8_t newState) {
|
||||
uint8_t changed = (input_state ^ newState) & TCA6408_ROTARY_MASK;
|
||||
RotaryInputEvent event = RotaryInputEvent::None;
|
||||
bool a_low = (newState & TCA6408_ROTARY_A_MASK) == 0;
|
||||
bool b_low = (newState & TCA6408_ROTARY_B_MASK) == 0;
|
||||
|
||||
if (!a_low && !b_low) {
|
||||
active_low_phase = false;
|
||||
}
|
||||
|
||||
if (!active_low_phase && (changed & TCA6408_ROTARY_A_MASK) && a_low && !b_low) {
|
||||
event = RotaryInputEvent::Prev;
|
||||
active_low_phase = true;
|
||||
} else if (!active_low_phase && (changed & TCA6408_ROTARY_B_MASK) && b_low && !a_low) {
|
||||
event = RotaryInputEvent::Next;
|
||||
active_low_phase = true;
|
||||
}
|
||||
|
||||
if (event == RotaryInputEvent::None && !active_low_phase && (changed & TCA6408_ROTARY_A_MASK)) {
|
||||
bool a_rising = (newState & TCA6408_ROTARY_A_MASK) != 0;
|
||||
if (a_rising && b_low) {
|
||||
event = RotaryInputEvent::Prev;
|
||||
}
|
||||
}
|
||||
|
||||
if (event == RotaryInputEvent::None && !active_low_phase && (changed & TCA6408_ROTARY_B_MASK)) {
|
||||
bool b_rising = (newState & TCA6408_ROTARY_B_MASK) != 0;
|
||||
if (b_rising && a_low) {
|
||||
event = RotaryInputEvent::Next;
|
||||
}
|
||||
}
|
||||
|
||||
if (event == RotaryInputEvent::None || (millis() - last_event_ms) < TCA6408_DEBOUNCE_MS) {
|
||||
return RotaryInputEvent::None;
|
||||
}
|
||||
|
||||
last_event_ms = millis();
|
||||
return event;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include <helpers/RefCountedDigitalPin.h>
|
||||
#include <helpers/ui/RotaryInput.h>
|
||||
|
||||
class HeltecRC32RotaryInput : public RotaryInput {
|
||||
public:
|
||||
explicit HeltecRC32RotaryInput(RefCountedDigitalPin* periphPower = nullptr) : periph_power(periphPower) { }
|
||||
|
||||
bool begin() override;
|
||||
RotaryInputEvent poll() override;
|
||||
bool isReady() const override { return ready; }
|
||||
|
||||
private:
|
||||
bool writeRegister(uint8_t reg, uint8_t value);
|
||||
bool readInput(uint8_t& value);
|
||||
RotaryInputEvent handleTransition(uint8_t newState);
|
||||
|
||||
uint8_t input_state = 0x03;
|
||||
uint32_t last_event_ms = 0;
|
||||
bool ready = false;
|
||||
bool initialized = false;
|
||||
bool power_claimed = false;
|
||||
bool active_low_phase = false;
|
||||
RefCountedDigitalPin* periph_power = nullptr;
|
||||
};
|
||||
@@ -23,8 +23,6 @@ build_flags =
|
||||
-D PIN_USER_BTN=0
|
||||
-D PIN_BOARD_SDA=21
|
||||
-D PIN_BOARD_SCL=18
|
||||
-D PIN_VEXT_EN=3
|
||||
-D PIN_VEXT_EN_ACTIVE=HIGH
|
||||
-D SENSOR_POWER_CTRL_PIN=46
|
||||
-D SENSOR_POWER_ON=HIGH
|
||||
-D SENSOR_RST_PIN=2
|
||||
@@ -270,6 +268,7 @@ extends = Heltec_RC32_with_display
|
||||
build_flags =
|
||||
${Heltec_RC32_with_display.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D UI_HAS_ROTARY_INPUT
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
build_src_filter = ${Heltec_RC32_with_display.build_src_filter}
|
||||
@@ -287,6 +286,7 @@ extends = Heltec_RC32_with_display
|
||||
build_flags =
|
||||
${Heltec_RC32_with_display.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D UI_HAS_ROTARY_INPUT
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D BLE_PIN_CODE=123456
|
||||
@@ -308,6 +308,7 @@ extends = Heltec_RC32_with_display
|
||||
build_flags =
|
||||
${Heltec_RC32_with_display.build_flags}
|
||||
-I examples/companion_radio/ui-new
|
||||
-D UI_HAS_ROTARY_INPUT
|
||||
-D MAX_CONTACTS=350
|
||||
-D MAX_GROUP_CHANNELS=40
|
||||
-D WIFI_DEBUG_LOGGING=1
|
||||
|
||||
@@ -17,7 +17,7 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
|
||||
#if ENV_INCLUDE_GPS
|
||||
#include <helpers/sensors/MicroNMEALocationProvider.h>
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, PIN_GPS_RESET, PIN_GPS_EN, &board.periph_power);
|
||||
MicroNMEALocationProvider nmea = MicroNMEALocationProvider(Serial1, &rtc_clock, PIN_GPS_RESET, PIN_GPS_EN);
|
||||
EnvironmentSensorManager sensors = EnvironmentSensorManager(nmea);
|
||||
#else
|
||||
EnvironmentSensorManager sensors;
|
||||
@@ -26,6 +26,9 @@ AutoDiscoverRTCClock rtc_clock(fallback_clock);
|
||||
#ifdef DISPLAY_CLASS
|
||||
DISPLAY_CLASS display;
|
||||
MomentaryButton user_btn(PIN_USER_BTN, 1000, true);
|
||||
#if defined(UI_HAS_ROTARY_INPUT)
|
||||
RotaryInput& rotary_input = board.rotaryInput();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool radio_init() {
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
|
||||
#ifdef DISPLAY_CLASS
|
||||
#include <helpers/ui/MomentaryButton.h>
|
||||
#if defined(UI_HAS_ROTARY_INPUT)
|
||||
#include <helpers/ui/RotaryInput.h>
|
||||
#endif
|
||||
#ifdef HELTEC_RC32_WITH_DISPLAY
|
||||
#include <helpers/ui/NV3001BDisplay.h>
|
||||
#else
|
||||
@@ -25,6 +28,9 @@ extern EnvironmentSensorManager sensors;
|
||||
#ifdef DISPLAY_CLASS
|
||||
extern DISPLAY_CLASS display;
|
||||
extern MomentaryButton user_btn;
|
||||
#if defined(UI_HAS_ROTARY_INPUT)
|
||||
extern RotaryInput& rotary_input;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
bool radio_init();
|
||||
|
||||
@@ -22,9 +22,6 @@
|
||||
#define SENSOR_POWER_ON HIGH
|
||||
#define PERIPHERAL_WARMUP_MS 100
|
||||
|
||||
#define VEXT_ENABLE 3
|
||||
#define VEXT_ON_VALUE HIGH
|
||||
|
||||
#define USE_SX1262
|
||||
#define LORA_SCK 11
|
||||
#define LORA_MISO 13
|
||||
|
||||
Reference in New Issue
Block a user