From 8f16bc877f24478367a76593484943e3abc5a66a Mon Sep 17 00:00:00 2001 From: Eve Redero Date: Tue, 5 Mar 2024 23:50:48 +0100 Subject: [PATCH] wip: cc2500 implementation and test app --- ccapp/CMakeLists.txt | 14 ++ ccapp/Kconfig | 15 ++ ccapp/README.md | 237 +++++++++++++++++++++++++++++ ccapp/VERSION | 5 + ccapp/boards/nucleo_f756zg.overlay | 23 +++ ccapp/prj.conf | 14 ++ ccapp/sample.yaml | 15 ++ ccapp/src/main.c | 41 +++++ drivers/cc2500/cc2500.c | 214 +++++++++++++++++++++++++- 9 files changed, 572 insertions(+), 6 deletions(-) create mode 100644 ccapp/CMakeLists.txt create mode 100644 ccapp/Kconfig create mode 100644 ccapp/README.md create mode 100644 ccapp/VERSION create mode 100644 ccapp/boards/nucleo_f756zg.overlay create mode 100644 ccapp/prj.conf create mode 100644 ccapp/sample.yaml create mode 100644 ccapp/src/main.c diff --git a/ccapp/CMakeLists.txt b/ccapp/CMakeLists.txt new file mode 100644 index 0000000..ac625be --- /dev/null +++ b/ccapp/CMakeLists.txt @@ -0,0 +1,14 @@ +#------------------------------------------------------------------------------- +# Zephyr Example Application +# +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) +set(SYSCALL_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/../include") + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) + +project(app LANGUAGES C) + +target_sources(app PRIVATE src/main.c) diff --git a/ccapp/Kconfig b/ccapp/Kconfig new file mode 100644 index 0000000..140eaaf --- /dev/null +++ b/ccapp/Kconfig @@ -0,0 +1,15 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +# This file is the application Kconfig entry point. All application Kconfig +# options can be defined here or included via other application Kconfig files. +# You can browse these options using the west targets menuconfig (terminal) or +# guiconfig (GUI). + +menu "Zephyr" +source "Kconfig.zephyr" +endmenu + +module = APP +module-str = APP +source "subsys/logging/Kconfig.template.log_config" diff --git a/ccapp/README.md b/ccapp/README.md new file mode 100644 index 0000000..69834d8 --- /dev/null +++ b/ccapp/README.md @@ -0,0 +1,237 @@ +# Example application for CC2500 driver + +## Description + +This application tries to copy a third party remote control. + +This example app can be run on the following boards: + +* STM32 Nucleo F756ZX (nucleo\_f756zg) + +For each board, an example overlay layer is provided. + +``` +BOARD="nucleo_f756zg";west build -b $BOARD -p always ccapp -- -DOVERLAY_CONFIG=bob.conf +``` + +## Pinout + +| Name | NRF24 pin | Nucleo pin | Nucleo logical GPIO | NRF52DK pin | NRF52 logical GPIO | ESP32WROOM pin | ESP32 logical GPIO | +|-----------|-----------|------------|---------------------|-------------|--------------------|----------------|--------------------| +| GND | 1 | GND | | GND | | GND | | +| VCC | 2 | 3V3 | | VDD | | 3V3 | | +| CSN | 4 | D24 | PA4 | P0.22 | D10 | D3 | 10 | +| SCK | 5 | D23 | PB3 | P0.25 | D13 | 14 | 14 | +| MOSI | 6 | D22 | PB5 | P0.23 | D11 | 15 | 15 | +| MISO | 7 | D25 | PB4 | P0.24 | D12 | 2 | 2 | + +### Pinout diagrams +#### CC2400 + +![Kroki generated +PlantUML](https://kroki.io/ditaa/svg/eNpTUIACbV1dXTDmAvHc_VwUFGoUDIHYCIjDnJ25FFBUAukasJCzK4ipYAwkTYC0c7CfgoatX3CwJkJDDYwGCwU7e4OETIFMMyDt6x_siUupr2ewP1DIHMi0ANKeQYG4VMIdBgLaAAqjJlw=) + + +#### STM32 Nucleo + +![Kroki generated +PlantUML](https://kroki.io/ditaa/svg/eNrNmMFO5DAMhu_zFDkOQkhxHDvpsWoXNEJbdqnElRfh4dduZ0oiFRRQMksl3xr36z9__KdjTKVrmMLhUKnX7d163dZoOAKbNwNSTmoEqkX5dqk6lEGaoZRfKP0PpYzSjKT4g4bDFP8zYSfNVMu423CzVhXCaUit5bGI0Fm5WSnB6i-Nh08eWEvHxFrel1HqawFIOaV016E8W0soaW_xkW_M_OcEr7-f5tNCqcIDSnmlhNaU-ILv9hJK3qWkM-U8PK5a6iIgKVZKK8Z5vn89Pf81x3jTXFh6Sf3mwy6yPyNP87wiq1cgSEVZ1JkVefglt2Jz5IdpTM3nd0fKMVy8cJqfFmQ1D3SyGfU945UgL97zXY10-3x3bBYiW_VhX5Njm3eh-Xz9fuht445bQ_Y2E4WgoJd6J5121NqsPWSikCtp1rPJhl1zSJeLUhSnfTDpeGuepj1molBRmvbRpAOteZj2PhOFqCzyOQvT5pCUirJsiRLIkA5C2xpyDNkJg9gUbu8kPb1rTwlZPIQyKWMamB7aU9pUFopllGpjJy5xq0uaU3KXykJFuT6ivpoTm7jlMNDelxwTWUa2ZZRLTIlNnNoEu-uckTZZGMp3jxObOLUJxvZahlQWdmVa6mBwYhNccie0p-RUFi772ETNfBSboNoEuT0lpbJw2ccm6qkExSaoNkG6xsfmtw6B78fpw95_H5358jVMYP8BcKUNlA==) + + +#### NRF52DK + +![Kroki generated +PlantUML](https://kroki.io/ditaa/svg/eNrNl81uhCAURvc-Bcsa04Z_dK2mMU0dOzbzGr6AD19AplpoJqgoQ4ITF_fLkStHJgE7RvYqR5ZsKe3gGxbydwQIgjHZQzHqy2aKXEcUICoFxDoiX0YMOylUdzL_0ve2MhHiN0J2R85bVW2nGO_3j8YLS0FffpiOMF3CFxH4HAqRgs-mv0wUVJewRQSR81r39fexFFxSXPpmoiC6hC4i6DlrQVNQ9q3pCDbPP0cwNW_gaIo8Bc31y1BA8y7MEVzO-3t7IAWRa1GbnYoKsy_mCHEKxWP9KneMoC1Xhwy7EEBHF7Ix6upQgI_JsE6gKLcEutJ-_7dF2U_ZmfhSCEegm5b1LwU2FNSXgjsCDUBBJgr9vfSiYI5AA1BQQ1H4UlBHoAEo2ERBoC8FcQQagIIbCuRLgR2B7qZYuc0UBbIECjp88oErwPnVEejW0ZEk1jOoZsCnOP0W7uk3AkVuyTsOhbDkHYeCW_KOQ8Esecf5h4gsecdZC2TJOw4FtOV9OsVTyZv_APQBfRw=) + +### ESP32-WROOM + +![Kroki generated +PlantUML](https://kroki.io/ditaa/svg/eNrFls0KgzAMx-8-RY4VEdbGuu1c3RDnx-xwexgffptOXHVIwMByKJTk31-aNFCAyYLwbYGzc8x1Bd6XFjrAFl_ruFvY5DqXCXTe0kcS9-tMnJZEsULgJbf1LCK1dZNam53mZMVNLpdkVOG9qarCEd8ezGSMiOKGnaypfZbcZAV_etuIU8TKSHYgj-t3XrHfZKWJYnngJsdEsQZu8p565yEwa64gDv62FIT2wZp8PDmipjBUyaQAAn3OKkhFFEfc9e_HhyLecZMlEsVqOKLIbAViz1r3hFp3OYxmUdkMRLz1-UU-GFuOOVDrkEjmDpiC2Ptkx0zWLVFsLjkn2f1wrdgn8An4ooaa) diff --git a/ccapp/VERSION b/ccapp/VERSION new file mode 100644 index 0000000..16a1373 --- /dev/null +++ b/ccapp/VERSION @@ -0,0 +1,5 @@ +VERSION_MAJOR = 1 +VERSION_MINOR = 0 +PATCHLEVEL = 0 +VERSION_TWEAK = 0 +EXTRAVERSION = diff --git a/ccapp/boards/nucleo_f756zg.overlay b/ccapp/boards/nucleo_f756zg.overlay new file mode 100644 index 0000000..dce6c11 --- /dev/null +++ b/ccapp/boards/nucleo_f756zg.overlay @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2024 Eve Redero + * SPDX-License-Identifier: Apache-2.0 + */ + +&spi1 { + pinctrl-0 = <&spi1_sck_pb3 &spi1_miso_pb4 &spi1_mosi_pb5>; + pinctrl-names = "default"; + cs-gpios = <&gpioa 4 GPIO_ACTIVE_LOW>; + clock-frequency = <8000000>; // Max 8 Mbps for SPI + status = "okay"; + + radio0: propy_radio@0 { + reg = <0>; + compatible = "ti,cc2500"; + status = "okay"; + spi-max-frequency = <500000>; // This really sets frequency + /* From 0x07 to 0x2E */ + conf-array = [0A 04 01 00 0A 00 5D 13 B1 + 2D 3B 73 22 F8 00 07 30 18 1D 1C C7 00 B0 87 6B + F8 B6 10 EA 0A 00 11 41 00 59 7F 3F 88 31 0B]; + }; +}; diff --git a/ccapp/prj.conf b/ccapp/prj.conf new file mode 100644 index 0000000..80169a4 --- /dev/null +++ b/ccapp/prj.conf @@ -0,0 +1,14 @@ +# Copyright (c) 2021 Nordic Semiconductor ASA +# SPDX-License-Identifier: Apache-2.0 +# +# This file contains selected Kconfig options for the application. + +CONFIG_SPI=y +CONFIG_CC2500=y +CONFIG_CC2500_TRIGGER=y + +# logging +CONFIG_LOG=y +CONFIG_APP_LOG_LEVEL_DBG=y +CONFIG_CC2500_LOG_LEVEL_DBG=y +CONFIG_LOG_MODE_IMMEDIATE=y diff --git a/ccapp/sample.yaml b/ccapp/sample.yaml new file mode 100644 index 0000000..d992e53 --- /dev/null +++ b/ccapp/sample.yaml @@ -0,0 +1,15 @@ +# This file is provided so that the application can be compiled using Twister, +# the Zephyr testing tool. In this file, multiple combinations can be specified, +# so that you can easily test all of them locally or in CI. +sample: + description: Example application + name: example-application +common: + build_only: true + integration_platforms: + - nucleo_f756zg +tests: + app.default: {} + app.debug: + extra_overlay_confs: + - debug.conf diff --git a/ccapp/src/main.c b/ccapp/src/main.c new file mode 100644 index 0000000..5a3b1ea --- /dev/null +++ b/ccapp/src/main.c @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2024 Eve Redero + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include + +#include +#include +LOG_MODULE_REGISTER(main, CONFIG_APP_LOG_LEVEL); +#if !DT_NODE_EXISTS(DT_NODELABEL(radio0)) +#error "whoops, node label radio0 not found" +#endif + + +int main(void) +{ + static const struct device *cc2500 = DEVICE_DT_GET(DT_NODELABEL(radio0)); + uint8_t data_len = 7; + uint8_t buffer[] = {0x01, 0x00, 0xa5, 0x28, 0x28, 0x00, 0x00}; + int i = 0; + + if (!device_is_ready(cc2500)) { + LOG_ERR("Sensor not ready"); + return 0; + } + LOG_INF("Device ready"); + for (i=0; i<20; i++) { + propy_radio_write(cc2500, buffer, data_len); + k_sleep(K_MSEC(20)); + } + /* + while (!propy_radio_write(cc2500, buffer, data_len)) + { + k_sleep(K_MSEC(10)); + }*/ + + return 0; +} + diff --git a/drivers/cc2500/cc2500.c b/drivers/cc2500/cc2500.c index 6648171..fad7464 100644 --- a/drivers/cc2500/cc2500.c +++ b/drivers/cc2500/cc2500.c @@ -13,9 +13,8 @@ #include #include "cc2500_defines.h" +/* Max data fifo len */ #define SPI_MAX_MSG_LEN 64 -#define SPI_MAX_REG_LEN 5 -#define SPI_MSG_QUEUE_LEN 10 LOG_MODULE_REGISTER(cc2500, CONFIG_CC2500_LOG_LEVEL); @@ -111,6 +110,124 @@ uint8_t cc2500_read_register(const struct device *dev, uint8_t reg) return rx_data[1]; } +uint8_t cc2500_read_status(const struct device *dev) +{ + const struct cc2500_config *config = dev->config; + uint8_t tx_data[2]; + uint8_t rx_data[2]; + int ret; + const struct spi_buf tx_buf[1] = { + { + .buf = tx_data, + .len = 2 + } + }; + const struct spi_buf rx_buf[1] = { + { + .buf = (void *)rx_data, + .len = 2 + } + }; + struct spi_buf_set tx = { + .buffers = tx_buf, + .count = 1 + }; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = 1 + }; + + // 5 lower bits for address, the 6th is 0 for read and 1 for write + tx_data[0] = ( READ_SINGLE | ( RW_MASK & 0x00 ) ); + tx_data[1] = 0x00; + + ret = spi_transceive_dt(&config->spi, &tx, &rx); + + if (ret) { + LOG_ERR("Error transceive %d", ret); + return 0; + } + + // status is 1st byte of receive buffer + return rx_data[0]; +} + +uint8_t cc2500_write_register_len(const struct device *dev, uint8_t reg, const uint8_t* data, uint8_t len) +{ + const struct cc2500_config *config = dev->config; + uint8_t tx_data[SPI_MAX_MSG_LEN + 1] = {0}; + uint8_t rx_data = 0; + int ret; + const struct spi_buf tx_buf[1] = { + { + .buf = tx_data, + .len = (len + 1) + } + }; + const struct spi_buf rx_buf[1] = { + { + .buf = &rx_data, + .len = 1 + } + }; + struct spi_buf_set tx = { + .buffers = tx_buf, + .count = 1 + }; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = 1 + }; + + tx_data[0] = ( WRITE_BURST | ( RW_MASK & reg ) ); + memcpy(&tx_data[1], data, len); + + ret = spi_transceive_dt(&config->spi, &tx, &rx); + if (ret) { + LOG_ERR("Error transceive %d", ret); + return 0; + } + return rx_data; +} + +uint8_t cc2500_cmd_register(const struct device *dev, uint8_t cmd) +{ + const struct cc2500_config *config = dev->config; + int ret; + uint8_t tx_data[1]; + uint8_t rx_data[1]; + const struct spi_buf tx_buf[1] = { + { + .buf = tx_data, + .len = 1 + } + }; + const struct spi_buf rx_buf[1] = { + { + .buf = rx_data, + .len = 1 + } + }; + struct spi_buf_set tx = { + .buffers = tx_buf, + .count = 1 + }; + const struct spi_buf_set rx = { + .buffers = rx_buf, + .count = 1 + }; + + tx_data[0] = cmd; + + ret = spi_transceive_dt(&config->spi, &tx, &rx); + if (ret) { + LOG_ERR("Error transceive %d\n", ret); + return 0; + } + + return rx_data[0]; +} + static int cc2500_set_config_registers(const struct device *dev) { int ret = 0; @@ -128,19 +245,77 @@ static int cc2500_set_config_registers(const struct device *dev) return ret; } -/* API functions */ +/* Private driver function */ +static uint8_t cc2500_reset(const struct device *dev) +{ + return(cc2500_cmd_register(dev, SRES)); +} +static uint8_t cc2500_flush_rx(const struct device *dev) +{ + return(cc2500_cmd_register(dev, SFRX)); +} + +static uint8_t cc2500_flush_tx(const struct device *dev) +{ + return(cc2500_cmd_register(dev, SFTX)); +} + +static uint8_t cc2500_idle(const struct device *dev) +{ + return(cc2500_cmd_register(dev, SIDLE)); +} + +static uint8_t cc2500_set_rx(const struct device *dev) +{ + return(cc2500_cmd_register(dev, SRX)); +} + +static uint8_t cc2500_set_tx(const struct device *dev) +{ + return(cc2500_cmd_register(dev, STX)); +} + +static uint8_t cc2500_set_pkt_len(const struct device *dev, int len) +{ + return(cc2500_write_register(dev, PKTLEN, len)); +} + +static void cc2500_write_register_burst(const struct device *dev, uint8_t reg, const uint8_t* data, uint8_t len) +{ + /* Packet length +1 because we count the reg byte */ + cc2500_set_pkt_len(dev, len+1); + cc2500_write_register_len(dev, reg, data, len); +} + +/* API functions */ static int cc2500_read(const struct device *dev, uint8_t *buffer, uint8_t data_len) { int ret = 0; - struct cc2500_data *data = dev->data; + return ret; } static int cc2500_write(const struct device *dev, uint8_t *buffer, uint8_t data_len) { int ret = 0; - struct cc2500_data *data = dev->data; + int status = 0; + + cc2500_idle(dev); + cc2500_write_register_burst(dev, TXFIFO, buffer, data_len); + cc2500_set_tx(dev); + status = cc2500_read_status(dev); + LOG_DBG("Status: 0x%x", status); + k_msleep(1); + status = cc2500_read_status(dev); + LOG_DBG("Status: 0x%x", status); + + cc2500_flush_tx(dev); + status = cc2500_idle(dev); + LOG_DBG("Status idle: 0x%x", status); + cc2500_set_rx(dev); + status = cc2500_idle(dev); + LOG_DBG("Status idle: 0x%x", status); return ret; } @@ -153,8 +328,11 @@ static const struct propy_radio_api cc2500_api = { /* Init */ static int cc2500_init(const struct device *dev) { + uint8_t pa_data[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const struct cc2500_config *config = dev->config; struct cc2500_data *data = dev->data; + uint8_t reg_value; + int i; int ret; if (!spi_is_ready_dt(&config->spi)) { @@ -169,9 +347,33 @@ static int cc2500_init(const struct device *dev) LOG_ERR("Could not configure CS GPIO (%d)", ret); return ret; } - + cc2500_reset(dev); cc2500_set_config_registers(dev); + cc2500_write_register_burst(dev, PATABLE, pa_data, 8); + + reg_value = cc2500_read_register(dev, FREQ0); + LOG_DBG("Freq 0: %d", reg_value); + + cc2500_write_register(dev, IOCFG2, 0x5C); + cc2500_write_register(dev, IOCFG0, 0x5B); + + cc2500_flush_rx(dev); + cc2500_flush_tx(dev); + cc2500_idle(dev); + + cc2500_set_rx(dev); + + /* Single read */ + reg_value = cc2500_read_register(dev, FSCAL1); + LOG_DBG("FS Cal1: %d", reg_value); + + for (i=0; i<30; i++) { + reg_value = cc2500_read_register(dev, RSSI); + LOG_DBG("RSSI: %d", reg_value); + k_msleep(1); + } + return 0; }