Browse Source

Moving interrupt handling routines from Abstract classes (ICACHE_RAM_ATTR and virtual do not get on well)

fastled
Xose Pérez 7 years ago
parent
commit
1fd269e05e
4 changed files with 264 additions and 153 deletions
  1. +6
    -72
      code/espurna/sensors/BaseSensor.h
  2. +88
    -26
      code/espurna/sensors/ECH1560Sensor.h
  3. +78
    -16
      code/espurna/sensors/EventSensor.h
  4. +92
    -39
      code/espurna/sensors/HLW8012Sensor.h

+ 6
- 72
code/espurna/sensors/BaseSensor.h View File

@ -123,20 +123,6 @@ class BaseSensor {
}
// Interrupt attach callback
void attached(unsigned char gpio) {
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] GPIO%d interrupt attached to %s\n", gpio, description().c_str());
#endif
}
// Interrupt detach callback
void detached(unsigned char gpio) {
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] GPIO%d interrupt detached from %s\n", gpio, description().c_str());
#endif
}
// Return sensor status (true for ready)
bool status() { return _error == 0; }
@ -146,16 +132,14 @@ class BaseSensor {
// Number of available slots
unsigned char count() { return _count; }
// Handle interrupt calls
void ICACHE_RAM_ATTR handleInterrupt(unsigned char gpio) {}
protected:
// Attach interrupt
void attach(BaseSensor * instance, unsigned char gpio, unsigned char mode);
// Detach interrupt
void detach(unsigned char gpio);
// Check if valid GPIO
bool _validGPIO(unsigned char gpio) {
if (0 <= gpio && gpio <= 5) return true;
if (12 <= gpio && gpio <= 15) return true;
return false;
}
unsigned char _sensor_id = 0x00;
int _error = 0;
@ -167,53 +151,3 @@ class BaseSensor {
unsigned char _address = 0;
};
// -----------------------------------------------------------------------------
// Interrupt helpers
// -----------------------------------------------------------------------------
BaseSensor * _isr_sensor_instance[16] = {NULL};
void ICACHE_RAM_ATTR _sensor_isr(unsigned char gpio) {
if (_isr_sensor_instance[gpio]) {
_isr_sensor_instance[gpio]->handleInterrupt(gpio);
}
}
void ICACHE_RAM_ATTR _sensor_isr_0() { _sensor_isr(0); }
void ICACHE_RAM_ATTR _sensor_isr_1() { _sensor_isr(1); }
void ICACHE_RAM_ATTR _sensor_isr_2() { _sensor_isr(2); }
void ICACHE_RAM_ATTR _sensor_isr_3() { _sensor_isr(3); }
void ICACHE_RAM_ATTR _sensor_isr_4() { _sensor_isr(4); }
void ICACHE_RAM_ATTR _sensor_isr_5() { _sensor_isr(5); }
void ICACHE_RAM_ATTR _sensor_isr_12() { _sensor_isr(12); }
void ICACHE_RAM_ATTR _sensor_isr_13() { _sensor_isr(13); }
void ICACHE_RAM_ATTR _sensor_isr_14() { _sensor_isr(14); }
void ICACHE_RAM_ATTR _sensor_isr_15() { _sensor_isr(15); }
static void (*_sensor_isrs[16])() = {
_sensor_isr_0, _sensor_isr_1, _sensor_isr_2, _sensor_isr_3, _sensor_isr_4, _sensor_isr_5,
NULL, NULL, NULL, NULL, NULL, NULL,
_sensor_isr_12, _sensor_isr_13, _sensor_isr_14, _sensor_isr_15
};
void BaseSensor::attach(BaseSensor * instance, unsigned char gpio, unsigned char mode) {
if ((6 <= gpio) && (gpio <=11)) return;
if (gpio >= 16) return;
detach(gpio);
if (_sensor_isrs[gpio]) {
_isr_sensor_instance[gpio] = instance;
attachInterrupt(gpio, _sensor_isrs[gpio], mode);
instance->attached(gpio);
}
}
void BaseSensor::detach(unsigned char gpio) {
if ((6 <= gpio) && (gpio <=11)) return;
if (gpio >= 16) return;
if (_isr_sensor_instance[gpio]) {
detachInterrupt(gpio);
_isr_sensor_instance[gpio]->detached(gpio);
_isr_sensor_instance[gpio] = NULL;
}
}

+ 88
- 26
code/espurna/sensors/ECH1560Sensor.h View File

@ -22,7 +22,7 @@ class ECH1560Sensor : public BaseSensor {
}
~ECH1560Sensor() {
if (_interrupt_gpio != GPIO_NONE) detach(_interrupt_gpio);
_enableInterrupts(false);
}
// ---------------------------------------------------------------------
@ -69,27 +69,10 @@ class ECH1560Sensor : public BaseSensor {
pinMode(_clk, INPUT);
pinMode(_miso, INPUT);
if (_interrupt_gpio != GPIO_NONE) detach(_interrupt_gpio);
attach(this, _clk, RISING);
_enableInterrupts(true);
}
// Interrupt attach callback
void attached(unsigned char gpio) {
BaseSensor::attached(gpio);
_interrupt_gpio = gpio;
}
// Interrupt detach callback
void detached(unsigned char gpio) {
BaseSensor::detached(gpio);
if (_interrupt_gpio == gpio) _interrupt_gpio = GPIO_NONE;
}
void ICACHE_RAM_ATTR handleInterrupt() {
_isr();
}
// Descriptive name of the sensor
String description() {
char buffer[25];
@ -117,13 +100,9 @@ class ECH1560Sensor : public BaseSensor {
return 0;
}
protected:
void ICACHE_RAM_ATTR handleInterrupt(unsigned char gpio) {
// ---------------------------------------------------------------------
// Protected
// ---------------------------------------------------------------------
void ICACHE_RAM_ATTR _isr() {
(void) gpio;
// if we are trying to find the sync-time (CLK goes high for 1-2ms)
if (_dosync == false) {
@ -152,6 +131,36 @@ class ECH1560Sensor : public BaseSensor {
}
protected:
// ---------------------------------------------------------------------
// Interrupt management
// ---------------------------------------------------------------------
void _attach(ECH1560Sensor * instance, unsigned char gpio, unsigned char mode);
void _detach(unsigned char gpio);
void _enableInterrupts(bool value) {
static unsigned char _interrupt_clk = GPIO_NONE;
if (value) {
if (_interrupt_clk != _clk) {
if (_interrupt_clk != GPIO_NONE) _detach(_interrupt_clk);
_attach(this, _clk, RISING);
_interrupt_clk = _clk;
}
} else if (_interrupt_clk != GPIO_NONE) {
_detach(_interrupt_clk);
_interrupt_clk = GPIO_NONE;
}
}
// ---------------------------------------------------------------------
// Protected
// ---------------------------------------------------------------------
void _sync() {
unsigned int byte1 = 0;
@ -247,7 +256,6 @@ class ECH1560Sensor : public BaseSensor {
unsigned char _clk = 0;
unsigned char _miso = 0;
unsigned char _interrupt_gpio = GPIO_NONE;
bool _inverted = false;
volatile long _bits_count = 0;
@ -262,3 +270,57 @@ class ECH1560Sensor : public BaseSensor {
unsigned char _data[24];
};
// -----------------------------------------------------------------------------
// Interrupt helpers
// -----------------------------------------------------------------------------
ECH1560Sensor * _ech1560_sensor_instance[10] = {NULL};
void ICACHE_RAM_ATTR _ech1560_sensor_isr(unsigned char gpio) {
unsigned char index = gpio > 5 ? gpio-6 : gpio;
if (_ech1560_sensor_instance[index]) {
_ech1560_sensor_instance[index]->handleInterrupt(gpio);
}
}
void ICACHE_RAM_ATTR _ech1560_sensor_isr_0() { _ech1560_sensor_isr(0); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_1() { _ech1560_sensor_isr(1); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_2() { _ech1560_sensor_isr(2); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_3() { _ech1560_sensor_isr(3); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_4() { _ech1560_sensor_isr(4); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_5() { _ech1560_sensor_isr(5); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_12() { _ech1560_sensor_isr(12); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_13() { _ech1560_sensor_isr(13); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_14() { _ech1560_sensor_isr(14); }
void ICACHE_RAM_ATTR _ech1560_sensor_isr_15() { _ech1560_sensor_isr(15); }
static void (*_ech1560_sensor_isr_list[10])() = {
_ech1560_sensor_isr_0, _ech1560_sensor_isr_1, _ech1560_sensor_isr_2,
_ech1560_sensor_isr_3, _ech1560_sensor_isr_4, _ech1560_sensor_isr_5,
_ech1560_sensor_isr_12, _ech1560_sensor_isr_13, _ech1560_sensor_isr_14,
_ech1560_sensor_isr_15
};
void ECH1560Sensor::_attach(ECH1560Sensor * instance, unsigned char gpio, unsigned char mode) {
if (!_validGPIO(gpio)) return;
_detach(gpio);
unsigned char index = gpio > 5 ? gpio-6 : gpio;
_ech1560_sensor_instance[index] = instance;
attachInterrupt(gpio, _ech1560_sensor_isr_list[index], mode);
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] GPIO%d interrupt attached to %s\n", gpio, instance->description().c_str());
#endif
}
void ECH1560Sensor::_detach(unsigned char gpio) {
if (!_validGPIO(gpio)) return;
unsigned char index = gpio > 5 ? gpio-6 : gpio;
if (_ech1560_sensor_instance[index]) {
detachInterrupt(gpio);
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] GPIO%d interrupt detached from %s\n", gpio, _ech1560_sensor_instance[index]->description().c_str());
#endif
_ech1560_sensor_instance[index] = NULL;
}
}

+ 78
- 16
code/espurna/sensors/EventSensor.h View File

@ -22,7 +22,7 @@ class EventSensor : public BaseSensor {
}
~EventSensor() {
detach(_gpio);
_enableInterrupts(false);
}
// ---------------------------------------------------------------------
@ -68,9 +68,8 @@ class EventSensor : public BaseSensor {
// Initialization method, must be idempotent
// Defined outside the class body
void begin() {
if (_interrupt_gpio != GPIO_NONE) detach(_interrupt_gpio);
pinMode(_gpio, _mode);
attach(this, _gpio, _interrupt_mode);
_enableInterrupts(true);
}
// Descriptive name of the sensor
@ -101,7 +100,7 @@ class EventSensor : public BaseSensor {
}
// Handle interrupt calls
void ICACHE_RAM_ATTR handleInterrupt(unsigned char gpio) {
void handleInterrupt(unsigned char gpio) {
(void) gpio;
static unsigned long last = 0;
if (millis() - last > _debounce) {
@ -110,19 +109,29 @@ class EventSensor : public BaseSensor {
}
}
// Interrupt attach callback
void attached(unsigned char gpio) {
BaseSensor::attached(gpio);
_interrupt_gpio = gpio;
}
protected:
// Interrupt detach callback
void detached(unsigned char gpio) {
BaseSensor::detached(gpio);
if (_interrupt_gpio == gpio) _interrupt_gpio = GPIO_NONE;
}
// ---------------------------------------------------------------------
// Interrupt management
// ---------------------------------------------------------------------
protected:
void _attach(EventSensor * instance, unsigned char gpio, unsigned char mode);
void _detach(unsigned char gpio);
void _enableInterrupts(bool value) {
static unsigned char _interrupt_gpio = GPIO_NONE;
if (value) {
if (_interrupt_gpio != GPIO_NONE) _detach(_interrupt_gpio);
_attach(this, _gpio, _interrupt_mode);
_interrupt_gpio = _gpio;
} else if (_interrupt_gpio != GPIO_NONE) {
_detach(_interrupt_gpio);
_interrupt_gpio = GPIO_NONE;
}
}
// ---------------------------------------------------------------------
// Protected
@ -133,6 +142,59 @@ class EventSensor : public BaseSensor {
unsigned char _gpio;
unsigned char _mode;
unsigned char _interrupt_mode;
unsigned char _interrupt_gpio = GPIO_NONE;
};
// -----------------------------------------------------------------------------
// Interrupt helpers
// -----------------------------------------------------------------------------
EventSensor * _event_sensor_instance[10] = {NULL};
void ICACHE_RAM_ATTR _event_sensor_isr(unsigned char gpio) {
unsigned char index = gpio > 5 ? gpio-6 : gpio;
if (_event_sensor_instance[index]) {
_event_sensor_instance[index]->handleInterrupt(gpio);
}
}
void ICACHE_RAM_ATTR _event_sensor_isr_0() { _event_sensor_isr(0); }
void ICACHE_RAM_ATTR _event_sensor_isr_1() { _event_sensor_isr(1); }
void ICACHE_RAM_ATTR _event_sensor_isr_2() { _event_sensor_isr(2); }
void ICACHE_RAM_ATTR _event_sensor_isr_3() { _event_sensor_isr(3); }
void ICACHE_RAM_ATTR _event_sensor_isr_4() { _event_sensor_isr(4); }
void ICACHE_RAM_ATTR _event_sensor_isr_5() { _event_sensor_isr(5); }
void ICACHE_RAM_ATTR _event_sensor_isr_12() { _event_sensor_isr(12); }
void ICACHE_RAM_ATTR _event_sensor_isr_13() { _event_sensor_isr(13); }
void ICACHE_RAM_ATTR _event_sensor_isr_14() { _event_sensor_isr(14); }
void ICACHE_RAM_ATTR _event_sensor_isr_15() { _event_sensor_isr(15); }
static void (*_event_sensor_isr_list[10])() = {
_event_sensor_isr_0, _event_sensor_isr_1, _event_sensor_isr_2,
_event_sensor_isr_3, _event_sensor_isr_4, _event_sensor_isr_5,
_event_sensor_isr_12, _event_sensor_isr_13, _event_sensor_isr_14,
_event_sensor_isr_15
};
void EventSensor::_attach(EventSensor * instance, unsigned char gpio, unsigned char mode) {
if (!_validGPIO(gpio)) return;
_detach(gpio);
unsigned char index = gpio > 5 ? gpio-6 : gpio;
_event_sensor_instance[index] = instance;
attachInterrupt(gpio, _event_sensor_isr_list[index], mode);
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] GPIO%d interrupt attached to %s\n", gpio, instance->description().c_str());
#endif
}
void EventSensor::_detach(unsigned char gpio) {
if (!_validGPIO(gpio)) return;
unsigned char index = gpio > 5 ? gpio-6 : gpio;
if (_event_sensor_instance[index]) {
detachInterrupt(gpio);
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] GPIO%d interrupt detached from %s\n", gpio, _event_sensor_instance[index]->description().c_str());
#endif
_event_sensor_instance[index] = NULL;
}
}

+ 92
- 39
code/espurna/sensors/HLW8012Sensor.h View File

@ -26,8 +26,7 @@ class HLW8012Sensor : public BaseSensor {
}
~HLW8012Sensor() {
detach(_interrupt_cf);
detach(_interrupt_cf1);
_enableInterrupts(false);
}
void expectedCurrent(double expected) {
@ -141,13 +140,13 @@ class HLW8012Sensor : public BaseSensor {
// Handle interrupts
#if HLW8012_USE_INTERRUPTS
_enable(true);
_enableInterrupts(true);
#else
_onconnect_handler = WiFi.onStationModeGotIP([this](WiFiEventStationModeGotIP ipInfo) {
_enable(true);
_enableInterrupts(true);
});
_ondisconnect_handler = WiFi.onStationModeDisconnected([this](WiFiEventStationModeDisconnected ipInfo) {
_enable(false);
_enableInterrupts(false);
});
#endif
@ -188,54 +187,55 @@ class HLW8012Sensor : public BaseSensor {
return 0;
}
// Toggle between current and voltage monitoring
#if HLW8012_USE_INTERRUPTS == 0
// Post-read hook (usually to reset things)
void post() {
// Toggle between current and voltage monitoring
#if (HLW8012_USE_INTERRUPTS == 0)
_hlw8012->toggleMode();
#endif // (HLW8012_USE_INTERRUPTS == 0)
}
void post() { _hlw8012->toggleMode(); }
#endif // HLW8012_USE_INTERRUPTS == 0
// Handle interrupt calls
void ICACHE_RAM_ATTR handleInterrupt(unsigned char gpio) {
if (gpio == _interrupt_cf) _hlw8012->cf_interrupt();
if (gpio == _interrupt_cf1) _hlw8012->cf1_interrupt();
}
// Interrupt attach callback
void attached(unsigned char gpio) {
BaseSensor::attached(gpio);
if (_cf == gpio) _interrupt_cf = gpio;
if (_cf1 == gpio) _interrupt_cf1 = gpio;
}
// Interrupt detach callback
void detached(unsigned char gpio) {
BaseSensor::detached(gpio);
if (_interrupt_cf == gpio) _interrupt_cf = GPIO_NONE;
if (_interrupt_cf1 == gpio) _interrupt_cf1 = GPIO_NONE;
if (gpio == _cf) _hlw8012->cf_interrupt();
if (gpio == _cf1) _hlw8012->cf1_interrupt();
}
protected:
// ---------------------------------------------------------------------
// Protected
// Interrupt management
// ---------------------------------------------------------------------
void _enable(bool value) {
void _attach(HLW8012Sensor * instance, unsigned char gpio, unsigned char mode);
void _detach(unsigned char gpio);
void _enableInterrupts(bool value) {
static unsigned char _interrupt_cf = GPIO_NONE;
static unsigned char _interrupt_cf1 = GPIO_NONE;
if (value) {
if (_interrupt_cf != _cf) {
detach(_interrupt_cf);
attach(this, _cf, CHANGE);
if (_interrupt_cf != GPIO_NONE) _detach(_interrupt_cf);
_attach(this, _cf, CHANGE);
_interrupt_cf = _cf;
}
if (_interrupt_cf1 != _cf1) {
detach(_interrupt_cf1);
attach(this, _cf1, CHANGE);
if (_interrupt_cf1 != GPIO_NONE) _detach(_interrupt_cf1);
_attach(this, _cf1, CHANGE);
_interrupt_cf1 = _cf1;
}
} else {
detach(_interrupt_cf);
detach(_interrupt_cf1);
_detach(_cf);
_detach(_cf1);
_interrupt_cf = GPIO_NONE;
_interrupt_cf1 = GPIO_NONE;
}
}
// ---------------------------------------------------------------------
@ -247,10 +247,63 @@ class HLW8012Sensor : public BaseSensor {
HLW8012 * _hlw8012 = NULL;
WiFiEventHandler _onconnect_handler;
WiFiEventHandler _ondisconnect_handler;
#if HLW8012_USE_INTERRUPTS == 0
WiFiEventHandler _onconnect_handler;
WiFiEventHandler _ondisconnect_handler;
#endif
unsigned char _interrupt_cf = GPIO_NONE;
unsigned char _interrupt_cf1 = GPIO_NONE;
};
// -----------------------------------------------------------------------------
// Interrupt helpers
// -----------------------------------------------------------------------------
HLW8012Sensor * _hlw8012_sensor_instance[10] = {NULL};
void ICACHE_RAM_ATTR _hlw8012_sensor_isr(unsigned char gpio) {
unsigned char index = gpio > 5 ? gpio-6 : gpio;
if (_hlw8012_sensor_instance[index]) {
_hlw8012_sensor_instance[index]->handleInterrupt(gpio);
}
}
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_0() { _hlw8012_sensor_isr(0); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_1() { _hlw8012_sensor_isr(1); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_2() { _hlw8012_sensor_isr(2); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_3() { _hlw8012_sensor_isr(3); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_4() { _hlw8012_sensor_isr(4); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_5() { _hlw8012_sensor_isr(5); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_12() { _hlw8012_sensor_isr(12); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_13() { _hlw8012_sensor_isr(13); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_14() { _hlw8012_sensor_isr(14); }
void ICACHE_RAM_ATTR _hlw8012_sensor_isr_15() { _hlw8012_sensor_isr(15); }
static void (*_hlw8012_sensor_isr_list[10])() = {
_hlw8012_sensor_isr_0, _hlw8012_sensor_isr_1, _hlw8012_sensor_isr_2,
_hlw8012_sensor_isr_3, _hlw8012_sensor_isr_4, _hlw8012_sensor_isr_5,
_hlw8012_sensor_isr_12, _hlw8012_sensor_isr_13, _hlw8012_sensor_isr_14,
_hlw8012_sensor_isr_15
};
void HLW8012Sensor::_attach(HLW8012Sensor * instance, unsigned char gpio, unsigned char mode) {
if (!_validGPIO(gpio)) return;
_detach(gpio);
unsigned char index = gpio > 5 ? gpio-6 : gpio;
_hlw8012_sensor_instance[index] = instance;
attachInterrupt(gpio, _hlw8012_sensor_isr_list[index], mode);
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] GPIO%d interrupt attached to %s\n", gpio, instance->description().c_str());
#endif
}
void HLW8012Sensor::_detach(unsigned char gpio) {
if (!_validGPIO(gpio)) return;
unsigned char index = gpio > 5 ? gpio-6 : gpio;
if (_hlw8012_sensor_instance[index]) {
detachInterrupt(gpio);
#if SENSOR_DEBUG
DEBUG_MSG("[SENSOR] GPIO%d interrupt detached from %s\n", gpio, _hlw8012_sensor_instance[index]->description().c_str());
#endif
_hlw8012_sensor_instance[index] = NULL;
}
}

Loading…
Cancel
Save