diff --git a/src/hm/hmRadio.h b/src/hm/hmRadio.h
index 54667571..78a7985e 100644
--- a/src/hm/hmRadio.h
+++ b/src/hm/hmRadio.h
@@ -9,7 +9,9 @@
 #include <RF24.h>
 #include "SPI.h"
 #include "radio.h"
+#if defined(CONFIG_IDF_TARGET_ESP32S3)
 #include "nrfHal.h"
+#endif
 
 #define SPI_SPEED           1000000
 
@@ -38,8 +40,6 @@ class HmRadio : public Radio {
         void setup(bool *serialDebug, bool *privacyMode, bool *printWholeTrace, uint8_t irq = IRQ_PIN, uint8_t ce = CE_PIN, uint8_t cs = CS_PIN, uint8_t sclk = SCLK_PIN, uint8_t mosi = MOSI_PIN, uint8_t miso = MISO_PIN) {
             DPRINTLN(DBG_VERBOSE, F("hmRadio.h:setup"));
             #if defined(CONFIG_IDF_TARGET_ESP32S3)
-            DBGPRINTLN("1");
-            delay(300);
             mNrfHal->init(mosi, miso, sclk, cs, ce);
             mNrf24 = new RF24(mNrfHal);
             #else
@@ -352,7 +352,9 @@ class HmRadio : public Radio {
 
         SPIClass* mSpi;
         RF24 *mNrf24;
+        #if defined(CONFIG_IDF_TARGET_ESP32S3)
         nrfHal *mNrfHal;
+        #endif
         Inverter<> *mLastIv = NULL;
 };
 
diff --git a/src/hms/cmt2300a.h b/src/hms/cmt2300a.h
index 24f71608..54e7095e 100644
--- a/src/hms/cmt2300a.h
+++ b/src/hms/cmt2300a.h
@@ -6,7 +6,11 @@
 #ifndef __CMT2300A_H__
 #define __CMT2300A_H__
 
+#if defined(CONFIG_IDF_TARGET_ESP32S3)
 #include "cmtHal.h"
+#else
+#include "esp32_3wSpi.h"
+#endif
 
 // detailed register infos from AN142_CMT2300AW_Quick_Start_Guide-Rev0.8.pdf
 
@@ -476,7 +480,11 @@ class Cmt2300a {
             return mSpi.readReg(CMT2300A_CUS_MODE_STA) & CMT2300A_MASK_CHIP_MODE_STA;
         }
 
+        #if defined(CONFIG_IDF_TARGET_ESP32S3)
         cmtHal mSpi;
+        #else
+        esp32_3wSpi mSpi;
+        #endif
         uint8_t mCnt;
         bool mTxPending;
         bool mInRxMode;
diff --git a/src/hms/esp32_3wSpi.h b/src/hms/esp32_3wSpi.h
new file mode 100644
index 00000000..20c42632
--- /dev/null
+++ b/src/hms/esp32_3wSpi.h
@@ -0,0 +1,183 @@
+//-----------------------------------------------------------------------------
+// 2023 Ahoy, https://github.com/lumpapu/ahoy
+// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
+//-----------------------------------------------------------------------------
+
+#ifndef __ESP32_3WSPI_H__
+#define __ESP32_3WSPI_H__
+
+#include "Arduino.h"
+#if defined(ESP32)
+#include "driver/spi_master.h"
+#include "esp_rom_gpio.h" // for esp_rom_gpio_connect_out_signal
+
+#define SPI_CLK     1 * 1000 * 1000 // 1MHz
+
+#define SPI_PARAM_LOCK() \
+    do {                 \
+    } while (xSemaphoreTake(paramLock, portMAX_DELAY) != pdPASS)
+#define SPI_PARAM_UNLOCK() xSemaphoreGive(paramLock)
+
+// for ESP32 this is the so-called HSPI
+// for ESP32-S2/S3/C3 this nomenclature does not really exist anymore,
+// it is simply the first externally usable hardware SPI master controller
+#define SPI_CMT SPI2_HOST
+
+class esp32_3wSpi {
+    public:
+        esp32_3wSpi() {
+            mInitialized = false;
+        }
+
+        void init(uint8_t pinSdio = DEF_CMT_SDIO, uint8_t pinSclk = DEF_CMT_SCLK, uint8_t pinCsb = DEF_CMT_CSB, uint8_t pinFcsb = DEF_CMT_FCSB) {
+            paramLock = xSemaphoreCreateMutex();
+            spi_bus_config_t buscfg = {
+                .mosi_io_num = pinSdio,
+                .miso_io_num = -1, // single wire MOSI/MISO
+                .sclk_io_num = pinSclk,
+                .quadwp_io_num = -1,
+                .quadhd_io_num = -1,
+                .max_transfer_sz = 32,
+            };
+            spi_device_interface_config_t devcfg = {
+                .command_bits = 1,
+                .address_bits = 7,
+                .dummy_bits = 0,
+                .mode = 0,
+                .cs_ena_pretrans = 1,
+                .cs_ena_posttrans = 1,
+                .clock_speed_hz = SPI_CLK,
+                .spics_io_num = pinCsb,
+                .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
+                .queue_size = 1,
+                .pre_cb = NULL,
+                .post_cb = NULL,
+            };
+
+            ESP_ERROR_CHECK(spi_bus_initialize(SPI_CMT, &buscfg, SPI_DMA_DISABLED));
+            ESP_ERROR_CHECK(spi_bus_add_device(SPI_CMT, &devcfg, &spi_reg));
+
+            // FiFo
+            spi_device_interface_config_t devcfg2 = {
+                .command_bits = 0,
+                .address_bits = 0,
+                .dummy_bits = 0,
+                .mode = 0,
+                .cs_ena_pretrans = 2,
+                .cs_ena_posttrans = (uint8_t)(1 / (SPI_CLK * 10e6 * 2) + 2), // >2 us
+                .clock_speed_hz = SPI_CLK,
+                .spics_io_num = pinFcsb,
+                .flags = SPI_DEVICE_HALFDUPLEX | SPI_DEVICE_3WIRE,
+                .queue_size = 1,
+                .pre_cb = NULL,
+                .post_cb = NULL,
+            };
+            ESP_ERROR_CHECK(spi_bus_add_device(SPI_CMT, &devcfg2, &spi_fifo));
+
+            esp_rom_gpio_connect_out_signal(pinSdio, spi_periph_signal[SPI_CMT].spid_out, true, false);
+            delay(100);
+
+            //pinMode(pinGpio3, INPUT);
+            mInitialized = true;
+        }
+
+        void writeReg(uint8_t addr, uint8_t reg) {
+            if(!mInitialized)
+                return;
+
+            uint8_t tx_data;
+            tx_data = ~reg;
+            spi_transaction_t t = {
+                .cmd = 1,
+                .addr = (uint64_t)(~addr),
+                .length = 8,
+                .tx_buffer = &tx_data,
+                .rx_buffer = NULL
+            };
+            SPI_PARAM_LOCK();
+            ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t));
+            SPI_PARAM_UNLOCK();
+            delayMicroseconds(100);
+        }
+
+        uint8_t readReg(uint8_t addr) {
+            if(!mInitialized)
+                return 0;
+
+            uint8_t rx_data;
+            spi_transaction_t t = {
+                .cmd = 0,
+                .addr = (uint64_t)(~addr),
+                .length = 8,
+                .rxlength = 8,
+                .tx_buffer = NULL,
+                .rx_buffer = &rx_data
+            };
+
+            SPI_PARAM_LOCK();
+            ESP_ERROR_CHECK(spi_device_polling_transmit(spi_reg, &t));
+            SPI_PARAM_UNLOCK();
+            delayMicroseconds(100);
+            return rx_data;
+        }
+
+        void writeFifo(uint8_t buf[], uint8_t len) {
+            if(!mInitialized)
+                return;
+            uint8_t tx_data;
+
+            spi_transaction_t t = {
+                .length    = 8,
+                .tx_buffer = &tx_data, // reference to write data
+                .rx_buffer = NULL
+            };
+
+            SPI_PARAM_LOCK();
+            for(uint8_t i = 0; i < len; i++) {
+                tx_data = ~buf[i]; // negate buffer contents
+                ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t));
+                delayMicroseconds(4); // > 4 us
+            }
+            SPI_PARAM_UNLOCK();
+        }
+
+        void readFifo(uint8_t buf[], uint8_t *len, uint8_t maxlen) {
+            if(!mInitialized)
+                return;
+            uint8_t rx_data;
+
+            spi_transaction_t t = {
+                .length = 8,
+                .rxlength = 8,
+                .tx_buffer = NULL,
+                .rx_buffer = &rx_data
+            };
+
+            SPI_PARAM_LOCK();
+            for(uint8_t i = 0; i < maxlen; i++) {
+                ESP_ERROR_CHECK(spi_device_polling_transmit(spi_fifo, &t));
+                delayMicroseconds(4); // > 4 us
+                if(0 == i)
+                    *len = rx_data;
+                else
+                    buf[i-1] = rx_data;
+            }
+            SPI_PARAM_UNLOCK();
+        }
+
+    private:
+        spi_device_handle_t spi_reg, spi_fifo;
+        bool mInitialized;
+        SemaphoreHandle_t paramLock = NULL;
+};
+#else
+    template<uint8_t CSB_PIN=5, uint8_t FCSB_PIN=4>
+    class esp32_3wSpi {
+        public:
+            esp32_3wSpi() {}
+            void setup() {}
+            void loop() {}
+    };
+#endif
+
+#endif /*__ESP32_3WSPI_H__*/