#ifndef RADIO_CC1101_H #define RADIO_CC1101_H #include #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