Snapshot: full project state
This commit is contained in:
224
include/radio_cc1101.h
Normal file
224
include/radio_cc1101.h
Normal file
@@ -0,0 +1,224 @@
|
||||
#ifndef RADIO_CC1101_H
|
||||
#define RADIO_CC1101_H
|
||||
|
||||
#include <SPI.h>
|
||||
#include "board_config.h"
|
||||
|
||||
// CC1101 SubGHz Radio Driver
|
||||
// Supports 300-928 MHz, optional E07-433M20S PA module (20dBm amplified)
|
||||
class RadioCC1101 {
|
||||
public:
|
||||
// Frequency bands
|
||||
enum FreqBand {
|
||||
BAND_433MHZ = 0,
|
||||
BAND_868MHZ = 1,
|
||||
BAND_915MHZ = 2,
|
||||
};
|
||||
|
||||
// Initialize SPI and radio
|
||||
static bool begin(FreqBand band = BAND_433MHZ, bool use_pa_module = false) {
|
||||
// Setup GPIO
|
||||
pinMode(CC1101_CS, OUTPUT);
|
||||
pinMode(CC1101_GDO0, INPUT); // TX/data out
|
||||
pinMode(CC1101_GDO2, INPUT); // RX/data in
|
||||
|
||||
if (use_pa_module) {
|
||||
pinMode(CC1101_TX_EN, OUTPUT);
|
||||
pinMode(CC1101_RX_EN, OUTPUT);
|
||||
digitalWrite(CC1101_TX_EN, LOW);
|
||||
digitalWrite(CC1101_RX_EN, LOW);
|
||||
}
|
||||
|
||||
// Start SPI
|
||||
SPI.begin(RADIO_SPI_CLK, RADIO_SPI_MISO, RADIO_SPI_MOSI);
|
||||
SPI.setFrequency(10000000); // 10 MHz
|
||||
SPI.setDataMode(SPI_MODE0);
|
||||
|
||||
// Reset radio
|
||||
reset();
|
||||
delay(100);
|
||||
|
||||
// Verify chip
|
||||
uint8_t id = readReg(0x0F);
|
||||
if (id != 0x04) {
|
||||
return false; // Not a CC1101
|
||||
}
|
||||
|
||||
// Configure for band
|
||||
switch (band) {
|
||||
case BAND_433MHZ:
|
||||
setFreq(433.92f);
|
||||
break;
|
||||
case BAND_868MHZ:
|
||||
setFreq(868.0f);
|
||||
break;
|
||||
case BAND_915MHZ:
|
||||
setFreq(915.0f);
|
||||
break;
|
||||
}
|
||||
|
||||
// RX mode
|
||||
setRxMode();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set frequency (MHz)
|
||||
static void setFreq(float freq_mhz) {
|
||||
// CC1101 frequency = FREQ_REG * (Fxosc / 2^16)
|
||||
// Fxosc = 26 MHz
|
||||
uint32_t freq = (uint32_t)(freq_mhz / (26.0f / 65536.0f));
|
||||
|
||||
writeReg(0x0D, (freq >> 16) & 0xFF);
|
||||
writeReg(0x0E, (freq >> 8) & 0xFF);
|
||||
writeReg(0x0F, freq & 0xFF);
|
||||
}
|
||||
|
||||
// Set TX power (dBm)
|
||||
// 0xFF = +10dBm, 0xFE = +7dBm, 0x84 = +5dBm, etc.
|
||||
static void setTxPower(uint8_t pwr) {
|
||||
writeReg(0x3E, pwr);
|
||||
}
|
||||
|
||||
// Set max power (12dBm for stock, 20dBm with E07 PA)
|
||||
static void setMaxPower(bool use_pa_module = false) {
|
||||
if (use_pa_module) {
|
||||
// E07 PA module: TX_EN + RX_EN control
|
||||
setTxPower(0xFF); // +10 dBm + 10 dBm from PA = ~20 dBm
|
||||
} else {
|
||||
// Stock CC1101: +12 dBm
|
||||
setTxPower(0x84);
|
||||
}
|
||||
}
|
||||
|
||||
// Switch to RX mode
|
||||
static void setRxMode() {
|
||||
strobe(0x34); // RX enable
|
||||
}
|
||||
|
||||
// Switch to TX mode
|
||||
static void setTxMode() {
|
||||
strobe(0x35); // TX enable
|
||||
}
|
||||
|
||||
// Transmit data
|
||||
static void transmit(const uint8_t* data, uint8_t len) {
|
||||
// Clear TX FIFO
|
||||
strobe(0x3B);
|
||||
delay(10);
|
||||
|
||||
// Fill TX FIFO
|
||||
digitalWrite(CC1101_CS, LOW);
|
||||
SPI.transfer(0x3F); // FIFO address
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
SPI.transfer(data[i]);
|
||||
}
|
||||
digitalWrite(CC1101_CS, HIGH);
|
||||
|
||||
// TX
|
||||
setTxMode();
|
||||
}
|
||||
|
||||
// Receive data (blocking)
|
||||
// Returns length of received packet or 0 if none
|
||||
static uint8_t receive(uint8_t* buffer, uint8_t max_len, uint32_t timeout_ms) {
|
||||
uint32_t start = millis();
|
||||
|
||||
setRxMode();
|
||||
|
||||
while (millis() - start < timeout_ms) {
|
||||
// Check for RX packet (GDO0)
|
||||
if (digitalRead(CC1101_GDO0) == HIGH) {
|
||||
// Read FIFO
|
||||
uint8_t rx_len = readReg(0x3F);
|
||||
|
||||
if (rx_len > 0 && rx_len <= max_len) {
|
||||
digitalWrite(CC1101_CS, LOW);
|
||||
SPI.transfer(0xBF); // RX FIFO read
|
||||
for (uint8_t i = 0; i < rx_len; i++) {
|
||||
buffer[i] = SPI.transfer(0x00);
|
||||
}
|
||||
digitalWrite(CC1101_CS, HIGH);
|
||||
|
||||
// Clear RX FIFO
|
||||
strobe(0x3A);
|
||||
|
||||
return rx_len;
|
||||
}
|
||||
}
|
||||
delayMicroseconds(100);
|
||||
}
|
||||
|
||||
return 0; // Timeout
|
||||
}
|
||||
|
||||
// Get RSSI (signal strength)
|
||||
static int8_t getRSSI() {
|
||||
uint8_t raw = readReg(0x34);
|
||||
if (raw >= 128) {
|
||||
return (raw - 256) / 2 - 74;
|
||||
}
|
||||
return raw / 2 - 74;
|
||||
}
|
||||
|
||||
// Sleep mode (low power)
|
||||
static void sleep() {
|
||||
strobe(0x36); // IDLE
|
||||
delay(10);
|
||||
strobe(0x39); // Sleep
|
||||
}
|
||||
|
||||
static void wakeup() {
|
||||
strobe(0x3C); // Wakeup
|
||||
delay(10);
|
||||
}
|
||||
|
||||
private:
|
||||
// Reset CC1101
|
||||
static void reset() {
|
||||
digitalWrite(CC1101_CS, LOW);
|
||||
delayMicroseconds(10);
|
||||
digitalWrite(CC1101_CS, HIGH);
|
||||
delayMicroseconds(40);
|
||||
|
||||
digitalWrite(CC1101_CS, LOW);
|
||||
while (digitalRead(RADIO_SPI_MISO) == HIGH);
|
||||
SPI.transfer(0x30); // SRES (reset strobe)
|
||||
while (digitalRead(RADIO_SPI_MISO) == HIGH);
|
||||
digitalWrite(CC1101_CS, HIGH);
|
||||
|
||||
delayMicroseconds(40);
|
||||
}
|
||||
|
||||
// Send strobe command
|
||||
static void strobe(uint8_t cmd) {
|
||||
digitalWrite(CC1101_CS, LOW);
|
||||
while (digitalRead(RADIO_SPI_MISO) == HIGH);
|
||||
SPI.transfer(cmd);
|
||||
while (digitalRead(RADIO_SPI_MISO) == HIGH);
|
||||
digitalWrite(CC1101_CS, HIGH);
|
||||
}
|
||||
|
||||
// Read register
|
||||
static uint8_t readReg(uint8_t reg) {
|
||||
digitalWrite(CC1101_CS, LOW);
|
||||
while (digitalRead(RADIO_SPI_MISO) == HIGH);
|
||||
SPI.transfer(0x80 | reg); // Read bit
|
||||
uint8_t val = SPI.transfer(0x00);
|
||||
while (digitalRead(RADIO_SPI_MISO) == HIGH);
|
||||
digitalWrite(CC1101_CS, HIGH);
|
||||
return val;
|
||||
}
|
||||
|
||||
// Write register
|
||||
static void writeReg(uint8_t reg, uint8_t val) {
|
||||
digitalWrite(CC1101_CS, LOW);
|
||||
while (digitalRead(RADIO_SPI_MISO) == HIGH);
|
||||
SPI.transfer(reg);
|
||||
SPI.transfer(val);
|
||||
while (digitalRead(RADIO_SPI_MISO) == HIGH);
|
||||
digitalWrite(CC1101_CS, HIGH);
|
||||
}
|
||||
};
|
||||
|
||||
#endif // RADIO_CC1101_H
|
||||
Reference in New Issue
Block a user