From c60f58039677cffeac418a9315750f720c7a90c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Niccol=C3=B2=20Izzo?= Date: Mon, 7 Aug 2023 09:02:43 +0200 Subject: [PATCH] ttwrplus: add support for SA868 Add support for initializing SA868 and querying its firmware version, created a new instance of the AT1846S class that leverages the SA8x8 serial connection as an i2c implementation. Rx works! In the sense that the RSSI bar behaves as expected, still no audio. This commit was contributed by edgetriggered. TG-553 --- platform/drivers/baseband/AT1846S_SA8x8.cpp | 238 ++++++++++++++ platform/drivers/baseband/radio_ttwrplus.cpp | 313 +++++++++++++++++++ platform/mcu/ESP32S3/zephyr.conf | 1 + platform/targets/ttwrplus/CMakeLists.txt | 3 +- platform/targets/ttwrplus/platform.c | 7 +- platform/targets/ttwrplus/ttwrplus.dts | 22 ++ platform/targets/ttwrplus/ttwrplus_defconfig | 4 + 7 files changed, 585 insertions(+), 3 deletions(-) create mode 100644 platform/drivers/baseband/AT1846S_SA8x8.cpp create mode 100644 platform/drivers/baseband/radio_ttwrplus.cpp 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