| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258 |
- #include "subghz_tx_rx_worker.h"
- #include <furi.h>
- #define TAG "SubGhzTxRxWorker"
- #define SUBGHZ_TXRX_WORKER_BUF_SIZE 2048
- //you can not set more than 62 because it will not fit into the FIFO CC1101
- #define SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE 60
- #define SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF 40
- struct SubGhzTxRxWorker {
- FuriThread* thread;
- FuriStreamBuffer* stream_tx;
- FuriStreamBuffer* stream_rx;
- volatile bool worker_running;
- volatile bool worker_stoping;
- SubGhzTxRxWorkerStatus status;
- uint32_t frequency;
- SubGhzTxRxWorkerCallbackHaveRead callback_have_read;
- void* context_have_read;
- };
- bool subghz_tx_rx_worker_write(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
- furi_assert(instance);
- bool ret = false;
- size_t stream_tx_free_byte = furi_stream_buffer_spaces_available(instance->stream_tx);
- if(size && (stream_tx_free_byte >= size)) {
- if(furi_stream_buffer_send(
- instance->stream_tx, data, size, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF) ==
- size) {
- ret = true;
- }
- }
- return ret;
- }
- size_t subghz_tx_rx_worker_available(SubGhzTxRxWorker* instance) {
- furi_assert(instance);
- return furi_stream_buffer_bytes_available(instance->stream_rx);
- }
- size_t subghz_tx_rx_worker_read(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
- furi_assert(instance);
- return furi_stream_buffer_receive(instance->stream_rx, data, size, 0);
- }
- void subghz_tx_rx_worker_set_callback_have_read(
- SubGhzTxRxWorker* instance,
- SubGhzTxRxWorkerCallbackHaveRead callback,
- void* context) {
- furi_assert(instance);
- furi_assert(callback);
- furi_assert(context);
- instance->callback_have_read = callback;
- instance->context_have_read = context;
- }
- bool subghz_tx_rx_worker_rx(SubGhzTxRxWorker* instance, uint8_t* data, uint8_t* size) {
- uint8_t timeout = 100;
- bool ret = false;
- if(instance->status != SubGhzTxRxWorkerStatusRx) {
- furi_hal_subghz_rx();
- instance->status = SubGhzTxRxWorkerStatusRx;
- furi_delay_tick(1);
- }
- //waiting for reception to complete
- while(furi_hal_gpio_read(&gpio_cc1101_g0)) {
- furi_delay_tick(1);
- if(!--timeout) {
- FURI_LOG_W(TAG, "RX cc1101_g0 timeout");
- furi_hal_subghz_flush_rx();
- furi_hal_subghz_rx();
- break;
- }
- }
- if(furi_hal_subghz_rx_pipe_not_empty()) {
- FURI_LOG_I(
- TAG,
- "RSSI: %03.1fdbm LQI: %d",
- (double)furi_hal_subghz_get_rssi(),
- furi_hal_subghz_get_lqi());
- if(furi_hal_subghz_is_rx_data_crc_valid()) {
- furi_hal_subghz_read_packet(data, size);
- ret = true;
- }
- furi_hal_subghz_flush_rx();
- furi_hal_subghz_rx();
- }
- return ret;
- }
- void subghz_tx_rx_worker_tx(SubGhzTxRxWorker* instance, uint8_t* data, size_t size) {
- uint8_t timeout = 200;
- if(instance->status != SubGhzTxRxWorkerStatusIDLE) {
- furi_hal_subghz_idle();
- }
- furi_hal_subghz_write_packet(data, size);
- furi_hal_subghz_tx(); //start send
- instance->status = SubGhzTxRxWorkerStatusTx;
- while(!furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be set -> sync transmitted
- furi_delay_tick(1);
- if(!--timeout) {
- FURI_LOG_W(TAG, "TX !cc1101_g0 timeout");
- break;
- }
- }
- while(furi_hal_gpio_read(&gpio_cc1101_g0)) { // Wait for GDO0 to be cleared -> end of packet
- furi_delay_tick(1);
- if(!--timeout) {
- FURI_LOG_W(TAG, "TX cc1101_g0 timeout");
- break;
- }
- }
- furi_hal_subghz_idle();
- instance->status = SubGhzTxRxWorkerStatusIDLE;
- }
- /** Worker thread
- *
- * @param context
- * @return exit code
- */
- static int32_t subghz_tx_rx_worker_thread(void* context) {
- SubGhzTxRxWorker* instance = context;
- FURI_LOG_I(TAG, "Worker start");
- furi_hal_subghz_reset();
- furi_hal_subghz_idle();
- furi_hal_subghz_load_preset(FuriHalSubGhzPresetGFSK9_99KbAsync);
- //furi_hal_subghz_load_preset(FuriHalSubGhzPresetMSK99_97KbAsync);
- furi_hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow);
- furi_hal_subghz_set_frequency_and_path(instance->frequency);
- furi_hal_subghz_flush_rx();
- uint8_t data[SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE + 1] = {0};
- size_t size_tx = 0;
- uint8_t size_rx[1] = {0};
- uint8_t timeout_tx = 0;
- bool callback_rx = false;
- while(instance->worker_running) {
- //transmit
- size_tx = furi_stream_buffer_bytes_available(instance->stream_tx);
- if(size_tx > 0 && !timeout_tx) {
- timeout_tx = 10; //20ms
- if(size_tx > SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE) {
- furi_stream_buffer_receive(
- instance->stream_tx,
- &data,
- SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE,
- SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF);
- subghz_tx_rx_worker_tx(instance, data, SUBGHZ_TXRX_WORKER_MAX_TXRX_SIZE);
- } else {
- //todo checking that he managed to write all the data to the TX buffer
- furi_stream_buffer_receive(
- instance->stream_tx, &data, size_tx, SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF);
- subghz_tx_rx_worker_tx(instance, data, size_tx);
- }
- } else {
- //recive
- if(subghz_tx_rx_worker_rx(instance, data, size_rx)) {
- if(furi_stream_buffer_spaces_available(instance->stream_rx) >= size_rx[0]) {
- if(instance->callback_have_read &&
- furi_stream_buffer_bytes_available(instance->stream_rx) == 0) {
- callback_rx = true;
- }
- //todo checking that he managed to write all the data to the RX buffer
- furi_stream_buffer_send(
- instance->stream_rx,
- &data,
- size_rx[0],
- SUBGHZ_TXRX_WORKER_TIMEOUT_READ_WRITE_BUF);
- if(callback_rx) {
- instance->callback_have_read(instance->context_have_read);
- callback_rx = false;
- }
- } else {
- //todo RX buffer overflow
- }
- }
- }
- if(timeout_tx) timeout_tx--;
- furi_delay_tick(1);
- }
- furi_hal_subghz_set_path(FuriHalSubGhzPathIsolate);
- furi_hal_subghz_sleep();
- FURI_LOG_I(TAG, "Worker stop");
- return 0;
- }
- SubGhzTxRxWorker* subghz_tx_rx_worker_alloc() {
- SubGhzTxRxWorker* instance = malloc(sizeof(SubGhzTxRxWorker));
- instance->thread =
- furi_thread_alloc_ex("SubGhzTxRxWorker", 2048, subghz_tx_rx_worker_thread, instance);
- instance->stream_tx =
- furi_stream_buffer_alloc(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t));
- instance->stream_rx =
- furi_stream_buffer_alloc(sizeof(uint8_t) * SUBGHZ_TXRX_WORKER_BUF_SIZE, sizeof(uint8_t));
- instance->status = SubGhzTxRxWorkerStatusIDLE;
- instance->worker_stoping = true;
- return instance;
- }
- void subghz_tx_rx_worker_free(SubGhzTxRxWorker* instance) {
- furi_assert(instance);
- furi_assert(!instance->worker_running);
- furi_stream_buffer_free(instance->stream_tx);
- furi_stream_buffer_free(instance->stream_rx);
- furi_thread_free(instance->thread);
- free(instance);
- }
- bool subghz_tx_rx_worker_start(SubGhzTxRxWorker* instance, uint32_t frequency) {
- furi_assert(instance);
- furi_assert(!instance->worker_running);
- bool res = false;
- furi_stream_buffer_reset(instance->stream_tx);
- furi_stream_buffer_reset(instance->stream_rx);
- instance->worker_running = true;
- if(furi_hal_region_is_frequency_allowed(frequency)) {
- instance->frequency = frequency;
- res = true;
- }
- furi_thread_start(instance->thread);
- return res;
- }
- void subghz_tx_rx_worker_stop(SubGhzTxRxWorker* instance) {
- furi_assert(instance);
- furi_assert(instance->worker_running);
- instance->worker_running = false;
- furi_thread_join(instance->thread);
- }
- bool subghz_tx_rx_worker_is_running(SubGhzTxRxWorker* instance) {
- furi_assert(instance);
- return instance->worker_running;
- }
|