mirror of
https://github.com/esphome/esphome.git
synced 2025-10-31 23:21:54 +00:00
init commit for nrf52
This commit is contained in:
@@ -35,6 +35,7 @@ from esphome.const import (
|
|||||||
PLATFORM_ESP8266,
|
PLATFORM_ESP8266,
|
||||||
PLATFORM_RP2040,
|
PLATFORM_RP2040,
|
||||||
SECRETS_FILES,
|
SECRETS_FILES,
|
||||||
|
PLATFORM_NRF52,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, EsphomeError, coroutine
|
from esphome.core import CORE, EsphomeError, coroutine
|
||||||
from esphome.helpers import indent, is_ip_address
|
from esphome.helpers import indent, is_ip_address
|
||||||
@@ -297,6 +298,38 @@ def upload_using_platformio(config, port):
|
|||||||
return platformio_api.run_platformio_cli_run(config, CORE.verbose, *upload_args)
|
return platformio_api.run_platformio_cli_run(config, CORE.verbose, *upload_args)
|
||||||
|
|
||||||
|
|
||||||
|
def update_progress(progress=0, done=False, log_message=""):
|
||||||
|
import click
|
||||||
|
|
||||||
|
del done, log_message # Unused parameters
|
||||||
|
if progress == 0:
|
||||||
|
return
|
||||||
|
|
||||||
|
if progress % 40 == 0:
|
||||||
|
click.echo("#", nl=True)
|
||||||
|
else:
|
||||||
|
click.echo("#", nl=False)
|
||||||
|
|
||||||
|
|
||||||
|
def upload_adafruit_nrfutil(config, port):
|
||||||
|
from esphome import platformio_api
|
||||||
|
from pathlib import Path
|
||||||
|
from nordicsemi.dfu.dfu_transport_serial import DfuTransportSerial
|
||||||
|
from nordicsemi.dfu.dfu_transport import DfuEvent
|
||||||
|
from nordicsemi.dfu.dfu import Dfu
|
||||||
|
|
||||||
|
idedata = platformio_api.get_idedata(config)
|
||||||
|
dfu_package = str(Path(idedata.firmware_elf_path).with_suffix(".zip"))
|
||||||
|
serial_backend = DfuTransportSerial(port)
|
||||||
|
serial_backend.register_events_callback(DfuEvent.PROGRESS_EVENT, update_progress)
|
||||||
|
dfu = Dfu(dfu_package, dfu_transport=serial_backend)
|
||||||
|
|
||||||
|
try:
|
||||||
|
dfu.dfu_send_images()
|
||||||
|
except Exception as e:
|
||||||
|
raise EsphomeError(f"Unable to send image: {e}")
|
||||||
|
|
||||||
|
|
||||||
def upload_program(config, args, host):
|
def upload_program(config, args, host):
|
||||||
if get_port_type(host) == "SERIAL":
|
if get_port_type(host) == "SERIAL":
|
||||||
if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
|
if CORE.target_platform in (PLATFORM_ESP32, PLATFORM_ESP8266):
|
||||||
@@ -309,7 +342,10 @@ def upload_program(config, args, host):
|
|||||||
if CORE.target_platform in (PLATFORM_BK72XX, PLATFORM_RTL87XX):
|
if CORE.target_platform in (PLATFORM_BK72XX, PLATFORM_RTL87XX):
|
||||||
return upload_using_platformio(config, host)
|
return upload_using_platformio(config, host)
|
||||||
|
|
||||||
return 1 # Unknown target platform
|
if CORE.target_platform in (PLATFORM_NRF52):
|
||||||
|
return upload_adafruit_nrfutil(config, host)
|
||||||
|
|
||||||
|
raise EsphomeError(f"Unknown target platform: {CORE.target_platform}")
|
||||||
|
|
||||||
if CONF_OTA not in config:
|
if CONF_OTA not in config:
|
||||||
raise EsphomeError(
|
raise EsphomeError(
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ from esphome.const import (
|
|||||||
PLATFORM_ESP32,
|
PLATFORM_ESP32,
|
||||||
PLATFORM_ESP8266,
|
PLATFORM_ESP8266,
|
||||||
PLATFORM_RP2040,
|
PLATFORM_RP2040,
|
||||||
|
PLATFORM_NRF52,
|
||||||
)
|
)
|
||||||
from esphome.core import CORE, EsphomeError, Lambda, coroutine_with_priority
|
from esphome.core import CORE, EsphomeError, Lambda, coroutine_with_priority
|
||||||
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant
|
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant
|
||||||
@@ -101,6 +102,8 @@ ESP_ARDUINO_UNSUPPORTED_USB_UARTS = [USB_SERIAL_JTAG]
|
|||||||
|
|
||||||
UART_SELECTION_RP2040 = [USB_CDC, UART0, UART1]
|
UART_SELECTION_RP2040 = [USB_CDC, UART0, UART1]
|
||||||
|
|
||||||
|
UART_SELECTION_NRF52 = [USB_CDC]
|
||||||
|
|
||||||
HARDWARE_UART_TO_UART_SELECTION = {
|
HARDWARE_UART_TO_UART_SELECTION = {
|
||||||
UART0: logger_ns.UART_SELECTION_UART0,
|
UART0: logger_ns.UART_SELECTION_UART0,
|
||||||
UART0_SWAP: logger_ns.UART_SELECTION_UART0_SWAP,
|
UART0_SWAP: logger_ns.UART_SELECTION_UART0_SWAP,
|
||||||
@@ -140,6 +143,8 @@ def uart_selection(value):
|
|||||||
component = get_libretiny_component()
|
component = get_libretiny_component()
|
||||||
if component in UART_SELECTION_LIBRETINY:
|
if component in UART_SELECTION_LIBRETINY:
|
||||||
return cv.one_of(*UART_SELECTION_LIBRETINY[component], upper=True)(value)
|
return cv.one_of(*UART_SELECTION_LIBRETINY[component], upper=True)(value)
|
||||||
|
if CORE.is_nrf52:
|
||||||
|
return cv.one_of(*UART_SELECTION_NRF52, upper=True)(value)
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
||||||
@@ -179,6 +184,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
rp2040=USB_CDC,
|
rp2040=USB_CDC,
|
||||||
bk72xx=DEFAULT,
|
bk72xx=DEFAULT,
|
||||||
rtl87xx=DEFAULT,
|
rtl87xx=DEFAULT,
|
||||||
|
nrf52=USB_CDC,
|
||||||
): cv.All(
|
): cv.All(
|
||||||
cv.only_on(
|
cv.only_on(
|
||||||
[
|
[
|
||||||
@@ -187,6 +193,7 @@ CONFIG_SCHEMA = cv.All(
|
|||||||
PLATFORM_RP2040,
|
PLATFORM_RP2040,
|
||||||
PLATFORM_BK72XX,
|
PLATFORM_BK72XX,
|
||||||
PLATFORM_RTL87XX,
|
PLATFORM_RTL87XX,
|
||||||
|
PLATFORM_NRF52,
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
uart_selection,
|
uart_selection,
|
||||||
@@ -263,7 +270,7 @@ async def to_code(config):
|
|||||||
if config.get(CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH):
|
if config.get(CONF_ESP8266_STORE_LOG_STRINGS_IN_FLASH):
|
||||||
cg.add_build_flag("-DUSE_STORE_LOG_STR_IN_FLASH")
|
cg.add_build_flag("-DUSE_STORE_LOG_STR_IN_FLASH")
|
||||||
|
|
||||||
if CORE.using_arduino:
|
if CORE.using_arduino and not CORE.is_nrf52:
|
||||||
if config[CONF_HARDWARE_UART] == USB_CDC:
|
if config[CONF_HARDWARE_UART] == USB_CDC:
|
||||||
cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=1")
|
cg.add_build_flag("-DARDUINO_USB_CDC_ON_BOOT=1")
|
||||||
if CORE.is_esp32 and get_esp32_variant() == VARIANT_ESP32C3:
|
if CORE.is_esp32 and get_esp32_variant() == VARIANT_ESP32C3:
|
||||||
|
|||||||
@@ -26,6 +26,10 @@
|
|||||||
#include "esphome/core/hal.h"
|
#include "esphome/core/hal.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
|
||||||
|
#ifdef USE_NRF52
|
||||||
|
#include <Adafruit_TinyUSB.h> // for Serial
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace esphome {
|
namespace esphome {
|
||||||
namespace logger {
|
namespace logger {
|
||||||
|
|
||||||
@@ -228,10 +232,11 @@ void Logger::pre_setup() {
|
|||||||
if (this->baud_rate_ > 0) {
|
if (this->baud_rate_ > 0) {
|
||||||
#ifdef USE_ARDUINO
|
#ifdef USE_ARDUINO
|
||||||
switch (this->uart_) {
|
switch (this->uart_) {
|
||||||
|
#ifndef USE_NRF52
|
||||||
case UART_SELECTION_UART0:
|
case UART_SELECTION_UART0:
|
||||||
#ifdef USE_ESP8266
|
#ifdef USE_ESP8266
|
||||||
case UART_SELECTION_UART0_SWAP:
|
case UART_SELECTION_UART0_SWAP:
|
||||||
#endif
|
#endif // USE_ESP8266
|
||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
this->hw_serial_ = &Serial1;
|
this->hw_serial_ = &Serial1;
|
||||||
Serial1.begin(this->baud_rate_);
|
Serial1.begin(this->baud_rate_);
|
||||||
@@ -242,14 +247,15 @@ void Logger::pre_setup() {
|
|||||||
#else
|
#else
|
||||||
this->hw_serial_ = &Serial;
|
this->hw_serial_ = &Serial;
|
||||||
Serial.begin(this->baud_rate_);
|
Serial.begin(this->baud_rate_);
|
||||||
#endif
|
#endif // ARDUINO_USB_CDC_ON_BOOT
|
||||||
#endif
|
#endif // USE_RP2040
|
||||||
|
#endif // USE_NRF52
|
||||||
#ifdef USE_ESP8266
|
#ifdef USE_ESP8266
|
||||||
if (this->uart_ == UART_SELECTION_UART0_SWAP) {
|
if (this->uart_ == UART_SELECTION_UART0_SWAP) {
|
||||||
Serial.swap();
|
Serial.swap();
|
||||||
}
|
}
|
||||||
Serial.setDebugOutput(ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE);
|
Serial.setDebugOutput(ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE);
|
||||||
#endif
|
#endif // USE_ESP8266
|
||||||
break;
|
break;
|
||||||
case UART_SELECTION_UART1:
|
case UART_SELECTION_UART1:
|
||||||
#ifdef USE_RP2040
|
#ifdef USE_RP2040
|
||||||
@@ -258,10 +264,10 @@ void Logger::pre_setup() {
|
|||||||
#else
|
#else
|
||||||
this->hw_serial_ = &Serial1;
|
this->hw_serial_ = &Serial1;
|
||||||
Serial1.begin(this->baud_rate_);
|
Serial1.begin(this->baud_rate_);
|
||||||
#endif
|
#endif // USE_RP2040
|
||||||
#ifdef USE_ESP8266
|
#ifdef USE_ESP8266
|
||||||
Serial1.setDebugOutput(ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE);
|
Serial1.setDebugOutput(ESPHOME_LOG_LEVEL >= ESPHOME_LOG_LEVEL_VERBOSE);
|
||||||
#endif
|
#endif // USE_ESP8266
|
||||||
break;
|
break;
|
||||||
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
#if defined(USE_ESP32) && !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
||||||
!defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
|
!defined(USE_ESP32_VARIANT_ESP32S2) && !defined(USE_ESP32_VARIANT_ESP32S3)
|
||||||
@@ -290,7 +296,7 @@ void Logger::pre_setup() {
|
|||||||
#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32C3
|
#endif // USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32C3
|
||||||
break;
|
break;
|
||||||
#endif // USE_ESP32 && (USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32C3)
|
#endif // USE_ESP32 && (USE_ESP32_VARIANT_ESP32S2 || USE_ESP32_VARIANT_ESP32S3 || USE_ESP32_VARIANT_ESP32C3)
|
||||||
#ifdef USE_RP2040
|
#if defined(USE_RP2040) || defined(USE_NRF52)
|
||||||
case UART_SELECTION_USB_CDC:
|
case UART_SELECTION_USB_CDC:
|
||||||
this->hw_serial_ = &Serial;
|
this->hw_serial_ = &Serial;
|
||||||
Serial.begin(this->baud_rate_);
|
Serial.begin(this->baud_rate_);
|
||||||
@@ -401,7 +407,7 @@ void Logger::set_log_level(const std::string &tag, int log_level) {
|
|||||||
this->log_levels_.push_back(LogLevelOverride{tag, log_level});
|
this->log_levels_.push_back(LogLevelOverride{tag, log_level});
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY)
|
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_NRF52)
|
||||||
UARTSelection Logger::get_uart() const { return this->uart_; }
|
UARTSelection Logger::get_uart() const { return this->uart_; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace esphome {
|
|||||||
|
|
||||||
namespace logger {
|
namespace logger {
|
||||||
|
|
||||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY)
|
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_NRF52)
|
||||||
/** Enum for logging UART selection
|
/** Enum for logging UART selection
|
||||||
*
|
*
|
||||||
* Advanced configuration (pin selection, etc) is not supported.
|
* Advanced configuration (pin selection, etc) is not supported.
|
||||||
@@ -37,7 +37,9 @@ enum UARTSelection {
|
|||||||
UART_SELECTION_UART1,
|
UART_SELECTION_UART1,
|
||||||
UART_SELECTION_UART2,
|
UART_SELECTION_UART2,
|
||||||
#else
|
#else
|
||||||
|
#ifndef USE_NRF52
|
||||||
UART_SELECTION_UART0 = 0,
|
UART_SELECTION_UART0 = 0,
|
||||||
|
#endif
|
||||||
UART_SELECTION_UART1,
|
UART_SELECTION_UART1,
|
||||||
#if defined(USE_ESP32)
|
#if defined(USE_ESP32)
|
||||||
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
#if !defined(USE_ESP32_VARIANT_ESP32C3) && !defined(USE_ESP32_VARIANT_ESP32C6) && \
|
||||||
@@ -58,7 +60,7 @@ enum UARTSelection {
|
|||||||
#ifdef USE_ESP8266
|
#ifdef USE_ESP8266
|
||||||
UART_SELECTION_UART0_SWAP,
|
UART_SELECTION_UART0_SWAP,
|
||||||
#endif // USE_ESP8266
|
#endif // USE_ESP8266
|
||||||
#ifdef USE_RP2040
|
#if defined(USE_RP2040) || defined(USE_NRF52)
|
||||||
UART_SELECTION_USB_CDC,
|
UART_SELECTION_USB_CDC,
|
||||||
#endif // USE_RP2040
|
#endif // USE_RP2040
|
||||||
#endif // USE_LIBRETINY
|
#endif // USE_LIBRETINY
|
||||||
@@ -78,7 +80,7 @@ class Logger : public Component {
|
|||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP_IDF
|
||||||
uart_port_t get_uart_num() const { return uart_num_; }
|
uart_port_t get_uart_num() const { return uart_num_; }
|
||||||
#endif
|
#endif
|
||||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY)
|
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040) || defined(USE_LIBRETINY) || defined(USE_NRF52)
|
||||||
void set_uart_selection(UARTSelection uart_selection) { uart_ = uart_selection; }
|
void set_uart_selection(UARTSelection uart_selection) { uart_ = uart_selection; }
|
||||||
/// Get the UART used by the logger.
|
/// Get the UART used by the logger.
|
||||||
UARTSelection get_uart() const;
|
UARTSelection get_uart() const;
|
||||||
@@ -165,6 +167,9 @@ class Logger : public Component {
|
|||||||
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040)
|
#if defined(USE_ESP32) || defined(USE_ESP8266) || defined(USE_RP2040)
|
||||||
UARTSelection uart_{UART_SELECTION_UART0};
|
UARTSelection uart_{UART_SELECTION_UART0};
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef USE_NRF52
|
||||||
|
UARTSelection uart_{UART_SELECTION_USB_CDC};
|
||||||
|
#endif
|
||||||
#ifdef USE_LIBRETINY
|
#ifdef USE_LIBRETINY
|
||||||
UARTSelection uart_{UART_SELECTION_DEFAULT};
|
UARTSelection uart_{UART_SELECTION_DEFAULT};
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
112
esphome/components/nrf52/gpio.cpp
Normal file
112
esphome/components/nrf52/gpio.cpp
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
#ifdef USE_NRF52
|
||||||
|
|
||||||
|
#include "gpio.h"
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nrf52 {
|
||||||
|
|
||||||
|
static const char *const TAG = "nrf52";
|
||||||
|
|
||||||
|
static int IRAM_ATTR flags_to_mode(gpio::Flags flags, uint8_t pin) {
|
||||||
|
// For nRF52 extra modes are available.
|
||||||
|
// Standard drive is typically 2mA (min 1mA) '0' sink (low) or '1' source (high). High drive (VDD > 2.7V) is typically 10mA low, 9mA high (min 6mA)
|
||||||
|
// OUTPUT_S0S1 Standard '0', standard '1' same as OUTPUT
|
||||||
|
// OUTPUT_H0S1 High drive '0', standard '1'
|
||||||
|
// OUTPUT_S0H1 Standard '0', high drive '1'
|
||||||
|
// OUTPUT_H0H1 High drive '0', high 'drive '1''
|
||||||
|
// OUTPUT_D0S1 Disconnect '0' standard '1' (normally used for wired-or connections)
|
||||||
|
// OUTPUT_D0H1 Disconnect '0', high drive '1' (normally used for wired-or connections)
|
||||||
|
// OUTPUT_S0D1 Standard '0'. disconnect '1' (normally used for wired-and connections)
|
||||||
|
// OUTPUT_H0D1 High drive '0', disconnect '1' (normally used for wired-and connections)
|
||||||
|
// NOTE P0.27 should be only low (standard) drive, low frequency
|
||||||
|
if (flags == gpio::FLAG_INPUT) { // NOLINT(bugprone-branch-clone)
|
||||||
|
return INPUT;
|
||||||
|
} else if (flags == gpio::FLAG_OUTPUT) {
|
||||||
|
return OUTPUT;
|
||||||
|
} else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLUP)) {
|
||||||
|
return INPUT_PULLUP;
|
||||||
|
} else if (flags == (gpio::FLAG_INPUT | gpio::FLAG_PULLDOWN)) {
|
||||||
|
return INPUT_PULLDOWN;
|
||||||
|
} else if (flags == (gpio::FLAG_OUTPUT | gpio::FLAG_OPEN_DRAIN)) {
|
||||||
|
return OUTPUT_S0D1;
|
||||||
|
} else {
|
||||||
|
return INPUT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ISRPinArg {
|
||||||
|
uint8_t pin;
|
||||||
|
bool inverted;
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO implement
|
||||||
|
//TODO test
|
||||||
|
void (*irq_cb)(void *);
|
||||||
|
void* irq_arg;
|
||||||
|
static void pin_irq(void){
|
||||||
|
irq_cb(irq_arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISRInternalGPIOPin NRF52GPIOPin::to_isr() const {
|
||||||
|
auto *arg = new ISRPinArg{}; // NOLINT(cppcoreguidelines-owning-memory)
|
||||||
|
arg->pin = pin_;
|
||||||
|
arg->inverted = inverted_;
|
||||||
|
return ISRInternalGPIOPin((void *) arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NRF52GPIOPin::attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const {
|
||||||
|
uint32_t mode = ISR_DEFERRED;
|
||||||
|
switch (type) {
|
||||||
|
case gpio::INTERRUPT_RISING_EDGE:
|
||||||
|
mode |= inverted_ ? FALLING : RISING;
|
||||||
|
break;
|
||||||
|
case gpio::INTERRUPT_FALLING_EDGE:
|
||||||
|
mode |= inverted_ ? RISING : FALLING;
|
||||||
|
break;
|
||||||
|
case gpio::INTERRUPT_ANY_EDGE:
|
||||||
|
mode |= CHANGE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq_cb = func;
|
||||||
|
irq_arg = arg;
|
||||||
|
attachInterrupt(pin_, pin_irq, mode);
|
||||||
|
}
|
||||||
|
void NRF52GPIOPin::pin_mode(gpio::Flags flags) {
|
||||||
|
pinMode(pin_, flags_to_mode(flags, pin_)); // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string NRF52GPIOPin::dump_summary() const {
|
||||||
|
char buffer[32];
|
||||||
|
snprintf(buffer, sizeof(buffer), "GPIO%u", pin_);
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NRF52GPIOPin::digital_read() {
|
||||||
|
return bool(digitalRead(pin_)) != inverted_; // NOLINT
|
||||||
|
}
|
||||||
|
void NRF52GPIOPin::digital_write(bool value) {
|
||||||
|
digitalWrite(pin_, value != inverted_ ? 1 : 0); // NOLINT
|
||||||
|
}
|
||||||
|
void NRF52GPIOPin::detach_interrupt() const {
|
||||||
|
detachInterrupt(pin_);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nrf52
|
||||||
|
|
||||||
|
// using namespace nrf52;
|
||||||
|
|
||||||
|
// TODO seems to not work???
|
||||||
|
bool IRAM_ATTR ISRInternalGPIOPin::digital_read() {
|
||||||
|
auto *arg = reinterpret_cast<nrf52::ISRPinArg *>(arg_);
|
||||||
|
return bool(digitalRead(arg->pin)) != arg->inverted; // NOLINT
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // USE_NRF52
|
||||||
38
esphome/components/nrf52/gpio.h
Normal file
38
esphome/components/nrf52/gpio.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef USE_NRF52
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include "esphome/core/hal.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace nrf52 {
|
||||||
|
|
||||||
|
class NRF52GPIOPin : public InternalGPIOPin {
|
||||||
|
public:
|
||||||
|
void set_pin(uint8_t pin) { pin_ = pin; }
|
||||||
|
void set_inverted(bool inverted) { inverted_ = inverted; }
|
||||||
|
void set_flags(gpio::Flags flags) { flags_ = flags; }
|
||||||
|
|
||||||
|
void setup() override { pin_mode(flags_); }
|
||||||
|
void pin_mode(gpio::Flags flags) override;
|
||||||
|
bool digital_read() override;
|
||||||
|
void digital_write(bool value) override;
|
||||||
|
std::string dump_summary() const override;
|
||||||
|
void detach_interrupt() const override;
|
||||||
|
ISRInternalGPIOPin to_isr() const override;
|
||||||
|
uint8_t get_pin() const override { return pin_; }
|
||||||
|
bool is_inverted() const override { return inverted_; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void attach_interrupt(void (*func)(void *), void *arg, gpio::InterruptType type) const override;
|
||||||
|
|
||||||
|
uint8_t pin_;
|
||||||
|
bool inverted_;
|
||||||
|
gpio::Flags flags_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nrf52
|
||||||
|
} // namespace esphome
|
||||||
|
|
||||||
|
#endif // USE_NRF52
|
||||||
58
esphome/components/nrf52/gpio.py
Normal file
58
esphome/components/nrf52/gpio.py
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
from esphome import pins
|
||||||
|
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_ID,
|
||||||
|
CONF_MODE,
|
||||||
|
CONF_INVERTED,
|
||||||
|
CONF_NUMBER,
|
||||||
|
)
|
||||||
|
|
||||||
|
nrf52_ns = cg.esphome_ns.namespace("nrf52")
|
||||||
|
NRF52GPIOPin = nrf52_ns.class_("NRF52GPIOPin", cg.InternalGPIOPin)
|
||||||
|
|
||||||
|
|
||||||
|
def _translate_pin(value):
|
||||||
|
if isinstance(value, dict) or value is None:
|
||||||
|
raise cv.Invalid(
|
||||||
|
"This variable only supports pin numbers, not full pin schemas "
|
||||||
|
"(with inverted and mode)."
|
||||||
|
)
|
||||||
|
if isinstance(value, int):
|
||||||
|
return value
|
||||||
|
try:
|
||||||
|
return int(value)
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
# e.g. P0.27
|
||||||
|
if len(value) >= len("P0.0") and value[0] == "P" and value[2] == ".":
|
||||||
|
return cv.int_(value[len("P")].strip()) * 32 + cv.int_(
|
||||||
|
value[len("P0.") :].strip()
|
||||||
|
)
|
||||||
|
raise cv.Invalid(f"Invalid pin: {value}")
|
||||||
|
|
||||||
|
|
||||||
|
def validate_gpio_pin(value):
|
||||||
|
value = _translate_pin(value)
|
||||||
|
if value < 0 or value > (32 + 16):
|
||||||
|
raise cv.Invalid(f"NRF52: Invalid pin number: {value}")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
NRF52_PIN_SCHEMA = cv.All(
|
||||||
|
pins.gpio_base_schema(
|
||||||
|
NRF52GPIOPin,
|
||||||
|
validate_gpio_pin,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pins.PIN_SCHEMA_REGISTRY.register("nrf52", NRF52_PIN_SCHEMA)
|
||||||
|
async def nrf52_pin_to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
num = config[CONF_NUMBER]
|
||||||
|
cg.add(var.set_pin(num))
|
||||||
|
cg.add(var.set_inverted(config[CONF_INVERTED]))
|
||||||
|
cg.add(var.set_flags(pins.gpio_flags_expr(config[CONF_MODE])))
|
||||||
|
return var
|
||||||
@@ -1548,6 +1548,7 @@ class SplitDefault(Optional):
|
|||||||
bk72xx=vol.UNDEFINED,
|
bk72xx=vol.UNDEFINED,
|
||||||
rtl87xx=vol.UNDEFINED,
|
rtl87xx=vol.UNDEFINED,
|
||||||
host=vol.UNDEFINED,
|
host=vol.UNDEFINED,
|
||||||
|
nrf52=vol.UNDEFINED,
|
||||||
):
|
):
|
||||||
super().__init__(key)
|
super().__init__(key)
|
||||||
self._esp8266_default = vol.default_factory(esp8266)
|
self._esp8266_default = vol.default_factory(esp8266)
|
||||||
@@ -1579,6 +1580,7 @@ class SplitDefault(Optional):
|
|||||||
self._bk72xx_default = vol.default_factory(bk72xx)
|
self._bk72xx_default = vol.default_factory(bk72xx)
|
||||||
self._rtl87xx_default = vol.default_factory(rtl87xx)
|
self._rtl87xx_default = vol.default_factory(rtl87xx)
|
||||||
self._host_default = vol.default_factory(host)
|
self._host_default = vol.default_factory(host)
|
||||||
|
self._nrf52 = vol.default_factory(nrf52)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def default(self):
|
def default(self):
|
||||||
@@ -1621,6 +1623,8 @@ class SplitDefault(Optional):
|
|||||||
return self._rtl87xx_default
|
return self._rtl87xx_default
|
||||||
if CORE.is_host:
|
if CORE.is_host:
|
||||||
return self._host_default
|
return self._host_default
|
||||||
|
if CORE.is_nrf52:
|
||||||
|
return self._nrf52
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
@default.setter
|
@default.setter
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ PLATFORM_HOST = "host"
|
|||||||
PLATFORM_BK72XX = "bk72xx"
|
PLATFORM_BK72XX = "bk72xx"
|
||||||
PLATFORM_RTL87XX = "rtl87xx"
|
PLATFORM_RTL87XX = "rtl87xx"
|
||||||
PLATFORM_LIBRETINY_OLDSTYLE = "libretiny"
|
PLATFORM_LIBRETINY_OLDSTYLE = "libretiny"
|
||||||
|
PLATFORM_NRF52 = "nrf52"
|
||||||
|
|
||||||
TARGET_PLATFORMS = [
|
TARGET_PLATFORMS = [
|
||||||
PLATFORM_ESP32,
|
PLATFORM_ESP32,
|
||||||
@@ -23,6 +24,7 @@ TARGET_PLATFORMS = [
|
|||||||
PLATFORM_BK72XX,
|
PLATFORM_BK72XX,
|
||||||
PLATFORM_RTL87XX,
|
PLATFORM_RTL87XX,
|
||||||
PLATFORM_LIBRETINY_OLDSTYLE,
|
PLATFORM_LIBRETINY_OLDSTYLE,
|
||||||
|
PLATFORM_NRF52,
|
||||||
]
|
]
|
||||||
|
|
||||||
SOURCE_FILE_EXTENSIONS = {".cpp", ".hpp", ".h", ".c", ".tcc", ".ino"}
|
SOURCE_FILE_EXTENSIONS = {".cpp", ".hpp", ".h", ".c", ".tcc", ".ino"}
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ from esphome.const import (
|
|||||||
PLATFORM_RTL87XX,
|
PLATFORM_RTL87XX,
|
||||||
PLATFORM_RP2040,
|
PLATFORM_RP2040,
|
||||||
PLATFORM_HOST,
|
PLATFORM_HOST,
|
||||||
|
PLATFORM_NRF52,
|
||||||
)
|
)
|
||||||
from esphome.coroutine import FakeAwaitable as _FakeAwaitable
|
from esphome.coroutine import FakeAwaitable as _FakeAwaitable
|
||||||
from esphome.coroutine import FakeEventLoop as _FakeEventLoop
|
from esphome.coroutine import FakeEventLoop as _FakeEventLoop
|
||||||
@@ -659,6 +660,10 @@ class EsphomeCore:
|
|||||||
def is_host(self):
|
def is_host(self):
|
||||||
return self.target_platform == PLATFORM_HOST
|
return self.target_platform == PLATFORM_HOST
|
||||||
|
|
||||||
|
@property
|
||||||
|
def is_nrf52(self):
|
||||||
|
return self.target_platform == PLATFORM_NRF52
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def target_framework(self):
|
def target_framework(self):
|
||||||
return self.data[KEY_CORE][KEY_TARGET_FRAMEWORK]
|
return self.data[KEY_CORE][KEY_TARGET_FRAMEWORK]
|
||||||
|
|||||||
@@ -20,6 +20,8 @@
|
|||||||
#elif defined(USE_LIBRETINY)
|
#elif defined(USE_LIBRETINY)
|
||||||
#include <FreeRTOS.h>
|
#include <FreeRTOS.h>
|
||||||
#include <semphr.h>
|
#include <semphr.h>
|
||||||
|
#elif defined(USE_NRF52)
|
||||||
|
#include <Arduino.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define HOT __attribute__((hot))
|
#define HOT __attribute__((hot))
|
||||||
@@ -546,7 +548,7 @@ class Mutex {
|
|||||||
Mutex &operator=(const Mutex &) = delete;
|
Mutex &operator=(const Mutex &) = delete;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if defined(USE_ESP32) || defined(USE_LIBRETINY)
|
#if defined(USE_ESP32) || defined(USE_LIBRETINY) || defined(USE_NRF52)
|
||||||
SemaphoreHandle_t handle_;
|
SemaphoreHandle_t handle_;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user