diff options
author | Albert Kharisov <ah@bright-box.com> | 2021-05-18 13:51:00 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-05-18 13:51:00 +0300 |
commit | 3114a2d4b8fc3ec13e5542377d65ac2c922bc7c3 (patch) | |
tree | 4246eba9cc9f44615fb6b6feb03e1619b15739a9 /applications/irda | |
parent | ba0419276e26ba6bf32688e0bf0af4b3c544dd1a (diff) |
[FL-1156, FL-1249] Add IRDA encoder/decoder library (#451)
* Add cscope db generation
* Add api-hal-irda, TIM2: HAL->LL
* Add libirda: pwm decoding
* Universal state machine
* Add irda decoder library
* Move IRDA capture to standalone tool
* Add encoder/decoder samsung32, NEC, fix bugs
* Port current App to new Irda lib
* Fix clang format for test data
* Port IRDA api-hal to f6
Co-authored-by: あく <alleteam@gmail.com>
Diffstat (limited to 'applications/irda')
-rw-r--r--[-rwxr-xr-x] | applications/irda/irda_app.c (renamed from applications/irda/irda.c) | 257 | ||||
-rw-r--r-- | applications/irda/irda_nec.c | 55 | ||||
-rw-r--r-- | applications/irda/irda_nec.h | 4 | ||||
-rw-r--r-- | applications/irda/irda_samsung.c | 47 | ||||
-rw-r--r-- | applications/irda/irda_samsung.h | 4 |
5 files changed, 98 insertions, 269 deletions
diff --git a/applications/irda/irda.c b/applications/irda/irda_app.c index 6944f276..2833fc71 100755..100644 --- a/applications/irda/irda.c +++ b/applications/irda/irda_app.c @@ -4,10 +4,8 @@ #include <input/input.h> #include <cli/cli.h> -#include "irda_nec.h" -#include "irda_samsung.h" -#include "irda_protocols.h" -#include "irda-decoder/irda-decoder.h" +#include <api-hal-irda.h> +#include "irda.h" typedef enum { EventTypeTick, @@ -15,24 +13,21 @@ typedef enum { EventTypeRX, } EventType; -typedef struct { - bool edge; - uint32_t lasted; -} RXValue; +typedef IrdaMessage IrDAPacket; typedef struct { union { InputEvent input; - RXValue rx; + IrDAPacket rx; } value; EventType type; } AppEvent; -typedef struct { - IrDAProtocolType protocol; - uint32_t address; - uint32_t command; -} IrDAPacket; +//typedef struct { +// IrdaProtocol protocol; +// uint32_t address; +// uint32_t command; +//} IrDAPacket; #define IRDA_PACKET_COUNT 8 @@ -88,9 +83,9 @@ void render_carrier(Canvas* canvas, State* state) { void input_carrier(AppEvent* event, State* state) { if(event->value.input.key == InputKeyOk) { if(event->value.input.type == InputTypePress) { - irda_pwm_set(duty_cycles[state->carrier_duty_cycle_id], state->carrier_freq); + api_hal_irda_pwm_set(duty_cycles[state->carrier_duty_cycle_id], state->carrier_freq); } else if(event->value.input.type == InputTypeRelease) { - irda_pwm_stop(); + api_hal_irda_pwm_stop(); } } @@ -117,27 +112,12 @@ void render_packet(Canvas* canvas, State* state) { canvas_draw_str(canvas, 2, 25, "< packet mode"); canvas_draw_str(canvas, 2, 37, "? /\\ \\/ packet"); { - const char* protocol; - - switch(state->packets[state->packet_id].protocol) { - case IRDA_NEC: - protocol = "NEC"; - break; - case IRDA_SAMSUNG: - protocol = "SAMS"; - break; - case IRDA_UNKNOWN: - default: - protocol = "UNK"; - break; - } - - char buf[24]; + char buf[30]; sprintf( buf, "P[%d]: %s 0x%lX 0x%lX", state->packet_id, - protocol, + irda_get_protocol_name(state->packets[state->packet_id].protocol), state->packets[state->packet_id].address, state->packets[state->packet_id].command); canvas_draw_str(canvas, 2, 50, buf); @@ -147,20 +127,12 @@ void render_packet(Canvas* canvas, State* state) { void input_packet(AppEvent* event, State* state) { if(event->value.input.key == InputKeyOk) { if(event->value.input.type == InputTypeShort) { - switch(state->packets[state->packet_id].protocol) { - case IRDA_NEC: - ir_nec_send( - state->packets[state->packet_id].address, - state->packets[state->packet_id].command); - break; - case IRDA_SAMSUNG: - ir_samsung_send( - state->packets[state->packet_id].address, - state->packets[state->packet_id].command); - break; - default: - break; - } + IrdaMessage message = { + .protocol = state->packets[state->packet_id].protocol, + .address = state->packets[state->packet_id].address, + .command = state->packets[state->packet_id].command, + }; + irda_send(&message, 1); } } @@ -201,39 +173,10 @@ static void input_callback(InputEvent* input_event, void* ctx) { osMessageQueuePut(event_queue, &event, 0, 0); } -void irda_timer_capture_callback(void* htim, void* comp_ctx) { - TIM_HandleTypeDef* _htim = (TIM_HandleTypeDef*)htim; - osMessageQueueId_t event_queue = (osMessageQueueId_t)comp_ctx; - - if(_htim->Instance == TIM2) { - AppEvent event; - event.type = EventTypeRX; - uint32_t channel; - - if(_htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { - // falling event - event.value.rx.edge = false; - channel = TIM_CHANNEL_1; - } else if(_htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { - // rising event - event.value.rx.edge = true; - channel = TIM_CHANNEL_2; - } else { - // not our event - return; - } - - event.value.rx.lasted = HAL_TIM_ReadCapturedValue(_htim, channel); - __HAL_TIM_SET_COUNTER(_htim, 0); - - osMessageQueuePut(event_queue, &event, 0, 0); - } -} - void init_packet( State* state, uint8_t index, - IrDAProtocolType protocol, + IrdaProtocol protocol, uint32_t address, uint32_t command) { if(index >= IRDA_PACKET_COUNT) return; @@ -252,18 +195,15 @@ void irda_cli_cmd_rx(string_t args, void* context) { printf("Reading income packets...\r\nPress Ctrl+C to abort\r\n"); while(!exit) { exit = cli_cmd_interrupt_received(app->cli); - osStatus status = osMessageQueueGet(app->cli_ir_rx_queue, &packet, 0, 50); + osStatus status = osMessageQueueGet(app->cli_ir_rx_queue, &packet, 0, 5); if(status == osOK) { - if(packet.protocol == IRDA_NEC) { - printf("NEC "); - } else if(packet.protocol == IRDA_SAMSUNG) { - printf("SAMSUNG "); - } printf( - "Address:0x%02X%02X Command: 0x%02X\r\n", - (uint8_t)(packet.address >> 8), + "%s " + "Address:0x%02X Command: 0x%02X %s\r\n", + irda_get_protocol_name(packet.protocol), (uint8_t)packet.address, - (uint8_t)packet.command); + (uint8_t)packet.command, + packet.repeat ? "R" : ""); } } printf("Interrupt command received"); @@ -275,7 +215,7 @@ void irda_cli_cmd_tx(string_t args, void* context) { furi_assert(context); ValueMutex* state_mutex = context; // Read protocol name - IrDAProtocolType protocol; + IrdaProtocol protocol; string_t protocol_str; string_init(protocol_str); size_t ws = string_search_char(args, ' '); @@ -289,9 +229,9 @@ void irda_cli_cmd_tx(string_t args, void* context) { string_strim(args); } if(!string_cmp_str(protocol_str, "NEC")) { - protocol = IRDA_NEC; + protocol = IrdaProtocolNEC; } else if(!string_cmp_str(protocol_str, "SAMSUNG")) { - protocol = IRDA_SAMSUNG; + protocol = IrdaProtocolSamsung32; } else { printf("Incorrect protocol. Valid protocols: `NEC`, `SAMSUNG`"); string_clear(protocol_str); @@ -320,15 +260,34 @@ void irda_cli_cmd_tx(string_t args, void* context) { printf("IRDA resources busy\r\n"); return; } - if(protocol == IRDA_NEC) { - ir_nec_send(address, command); - } else if(protocol == IRDA_SAMSUNG) { - ir_samsung_send(address, command); - } + + IrdaMessage message = { + .protocol = protocol, + .address = address, + .command = command, + }; + irda_send(&message, 1); release_mutex(state_mutex, state); return; } +typedef struct { + osMessageQueueId_t event_queue; + IrdaHandler* handler; +} IsrContext; + +void irda_rx_callback(void* ctx, bool level, uint32_t duration) { + IsrContext* isr_context = ctx; + const IrdaMessage* message = irda_decode(isr_context->handler, level, duration); + AppEvent event; + event.type = EventTypeRX; + + if(message) { + event.value.rx = *message; + furi_assert(osOK == osMessageQueuePut(isr_context->event_queue, &event, 0, 0)); + } +} + int32_t irda(void* p) { osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(AppEvent), NULL); @@ -347,17 +306,17 @@ int32_t irda(void* p) { irda_app.cli_cmd_is_active = false; for(uint8_t i = 0; i < IRDA_PACKET_COUNT; i++) { - init_packet(&_state, i, IRDA_UNKNOWN, 0, 0); + init_packet(&_state, i, 0, 0, 0); } - init_packet(&_state, 0, IRDA_NEC, 0xFF00, 0x11); - init_packet(&_state, 1, IRDA_NEC, 0xF708, 0x59); - init_packet(&_state, 2, IRDA_NEC, 0xFF00, 0x10); - init_packet(&_state, 3, IRDA_NEC, 0xFF00, 0x15); - init_packet(&_state, 4, IRDA_NEC, 0xFF00, 0x25); - init_packet(&_state, 5, IRDA_SAMSUNG, 0xE0E, 0xF30C); - init_packet(&_state, 6, IRDA_SAMSUNG, 0xE0E, 0xF40D); - init_packet(&_state, 7, IRDA_SAMSUNG, 0xE0E, 0xF50E); + init_packet(&_state, 0, IrdaProtocolNEC, 0x00, 0x11); + init_packet(&_state, 1, IrdaProtocolNEC, 0x08, 0x59); + init_packet(&_state, 2, IrdaProtocolNEC, 0x00, 0x10); + init_packet(&_state, 3, IrdaProtocolNEC, 0x00, 0x15); + init_packet(&_state, 4, IrdaProtocolNEC, 0x00, 0x25); + init_packet(&_state, 5, IrdaProtocolSamsung32, 0x0E, 0x0C); + init_packet(&_state, 6, IrdaProtocolSamsung32, 0x0E, 0x0D); + init_packet(&_state, 7, IrdaProtocolSamsung32, 0x0E, 0x0E); ValueMutex state_mutex; if(!init_mutex(&state_mutex, &_state, sizeof(State))) { @@ -377,13 +336,12 @@ int32_t irda(void* p) { Gui* gui = furi_record_open("gui"); gui_add_view_port(gui, view_port, GuiLayerFullscreen); - // setup irda rx timer - tim_irda_rx_init(); - - // add timer capture interrupt - api_interrupt_add(irda_timer_capture_callback, InterruptTypeTimerCapture, event_queue); - - IrDADecoder* decoder = alloc_decoder(); + IsrContext isr_context = { + .handler = irda_alloc_decoder(), + .event_queue = event_queue, + }; + api_hal_irda_rx_irq_init(); + api_hal_irda_rx_irq_set_callback(irda_rx_callback, &isr_context); AppEvent event; while(1) { @@ -396,7 +354,6 @@ int32_t irda(void* p) { // press events if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyBack) { - api_interrupt_remove(irda_timer_capture_callback, InterruptTypeTimerCapture); release_mutex(&state_mutex, state); // remove all view_ports create by app @@ -404,14 +361,14 @@ int32_t irda(void* p) { view_port_free(view_port); // free decoder - free_decoder(decoder); - delete_mutex(&state_mutex); osMessageQueueDelete(event_queue); osMessageQueueDelete(irda_app.cli_ir_rx_queue); cli_delete_command(irda_app.cli, "ir_rx"); cli_delete_command(irda_app.cli, "ir_tx"); furi_record_close("cli"); + api_hal_irda_rx_irq_deinit(); + irda_free_decoder(isr_context.handler); // exit return 0; @@ -437,58 +394,40 @@ int32_t irda(void* p) { view_port_update(view_port); } else if(event.type == EventTypeRX) { - IrDADecoderOutputData out; - const uint8_t out_data_length = 4; - uint8_t out_data[out_data_length]; - - out.data_length = out_data_length; - out.data = out_data; - - api_hal_light_set(LightRed, event.value.rx.edge ? 0x00 : 0xFF); - - bool decoded = - process_decoder(decoder, event.value.rx.edge, &event.value.rx.lasted, 1, &out); - - if(decoded) { - // save only if we in packet mode - State* state = (State*)acquire_mutex_block(&state_mutex); - IrDAPacket packet; - packet.protocol = IRDA_NEC; - packet.address = out_data[1] << 8 | out_data[0]; - packet.command = out_data[2]; - - if(state->mode_id == 1) { - if(out.protocol == IRDA_NEC) { - printf("P=NEC "); - printf("A=0x%02X%02X ", out_data[1], out_data[0]); - printf("C=0x%02X ", out_data[2]); - if(out.flags & IRDA_REPEAT) { - printf("R"); - } - printf("\r\n"); - // Save packet to state - memcpy( - &(state->packets[state->packet_id]), &packet, sizeof(IrDAPacket)); - } else { - printf("Unknown protocol\r\n"); - } - } - if(irda_app.cli_cmd_is_active) { - // Send decoded packet to cli - osMessageQueuePut(irda_app.cli_ir_rx_queue, &packet, 0, 0); + api_hal_light_set(LightRed, 0xFF); + delay(60); + api_hal_light_set(LightRed, 0xFF); + + // save only if we in packet mode + State* state = (State*)acquire_mutex_block(&state_mutex); + IrDAPacket packet = event.value.rx; + + if(state->mode_id == 1) { + printf("P=%s ", irda_get_protocol_name(packet.protocol)); + printf("A=0x%02lX ", packet.address); + printf("C=0x%02lX ", packet.command); + if(packet.repeat) { + printf("R"); } + printf("\r\n"); + // Save packet to state + memcpy(&(state->packets[state->packet_id]), &packet, sizeof(IrDAPacket)); + } + if(irda_app.cli_cmd_is_active) { + // Send decoded packet to cli + osMessageQueuePut(irda_app.cli_ir_rx_queue, &packet, 0, 0); + } - release_mutex(&state_mutex, state); - view_port_update(view_port); + release_mutex(&state_mutex, state); + view_port_update(view_port); - // blink anyway - api_hal_light_set(LightGreen, 0xFF); - api_hal_light_set(LightGreen, 0x00); - } + // blink anyway + api_hal_light_set(LightGreen, 0xFF); + api_hal_light_set(LightGreen, 0x00); } } else { // event timeout } } -}
\ No newline at end of file +} diff --git a/applications/irda/irda_nec.c b/applications/irda/irda_nec.c deleted file mode 100644 index 72f6230c..00000000 --- a/applications/irda/irda_nec.c +++ /dev/null @@ -1,55 +0,0 @@ -#include <furi.h> -#include <api-hal.h> - -#include "irda_nec.h" -#include "irda_protocols.h" - -void ir_nec_preambula(void) { - // 9ms carrier + 4.5ms pause - irda_pwm_set(NEC_DUTY_CYCLE, NEC_CARRIER_FREQUENCY); - delay_us(9000); - irda_pwm_stop(); - delay_us(4500); -} - -void ir_nec_send_bit(bool bit) { - // 0 is 562.5us carrier + 1687.5us pause - // 1 is 562.5us carrier + 562.5us pause - irda_pwm_set(NEC_DUTY_CYCLE, NEC_CARRIER_FREQUENCY); - delay_us(562.5); - irda_pwm_stop(); - if(bit) { - delay_us(562.5); - } else { - delay_us(1687.5); - } -} - -void ir_nec_send_byte(uint8_t data) { - for(uint8_t i = 0; i < 8; i++) { - ir_nec_send_bit((data & (1 << (i))) != 0); - } -} - -void ir_nec_send(uint16_t addr, uint8_t data) { - // nec protocol is: - // preambula + addr + inverse addr + command + inverse command + bit pulse - // - // oddly enough, my analyzer (https://github.com/ukw100/IRMP) displays the reverse command - // and I don’t know if this is my fault or a feature of the analyzer - // TODO: check the dictionary and check with a known remote - uint8_t nec_packet[4] = {~(uint8_t)addr, ~(uint8_t)(addr >> 8), ~(uint8_t)data, data}; - - osKernelLock(); - __disable_irq(); - - ir_nec_preambula(); - ir_nec_send_byte(nec_packet[0]); - ir_nec_send_byte(nec_packet[1]); - ir_nec_send_byte(nec_packet[2]); - ir_nec_send_byte(nec_packet[3]); - ir_nec_send_bit(1); - - __enable_irq(); - osKernelUnlock(); -}
\ No newline at end of file diff --git a/applications/irda/irda_nec.h b/applications/irda/irda_nec.h deleted file mode 100644 index 5506b1e7..00000000 --- a/applications/irda/irda_nec.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include <furi.h> - -void ir_nec_send(uint16_t addr, uint8_t data);
\ No newline at end of file diff --git a/applications/irda/irda_samsung.c b/applications/irda/irda_samsung.c deleted file mode 100644 index 6be36a2b..00000000 --- a/applications/irda/irda_samsung.c +++ /dev/null @@ -1,47 +0,0 @@ -#include <furi.h> -#include <api-hal.h> - -#include "irda_samsung.h" -#include "irda_protocols.h" - -void ir_samsung_preambula(void) { - irda_pwm_set(SAMSUNG_DUTY_CYCLE, SAMSUNG_CARRIER_FREQUENCY); - delay_us(4500); - irda_pwm_stop(); - delay_us(4500); -} - -void ir_samsung_send_bit(bool bit) { - irda_pwm_set(SAMSUNG_DUTY_CYCLE, SAMSUNG_CARRIER_FREQUENCY); - delay_us(560); - irda_pwm_stop(); - if(bit) { - delay_us(1590); - } else { - delay_us(560); - } -} - -void ir_samsung_send_byte(uint8_t data) { - for(uint8_t i = 0; i < 8; i++) { - ir_samsung_send_bit((data & (1 << (i))) != 0); - } -} - -void ir_samsung_send(uint16_t addr, uint16_t data) { - uint8_t samsung_packet[4] = { - (uint8_t)addr, (uint8_t)(addr >> 8), (uint8_t)data, (uint8_t)(data >> 8)}; - - osKernelLock(); - __disable_irq(); - - ir_samsung_preambula(); - ir_samsung_send_byte(samsung_packet[0]); - ir_samsung_send_byte(samsung_packet[1]); - ir_samsung_send_byte(samsung_packet[2]); - ir_samsung_send_byte(samsung_packet[3]); - ir_samsung_send_bit(0); - - __enable_irq(); - osKernelUnlock(); -}
\ No newline at end of file diff --git a/applications/irda/irda_samsung.h b/applications/irda/irda_samsung.h deleted file mode 100644 index 85f98abe..00000000 --- a/applications/irda/irda_samsung.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include <furi.h> - -void ir_samsung_send(uint16_t addr, uint16_t data);
\ No newline at end of file |