[FL-1528] SubGhz: dma send (#579)
* Gui: input injection in screen stream * Cli: expose ASCII table in public header * SubGhz: dma output draft * SubGhz: output initialization cleanup * SubGhz: update dma send routine, add subghz_tx cli command. * SubGhz: proper register address for DMA * SubGhz: proper, fully working dma+tim2 configuration * SubGhz: transmit PT with cli. * Drivers: fix invalid size in CC1101 PA_TABLE loading routine. * Interrupts: configurable DMA isrs. * F5: backport fixes. * SubGhz: free buffer after use * SubGhz: use sleep instead of reset at the end * SubGhz: async tx repeat with circular DMA * SubGhz: disable dma channel on complete, adjust PT send timings * SubGhz: backport function singature change to F5 * SubGhz: add tx debug gpio
This commit is contained in:
		
							parent
							
								
									5df346aebe
								
							
						
					
					
						commit
						851a44dc59
					
				| @ -66,9 +66,8 @@ void subghz_cli_command_tx_carrier(Cli* cli, string_t args, void* context) { | |||||||
|         osDelay(250); |         osDelay(250); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     api_hal_subghz_reset(); |  | ||||||
|     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); |     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     api_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | ||||||
| @ -92,8 +91,6 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | |||||||
|     printf("Receiving at frequency %lu Hz\r\n", frequency); |     printf("Receiving at frequency %lu Hz\r\n", frequency); | ||||||
|     printf("Press CTRL+C to stop\r\n"); |     printf("Press CTRL+C to stop\r\n"); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
| 
 |  | ||||||
|     api_hal_subghz_rx(); |     api_hal_subghz_rx(); | ||||||
| 
 | 
 | ||||||
|     while(!cli_cmd_interrupt_received(cli)) { |     while(!cli_cmd_interrupt_received(cli)) { | ||||||
| @ -102,8 +99,8 @@ void subghz_cli_command_rx_carrier(Cli* cli, string_t args, void* context) { | |||||||
|         fflush(stdout); |         fflush(stdout); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     api_hal_subghz_reset(); |  | ||||||
|     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); |     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); | ||||||
|  |     api_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) { | void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) { | ||||||
| @ -148,16 +145,13 @@ void subghz_cli_command_tx_pt(Cli* cli, string_t args, void* context) { | |||||||
|         api_hal_subghz_idle(); |         api_hal_subghz_idle(); | ||||||
|         api_hal_subghz_write_packet(subghz_test_packet_data, sizeof(subghz_test_packet_data)); |         api_hal_subghz_write_packet(subghz_test_packet_data, sizeof(subghz_test_packet_data)); | ||||||
|         api_hal_subghz_tx(); |         api_hal_subghz_tx(); | ||||||
|         while(!hal_gpio_read(&gpio_cc1101_g0)) |         while(!hal_gpio_read(&gpio_cc1101_g0)) osDelay(1); // Wait for sync
 | ||||||
|             ; // Wait for sync
 |         while(hal_gpio_read(&gpio_cc1101_g0)) osDelay(1); // Wait end of transaction
 | ||||||
|         while(hal_gpio_read(&gpio_cc1101_g0)) |  | ||||||
|             ; // Wait end of transaction
 |  | ||||||
|         count--; |         count--; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     api_hal_subghz_reset(); |     api_hal_subghz_sleep(); | ||||||
|     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); |     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) { | void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context) { | ||||||
| @ -204,12 +198,73 @@ void subghz_cli_command_rx_pt(Cli* cli, string_t args, void* context) { | |||||||
| 
 | 
 | ||||||
|     printf("Received %lu packets", packet_cnt); |     printf("Received %lu packets", packet_cnt); | ||||||
| 
 | 
 | ||||||
|     api_hal_subghz_reset(); |     api_hal_subghz_sleep(); | ||||||
|     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); |     api_hal_subghz_set_path(ApiHalSubGhzPathIsolate); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #define SUBGHZ_PT_SHORT 260 | ||||||
|  | #define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3) | ||||||
|  | #define SUBGHZ_PT_GUARD 8060 | ||||||
|  | 
 | ||||||
| void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | void subghz_cli_command_tx(Cli* cli, string_t args, void* context) { | ||||||
|  |     uint32_t frequency = 433920000; | ||||||
|  |     size_t repeat = 10; | ||||||
|  |     uint32_t key = 0x0074BADE; | ||||||
|  | 
 | ||||||
|  |     if(string_size(args)) { | ||||||
|  |         int ret = sscanf(string_get_cstr(args), "%lx %lu %u", &key, &frequency, &repeat); | ||||||
|  |         if(ret != 3) { | ||||||
|  |             printf( | ||||||
|  |                 "sscanf returned %d, key: %lx, frequency: %lu, repeat: %u\r\n", | ||||||
|  |                 ret, | ||||||
|  |                 key, | ||||||
|  |                 frequency, | ||||||
|  |                 repeat); | ||||||
|  |             cli_print_usage( | ||||||
|  |                 "subghz_rx", | ||||||
|  |                 "<3 Byte Key in hex> <Frequency in HZ> <Repeat count>", | ||||||
|  |                 string_get_cstr(args)); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if(!subghz_check_frequency_range(frequency)) { | ||||||
|  |             printf( | ||||||
|  |                 "Frequency must be in " CC1101_FREQUENCY_RANGE_STR " range, not %lu\r\n", | ||||||
|  |                 frequency); | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     size_t subghz_test_data_size = 25 * 2 * sizeof(uint32_t); | ||||||
|  |     uint32_t* subghz_test_data = furi_alloc(subghz_test_data_size); | ||||||
|  | 
 | ||||||
|  |     size_t pos = 0; | ||||||
|  |     for(uint8_t i = 0; i < 24; i++) { | ||||||
|  |         uint8_t byte = i / 8; | ||||||
|  |         uint8_t bit = i % 8; | ||||||
|  |         bool value = (((uint8_t*)&key)[2 - byte] >> (7 - bit)) & 1; | ||||||
|  |         if(value) { | ||||||
|  |             subghz_test_data[pos++] = SUBGHZ_PT_SHORT; | ||||||
|  |             subghz_test_data[pos++] = SUBGHZ_PT_LONG; | ||||||
|  |         } else { | ||||||
|  |             subghz_test_data[pos++] = SUBGHZ_PT_LONG; | ||||||
|  |             subghz_test_data[pos++] = SUBGHZ_PT_SHORT; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     subghz_test_data[pos++] = SUBGHZ_PT_SHORT; | ||||||
|  |     subghz_test_data[pos++] = SUBGHZ_PT_SHORT + SUBGHZ_PT_GUARD; | ||||||
|  | 
 | ||||||
|  |     api_hal_subghz_reset(); | ||||||
|  |     api_hal_subghz_load_preset(ApiHalSubGhzPresetMP); | ||||||
|  |     frequency = api_hal_subghz_set_frequency_and_path(frequency); | ||||||
|  | 
 | ||||||
|  |     api_hal_subghz_start_async_tx(subghz_test_data, subghz_test_data_size, repeat); | ||||||
|  |     api_hal_subghz_wait_async_tx(); | ||||||
|  |     api_hal_subghz_stop_async_tx(); | ||||||
|  | 
 | ||||||
|  |     free(subghz_test_data); | ||||||
|  |     api_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #include <fl_subghz/protocols/subghz_protocol.h> | #include <fl_subghz/protocols/subghz_protocol.h> | ||||||
| @ -248,25 +303,20 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     api_hal_subghz_reset(); |     api_hal_subghz_reset(); | ||||||
|     api_hal_subghz_idle(); |  | ||||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetMP); |     api_hal_subghz_load_preset(ApiHalSubGhzPresetMP); | ||||||
|  |     frequency = api_hal_subghz_set_frequency_and_path(frequency); | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     SubGhzProtocol* protocol = subghz_protocol_alloc(); |     SubGhzProtocol* protocol = subghz_protocol_alloc(); | ||||||
|     subghz_protocol_load_keeloq_file(protocol, "/assets/subghz/keeloq_mfcodes"); |     subghz_protocol_load_keeloq_file(protocol, "/assets/subghz/keeloq_mfcodes"); | ||||||
|     subghz_protocol_load_nice_flor_s_file(protocol, "/assets/subghz/nice_floor_s_rx"); |     subghz_protocol_load_nice_flor_s_file(protocol, "/assets/subghz/nice_floor_s_rx"); | ||||||
|     subghz_protocol_enable_dump_text(protocol, NULL, NULL); |     subghz_protocol_enable_dump_text(protocol, NULL, NULL); | ||||||
| 
 | 
 | ||||||
|     frequency = api_hal_subghz_set_frequency_and_path(frequency); |  | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |  | ||||||
| 
 |  | ||||||
|     StreamBufferHandle_t rx_stream = |     StreamBufferHandle_t rx_stream = | ||||||
|         xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration)); |         xStreamBufferCreate(sizeof(LevelDuration) * 1024, sizeof(LevelDuration)); | ||||||
| 
 | 
 | ||||||
|     api_hal_subghz_set_capture_callback(subghz_cli_command_rx_callback, rx_stream); |     api_hal_subghz_set_async_rx_callback(subghz_cli_command_rx_callback, rx_stream); | ||||||
|     api_hal_subghz_enable_capture(); |     api_hal_subghz_start_async_rx(); | ||||||
| 
 |  | ||||||
|     api_hal_subghz_flush_rx(); |  | ||||||
|     api_hal_subghz_rx(); |  | ||||||
| 
 | 
 | ||||||
|     printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency); |     printf("Listening at %lu. Press CTRL+C to stop\r\n", frequency); | ||||||
|     LevelDuration level_duration; |     LevelDuration level_duration; | ||||||
| @ -284,8 +334,8 @@ void subghz_cli_command_rx(Cli* cli, string_t args, void* context) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     api_hal_subghz_stop_async_rx(); | ||||||
|  |     api_hal_subghz_sleep(); | ||||||
|     subghz_protocol_free(protocol); |     subghz_protocol_free(protocol); | ||||||
|     vStreamBufferDelete(rx_stream); |     vStreamBufferDelete(rx_stream); | ||||||
|     api_hal_subghz_disable_capture(); |  | ||||||
|     api_hal_subghz_init(); |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -156,8 +156,8 @@ void subghz_capture_enter(void* context) { | |||||||
| 
 | 
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| 
 | 
 | ||||||
|     api_hal_subghz_set_capture_callback(subghz_worker_rx_callback, subghz_capture->worker); |     api_hal_subghz_set_async_rx_callback(subghz_worker_rx_callback, subghz_capture->worker); | ||||||
|     api_hal_subghz_enable_capture(); |     api_hal_subghz_start_async_rx(); | ||||||
| 
 | 
 | ||||||
|     subghz_worker_start(subghz_capture->worker); |     subghz_worker_start(subghz_capture->worker); | ||||||
| 
 | 
 | ||||||
| @ -171,8 +171,8 @@ void subghz_capture_exit(void* context) { | |||||||
| 
 | 
 | ||||||
|     subghz_worker_stop(subghz_capture->worker); |     subghz_worker_stop(subghz_capture->worker); | ||||||
| 
 | 
 | ||||||
|     api_hal_subghz_disable_capture(); |     api_hal_subghz_stop_async_rx(); | ||||||
|     api_hal_subghz_init(); |     api_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t subghz_capture_back(void* context) { | uint32_t subghz_capture_back(void* context) { | ||||||
|  | |||||||
| @ -100,15 +100,15 @@ bool subghz_static_input(InputEvent* event, void* context) { | |||||||
|                             uint8_t bit = i % 8; |                             uint8_t bit = i % 8; | ||||||
|                             bool value = (key[byte] >> (7 - bit)) & 1; |                             bool value = (key[byte] >> (7 - bit)) & 1; | ||||||
|                             // Payload send
 |                             // Payload send
 | ||||||
|                             hal_gpio_write(&gpio_cc1101_g0, false); |  | ||||||
|                             delay_us(value ? SUBGHZ_PT_ONE : SUBGHZ_PT_ZERO); |  | ||||||
|                             hal_gpio_write(&gpio_cc1101_g0, true); |                             hal_gpio_write(&gpio_cc1101_g0, true); | ||||||
|  |                             delay_us(value ? SUBGHZ_PT_ONE : SUBGHZ_PT_ZERO); | ||||||
|  |                             hal_gpio_write(&gpio_cc1101_g0, false); | ||||||
|                             delay_us(value ? SUBGHZ_PT_ZERO : SUBGHZ_PT_ONE); |                             delay_us(value ? SUBGHZ_PT_ZERO : SUBGHZ_PT_ONE); | ||||||
|                         } |                         } | ||||||
|                         // Last bit
 |                         // Last bit
 | ||||||
|                         hal_gpio_write(&gpio_cc1101_g0, false); |  | ||||||
|                         delay_us(SUBGHZ_PT_ONE); |  | ||||||
|                         hal_gpio_write(&gpio_cc1101_g0, true); |                         hal_gpio_write(&gpio_cc1101_g0, true); | ||||||
|  |                         delay_us(SUBGHZ_PT_ONE); | ||||||
|  |                         hal_gpio_write(&gpio_cc1101_g0, false); | ||||||
|                         // Guard time
 |                         // Guard time
 | ||||||
|                         delay_us(10600); |                         delay_us(10600); | ||||||
|                     } |                     } | ||||||
| @ -132,7 +132,7 @@ void subghz_static_enter(void* context) { | |||||||
|     api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync); |     api_hal_subghz_load_preset(ApiHalSubGhzPresetOokAsync); | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     hal_gpio_write(&gpio_cc1101_g0, true); |     hal_gpio_write(&gpio_cc1101_g0, false); | ||||||
| 
 | 
 | ||||||
|     with_view_model( |     with_view_model( | ||||||
|         subghz_static->view, (SubghzStaticModel * model) { |         subghz_static->view, (SubghzStaticModel * model) { | ||||||
| @ -151,7 +151,7 @@ void subghz_static_exit(void* context) { | |||||||
|     // SubghzStatic* subghz_static = context;
 |     // SubghzStatic* subghz_static = context;
 | ||||||
| 
 | 
 | ||||||
|     // Reinitialize IC to default state
 |     // Reinitialize IC to default state
 | ||||||
|     api_hal_subghz_init(); |     api_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t subghz_static_back(void* context) { | uint32_t subghz_static_back(void* context) { | ||||||
|  | |||||||
| @ -108,7 +108,7 @@ bool subghz_test_basic_input(InputEvent* event, void* context) { | |||||||
|                 osTimerStart(subghz_test_basic->timer, 1024 / 4); |                 osTimerStart(subghz_test_basic->timer, 1024 / 4); | ||||||
|             } else { |             } else { | ||||||
|                 hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |                 hal_gpio_init(&gpio_cc1101_g0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|                 hal_gpio_write(&gpio_cc1101_g0, false); |                 hal_gpio_write(&gpio_cc1101_g0, true); | ||||||
|                 api_hal_subghz_tx(); |                 api_hal_subghz_tx(); | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
| @ -150,7 +150,7 @@ void subghz_test_basic_exit(void* context) { | |||||||
|     osTimerStop(subghz_test_basic->timer); |     osTimerStop(subghz_test_basic->timer); | ||||||
| 
 | 
 | ||||||
|     // Reinitialize IC to default state
 |     // Reinitialize IC to default state
 | ||||||
|     api_hal_subghz_init(); |     api_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_test_basic_rssi_timer_callback(void* context) { | void subghz_test_basic_rssi_timer_callback(void* context) { | ||||||
|  | |||||||
| @ -157,7 +157,7 @@ void subghz_test_packet_exit(void* context) { | |||||||
|     osTimerStop(subghz_test_packet->timer); |     osTimerStop(subghz_test_packet->timer); | ||||||
| 
 | 
 | ||||||
|     // Reinitialize IC to default state
 |     // Reinitialize IC to default state
 | ||||||
|     api_hal_subghz_init(); |     api_hal_subghz_sleep(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void subghz_test_packet_rssi_timer_callback(void* context) { | void subghz_test_packet_rssi_timer_callback(void* context) { | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| 
 | 
 | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
|  | #include <stddef.h> | ||||||
| #include <toolbox/level_duration.h> | #include <toolbox/level_duration.h> | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| @ -23,12 +24,28 @@ typedef enum { | |||||||
|     ApiHalSubGhzPath868,            /** Center Frquency: 868MHz. Path 3: SW1RF3-SW2RF3, LCLC */ |     ApiHalSubGhzPath868,            /** Center Frquency: 868MHz. Path 3: SW1RF3-SW2RF3, LCLC */ | ||||||
| } ApiHalSubGhzPath; | } ApiHalSubGhzPath; | ||||||
| 
 | 
 | ||||||
|  | /** SubGhz state */ | ||||||
|  | typedef enum { | ||||||
|  |     SubGhzStateInit,        /** Init pending */ | ||||||
|  | 
 | ||||||
|  |     SubGhzStateIdle,        /** Idle, energy save mode */ | ||||||
|  | 
 | ||||||
|  |     SubGhzStateAsyncRx,   /** Async RX started */ | ||||||
|  | 
 | ||||||
|  |     SubGhzStateAsyncTx,   /** Async TX started, DMA and timer is on */ | ||||||
|  |     SubGhzStateAsyncTxLast, /** Async TX continue, DMA completed and timer got last value to go */ | ||||||
|  |     SubGhzStateAsyncTxEnd,  /** Async TX complete, cleanup needed */ | ||||||
|  | } SubGhzState; | ||||||
|  | 
 | ||||||
| /** Initialize and switch to power save mode
 | /** Initialize and switch to power save mode
 | ||||||
|  * Used by internal API-HAL initalization routine |  * Used by internal API-HAL initalization routine | ||||||
|  * Can be used to reinitialize device to safe state and send it to sleep |  * Can be used to reinitialize device to safe state and send it to sleep | ||||||
|  */ |  */ | ||||||
| void api_hal_subghz_init(); | void api_hal_subghz_init(); | ||||||
| 
 | 
 | ||||||
|  | /** Send device to sleep mode */ | ||||||
|  | void api_hal_subghz_sleep(); | ||||||
|  | 
 | ||||||
| /** Dump info to stdout */ | /** Dump info to stdout */ | ||||||
| void api_hal_subghz_dump_state(); | void api_hal_subghz_dump_state(); | ||||||
| 
 | 
 | ||||||
| @ -60,7 +77,6 @@ void api_hal_subghz_write_packet(const uint8_t* data, uint8_t size); | |||||||
|  * @param data, pointer |  * @param data, pointer | ||||||
|  * @param size, size |  * @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 */ | /** Flush rx FIFO buffer */ | ||||||
| @ -108,23 +124,40 @@ uint32_t api_hal_subghz_set_frequency(uint32_t value); | |||||||
|  */ |  */ | ||||||
| void api_hal_subghz_set_path(ApiHalSubGhzPath path); | void api_hal_subghz_set_path(ApiHalSubGhzPath path); | ||||||
| 
 | 
 | ||||||
|  | /* High Level API */ | ||||||
|  | 
 | ||||||
| /** Signal Timings Capture callback */ | /** Signal Timings Capture callback */ | ||||||
| typedef void (*ApiHalSubGhzCaptureCallback)(bool level, uint32_t duration, void* context); | typedef void (*ApiHalSubGhzCaptureCallback)(bool level, uint32_t duration, void* context); | ||||||
| 
 | 
 | ||||||
| /** Set signal timings capture callback
 | /** Set signal timings capture callback
 | ||||||
|  * @param callback - your callback for front capture |  * @param callback - your callback for front capture | ||||||
|  */ |  */ | ||||||
| void api_hal_subghz_set_capture_callback(ApiHalSubGhzCaptureCallback callback, void* context); | void api_hal_subghz_set_async_rx_callback(ApiHalSubGhzCaptureCallback callback, void* context); | ||||||
| 
 | 
 | ||||||
| /** Enable signal timings capture 
 | /** Enable signal timings capture 
 | ||||||
|  * Initializes GPIO and TIM2 for timings capture |  * Initializes GPIO and TIM2 for timings capture | ||||||
|  */ |  */ | ||||||
| void api_hal_subghz_enable_capture(); | void api_hal_subghz_start_async_rx(); | ||||||
| 
 | 
 | ||||||
| /** Disable signal timings capture
 | /** Disable signal timings capture
 | ||||||
|  * Resets GPIO and TIM2 |  * Resets GPIO and TIM2 | ||||||
|  */ |  */ | ||||||
| void api_hal_subghz_disable_capture(); | void api_hal_subghz_stop_async_rx(); | ||||||
|  | 
 | ||||||
|  | /** Send buffer
 | ||||||
|  |  * Initializes GPIO, TIM2 and DMA1 for signal output | ||||||
|  |  * @param buffer - pointer to data buffer | ||||||
|  |  * @param buffer_size - buffer size in bytes | ||||||
|  |  */ | ||||||
|  | void api_hal_subghz_start_async_tx(uint32_t* buffer, size_t buffer_size, size_t repeat); | ||||||
|  | 
 | ||||||
|  | /** Wait for async transmission to complete */ | ||||||
|  | void api_hal_subghz_wait_async_tx(); | ||||||
|  | 
 | ||||||
|  | /** Stop async transmission and cleanup resources
 | ||||||
|  |  * Resets GPIO, TIM2, and DMA1 | ||||||
|  |  */ | ||||||
|  | void api_hal_subghz_stop_async_tx(); | ||||||
| 
 | 
 | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
| } | } | ||||||
|  | |||||||
| @ -5,6 +5,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {}; | |||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #include "api-hal-boot.h" | #include "api-hal-boot.h" | ||||||
|  | #include "api-hal-clock.h" | ||||||
| #include "api-hal-os.h" | #include "api-hal-os.h" | ||||||
| #include "api-hal-i2c.h" | #include "api-hal-i2c.h" | ||||||
| #include "api-hal-resources.h" | #include "api-hal-resources.h" | ||||||
| @ -15,6 +16,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {}; | |||||||
| #include "api-hal-task.h" | #include "api-hal-task.h" | ||||||
| #include "api-hal-power.h" | #include "api-hal-power.h" | ||||||
| #include "api-hal-vcp.h" | #include "api-hal-vcp.h" | ||||||
|  | #include "api-hal-interrupt.h" | ||||||
| #include "api-hal-version.h" | #include "api-hal-version.h" | ||||||
| #include "api-hal-bt.h" | #include "api-hal-bt.h" | ||||||
| #include "api-hal-spi.h" | #include "api-hal-spi.h" | ||||||
|  | |||||||
							
								
								
									
										0
									
								
								firmware/targets/f5/api-hal/api-hal-interrupt.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								firmware/targets/f5/api-hal/api-hal-interrupt.h
									
									
									
									
									
										Normal file
									
								
							| @ -2,11 +2,15 @@ | |||||||
| 
 | 
 | ||||||
| #include <api-hal-gpio.h> | #include <api-hal-gpio.h> | ||||||
| #include <api-hal-spi.h> | #include <api-hal-spi.h> | ||||||
|  | #include <api-hal-interrupt.h> | ||||||
| #include <api-hal-resources.h> | #include <api-hal-resources.h> | ||||||
|  | 
 | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <cc1101.h> | #include <cc1101.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| 
 | 
 | ||||||
|  | static volatile SubGhzState api_hal_subghz_state = SubGhzStateInit; | ||||||
|  | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = { | static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = { | ||||||
|     /* Base setting */ |     /* Base setting */ | ||||||
|     { CC1101_IOCFG0,    0x0D }, // GD0 as async serial data output/input
 |     { CC1101_IOCFG0,    0x0D }, // GD0 as async serial data output/input
 | ||||||
| @ -22,7 +26,7 @@ static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_ook_async_patable[8] = { | static const uint8_t api_hal_subghz_preset_ook_async_patable[8] = { | ||||||
|     0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |     0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_mp_regs[][2] = { | static const uint8_t api_hal_subghz_preset_mp_regs[][2] = { | ||||||
| @ -61,7 +65,7 @@ static const uint8_t api_hal_subghz_preset_mp_regs[][2] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_mp_patable[8] = { | static const uint8_t api_hal_subghz_preset_mp_patable[8] = { | ||||||
|     0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |     0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = { | static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = { | ||||||
| @ -83,25 +87,52 @@ static const uint8_t api_hal_subghz_preset_2fsk_packet_patable[8] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void api_hal_subghz_init() { | void api_hal_subghz_init() { | ||||||
|     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     furi_assert(api_hal_subghz_state == SubGhzStateInit); | ||||||
|     hal_gpio_init(&gpio_rf_sw_1, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     api_hal_subghz_state = SubGhzStateIdle; | ||||||
| 
 | 
 | ||||||
|     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); |     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); | ||||||
|     // Reset and shutdown
 | 
 | ||||||
|  |     // Reset
 | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_reset(device); |     cc1101_reset(device); | ||||||
|  |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|  | 
 | ||||||
|     // Prepare GD0 for power on self test
 |     // Prepare GD0 for power on self test
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|     // GD0 low
 |     // GD0 low
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW); | ||||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != false); |     while(hal_gpio_read(&gpio_cc1101_g0) != false); | ||||||
|  | 
 | ||||||
|     // GD0 high
 |     // GD0 high
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHW | CC1101_IOCFG_INV); | ||||||
|     while(hal_gpio_read(&gpio_cc1101_g0) != true); |     while(hal_gpio_read(&gpio_cc1101_g0) != true); | ||||||
|  | 
 | ||||||
|     // Reset GD0 to floating state
 |     // Reset GD0 to floating state
 | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|     // Turn off oscillator
 | 
 | ||||||
|  |     // RF switches
 | ||||||
|  |     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|  |     hal_gpio_init(&gpio_rf_sw_1, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |     // Go to sleep
 | ||||||
|     cc1101_shutdown(device); |     cc1101_shutdown(device); | ||||||
|  | 
 | ||||||
|  |     api_hal_spi_device_return(device); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_sleep() { | ||||||
|  |     furi_assert(api_hal_subghz_state == SubGhzStateIdle); | ||||||
|  |     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); | ||||||
|  | 
 | ||||||
|  |     cc1101_switch_to_idle(device); | ||||||
|  | 
 | ||||||
|  |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |     cc1101_shutdown(device); | ||||||
|  | 
 | ||||||
|     api_hal_spi_device_return(device); |     api_hal_spi_device_return(device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -181,7 +212,10 @@ void api_hal_subghz_shutdown() { | |||||||
| 
 | 
 | ||||||
| void api_hal_subghz_reset() { | void api_hal_subghz_reset() { | ||||||
|     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); |     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     cc1101_switch_to_idle(device); | ||||||
|     cc1101_reset(device); |     cc1101_reset(device); | ||||||
|  |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     api_hal_spi_device_return(device); |     api_hal_spi_device_return(device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -266,8 +300,15 @@ void api_hal_subghz_set_path(ApiHalSubGhzPath path) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void api_hal_subghz_set_capture_callback(ApiHalSubGhzCaptureCallback callback, void* context) {} | void api_hal_subghz_set_async_rx_callback(ApiHalSubGhzCaptureCallback callback, void* context) {} | ||||||
| 
 | 
 | ||||||
| void api_hal_subghz_enable_capture() {} | void api_hal_subghz_start_async_rx() {} | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_stop_async_rx() {} | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_start_async_tx(uint32_t* buffer, size_t buffer_size, size_t repeat) {} | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_wait_async_tx() {} | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_stop_async_tx() {} | ||||||
| 
 | 
 | ||||||
| void api_hal_subghz_disable_capture() {} |  | ||||||
|  | |||||||
| @ -2,6 +2,15 @@ | |||||||
| 
 | 
 | ||||||
| #include <stm32wbxx_ll_rcc.h> | #include <stm32wbxx_ll_rcc.h> | ||||||
| 
 | 
 | ||||||
|  | void api_hal_clock_init() { | ||||||
|  |     // AHB
 | ||||||
|  |     LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMAMUX1); | ||||||
|  |     LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1); | ||||||
|  | 
 | ||||||
|  |     // APB
 | ||||||
|  |     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void api_hal_clock_switch_to_hsi() { | void api_hal_clock_switch_to_hsi() { | ||||||
|     LL_RCC_HSI_Enable( ); |     LL_RCC_HSI_Enable( ); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,7 +1,10 @@ | |||||||
| #pragma once | #pragma once | ||||||
| 
 | 
 | ||||||
| /* Switch to HSI clock */ | /** Initialize clocks */ | ||||||
|  | void api_hal_clock_init(); | ||||||
|  | 
 | ||||||
|  | /** Switch to HSI clock */ | ||||||
| void api_hal_clock_switch_to_hsi(); | void api_hal_clock_switch_to_hsi(); | ||||||
| 
 | 
 | ||||||
| /* Switch to PLL clock */ | /** Switch to PLL clock */ | ||||||
| void api_hal_clock_switch_to_pll(); | void api_hal_clock_switch_to_pll(); | ||||||
|  | |||||||
| @ -6,12 +6,14 @@ | |||||||
| 
 | 
 | ||||||
| volatile ApiHalInterruptISR api_hal_tim_tim2_isr = NULL; | volatile ApiHalInterruptISR api_hal_tim_tim2_isr = NULL; | ||||||
| 
 | 
 | ||||||
| void TIM2_IRQHandler(void) { | #define API_HAL_INTERRUPT_DMA_COUNT 2 | ||||||
|     if (api_hal_tim_tim2_isr) { | #define API_HAL_INTERRUPT_DMA_CHANNELS_COUNT 8 | ||||||
|         api_hal_tim_tim2_isr(); | 
 | ||||||
|     } else { | volatile ApiHalInterruptISR api_hal_dma_channel_isr[API_HAL_INTERRUPT_DMA_COUNT][API_HAL_INTERRUPT_DMA_CHANNELS_COUNT] = {0}; | ||||||
|         HAL_TIM_IRQHandler(&htim2); | 
 | ||||||
|     } | void api_hal_interrupt_init() { | ||||||
|  |     NVIC_SetPriority(DMA1_Channel1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); | ||||||
|  |     NVIC_EnableIRQ(DMA1_Channel1_IRQn); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void api_hal_interrupt_set_timer_isr(TIM_TypeDef* timer, ApiHalInterruptISR isr) { | void api_hal_interrupt_set_timer_isr(TIM_TypeDef* timer, ApiHalInterruptISR isr) { | ||||||
| @ -27,6 +29,19 @@ void api_hal_interrupt_set_timer_isr(TIM_TypeDef *timer, ApiHalInterruptISR isr) | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void api_hal_interrupt_set_dma_channel_isr(DMA_TypeDef* dma, uint32_t channel, ApiHalInterruptISR isr) { | ||||||
|  |     --channel; // Pascal 
 | ||||||
|  |     furi_check(dma); | ||||||
|  |     furi_check(channel < API_HAL_INTERRUPT_DMA_CHANNELS_COUNT); | ||||||
|  |     if (dma == DMA1) { | ||||||
|  |         api_hal_dma_channel_isr[0][channel] = isr; | ||||||
|  |     } else if (dma == DMA1) { | ||||||
|  |         api_hal_dma_channel_isr[1][channel] = isr; | ||||||
|  |     } else { | ||||||
|  |         furi_check(0); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| extern void api_interrupt_call(InterruptType type, void* hw); | extern void api_interrupt_call(InterruptType type, void* hw); | ||||||
| 
 | 
 | ||||||
| /* ST HAL symbols */ | /* ST HAL symbols */ | ||||||
| @ -40,3 +55,78 @@ void HAL_COMP_TriggerCallback(COMP_HandleTypeDef* hcomp) { | |||||||
| void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) { | void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef* htim) { | ||||||
|     api_interrupt_call(InterruptTypeTimerUpdate, htim); |     api_interrupt_call(InterruptTypeTimerUpdate, htim); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | /* Timer 2 */ | ||||||
|  | void TIM2_IRQHandler(void) { | ||||||
|  |     if (api_hal_tim_tim2_isr) { | ||||||
|  |         api_hal_tim_tim2_isr(); | ||||||
|  |     } else { | ||||||
|  |         HAL_TIM_IRQHandler(&htim2); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* DMA 1 */ | ||||||
|  | void DMA1_Channel1_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[0][0]) api_hal_dma_channel_isr[0][0](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA1_Channel2_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[0][1]) api_hal_dma_channel_isr[0][1](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA1_Channel3_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[0][2]) api_hal_dma_channel_isr[0][2](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA1_Channel4_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[0][3]) api_hal_dma_channel_isr[0][3](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA1_Channel5_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[0][4]) api_hal_dma_channel_isr[0][4](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA1_Channel6_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[0][5]) api_hal_dma_channel_isr[0][5](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA1_Channel7_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[0][6]) api_hal_dma_channel_isr[0][6](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA1_Channel8_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[0][7]) api_hal_dma_channel_isr[0][7](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | /* DMA 2 */ | ||||||
|  | void DMA2_Channel1_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[1][0]) api_hal_dma_channel_isr[1][0](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA2_Channel2_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[1][1]) api_hal_dma_channel_isr[1][1](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA2_Channel3_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[1][2]) api_hal_dma_channel_isr[1][2](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA2_Channel4_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[1][3]) api_hal_dma_channel_isr[1][3](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA2_Channel5_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[1][4]) api_hal_dma_channel_isr[1][4](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA2_Channel6_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[1][5]) api_hal_dma_channel_isr[1][5](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA2_Channel7_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[1][6]) api_hal_dma_channel_isr[1][6](); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void DMA2_Channel8_IRQHandler(void) { | ||||||
|  |     if (api_hal_dma_channel_isr[1][7]) api_hal_dma_channel_isr[1][7](); | ||||||
|  | } | ||||||
|  | |||||||
| @ -9,11 +9,22 @@ extern "C" { | |||||||
| /** Timer ISR */ | /** Timer ISR */ | ||||||
| typedef void (*ApiHalInterruptISR)(); | typedef void (*ApiHalInterruptISR)(); | ||||||
| 
 | 
 | ||||||
|  | /** Initialize interrupt subsystem */ | ||||||
|  | void api_hal_interrupt_init(); | ||||||
|  | 
 | ||||||
|  | /** Set DMA Channel ISR
 | ||||||
|  |  * We don't clear interrupt flags for you, do it by your self. | ||||||
|  |  * @param dma - DMA instance | ||||||
|  |  * @param channel - DMA channel | ||||||
|  |  * @param isr - your interrupt service routine or use NULL to clear | ||||||
|  |  */ | ||||||
|  | void api_hal_interrupt_set_dma_channel_isr(DMA_TypeDef* dma, uint32_t channel, ApiHalInterruptISR isr); | ||||||
|  | 
 | ||||||
| /** Set Timer ISR
 | /** Set Timer ISR
 | ||||||
|  * By default ISR is serviced by ST HAL. Use this function to override it. |  * By default ISR is serviced by ST HAL. Use this function to override it. | ||||||
|  * We don't clear interrupt flags for you, do it by your self. |  * We don't clear interrupt flags for you, do it by your self. | ||||||
|  * @timer - timer instance |  * @param timer - timer instance | ||||||
|  * @isr - your interrupt service routine or use NULL to clear |  * @param isr - your interrupt service routine or use NULL to clear | ||||||
|  */ |  */ | ||||||
| void api_hal_interrupt_set_timer_isr(TIM_TypeDef *timer, ApiHalInterruptISR isr); | void api_hal_interrupt_set_timer_isr(TIM_TypeDef *timer, ApiHalInterruptISR isr); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -9,6 +9,8 @@ | |||||||
| #include <cc1101.h> | #include <cc1101.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
| 
 | 
 | ||||||
|  | static volatile SubGhzState api_hal_subghz_state = SubGhzStateInit; | ||||||
|  | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = { | static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = { | ||||||
|     /* Base setting */ |     /* Base setting */ | ||||||
|     { CC1101_IOCFG0,    0x0D }, // GD0 as async serial data output/input
 |     { CC1101_IOCFG0,    0x0D }, // GD0 as async serial data output/input
 | ||||||
| @ -24,7 +26,7 @@ static const uint8_t api_hal_subghz_preset_ook_async_regs[][2] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_ook_async_patable[8] = { | static const uint8_t api_hal_subghz_preset_ook_async_patable[8] = { | ||||||
|     0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |     0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_mp_regs[][2] = { | static const uint8_t api_hal_subghz_preset_mp_regs[][2] = { | ||||||
| @ -63,7 +65,7 @@ static const uint8_t api_hal_subghz_preset_mp_regs[][2] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_mp_patable[8] = { | static const uint8_t api_hal_subghz_preset_mp_patable[8] = { | ||||||
|     0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |     0x00, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = { | static const uint8_t api_hal_subghz_preset_2fsk_packet_regs[][2] = { | ||||||
| @ -85,9 +87,19 @@ static const uint8_t api_hal_subghz_preset_2fsk_packet_patable[8] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void api_hal_subghz_init() { | void api_hal_subghz_init() { | ||||||
|  |     furi_assert(api_hal_subghz_state == SubGhzStateInit); | ||||||
|  |     api_hal_subghz_state = SubGhzStateIdle; | ||||||
|  | 
 | ||||||
|     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); |     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); | ||||||
|     // Reset and shutdown
 | 
 | ||||||
|  | #ifdef API_HAL_SUBGHZ_TX_GPIO | ||||||
|  |     hal_gpio_init(&API_HAL_SUBGHZ_TX_GPIO, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     // Reset
 | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_reset(device); |     cc1101_reset(device); | ||||||
|  |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
| 
 | 
 | ||||||
|     // Prepare GD0 for power on self test
 |     // Prepare GD0 for power on self test
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeInput, GpioPullNo, GpioSpeedLow); | ||||||
| @ -108,8 +120,23 @@ void api_hal_subghz_init() { | |||||||
|     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_rf_sw_0, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); |     cc1101_write_reg(device, CC1101_IOCFG2, CC1101IocfgHW); | ||||||
| 
 | 
 | ||||||
|     // Turn off oscillator
 |     // Go to sleep
 | ||||||
|     cc1101_shutdown(device); |     cc1101_shutdown(device); | ||||||
|  | 
 | ||||||
|  |     api_hal_spi_device_return(device); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_sleep() { | ||||||
|  |     furi_assert(api_hal_subghz_state == SubGhzStateIdle); | ||||||
|  |     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); | ||||||
|  | 
 | ||||||
|  |     cc1101_switch_to_idle(device); | ||||||
|  | 
 | ||||||
|  |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | 
 | ||||||
|  |     cc1101_shutdown(device); | ||||||
|  | 
 | ||||||
|     api_hal_spi_device_return(device); |     api_hal_spi_device_return(device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -189,7 +216,10 @@ void api_hal_subghz_shutdown() { | |||||||
| 
 | 
 | ||||||
| void api_hal_subghz_reset() { | void api_hal_subghz_reset() { | ||||||
|     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); |     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     cc1101_switch_to_idle(device); | ||||||
|     cc1101_reset(device); |     cc1101_reset(device); | ||||||
|  |     cc1101_write_reg(device, CC1101_IOCFG0, CC1101IocfgHighImpedance); | ||||||
|     api_hal_spi_device_return(device); |     api_hal_spi_device_return(device); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -207,7 +237,6 @@ void api_hal_subghz_rx() { | |||||||
| 
 | 
 | ||||||
| void api_hal_subghz_tx() { | void api_hal_subghz_tx() { | ||||||
|     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); |     const ApiHalSpiDevice* device = api_hal_spi_device_get(ApiHalSpiDeviceIdSubGhz); | ||||||
|     cc1101_switch_to_idle(device); |  | ||||||
|     cc1101_switch_to_tx(device); |     cc1101_switch_to_tx(device); | ||||||
|     api_hal_spi_device_return(device); |     api_hal_spi_device_return(device); | ||||||
| } | } | ||||||
| @ -281,11 +310,6 @@ volatile uint32_t api_hal_subghz_capture_delta_duration = 0; | |||||||
| volatile ApiHalSubGhzCaptureCallback api_hal_subghz_capture_callback = NULL; | volatile ApiHalSubGhzCaptureCallback api_hal_subghz_capture_callback = NULL; | ||||||
| volatile void* api_hal_subghz_capture_callback_context = NULL; | volatile void* api_hal_subghz_capture_callback_context = NULL; | ||||||
| 
 | 
 | ||||||
| void api_hal_subghz_set_capture_callback(ApiHalSubGhzCaptureCallback callback, void* context) { |  | ||||||
|     api_hal_subghz_capture_callback = callback; |  | ||||||
|     api_hal_subghz_capture_callback_context = context; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static void api_hal_subghz_capture_ISR() { | static void api_hal_subghz_capture_ISR() { | ||||||
|     // Channel 1
 |     // Channel 1
 | ||||||
|     if(LL_TIM_IsActiveFlag_CC1(TIM2)) { |     if(LL_TIM_IsActiveFlag_CC1(TIM2)) { | ||||||
| @ -308,10 +332,14 @@ static void api_hal_subghz_capture_ISR() { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void api_hal_subghz_enable_capture() { | void api_hal_subghz_set_async_rx_callback(ApiHalSubGhzCaptureCallback callback, void* context) { | ||||||
|     /* Peripheral clock enable */ |     api_hal_subghz_capture_callback = callback; | ||||||
|     LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_TIM2); |     api_hal_subghz_capture_callback_context = context; | ||||||
|     LL_AHB2_GRP1_EnableClock(LL_AHB2_GRP1_PERIPH_GPIOA); | } | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_start_async_rx() { | ||||||
|  |     furi_assert(api_hal_subghz_state == SubGhzStateIdle); | ||||||
|  |     api_hal_subghz_state = SubGhzStateAsyncRx; | ||||||
| 
 | 
 | ||||||
|     hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); |     hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullNo, GpioSpeedLow, GpioAltFn1TIM2); | ||||||
| 
 | 
 | ||||||
| @ -323,24 +351,27 @@ void api_hal_subghz_enable_capture() { | |||||||
|     TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; |     TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; | ||||||
|     LL_TIM_Init(TIM2, &TIM_InitStruct); |     LL_TIM_Init(TIM2, &TIM_InitStruct); | ||||||
| 
 | 
 | ||||||
|     // Timer: advanced and channel
 |     // Timer: advanced
 | ||||||
|     LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); |     LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); | ||||||
|     LL_TIM_DisableARRPreload(TIM2); |     LL_TIM_DisableARRPreload(TIM2); | ||||||
|     LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI2FP2); |     LL_TIM_SetTriggerInput(TIM2, LL_TIM_TS_TI2FP2); | ||||||
|     LL_TIM_SetSlaveMode(TIM2, LL_TIM_SLAVEMODE_RESET); |     LL_TIM_SetSlaveMode(TIM2, LL_TIM_SLAVEMODE_RESET); | ||||||
|     LL_TIM_CC_DisableChannel(TIM2, LL_TIM_CHANNEL_CH2); |  | ||||||
|     LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1); |  | ||||||
|     LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING); |  | ||||||
|     LL_TIM_DisableIT_TRIG(TIM2); |  | ||||||
|     LL_TIM_DisableDMAReq_TRIG(TIM2); |  | ||||||
|     LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET); |     LL_TIM_SetTriggerOutput(TIM2, LL_TIM_TRGO_RESET); | ||||||
|     LL_TIM_EnableMasterSlaveMode(TIM2); |     LL_TIM_EnableMasterSlaveMode(TIM2); | ||||||
|  |     LL_TIM_DisableDMAReq_TRIG(TIM2); | ||||||
|  |     LL_TIM_DisableIT_TRIG(TIM2); | ||||||
|  | 
 | ||||||
|  |     // Timer: channel 1 indirect
 | ||||||
|     LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_INDIRECTTI); |     LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ACTIVEINPUT_INDIRECTTI); | ||||||
|     LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1); |     LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_ICPSC_DIV1); | ||||||
|     LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1); |  | ||||||
|     LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_FALLING); |     LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_POLARITY_FALLING); | ||||||
|  |     LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH1, LL_TIM_IC_FILTER_FDIV1); | ||||||
|  | 
 | ||||||
|  |     // Timer: channel 2 direct
 | ||||||
|     LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI); |     LL_TIM_IC_SetActiveInput(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ACTIVEINPUT_DIRECTTI); | ||||||
|     LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1); |     LL_TIM_IC_SetPrescaler(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_ICPSC_DIV1); | ||||||
|  |     LL_TIM_IC_SetPolarity(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_POLARITY_RISING); | ||||||
|  |     LL_TIM_IC_SetFilter(TIM2, LL_TIM_CHANNEL_CH2, LL_TIM_IC_FILTER_FDIV1); | ||||||
| 
 | 
 | ||||||
|     // ISR setup
 |     // ISR setup
 | ||||||
|     api_hal_interrupt_set_timer_isr(TIM2, api_hal_subghz_capture_ISR); |     api_hal_interrupt_set_timer_isr(TIM2, api_hal_subghz_capture_ISR); | ||||||
| @ -356,10 +387,132 @@ void api_hal_subghz_enable_capture() { | |||||||
|     // Start timer
 |     // Start timer
 | ||||||
|     LL_TIM_SetCounter(TIM2, 0); |     LL_TIM_SetCounter(TIM2, 0); | ||||||
|     LL_TIM_EnableCounter(TIM2); |     LL_TIM_EnableCounter(TIM2); | ||||||
|  | 
 | ||||||
|  |     // Switch to RX
 | ||||||
|  |     api_hal_subghz_rx(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void api_hal_subghz_disable_capture() { | void api_hal_subghz_stop_async_rx() { | ||||||
|  |     furi_assert(api_hal_subghz_state == SubGhzStateAsyncRx); | ||||||
|  |     api_hal_subghz_state = SubGhzStateIdle; | ||||||
|  | 
 | ||||||
|  |     // Shutdown radio
 | ||||||
|  |     api_hal_subghz_idle(); | ||||||
|  | 
 | ||||||
|     LL_TIM_DeInit(TIM2); |     LL_TIM_DeInit(TIM2); | ||||||
|     api_hal_interrupt_set_timer_isr(TIM2, NULL); |     api_hal_interrupt_set_timer_isr(TIM2, NULL); | ||||||
|  | 
 | ||||||
|  |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | volatile size_t api_hal_subghz_tx_repeat = 0; | ||||||
|  | 
 | ||||||
|  | static void api_hal_subghz_tx_dma_isr() { | ||||||
|  |     if (LL_DMA_IsActiveFlag_TC1(DMA1)) { | ||||||
|  |         LL_DMA_ClearFlag_TC1(DMA1); | ||||||
|  |         furi_assert(api_hal_subghz_state == SubGhzStateAsyncTx); | ||||||
|  |         if (--api_hal_subghz_tx_repeat == 0) { | ||||||
|  |             api_hal_subghz_state = SubGhzStateAsyncTxLast; | ||||||
|  |             LL_DMA_DisableChannel(DMA1, LL_DMA_CHANNEL_1); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | static void api_hal_subghz_tx_timer_isr() { | ||||||
|  |     if(LL_TIM_IsActiveFlag_UPDATE(TIM2)) { | ||||||
|  |         LL_TIM_ClearFlag_UPDATE(TIM2); | ||||||
|  |         if (api_hal_subghz_state == SubGhzStateAsyncTxLast) { | ||||||
|  |             LL_TIM_DisableCounter(TIM2); | ||||||
|  |             api_hal_subghz_state = SubGhzStateAsyncTxEnd; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_start_async_tx(uint32_t* buffer, size_t buffer_size, size_t repeat) { | ||||||
|  |     furi_assert(api_hal_subghz_state == SubGhzStateIdle); | ||||||
|  |     api_hal_subghz_state = SubGhzStateAsyncTx; | ||||||
|  |     api_hal_subghz_tx_repeat = repeat; | ||||||
|  | 
 | ||||||
|  |     // Connect CC1101_GD0 to TIM2 as output
 | ||||||
|  |     hal_gpio_init_ex(&gpio_cc1101_g0, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn1TIM2); | ||||||
|  | 
 | ||||||
|  |     // Configure DMA
 | ||||||
|  |     LL_DMA_InitTypeDef dma_config = {0}; | ||||||
|  |     dma_config.PeriphOrM2MSrcAddress = (uint32_t)&(TIM2->ARR); | ||||||
|  |     dma_config.MemoryOrM2MDstAddress = (uint32_t)buffer; | ||||||
|  |     dma_config.Direction = LL_DMA_DIRECTION_MEMORY_TO_PERIPH; | ||||||
|  |     dma_config.Mode = LL_DMA_MODE_CIRCULAR; | ||||||
|  |     dma_config.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; | ||||||
|  |     dma_config.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; | ||||||
|  |     dma_config.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; | ||||||
|  |     dma_config.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; | ||||||
|  |     dma_config.NbData = buffer_size / sizeof(uint32_t); | ||||||
|  |     dma_config.PeriphRequest = LL_DMAMUX_REQ_TIM2_UP; | ||||||
|  |     dma_config.Priority = LL_DMA_MODE_NORMAL; | ||||||
|  |     LL_DMA_Init(DMA1, LL_DMA_CHANNEL_1, &dma_config); | ||||||
|  |     api_hal_interrupt_set_dma_channel_isr(DMA1, LL_DMA_CHANNEL_1, api_hal_subghz_tx_dma_isr); | ||||||
|  |     LL_DMA_EnableIT_TC(DMA1, LL_DMA_CHANNEL_1); | ||||||
|  |     LL_DMA_EnableChannel(DMA1, LL_DMA_CHANNEL_1); | ||||||
|  | 
 | ||||||
|  |     // Configure TIM2
 | ||||||
|  |     LL_TIM_InitTypeDef TIM_InitStruct = {0}; | ||||||
|  |     TIM_InitStruct.Prescaler = 64-1; | ||||||
|  |     TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP; | ||||||
|  |     TIM_InitStruct.Autoreload = 1000; | ||||||
|  |     TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1; | ||||||
|  |     LL_TIM_Init(TIM2, &TIM_InitStruct); | ||||||
|  |     LL_TIM_SetClockSource(TIM2, LL_TIM_CLOCKSOURCE_INTERNAL); | ||||||
|  |     LL_TIM_EnableARRPreload(TIM2); | ||||||
|  | 
 | ||||||
|  |     // Configure TIM2 CH2
 | ||||||
|  |     LL_TIM_OC_InitTypeDef TIM_OC_InitStruct = {0}; | ||||||
|  |     TIM_OC_InitStruct.OCMode = LL_TIM_OCMODE_TOGGLE; | ||||||
|  |     TIM_OC_InitStruct.OCState = LL_TIM_OCSTATE_DISABLE; | ||||||
|  |     TIM_OC_InitStruct.OCNState = LL_TIM_OCSTATE_DISABLE; | ||||||
|  |     TIM_OC_InitStruct.CompareValue = 0; | ||||||
|  |     TIM_OC_InitStruct.OCPolarity = LL_TIM_OCPOLARITY_HIGH; | ||||||
|  |     LL_TIM_OC_Init(TIM2, LL_TIM_CHANNEL_CH2, &TIM_OC_InitStruct); | ||||||
|  |     LL_TIM_OC_DisableFast(TIM2, LL_TIM_CHANNEL_CH2); | ||||||
|  |     LL_TIM_DisableMasterSlaveMode(TIM2); | ||||||
|  | 
 | ||||||
|  |     api_hal_interrupt_set_timer_isr(TIM2, api_hal_subghz_tx_timer_isr); | ||||||
|  |     LL_TIM_EnableIT_UPDATE(TIM2); | ||||||
|  |     LL_TIM_EnableDMAReq_UPDATE(TIM2); | ||||||
|  |     LL_TIM_CC_EnableChannel(TIM2, LL_TIM_CHANNEL_CH2); | ||||||
|  | 
 | ||||||
|  |     // Start counter
 | ||||||
|  |     LL_TIM_GenerateEvent_UPDATE(TIM2); | ||||||
|  | #ifdef API_HAL_SUBGHZ_TX_GPIO | ||||||
|  |     hal_gpio_write(&API_HAL_SUBGHZ_TX_GPIO, true); | ||||||
|  | #endif | ||||||
|  |     api_hal_subghz_tx(); | ||||||
|  | 
 | ||||||
|  |     LL_TIM_SetCounter(TIM2, 0); | ||||||
|  |     LL_TIM_EnableCounter(TIM2); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_wait_async_tx() { | ||||||
|  |     while(api_hal_subghz_state != SubGhzStateAsyncTxEnd) osDelay(1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void api_hal_subghz_stop_async_tx() { | ||||||
|  |     furi_assert(api_hal_subghz_state == SubGhzStateAsyncTxEnd); | ||||||
|  |     api_hal_subghz_state = SubGhzStateIdle; | ||||||
|  | 
 | ||||||
|  |     // Shutdown radio
 | ||||||
|  |     api_hal_subghz_idle(); | ||||||
|  | #ifdef API_HAL_SUBGHZ_TX_GPIO | ||||||
|  |     hal_gpio_write(&API_HAL_SUBGHZ_TX_GPIO, false); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |     // Deinitialize Timer
 | ||||||
|  |     LL_TIM_DeInit(TIM2); | ||||||
|  |     api_hal_interrupt_set_timer_isr(TIM2, NULL); | ||||||
|  | 
 | ||||||
|  |     // Deinitialize DMA
 | ||||||
|  |     LL_DMA_DeInit(DMA1, LL_DMA_CHANNEL_1); | ||||||
|  |     api_hal_interrupt_set_dma_channel_isr(DMA1, LL_DMA_CHANNEL_1, NULL); | ||||||
|  | 
 | ||||||
|  |     // Deinitialize GPIO
 | ||||||
|     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |     hal_gpio_init(&gpio_cc1101_g0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| } | } | ||||||
|  | |||||||
| @ -3,6 +3,10 @@ | |||||||
| void api_hal_init() { | void api_hal_init() { | ||||||
|     api_hal_boot_init(); |     api_hal_boot_init(); | ||||||
|     FURI_LOG_I("FURI_HAL", "BOOT OK"); |     FURI_LOG_I("FURI_HAL", "BOOT OK"); | ||||||
|  |     api_hal_interrupt_init(); | ||||||
|  |     FURI_LOG_I("FURI_HAL", "INTERRUPT OK"); | ||||||
|  |     api_hal_clock_init(); | ||||||
|  |     FURI_LOG_I("FURI_HAL", "CLOCK OK"); | ||||||
|     api_hal_version_init(); |     api_hal_version_init(); | ||||||
|     FURI_LOG_I("FURI_HAL", "VERSION OK"); |     FURI_LOG_I("FURI_HAL", "VERSION OK"); | ||||||
|     api_hal_delay_init(); |     api_hal_delay_init(); | ||||||
|  | |||||||
| @ -19,6 +19,11 @@ ifeq ($(API_HAL_OS_DEBUG), 1) | |||||||
| CFLAGS			+= -DAPI_HAL_OS_DEBUG | CFLAGS			+= -DAPI_HAL_OS_DEBUG | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | API_HAL_SUBGHZ_TX_GPIO ?= 0 | ||||||
|  | ifneq ($(API_HAL_SUBGHZ_TX_GPIO), 0) | ||||||
|  | CFLAGS			+= -DAPI_HAL_SUBGHZ_TX_GPIO=$(API_HAL_SUBGHZ_TX_GPIO) | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| ifeq ($(INVERT_RFID_IN), 1) | ifeq ($(INVERT_RFID_IN), 1) | ||||||
| CFLAGS += -DINVERT_RFID_IN | CFLAGS += -DINVERT_RFID_IN | ||||||
| endif | endif | ||||||
| @ -46,8 +51,6 @@ C_SOURCES		+= \ | |||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cryp.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_cryp.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_crc.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_crc.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_crc_ex.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_crc_ex.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma.c \
 |  | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_dma_ex.c \
 |  | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_exti.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_exti.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash_ex.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_flash_ex.c \
 | ||||||
| @ -72,6 +75,7 @@ C_SOURCES		+= \ | |||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_uart_ex.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_uart_ex.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_lptim.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_hal_lptim.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_adc.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_adc.c \
 | ||||||
|  | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_dma.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_gpio.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_gpio.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_i2c.c \
 | ||||||
| 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c \
 | 	$(CUBE_DIR)/Drivers/STM32WBxx_HAL_Driver/Src/stm32wbxx_ll_rcc.c \
 | ||||||
|  | |||||||
| @ -145,7 +145,7 @@ void cc1101_set_pa_table(const ApiHalSpiDevice* device, const uint8_t value[8]) | |||||||
| 
 | 
 | ||||||
|     hal_gpio_write(device->chip_select, false); |     hal_gpio_write(device->chip_select, false); | ||||||
|     while(hal_gpio_read(device->bus->miso)); |     while(hal_gpio_read(device->bus->miso)); | ||||||
|     api_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, 2, CC1101_TIMEOUT); |     api_hal_spi_bus_trx(device->bus, tx, (uint8_t*)rx, sizeof(rx), CC1101_TIMEOUT); | ||||||
|     hal_gpio_write(device->chip_select, true); |     hal_gpio_write(device->chip_select, true); | ||||||
| 
 | 
 | ||||||
|     assert((rx[0].CHIP_RDYn|rx[8].CHIP_RDYn) == 0); |     assert((rx[0].CHIP_RDYn|rx[8].CHIP_RDYn) == 0); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 あく
						あく