Fork of the espurna firmware for `mhsw` switches
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

161 lines
4.6 KiB

/*
ENCODER MODULE
Copyright (C) 2018-2019 by Xose Pérez <xose dot perez at gmail dot com>
*/
#include "encoder.h"
#if ENCODER_SUPPORT && (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE)
#include "light.h"
#include "libs/Encoder.h"
#include <vector>
struct encoder_t {
Encoder * encoder;
unsigned char button_pin;
unsigned char button_logic;
unsigned char button_mode;
unsigned char mode;
unsigned char channel1; // default
unsigned char channel2; // only if button defined and pressed
};
std::vector<encoder_t> _encoders;
unsigned long _encoder_min_delta = 1;
void _encoderConfigure() {
_encoder_min_delta = getSetting("encMinDelta", ENCODER_MINIMUM_DELTA);
if (!_encoder_min_delta) _encoder_min_delta = 1;
// no need to reload objects right now
if (_encoders.size()) return;
// Clean previous encoders and re-add them
for (auto& encoder : _encoders) {
delete encoder.encoder;
}
_encoders.clear();
// TODO: encEnable
// TODO: implement reloading without re-allocating objects
#if (ENCODER1_PIN1 != GPIO_NONE) && (ENCODER1_PIN2 != GPIO_NONE)
{
_encoders.push_back({
new Encoder(ENCODER1_PIN1, ENCODER1_PIN2),
ENCODER1_BUTTON_PIN, ENCODER1_BUTTON_LOGIC, ENCODER1_BUTTON_MODE, ENCODER1_MODE,
ENCODER1_CHANNEL1, ENCODER1_CHANNEL2
});
}
#endif
#if (ENCODER2_PIN1 != GPIO_NONE) && (ENCODER2_PIN2 != GPIO_NONE)
{
_encoders.push_back({
new Encoder(ENCODER2_PIN1, ENCODER2_PIN2),
ENCODER2_BUTTON_PIN, ENCODER2_BUTTON_LOGIC, ENCODER2_BUTTON_MODE, ENCODER2_MODE,
ENCODER2_CHANNEL1, ENCODER2_CHANNEL2
});
}
#endif
#if (ENCODER3_PIN1 != GPIO_NONE) && (ENCODER3_PIN2 != GPIO_NONE)
{
_encoders.push_back({
new Encoder(ENCODER3_PIN1, ENCODER3_PIN2),
ENCODER3_BUTTON_PIN, ENCODER3_BUTTON_LOGIC, ENCODER3_BUTTON_MODE, ENCODER3_MODE,
ENCODER3_CHANNEL1, ENCODER3_CHANNEL2
});
}
#endif
#if (ENCODER4_PIN1 != GPIO_NONE) && (ENCODER4_PIN2 != GPIO_NONE)
{
_encoders.push_back({
new Encoder(ENCODER4_PIN1, ENCODER4_PIN2),
ENCODER4_BUTTON_PIN, ENCODER4_BUTTON_LOGIC, ENCODER4_BUTTON_MODE, ENCODER4_MODE,
ENCODER4_CHANNEL1, ENCODER4_CHANNEL2
});
}
#endif
#if (ENCODER5_PIN1 != GPIO_NONE) && (ENCODER5_PIN2 != GPIO_NONE)
{
_encoders.push_back({
new Encoder(ENCODER5_PIN1, ENCODER5_PIN2),
ENCODER5_BUTTON_PIN, ENCODER5_BUTTON_LOGIC, ENCODER5_BUTTON_MODE, ENCODER5_MODE,
ENCODER5_CHANNEL1, ENCODER5_CHANNEL2
});
}
#endif
// TODO: manage buttons through debounceevent?
for (auto& encoder : _encoders) {
if (GPIO_NONE != encoder.button_pin) {
pinMode(encoder.button_pin, encoder.button_mode);
}
}
}
void _encoderLoop() {
// for each encoder, read delta (read()) and map button action
for (auto& encoder : _encoders) {
const auto delta = encoder.encoder->read();
encoder.encoder->write(0);
if ((0 == delta) || (_encoder_min_delta > abs(delta))) continue;
if (encoder.button_pin == GPIO_NONE) {
// if there is no button, the encoder drives CHANNEL1
lightChannelStep(encoder.channel1, delta);
} else {
// otherwise, use button based on encoder mode
bool pressed = (digitalRead(encoder.button_pin) != encoder.button_logic);
if (ENCODER_MODE_CHANNEL == encoder.mode) {
// the button controls what channel we are changing
lightChannelStep(pressed ? encoder.channel2 : encoder.channel1, delta);
} if (ENCODER_MODE_RATIO == encoder.mode) {
// the button controls if we are changing the channel ratio or the overall brightness
if (pressed) {
lightChannelStep(encoder.channel1, delta);
lightChannelStep(encoder.channel2, -delta);
} else {
lightBrightnessStep(delta);
}
}
}
lightUpdate();
}
}
// -----------------------------------------------------------------------------
void encoderSetup() {
// Configure encoders
_encoderConfigure();
// Main callbacks
espurnaRegisterLoop(_encoderLoop);
espurnaRegisterReload(_encoderConfigure);
DEBUG_MSG_P(PSTR("[ENCODER] Number of encoders: %u\n"), _encoders.size());
}
#endif // ENCODER_SUPPORT && (LIGHT_PROVIDER != LIGHT_PROVIDER_NONE)