mirror of
https://github.com/esphome/esphome.git
synced 2024-11-30 18:54:14 +01:00
cc1101 radio transmitter component initial commit
This commit is contained in:
parent
3c651f4091
commit
abc1c3aba4
5 changed files with 1010 additions and 0 deletions
0
esphome/components/cc1101/__init__.py
Normal file
0
esphome/components/cc1101/__init__.py
Normal file
702
esphome/components/cc1101/cc1101.cpp
Normal file
702
esphome/components/cc1101/cc1101.cpp
Normal file
|
@ -0,0 +1,702 @@
|
||||||
|
/*
|
||||||
|
https://github.com/gabest11/esphome-cc1101
|
||||||
|
|
||||||
|
This is a CC1101 transceiver component that works with esphome's remote_transmitter/remote_receiver.
|
||||||
|
|
||||||
|
It can be compiled with Arduino and esp-idf framework and should support any esphome compatible board through the SPI Bus.
|
||||||
|
|
||||||
|
On ESP8266, you can use the same pin for GDO and GD2 (it is an optional parameter).
|
||||||
|
|
||||||
|
The source code is a mashup of the following github projects with some special esphome sauce:
|
||||||
|
|
||||||
|
https://github.com/dbuezas/esphome-cc1101 (the original esphome component)
|
||||||
|
https://github.com/nistvan86/esphome-q7rf (how to use esphome with spi)
|
||||||
|
https://github.com/LSatan/SmartRC-CC1101-Driver-Lib (cc1101 setup code)
|
||||||
|
|
||||||
|
TODO: RP2040? (USE_RP2040)
|
||||||
|
TODO: Libretiny? (USE_LIBRETINY)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esphome/core/log.h"
|
||||||
|
#include "cc1101.h"
|
||||||
|
#include "cc1101defs.h"
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#ifdef USE_ARDUINO
|
||||||
|
#include <Arduino.h>
|
||||||
|
#else // USE_ESP_IDF
|
||||||
|
#include <driver/gpio.h>
|
||||||
|
long map(long x, long in_min, long in_max, long out_min, long out_max) { return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace cc1101 {
|
||||||
|
|
||||||
|
static const char *TAG = "cc1101";
|
||||||
|
|
||||||
|
uint8_t PA_TABLE[8] {0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00};
|
||||||
|
// -30 -20 -15 -10 0 5 7 10
|
||||||
|
uint8_t PA_TABLE_315[8] {0x12,0x0D,0x1C,0x34,0x51,0x85,0xCB,0xC2}; // 300 - 348
|
||||||
|
uint8_t PA_TABLE_433[8] {0x12,0x0E,0x1D,0x34,0x60,0x84,0xC8,0xC0}; // 387 - 464
|
||||||
|
// -30 -20 -15 -10 -6 0 5 7 10 12
|
||||||
|
uint8_t PA_TABLE_868[10] {0x03,0x17,0x1D,0x26,0x37,0x50,0x86,0xCD,0xC5,0xC0}; // 779 - 899.99
|
||||||
|
// -30 -20 -15 -10 -6 0 5 7 10 11
|
||||||
|
uint8_t PA_TABLE_915[10] {0x03,0x0E,0x1E,0x27,0x38,0x8E,0x84,0xCC,0xC3,0xC0}; // 900 - 928
|
||||||
|
|
||||||
|
CC1101::CC1101()
|
||||||
|
{
|
||||||
|
this->gdo0_ = NULL;
|
||||||
|
this->gdo2_ = NULL;
|
||||||
|
this->bandwidth_ = 200;
|
||||||
|
this->frequency_ = 433920;
|
||||||
|
this->rssi_sensor_ = NULL;
|
||||||
|
this->lqi_sensor_ = NULL;
|
||||||
|
|
||||||
|
this->partnum_ = 0;
|
||||||
|
this->version_ = 0;
|
||||||
|
this->last_rssi_ = INT_MIN;
|
||||||
|
this->last_lqi_ = INT_MIN;
|
||||||
|
|
||||||
|
this->mode_ = false;
|
||||||
|
this->modulation_ = 2;
|
||||||
|
this->chan_ = 0;
|
||||||
|
this->pa_ = 12;
|
||||||
|
this->last_pa_ = -1;
|
||||||
|
this->m4RxBw_ = 0;
|
||||||
|
this->trxstate_ = 0;
|
||||||
|
|
||||||
|
this->clb_[0][0] = 24;
|
||||||
|
this->clb_[0][1] = 28;
|
||||||
|
this->clb_[1][0] = 31;
|
||||||
|
this->clb_[1][1] = 38;
|
||||||
|
this->clb_[2][0] = 65;
|
||||||
|
this->clb_[2][1] = 76;
|
||||||
|
this->clb_[3][0] = 77;
|
||||||
|
this->clb_[3][1] = 79;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_config_gdo0(InternalGPIOPin* pin)
|
||||||
|
{
|
||||||
|
gdo0_ = pin;
|
||||||
|
|
||||||
|
if(gdo2_ == NULL) gdo2_ = pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_config_gdo2(InternalGPIOPin* pin)
|
||||||
|
{
|
||||||
|
gdo2_ = pin;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_config_bandwidth(uint32_t bandwidth)
|
||||||
|
{
|
||||||
|
bandwidth_ = bandwidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_config_frequency(uint32_t frequency)
|
||||||
|
{
|
||||||
|
frequency_ = frequency;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_config_rssi_sensor(sensor::Sensor* rssi_sensor)
|
||||||
|
{
|
||||||
|
rssi_sensor_ = rssi_sensor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_config_lqi_sensor(sensor::Sensor* lqi_sensor)
|
||||||
|
{
|
||||||
|
lqi_sensor_ = lqi_sensor;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::setup()
|
||||||
|
{
|
||||||
|
this->gdo0_->setup();
|
||||||
|
this->gdo2_->setup();
|
||||||
|
this->gdo0_->pin_mode(gpio::FLAG_OUTPUT);
|
||||||
|
this->gdo2_->pin_mode(gpio::FLAG_INPUT);
|
||||||
|
|
||||||
|
this->spi_setup();
|
||||||
|
|
||||||
|
if(!this->reset())
|
||||||
|
{
|
||||||
|
mark_failed();
|
||||||
|
ESP_LOGE(TAG, "Failed to reset CC1101 modem. Check connection.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ELECHOUSE_cc1101.Init();
|
||||||
|
|
||||||
|
this->write_register(CC1101_FSCTRL1, 0x06);
|
||||||
|
|
||||||
|
this->set_mode(false);
|
||||||
|
this->set_frequency(this->frequency_);
|
||||||
|
|
||||||
|
this->write_register(CC1101_MDMCFG1, 0x02);
|
||||||
|
this->write_register(CC1101_MDMCFG0, 0xF8);
|
||||||
|
this->write_register(CC1101_CHANNR, this->chan_);
|
||||||
|
this->write_register(CC1101_DEVIATN, 0x47);
|
||||||
|
this->write_register(CC1101_FREND1, 0x56);
|
||||||
|
this->write_register(CC1101_MCSM0, 0x18);
|
||||||
|
this->write_register(CC1101_FOCCFG, 0x16);
|
||||||
|
this->write_register(CC1101_BSCFG, 0x1C);
|
||||||
|
this->write_register(CC1101_AGCCTRL2, 0xC7);
|
||||||
|
this->write_register(CC1101_AGCCTRL1, 0x00);
|
||||||
|
this->write_register(CC1101_AGCCTRL0, 0xB2);
|
||||||
|
this->write_register(CC1101_FSCAL3, 0xE9);
|
||||||
|
this->write_register(CC1101_FSCAL2, 0x2A);
|
||||||
|
this->write_register(CC1101_FSCAL1, 0x00);
|
||||||
|
this->write_register(CC1101_FSCAL0, 0x1F);
|
||||||
|
this->write_register(CC1101_FSTEST, 0x59);
|
||||||
|
this->write_register(CC1101_TEST2, 0x81);
|
||||||
|
this->write_register(CC1101_TEST1, 0x35);
|
||||||
|
this->write_register(CC1101_TEST0, 0x09);
|
||||||
|
this->write_register(CC1101_PKTCTRL1, 0x04);
|
||||||
|
this->write_register(CC1101_ADDR, 0x00);
|
||||||
|
this->write_register(CC1101_PKTLEN, 0x00);
|
||||||
|
|
||||||
|
// ELECHOUSE_cc1101.setRxBW(_bandwidth);
|
||||||
|
|
||||||
|
this->set_rxbw(this->bandwidth_);
|
||||||
|
|
||||||
|
// ELECHOUSE_cc1101.setMHZ(_freq);
|
||||||
|
|
||||||
|
this->set_frequency(this->frequency_); // TODO: already set
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
this->set_rx();
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "CC1101 initialized.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::update()
|
||||||
|
{
|
||||||
|
if(this->rssi_sensor_ != NULL)
|
||||||
|
{
|
||||||
|
int32_t rssi = this->get_rssi();
|
||||||
|
|
||||||
|
if(rssi != this->last_rssi_)
|
||||||
|
{
|
||||||
|
this->rssi_sensor_->publish_state(rssi);
|
||||||
|
|
||||||
|
this->last_rssi_ = rssi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->lqi_sensor_ != NULL)
|
||||||
|
{
|
||||||
|
int32_t lqi = this->get_lqi() & 0x7f; // msb = CRC ok or not set
|
||||||
|
|
||||||
|
if(lqi != this->last_lqi_)
|
||||||
|
{
|
||||||
|
this->lqi_sensor_->publish_state(lqi);
|
||||||
|
|
||||||
|
this->last_lqi_ = lqi;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::dump_config()
|
||||||
|
{
|
||||||
|
ESP_LOGCONFIG(TAG, "CC1101 partnum %02x version %02x:", this->partnum_, this->version_);
|
||||||
|
LOG_PIN(" CC1101 CS Pin: ", this->cs_);
|
||||||
|
LOG_PIN(" CC1101 GDO0: ", this->gdo0_);
|
||||||
|
LOG_PIN(" CC1101 GDO2: ", this->gdo2_);
|
||||||
|
ESP_LOGCONFIG(TAG, " CC1101 Bandwith: %d KHz", this->bandwidth_);
|
||||||
|
ESP_LOGCONFIG(TAG, " CC1101 Frequency: %d KHz", this->frequency_);
|
||||||
|
LOG_SENSOR(" ", "RSSI", this->rssi_sensor_);
|
||||||
|
LOG_SENSOR(" ", "LQI", this->lqi_sensor_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CC1101::reset()
|
||||||
|
{
|
||||||
|
// Chip reset sequence. CS wiggle (CC1101 manual page 45)
|
||||||
|
|
||||||
|
//this->disable(); // esp-idf calls end_transaction and asserts, because no begin_transaction was called
|
||||||
|
this->cs_->digital_write(false);
|
||||||
|
delayMicroseconds(5);
|
||||||
|
//this->enable();
|
||||||
|
this->cs_->digital_write(true);
|
||||||
|
delayMicroseconds(10);
|
||||||
|
//this->disable();
|
||||||
|
this->cs_->digital_write(false);
|
||||||
|
delayMicroseconds(41);
|
||||||
|
|
||||||
|
this->send_cmd(CC1101_SRES);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "Issued CC1101 reset sequence.");
|
||||||
|
|
||||||
|
// Read part number and version
|
||||||
|
|
||||||
|
this->partnum_ = this->read_status_register(CC1101_PARTNUM);
|
||||||
|
this->version_ = this->read_status_register(CC1101_VERSION);
|
||||||
|
|
||||||
|
ESP_LOGI(TAG, "CC1101 found with partnum: %02x and version: %02x", this->partnum_, this->version_);
|
||||||
|
|
||||||
|
return this->version_ > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::send_cmd(uint8_t cmd)
|
||||||
|
{
|
||||||
|
this->enable();
|
||||||
|
this->transfer_byte(cmd);
|
||||||
|
this->disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CC1101::read_register(uint8_t reg)
|
||||||
|
{
|
||||||
|
this->enable();
|
||||||
|
this->transfer_byte(reg);
|
||||||
|
uint8_t value = this->transfer_byte(0);
|
||||||
|
this->disable();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CC1101::read_config_register(uint8_t reg)
|
||||||
|
{
|
||||||
|
return this->read_register(reg | CC1101_READ_SINGLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CC1101::read_status_register(uint8_t reg)
|
||||||
|
{
|
||||||
|
return this->read_register(reg | CC1101_READ_BURST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::read_register_burst(uint8_t reg, uint8_t* buffer, size_t length)
|
||||||
|
{
|
||||||
|
this->enable();
|
||||||
|
this->write_byte(reg | CC1101_READ_BURST);
|
||||||
|
this->read_array(buffer, length);
|
||||||
|
this->disable();
|
||||||
|
}
|
||||||
|
void CC1101::write_register(uint8_t reg, uint8_t* value, size_t length)
|
||||||
|
{
|
||||||
|
this->enable();
|
||||||
|
this->transfer_byte(reg);
|
||||||
|
this->transfer_array(value, length);
|
||||||
|
this->disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::write_register(uint8_t reg, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t arr[1] = {value};
|
||||||
|
this->write_register(reg, arr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::write_register_burst(uint8_t reg, uint8_t* buffer, size_t length)
|
||||||
|
{
|
||||||
|
this->write_register(reg | CC1101_WRITE_BURST, buffer, length);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
bool CC1101::send_data(const uint8_t* data, size_t length)
|
||||||
|
{
|
||||||
|
uint8_t buffer[length];
|
||||||
|
|
||||||
|
memcpy(buffer, data, lenght);
|
||||||
|
|
||||||
|
this->send_cmd(CC1101_SIDLE);
|
||||||
|
this->send_cmd(CC1101_SFRX);
|
||||||
|
this->send_cmd(CC1101_SFTX);
|
||||||
|
|
||||||
|
this->write_register_burst(CC1101_TXFIFO, buffer, length);
|
||||||
|
|
||||||
|
this->send_cmd(CC1101_STX);
|
||||||
|
|
||||||
|
uint8_t state = this->read_status_register(CC1101_MARCSTATE) & 0x1f;
|
||||||
|
|
||||||
|
if(state != CC1101_MARCSTATE_TX && state != CC1101_MARCSTATE_TX_END && state != CC1101_MARCSTATE_RXTX_SWITCH)
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "CC1101 in invalid state after sending, returning to idle. State: 0x%02x", state);
|
||||||
|
this->send_cmd(CC1101_SIDLE);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ELECHOUSE_CC1101 stuff
|
||||||
|
|
||||||
|
void CC1101::set_mode(bool s)
|
||||||
|
{
|
||||||
|
this->mode_ = s;
|
||||||
|
|
||||||
|
if(s)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_IOCFG2, 0x0B);
|
||||||
|
this->write_register(CC1101_IOCFG0, 0x06);
|
||||||
|
this->write_register(CC1101_PKTCTRL0, 0x05);
|
||||||
|
this->write_register(CC1101_MDMCFG3, 0xF8);
|
||||||
|
this->write_register(CC1101_MDMCFG4, 11 + this->m4RxBw_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_IOCFG2, 0x0D);
|
||||||
|
this->write_register(CC1101_IOCFG0, 0x0D);
|
||||||
|
this->write_register(CC1101_PKTCTRL0, 0x32);
|
||||||
|
this->write_register(CC1101_MDMCFG3, 0x93);
|
||||||
|
this->write_register(CC1101_MDMCFG4, 7 + this->m4RxBw_);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->set_modulation(this->modulation_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_modulation(uint8_t m)
|
||||||
|
{
|
||||||
|
if(m > 4) m = 4;
|
||||||
|
|
||||||
|
this->modulation_ = m;
|
||||||
|
|
||||||
|
this->split_MDMCFG2();
|
||||||
|
|
||||||
|
switch(m)
|
||||||
|
{
|
||||||
|
case 0: this->m2MODFM_ = 0x00; this->frend0_ = 0x10; break; // 2-FSK
|
||||||
|
case 1: this->m2MODFM_ = 0x10; this->frend0_ = 0x10; break; // GFSK
|
||||||
|
case 2: this->m2MODFM_ = 0x30; this->frend0_ = 0x11; break; // ASK
|
||||||
|
case 3: this->m2MODFM_ = 0x40; this->frend0_ = 0x10; break; // 4-FSK
|
||||||
|
case 4: this->m2MODFM_ = 0x70; this->frend0_ = 0x10; break; // MSK
|
||||||
|
}
|
||||||
|
|
||||||
|
this->write_register(CC1101_MDMCFG2, this->m2DCOFF_ + this->m2MODFM_ + this->m2MANCH_ + this->m2SYNCM_);
|
||||||
|
this->write_register(CC1101_FREND0, this->frend0_);
|
||||||
|
|
||||||
|
this->set_pa(this->pa_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_pa(int8_t pa)
|
||||||
|
{
|
||||||
|
this->pa_ = pa;
|
||||||
|
|
||||||
|
int a;
|
||||||
|
|
||||||
|
if(this->frequency_ >= 300000 && this->frequency_ <= 348000)
|
||||||
|
{
|
||||||
|
if(pa <= -30) a = PA_TABLE_315[0];
|
||||||
|
else if(pa > -30 && pa <= -20) a = PA_TABLE_315[1];
|
||||||
|
else if(pa > -20 && pa <= -15) a = PA_TABLE_315[2];
|
||||||
|
else if(pa > -15 && pa <= -10) a = PA_TABLE_315[3];
|
||||||
|
else if(pa > -10 && pa <= 0) a = PA_TABLE_315[4];
|
||||||
|
else if(pa > 0 && pa <= 5) a = PA_TABLE_315[5];
|
||||||
|
else if(pa > 5 && pa <= 7) a = PA_TABLE_315[6];
|
||||||
|
else a = PA_TABLE_315[7];
|
||||||
|
this->last_pa_ = 1;
|
||||||
|
}
|
||||||
|
else if(this->frequency_ >= 378000 && this->frequency_ <= 464000)
|
||||||
|
{
|
||||||
|
if(pa <= -30) a = PA_TABLE_433[0];
|
||||||
|
else if(pa > -30 && pa <= -20) a = PA_TABLE_433[1];
|
||||||
|
else if(pa > -20 && pa <= -15) a = PA_TABLE_433[2];
|
||||||
|
else if(pa > -15 && pa <= -10) a = PA_TABLE_433[3];
|
||||||
|
else if(pa > -10 && pa <= 0) a = PA_TABLE_433[4];
|
||||||
|
else if(pa > 0 && pa <= 5) a = PA_TABLE_433[5];
|
||||||
|
else if(pa > 5 && pa <= 7) a = PA_TABLE_433[6];
|
||||||
|
else a = PA_TABLE_433[7];
|
||||||
|
this->last_pa_ = 2;
|
||||||
|
}
|
||||||
|
else if(this->frequency_ >= 779000 && this->frequency_ < 900000)
|
||||||
|
{
|
||||||
|
if(pa <= -30) a = PA_TABLE_868[0];
|
||||||
|
else if(pa > -30 && pa <= -20) a = PA_TABLE_868[1];
|
||||||
|
else if(pa > -20 && pa <= -15) a = PA_TABLE_868[2];
|
||||||
|
else if(pa > -15 && pa <= -10) a = PA_TABLE_868[3];
|
||||||
|
else if(pa > -10 && pa <= -6) a = PA_TABLE_868[4];
|
||||||
|
else if(pa > -6 && pa <= 0) a = PA_TABLE_868[5];
|
||||||
|
else if(pa > 0 && pa <= 5) a = PA_TABLE_868[6];
|
||||||
|
else if(pa > 5 && pa <= 7) a = PA_TABLE_868[7];
|
||||||
|
else if(pa > 7 && pa <= 10) a = PA_TABLE_868[8];
|
||||||
|
else a = PA_TABLE_868[9];
|
||||||
|
this->last_pa_ = 3;
|
||||||
|
}
|
||||||
|
else if(this->frequency_ >= 900000 && this->frequency_ <= 928000)
|
||||||
|
{
|
||||||
|
if(pa <= -30) a = PA_TABLE_915[0];
|
||||||
|
else if(pa > -30 && pa <= -20) a = PA_TABLE_915[1];
|
||||||
|
else if(pa > -20 && pa <= -15) a = PA_TABLE_915[2];
|
||||||
|
else if(pa > -15 && pa <= -10) a = PA_TABLE_915[3];
|
||||||
|
else if(pa > -10 && pa <= -6) a = PA_TABLE_915[4];
|
||||||
|
else if(pa > -6 && pa <= 0) a = PA_TABLE_915[5];
|
||||||
|
else if(pa > 0 && pa <= 5) a = PA_TABLE_915[6];
|
||||||
|
else if(pa > 5 && pa <= 7) a = PA_TABLE_915[7];
|
||||||
|
else if(pa > 7 && pa <= 10) a = PA_TABLE_915[8];
|
||||||
|
else a = PA_TABLE_915[9];
|
||||||
|
this->last_pa_ = 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESP_LOGE(TAG, "CC1101 set_pa(%d) frequency out of range: %d", pa, this->frequency_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->modulation_ == 2)
|
||||||
|
{
|
||||||
|
PA_TABLE[0] = 0;
|
||||||
|
PA_TABLE[1] = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
PA_TABLE[0] = a;
|
||||||
|
PA_TABLE[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->write_register_burst(CC1101_PATABLE, PA_TABLE, sizeof(PA_TABLE));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_frequency(uint32_t f)
|
||||||
|
{
|
||||||
|
this->frequency_ = f;
|
||||||
|
|
||||||
|
uint8_t freq2 = 0;
|
||||||
|
uint8_t freq1 = 0;
|
||||||
|
uint8_t freq0 = 0;
|
||||||
|
|
||||||
|
float mhz = (float)f / 1000;
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
if(mhz >= 26) { mhz -= 26; freq2++; }
|
||||||
|
else if(mhz >= 0.1015625) { mhz -= 0.1015625; freq1++; }
|
||||||
|
else if(mhz >= 0.00039675) { mhz -= 0.00039675; freq0++; }
|
||||||
|
else break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// TODO: impossible, freq0 being uint8_t, also 0.1015625/0.00039675 = 255.9861373660996, it would never reach 256
|
||||||
|
if(freq0 > 255)
|
||||||
|
{
|
||||||
|
freq1 += 1;
|
||||||
|
freq0 -= 256;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
this->write_register(CC1101_FREQ2, freq2);
|
||||||
|
this->write_register(CC1101_FREQ1, freq1);
|
||||||
|
this->write_register(CC1101_FREQ0, freq0);
|
||||||
|
|
||||||
|
// calibrate
|
||||||
|
|
||||||
|
mhz = (float)f / 1000;
|
||||||
|
|
||||||
|
if(mhz >= 300 && mhz <= 348)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_FSCTRL0, map(mhz, 300, 348, this->clb_[0][0], this->clb_[0][1]));
|
||||||
|
|
||||||
|
if(mhz < 322.88)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_TEST0, 0x0B);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_TEST0, 0x09);
|
||||||
|
|
||||||
|
uint8_t s = this->read_status_register(CC1101_FSCAL2);
|
||||||
|
|
||||||
|
if(s < 32)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_FSCAL2, s + 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->last_pa_ != 1) this->set_pa(this->pa_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(mhz >= 378 && mhz <= 464)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_FSCTRL0, map(mhz, 378, 464, this->clb_[1][0], this->clb_[1][1]));
|
||||||
|
|
||||||
|
if(mhz < 430.5)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_TEST0, 0x0B);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_TEST0, 0x09);
|
||||||
|
|
||||||
|
uint8_t s = this->read_status_register(CC1101_FSCAL2);
|
||||||
|
|
||||||
|
if(s < 32)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_FSCAL2, s + 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->last_pa_ != 2) this->set_pa(this->pa_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(mhz >= 779 && mhz <= 899.99)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_FSCTRL0, map(mhz, 779, 899, this->clb_[2][0], this->clb_[2][1]));
|
||||||
|
|
||||||
|
if(mhz < 861)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_TEST0, 0x0B);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_TEST0, 0x09);
|
||||||
|
|
||||||
|
uint8_t s = this->read_status_register(CC1101_FSCAL2);
|
||||||
|
|
||||||
|
if(s < 32)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_FSCAL2, s + 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->last_pa_ != 3) this->set_pa(this->pa_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(mhz >= 900 && mhz <= 928)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_FSCTRL0, map(mhz, 900, 928, this->clb_[3][0], this->clb_[3][1]));
|
||||||
|
this->write_register(CC1101_TEST0, 0x09);
|
||||||
|
|
||||||
|
uint8_t s = this->read_status_register(CC1101_FSCAL2);
|
||||||
|
|
||||||
|
if(s < 32)
|
||||||
|
{
|
||||||
|
this->write_register(CC1101_FSCAL2, s + 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->last_pa_ != 4) this->set_pa(this->pa_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_clb(uint8_t b, uint8_t s, uint8_t e)
|
||||||
|
{
|
||||||
|
if(b < 4)
|
||||||
|
{
|
||||||
|
this->clb_[b][0] = s;
|
||||||
|
this->clb_[b][1] = e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_rxbw(uint32_t bw)
|
||||||
|
{
|
||||||
|
this->bandwidth_ = bw;
|
||||||
|
|
||||||
|
float f = (float)this->bandwidth_;
|
||||||
|
|
||||||
|
int s1 = 3;
|
||||||
|
int s2 = 3;
|
||||||
|
|
||||||
|
for(int i = 0; i < 3 && f > 101.5625f; i++)
|
||||||
|
{
|
||||||
|
f /= 2;
|
||||||
|
s1--;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < 3 && f > 58.1f; i++)
|
||||||
|
{
|
||||||
|
f /= 1.25f;
|
||||||
|
s2--;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->split_MDMCFG4();
|
||||||
|
|
||||||
|
this->m4RxBw_ = (s1 << 6) | (s2 << 4);
|
||||||
|
|
||||||
|
this->write_register(CC1101_MDMCFG4, this->m4RxBw_ + this->m4DaRa_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_tx()
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "CC1101 set_tx");
|
||||||
|
this->send_cmd(CC1101_SIDLE);
|
||||||
|
this->send_cmd(CC1101_STX);
|
||||||
|
this->trxstate_ = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_rx()
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "CC1101 set_rx");
|
||||||
|
this->send_cmd(CC1101_SIDLE);
|
||||||
|
this->send_cmd(CC1101_SRX);
|
||||||
|
this->trxstate_ = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_sres()
|
||||||
|
{
|
||||||
|
this->send_cmd(CC1101_SRES);
|
||||||
|
this->trxstate_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_sidle()
|
||||||
|
{
|
||||||
|
this->send_cmd(CC1101_SIDLE);
|
||||||
|
this->trxstate_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::set_sleep()
|
||||||
|
{
|
||||||
|
this->send_cmd(CC1101_SIDLE); // Exit RX / TX, turn off frequency synthesizer and exit
|
||||||
|
this->send_cmd(CC1101_SPWD); // Enter power down mode when CSn goes high.
|
||||||
|
this->trxstate_ = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::split_MDMCFG2()
|
||||||
|
{
|
||||||
|
uint8_t calc = this->read_status_register(CC1101_MDMCFG2);
|
||||||
|
|
||||||
|
this->m2DCOFF_ = calc & 0x80;
|
||||||
|
this->m2MODFM_ = calc & 0x70;
|
||||||
|
this->m2MANCH_ = calc & 0x08;
|
||||||
|
this->m2SYNCM_ = calc & 0x07;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::split_MDMCFG4()
|
||||||
|
{
|
||||||
|
uint8_t calc = this->read_status_register(CC1101_MDMCFG4);
|
||||||
|
|
||||||
|
this->m4RxBw_ = calc & 0xf0;
|
||||||
|
this->m4DaRa_ = calc & 0x0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CC1101::get_rssi()
|
||||||
|
{
|
||||||
|
int32_t rssi;
|
||||||
|
rssi = this->read_status_register(CC1101_RSSI);
|
||||||
|
if(rssi >= 128) rssi -= 256;
|
||||||
|
return (rssi / 2) - 74;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t CC1101::get_lqi()
|
||||||
|
{
|
||||||
|
return this->read_status_register(CC1101_LQI);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::begin_tx()
|
||||||
|
{
|
||||||
|
this->set_tx();
|
||||||
|
|
||||||
|
if(this->gdo0_ == this->gdo2_)
|
||||||
|
{
|
||||||
|
#ifdef USE_ESP8266
|
||||||
|
#ifdef USE_ARDUINO
|
||||||
|
noInterrupts();
|
||||||
|
#else // USE_ESP_IDF
|
||||||
|
portDISABLE_INTERRUPTS()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
this->gdo0_->pin_mode(gpio::FLAG_OUTPUT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CC1101::end_tx()
|
||||||
|
{
|
||||||
|
if(this->gdo0_ == this->gdo2_)
|
||||||
|
{
|
||||||
|
#ifdef USE_ESP8266
|
||||||
|
#ifdef USE_ARDUINO
|
||||||
|
interrupts();
|
||||||
|
#else // USE_ESP_IDF
|
||||||
|
portENABLE_INTERRUPTS()
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
this->gdo0_->pin_mode(gpio::FLAG_INPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->set_rx();
|
||||||
|
this->set_rx(); // yes, twice (really?)
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cc1101
|
||||||
|
} // namespace esphome
|
109
esphome/components/cc1101/cc1101.h
Normal file
109
esphome/components/cc1101/cc1101.h
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "esphome/core/component.h"
|
||||||
|
#include "esphome/components/sensor/sensor.h"
|
||||||
|
#include "esphome/components/spi/spi.h"
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace cc1101 {
|
||||||
|
|
||||||
|
class CC1101
|
||||||
|
: public sensor::Sensor,
|
||||||
|
public PollingComponent,
|
||||||
|
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_1KHZ>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
InternalGPIOPin* gdo0_;
|
||||||
|
InternalGPIOPin* gdo2_;
|
||||||
|
uint32_t bandwidth_;
|
||||||
|
uint32_t frequency_;
|
||||||
|
sensor::Sensor* rssi_sensor_;
|
||||||
|
sensor::Sensor* lqi_sensor_;
|
||||||
|
|
||||||
|
uint8_t partnum_;
|
||||||
|
uint8_t version_;
|
||||||
|
int32_t last_rssi_;
|
||||||
|
int32_t last_lqi_;
|
||||||
|
|
||||||
|
bool reset();
|
||||||
|
void send_cmd(uint8_t cmd);
|
||||||
|
uint8_t read_register(uint8_t reg);
|
||||||
|
uint8_t read_config_register(uint8_t reg);
|
||||||
|
uint8_t read_status_register(uint8_t reg);
|
||||||
|
void read_register_burst(uint8_t reg, uint8_t* buffer, size_t length);
|
||||||
|
void write_register(uint8_t reg, uint8_t* value, size_t length);
|
||||||
|
void write_register(uint8_t reg, uint8_t value);
|
||||||
|
void write_register_burst(uint8_t reg, uint8_t* buffer, size_t length);
|
||||||
|
//bool send_data(const uint8_t* data, size_t length);
|
||||||
|
|
||||||
|
// ELECHOUSE_CC1101 stuff
|
||||||
|
|
||||||
|
bool mode_;
|
||||||
|
uint8_t modulation_;
|
||||||
|
uint8_t frend0_;
|
||||||
|
uint8_t chan_;
|
||||||
|
int8_t pa_;
|
||||||
|
uint8_t last_pa_;
|
||||||
|
uint8_t m4RxBw_;
|
||||||
|
uint8_t m4DaRa_;
|
||||||
|
uint8_t m2DCOFF_;
|
||||||
|
uint8_t m2MODFM_;
|
||||||
|
uint8_t m2MANCH_;
|
||||||
|
uint8_t m2SYNCM_;
|
||||||
|
uint8_t m1FEC_;
|
||||||
|
uint8_t m1PRE_;
|
||||||
|
uint8_t m1CHSP_;
|
||||||
|
uint8_t trxstate_;
|
||||||
|
uint8_t clb_[4][2];
|
||||||
|
|
||||||
|
void set_mode(bool s);
|
||||||
|
void set_frequency(uint32_t f);
|
||||||
|
void set_modulation(uint8_t m);
|
||||||
|
void set_pa(int8_t pa);
|
||||||
|
void set_clb(uint8_t b, uint8_t s, uint8_t e);
|
||||||
|
void set_rxbw(uint32_t bw);
|
||||||
|
void set_tx();
|
||||||
|
void set_rx();
|
||||||
|
void set_sres();
|
||||||
|
void set_sidle();
|
||||||
|
void set_sleep();
|
||||||
|
|
||||||
|
void split_MDMCFG2();
|
||||||
|
void split_MDMCFG4();
|
||||||
|
|
||||||
|
public:
|
||||||
|
CC1101();
|
||||||
|
|
||||||
|
void set_config_gdo0(InternalGPIOPin* pin);
|
||||||
|
void set_config_gdo2(InternalGPIOPin* pin);
|
||||||
|
void set_config_bandwidth(uint32_t bandwidth);
|
||||||
|
void set_config_frequency(uint32_t frequency);
|
||||||
|
void set_config_rssi_sensor(sensor::Sensor* rssi_sensor);
|
||||||
|
void set_config_lqi_sensor(sensor::Sensor* lqi_sensor);
|
||||||
|
|
||||||
|
void setup() override;
|
||||||
|
void update() override;
|
||||||
|
void dump_config() override;
|
||||||
|
|
||||||
|
int32_t get_rssi();
|
||||||
|
uint8_t get_lqi();
|
||||||
|
|
||||||
|
void begin_tx();
|
||||||
|
void end_tx();
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class BeginTxAction : public Action<Ts...>, public Parented<CC1101>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void play(Ts... x) override { this->parent_->begin_tx(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename... Ts> class EndTxAction : public Action<Ts...>, public Parented<CC1101>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void play(Ts... x) override { this->parent_->end_tx(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace cc1101
|
||||||
|
} // namespace esphome
|
||||||
|
|
110
esphome/components/cc1101/cc1101defs.h
Normal file
110
esphome/components/cc1101/cc1101defs.h
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Datasheet: https://www.ti.com/lit/ds/symlink/cc1101.pdf
|
||||||
|
|
||||||
|
namespace esphome {
|
||||||
|
namespace cc1101 {
|
||||||
|
|
||||||
|
//***************************************CC1101 define**************************************************//
|
||||||
|
// CC1101 CONFIG REGSITER
|
||||||
|
static const uint32_t CC1101_IOCFG2 = 0x00; // GDO2 output pin configuration
|
||||||
|
static const uint32_t CC1101_IOCFG1 = 0x01; // GDO1 output pin configuration
|
||||||
|
static const uint32_t CC1101_IOCFG0 = 0x02; // GDO0 output pin configuration
|
||||||
|
static const uint32_t CC1101_FIFOTHR = 0x03; // RX FIFO and TX FIFO thresholds
|
||||||
|
static const uint32_t CC1101_SYNC1 = 0x04; // Sync word, high INT8U
|
||||||
|
static const uint32_t CC1101_SYNC0 = 0x05; // Sync word, low INT8U
|
||||||
|
static const uint32_t CC1101_PKTLEN = 0x06; // Packet length
|
||||||
|
static const uint32_t CC1101_PKTCTRL1 = 0x07; // Packet automation control
|
||||||
|
static const uint32_t CC1101_PKTCTRL0 = 0x08; // Packet automation control
|
||||||
|
static const uint32_t CC1101_ADDR = 0x09; // Device address
|
||||||
|
static const uint32_t CC1101_CHANNR = 0x0A; // Channel number
|
||||||
|
static const uint32_t CC1101_FSCTRL1 = 0x0B; // Frequency synthesizer control
|
||||||
|
static const uint32_t CC1101_FSCTRL0 = 0x0C; // Frequency synthesizer control
|
||||||
|
static const uint32_t CC1101_FREQ2 = 0x0D; // Frequency control word, high INT8U
|
||||||
|
static const uint32_t CC1101_FREQ1 = 0x0E; // Frequency control word, middle INT8U
|
||||||
|
static const uint32_t CC1101_FREQ0 = 0x0F; // Frequency control word, low INT8U
|
||||||
|
static const uint32_t CC1101_MDMCFG4 = 0x10; // Modem configuration
|
||||||
|
static const uint32_t CC1101_MDMCFG3 = 0x11; // Modem configuration
|
||||||
|
static const uint32_t CC1101_MDMCFG2 = 0x12; // Modem configuration
|
||||||
|
static const uint32_t CC1101_MDMCFG1 = 0x13; // Modem configuration
|
||||||
|
static const uint32_t CC1101_MDMCFG0 = 0x14; // Modem configuration
|
||||||
|
static const uint32_t CC1101_DEVIATN = 0x15; // Modem deviation setting
|
||||||
|
static const uint32_t CC1101_MCSM2 = 0x16; // Main Radio Control State Machine configuration
|
||||||
|
static const uint32_t CC1101_MCSM1 = 0x17; // Main Radio Control State Machine configuration
|
||||||
|
static const uint32_t CC1101_MCSM0 = 0x18; // Main Radio Control State Machine configuration
|
||||||
|
static const uint32_t CC1101_FOCCFG = 0x19; // Frequency Offset Compensation configuration
|
||||||
|
static const uint32_t CC1101_BSCFG = 0x1A; // Bit Synchronization configuration
|
||||||
|
static const uint32_t CC1101_AGCCTRL2 = 0x1B; // AGC control
|
||||||
|
static const uint32_t CC1101_AGCCTRL1 = 0x1C; // AGC control
|
||||||
|
static const uint32_t CC1101_AGCCTRL0 = 0x1D; // AGC control
|
||||||
|
static const uint32_t CC1101_WOREVT1 = 0x1E; // High INT8U Event 0 timeout
|
||||||
|
static const uint32_t CC1101_WOREVT0 = 0x1F; // Low INT8U Event 0 timeout
|
||||||
|
static const uint32_t CC1101_WORCTRL = 0x20; // Wake On Radio control
|
||||||
|
static const uint32_t CC1101_FREND1 = 0x21; // Front end RX configuration
|
||||||
|
static const uint32_t CC1101_FREND0 = 0x22; // Front end TX configuration
|
||||||
|
static const uint32_t CC1101_FSCAL3 = 0x23; // Frequency synthesizer calibration
|
||||||
|
static const uint32_t CC1101_FSCAL2 = 0x24; // Frequency synthesizer calibration
|
||||||
|
static const uint32_t CC1101_FSCAL1 = 0x25; // Frequency synthesizer calibration
|
||||||
|
static const uint32_t CC1101_FSCAL0 = 0x26; // Frequency synthesizer calibration
|
||||||
|
static const uint32_t CC1101_RCCTRL1 = 0x27; // RC oscillator configuration
|
||||||
|
static const uint32_t CC1101_RCCTRL0 = 0x28; // RC oscillator configuration
|
||||||
|
static const uint32_t CC1101_FSTEST = 0x29; // Frequency synthesizer calibration control
|
||||||
|
static const uint32_t CC1101_PTEST = 0x2A; // Production test
|
||||||
|
static const uint32_t CC1101_AGCTEST = 0x2B; // AGC test
|
||||||
|
static const uint32_t CC1101_TEST2 = 0x2C; // Various test settings
|
||||||
|
static const uint32_t CC1101_TEST1 = 0x2D; // Various test settings
|
||||||
|
static const uint32_t CC1101_TEST0 = 0x2E; // Various test settings
|
||||||
|
|
||||||
|
//CC1101 Strobe commands
|
||||||
|
static const uint32_t CC1101_SRES = 0x30; // Reset chip.
|
||||||
|
static const uint32_t CC1101_SFSTXON = 0x31; // Enable and calibrate frequency synthesizer (if MCSM0.FS_AUTOCAL=1).
|
||||||
|
// If in RX/TX: Go to a wait state where only the synthesizer is
|
||||||
|
// running (for quick RX / TX turnaround).
|
||||||
|
static const uint32_t CC1101_SXOFF = 0x32; // Turn off crystal oscillator.
|
||||||
|
static const uint32_t CC1101_SCAL = 0x33; // Calibrate frequency synthesizer and turn it off
|
||||||
|
// (enables quick start).
|
||||||
|
static const uint32_t CC1101_SRX = 0x34; // Enable RX. Perform calibration first if coming from IDLE and
|
||||||
|
// MCSM0.FS_AUTOCAL=1.
|
||||||
|
static const uint32_t CC1101_STX = 0x35; // In IDLE state: Enable TX. Perform calibration first if
|
||||||
|
// MCSM0.FS_AUTOCAL=1. If in RX state and CCA is enabled:
|
||||||
|
// Only go to TX if channel is clear.
|
||||||
|
static const uint32_t CC1101_SIDLE = 0x36; // Exit RX / TX, turn off frequency synthesizer and exit
|
||||||
|
// Wake-On-Radio mode if applicable.
|
||||||
|
static const uint32_t CC1101_SAFC = 0x37; // Perform AFC adjustment of the frequency synthesizer
|
||||||
|
static const uint32_t CC1101_SWOR = 0x38; // Start automatic RX polling sequence (Wake-on-Radio)
|
||||||
|
static const uint32_t CC1101_SPWD = 0x39; // Enter power down mode when CSn goes high.
|
||||||
|
static const uint32_t CC1101_SFRX = 0x3A; // Flush the RX FIFO buffer.
|
||||||
|
static const uint32_t CC1101_SFTX = 0x3B; // Flush the TX FIFO buffer.
|
||||||
|
static const uint32_t CC1101_SWORRST = 0x3C; // Reset real time clock.
|
||||||
|
static const uint32_t CC1101_SNOP = 0x3D; // No operation. May be used to pad strobe commands to two
|
||||||
|
// INT8Us for simpler software.
|
||||||
|
//CC1101 STATUS REGSITER
|
||||||
|
static const uint32_t CC1101_PARTNUM = 0x30;
|
||||||
|
static const uint32_t CC1101_VERSION = 0x31;
|
||||||
|
static const uint32_t CC1101_FREQEST = 0x32;
|
||||||
|
static const uint32_t CC1101_LQI = 0x33;
|
||||||
|
static const uint32_t CC1101_RSSI = 0x34;
|
||||||
|
static const uint32_t CC1101_MARCSTATE = 0x35;
|
||||||
|
static const uint32_t CC1101_WORTIME1 = 0x36;
|
||||||
|
static const uint32_t CC1101_WORTIME0 = 0x37;
|
||||||
|
static const uint32_t CC1101_PKTSTATUS = 0x38;
|
||||||
|
static const uint32_t CC1101_VCO_VC_DAC = 0x39;
|
||||||
|
static const uint32_t CC1101_TXBYTES = 0x3A;
|
||||||
|
static const uint32_t CC1101_RXBYTES = 0x3B;
|
||||||
|
|
||||||
|
//CC1101 PATABLE,TXFIFO,RXFIFO
|
||||||
|
static const uint32_t CC1101_PATABLE = 0x3E;
|
||||||
|
static const uint32_t CC1101_TXFIFO = 0x3F;
|
||||||
|
static const uint32_t CC1101_RXFIFO = 0x3F;
|
||||||
|
|
||||||
|
static const uint32_t CC1101_WRITE_BURST = 0x40; // write burst
|
||||||
|
static const uint32_t CC1101_READ_SINGLE = 0x80; // read single
|
||||||
|
static const uint32_t CC1101_READ_BURST = 0xC0; // read burst
|
||||||
|
static const uint32_t CC1101_BYTES_IN_RXFIFO = 0x7F; // byte number in RXfifo
|
||||||
|
|
||||||
|
static const uint32_t CC1101_MARCSTATE_TX = 0x13;
|
||||||
|
static const uint32_t CC1101_MARCSTATE_TX_END = 0x14;
|
||||||
|
static const uint32_t CC1101_MARCSTATE_RXTX_SWITCH = 0x15;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
89
esphome/components/cc1101/sensor.py
Normal file
89
esphome/components/cc1101/sensor.py
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
import esphome.codegen as cg
|
||||||
|
import esphome.config_validation as cv
|
||||||
|
from esphome import automation, pins
|
||||||
|
from esphome.components import sensor
|
||||||
|
from esphome.components import spi
|
||||||
|
from esphome.automation import maybe_simple_id
|
||||||
|
from esphome.const import (
|
||||||
|
CONF_ID,
|
||||||
|
UNIT_EMPTY,
|
||||||
|
UNIT_DECIBEL_MILLIWATT,
|
||||||
|
DEVICE_CLASS_SIGNAL_STRENGTH,
|
||||||
|
STATE_CLASS_MEASUREMENT
|
||||||
|
)
|
||||||
|
|
||||||
|
CODEOWNERS = ["@gabest11", "@dbuezas", "@nistvan86", "@LSatan"]
|
||||||
|
|
||||||
|
DEPENDENCIES = ["spi"]
|
||||||
|
|
||||||
|
CONF_GDO0 = "gdo0"
|
||||||
|
CONF_GDO2 = "gdo2"
|
||||||
|
CONF_BANDWIDTH = "bandwidth"
|
||||||
|
CONF_FREQUENCY = "frequency"
|
||||||
|
CONF_RSSI = "rssi"
|
||||||
|
CONF_LQI = "lqi"
|
||||||
|
|
||||||
|
cc1101_ns = cg.esphome_ns.namespace("cc1101")
|
||||||
|
CC1101 = cc1101_ns.class_("CC1101", sensor.Sensor, cg.PollingComponent, spi.SPIDevice)
|
||||||
|
|
||||||
|
BeginTxAction = cc1101_ns.class_("BeginTxAction", automation.Action)
|
||||||
|
EndTxAction = cc1101_ns.class_("EndTxAction", automation.Action)
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = (
|
||||||
|
cv.Schema(
|
||||||
|
{
|
||||||
|
cv.GenerateID(): cv.declare_id(CC1101),
|
||||||
|
cv.Required(CONF_GDO0): pins.gpio_output_pin_schema,
|
||||||
|
cv.Optional(CONF_GDO2): pins.gpio_input_pin_schema,
|
||||||
|
cv.Optional(CONF_BANDWIDTH, default=200): cv.uint32_t,
|
||||||
|
cv.Optional(CONF_FREQUENCY, default=433920): cv.uint32_t,
|
||||||
|
cv.Optional(CONF_RSSI): sensor.sensor_schema(
|
||||||
|
unit_of_measurement = UNIT_DECIBEL_MILLIWATT,
|
||||||
|
accuracy_decimals = 0,
|
||||||
|
device_class = DEVICE_CLASS_SIGNAL_STRENGTH,
|
||||||
|
state_class = STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
cv.Optional(CONF_LQI): sensor.sensor_schema(
|
||||||
|
unit_of_measurement = UNIT_EMPTY,
|
||||||
|
accuracy_decimals = 0,
|
||||||
|
state_class = STATE_CLASS_MEASUREMENT,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.extend(cv.polling_component_schema("60s"))
|
||||||
|
.extend(spi.spi_device_schema(cs_pin_required=True))
|
||||||
|
)
|
||||||
|
|
||||||
|
CC1101_ACTION_SCHEMA = maybe_simple_id(
|
||||||
|
{
|
||||||
|
cv.Required(CONF_ID): cv.use_id(CC1101),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
@automation.register_action("cc1101.begin_tx", BeginTxAction, CC1101_ACTION_SCHEMA)
|
||||||
|
@automation.register_action("cc1101.end_tx", EndTxAction, CC1101_ACTION_SCHEMA)
|
||||||
|
|
||||||
|
async def cc1101_action_to_code(config, action_id, template_arg, args):
|
||||||
|
var = cg.new_Pvariable(action_id, template_arg)
|
||||||
|
await cg.register_parented(var, config[CONF_ID])
|
||||||
|
return var
|
||||||
|
|
||||||
|
async def to_code(config):
|
||||||
|
var = cg.new_Pvariable(config[CONF_ID])
|
||||||
|
await cg.register_component(var, config)
|
||||||
|
await spi.register_spi_device(var, config)
|
||||||
|
|
||||||
|
gdo0 = await cg.gpio_pin_expression(config[CONF_GDO0])
|
||||||
|
cg.add(var.set_config_gdo0(gdo0))
|
||||||
|
if CONF_GDO2 in config:
|
||||||
|
gdo2 = await cg.gpio_pin_expression(config[CONF_GDO2])
|
||||||
|
cg.add(var.set_config_gdo2(gdo2))
|
||||||
|
cg.add(var.set_config_bandwidth(config[CONF_BANDWIDTH]))
|
||||||
|
cg.add(var.set_config_frequency(config[CONF_FREQUENCY]))
|
||||||
|
if CONF_RSSI in config:
|
||||||
|
rssi = await sensor.new_sensor(config[CONF_RSSI])
|
||||||
|
cg.add(var.set_config_rssi_sensor(rssi))
|
||||||
|
if CONF_LQI in config:
|
||||||
|
lqi = await sensor.new_sensor(config[CONF_LQI])
|
||||||
|
cg.add(var.set_config_lqi_sensor(lqi))
|
||||||
|
|
Loading…
Reference in a new issue