[FL-1505] Add RAW format (#576)
* Add RAW format * F5 stubs for build to pass * Fix saving decoded signal error * Irda: set ISR before starting timer, remove explicit NVIC configuration Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		| @@ -1,24 +1,48 @@ | ||||
| #include "app-template.h" | ||||
| #include "cli/cli.h" | ||||
| #include "cmsis_os2.h" | ||||
| #include <api-hal-delay.h> | ||||
| #include <irda.h> | ||||
| #include <app-template.h> | ||||
| #include <cli/cli.h> | ||||
| #include <cmsis_os2.h> | ||||
| #include <irda_worker.h> | ||||
| #include <furi.h> | ||||
| #include <api-hal-irda.h> | ||||
| #include "irda.h" | ||||
| #include <sstream> | ||||
| #include <string> | ||||
| #include <m-string.h> | ||||
| #include <irda_transmit.h> | ||||
|  | ||||
| typedef struct IrdaCli { | ||||
|     IrdaDecoderHandler* handler; | ||||
|     osMessageQueueId_t message_queue; | ||||
| } IrdaCli; | ||||
| static void signal_received_callback(void* context, IrdaWorkerSignal* received_signal) { | ||||
|     furi_assert(received_signal); | ||||
|     char buf[100]; | ||||
|     size_t buf_cnt; | ||||
|     Cli* cli = (Cli*)context; | ||||
|  | ||||
| static void irda_rx_callback(void* ctx, bool level, uint32_t duration) { | ||||
|     IrdaCli* irda_cli = (IrdaCli*)ctx; | ||||
|     const IrdaMessage* message; | ||||
|     message = irda_decode(irda_cli->handler, level, duration); | ||||
|     if(message) { | ||||
|         osMessageQueuePut(irda_cli->message_queue, message, 0, 0); | ||||
|     if(irda_worker_signal_is_decoded(received_signal)) { | ||||
|         const IrdaMessage* message = irda_worker_get_decoded_message(received_signal); | ||||
|         buf_cnt = sniprintf( | ||||
|             buf, | ||||
|             sizeof(buf), | ||||
|             "%s, A:0x%0*lX, C:0x%0*lX%s\r\n", | ||||
|             irda_get_protocol_name(message->protocol), | ||||
|             irda_get_protocol_address_length(message->protocol), | ||||
|             message->address, | ||||
|             irda_get_protocol_command_length(message->protocol), | ||||
|             message->command, | ||||
|             message->repeat ? " R" : ""); | ||||
|         cli_write(cli, (uint8_t*)buf, buf_cnt); | ||||
|     } else { | ||||
|         const uint32_t* timings; | ||||
|         size_t timings_cnt; | ||||
|         irda_worker_get_raw_signal(received_signal, &timings, &timings_cnt); | ||||
|  | ||||
|         buf_cnt = sniprintf(buf, sizeof(buf), "RAW, %d samples:\r\n", timings_cnt); | ||||
|         cli_write(cli, (uint8_t*)buf, buf_cnt); | ||||
|         for(size_t i = 0; i < timings_cnt; ++i) { | ||||
|             buf_cnt = sniprintf(buf, sizeof(buf), "%lu ", timings[i]); | ||||
|             cli_write(cli, (uint8_t*)buf, buf_cnt); | ||||
|         } | ||||
|         buf_cnt = sniprintf(buf, sizeof(buf), "\r\n"); | ||||
|         cli_write(cli, (uint8_t*)buf, buf_cnt); | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -27,30 +51,19 @@ static void irda_cli_start_ir_rx(Cli* cli, string_t args, void* context) { | ||||
|         printf("IRDA is busy. Exit."); | ||||
|         return; | ||||
|     } | ||||
|     IrdaCli irda_cli; | ||||
|     irda_cli.handler = irda_alloc_decoder(); | ||||
|     irda_cli.message_queue = osMessageQueueNew(2, sizeof(IrdaMessage), NULL); | ||||
|     api_hal_irda_rx_irq_init(); | ||||
|     api_hal_irda_rx_irq_set_callback(irda_rx_callback, &irda_cli); | ||||
|  | ||||
|     IrdaWorker* worker = irda_worker_alloc(); | ||||
|     irda_worker_set_context(worker, cli); | ||||
|     irda_worker_start(worker); | ||||
|     irda_worker_set_received_signal_callback(worker, signal_received_callback); | ||||
|  | ||||
|     printf("Receiving IRDA...\r\nPress Ctrl+C to abort\r\n"); | ||||
|     while(!cli_cmd_interrupt_received(cli)) { | ||||
|         IrdaMessage message; | ||||
|         if(osOK == osMessageQueueGet(irda_cli.message_queue, &message, NULL, 50)) { | ||||
|             printf( | ||||
|                 "%s, A:0x%0*lX, C:0x%0*lX%s\r\n", | ||||
|                 irda_get_protocol_name(message.protocol), | ||||
|                 irda_get_protocol_address_length(message.protocol), | ||||
|                 message.address, | ||||
|                 irda_get_protocol_command_length(message.protocol), | ||||
|                 message.command, | ||||
|                 message.repeat ? " R" : ""); | ||||
|         } | ||||
|         delay(50); | ||||
|     } | ||||
|  | ||||
|     api_hal_irda_rx_irq_deinit(); | ||||
|     irda_free_decoder(irda_cli.handler); | ||||
|     osMessageQueueDelete(irda_cli.message_queue); | ||||
|     irda_worker_stop(worker); | ||||
|     irda_worker_free(worker); | ||||
| } | ||||
|  | ||||
| static void irda_cli_print_usage(void) { | ||||
| @@ -63,38 +76,93 @@ static void irda_cli_print_usage(void) { | ||||
|     printf("\r\n"); | ||||
| } | ||||
|  | ||||
| static bool parse_message(const char* str, IrdaMessage* message) { | ||||
|     uint32_t command = 0; | ||||
|     uint32_t address = 0; | ||||
|     char protocol_name[32]; | ||||
|     int parsed = sscanf(str, "%31s %lX %lX", protocol_name, &address, &command); | ||||
|  | ||||
|     if(parsed != 3) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     IrdaProtocol protocol = irda_get_protocol_by_name(protocol_name); | ||||
|  | ||||
|     if(!irda_is_protocol_valid(protocol)) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     message->protocol = protocol; | ||||
|     message->address = address; | ||||
|     message->command = command; | ||||
|     message->repeat = false; | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| static bool parse_signal_raw( | ||||
|     const char* str, | ||||
|     uint32_t* timings, | ||||
|     uint32_t* timings_cnt, | ||||
|     float* duty_cycle, | ||||
|     float* frequency) { | ||||
|     char frequency_str[10]; | ||||
|     char duty_cycle_str[10]; | ||||
|     int parsed = sscanf(str, "RAW F:%9s DC:%9s", frequency_str, duty_cycle_str); | ||||
|     if(parsed != 2) return false; | ||||
|  | ||||
|     *frequency = atoi(frequency_str); | ||||
|     *duty_cycle = (float)atoi(duty_cycle_str) / 100; | ||||
|     str += strlen(frequency_str) + strlen(duty_cycle_str) + 10; | ||||
|  | ||||
|     uint32_t timings_cnt_max = *timings_cnt; | ||||
|     *timings_cnt = 0; | ||||
|  | ||||
|     while(1) { | ||||
|         char timing_str[10]; | ||||
|         for(; *str == ' '; ++str) | ||||
|             ; | ||||
|         if(1 != sscanf(str, "%9s", timing_str)) break; | ||||
|         str += strlen(timing_str); | ||||
|         uint32_t timing = atoi(timing_str); | ||||
|         if(timing <= 0) break; | ||||
|         if(*timings_cnt >= timings_cnt_max) break; | ||||
|         timings[*timings_cnt] = timing; | ||||
|         ++*timings_cnt; | ||||
|     } | ||||
|  | ||||
|     printf("\r\nTransmit:"); | ||||
|     for(size_t i = 0; i < *timings_cnt; ++i) { | ||||
|         printf(" %ld", timings[i]); | ||||
|     } | ||||
|     printf("\r\n"); | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| static void irda_cli_start_ir_tx(Cli* cli, string_t args, void* context) { | ||||
|     if(api_hal_irda_rx_irq_is_busy()) { | ||||
|         printf("IRDA is busy. Exit."); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     uint32_t command = 0; | ||||
|     uint32_t address = 0; | ||||
|     char protocol_name[32]; | ||||
|     int parsed = sscanf(string_get_cstr(args), "%31s %lX %lX", protocol_name, &address, &command); | ||||
|     IrdaMessage message; | ||||
|     const char* str = string_get_cstr(args); | ||||
|     float frequency; | ||||
|     float duty_cycle; | ||||
|     uint32_t* timings = (uint32_t*)furi_alloc(sizeof(uint32_t) * 1000); | ||||
|     uint32_t timings_cnt = 1000; | ||||
|  | ||||
|     if(parsed != 3) { | ||||
|     if(parse_message(str, &message)) { | ||||
|         irda_send(&message, 1); | ||||
|     } else if(parse_signal_raw(str, timings, &timings_cnt, &duty_cycle, &frequency)) { | ||||
|         irda_send_raw_ext(timings, timings_cnt, true, duty_cycle, frequency); | ||||
|     } else { | ||||
|         printf("Wrong arguments.\r\n"); | ||||
|         irda_cli_print_usage(); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     IrdaProtocol protocol = irda_get_protocol_by_name(protocol_name); | ||||
|  | ||||
|     if(!irda_is_protocol_valid(protocol)) { | ||||
|         printf("Unknown protocol.\r\n"); | ||||
|         irda_cli_print_usage(); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     IrdaMessage message = { | ||||
|         .protocol = protocol, | ||||
|         .address = address, | ||||
|         .command = command, | ||||
|         .repeat = false, | ||||
|     }; | ||||
|     irda_send(&message, 1); | ||||
|     free(timings); | ||||
| } | ||||
|  | ||||
| extern "C" void irda_cli_init() { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user