Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions content/components/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -1036,6 +1036,7 @@ Used for creating infrared (IR) or radio frequency (RF) remote control transmitt
ESPHome to cellular networks. **Does not encompass Wi-Fi.**

{{< imgtable >}}
"CC1101","components/cc1101","cc1101.webp",""
"IR Remote Climate","components/climate/climate_ir","air-conditioner-ir.svg","dark-invert"
"Remote Receiver","components/remote_receiver","remote.svg","dark-invert"
"Remote Transmitter","components/remote_transmitter","remote.svg","dark-invert"
Expand Down
197 changes: 197 additions & 0 deletions content/components/cc1101.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
---
title: CC1101 Low-Power Sub-1 GHz RF Transceiver
description: Instructions for setting up CC1101 RF Transceiver in ESPHome.
image: cc1101.webp
keywords: [cc1101]
---

The **CC1101** component provides a driver for the **Texas Instruments CC1101** Sub-1 GHz RF Transceiver.
It allows you to transmit and receive raw RF signals (ASK/OOK, FSK, etc.) using the standard
[Remote Transmitter](remote_transmitter.md) and [Remote Receiver](remote_receiver.md) components.

This component requires the [SPI Component](spi.md) to be enabled.

<img src="cc1101.webp" alt="Image" width="50.0%" class="align-center">

## Component Configuration

```yaml
# Minimal Example
cc1101:
cs_pin: GPIOXX
gdo0_pin: GPIOXX
frequency: 433.92MHz
```

## Configuration Variables

### Hardware Settings

- **cs\_pin** (**Required**, [Pin](pin.md)): The SPI Chip Select (CSN) pin connected to the module.
- **gdo0\_pin** (**Required**, [Pin](pin.md)): The pin connected to **GDO0** on the CC1101.
- **Note:** `remote_transmitter` **must** use the pin connected to **GDO0** to transmit successfully.

### General Settings

- **frequency** (*Optional*, frequency): The operating frequency. Range: `300MHz` to `928MHz`. Default: `433.92MHz`.
- **output\_power** (*Optional*, float): The transmission power in dBm. Range: `-30` to `11`. Default: `10`.
- **modulation\_type** (*Optional*, enum): The modulation format. Options: `ASK/OOK` (default), `2-FSK`, `4-FSK`, `GFSK`, `MSK`.
- **symbol\_rate** (*Optional*, int): The symbol rate in Baud. Range: `600` to `500000`. Default: `5000`.
- **rx\_attenuation** (*Optional*, enum): Internal RX attenuation. Options: `0dB`, `6dB`, `12dB`, `18dB`. Default: `0dB`.
- **dc\_blocking\_filter** (*Optional*, boolean): Enable the digital DC blocking filter. Default: `True`.

### Tuner Settings

- **filter\_bandwidth** (*Optional*, frequency): The receive filter bandwidth. Range: `58kHz` to `812kHz`. Default: `203kHz`.
- **fsk\_deviation** (*Optional*, frequency): Frequency deviation for FSK/GFSK modulation.
- **channel** (*Optional*, int): Channel number (added to base frequency).
- **channel\_spacing** (*Optional*, frequency): Spacing between channels.
- **if\_frequency** (*Optional*, frequency): Intermediate Frequency. Default is optimized for 433MHz usage.
- **pktlen** (*Optional*, int): Packet length config. -->

### AGC (Automatic Gain Control) Settings

Advanced users can fine-tune the AGC dynamics.

- **magn\_target** (*Optional*, dB): Target signal amplitude. Range: `24dB` to `42dB` in increments of 3(eg. `33dB`).
- **max\_lna\_gain** (*Optional*, dB): Maximum LNA gain reduction. Options: `Default`, `2.6dB`, `6.1dB`, `7.4dB`, `9.2dB`, `11.5dB`, `14.6dB`, `17.1dB`.
- **max\_dvga\_gain** (*Optional*, enum): Maximum Digital Variable Gain reduction. Options: `Default`, `-1`, `-2`, `-3`.
- **lna\_priority** (*Optional*, boolean): If true, decrease LNA gain before DVGA gain.
- **carrier\_sense\_abs\_thr** (*Optional*, int): Absolute RSSI threshold for Carrier Sense.
- **carrier\_sense\_rel\_thr** (*Optional*, enum): Relative RSSI threshold for Carrier Sense.
- **filter\_length\_fsk\_msk** (*Optional*, enum): Averaging length for FSK/MSK.
- **filter\_length\_ask\_ook** (*Optional*, enum): Averaging length for ASK/OOK.
- **freeze** (*Optional*, enum): AGC gain freeze behavior.
- **wait\_time** (*Optional*, enum): AGC wait time.
- **hyst\_level** (*Optional*, enum): AGC hysteresis level.

## Actions

This component provides actions to control the radio state, primarily used for coordinating transmission.

- **cc1101.begin\_tx**: Wakes the radio and forces it into TX mode. This **must** be called before `remote_transmitter` starts sending data.
- **cc1101.end\_tx**: Puts the radio back into RX mode and resets the pin configuration to safe defaults.
- **cc1101.reset**: Resets the CC1101 chip and re-applies configuration.

### Example Transmit Button

```yaml
button:
- platform: template
name: "Send Signal"
on_press:
# 1. Wake up radio and enter TX mode (Blocking wait)
- cc1101.begin_tx:

# 2. Send data using standard Remote Transmitter
- remote_transmitter.transmit_raw:
code: [1000, -1000, 1000, -1000]
repeat: 5

# 3. Return to RX mode
- cc1101.end_tx:
```

## Integration with Remote Receiver/Transmitter

### Wiring for Single Pin Usage

Wire **GDO0** to a single GPIO and use it for both TX and RX.

```yaml
cc1101:
gdo0_pin:
pin:
number: GPIOXX # CC1101 GDO0
mode:
input: true
output: true
pullup: true
open_drain: true
allow_other_uses: true

remote_transmitter:
pin:
number: GPIOXX # Must match GDO0
mode:
input: true
output: true
pullup: true
open_drain: true
allow_other_uses: true
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still missing this in remote transmitter:

  eot_level: false
  on_transmit:
    then:
      - sx127x.set_mode_standby
      - remote_transmitter.digital_write: false
      - sx127x.set_mode_tx
  on_complete:
    then:
      - sx127x.set_mode_standby
      - remote_transmitter.digital_write: true
      - sx127x.set_mode_rx

carrier_duty_percent: 100%
on_transmit:
then:
- cc1101.begin_tx:
on_complete:
then:
- cc1101.end_tx:
Copy link
Member

@swoboda1337 swoboda1337 Nov 19, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You really need to do the same thing as the sx127x when using the same pin:

  eot_level: false
  on_transmit:
    then:
      - sx127x.set_mode_standby
      - remote_transmitter.digital_write: false
      - sx127x.set_mode_tx
  on_complete:
    then:
      - sx127x.set_mode_standby
      - remote_transmitter.digital_write: true
      - sx127x.set_mode_rx

Since the pin is configured as open drain it needs special handling. With open drain it is actively driven low by the chip but passively pulled up by the pull up. In rx the transmitter needs to be set the pin to high. By setting it to high the chip no longer drives the pin and the receiver is able to drive it (only the pullup is connected). Before switching to transmit its best to set the radio to idle, then drive the pin low and only then switch to tx. This avoids transmitting 'on' before remote transmitter starts. When switching to rx it is the same thing in reverse.

What you have won't work without the remote_transmitter.digital_write calls


remote_receiver:
pin:
number: GPIOXX # Must match GDO0
mode:
input: true
output: true
pullup: true
open_drain: true
allow_other_uses: true
dump: all
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need modify the pin config that will fail validation and not work, see: https://esphome.io/components/sx127x/#as-a-transmitter--receiver

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can copy the example from my docs. Claude is really good at it too and can do it in a few seconds.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i think fixed it correctly in the latest commit?

### Wiring for Split Pin Usage

- **GDO0 (Pin 3)**: Connect to the pin used by `remote_transmitter`.
- **GDO2 (Pin 8)**: Connect to the pin used by `remote_receiver`.

```yaml
cc1101:
gdo0_pin:
pin:
number: GPIOXX # Must match GDO0
mode:
input: true
output: true
pullup: true
open_drain: true
allow_other_uses: true

remote_transmitter:
pin:
number: GPIOXX # Must match GDO0
mode:
input: true
output: true
pullup: true
open_drain: true
allow_other_uses: true
carrier_duty_percent: 100%
on_transmit:
then:
- cc1101.begin_tx:
on_complete:
then:
- cc1101.end_tx:

remote_receiver:
pin: GPIOXX # CC1101 GDO2
dump: all
```

## Troubleshooting

### "FF0F was found" Error

If you see a log entry stating `FF0F`, `0000`, or `FFFF` during setup, this indicates an SPI communication failure. Check your wiring (MISO/MOSI/CS).

### No Signal during Transmit

- **Check Pinout:** Ensure `remote_transmitter` is assigned to the pin physically connected to **GDO0**. The CC1101 **only** supports transmission via GDO0.

## See Also

- [I²C Bus](/components/i2c)
- [Remote Receiver](/components/remote_receiver)
- [Remote Transmitter](/components/remote_transmitter)
- [SPI Component](/components/spi)
- [CC1101 Datasheet](https://www.ti.com/lit/ds/symlink/cc1101.pdf)
Binary file added content/components/images/cc1101.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.