diff --git a/platform/drivers/baseband/AT1846S_SA8x8.cpp b/platform/drivers/baseband/AT1846S_SA8x8.cpp
new file mode 100644
index 00000000..edbacac1
--- /dev/null
+++ b/platform/drivers/baseband/AT1846S_SA8x8.cpp
@@ -0,0 +1,238 @@
+/***************************************************************************
+ * Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, see *
+ **************************************************************************/
+
+#include
+
+#include
+#include
+
+#include
+#include "AT1846S.h"
+
+#define SA8X8_MSG_SIZE 32
+
+char rx_buf[SA8X8_MSG_SIZE] = { 0 };
+
+void AT1846S::init()
+{
+ i2c_writeReg16(0x30, 0x0001); // Soft reset
+ delayMs(50);
+
+ i2c_writeReg16(0x30, 0x0004); // Chip enable
+ i2c_writeReg16(0x04, 0x0FD0); // 26MHz crystal frequency
+ i2c_writeReg16(0x1F, 0x1000); // Gpio6 squelch output
+ i2c_writeReg16(0x09, 0x03AC);
+ i2c_writeReg16(0x24, 0x0001);
+ i2c_writeReg16(0x31, 0x0031);
+ i2c_writeReg16(0x33, 0x45F5); // AGC number
+ i2c_writeReg16(0x34, 0x2B89); // RX digital gain
+ i2c_writeReg16(0x3F, 0x3263); // RSSI 3 threshold
+ i2c_writeReg16(0x41, 0x470F); // Tx digital gain
+ i2c_writeReg16(0x42, 0x1036);
+ i2c_writeReg16(0x43, 0x00BB);
+ i2c_writeReg16(0x44, 0x06FF); // Tx digital gain
+ i2c_writeReg16(0x47, 0x7F2F); // Soft mute
+ i2c_writeReg16(0x4E, 0x0082);
+ i2c_writeReg16(0x4F, 0x2C62);
+ i2c_writeReg16(0x53, 0x0094);
+ i2c_writeReg16(0x54, 0x2A3C);
+ i2c_writeReg16(0x55, 0x0081);
+ i2c_writeReg16(0x56, 0x0B02);
+ i2c_writeReg16(0x57, 0x1C00); // Bypass RSSI low-pass
+ i2c_writeReg16(0x5A, 0x4935); // SQ detection time
+ i2c_writeReg16(0x58, 0xBCCD);
+ i2c_writeReg16(0x62, 0x3263); // Modulation detect tresh
+ i2c_writeReg16(0x4E, 0x2082);
+ i2c_writeReg16(0x63, 0x16AD);
+ i2c_writeReg16(0x30, 0x40A4);
+ delayMs(50);
+
+ i2c_writeReg16(0x30, 0x40A6); // Start calibration
+ delayMs(100);
+ i2c_writeReg16(0x30, 0x4006); // Stop calibration
+
+ delayMs(100);
+
+ i2c_writeReg16(0x58, 0xBCED);
+ i2c_writeReg16(0x0A, 0x7BA0); // PGA gain
+ i2c_writeReg16(0x41, 0x4731); // Tx digital gain
+ i2c_writeReg16(0x44, 0x05FF); // Tx digital gain
+ i2c_writeReg16(0x59, 0x09D2); // Mixer gain
+ i2c_writeReg16(0x44, 0x05CF); // Tx digital gain
+ i2c_writeReg16(0x44, 0x05CC); // Tx digital gain
+ i2c_writeReg16(0x48, 0x1A32); // Noise 1 threshold
+ i2c_writeReg16(0x60, 0x1A32); // Noise 2 threshold
+ i2c_writeReg16(0x3F, 0x29D1); // RSSI 3 threshold
+ i2c_writeReg16(0x0A, 0x7BA0); // PGA gain
+ i2c_writeReg16(0x49, 0x0C96); // RSSI SQL thresholds
+ i2c_writeReg16(0x33, 0x45F5); // AGC number
+ i2c_writeReg16(0x41, 0x470F); // Tx digital gain
+ i2c_writeReg16(0x42, 0x1036);
+ i2c_writeReg16(0x43, 0x00BB);
+}
+
+void AT1846S::setBandwidth(const AT1846S_BW band)
+{
+ if(band == AT1846S_BW::_25)
+ {
+ // 25kHz bandwidth
+ i2c_writeReg16(0x15, 0x1F00); // Tuning bit
+ i2c_writeReg16(0x32, 0x7564); // AGC target power
+ i2c_writeReg16(0x3A, 0x44C3); // Modulation detect sel
+ i2c_writeReg16(0x3F, 0x29D2); // RSSI 3 threshold
+ i2c_writeReg16(0x3C, 0x0E1C); // Peak detect threshold
+ i2c_writeReg16(0x48, 0x1E38); // Noise 1 threshold
+ i2c_writeReg16(0x62, 0x3767); // Modulation detect tresh
+ i2c_writeReg16(0x65, 0x248A);
+ i2c_writeReg16(0x66, 0xFF2E); // RSSI comp and AFC range
+ i2c_writeReg16(0x7F, 0x0001); // Switch to page 1
+ i2c_writeReg16(0x06, 0x0024); // AGC gain table
+ i2c_writeReg16(0x07, 0x0214);
+ i2c_writeReg16(0x08, 0x0224);
+ i2c_writeReg16(0x09, 0x0314);
+ i2c_writeReg16(0x0A, 0x0324);
+ i2c_writeReg16(0x0B, 0x0344);
+ i2c_writeReg16(0x0D, 0x1384);
+ i2c_writeReg16(0x0E, 0x1B84);
+ i2c_writeReg16(0x0F, 0x3F84);
+ i2c_writeReg16(0x12, 0xE0EB);
+ i2c_writeReg16(0x7F, 0x0000); // Back to page 0
+ maskSetRegister(0x30, 0x3000, 0x3000);
+ }
+ else
+ {
+ // 12.5kHz bandwidth
+ i2c_writeReg16(0x15, 0x1100); // Tuning bit
+ i2c_writeReg16(0x32, 0x4495); // AGC target power
+ i2c_writeReg16(0x3A, 0x40C3); // Modulation detect sel
+ i2c_writeReg16(0x3F, 0x28D0); // RSSI 3 threshold
+ i2c_writeReg16(0x3C, 0x0F1E); // Peak detect threshold
+ i2c_writeReg16(0x48, 0x1DB6); // Noise 1 threshold
+ i2c_writeReg16(0x62, 0x1425); // Modulation detect tresh
+ i2c_writeReg16(0x65, 0x2494);
+ i2c_writeReg16(0x66, 0xEB2E); // RSSI comp and AFC range
+ i2c_writeReg16(0x7F, 0x0001); // Switch to page 1
+ i2c_writeReg16(0x06, 0x0014); // AGC gain table
+ i2c_writeReg16(0x07, 0x020C);
+ i2c_writeReg16(0x08, 0x0214);
+ i2c_writeReg16(0x09, 0x030C);
+ i2c_writeReg16(0x0A, 0x0314);
+ i2c_writeReg16(0x0B, 0x0324);
+ i2c_writeReg16(0x0C, 0x0344);
+ i2c_writeReg16(0x0D, 0x1344);
+ i2c_writeReg16(0x0E, 0x1B44);
+ i2c_writeReg16(0x0F, 0x3F44);
+ i2c_writeReg16(0x12, 0xE0EB); // Back to page 0
+ i2c_writeReg16(0x7F, 0x0000);
+ maskSetRegister(0x30, 0x3000, 0x0000);
+ }
+
+ reloadConfig();
+}
+
+void AT1846S::setOpMode(const AT1846S_OpMode mode)
+{
+ if(mode == AT1846S_OpMode::DMR)
+ {
+ // DMR mode
+ i2c_writeReg16(0x3A, 0x00C2);
+ i2c_writeReg16(0x33, 0x45F5);
+ i2c_writeReg16(0x41, 0x4731);
+ i2c_writeReg16(0x42, 0x1036);
+ i2c_writeReg16(0x43, 0x00BB);
+ i2c_writeReg16(0x58, 0xBCFD); // Bit 0 = 1: CTCSS LPF bandwidth to 250Hz
+ // Bit 3 = 1: bypass CTCSS HPF
+ // Bit 4 = 1: bypass CTCSS LPF
+ // Bit 5 = 1: bypass voice LPF
+ // Bit 6 = 1: bypass voice HPF
+ // Bit 7 = 1: bypass pre/de-emphasis
+ // Bit 11 = 1: bypass VOX HPF
+ // Bit 12 = 1: bypass VOX LPF
+ // Bit 13 = 1: bypass RSSI LPF
+ i2c_writeReg16(0x44, 0x06CC);
+ i2c_writeReg16(0x40, 0x0031);
+ }
+ else
+ {
+ // FM mode
+ i2c_writeReg16(0x33, 0x44A5);
+ i2c_writeReg16(0x41, 0x4431);
+ i2c_writeReg16(0x42, 0x10F0);
+ i2c_writeReg16(0x43, 0x00A9);
+ i2c_writeReg16(0x58, 0xBC05); // Bit 0 = 1: CTCSS LPF badwidth to 250Hz
+ // Bit 3 = 0: enable CTCSS HPF
+ // Bit 4 = 0: enable CTCSS LPF
+ // Bit 5 = 0: enable voice LPF
+ // Bit 6 = 0: enable voice HPF
+ // Bit 7 = 0: enable pre/de-emphasis
+ // Bit 11 = 1: bypass VOX HPF
+ // Bit 12 = 1: bypass VOX LPF
+ // Bit 13 = 1: bypass RSSI LPF
+ i2c_writeReg16(0x44, 0x06FF);
+ i2c_writeReg16(0x40, 0x0030);
+
+ maskSetRegister(0x57, 0x0001, 0x00); // Audio feedback off
+ maskSetRegister(0x3A, 0x7000, 0x4000); // Select voice channel
+ }
+
+ reloadConfig();
+}
+
+/*
+ * Implementation of AT1846S I2C interface through SA8x8
+ */
+
+static constexpr uint8_t devAddr = 0xE2;
+
+void AT1846S::i2c_init()
+{
+ // I2C already init'd by platform support package
+}
+
+/*
+ * These callbacks needs to be implemented by the platform, providing functions
+ * to read and write from the serial port
+ */
+extern void radio_uartPrint(const char *fmt, ...);
+extern void radio_uartScan(char *buf);
+
+void AT1846S::i2c_writeReg16(uint8_t reg, uint16_t value)
+{
+ /*
+ * SA8x8 with sa8x8_fw uses PEEK and POKE AT commands to write to AT1846S
+ */
+ radio_uartPrint("AT+POKE=%d,%d\r\n", reg, value);
+ radio_uartScan(rx_buf);
+ // Check that response is "OK\r"
+ if (strncmp(rx_buf, "OK\r", 3))
+ printk("SA8x8 Error: %d <- %d\n", reg, value);
+}
+
+uint16_t AT1846S::i2c_readReg16(uint8_t reg)
+{
+ /*
+ * SA8x8 with sa8x8_fw uses PEEK and POKE AT commands to write to AT1846S
+ */
+ int32_t value = 0;
+ radio_uartPrint("AT+PEEK=%d\r\n", reg);
+ radio_uartScan(rx_buf);
+ sscanf(rx_buf, "%d\r", &value);
+ return value;
+}
diff --git a/platform/drivers/baseband/radio_ttwrplus.cpp b/platform/drivers/baseband/radio_ttwrplus.cpp
new file mode 100644
index 00000000..3b77a808
--- /dev/null
+++ b/platform/drivers/baseband/radio_ttwrplus.cpp
@@ -0,0 +1,313 @@
+/***************************************************************************
+ * Copyright (C) 2021 - 2023 by Federico Amedeo Izzo IU2NUO, *
+ * Niccolò Izzo IU2KIN *
+ * Frederik Saraci IU2NRO *
+ * Silvano Seva IU2KWO *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 3 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, see *
+ ***************************************************************************/
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "AT1846S.h"
+#include "radioUtils.h"
+
+/*
+ * Define radio node to control the SA868
+ */
+#if DT_NODE_HAS_STATUS(DT_ALIAS(radio), okay)
+#define UART_RADIO_DEV_NODE DT_ALIAS(radio)
+#else
+#error "Please select the correct radio UART device"
+#endif
+
+#define SA8X8_MSG_SIZE 32
+
+K_MSGQ_DEFINE(uart_msgq, SA8X8_MSG_SIZE, 10, 4);
+
+/* receive buffer used in UART ISR callback */
+static char rx_buf[SA8X8_MSG_SIZE];
+static uint16_t rx_buf_pos;
+
+static const struct device *const radio_dev = DEVICE_DT_GET(UART_RADIO_DEV_NODE);
+
+#define RADIO_PDN_NODE DT_ALIAS(radio_pdn)
+
+static const struct gpio_dt_spec radio_pdn = GPIO_DT_SPEC_GET(RADIO_PDN_NODE, gpios);
+
+
+const rtxStatus_t *config; // Pointer to data structure with radio configuration
+
+Band currRxBand = BND_NONE; // Current band for RX
+Band currTxBand = BND_NONE; // Current band for TX
+
+enum opstatus radioStatus; // Current operating status
+
+AT1846S& at1846s = AT1846S::instance(); // AT1846S driver
+
+void radio_serialCb(const struct device *dev, void *user_data)
+{
+ uint8_t c;
+
+ if (!uart_irq_update(radio_dev)) {
+ return;
+ }
+
+ if (!uart_irq_rx_ready(radio_dev)) {
+ return;
+ }
+
+ /* read until FIFO empty */
+ while (uart_fifo_read(radio_dev, &c, 1) == 1) {
+ if (c == '\n' && rx_buf_pos > 0) {
+ /* terminate string */
+ rx_buf[rx_buf_pos] = '\0';
+
+ /* if queue is full, message is silently dropped */
+ k_msgq_put(&uart_msgq, &rx_buf, K_NO_WAIT);
+
+ /* reset the buffer (it was copied to the msgq) */
+ rx_buf_pos = 0;
+ } else if (rx_buf_pos < (sizeof(rx_buf) - 1)) {
+ rx_buf[rx_buf_pos++] = c;
+ }
+ /* else: characters beyond buffer size are dropped */
+ }
+}
+
+void radio_uartPrint(const char *fmt, ...)
+{
+ char buf[SA8X8_MSG_SIZE] = { 0 };
+ va_list args;
+ va_start(args, fmt);
+ vsnprintk(buf, SA8X8_MSG_SIZE, fmt, args);
+ int msg_len = strnlen(buf, SA8X8_MSG_SIZE);
+ for (uint16_t i = 0; i < msg_len; i++) {
+ uart_poll_out(radio_dev, buf[i]);
+ }
+ va_end(args);
+}
+
+void radio_uartScan(char *buf)
+{
+ k_msgq_get(&uart_msgq, buf, K_FOREVER);
+}
+
+char *radio_getFwVersion()
+{
+ char *tx_buf = (char *) malloc(sizeof(char) * SA8X8_MSG_SIZE);
+ radio_uartPrint("AT+VERSION\r\n");
+ k_msgq_get(&uart_msgq, tx_buf, K_FOREVER);
+ return tx_buf;
+}
+
+void radio_init(const rtxStatus_t *rtxState)
+{
+ config = rtxState;
+ radioStatus = OFF;
+ int ret;
+
+ // Initialize GPIO for SA868S power down
+ if (!gpio_is_ready_dt(&radio_pdn)) {
+ printk("Error: radio device %s is not ready\n",
+ radio_pdn.port->name);
+ }
+
+ ret = gpio_pin_configure_dt(&radio_pdn, GPIO_OUTPUT);
+ if (ret != 0) {
+ printk("Error %d: failed to configure %s pin %d\n", ret, radio_pdn.port->name, radio_pdn.pin);
+ }
+
+ if (!device_is_ready(radio_dev)) {
+ printk("UART device not found!\n");
+ return;
+ }
+
+ ret = uart_irq_callback_user_data_set(radio_dev, radio_serialCb, NULL);
+
+ if (ret < 0) {
+ if (ret == -ENOTSUP) {
+ printk("Interrupt-driven UART support not enabled\n");
+ } else if (ret == -ENOSYS) {
+ printk("UART device does not support interrupt-driven API\n");
+ } else {
+ printk("Error setting UART callback: %d\n", ret);
+ }
+
+ return;
+ }
+
+ uart_irq_rx_enable(radio_dev);
+
+ ret = gpio_pin_toggle_dt(&radio_pdn);
+ if (ret != 0) {
+ printk("Failed to toggle radio power down");
+ return;
+ }
+
+ // Add SA8x8 FW version to Info menu
+ ui_registerInfoExtraEntry("Radio", radio_getFwVersion);
+
+ // TODO: Implement audio paths configuration
+
+ /*
+ * Configure AT1846S, keep AF output disabled at power on.
+ */
+ at1846s.init();
+}
+
+void radio_disableRtx()
+{
+ at1846s.disableCtcss();
+ at1846s.setFuncMode(AT1846S_FuncMode::OFF);
+ radioStatus = OFF;
+}
+
+void radio_terminate()
+{
+ radio_disableRtx();
+ at1846s.terminate();
+}
+
+void radio_tuneVcxo(const int16_t vhfOffset, const int16_t uhfOffset)
+{
+ //TODO: this part will be implemented in the future, when proved to be
+ // necessary.
+ (void) vhfOffset;
+ (void) uhfOffset;
+}
+
+void radio_setOpmode(const enum opmode mode)
+{
+ switch(mode)
+ {
+ case OPMODE_FM:
+ at1846s.setOpMode(AT1846S_OpMode::FM); // AT1846S in FM mode
+ break;
+
+ case OPMODE_DMR:
+ at1846s.setOpMode(AT1846S_OpMode::DMR);
+ at1846s.setBandwidth(AT1846S_BW::_12P5);
+ break;
+
+ case OPMODE_M17:
+ at1846s.setOpMode(AT1846S_OpMode::DMR); // AT1846S in DMR mode, disables RX filter
+ at1846s.setBandwidth(AT1846S_BW::_25); // Set bandwidth to 25kHz for proper deviation
+ break;
+
+ default:
+ break;
+ }
+}
+
+bool radio_checkRxDigitalSquelch()
+{
+ return at1846s.rxCtcssDetected();
+}
+
+void radio_enableAfOutput()
+{
+ ;
+}
+
+void radio_disableAfOutput()
+{
+ ;
+}
+
+void radio_enableRx()
+{
+ if(currRxBand == BND_NONE) return;
+
+ at1846s.setFrequency(config->rxFrequency);
+ at1846s.setFuncMode(AT1846S_FuncMode::RX);
+
+ if(config->rxToneEn)
+ {
+ at1846s.enableRxCtcss(config->rxTone);
+ }
+
+ radioStatus = RX;
+}
+
+void radio_enableTx()
+{
+ // TODO; Do not enable Tx until proven to be safe
+ return;
+ if(config->txDisable == 1) return;
+
+ at1846s.setFrequency(config->txFrequency);
+ at1846s.setFuncMode(AT1846S_FuncMode::TX);
+
+ if(config->txToneEn)
+ {
+ at1846s.enableTxCtcss(config->txTone);
+ }
+
+ radioStatus = TX;
+}
+
+void radio_updateConfiguration()
+{
+ currRxBand = getBandFromFrequency(config->rxFrequency);
+ currTxBand = getBandFromFrequency(config->txFrequency);
+
+ if((currRxBand == BND_NONE) || (currTxBand == BND_NONE)) return;
+
+ // Set bandwidth, only for analog FM mode
+ if(config->opMode == OPMODE_FM)
+ {
+ switch(config->bandwidth)
+ {
+ case BW_12_5:
+ at1846s.setBandwidth(AT1846S_BW::_12P5);
+ break;
+
+ case BW_20:
+ case BW_25:
+ at1846s.setBandwidth(AT1846S_BW::_25);
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /*
+ * Update VCO frequency and tuning parameters if current operating status
+ * is different from OFF.
+ * This is done by calling again the corresponding functions, which is safe
+ * to do and avoids code duplication.
+ */
+ if(radioStatus == RX) radio_enableRx();
+ if(radioStatus == TX) radio_enableTx();
+}
+
+float radio_getRssi()
+{
+ return static_cast< float > (at1846s.readRSSI());
+}
+
+enum opstatus radio_getStatus()
+{
+ return radioStatus;
+}
diff --git a/platform/mcu/ESP32S3/zephyr.conf b/platform/mcu/ESP32S3/zephyr.conf
index ef4c4719..5bad2a51 100644
--- a/platform/mcu/ESP32S3/zephyr.conf
+++ b/platform/mcu/ESP32S3/zephyr.conf
@@ -4,6 +4,7 @@ CONFIG_CPP=y
CONFIG_REQUIRES_FULL_LIBCPP=y
CONFIG_STD_CPP14=y
CONFIG_PRINTK=y
+CONFIG_PRINTK_SYNC=y
CONFIG_LOG=y
CONFIG_LOG_PRINTK=y
CONFIG_LOG_MODE_IMMEDIATE=y
diff --git a/platform/targets/ttwrplus/CMakeLists.txt b/platform/targets/ttwrplus/CMakeLists.txt
index b3b1fbf2..f0fc0ece 100644
--- a/platform/targets/ttwrplus/CMakeLists.txt
+++ b/platform/targets/ttwrplus/CMakeLists.txt
@@ -14,11 +14,12 @@ target_sources(app
${OPENRTX_ROOT}/platform/drivers/display/SH1106_ttwrplus.c
${OPENRTX_ROOT}/platform/drivers/keyboard/keyboard_ttwrplus.c
+ ${OPENRTX_ROOT}/platform/drivers/baseband/radio_ttwrplus.cpp
+ ${OPENRTX_ROOT}/platform/drivers/baseband/AT1846S_SA8x8.cpp
${OPENRTX_ROOT}/platform/drivers/stubs/audio_stub.c
${OPENRTX_ROOT}/platform/drivers/stubs/cps_io_stub.c
${OPENRTX_ROOT}/platform/drivers/stubs/nvmem_stub.c
- ${OPENRTX_ROOT}/platform/drivers/stubs/radio_stub.c
${OPENRTX_ROOT}/subprojects/XPowersLib/src/XPowersLibInterface.cpp
)
diff --git a/platform/targets/ttwrplus/platform.c b/platform/targets/ttwrplus/platform.c
index 79838f5a..a53d8e19 100644
--- a/platform/targets/ttwrplus/platform.c
+++ b/platform/targets/ttwrplus/platform.c
@@ -23,6 +23,7 @@
#include
#include
+#include
#include "pmu.h"
#define BUTTON_PTT_NODE DT_NODELABEL(button_ptt)
@@ -33,10 +34,12 @@ static const struct device *const qdec_dev = DEVICE_DT_GET(DT_ALIAS(qdec0));
static const hwInfo_t hwInfo =
{
+ .name = "ttwrplus",
+ .hw_version = 0,
+ .uhf_band = 1,
+ .vhf_band = 0,
.uhf_maxFreq = 430,
.uhf_minFreq = 440,
- .uhf_band = 1,
- .name = "ttwrplus"
};
void platform_init()
diff --git a/platform/targets/ttwrplus/ttwrplus.dts b/platform/targets/ttwrplus/ttwrplus.dts
index d1f1faf9..8c07cfb4 100644
--- a/platform/targets/ttwrplus/ttwrplus.dts
+++ b/platform/targets/ttwrplus/ttwrplus.dts
@@ -18,6 +18,9 @@
i2c-0 = &i2c0;
watchdog0 = &wdt0;
radio = &uart0;
+ radio-pwr = &radio_pwr;
+ radio-pdn = &radio_pdn;
+ radio-ptt = &radio_ptt;
qdec0 = &pcnt;
};
@@ -29,6 +32,25 @@
zephyr,display = &ssd1306;
};
+ leds: leds {
+ compatible = "gpio-leds";
+
+ radio_pwr: radio_pwr {
+ gpios = <&gpio1 6 GPIO_ACTIVE_HIGH>;
+ label = "SA868S H/L on IO38";
+ };
+
+ radio_pdn: radio_pdn {
+ gpios = <&gpio1 8 GPIO_ACTIVE_LOW>;
+ label = "SA868S PDN on IO40";
+ };
+
+ radio_ptt: radio_ptt {
+ gpios = <&gpio1 9 GPIO_ACTIVE_HIGH>;
+ label = "SA868S PTT on IO41";
+ };
+ };
+
buttons: buttons {
compatible = "zephyr,gpio-keys";
diff --git a/platform/targets/ttwrplus/ttwrplus_defconfig b/platform/targets/ttwrplus/ttwrplus_defconfig
index cdcb1c52..6825fa34 100644
--- a/platform/targets/ttwrplus/ttwrplus_defconfig
+++ b/platform/targets/ttwrplus/ttwrplus_defconfig
@@ -10,5 +10,9 @@ CONFIG_DYNAMIC_THREAD_PREFER_POOL=y
CONFIG_DYNAMIC_THREAD_POOL_SIZE=4
CONFIG_COMMON_LIBC_MALLOC=y
CONFIG_COMMON_LIBC_MALLOC_ARENA_SIZE=131072
+CONFIG_NEWLIB_LIBC_MIN_REQUIRED_HEAP_SIZE=0
CONFIG_INPUT=y
CONFIG_SENSOR=y
+CONFIG_SERIAL=y
+CONFIG_UART_INTERRUPT_DRIVEN=y
+CONFIG_ASSERT=y