Closed Ierlandfan closed 3 years ago
I've been looking at this myself.
I don't think the ESP8266 is a good fit because it only has a single UART which tends to get tied up with the host/programming interface. That was the problem with the original nano platforms that used an atmega328p - the radio interface had to be a software UART for RX which isn't trivial.
The ESP32 might be a better candidate because I think it has a USB interface and 2 UARTS.
I don't think the code changes would be too difficult .
The next release I'm working on is going to drop the Arduino GUI (and custom board definitions) and just use standard make tools. That would probably also make it easier to support a different processor family.
I've been looking at this myself.
I don't think the ESP8266 is a good fit because it only has a single UART which tends to get tied up with the host/programming interface. That was the problem with the original nano platforms that used an atmega328p - the radio interface had to be a software UART for RX which isn't trivial.
Ierlandfan mentioned this repo and this repo is just brilliant work! I have been decoding the itho rf (and i2c) protocol for an add-on in these devices that I made and came a long way but what you created was jsut that last piece of info I was missing. Thanks!
About the UART interface, I'm using the CC1101 in SPI mode, I trigger the GDO2 pin when the sync word is detected (in the CC1101 hardware) and then start reading out the buffer using the SPI interface. This way you do not need to use any of the UARTs on the ESP8266/ESP32 (or any other MCU). I haven't fully updated my code on github yet to RX more than the 64 byte buffer of the CC1101 (at first I didn't needed it for itho devices) but I now have a working solution on my local repo that I can share if your interested.
Edit, a little more info: https://github.com/arjenhiemstra/ithowifi/blob/2135f9fc9a3cc3d93e0fc51439a47a2c7d8f551d/software/NRG_itho_wifi/IthoCC1101.cpp#L198
With this reg setting the GDO2 pin will turn to 1 when the sync word is detected. Use this as the ISR trigger and start reading out the RX buffer in a loop until the buffer is empty (taking into account some CC1101 errata stuff).
I moved to a 32/30 bit sync word based on the raw manchester encoded message stream, this way you can handle this part in CC1101 hardware. The first byte in the CC1101 buffer to parse by the MCU then is the first byte with relevant information (a part of the header byte when decoded) The only difference is that I (mistakenly) started the decoding with the 10 bit pattern that I saw repeating but looking at your code this is actually the start and stop bit. So this sync word would end you up 1 bit to 'early' in de raw data stream.
I tried using the cc1101 RX fifo for RX with the evohome system.
I had to give it up as unworkable because of the fact that some evohome devices would simply not generate RF data that could be captured synchronously. There would be occasional bits that were extended and that meant it was impossible to extract the data bits from the uart start/stop bits (that are included in the RF bitstream)
The latest version of evofw3 does use the TX fifo so GDO0 is not actually used. evofw3 will happily transmit more than64 bytes through the TX fifo.
I had to give it up as unworkable because of the fact that some evohome devices would simply not generate RF data that could be captured synchronously.
So the data in the buffer of the CC1101 is not DC balanced anymore then? That's weird stuff!
I first readout the raw datastream from the CC1101 buffer to a local buffer and then proces the data. I seems to me (but I might be missing the point) that you could just work on that local buffered data to account for the stray bits. The processing is fully async. I just process (manchester decode) the resulting data in the packet->data buffer after the ISR completed.
Not sure if this would work for you, but just my two cents then :) This is my (ugly hacked but it works for now) code to pull data out of the CC1101 buffer:
size_t CC1101::readData(CC1101Packet* packet, size_t maxLen) {
size_t length = maxLen;
uint8_t bytesInFIFO = 0;
while (bytesInFIFO < 2) { //prevent readout of just 1 byte
bytesInFIFO = readRegisterWithSyncProblem(CC1101_RXBYTES, CC1101_READ_BURST) & CC1101_BITS_RX_BYTES_IN_FIFO; //read reg at least twice until same both reg reads have the same result
}
size_t readBytes = 0;
uint32_t lastFIFORead = millis();
// keep reading from FIFO until we get all the packet.
while (readBytes < length) {
if (bytesInFIFO == 0) {
if (millis() - lastFIFORead > 5) {
break;
} else {
//delayMicroseconds(100);
bytesInFIFO = readRegisterWithSyncProblem(CC1101_RXBYTES, CC1101_READ_BURST) & CC1101_BITS_RX_BYTES_IN_FIFO;
continue;
}
}
uint8_t bytesToRead = min((uint8_t)(length - readBytes), bytesInFIFO); // only read from bytesInFIFO if there is buffer length available
if(bytesToRead > 1) { //CC1101 errata: RX FIFO pointer is sometimes not properly updated and the last read byte is duplicated, leave on byte in buffer until only one byte is left
bytesToRead -= 1;
}
readBurstRegister(&(packet->data[readBytes]), CC1101_RXFIFO, bytesToRead);
readBytes += bytesToRead;
packet->length = readBytes;
lastFIFORead = millis();
// Get how many bytes are left in FIFO.
bytesInFIFO = readRegisterWithSyncProblem(CC1101_RXBYTES, CC1101_READ_BURST) & C1101_BITS_RX_BYTES_IN_FIFO;
}
writeCommand(CC1101_SIDLE); //idle
writeCommand(CC1101_SFRX); //flush RX buffer
writeCommand(CC1101_SRX); //switch to RX state
return readBytes;
}`
The problem with using the fifo is it assumes all the bits are exactly the same width. The problems start when there is jitter from the transmitter or does something like extend a STOP bit. That can come out as two bits from the fifo. It just doesn't work.
If you want some better fifo handling code check out the fifo branch of evofw2 (which is where I gave up on using the fifo for RX)
The problem with using the fifo is it assumes all the bits are exactly the same width. The problems start when there is jitter from the transmitter or does something like extend a STOP bit. That can come out as two bits from the fifo. It just doesn't work.
Ok clear!
Hi,
is it possible to use an ESP8266 or an ESP32 with an attached CC1101 instead of the Arduino? It would require a rewrite of the code I guess ( watchdog, io, timing, ISR or others perhaps) but would it be possible?