Use hasp_update_value_t to dispatch normalized value updates

This commit is contained in:
fvanroie 2021-05-12 04:29:05 +02:00
parent 5961ce87de
commit 7b03c0ae83
7 changed files with 168 additions and 229 deletions

View File

@ -429,47 +429,20 @@ void dispatch_config(const char* topic, const char* payload)
#endif // HASP_USE_CONFIG #endif // HASP_USE_CONFIG
/********************************************** Output States ******************************************/ /********************************************** Output States ******************************************/
/*
static inline void dispatch_state_msg(const __FlashStringHelper* subtopic, const char* payload) void dispatch_normalized_group_values(hasp_update_value_t& value)
{ {
if(value.group == 0) return;
}*/ LOG_VERBOSE(TAG_MSGR, F("GROUP %d value %d (%d-%d)"), value.group, value.val, value.min, value.max);
// void dispatch_group_onoff(uint8_t groupid, uint16_t eventid, lv_obj_t * obj)
// {
// if((eventid == HASP_EVENT_LONG) || (eventid == HASP_EVENT_HOLD)) return; // don't send repeat events
// if(groupid >= 0) {
// bool state = Parser::get_event_state(eventid);
// gpio_set_group_onoff(groupid, state);
// object_set_normalized_group_value(groupid, eventid, obj);
// }
// char payload[8];
// Parser::get_event_name(eventid, payload, sizeof(payload));
// // dispatch_output_group_state(groupid, payload);
// }
// void dispatch_group_value(uint8_t groupid, int16_t state, lv_obj_t * obj)
// {
// if(groupid >= 0) {
// gpio_set_group_value(groupid, state);
// object_set_normalized_group_value(groupid, state, obj);
// }
// char payload[8];
// // dispatch_output_group_state(groupid, payload);
// }
void dispatch_normalized_group_values(uint8_t groupid, lv_obj_t* obj, int16_t val, int16_t min, int16_t max)
{
if(groupid == 0) return;
LOG_VERBOSE(TAG_MSGR, F("GROUP %d value %d (%d-%d)"), groupid, val, min, max);
#if HASP_USE_GPIO > 0 #if HASP_USE_GPIO > 0
gpio_set_normalized_group_values(groupid, val, min, max); // Update GPIO states gpio_set_normalized_group_values(value); // Update GPIO states first
#endif
object_set_normalized_group_values(value); // Update onsreen objects except originating obj
#if HASP_USE_GPIO > 0
gpio_output_group_values(value.group); // Output new gpio values
#endif #endif
object_set_normalized_group_values(groupid, obj, val, min, max); // Update onsreen objects
} }
/********************************************** Native Commands ****************************************/ /********************************************** Native Commands ****************************************/

View File

@ -71,7 +71,7 @@ void dispatch_wakeup(const char*, const char*);
void dispatch_gpio_input_event(uint8_t pin, uint8_t group, uint8_t eventid); void dispatch_gpio_input_event(uint8_t pin, uint8_t group, uint8_t eventid);
void dispatch_output_pin_value(uint8_t pin, uint16_t val); void dispatch_output_pin_value(uint8_t pin, uint16_t val);
void dispatch_normalized_group_values(uint8_t groupid, lv_obj_t* obj, int16_t val, int16_t min, int16_t max); void dispatch_normalized_group_values(hasp_update_value_t& value);
void dispatch_state_subtopic(const char* subtopic, const char* payload); void dispatch_state_subtopic(const char* subtopic, const char* payload);

View File

@ -239,6 +239,18 @@ static void event_object_selection_changed(lv_obj_t* obj, uint8_t eventid, int16
// ##################### Event Handlers ######################################################## // ##################### Event Handlers ########################################################
static inline void event_update_group(uint8_t group, lv_obj_t* obj, int32_t val, int32_t min, int32_t max)
{
hasp_update_value_t value = {
.min = min,
.max = max,
.val = val,
.obj = obj,
.group = group,
};
dispatch_normalized_group_values(value);
}
#if HASP_USE_GPIO > 0 #if HASP_USE_GPIO > 0
void event_gpio_input(uint8_t pin, uint8_t group, uint8_t eventid) void event_gpio_input(uint8_t pin, uint8_t group, uint8_t eventid)
{ {
@ -448,8 +460,8 @@ void generic_event_handler(lv_obj_t* obj, lv_event_t event)
// Update group objects and gpios on release // Update group objects and gpios on release
if(last_value_sent == HASP_EVENT_UP || last_value_sent == HASP_EVENT_RELEASE) { if(last_value_sent == HASP_EVENT_UP || last_value_sent == HASP_EVENT_RELEASE) {
dispatch_normalized_group_values(obj->user_data.groupid, obj, Parser::get_event_state(last_value_sent), event_update_group(obj->user_data.groupid, obj, Parser::get_event_state(last_value_sent), HASP_EVENT_OFF,
HASP_EVENT_OFF, HASP_EVENT_ON); HASP_EVENT_ON);
} }
} }
@ -491,8 +503,8 @@ void toggle_event_handler(lv_obj_t* obj, lv_event_t event)
event_object_val_event(obj, hasp_event_id, last_value_sent); event_object_val_event(obj, hasp_event_id, last_value_sent);
// Update group objects and gpios on release // Update group objects and gpios on release
if(last_value_sent == HASP_EVENT_UP) { if(obj->user_data.groupid && hasp_event_id == HASP_EVENT_UP) {
dispatch_normalized_group_values(obj->user_data.groupid, obj, last_value_sent, HASP_EVENT_OFF, HASP_EVENT_ON); event_update_group(obj->user_data.groupid, obj, last_value_sent, HASP_EVENT_OFF, HASP_EVENT_ON);
} }
} }
@ -558,9 +570,9 @@ void selector_event_handler(lv_obj_t* obj, lv_event_t event)
last_value_sent = val; last_value_sent = val;
event_object_selection_changed(obj, hasp_event_id, val, buffer); event_object_selection_changed(obj, hasp_event_id, val, buffer);
if(max > 0) // max a cannot be 0, its the divider if(obj->user_data.groupid && max > 0) // max a cannot be 0, its the divider
if(hasp_event_id == HASP_EVENT_UP || hasp_event_id == LV_EVENT_VALUE_CHANGED) { if(hasp_event_id == HASP_EVENT_UP || hasp_event_id == LV_EVENT_VALUE_CHANGED) {
dispatch_normalized_group_values(obj->user_data.groupid, obj, last_value_sent, 0, max); event_update_group(obj->user_data.groupid, obj, last_value_sent, 0, max);
} }
// set the property // set the property
@ -599,7 +611,7 @@ void btnmatrix_event_handler(lv_obj_t* obj, lv_event_t event)
// if(max > 0) // max a cannot be 0, its the divider // if(max > 0) // max a cannot be 0, its the divider
// if(hasp_event_id == HASP_EVENT_UP || hasp_event_id == LV_EVENT_VALUE_CHANGED) { // if(hasp_event_id == HASP_EVENT_UP || hasp_event_id == LV_EVENT_VALUE_CHANGED) {
// dispatch_normalized_group_values(obj->user_data.groupid, obj, last_value_sent, 0, max); // event_update_group(obj->user_data.groupid, obj, last_value_sent, 0, max);
// } // }
} }
@ -632,7 +644,7 @@ void msgbox_event_handler(lv_obj_t* obj, lv_event_t event)
last_value_sent = val; last_value_sent = val;
event_object_selection_changed(obj, hasp_event_id, val, buffer); event_object_selection_changed(obj, hasp_event_id, val, buffer);
// if(max > 0) dispatch_normalized_group_values(obj->user_data.groupid, obj, val, 0, max); // if(max > 0) event_update_group(obj->user_data.groupid, obj, val, 0, max);
} }
/** /**
@ -671,8 +683,8 @@ void slider_event_handler(lv_obj_t* obj, lv_event_t event)
last_value_sent = val; last_value_sent = val;
event_object_val_event(obj, hasp_event_id, val); event_object_val_event(obj, hasp_event_id, val);
if(hasp_event_id == HASP_EVENT_CHANGED && min != max) if(obj->user_data.groupid && hasp_event_id == HASP_EVENT_CHANGED && min != max)
dispatch_normalized_group_values(obj->user_data.groupid, obj, val, min, max); event_update_group(obj->user_data.groupid, obj, val, min, max);
} }
/** /**
@ -704,7 +716,7 @@ void cpicker_event_handler(lv_obj_t* obj, lv_event_t event)
eventname, c32.ch.red, c32.ch.green, c32.ch.blue, c32.ch.red, c32.ch.green, c32.ch.blue); eventname, c32.ch.red, c32.ch.green, c32.ch.blue, c32.ch.red, c32.ch.green, c32.ch.blue);
event_send_object_data(obj, data); event_send_object_data(obj, data);
// dispatch_normalized_group_values(obj->user_data.groupid, obj, val, min, max); // event_update_group(obj->user_data.groupid, obj, val, min, max);
} }
void calendar_event_handler(lv_obj_t* obj, lv_event_t event) void calendar_event_handler(lv_obj_t* obj, lv_event_t event)
@ -736,5 +748,5 @@ void calendar_event_handler(lv_obj_t* obj, lv_event_t event)
eventname, date->day, date->year, date->month, date->day); eventname, date->day, date->year, date->month, date->day);
event_send_object_data(obj, data); event_send_object_data(obj, data);
// dispatch_normalized_group_values(obj->user_data.groupid, obj, val, min, max); // event_update_group(obj->user_data.groupid, obj, val, min, max);
} }

View File

@ -165,48 +165,42 @@ void object_dispatch_state(uint8_t pageid, uint8_t btnid, const char* payload)
// ##################### State Changers ######################################################## // ##################### State Changers ########################################################
void object_set_group_values(lv_obj_t* parent, uint8_t groupid, int16_t intval) // Recursive function that goes over all objects only ONCE
void object_set_group_values(lv_obj_t* parent, hasp_update_value_t& value)
{ {
if(groupid == 0 || parent == nullptr) return; if(parent == nullptr) return;
lv_obj_t* child; // Update object if it's in the same group
child = lv_obj_get_child(parent, NULL); if(value.group == parent->user_data.groupid && value.obj != parent)
while(child) { hasp_process_obj_attribute_val(parent, NULL, value.val, !!value.val, true);
/* child found, update it */
if(groupid == child->user_data.groupid) hasp_process_obj_attribute_val(child, NULL, intval, intval, true);
/* update grandchildren */ /* check tabs */
object_set_group_values(child, groupid, intval); if(obj_get_type(parent) == LV_HASP_TABVIEW) {
uint16_t tabcount = lv_tabview_get_tab_count(parent);
/* check tabs */ for(uint16_t i = 0; i < tabcount; i++) {
if(obj_check_type(child, LV_HASP_TABVIEW)) { lv_obj_t* tab = lv_tabview_get_tab(parent, i);
//#if LVGL_VERSION_MAJOR == 7 object_set_group_values(tab, value);
uint16_t tabcount = lv_tabview_get_tab_count(child); }
for(uint16_t i = 0; i < tabcount; i++) { } else {
lv_obj_t* tab = lv_tabview_get_tab(child, i); lv_obj_t* child;
LOG_VERBOSE(TAG_HASP, F("Found tab %i"), i); child = lv_obj_get_child(parent, NULL);
if(tab->user_data.groupid && groupid == tab->user_data.groupid) while(child) {
hasp_process_obj_attribute_val(tab, NULL, intval, intval, true); /* tab found, update it */ object_set_group_values(child, value);
child = lv_obj_get_child(parent, child);
/* check grandchildren */
object_set_group_values(tab, groupid, intval);
}
//#endif
} }
/* try next sibling */
child = lv_obj_get_child(parent, child);
} }
} }
// Recursive function that goes over all objects only ONCE // SHOULD only by called from DISPATCH
void object_set_normalized_group_values(uint8_t groupid, lv_obj_t* src_obj, int16_t val, int16_t min, int16_t max) void object_set_normalized_group_values(hasp_update_value_t& value)
{ {
if(groupid == 0) return; if(value.group == 0 || value.min == value.max) return;
if(min == max) return;
for(uint8_t page = 0; page < HASP_NUM_PAGES; page++) { uint8_t page = haspPages.get();
object_set_group_values(haspPages.get_obj(page), groupid, val); object_set_group_values(haspPages.get_obj(page), value); // Update visible objects first
for(uint8_t i = 0; i < HASP_NUM_PAGES; i++) {
if(i != page) object_set_group_values(haspPages.get_obj(i), value);
// uint8_t startid = 1; // uint8_t startid = 1;
// for(uint8_t objid = startid; objid < 20; objid++) { // for(uint8_t objid = startid; objid < 20; objid++) {
// lv_obj_t* obj = hasp_find_obj_from_parent_id(get_page_obj(page), objid); // lv_obj_t* obj = hasp_find_obj_from_parent_id(get_page_obj(page), objid);

View File

@ -20,6 +20,15 @@ typedef struct
uint16_t interval; uint16_t interval;
} hasp_task_user_data_t; } hasp_task_user_data_t;
typedef struct
{
int32_t min;
int32_t max;
int32_t val;
lv_obj_t* obj;
uint8_t group;
} hasp_update_value_t;
enum lv_hasp_obj_type_t { enum lv_hasp_obj_type_t {
/* Containers */ /* Containers */
LV_HASP_SCREEN = 1, LV_HASP_SCREEN = 1,
@ -81,7 +90,7 @@ void object_dispatch_state(uint8_t pageid, uint8_t btnid, const char* payload);
void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char* attr, const char* payload, bool update); void hasp_process_attribute(uint8_t pageid, uint8_t objid, const char* attr, const char* payload, bool update);
void object_set_normalized_group_values(uint8_t groupid, lv_obj_t* src_obj, int16_t val, int16_t min, int16_t max); void object_set_normalized_group_values(hasp_update_value_t& value);
#define HASP_OBJ_BAR 1971 #define HASP_OBJ_BAR 1971
#define HASP_OBJ_BTN 3164 #define HASP_OBJ_BTN 3164

View File

@ -16,10 +16,8 @@
#include "AceButton.h" #include "AceButton.h"
using namespace ace_button; using namespace ace_button;
static AceButton* button[HASP_NUM_INPUTS];
ButtonConfig buttonConfig; // Clicks, double-clicks and long presses ButtonConfig buttonConfig; // Clicks, double-clicks and long presses
ButtonConfig switchConfig; // Clicks only ButtonConfig switchConfig; // Clicks only
#else #else
#define HIGH 1 #define HIGH 1
@ -33,38 +31,52 @@ ButtonConfig switchConfig; // Clicks only
#define SCALE_8BIT_TO_12BIT(x) x << 4 | x >> 4 #define SCALE_8BIT_TO_12BIT(x) x << 4 | x >> 4
#define SCALE_8BIT_TO_10BIT(x) x << 2 | x >> 6 #define SCALE_8BIT_TO_10BIT(x) x << 2 | x >> 6
uint8_t gpioUsedInputCount = 0;
// An array of button pins, led pins, and the led states. Cannot be const // An array of button pins, led pins, and the led states. Cannot be const
// because ledState is mutable. // because ledState is mutable.
hasp_gpio_config_t gpioConfig[HASP_NUM_GPIO_CONFIG] = { hasp_gpio_config_t gpioConfig[HASP_NUM_GPIO_CONFIG] = {
// {2, 8, INPUT, LOW}, {3, 9, OUTPUT, LOW}, {4, 10, INPUT, HIGH}, {5, 11, OUTPUT, LOW}, {6, 12, INPUT, LOW}, // {2, 8, INPUT, LOW}, {3, 9, OUTPUT, LOW}, {4, 10, INPUT, HIGH}, {5, 11, OUTPUT, LOW}, {6, 12, INPUT, LOW},
}; };
static inline void gpio_update_group(uint8_t group, lv_obj_t* obj, int32_t val, int32_t min, int32_t max)
{
hasp_update_value_t value = {
.min = min,
.max = max,
.val = val,
.obj = obj,
.group = group,
};
dispatch_normalized_group_values(value);
}
#if defined(ARDUINO_ARCH_ESP32) #if defined(ARDUINO_ARCH_ESP32)
#include "driver/uart.h" #include "driver/uart.h"
#include <driver/dac.h> #include <driver/dac.h>
class TouchConfig : public ButtonConfig { volatile bool touchdetected = false;
public:
TouchConfig(); void gotTouch()
{
touchdetected = true;
}
// Overrides the readButton function on ESP32
class CapacitiveConfig : public ButtonConfig {
protected: protected:
// Number of iterations to sample the capacitive switch. Higher number // Number of iterations to sample the capacitive switch. Higher number
// provides better smoothing but increases the time taken for a single read. // provides better smoothing but increases the time taken for a single read.
static const uint8_t kSamples = 10; // static const uint8_t kSamples = 10;
// The threshold value which is considered to be a "touch" on the switch. // The threshold value which is considered to be a "touch" on the switch.
static const long kTouchThreshold = 70; static const long kTouchThreshold = 32;
int readButton(uint8_t pin) override int readButton(uint8_t pin) override
{ {
// long total = mSensor.capacitiveSensor(kSamples); return touchdetected ? HIGH : LOW; // HIGH = not touched
return (touchRead(pin) > kTouchThreshold) ? LOW : HIGH;
} }
}; };
CapacitiveConfig touchConfig; // Capacitive touch
TouchConfig touchConfig();
#endif #endif
void gpio_log_serial_dimmer(const char* command) void gpio_log_serial_dimmer(const char* command)
@ -88,7 +100,8 @@ static void gpio_event_handler(AceButton* button, uint8_t eventType, uint8_t but
} else { } else {
eventid = HASP_EVENT_DOWN; eventid = HASP_EVENT_DOWN;
} }
state = true; state = true;
touchdetected = false;
break; break;
case 2: // AceButton::kEventClicked: case 2: // AceButton::kEventClicked:
eventid = HASP_EVENT_UP; eventid = HASP_EVENT_UP;
@ -116,8 +129,10 @@ static void gpio_event_handler(AceButton* button, uint8_t eventType, uint8_t but
} }
event_gpio_input(gpioConfig[btnid].pin, gpioConfig[btnid].group, eventid); event_gpio_input(gpioConfig[btnid].pin, gpioConfig[btnid].group, eventid);
if(eventid != HASP_EVENT_LONG) // do not repeat DOWN + LONG
dispatch_normalized_group_values(gpioConfig[btnid].group, NULL, state, HASP_EVENT_OFF, HASP_EVENT_ON); // update objects and gpios in this group
if(gpioConfig[btnid].group && eventid != HASP_EVENT_LONG) // do not repeat DOWN + LONG
gpio_update_group(gpioConfig[btnid].group, NULL, state, HASP_EVENT_OFF, HASP_EVENT_ON);
} }
/* ********************************* GPIO Setup *************************************** */ /* ********************************* GPIO Setup *************************************** */
@ -129,11 +144,11 @@ void aceButtonSetup(void)
buttonConfig.setFeature(ButtonConfig::kFeatureClick); buttonConfig.setFeature(ButtonConfig::kFeatureClick);
buttonConfig.clearFeature(ButtonConfig::kFeatureDoubleClick); buttonConfig.clearFeature(ButtonConfig::kFeatureDoubleClick);
buttonConfig.setFeature(ButtonConfig::kFeatureLongPress); buttonConfig.setFeature(ButtonConfig::kFeatureLongPress);
// buttonConfig->clearFeature(ButtonConfig::kFeatureRepeatPress); // buttonConfig.clearFeature(ButtonConfig::kFeatureRepeatPress);
buttonConfig.clearFeature(ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses buttonConfig.clearFeature(ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses
buttonConfig.setFeature(ButtonConfig::kFeatureSuppressAfterClick); buttonConfig.setFeature(ButtonConfig::kFeatureSuppressAfterClick);
buttonConfig.setClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
// Delays // Delays
buttonConfig.setClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig.setDoubleClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME); buttonConfig.setDoubleClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig.setLongPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME); buttonConfig.setLongPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
buttonConfig.setRepeatPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME); buttonConfig.setRepeatPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
@ -146,68 +161,25 @@ void aceButtonSetup(void)
switchConfig.clearFeature(ButtonConfig::kFeatureRepeatPress); switchConfig.clearFeature(ButtonConfig::kFeatureRepeatPress);
switchConfig.clearFeature(ButtonConfig::kFeatureDoubleClick); switchConfig.clearFeature(ButtonConfig::kFeatureDoubleClick);
switchConfig.setClickDelay(100); // decrease click delay from default 200 ms switchConfig.setClickDelay(100); // decrease click delay from default 200 ms
#if defined(ARDUINO_ARCH_ESP32)
// Capacitive Touch Features
touchConfig.setEventHandler(gpio_event_handler);
touchConfig.setFeature(ButtonConfig::kFeatureClick);
touchConfig.clearFeature(ButtonConfig::kFeatureDoubleClick);
touchConfig.setFeature(ButtonConfig::kFeatureLongPress);
// touchConfig.clearFeature(ButtonConfig::kFeatureRepeatPress);
touchConfig.clearFeature(ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses
touchConfig.setFeature(ButtonConfig::kFeatureSuppressAfterClick);
// Delays
touchConfig.setClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
touchConfig.setDoubleClickDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
touchConfig.setLongPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
touchConfig.setRepeatPressDelay(LV_INDEV_DEF_LONG_PRESS_TIME);
touchConfig.setRepeatPressInterval(LV_INDEV_DEF_LONG_PRESS_REP_TIME);
#endif
} }
/* void gpioAddButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t index)
{
uint8_t i;
for(i = 0; i < HASP_NUM_INPUTS; i++) {
if(!button[i]) {
LOG_TRACE(TAG_GPIO, F("Creating Button%d on pin %d (index %d) mode %d default %d"), i, pin, index,
input_mode, default_state);
button[i] = new AceButton(&buttonConfig, pin, default_state, index);
if(button[i]) {
// pinMode(pin, input_mode);
// ButtonConfig* buttonConfig = button[i]->getButtonConfig();
// buttonConfig->setEventHandler(gpio_event_handler);
// buttonConfig->setFeature(ButtonConfig::kFeatureClick);
// buttonConfig->clearFeature(ButtonConfig::kFeatureDoubleClick);
// buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
// // buttonConfig->clearFeature(ButtonConfig::kFeatureRepeatPress);
// buttonConfig->clearFeature(
// ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses
// buttonConfig->setFeature(ButtonConfig::kFeatureSuppressAfterClick);
LOG_INFO(TAG_GPIO, F("Button%d created on pin %d (index %d) mode %d default %d"), i, pin, index,
input_mode, default_state);
gpioUsedInputCount = i + 1;
return;
}
}
}
LOG_ERROR(TAG_GPIO, F("Failed to create Button%d pin %d (index %d). All %d slots available are in use!"), i, pin,
index, HASP_NUM_INPUTS);
}
void gpioAddSwitch(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t index)
{
uint8_t i;
for(i = 0; i < HASP_NUM_INPUTS; i++) {
if(!button[i]) {
LOG_TRACE(TAG_GPIO, F("Creating Switch%d on pin %d (index %d) mode %d default %d"), i, pin, index,
input_mode, default_state);
button[i] = new AceButton(&switchConfig, pin, default_state, index);
if(button[i]) {
// pinMode(pin, input_mode);
LOG_INFO(TAG_GPIO, F("Switch%d on pin %d (index %d) mode %d default %d"), i, pin, index, input_mode,
default_state);
gpioUsedInputCount = i + 1;
return;
}
}
}
LOG_ERROR(TAG_GPIO, F("Failed to create Switch%d pin %d (index %d). All %d slots available are in use!"), i, pin,
index, HASP_NUM_INPUTS);
}*/
// Can be called ad-hoc to change a setup // Can be called ad-hoc to change a setup
static void gpio_setup_pin(uint8_t index) static void gpio_setup_pin(uint8_t index)
{ {
@ -240,13 +212,23 @@ static void gpio_setup_pin(uint8_t index)
switch(gpio->type) { switch(gpio->type) {
case HASP_GPIO_SWITCH: case HASP_GPIO_SWITCH:
config = &switchConfig;
case HASP_GPIO_BUTTON:
if(gpio->btn) delete gpio->btn; if(gpio->btn) delete gpio->btn;
gpio->btn = new AceButton(config, gpio->pin, HIGH, index); gpio->btn = new AceButton(&switchConfig, gpio->pin, HIGH, index);
pinMode(gpio->pin, INPUT_PULLUP); pinMode(gpio->pin, INPUT_PULLUP);
gpio->max = 0; gpio->max = 0;
break; break;
case HASP_GPIO_BUTTON:
if(gpio->btn) delete gpio->btn;
gpio->btn = new AceButton(&buttonConfig, gpio->pin, HIGH, index);
pinMode(gpio->pin, INPUT_PULLUP);
gpio->max = 0;
break;
case HASP_GPIO_TOUCH:
if(gpio->btn) delete gpio->btn;
gpio->btn = new AceButton(&touchConfig, gpio->pin, HIGH, index);
gpio->max = 0;
// touchAttachInterrupt(gpio->pin, gotTouch, 33);
break;
case HASP_GPIO_RELAY: case HASP_GPIO_RELAY:
pinMode(gpio->pin, OUTPUT); pinMode(gpio->pin, OUTPUT);
@ -300,37 +282,6 @@ static void gpio_setup_pin(uint8_t index)
LOG_VERBOSE(TAG_GPIO, F(D_BULLET "Configured pin %d"), gpio->pin); LOG_VERBOSE(TAG_GPIO, F(D_BULLET "Configured pin %d"), gpio->pin);
} }
void gpioAddTouchButton(uint8_t pin, uint8_t input_mode, uint8_t default_state, uint8_t index)
{
uint8_t i;
for(i = 0; i < HASP_NUM_INPUTS; i++) {
if(!button[i]) {
button[i] = new AceButton(pin, default_state, index);
if(button[i]) {
pinMode(pin, input_mode);
ButtonConfig* buttonConfig = button[i]->getButtonConfig();
buttonConfig->setEventHandler(gpio_event_handler);
buttonConfig->setFeature(ButtonConfig::kFeatureClick);
buttonConfig->clearFeature(ButtonConfig::kFeatureDoubleClick);
buttonConfig->setFeature(ButtonConfig::kFeatureLongPress);
buttonConfig->clearFeature(ButtonConfig::kFeatureRepeatPress);
buttonConfig->clearFeature(
ButtonConfig::kFeatureSuppressClickBeforeDoubleClick); // Causes annoying pauses
LOG_INFO(TAG_GPIO, F("Button%d created on pin %d (index %d) mode %d default %d"), i, pin, index,
input_mode, default_state);
gpioUsedInputCount = i + 1;
return;
}
}
}
LOG_ERROR(TAG_GPIO, F("Failed to create Button%d pin %d (index %d). All %d slots available are in use!"), i, pin,
index, HASP_NUM_INPUTS);
}
void gpioSetup() void gpioSetup()
{ {
LOG_INFO(TAG_GPIO, F(D_SERVICE_STARTING)); LOG_INFO(TAG_GPIO, F(D_SERVICE_STARTING));
@ -462,7 +413,7 @@ bool gpio_get_pin_config(uint8_t pin, hasp_gpio_config_t** gpio)
return false; return false;
} }
// Update the actual value of one pin // Update the actual value of one pin, does NOT update group members
// The value must be normalized first // The value must be normalized first
static bool gpio_set_output_value(hasp_gpio_config_t* gpio, uint16_t val) static bool gpio_set_output_value(hasp_gpio_config_t* gpio, uint16_t val)
{ {
@ -492,7 +443,7 @@ static bool gpio_set_output_value(hasp_gpio_config_t* gpio, uint16_t val)
// Update the normalized value of one pin // Update the normalized value of one pin
void gpio_set_normalized_value(hasp_gpio_config_t* gpio, int32_t val, int32_t min, int32_t max) void gpio_set_normalized_value(hasp_gpio_config_t* gpio, int32_t val, int32_t min, int32_t max)
{ {
if(min != 0 || max != gpio->max) { if(min != 0 || max != gpio->max) { // do we need to recalculate?
if(min == max) { if(min == max) {
LOG_ERROR(TAG_GPIO, F("Invalid value range")); LOG_ERROR(TAG_GPIO, F("Invalid value range"));
return; return;
@ -511,51 +462,48 @@ void gpio_set_normalized_value(hasp_gpio_config_t* gpio, int32_t val, int32_t mi
break; break;
default: default:
return; return; // invalid output type
} }
} }
gpio_set_output_value(gpio, val); // normalized gpio_set_output_value(gpio, val); // recalculated
} }
/* void gpio_set_normalized_group_values(uint8_t groupid, int16_t val, int16_t min, int16_t max) static inline bool gpio_is_input(hasp_gpio_config_t* gpio)
{ {
if(min == max) { return gpio->type == HASP_GPIO_BUTTON || gpio->type == HASP_GPIO_SWITCH || gpio->type == HASP_GPIO_TOUCH;
LOG_ERROR(TAG_GPIO, F("Invalid value range")); }
return;
}
// bool state = Parser::get_event_state(eventid); static inline bool gpio_is_output(hasp_gpio_config_t* gpio)
for(uint8_t i = 0; i < HASP_NUM_GPIO_CONFIG; i++) { {
if(gpioConfig[i].group == groupid) { return (gpio->type != HASP_GPIO_FREE) && !gpio_is_input(gpio);
gpio_set_normalized_value(&gpioConfig[i], val, min, max); }
}
}
} */
// Dispatch all group member values // Dispatch all group member values
void gpio_output_group_values(uint8_t group) void gpio_output_group_values(uint8_t group)
{ {
for(uint8_t k = 0; k < HASP_NUM_GPIO_CONFIG; k++) { for(uint8_t k = 0; k < HASP_NUM_GPIO_CONFIG; k++) {
hasp_gpio_config_t* gpio = &gpioConfig[k]; hasp_gpio_config_t* gpio = &gpioConfig[k];
if(gpio->group == group && gpio->type != HASP_GPIO_BUTTON && if(gpio->group == group && gpio_is_output(gpio)) // group members that are outputs
gpio->type != HASP_GPIO_SWITCH && // group members that are outputs
gpioConfigInUse(k))
dispatch_output_pin_value(gpioConfig[k].pin, gpioConfig[k].val); dispatch_output_pin_value(gpioConfig[k].pin, gpioConfig[k].val);
} }
} }
// SHOULD only by called from DISPATCH
// Update the normalized value of all group members // Update the normalized value of all group members
void gpio_set_normalized_group_values(uint8_t group, int32_t val, int32_t min, int32_t max) // Does not procude logging output
void gpio_set_normalized_group_values(hasp_update_value_t& value)
{ {
// Set all pins first, minimizes delays // Set all pins first, minimizes delays
for(uint8_t k = 0; k < HASP_NUM_GPIO_CONFIG; k++) { for(uint8_t k = 0; k < HASP_NUM_GPIO_CONFIG; k++) {
hasp_gpio_config_t* gpio = &gpioConfig[k]; hasp_gpio_config_t* gpio = &gpioConfig[k];
if(gpio->group == group && gpioConfigInUse(k)) // group members that are outputs if(gpio->group == value.group && gpioConfigInUse(k)) // group members that are outputs
gpio_set_normalized_value(gpio, val, min, max); gpio_set_normalized_value(gpio, value.val, value.min, value.max);
} }
gpio_output_group_values(group); // Log the changed output values
object_set_normalized_group_values(group, NULL, val, min, max); // Update onsreen objects // gpio_output_group_values(value.group);
// object_set_normalized_group_values(group, NULL, val, min, max); // Update onsreen objects
} }
// Update the value of an output pin and its group members // Update the value of an output pin and its group members
@ -563,22 +511,23 @@ bool gpio_set_pin_value(uint8_t pin, int32_t val)
{ {
hasp_gpio_config_t* gpio = NULL; hasp_gpio_config_t* gpio = NULL;
if(!gpio_get_pin_config(pin, &gpio) || !gpio || gpio->type == HASP_GPIO_FREE) { if(!gpio_get_pin_config(pin, &gpio) || !gpio) {
LOG_WARNING(TAG_GPIO, F(D_BULLET "Pin %d is not configured"), pin); LOG_WARNING(TAG_GPIO, F(D_BULLET "Pin %d is not configured"), pin);
return false; return false;
} else if(gpio->type == HASP_GPIO_BUTTON || gpio->type == HASP_GPIO_SWITCH) { } else if(gpio_is_output(gpio)) {
LOG_WARNING(TAG_GPIO, F(D_BULLET "Pin %d is an input"), pin); LOG_WARNING(TAG_GPIO, F(D_BULLET "Pin %d can not be set"), pin);
if(gpio->group) gpio_output_group_values(gpio->group); if(gpio->group) gpio_output_group_values(gpio->group);
return false; return false;
} }
if(gpio->group) { if(gpio->group) {
gpio_set_normalized_group_values(gpio->group, val, 0, gpio->max); // Set all pins in the group // update objects and gpios in this group
LOG_VERBOSE(TAG_GPIO, F("Group %d - Pin %d = %d"), gpio->group, gpio->pin, gpio->val); gpio_update_group(gpio->group, NULL, gpio->val, 0, gpio->max);
} else { } else {
gpio_set_output_value(gpio, val); // update this gpio value only // update this gpio value only
gpio_set_output_value(gpio, val);
dispatch_output_pin_value(gpio->pin, gpio->val); dispatch_output_pin_value(gpio->pin, gpio->val);
LOG_VERBOSE(TAG_GPIO, F("No Group - Pin %d = %d"), gpio->pin, gpio->val); LOG_VERBOSE(TAG_GPIO, F("No Group - Pin %d = %d"), gpio->pin, gpio->val);
} }
@ -625,6 +574,8 @@ void gpio_set_moodlight(moodlight_t& moodlight)
break; break;
} }
} }
// TODO: Update objects when the Mood Color Pin is in a group
} }
bool gpioIsSystemPin(uint8_t gpio) bool gpioIsSystemPin(uint8_t gpio)

View File

@ -34,9 +34,9 @@ void gpioSetup(void);
IRAM_ATTR void gpioLoop(void); IRAM_ATTR void gpioLoop(void);
void gpioEvery5Seconds(void); void gpioEvery5Seconds(void);
// void gpio_set_group_onoff(uint8_t groupid, bool ison); void gpio_set_normalized_group_values(hasp_update_value_t& value);
void gpio_set_normalized_group_values(uint8_t group, int32_t val, int32_t min, int32_t max); void gpio_output_group_values(uint8_t group);
// void gpio_set_gpio_state(uint8_t pin, uint16_t state);
bool gpio_get_value(uint8_t pin, uint16_t& val); bool gpio_get_value(uint8_t pin, uint16_t& val);
bool gpio_set_pin_value(uint8_t pin, int32_t val); bool gpio_set_pin_value(uint8_t pin, int32_t val);
void gpio_set_moodlight(moodlight_t& moodlight); void gpio_set_moodlight(moodlight_t& moodlight);