diff --git a/applications/subghz/subghz_cli.c b/applications/subghz/subghz_cli.c old mode 100644 new mode 100755 index 61bbcdea..419da1b6 --- a/applications/subghz/subghz_cli.c +++ b/applications/subghz/subghz_cli.c @@ -2,6 +2,13 @@ #include #include +static const uint8_t subghz_test_packet_data[] = { + 0x30, // 48bytes to transmit + 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, + 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, +}; + void subghz_cli_init() { Cli* cli = furi_record_open("cli"); @@ -32,9 +39,9 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { frequency = api_hal_subghz_set_frequency(frequency); printf("Transmitting at frequency %lu Hz\r\n", frequency); printf("Press CTRL+C to stop\r\n"); - if(frequency < 400) { + if(frequency < 400000000) { api_hal_subghz_set_path(ApiHalSubGhzPath315); - } else if(frequency < 500) { + } else if(frequency < 500000000) { api_hal_subghz_set_path(ApiHalSubGhzPath433); } else { api_hal_subghz_set_path(ApiHalSubGhzPath868); @@ -73,9 +80,9 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { frequency = api_hal_subghz_set_frequency(frequency); printf("Receiving at frequency %lu Hz\r\n", frequency); printf("Press CTRL+C to stop\r\n"); - if(frequency < 400) { + if(frequency < 400000000) { api_hal_subghz_set_path(ApiHalSubGhzPath315); - } else if(frequency < 500) { + } else if(frequency < 500000000) { api_hal_subghz_set_path(ApiHalSubGhzPath433); } else { api_hal_subghz_set_path(ApiHalSubGhzPath868); @@ -96,9 +103,116 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { } void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) { - printf("Not implemented\r\n"); + uint32_t frequency; + uint32_t pattern; + uint32_t count; + + int ret = sscanf(string_get_cstr(args), "%lu %lu %lu", &frequency, &pattern, &count); + if(ret != 3) { + printf( + "sscanf returned %d, frequency: %lu; pattern: %lu; count: %lu\r\n", + ret, + frequency, + pattern, + count); + cli_print_usage( + "subghz_tx_pt", " ", string_get_cstr(args)); + return; + } + + if(frequency < 300000000 || frequency > 925000000) { + printf("Frequency must be in 300000000...925000000 range, not %lu\r\n", frequency); + return; + } + if(pattern > 1) { + printf("Pattern must be 1, not %lu\r\n", pattern); + } + + api_hal_subghz_reset(); + api_hal_subghz_idle(); + + api_hal_subghz_load_preset(ApiHalSubGhzPreset2FskPacket); + + frequency = api_hal_subghz_set_frequency(frequency); + if(frequency < 400000000) { + api_hal_subghz_set_path(ApiHalSubGhzPath315); + } else if(frequency < 500000000) { + api_hal_subghz_set_path(ApiHalSubGhzPath433); + } else { + api_hal_subghz_set_path(ApiHalSubGhzPath868); + } + hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + + uint8_t status = api_hal_subghz_get_status(); + FURI_LOG_D("SUBGHZ CLI", "Status: %02X", status); + + while(!cli_cmd_interrupt_received(cli) && count) { + api_hal_subghz_idle(); + api_hal_subghz_write_packet(subghz_test_packet_data, sizeof(subghz_test_packet_data)); + api_hal_subghz_tx(); + while(!hal_gpio_read(&gpio_cc1101_g0)) + ; // Wait for sync + while(hal_gpio_read(&gpio_cc1101_g0)) + ; // Wait end of transaction + count--; + } + + api_hal_subghz_reset(); + api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); + hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context) { - printf("Not implemented\r\n"); + uint32_t frequency; + + int ret = sscanf(string_get_cstr(args), "%lu", &frequency); + if(ret != 1) { + printf("sscanf returned %d, frequency: %lu\r\n", ret, frequency); + cli_print_usage("subghz_rx_pt", "", string_get_cstr(args)); + return; + } + + if(frequency < 300000000 || frequency > 925000000) { + printf("Frequency must be in 300000000...925000000 range, not %lu\r\n", frequency); + return; + } + + api_hal_subghz_reset(); + api_hal_subghz_idle(); + api_hal_subghz_load_preset(ApiHalSubGhzPreset2FskPacket); + + frequency = api_hal_subghz_set_frequency(frequency); + if(frequency < 400000000) { + api_hal_subghz_set_path(ApiHalSubGhzPath315); + } else if(frequency < 500000000) { + api_hal_subghz_set_path(ApiHalSubGhzPath433); + } else { + api_hal_subghz_set_path(ApiHalSubGhzPath868); + } + hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); + + uint8_t status = api_hal_subghz_get_status(); + FURI_LOG_D("SUBGHZ CLI", "Status: %02X", status); + printf("Start receiving packets. Press CTRL+C to stop\r\n"); + + api_hal_subghz_flush_rx(); + api_hal_subghz_rx(); + uint32_t packet_cnt = 0; + + while(!cli_cmd_interrupt_received(cli)) { + if(hal_gpio_read(&gpio_cc1101_g0)) { + while(hal_gpio_read(&gpio_cc1101_g0)) + ; // Wait reception + packet_cnt++; + api_hal_subghz_idle(); + api_hal_subghz_flush_rx(); + api_hal_subghz_rx(); + } + } + + printf("Received %lu packets", packet_cnt); + + api_hal_subghz_reset(); + api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); + hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); } diff --git a/firmware/targets/api-hal-include/api-hal-subghz.h b/firmware/targets/api-hal-include/api-hal-subghz.h index 73cf68bc..6b5af436 100644 --- a/firmware/targets/api-hal-include/api-hal-subghz.h +++ b/firmware/targets/api-hal-include/api-hal-subghz.h @@ -35,6 +35,9 @@ void api_hal_subghz_dump_state(); */ void api_hal_subghz_load_preset(ApiHalSubGhzPreset preset); +/** Get status */ +uint8_t api_hal_subghz_get_status(); + /** Load registers * @param register-value pairs array, terminated with {0,0} */ @@ -55,7 +58,11 @@ void api_hal_subghz_write_packet(const uint8_t* data, uint8_t size); * @param data, pointer * @param size, size */ -void api_hal_subghz_read_packet(uint8_t* data, uint8_t size); + +void api_hal_subghz_read_packet(uint8_t* data, uint8_t* size); + +/** Flush rx FIFO buffer */ +void api_hal_subghz_flush_rx(); /** Shutdown * Issue spwd command diff --git a/firmware/targets/f5/api-hal/api-hal-subghz.c b/firmware/targets/f5/api-hal/api-hal-subghz.c index 5161c689..7bbc5917 100644 --- a/firmware/targets/f5/api-hal/api-hal-subghz.c +++ b/firmware/targets/f5/api-hal/api-hal-subghz.c @@ -29,6 +29,11 @@ static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = { { CC1101_IOCFG0, 0x06 }, // GD0 as async serial data output/input { CC1101_FSCTRL1, 0x06 }, // Set IF 26m/2^10*2=2.2MHz { CC1101_MCSM0, 0x18 }, // Autocalibrate on idle to TRX, ~150us OSC guard time + + { CC1101_TEST2, 0x81}, + { CC1101_TEST1, 0x35}, + { CC1101_TEST0, 0x09}, + /* End */ { 0, 0 }, }; @@ -80,6 +85,14 @@ void api_hal_subghz_load_preset(ApiHalSubGhzPreset preset) { } } +uint8_t api_hal_subghz_get_status() { + const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); + CC1101StatusRaw st; + st.status = cc1101_get_status(device); + api_hal_spi_device_return(device); + return st.status_raw; +} + void api_hal_subghz_load_registers(const uint8_t data[][2]) { const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); cc1101_reset(device); @@ -104,8 +117,16 @@ void api_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { api_hal_spi_device_return(device); } -void api_hal_subghz_read_packet(uint8_t* data, uint8_t size) { +void api_hal_subghz_flush_rx() { + const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); + cc1101_flush_rx(device); + api_hal_spi_device_return(device); +} +void api_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { + const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); + cc1101_read_fifo(device, data, size); + api_hal_spi_device_return(device); } void api_hal_subghz_shutdown() { diff --git a/firmware/targets/f6/api-hal/api-hal-subghz.c b/firmware/targets/f6/api-hal/api-hal-subghz.c index 57865dd8..25be8be2 100644 --- a/firmware/targets/f6/api-hal/api-hal-subghz.c +++ b/firmware/targets/f6/api-hal/api-hal-subghz.c @@ -29,6 +29,11 @@ static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = { { CC1101_IOCFG0, 0x06 }, // GD0 as async serial data output/input { CC1101_FSCTRL1, 0x06 }, // Set IF 26m/2^10*2=2.2MHz { CC1101_MCSM0, 0x18 }, // Autocalibrate on idle to TRX, ~150us OSC guard time + + { CC1101_TEST2, 0x81}, + { CC1101_TEST1, 0x35}, + { CC1101_TEST0, 0x09}, + /* End */ { 0, 0 }, }; @@ -80,6 +85,14 @@ void api_hal_subghz_load_preset(ApiHalSubGhzPreset preset) { } } +uint8_t api_hal_subghz_get_status() { + const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); + CC1101StatusRaw st; + st.status = cc1101_get_status(device); + api_hal_spi_device_return(device); + return st.status_raw; +} + void api_hal_subghz_load_registers(const uint8_t data[][2]) { const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); cc1101_reset(device); @@ -104,8 +117,16 @@ void api_hal_subghz_write_packet(const uint8_t* data, uint8_t size) { api_hal_spi_device_return(device); } -void api_hal_subghz_read_packet(uint8_t* data, uint8_t size) { +void api_hal_subghz_flush_rx() { + const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); + cc1101_flush_rx(device); + api_hal_spi_device_return(device); +} +void api_hal_subghz_read_packet(uint8_t* data, uint8_t* size) { + const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); + cc1101_read_fifo(device, data, size); + api_hal_spi_device_return(device); } void api_hal_subghz_shutdown() { @@ -135,6 +156,7 @@ void api_hal_subghz_rx() { void api_hal_subghz_tx() { const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); + cc1101_switch_to_idle(device); cc1101_switch_to_tx(device); api_hal_spi_device_return(device); } diff --git a/lib/drivers/cc1101.c b/lib/drivers/cc1101.c index d104ca7e..d8c4dc40 100644 --- a/lib/drivers/cc1101.c +++ b/lib/drivers/cc1101.c @@ -71,6 +71,10 @@ void cc1101_reset(const ApiHalSpiDevice* device) { cc1101_strobe(device, CC1101_STROBE_SRES); } +CC1101Status cc1101_get_status(const ApiHalSpiDevice* device) { + return cc1101_strobe(device, CC1101_STROBE_SNOP); +} + void cc1101_shutdown(const ApiHalSpiDevice* device) { cc1101_strobe(device, CC1101_STROBE_SPWD); } @@ -148,24 +152,40 @@ void cc1101_set_pa_table(const ApiHalSpiDevice* device, const uint8_t value[8]) } uint8_t cc1101_write_fifo(const ApiHalSpiDevice* device, const uint8_t* data, uint8_t size) { - uint8_t tx = CC1101_FIFO | CC1101_BURST; - CC1101Status rx = { 0 }; + uint8_t buff_tx[64]; + uint8_t buff_rx[64]; + buff_tx[0] = CC1101_FIFO | CC1101_BURST; + memcpy(&buff_tx[1], data, size); // Start transaction hal_gpio_write(device->chip_select, false); // Wait IC to become ready while(hal_gpio_read(device->bus->miso)); // Tell IC what we want - api_hal_spi_bus_trx(device->bus, &tx, (uint8_t*)&rx, 1, CC1101_TIMEOUT); - assert((rx.CHIP_RDYn) == 0); - // Transmit data - api_hal_spi_bus_tx(device->bus, (uint8_t*)data, size, CC1101_TIMEOUT); + api_hal_spi_bus_trx(device->bus, buff_tx, (uint8_t*) buff_rx, size + 1, CC1101_TIMEOUT); + // Finish transaction hal_gpio_write(device->chip_select, true); return size; } -uint8_t cc1101_read_fifo(const ApiHalSpiDevice* device, uint8_t* data, uint8_t size) { - return size; +uint8_t cc1101_read_fifo(const ApiHalSpiDevice* device, uint8_t* data, uint8_t* size) { + uint8_t buff_tx[64]; + buff_tx[0] = CC1101_FIFO | CC1101_READ | CC1101_BURST; + uint8_t buff_rx[2]; + + // Start transaction + hal_gpio_write(device->chip_select, false); + // Wait IC to become ready + while(hal_gpio_read(device->bus->miso)); + + // First byte - packet length + api_hal_spi_bus_trx(device->bus, buff_tx, buff_rx, 2, CC1101_TIMEOUT); + *size = buff_rx[2]; + api_hal_spi_bus_trx(device->bus, &buff_tx[1], data, *size, CC1101_TIMEOUT); + cc1101_flush_rx(device); + + hal_gpio_write(device->chip_select, true); + return *size; } diff --git a/lib/drivers/cc1101.h b/lib/drivers/cc1101.h index 567faa83..a7379f5f 100644 --- a/lib/drivers/cc1101.h +++ b/lib/drivers/cc1101.h @@ -42,6 +42,11 @@ CC1101Status cc1101_read_reg(const ApiHalSpiDevice* device, uint8_t reg, uint8_t */ void cc1101_reset(const ApiHalSpiDevice* device); +/** Get status + * @param device - pointer to ApiHalSpiDevice + */ +CC1101Status cc1101_get_status(const ApiHalSpiDevice* device); + /** Enable shutdown mode * @param device - pointer to ApiHalSpiDevice */ @@ -146,7 +151,7 @@ uint8_t cc1101_write_fifo(const ApiHalSpiDevice* device, const uint8_t* data, ui * @param size, bytes to read from fifo * @return size, read bytes count */ -uint8_t cc1101_read_fifo(const ApiHalSpiDevice* device, uint8_t* data, uint8_t size); +uint8_t cc1101_read_fifo(const ApiHalSpiDevice* device, uint8_t* data, uint8_t* size); #ifdef __cplusplus } diff --git a/lib/drivers/cc1101_regs.h b/lib/drivers/cc1101_regs.h index f8e3d920..c3c8366e 100644 --- a/lib/drivers/cc1101_regs.h +++ b/lib/drivers/cc1101_regs.h @@ -173,6 +173,12 @@ typedef struct { bool CHIP_RDYn:1; } CC1101Status; +typedef union { + CC1101Status status; + uint8_t status_raw; +} CC1101StatusRaw; + + typedef struct { uint8_t NUM_TXBYTES:7; bool TXFIFO_UNDERFLOW:1;