diff --git a/src/current_sense/InlineCurrentSense.cpp b/src/current_sense/InlineCurrentSense.cpp index c3db74ef..17793d53 100644 --- a/src/current_sense/InlineCurrentSense.cpp +++ b/src/current_sense/InlineCurrentSense.cpp @@ -61,6 +61,7 @@ void InlineCurrentSense::calibrateOffsets(){ offset_ic = 0; // read the adc voltage 1000 times ( arbitrary number ) for (int i = 0; i < calibration_rounds; i++) { + _startADC3PinConversionInline(); if(_isset(pinA)) offset_ia += _readADCVoltageInline(pinA, params); if(_isset(pinB)) offset_ib += _readADCVoltageInline(pinB, params); if(_isset(pinC)) offset_ic += _readADCVoltageInline(pinC, params); @@ -75,6 +76,7 @@ void InlineCurrentSense::calibrateOffsets(){ // read all three phase currents (if possible 2 or 3) PhaseCurrent_s InlineCurrentSense::getPhaseCurrents(){ PhaseCurrent_s current; + _startADC3PinConversionInline(); current.a = (!_isset(pinA)) ? 0 : (_readADCVoltageInline(pinA, params) - offset_ia)*gain_a;// amps current.b = (!_isset(pinB)) ? 0 : (_readADCVoltageInline(pinB, params) - offset_ib)*gain_b;// amps current.c = (!_isset(pinC)) ? 0 : (_readADCVoltageInline(pinC, params) - offset_ic)*gain_c; // amps diff --git a/src/current_sense/hardware_api.h b/src/current_sense/hardware_api.h index 7862b708..9765da22 100644 --- a/src/current_sense/hardware_api.h +++ b/src/current_sense/hardware_api.h @@ -35,6 +35,8 @@ float _readADCVoltageInline(const int pinA, const void* cs_params); */ void* _configureADCInline(const void *driver_params, const int pinA,const int pinB,const int pinC = NOT_SET); +void _startADC3PinConversionInline(); + /** * function reading an ADC value and returning the read voltage * diff --git a/src/current_sense/hardware_specific/esp32/esp32_i2s_driver.cpp b/src/current_sense/hardware_specific/esp32/esp32_i2s_driver.cpp new file mode 100644 index 00000000..006dfdc4 --- /dev/null +++ b/src/current_sense/hardware_specific/esp32/esp32_i2s_driver.cpp @@ -0,0 +1,392 @@ +#include "../../hardware_api.h" +#include "../../../drivers/hardware_api.h" +#include "../../../drivers/hardware_specific/esp32/esp32_driver_mcpwm.h" + +#include "esp32_i2s_driver.h" + +#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC) + +#include +#include + +#include +#include + +#include "soc/syscon_periph.h" +#include +// #include + +#include "soc/timer_group_struct.h" +#include "soc/timer_group_reg.h" + +#include +#include + +#include +#include +#include + + +#define BUF_LEN 1 +#define _ADC_VOLTAGE 3.3f +#define _ADC_RESOLUTION 4095.0f + +#define I2S_USE_INTERRUPT false +#define DEBUG_ADC false + +typedef struct ESP32MCPWMCurrentSenseParams { + int pins[3]; + float adc_voltage_conv; + mcpwm_unit_t mcpwm_unit; + int buffer_index; +} ESP32MCPWMCurrentSenseParams; + + +/** + * I2S reading implementation by @mcells. + */ + +static uint32_t IRAM_ATTR i2s_adc_buffer[ADC1_CHANNEL_MAX] = {0}; +int globalActiveChannels = 0; +int channels[ADC1_CHANNEL_MAX] = {0}; +bool running = false; +bool sampleOnCommand = true; +#if DEBUG_ADC == true +uint32_t IRAM_ATTR readscnt = 0; +volatile uint32_t IRAM_ATTR buffersread = 0; +uint32_t IRAM_ATTR intcnt = 0; +uint32_t IRAM_ATTR skipped = 0; +uint32_t IRAM_ATTR equal = 0; +uint32_t IRAM_ATTR currfifo = 0; +uint32_t IRAM_ATTR lastfifo = 0; +unsigned long IRAM_ATTR ts = 0; +unsigned long IRAM_ATTR fifotime = 0; +#endif + +// This function reads data from the I2S FIFO and processes it to obtain average readings for each channel. +// The ADC counts get saved in uint32_t i2s_adc_buffer[]. +void IRAM_ATTR readFiFo() +{ + CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START); // Stop aquisition to buffer + + // uint32_t readings[ADC1_CHANNEL_MAX][ADC1_CHANNEL_MAX*BUF_LEN]; + uint32_t avgreadings[ADC1_CHANNEL_MAX] = {0}; + uint32_t counts[ADC1_CHANNEL_MAX] = {0}; + uint32_t fifolen = GET_PERI_REG_BITS2(I2S_FIFO_CONF_REG(0), I2S_RX_DATA_NUM_M, I2S_RX_DATA_NUM_S); // I2S0.fifo_conf.rx_data_num; +#if DEBUG_ADC + uint32_t lastrd = 0; + uint32_t lasth = 0; + uint32_t lastl = 0; + uint32_t internalequal = 0; + uint32_t internal_buffersread = 0; +#endif + + I2S0.int_ena.rx_rempty = 1; + I2S0.int_clr.rx_rempty = 1; + + // FiFo length seems a fixed size -> read until empty for latest samples + while(!GET_PERI_REG_MASK(I2S_INT_RAW_REG(0), I2S_RX_REMPTY_INT_RAW_M)){ + SET_PERI_REG_MASK(I2S_INFIFO_POP_REG(0), I2S_INFIFO_POP_M); + CLEAR_PERI_REG_MASK(I2S_INFIFO_POP_REG(0), I2S_INFIFO_POP_M); + + uint32_t rd = *(uint32_t *)(REG_I2S_BASE(0) + 0x4); // GET_PERI_REG_BITS2(I2S_FIFO_CONF_REG, I2S_RX_DATA_NUM_M, I2S_RX_DATA_NUM_S);I2S0.fifo_rd; + + uint32_t highVal = rd >> 16; + uint32_t lowVal = rd & 0xFFFF; + +#if DEBUG_ADC == true + if (rd == lastrd || highVal == lastl || lowVal == lasth) + { // + internalequal++; + // currfifo = rd; + // lastfifo = lastrd; + // Serial.printf("\n|\nlast: "); + // for (int i = 31; i >= 15; i--) + // { + // Serial.printf("%d",(lastfifo >> i ) & 1); + // } + // Serial.printf(" "); + // for (int i = 15; i >= 0; i--) + // { + // Serial.printf("%d",(lastfifo >> i ) & 1); + // } + + // Serial.printf("\ncurr: "); + // for (int i = 31; i >= 15; i--) + // { + // Serial.printf("%d",(currfifo >> i ) & 1); + // } + // Serial.printf(" "); + // for (int i = 15; i >= 0; i--) + // { + // Serial.printf("%d",(currfifo >> i ) & 1); + // } + // Serial.printf("\n"); + } + + lasth = highVal; + lastl = lowVal; + lastrd = rd; + readscnt += 2; + internal_buffersread++; +#endif + uint32_t chan = (lowVal >> 12) & 0x07; + uint32_t adc_value = lowVal & 0xfff; + // readings[chan][counts[chan]] = adc_value; + avgreadings[chan] = adc_value; + i2s_adc_buffer[chan] = adc_value; + //avgreadings[chan] += adc_value; + counts[chan]++; + + chan = (highVal >> 12) & 0x07; + adc_value = highVal & 0xfff; + // readings[chan][counts[chan]] = adc_value; + avgreadings[chan] = adc_value; + i2s_adc_buffer[chan] = adc_value; + //avgreadings[chan] += adc_value; + counts[chan]++; + } + I2S0.int_ena.rx_rempty = 0; + I2S0.int_clr.rx_rempty = 1; +#if DEBUG_ADC == true + equal = internalequal; + intcnt += 1; // I2S0.fifo_conf.rx_data_num; + buffersread = internal_buffersread; +#endif +/*for (int j = 0; j < ADC1_CHANNEL_MAX; j++) + { + if (counts[j] != 0) + { + i2s_adc_buffer[j] = avgreadings[j] / counts[j]; + + // int32_t leastdiff = 4095; + // uint32_t idx = 0; + // for (size_t k = 0; k < counts[j]; k++) + // { + // int32_t diff = abs(int(i2s_adc_buffer[j]) - int(readings[j][k])); + // if (leastdiff > diff && diff != 0) + // { + // leastdiff = diff; + // idx = k; + // } + // } + // i2s_adc_buffer[j] = readings[j][idx]; + + // Serial.printf(">Channel%d:%d\n", j, i2s_adc_buffer[j]); + } + }*/ + + SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START); // Restart aquisition to buffer +} + +#if I2S_USE_INTERRUPT == true +static void IRAM_ATTR i2s_isr(void *arg) +{ +#if DEBUG_ADC == true + unsigned long fifostart = micros(); +#endif + + if (I2S0.int_st.rx_wfull) // fifo is full + { + readFiFo(); + } + + SET_PERI_REG_MASK(I2S_INT_CLR_REG(0), GET_PERI_REG_MASK(I2S_INT_ST_REG(0), 0xffff)); + // I2S0.int_clr.val = I2S0.int_st.val; // Clear all interrupt flags. + +#if DEBUG_ADC == true + fifotime = micros() - fifostart; +#endif +} +#endif + +void printdbg(){ + #if DEBUG_ADC == true + // skipped++; + // if (skipped >= 1000) + { + // skipped = 0; + unsigned long now = micros(); + volatile uint32_t interr = intcnt; + volatile uint32_t samplesss = readscnt; + intcnt = 0; + readscnt = 0; + + float readspersec = (1000000.0f * interr) / (now - ts); + float samplespersec = (1000000.0f * samplesss) / (now - ts); + + ts = now; + Serial.printf(">ips:%f\n", readspersec); + Serial.printf(">sps:%f\n", samplespersec); // readspersec * GET_PERI_REG_BITS2(I2S_FIFO_CONF_REG(0), I2S_RX_DATA_NUM_M, I2S_RX_DATA_NUM_S)); //I2S0.fifo_conf.rx_data_num + Serial.printf(">fifo:%ld\n", fifotime); + Serial.printf(">doubles:%ld\n", equal); + Serial.printf(">bufreads:%d\n", buffersread); + // if(equal > 0){ + // volatile uint32_t aktuell = currfifo; + // volatile uint32_t zuletzt = lastfifo; + + // Serial.printf("\n|\nlast: "); + // for (int i = 31; i >= 15; i--) + // { + // Serial.printf("%d",(zuletzt >> i ) & 1); + // } + // Serial.printf(" "); + // for (int i = 15; i >= 0; i--) + // { + // Serial.printf("%d",(zuletzt >> i ) & 1); + // } + + // Serial.printf("\ncurr: "); + // for (int i = 31; i >= 15; i--) + // { + // Serial.printf("%d",(aktuell >> i ) & 1); + // } + // Serial.printf(" "); + // for (int i = 15; i >= 0; i--) + // { + // Serial.printf("%d",(aktuell >> i ) & 1); + // } + // Serial.printf("\n"); + + // } + + for (size_t i = 0; i < ADC1_CHANNEL_MAX; i++) + { + Serial.printf(">Channel%d:%d\n", i, i2s_adc_buffer[i]); + } + } + #endif +} + +// Contrary to its name (so it can be called by the library), this function reads the already converted values from fifo +// and prints optional debug information. +// When using interrupt driven sampling, it only prints debug information. +void IRAM_ATTR _startADC3PinConversionLowSide() +{ +#if I2S_USE_INTERRUPT != true + if (sampleOnCommand) + { + readFiFo(); + } +#endif +} + +void IRAM_ATTR _startADC3PinConversionInline(){ + _startADC3PinConversionLowSide(); +} + +// Takes the buffered adc counts and returns the coresponding float voltage for a pin. +float IRAM_ATTR _readADCVoltageI2S(const int pin, const void *cs_params) +{ + float adc_voltage_conv = ((ESP32MCPWMCurrentSenseParams *)cs_params)->adc_voltage_conv; + + return i2s_adc_buffer[digitalPinToAnalogChannel(pin)] * adc_voltage_conv; +} + +// Sets up the I2S peripheral and ADC. Can be run multiple times to configure multiple motors. +void* IRAM_ATTR _configureI2S(const bool lowside, const void* driver_params, const int pinA, const int pinB, const int pinC){ + sampleOnCommand = !lowside; + + mcpwm_unit_t unit = ((ESP32MCPWMDriverParams*)driver_params)->mcpwm_unit; + + if( _isset(pinA) ) channels[digitalPinToAnalogChannel(pinA)] = 1; // pinMode(pinA, GPIO_MODE_DISABLE); + if( _isset(pinB) ) channels[digitalPinToAnalogChannel(pinB)] = 1; // pinMode(pinB, GPIO_MODE_DISABLE); + if( _isset(pinC) ) channels[digitalPinToAnalogChannel(pinC)] = 1; // pinMode(pinC, GPIO_MODE_DISABLE); + + int activeChannels = 0; + u_int some_channel = 0; + for (int i = 0; i < ADC1_CHANNEL_MAX; i++) + { + activeChannels += channels[i]; + if (channels[i]) + { + some_channel = channels[i]; + } + } + globalActiveChannels = activeChannels; + + ESP32MCPWMCurrentSenseParams* params = new ESP32MCPWMCurrentSenseParams { + .pins = { pinA, pinB, pinC }, + .adc_voltage_conv = (_ADC_VOLTAGE)/(_ADC_RESOLUTION), + .mcpwm_unit = unit + }; + + periph_module_reset(PERIPH_I2S0_MODULE); + periph_module_enable(PERIPH_I2S0_MODULE); + + // ESP_ERROR_CHECK(i2s_set_adc_mode(ADC_UNIT_1, (adc1_channel_t) some_channel)); + ESP_ERROR_CHECK(i2s_set_adc_mode(ADC_UNIT_1, ADC1_CHANNEL_0)); + + // Taken from https://github.com/pycom/esp-idf-2.0/blob/master/components/bootloader_support/src/bootloader_random.c + // The set values are good I guess? + DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN); + CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_FORCE_START_TOP); + CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_START_TOP); + + SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S); + SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE); + CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE); + SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX); + SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_CLK_DIV, 4, SYSCON_SARADC_SAR_CLK_DIV_S); + SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAMPLE_CYCLE, 16, SYSCON_SARADC_SAMPLE_CYCLE_S); + + SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_RSTB_WAIT, 8, SYSCON_SARADC_RSTB_WAIT_S); + SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 10, SYSCON_SARADC_START_WAIT_S); + SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_WORK_MODE, 0, SYSCON_SARADC_WORK_MODE_S); + CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL); + CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_SAR_SEL); + + SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_RX_BCK_DIV_NUM, 20, I2S_RX_BCK_DIV_NUM_S); + + SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG,SYSCON_SARADC_DATA_TO_I2S); + CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN); + SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN); + SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE); + SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START); + // End + + I2S0.conf_chan.rx_chan_mod = 2; + + I2S0.fifo_conf.rx_data_num = max(2, min(63, (globalActiveChannels * BUF_LEN) / 2)); + I2S0.fifo_conf.dscr_en = 0; // disable dma transfer. + + I2S0.int_ena.val = 0; +#if I2S_USE_INTERRUPT == true + I2S0.int_ena.rx_wfull = 1; + +// I2S0.int_ena.rx_take_data = 1; +// I2S0.int_ena.rx_rempty = 1; +#endif + + // ADC setting + int channelnum = 0; + for (size_t i = 0; i < ADC1_CHANNEL_MAX; i++) + { + if (channelnum <= 4 && channels[i] == 1) + { + SYSCON.saradc_sar1_patt_tab[0] |= ((i << 4) | (ADC_WIDTH_BIT_12 << 2) | ADC_ATTEN_DB_11) << (3 - channelnum) * 8; + channelnum++; + } + else if (channelnum > 4 && channels[i] == 1) + { + SYSCON.saradc_sar1_patt_tab[1] |= ((i << 4) | (ADC_WIDTH_BIT_12 << 2) | ADC_ATTEN_DB_11) << (3 - channelnum) * 8; + channelnum++; + } + } + + // Scan multiple channels. + SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR1_PATT_LEN, channelnum - 1, SYSCON_SARADC_SAR1_PATT_LEN_S); + + if (!running) + { +#if I2S_USE_INTERRUPT == true + ESP_ERROR_CHECK(esp_intr_alloc(ETS_I2S0_INTR_SOURCE, ESP_INTR_FLAG_IRAM, i2s_isr, NULL, NULL)); +#endif + + running = true; + } + + return params; +} + +#endif \ No newline at end of file diff --git a/src/current_sense/hardware_specific/esp32/esp32_i2s_driver.h b/src/current_sense/hardware_specific/esp32/esp32_i2s_driver.h new file mode 100644 index 00000000..b04fc44e --- /dev/null +++ b/src/current_sense/hardware_specific/esp32/esp32_i2s_driver.h @@ -0,0 +1,27 @@ +#ifndef SIMPLEFOC_ESP32_HAL_I2S_DRIVER_H_ +#define SIMPLEFOC_ESP32_HAL_I2S_DRIVER_H_ + +#include "Arduino.h" + +#if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) + +// This function reads data from the I2S FIFO and processes it to obtain average readings for each channel. +// The ADC counts get saved in uint32_t i2s_adc_buffer[]. +void readFiFo(); + +void printdbg(); + +// Contrary to its name (so it can be called by the library), this function reads the already converted values from fifo +// and prints optional debug information. +// When using interrupt driven sampling, it only prints debug information. +void _startADC3PinConversionLowSide(); +void _startADC3PinConversionInline(); + +// Takes the buffered adc counts and returns the coresponding float voltage for a pin. +float _readADCVoltageI2S(const int pin, const void *cs_params); + +// Sets up the I2S peripheral and ADC. Can be run multiple times to configure multiple motors. +void* _configureI2S(const bool lowside, const void* driver_params, const int pinA, const int pinB, const int pinC); + +#endif /* SIMPLEFOC_ESP32_HAL_I2S_DRIVER_H_ */ +#endif /* ESP32 */ \ No newline at end of file diff --git a/src/current_sense/hardware_specific/esp32/esp32_mcu.cpp b/src/current_sense/hardware_specific/esp32/esp32_mcu.cpp index 2057463c..17caeaf8 100644 --- a/src/current_sense/hardware_specific/esp32/esp32_mcu.cpp +++ b/src/current_sense/hardware_specific/esp32/esp32_mcu.cpp @@ -5,6 +5,7 @@ #if defined(ESP_H) && defined(ARDUINO_ARCH_ESP32) && defined(SOC_MCPWM_SUPPORTED) && !defined(SIMPLEFOC_ESP32_USELEDC) #include "esp32_adc_driver.h" +#include "esp32_i2s_driver.h" #include "driver/mcpwm.h" #include "soc/mcpwm_reg.h" @@ -15,7 +16,8 @@ #define _ADC_VOLTAGE 3.3f #define _ADC_RESOLUTION 4095.0f - +#define _I2S_ADC true +#define SAMPLE_BOTH false typedef struct ESP32MCPWMCurrentSenseParams { int pins[3]; @@ -29,13 +31,21 @@ typedef struct ESP32MCPWMCurrentSenseParams { * Inline adc reading implementation */ // function reading an ADC value and returning the read voltage -float _readADCVoltageInline(const int pinA, const void* cs_params){ +float _readADCVoltageInline(const int pinA, const void *cs_params) +{ +#if _I2S_ADC == true + return _readADCVoltageI2S(pinA, cs_params); +#else uint32_t raw_adc = adcRead(pinA); - return raw_adc * ((ESP32MCPWMCurrentSenseParams*)cs_params)->adc_voltage_conv; + return raw_adc * ((ESP32MCPWMCurrentSenseParams *)cs_params)->adc_voltage_conv; +#endif } // function reading an ADC value and returning the read voltage void* _configureADCInline(const void* driver_params, const int pinA, const int pinB, const int pinC){ +#if _I2S_ADC == true + return _configureI2S(false, driver_params, pinA, pinB, pinC); +#else _UNUSED(driver_params); if( _isset(pinA) ) pinMode(pinA, INPUT); @@ -46,8 +56,8 @@ void* _configureADCInline(const void* driver_params, const int pinA, const int p .pins = { pinA, pinB, pinC }, .adc_voltage_conv = (_ADC_VOLTAGE)/(_ADC_RESOLUTION) }; - return params; +#endif } @@ -67,7 +77,10 @@ uint32_t adc_buffer[2][6]={0}; int adc_read_index[2]={0}; // function reading an ADC value and returning the read voltage -float _readADCVoltageLowSide(const int pin, const void* cs_params){ +float IRAM_ATTR _readADCVoltageLowSide(const int pin, const void* cs_params){ +#if _I2S_ADC == true + return _readADCVoltageI2S(pin, cs_params); +#else mcpwm_unit_t unit = ((ESP32MCPWMCurrentSenseParams*)cs_params)->mcpwm_unit; int buffer_index = ((ESP32MCPWMCurrentSenseParams*)cs_params)->buffer_index; float adc_voltage_conv = ((ESP32MCPWMCurrentSenseParams*)cs_params)->adc_voltage_conv; @@ -78,11 +91,14 @@ float _readADCVoltageLowSide(const int pin, const void* cs_params){ } // not found return 0; +#endif } // function configuring low-side current sensing void* _configureADCLowSide(const void* driver_params, const int pinA,const int pinB,const int pinC){ - +#if _I2S_ADC == true + return _configureI2S(true, driver_params, pinA, pinB, pinC); +#else mcpwm_unit_t unit = ((ESP32MCPWMDriverParams*)driver_params)->mcpwm_unit; int index_start = adc_pin_count[unit]; if( _isset(pinA) ) adc_pins[unit][adc_pin_count[unit]++] = pinA; @@ -101,6 +117,7 @@ void* _configureADCLowSide(const void* driver_params, const int pinA,const int p }; return params; +#endif } @@ -108,57 +125,76 @@ void _driverSyncLowSide(void* driver_params, void* cs_params){ mcpwm_dev_t* mcpwm_dev = ((ESP32MCPWMDriverParams*)driver_params)->mcpwm_dev; mcpwm_unit_t mcpwm_unit = ((ESP32MCPWMDriverParams*)driver_params)->mcpwm_unit; - - // low-side register enable interrupt - mcpwm_dev->int_ena.timer0_tep_int_ena = true;//A PWM timer 0 TEP event will trigger this interrupt - // high side registers enable interrupt - //mcpwm_dev->int_ena.timer0_tep_int_ena = true;//A PWM timer 0 TEZ event will trigger this interrupt - + #if SAMPLE_BOTH == true + // low-side & high side register enable interrupt + mcpwm_dev->int_ena.timer0_tep_int_ena = true;//A PWM timer 0 TEP event will trigger this interrupt + mcpwm_dev->int_ena.timer0_tez_int_ena = true;//A PWM timer 0 TEZ event will trigger this interrupt + #else + // low-side register enable interrupt + mcpwm_dev->int_ena.timer0_tep_int_ena = true;//A PWM timer 0 TEP event will trigger this interrupt + // high side registers enable interrupt + // mcpwm_dev->int_ena.timer0_tep_int_ena = true;//A PWM timer 0 TEZ event will trigger this interrupt + #endif // register interrupts (mcpwm number, interrupt handler, handler argument = NULL, interrupt signal/flag, return handler = NULL) if(mcpwm_unit == MCPWM_UNIT_0) - mcpwm_isr_register(mcpwm_unit, mcpwm0_isr_handler, NULL, ESP_INTR_FLAG_IRAM, NULL); //Set ISR Handler + mcpwm_isr_register(mcpwm_unit, mcpwm0_isr_handler, NULL, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1, NULL); //Set ISR Handler else - mcpwm_isr_register(mcpwm_unit, mcpwm1_isr_handler, NULL, ESP_INTR_FLAG_IRAM, NULL); //Set ISR Handler + mcpwm_isr_register(mcpwm_unit, mcpwm1_isr_handler, NULL, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_LEVEL1, NULL); //Set ISR Handler } static void IRAM_ATTR mcpwm0_isr_handler(void*) __attribute__ ((unused)); // Read currents when interrupt is triggered static void IRAM_ATTR mcpwm0_isr_handler(void*){ - // // high side - // uint32_t mcpwm_intr_status = MCPWM0.int_st.timer0_tez_int_st; - + // high side + uint32_t mcpwm_intr_status_high = MCPWM0.int_st.timer0_tez_int_st; + // low side - uint32_t mcpwm_intr_status = MCPWM0.int_st.timer0_tep_int_st; - if(mcpwm_intr_status){ - adc_buffer[0][adc_read_index[0]] = adcRead(adc_pins[0][adc_read_index[0]]); - adc_read_index[0]++; - if(adc_read_index[0] == adc_pin_count[0]) adc_read_index[0] = 0; + uint32_t mcpwm_intr_status_low = MCPWM0.int_st.timer0_tep_int_st; + + bool runadc = mcpwm_intr_status_high || mcpwm_intr_status_low; + + if(runadc){ + #if _I2S_ADC == true + readFiFo(); + #else + adc_buffer[0][adc_read_index[0]] = adcRead(adc_pins[0][adc_read_index[0]]); + adc_read_index[0]++; + if(adc_read_index[0] == adc_pin_count[0]) adc_read_index[0] = 0; + #endif } + // low side - MCPWM0.int_clr.timer0_tep_int_clr = mcpwm_intr_status; + MCPWM0.int_clr.timer0_tep_int_clr = mcpwm_intr_status_low; // high side - // MCPWM0.int_clr.timer0_tez_int_clr = mcpwm_intr_status_0; + MCPWM0.int_clr.timer0_tez_int_clr = mcpwm_intr_status_high; } static void IRAM_ATTR mcpwm1_isr_handler(void*) __attribute__ ((unused)); // Read currents when interrupt is triggered static void IRAM_ATTR mcpwm1_isr_handler(void*){ - // // high side - // uint32_t mcpwm_intr_status = MCPWM1.int_st.timer0_tez_int_st; - + // high side + uint32_t mcpwm_intr_status_high = MCPWM1.int_st.timer0_tez_int_st; + // low side - uint32_t mcpwm_intr_status = MCPWM1.int_st.timer0_tep_int_st; - if(mcpwm_intr_status){ - adc_buffer[1][adc_read_index[1]] = adcRead(adc_pins[1][adc_read_index[1]]); - adc_read_index[1]++; - if(adc_read_index[1] == adc_pin_count[1]) adc_read_index[1] = 0; + uint32_t mcpwm_intr_status_low = MCPWM1.int_st.timer0_tep_int_st; + + bool runadc = mcpwm_intr_status_high || mcpwm_intr_status_low; + + if(runadc){ + #if _I2S_ADC == true + readFiFo(); + #else + adc_buffer[1][adc_read_index[1]] = adcRead(adc_pins[1][adc_read_index[1]]); + adc_read_index[1]++; + if(adc_read_index[1] == adc_pin_count[1]) adc_read_index[1] = 0; + #endif } // low side - MCPWM1.int_clr.timer0_tep_int_clr = mcpwm_intr_status; + MCPWM1.int_clr.timer0_tep_int_clr = mcpwm_intr_status_low; // high side - // MCPWM1.int_clr.timer0_tez_int_clr = mcpwm_intr_status_0; + MCPWM1.int_clr.timer0_tez_int_clr = mcpwm_intr_status_high; }