2021-03-31 20:52:26 +03:00
|
|
|
#include "cc1101.h"
|
|
|
|
#include <assert.h>
|
|
|
|
#include <string.h>
|
2023-07-12 12:41:46 +03:00
|
|
|
#include <furi_hal_cortex.h>
|
|
|
|
|
|
|
|
static bool cc1101_spi_trx(FuriHalSpiBusHandle* handle, uint8_t* tx, uint8_t* rx, uint8_t size) {
|
|
|
|
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(CC1101_TIMEOUT * 1000);
|
|
|
|
|
|
|
|
while(furi_hal_gpio_read(handle->miso)) {
|
|
|
|
if(furi_hal_cortex_timer_is_expired(timer)) {
|
|
|
|
//timeout
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(!furi_hal_spi_bus_trx(handle, tx, rx, size, CC1101_TIMEOUT)) return false;
|
|
|
|
return true;
|
|
|
|
}
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
CC1101Status cc1101_strobe(FuriHalSpiBusHandle* handle, uint8_t strobe) {
|
2022-01-05 19:10:18 +03:00
|
|
|
uint8_t tx[1] = {strobe};
|
|
|
|
CC1101Status rx[1] = {0};
|
2023-07-12 12:41:46 +03:00
|
|
|
rx[0].CHIP_RDYn = 1;
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
cc1101_spi_trx(handle, tx, (uint8_t*)rx, 1);
|
2021-03-31 20:52:26 +03:00
|
|
|
|
|
|
|
assert(rx[0].CHIP_RDYn == 0);
|
|
|
|
return rx[0];
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
CC1101Status cc1101_write_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t data) {
|
2022-01-05 19:10:18 +03:00
|
|
|
uint8_t tx[2] = {reg, data};
|
|
|
|
CC1101Status rx[2] = {0};
|
2023-07-12 12:41:46 +03:00
|
|
|
rx[0].CHIP_RDYn = 1;
|
|
|
|
rx[1].CHIP_RDYn = 1;
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
cc1101_spi_trx(handle, tx, (uint8_t*)rx, 2);
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2021-12-01 18:44:39 +03:00
|
|
|
assert((rx[0].CHIP_RDYn | rx[1].CHIP_RDYn) == 0);
|
2021-03-31 20:52:26 +03:00
|
|
|
return rx[1];
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
CC1101Status cc1101_read_reg(FuriHalSpiBusHandle* handle, uint8_t reg, uint8_t* data) {
|
2021-03-31 20:52:26 +03:00
|
|
|
assert(sizeof(CC1101Status) == 1);
|
2021-12-01 18:44:39 +03:00
|
|
|
uint8_t tx[2] = {reg | CC1101_READ, 0};
|
|
|
|
CC1101Status rx[2] = {0};
|
2023-07-12 12:41:46 +03:00
|
|
|
rx[0].CHIP_RDYn = 1;
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
cc1101_spi_trx(handle, tx, (uint8_t*)rx, 2);
|
2021-03-31 20:52:26 +03:00
|
|
|
|
|
|
|
assert((rx[0].CHIP_RDYn) == 0);
|
|
|
|
*data = *(uint8_t*)&rx[1];
|
|
|
|
return rx[0];
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
uint8_t cc1101_get_partnumber(FuriHalSpiBusHandle* handle) {
|
2022-01-05 19:10:18 +03:00
|
|
|
uint8_t partnumber = 0;
|
|
|
|
cc1101_read_reg(handle, CC1101_STATUS_PARTNUM | CC1101_BURST, &partnumber);
|
2021-03-31 20:52:26 +03:00
|
|
|
return partnumber;
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
uint8_t cc1101_get_version(FuriHalSpiBusHandle* handle) {
|
2022-01-05 19:10:18 +03:00
|
|
|
uint8_t version = 0;
|
|
|
|
cc1101_read_reg(handle, CC1101_STATUS_VERSION | CC1101_BURST, &version);
|
2021-03-31 20:52:26 +03:00
|
|
|
return version;
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
uint8_t cc1101_get_rssi(FuriHalSpiBusHandle* handle) {
|
2022-01-05 19:10:18 +03:00
|
|
|
uint8_t rssi = 0;
|
|
|
|
cc1101_read_reg(handle, CC1101_STATUS_RSSI | CC1101_BURST, &rssi);
|
2021-03-31 20:52:26 +03:00
|
|
|
return rssi;
|
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
CC1101Status cc1101_reset(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_SRES);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
CC1101Status cc1101_get_status(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_SNOP);
|
2021-06-08 12:51:16 +03:00
|
|
|
}
|
|
|
|
|
2024-01-19 22:39:53 +03:00
|
|
|
bool cc1101_wait_status_state(FuriHalSpiBusHandle* handle, CC1101State state, uint32_t timeout_us) {
|
|
|
|
bool result = false;
|
|
|
|
CC1101Status status = {0};
|
|
|
|
FuriHalCortexTimer timer = furi_hal_cortex_timer_get(timeout_us);
|
|
|
|
while(!furi_hal_cortex_timer_is_expired(timer)) {
|
|
|
|
status = cc1101_strobe(handle, CC1101_STROBE_SNOP);
|
|
|
|
if(status.STATE == state) {
|
|
|
|
result = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
CC1101Status cc1101_shutdown(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_SPWD);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
CC1101Status cc1101_calibrate(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_SCAL);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
CC1101Status cc1101_switch_to_idle(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_SIDLE);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
CC1101Status cc1101_switch_to_rx(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_SRX);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
CC1101Status cc1101_switch_to_tx(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_STX);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
CC1101Status cc1101_flush_rx(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_SFRX);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
CC1101Status cc1101_flush_tx(FuriHalSpiBusHandle* handle) {
|
|
|
|
return cc1101_strobe(handle, CC1101_STROBE_SFTX);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
uint32_t cc1101_set_frequency(FuriHalSpiBusHandle* handle, uint32_t value) {
|
2021-06-30 00:19:20 +03:00
|
|
|
uint64_t real_value = (uint64_t)value * CC1101_FDIV / CC1101_QUARTZ;
|
2021-03-31 20:52:26 +03:00
|
|
|
|
|
|
|
// Sanity check
|
2021-06-30 00:19:20 +03:00
|
|
|
assert((real_value & CC1101_FMASK) == real_value);
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
cc1101_write_reg(handle, CC1101_FREQ2, (real_value >> 16) & 0xFF);
|
2022-01-05 19:10:18 +03:00
|
|
|
cc1101_write_reg(handle, CC1101_FREQ1, (real_value >> 8) & 0xFF);
|
|
|
|
cc1101_write_reg(handle, CC1101_FREQ0, (real_value >> 0) & 0xFF);
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2021-06-30 00:19:20 +03:00
|
|
|
uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_FDIV;
|
2021-03-31 20:52:26 +03:00
|
|
|
|
|
|
|
return (uint32_t)real_frequency;
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
uint32_t cc1101_set_intermediate_frequency(FuriHalSpiBusHandle* handle, uint32_t value) {
|
2021-06-30 00:19:20 +03:00
|
|
|
uint64_t real_value = value * CC1101_IFDIV / CC1101_QUARTZ;
|
2021-03-31 20:52:26 +03:00
|
|
|
assert((real_value & 0xFF) == real_value);
|
|
|
|
|
2022-01-05 19:10:18 +03:00
|
|
|
cc1101_write_reg(handle, CC1101_FSCTRL0, (real_value >> 0) & 0xFF);
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2021-06-30 00:19:20 +03:00
|
|
|
uint64_t real_frequency = real_value * CC1101_QUARTZ / CC1101_IFDIV;
|
2021-03-31 20:52:26 +03:00
|
|
|
|
|
|
|
return (uint32_t)real_frequency;
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
void cc1101_set_pa_table(FuriHalSpiBusHandle* handle, const uint8_t value[8]) {
|
2022-12-26 15:13:30 +03:00
|
|
|
uint8_t tx[9] = {CC1101_PATABLE | CC1101_BURST}; //-V1009
|
2022-01-05 19:10:18 +03:00
|
|
|
CC1101Status rx[9] = {0};
|
2023-07-12 12:41:46 +03:00
|
|
|
rx[0].CHIP_RDYn = 1;
|
|
|
|
rx[8].CHIP_RDYn = 1;
|
2021-03-31 20:52:26 +03:00
|
|
|
|
|
|
|
memcpy(&tx[1], &value[0], 8);
|
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
cc1101_spi_trx(handle, tx, (uint8_t*)rx, sizeof(rx));
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2021-12-01 18:44:39 +03:00
|
|
|
assert((rx[0].CHIP_RDYn | rx[8].CHIP_RDYn) == 0);
|
2021-03-31 20:52:26 +03:00
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
uint8_t cc1101_write_fifo(FuriHalSpiBusHandle* handle, const uint8_t* data, uint8_t size) {
|
2021-06-08 12:51:16 +03:00
|
|
|
uint8_t buff_tx[64];
|
|
|
|
uint8_t buff_rx[64];
|
|
|
|
buff_tx[0] = CC1101_FIFO | CC1101_BURST;
|
|
|
|
memcpy(&buff_tx[1], data, size);
|
2021-03-31 20:52:26 +03:00
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
cc1101_spi_trx(handle, buff_tx, (uint8_t*)buff_rx, size + 1);
|
2021-03-31 20:52:26 +03:00
|
|
|
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2021-11-30 15:09:43 +03:00
|
|
|
uint8_t cc1101_read_fifo(FuriHalSpiBusHandle* handle, uint8_t* data, uint8_t* size) {
|
2023-02-09 08:45:30 +03:00
|
|
|
uint8_t buff_trx[2];
|
|
|
|
buff_trx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST;
|
2021-06-08 12:51:16 +03:00
|
|
|
|
2023-07-12 12:41:46 +03:00
|
|
|
cc1101_spi_trx(handle, buff_trx, buff_trx, 2);
|
2021-12-01 18:44:39 +03:00
|
|
|
|
|
|
|
// Check that the packet is placed in the receive buffer
|
2023-02-09 08:45:30 +03:00
|
|
|
if(buff_trx[1] > 64) {
|
2021-12-01 18:44:39 +03:00
|
|
|
*size = 64;
|
|
|
|
} else {
|
2023-02-09 08:45:30 +03:00
|
|
|
*size = buff_trx[1];
|
2021-12-01 18:44:39 +03:00
|
|
|
}
|
2023-02-09 08:45:30 +03:00
|
|
|
furi_hal_spi_bus_trx(handle, NULL, data, *size, CC1101_TIMEOUT);
|
2021-06-08 12:51:16 +03:00
|
|
|
|
|
|
|
return *size;
|
2024-07-15 20:02:45 +03:00
|
|
|
}
|