From 584545808d4733004878601f5b45eb822d413b46 Mon Sep 17 00:00:00 2001
From: Davide Mor <davide.mor@skywarder.eu>
Date: Mon, 25 Jul 2022 23:20:15 +0200
Subject: [PATCH] [cc3135] VERY early version of the driver, barely implemented
 bidirectional communication

---
 CMakeLists.txt                           |   3 +
 cmake/boardcore.cmake                    |   1 +
 src/shared/radio/CC3135/CC3135.cpp       | 161 +++++++++++++++++++++++
 src/shared/radio/CC3135/CC3135.h         |  78 +++++++++++
 src/shared/radio/CC3135/CC3135Defs.h     | 150 +++++++++++++++++++++
 src/shared/radio/CC3135/CC3135Iface.h    | 101 ++++++++++++++
 src/tests/drivers/CC3135/test-cc3135.cpp | 102 ++++++++++++++
 7 files changed, 596 insertions(+)
 create mode 100644 src/shared/radio/CC3135/CC3135.cpp
 create mode 100644 src/shared/radio/CC3135/CC3135.h
 create mode 100644 src/shared/radio/CC3135/CC3135Defs.h
 create mode 100644 src/shared/radio/CC3135/CC3135Iface.h
 create mode 100644 src/tests/drivers/CC3135/test-cc3135.cpp

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 53273bb84..5623c9375 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -276,6 +276,9 @@ add_executable(test-sx1278-serial
 )
 sbs_target(test-sx1278-serial stm32f429zi_stm32f4discovery)
 
+add_executable(test-cc3135 src/tests/drivers/CC3135/test-cc3135.cpp)
+sbs_target(test-cc3135 stm32f407vg_stm32f4discovery)
+
 #-----------------------------------------------------------------------------#
 #                               Tests - Sensors                               #
 #-----------------------------------------------------------------------------#
diff --git a/cmake/boardcore.cmake b/cmake/boardcore.cmake
index 2fdea04d4..7d5219421 100644
--- a/cmake/boardcore.cmake
+++ b/cmake/boardcore.cmake
@@ -62,6 +62,7 @@ foreach(OPT_BOARD ${BOARDS})
         ${SBS_BASE}/src/shared/radio/Xbee/APIFrameParser.cpp
         ${SBS_BASE}/src/shared/radio/Xbee/Xbee.cpp
         ${SBS_BASE}/src/shared/radio/SX1278/SX1278.cpp
+        ${SBS_BASE}/src/shared/radio/CC3135/CC3135.cpp
 
         # Scheduler
         ${SBS_BASE}/src/shared/scheduler/TaskScheduler.cpp
diff --git a/src/shared/radio/CC3135/CC3135.cpp b/src/shared/radio/CC3135/CC3135.cpp
new file mode 100644
index 000000000..9d8da2939
--- /dev/null
+++ b/src/shared/radio/CC3135/CC3135.cpp
@@ -0,0 +1,161 @@
+/* Copyright (c) 2021 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "CC3135.h"
+
+namespace Boardcore
+{
+
+using namespace CC3135Defs;
+
+void CC3135Proto::handleIntr()
+{
+    // TODO:
+}
+
+void CC3135::dummyRead()
+{
+    uint8_t buf[220];
+    proto.readPacket(buf);
+
+    ResponseHeader header;
+    memcpy(&header, &buf[0], sizeof(ResponseHeader));
+
+    // TRACE("status: %d\n", header.dev_status);
+    // TRACE("opcode: %s\n", opToStr(header.gen_header.opcode));
+    // TRACE("len: %d\n", header.gen_header.len);
+    // TRACE("\n");
+
+    // if(header.gen_header.opcode == OPCODE_DEVICE_DEVICEGETRESPONSE) {
+    //     for(int i = 0; i < header.gen_header.len + 4; i++) {
+    //         TRACE("%2x\n", buf[i]);
+    //     }
+    // }
+}
+
+DeviceVersion CC3135::getVersion()
+{
+    DeviceSetGet packet;
+    packet.gen_header.opcode = OPCODE_DEVICE_DEVICEGET;
+    packet.device_set_id     = 1;   // Device get general
+    packet.option            = 12;  // Device get version
+
+    proto.writePacket((uint8_t *)&packet, sizeof(packet));
+
+    return {};
+}
+
+//! Get a generic header out of a buffer.
+GenericHeader *getHeader(uint8_t *buf) { return (GenericHeader *)(buf); }
+
+void CC3135Proto::readPacket(uint8_t *buf)
+{
+    // 1. Write CNYS pattern (only if SPI)
+    if (iface->is_spi())
+    {
+        SyncPattern sync = H2N_CNYS_PATTERN;
+        iface->write((uint8_t *)(&sync.short1), SYNC_PATTERN_LEN);
+    }
+
+    // 2. Read initial data from the device
+    iface->read(&buf[0], 8);
+
+    /*
+    Here the TI driver does some weird stuff.
+    Also the TI comment is wrong, soooo, I'll just skip that part
+    */
+
+    // 3. Scan for device SYNC
+    while (true)
+    {
+        // Try and find the SYNC here
+        uint32_t sync;
+        memcpy(&sync, &buf[0], 4);
+
+        if (n2hSyncPatternMatch(sync, tx_seq_num))
+        {
+            // Copy the bytes after the sync to the start
+            memcpy(&buf[0], &buf[4], 4);
+            break;
+        }
+
+        // TODO: The TI driver reads 4 bytes at a time, is this also good?
+
+        // Shift everything
+        memmove(&buf[0], &buf[1], 7);
+        iface->read(&buf[7], 1);
+    }
+
+    // 4. Scan for double syncs
+    while (true)
+    {
+        uint32_t sync;
+        memcpy(&sync, &buf[0], 4);
+
+        if (!n2hSyncPatternMatch(sync, tx_seq_num))
+        {
+            break;
+        }
+
+        iface->read(&buf[0], 4);
+    }
+
+    tx_seq_num++;
+
+    // 5. Parse generic header
+    GenericHeader *header = getHeader(&buf[0]);
+
+    // 6. Finalize and read rest of the data
+    if (header->len > 0)
+    {
+        // TODO: The TI driver reads a ResponseHeader, violating zero size
+
+        size_t aligned_len = alignSize(header->len);
+        iface->read(&buf[sizeof(GenericHeader)], aligned_len);
+    }
+}
+
+void CC3135Proto::writePacket(uint8_t *buf, size_t size)
+{
+    // 1. Write SYNC pattern
+    if (iface->is_spi())
+    {
+        // Short pattern for SPI
+        SyncPattern sync = H2N_SYNC_PATTERN;
+        iface->write((uint8_t *)&sync.short1, SYNC_PATTERN_LEN);
+    }
+    else
+    {
+        // Long pattern for UART
+        SyncPattern sync = H2N_SYNC_PATTERN;
+        iface->write((uint8_t *)&sync.long1, SYNC_PATTERN_LEN * 2);
+    }
+
+    // 2. Setup header length
+    GenericHeader *header = getHeader(&buf[0]);
+    header->len           = size - sizeof(GenericHeader);
+
+    // 3. Write message
+    iface->write(buf, size);
+}
+
+}  // namespace Boardcore
diff --git a/src/shared/radio/CC3135/CC3135.h b/src/shared/radio/CC3135/CC3135.h
new file mode 100644
index 000000000..64629e3bb
--- /dev/null
+++ b/src/shared/radio/CC3135/CC3135.h
@@ -0,0 +1,78 @@
+/* Copyright (c) 2021 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <memory>
+
+#include "CC3135Defs.h"
+#include "CC3135Iface.h"
+
+/*
+TODO(davide.mor): Write a small description of the CC3135
+*/
+
+namespace Boardcore
+{
+
+/**
+ * @brief Abstraction over the comunication protocol.
+ */
+class CC3135Proto
+{
+public:
+    explicit CC3135Proto(std::unique_ptr<ICC3135Iface> &&iface)
+        : iface(std::move(iface)), tx_seq_num(0)
+    {
+    }
+
+    void handleIntr();
+
+    void readPacket(uint8_t *buf);
+    void writePacket(uint8_t *buf, size_t size);
+
+private:
+    std::unique_ptr<ICC3135Iface> iface;
+    uint8_t tx_seq_num;
+};
+
+class CC3135
+{
+public:
+    explicit CC3135(std::unique_ptr<ICC3135Iface> &&iface)
+        : proto(std::move(iface))
+    {
+    }
+
+    void handleIntr() { proto.handleIntr(); }
+
+    //! Dummy packet read, used to test comunication.
+    void dummyRead();
+
+    //! Retrieve information about the device
+    CC3135Defs::DeviceVersion getVersion();
+
+private:
+    CC3135Proto proto;
+};
+
+}  // namespace Boardcore
diff --git a/src/shared/radio/CC3135/CC3135Defs.h b/src/shared/radio/CC3135/CC3135Defs.h
new file mode 100644
index 000000000..09031e0ea
--- /dev/null
+++ b/src/shared/radio/CC3135/CC3135Defs.h
@@ -0,0 +1,150 @@
+/* Copyright (c) 2021 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <cstdlib>
+
+/*
+CC3135 Protocol definitions
+
+This definitions come mostly from the TI driver and a bit of RE
+*/
+
+namespace Boardcore
+{
+
+namespace CC3135Defs
+{
+
+//! Synchronous message mask.
+constexpr uint16_t OPCODE_SYNC = 1 << 10;
+
+//! Device command opcodes.
+enum OpCode : uint16_t
+{
+    OPCODE_DEVICE_INITCOMPLETE                  = 0x0008,
+    OPCODE_DEVICE_DEVICEASYNCDUMMY              = 0x0063,
+    OPCODE_DEVICE_DEVICEGETRESPONSE             = 0x0466,
+    OPCODE_DEVICE_DEVICESETRESPONSE             = 0x04B7,
+    OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT = 0x089A,  //< ????
+    OPCODE_NETAPP_IPACQUIRED                    = 0x1825,  //< ????
+    OPCODE_DEVICE_DEVICEGET                     = 0x8466,
+    OPCODE_DEVICE_DEVICESET                     = 0x84B7,
+};
+
+struct SyncPattern
+{
+    uint32_t long1;
+    uint16_t short1;
+    uint8_t byte1;
+    uint8_t byte2;
+};
+
+struct DeviceVersion
+{
+    uint32_t chip_id;
+    uint8_t fw_version[4];
+    uint8_t phy_version[4];
+    uint8_t nwp_version[4];
+    uint16_t rom_version;
+    uint16_t _pad;
+};
+
+struct GenericHeader
+{
+    OpCode opcode;
+    uint16_t len;
+};
+
+struct ResponseHeader
+{
+    GenericHeader gen_header;
+    uint8_t tx_pool_count;
+    uint8_t dev_status;
+    uint16_t min_max_payload;
+    uint16_t socket_tx_failure;
+    uint16_t socket_non_blocking;
+};
+
+struct DeviceSetGet
+{
+    GenericHeader gen_header;
+    uint16_t status;
+    uint16_t device_set_id;
+    uint16_t option;
+    uint16_t config_len;
+};
+
+constexpr SyncPattern H2N_SYNC_PATTERN = {0xBBDDEEFF, 0x4321, 0x34, 0x12};
+constexpr SyncPattern H2N_CNYS_PATTERN = {0xBBDDEEFF, 0x8765, 0x78, 0x56};
+
+constexpr size_t SYNC_PATTERN_LEN = sizeof(uint32_t);
+
+constexpr uint32_t N2H_SYNC_PATTERN                = 0xABCDDCBA;
+constexpr uint32_t N2H_SYNC_PATTERN_SEQ_NUM_BITS   = 0x00000003;
+constexpr uint32_t N2H_SYNC_PATTERN_SEQ_NUM_EXISTS = 0x00000004;
+constexpr uint32_t N2H_SYNC_PATTERN_MASK           = 0xFFFFFFF8;
+constexpr uint32_t N2H_SYNC_SPI_BUGS_MASK          = 0x7FFF7F7F;  // What?
+
+inline bool n2hSyncPatternMatch(uint32_t sync, uint8_t seq_num)
+{
+    // TODO: Add sequence number
+    return (sync & N2H_SYNC_SPI_BUGS_MASK & N2H_SYNC_PATTERN_MASK) ==
+           (N2H_SYNC_PATTERN & N2H_SYNC_SPI_BUGS_MASK & N2H_SYNC_PATTERN_MASK);
+}
+
+//! Is this message synchronous?
+inline bool isSync(OpCode op) { return op & OPCODE_SYNC; }
+
+//! Align message size.
+inline size_t alignSize(size_t size) { return (size + 3) & (~3); }
+
+inline const char *opToStr(OpCode op)
+{
+    switch (op)
+    {
+        case OpCode::OPCODE_DEVICE_INITCOMPLETE:
+            return "OPCODE_DEVICE_INITCOMPLETE";
+        case OpCode::OPCODE_DEVICE_DEVICEASYNCDUMMY:
+            return "OPCODE_DEVICE_DEVICEASYNCDUMMY";
+        case OpCode::OPCODE_DEVICE_DEVICEGETRESPONSE:
+            return "OPCODE_DEVICE_DEVICEGETRESPONSE";
+        case OpCode::OPCODE_DEVICE_DEVICESETRESPONSE:
+            return "OPCODE_DEVICE_DEVICESETRESPONSE";
+        case OpCode::OPCODE_NETAPP_IPACQUIRED:
+            return "OPCODE_NETAPP_IPACQUIRED";
+        case OpCode::OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT:
+            return "OPCODE_WLAN_PROVISIONING_STATUS_ASYNC_EVENT";
+        case OpCode::OPCODE_DEVICE_DEVICEGET:
+            return "OPCODE_DEVICE_DEVICEGET";
+        case OpCode::OPCODE_DEVICE_DEVICESET:
+            return "OPCODE_DEVICE_DEVICESET";
+        default:
+            return "<unknown>";
+    }
+}
+
+}  // namespace CC3135Defs
+
+}  // namespace Boardcore
diff --git a/src/shared/radio/CC3135/CC3135Iface.h b/src/shared/radio/CC3135/CC3135Iface.h
new file mode 100644
index 000000000..ef468ebe3
--- /dev/null
+++ b/src/shared/radio/CC3135/CC3135Iface.h
@@ -0,0 +1,101 @@
+/* Copyright (c) 2021 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#pragma once
+
+#include <drivers/spi/SPIDriver.h>
+#include <drivers/usart/USART.h>
+
+namespace Boardcore
+{
+
+/**
+ * @brief Abstraction over the kinds of interface of the CC3135
+ */
+class ICC3135Iface
+{
+public:
+    virtual void read(uint8_t *buffer, size_t size)  = 0;
+    virtual void write(uint8_t *buffer, size_t size) = 0;
+    virtual bool is_spi()                            = 0;
+};
+
+/**
+ * @brief SPI CC3135 implementation.
+ */
+class CC3135Spi : public ICC3135Iface
+{
+public:
+    explicit CC3135Spi(SPIBusInterface &bus, GpioType cs,
+                       SPIBusConfig config = {})
+        : slave(bus, cs, config)
+    {
+    }
+
+    void read(uint8_t *buffer, size_t size) override
+    {
+        SPITransaction spi(slave);
+        spi.read(buffer, size);
+    }
+
+    void write(uint8_t *buffer, size_t size) override
+    {
+        SPITransaction spi(slave);
+        spi.write(buffer, size);
+    }
+
+    bool is_spi() override { return true; }
+
+private:
+    SPISlave slave;
+};
+
+/**
+ * @brief UART CC3135 implementation.
+ */
+class CC3135Uart : public ICC3135Iface
+{
+public:
+    explicit CC3135Uart(USARTType *usart) : usart(usart, DEFAULT_BAUD)
+    {
+        this->usart.init();
+    }
+
+    void read(uint8_t *buffer, size_t size) override
+    {
+        usart.read(buffer, size);
+    }
+
+    void write(uint8_t *buffer, size_t size) override
+    {
+        usart.write(buffer, size);
+    }
+
+    bool is_spi() override { return false; }
+
+private:
+    static constexpr USART::Baudrate DEFAULT_BAUD = USART::Baudrate::B115200;
+
+    USART usart;
+};
+
+}  // namespace Boardcore
diff --git a/src/tests/drivers/CC3135/test-cc3135.cpp b/src/tests/drivers/CC3135/test-cc3135.cpp
new file mode 100644
index 000000000..8d115fe3d
--- /dev/null
+++ b/src/tests/drivers/CC3135/test-cc3135.cpp
@@ -0,0 +1,102 @@
+/* Copyright (c) 2021 Skyward Experimental Rocketry
+ * Author: Davide Mor
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <drivers/interrupt/external_interrupts.h>
+#include <radio/CC3135/CC3135.h>
+
+using namespace Boardcore;
+using namespace miosix;
+
+/*
+Connection diagram:
+cc3135:CC_SPI_CS   -> stm32:pa1
+cc3135:CC_nHIB     -> stm32:pc14
+cc3135:CC_IRQ      -> stm32:pc15
+cc3135:CC_SPI_DIN  -> stm32:pc12 (SPI3_MOSI)
+cc3135:CC_SPI_DOUT -> stm32:pc11 (SPI3_MISO)
+cc3135:CC_SPI_CLK  -> stm32:pc10 (SPI3_SCK)
+*/
+
+using tx  = Gpio<GPIOA_BASE, 2>;
+using rx  = Gpio<GPIOA_BASE, 3>;
+using irq = Gpio<GPIOA_BASE, 4>;
+using hib = Gpio<GPIOA_BASE, 5>;
+
+#define CC3135_UART USART2
+#define CC3135_HIB
+
+CC3135 *cc3135 = nullptr;
+
+void __attribute__((used)) EXTI4_IRQHandlerImpl()
+{
+    if (cc3135)
+        cc3135->handleIntr();
+}
+
+void initBoard()
+{
+
+#ifdef CC3135_HIB
+    {
+        miosix::FastInterruptDisableLock dLock;
+
+        hib::mode(miosix::Mode::OUTPUT);
+    }
+
+    hib::high();
+#endif
+
+#ifdef CC3135_UART
+    {
+        miosix::FastInterruptDisableLock dLock;
+
+        irq::mode(miosix::Mode::INPUT);
+        tx::mode(miosix::Mode::ALTERNATE);
+        tx::alternateFunction(7);
+        rx::mode(miosix::Mode::ALTERNATE);
+        rx::alternateFunction(7);
+    }
+
+    auto irq_pin = irq::getPin();
+    enableExternalInterrupt(irq_pin.getPort(), irq_pin.getNumber(),
+                            InterruptTrigger::RISING_EDGE);
+#endif
+}
+
+int main()
+{
+    initBoard();
+
+#ifdef CC3135_UART
+    std::unique_ptr<ICC3135Iface> iface(new CC3135Uart(CC3135_UART));
+#endif
+
+    cc3135 = new CC3135(std::move(iface));
+
+    Thread::sleep(200);
+
+    cc3135->getVersion();
+    while (true)
+    {
+        cc3135->dummyRead();
+    }
+}
-- 
GitLab