mxtommy / SigkSens

ESP8266 based SignalK Wifi Sensors
Apache License 2.0
38 stars 8 forks source link

Support MAX31850_OneWire library in ESP32 #67

Open mxtommy opened 5 years ago

mxtommy commented 5 years ago

I think I know how to add ESP32 support to the MAX31850_OneWire library. The two steps below allow SigkSens to compile for both of my ESP32 boards, and my Wemos D1 mino Lite, with the MAX31850_OneWire library instead of the standard OneWire library. I have not tested it with a MAX 31850 attached to my MCU yet, though.

First, install version 1.0.1 of the Adafruit MAX31850_OneWire library from GitHub: https://github.com/adafruit/MAX31850_OneWire (The Arduino Library Manager goes only to version 1.0.0.)

Then, copy this into MAX31850_OneWire/OneWire.h right after the #elif defined(ARDUINO_ARCH_ESP8266) section:

#elif defined(ARDUINO_ARCH_ESP32)
#include <driver/rtc_io.h>
#define PIN_TO_BASEREG(pin)             (0)
#define PIN_TO_BITMASK(pin)             (pin)
#define IO_REG_ASM
#define IO_REG_TYPE uint32_t
#define IO_REG_BASE_ATTR
#define IO_REG_MASK_ATTR

static inline __attribute__((always_inline))
IO_REG_TYPE directRead(IO_REG_TYPE pin)
{
    if ( pin < 32 )
        return (GPIO.in >> pin) & 0x1;
    else if ( pin < 40 )
        return (GPIO.in1.val >> (pin - 32)) & 0x1;

    return 0;
}

static inline __attribute__((always_inline))
void directWriteLow(IO_REG_TYPE pin)
{
    if ( pin < 32 )
        GPIO.out_w1tc = ((uint32_t)1 << pin);
    else if ( pin < 34 )
        GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32));
}

static inline __attribute__((always_inline))
void directWriteHigh(IO_REG_TYPE pin)
{
    if ( pin < 32 )
        GPIO.out_w1ts = ((uint32_t)1 << pin);
    else if ( pin < 34 )
        GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32));
}

static inline __attribute__((always_inline))
void directModeInput(IO_REG_TYPE pin)
{
    if ( digitalPinIsValid(pin) )
    {
        uint32_t rtc_reg(rtc_gpio_desc[pin].reg);

        if ( rtc_reg ) // RTC pins PULL settings
        {
            ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
            ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
        }

        if ( pin < 32 )
            GPIO.enable_w1tc = ((uint32_t)1 << pin);
        else
            GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32));

        uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
        pinFunction |= FUN_IE; // input enable but required for output as well?
        pinFunction |= ((uint32_t)2 << MCU_SEL_S);

        ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;

        GPIO.pin[pin].val = 0;
    }
}

static inline __attribute__((always_inline))
void directModeOutput(IO_REG_TYPE pin)
{
    if ( digitalPinIsValid(pin) && pin <= 33 ) // pins above 33 can be only inputs
    {
        uint32_t rtc_reg(rtc_gpio_desc[pin].reg);

        if ( rtc_reg ) // RTC pins PULL settings
        {
            ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux);
            ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown);
        }

        if ( pin < 32 )
            GPIO.enable_w1ts = ((uint32_t)1 << pin);
        else // already validated to pins <= 33
            GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32));

        uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers?
        pinFunction |= FUN_IE; // input enable but required for output as well?
        pinFunction |= ((uint32_t)2 << MCU_SEL_S);

        ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction;

        GPIO.pin[pin].val = 0;
    }
}

#define DIRECT_READ(base, pin)          directRead(pin)
#define DIRECT_WRITE_LOW(base, pin)     directWriteLow(pin)
#define DIRECT_WRITE_HIGH(base, pin)    directWriteHigh(pin)
#define DIRECT_MODE_INPUT(base, pin)    directModeInput(pin)
#define DIRECT_MODE_OUTPUT(base, pin)   directModeOutput(pin)
// https://github.com/PaulStoffregen/OneWire/pull/47
// https://github.com/stickbreaker/OneWire/commit/6eb7fc1c11a15b6ac8c60e5671cf36eb6829f82c
#ifdef  interrupts
#undef  interrupts
#endif
#ifdef  noInterrupts
#undef  noInterrupts
#endif
#define noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux)
#define interrupts() portEXIT_CRITICAL(&mux);}
//#warning "ESP32 OneWire testing"

Originally posted by @ba58smith in https://github.com/mxtommy/SigkSens/pull/60#issuecomment-450000161

mxtommy commented 5 years ago

Closed PR, so moved to this new issue :)