diff --git a/applications/services/gui/modules/button_menu.c b/applications/services/gui/modules/button_menu.c index 60bd160c5..427a3e1ae 100644 --- a/applications/services/gui/modules/button_menu.c +++ b/applications/services/gui/modules/button_menu.c @@ -178,6 +178,47 @@ static void button_menu_process_down(ButtonMenu* button_menu) { true); } +static void button_menu_process_right(ButtonMenu* button_menu) { + furi_assert(button_menu); + + with_view_model( + button_menu->view, + ButtonMenuModel * model, + { + if(ButtonMenuItemArray_size(model->items) > BUTTONS_PER_SCREEN) { + size_t position_candidate = model->position + BUTTONS_PER_SCREEN; + position_candidate -= position_candidate % BUTTONS_PER_SCREEN; + if(position_candidate < (ButtonMenuItemArray_size(model->items))) { + model->position = position_candidate; + } else { + model->position = 0; + } + } + }, + true); +} + +static void button_menu_process_left(ButtonMenu* button_menu) { + furi_assert(button_menu); + + with_view_model( + button_menu->view, + ButtonMenuModel * model, + { + if(ButtonMenuItemArray_size(model->items) > BUTTONS_PER_SCREEN) { + size_t position_candidate; + if(model->position < BUTTONS_PER_SCREEN) { + position_candidate = (ButtonMenuItemArray_size(model->items) - 1); + } else { + position_candidate = model->position - BUTTONS_PER_SCREEN; + }; + position_candidate -= position_candidate % BUTTONS_PER_SCREEN; + model->position = position_candidate; + } + }, + true); +} + static void button_menu_process_ok(ButtonMenu* button_menu, InputType type) { furi_assert(button_menu); @@ -239,6 +280,14 @@ static bool button_menu_view_input_callback(InputEvent* event, void* context) { consumed = true; button_menu_process_down(button_menu); break; + case InputKeyRight: + consumed = true; + button_menu_process_right(button_menu); + break; + case InputKeyLeft: + consumed = true; + button_menu_process_left(button_menu); + break; default: break; } diff --git a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c index 8acb6751b..d67b204f5 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_decoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_decoder.c @@ -1,11 +1,8 @@ +#include "infrared_common_i.h" + +#include #include #include -#include "infrared.h" -#include "infrared_common_i.h" -#include -#include -#include "infrared_i.h" -#include static void infrared_common_decoder_reset_state(InfraredCommonDecoder* decoder); diff --git a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c index 9c774617e..f145a585a 100644 --- a/lib/infrared/encoder_decoder/common/infrared_common_encoder.c +++ b/lib/infrared/encoder_decoder/common/infrared_common_encoder.c @@ -1,10 +1,9 @@ -#include -#include "infrared.h" #include "infrared_common_i.h" -#include -#include -#include "infrared_i.h" -#include + +#include +#include +#include +#include static InfraredStatus infrared_common_encode_bits(InfraredCommonEncoder* encoder, uint32_t* duration, bool* level) { diff --git a/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c b/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c deleted file mode 100644 index 3dd26e9d8..000000000 --- a/lib/infrared/encoder_decoder/common/infrared_common_protocol_defs.c +++ /dev/null @@ -1,140 +0,0 @@ -#include "infrared_common_i.h" -#include "infrared_protocol_defs_i.h" - -const InfraredCommonProtocolSpec protocol_nec = { - .timings = - { - .preamble_mark = INFRARED_NEC_PREAMBLE_MARK, - .preamble_space = INFRARED_NEC_PREAMBLE_SPACE, - .bit1_mark = INFRARED_NEC_BIT1_MARK, - .bit1_space = INFRARED_NEC_BIT1_SPACE, - .bit0_mark = INFRARED_NEC_BIT0_MARK, - .bit0_space = INFRARED_NEC_BIT0_SPACE, - .preamble_tolerance = INFRARED_NEC_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_NEC_BIT_TOLERANCE, - .silence_time = INFRARED_NEC_SILENCE, - .min_split_time = INFRARED_NEC_MIN_SPLIT_TIME, - }, - .databit_len[0] = 42, - .databit_len[1] = 32, - .no_stop_bit = false, - .decode = infrared_common_decode_pdwm, - .encode = infrared_common_encode_pdwm, - .interpret = infrared_decoder_nec_interpret, - .decode_repeat = infrared_decoder_nec_decode_repeat, - .encode_repeat = infrared_encoder_nec_encode_repeat, -}; - -const InfraredCommonProtocolSpec protocol_samsung32 = { - .timings = - { - .preamble_mark = INFRARED_SAMSUNG_PREAMBLE_MARK, - .preamble_space = INFRARED_SAMSUNG_PREAMBLE_SPACE, - .bit1_mark = INFRARED_SAMSUNG_BIT1_MARK, - .bit1_space = INFRARED_SAMSUNG_BIT1_SPACE, - .bit0_mark = INFRARED_SAMSUNG_BIT0_MARK, - .bit0_space = INFRARED_SAMSUNG_BIT0_SPACE, - .preamble_tolerance = INFRARED_SAMSUNG_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_SAMSUNG_BIT_TOLERANCE, - .silence_time = INFRARED_SAMSUNG_SILENCE, - .min_split_time = INFRARED_SAMSUNG_MIN_SPLIT_TIME, - }, - .databit_len[0] = 32, - .no_stop_bit = false, - .decode = infrared_common_decode_pdwm, - .encode = infrared_common_encode_pdwm, - .interpret = infrared_decoder_samsung32_interpret, - .decode_repeat = infrared_decoder_samsung32_decode_repeat, - .encode_repeat = infrared_encoder_samsung32_encode_repeat, -}; - -const InfraredCommonProtocolSpec protocol_rc6 = { - .timings = - { - .preamble_mark = INFRARED_RC6_PREAMBLE_MARK, - .preamble_space = INFRARED_RC6_PREAMBLE_SPACE, - .bit1_mark = INFRARED_RC6_BIT, - .preamble_tolerance = INFRARED_RC6_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_RC6_BIT_TOLERANCE, - .silence_time = INFRARED_RC6_SILENCE, - .min_split_time = INFRARED_RC6_MIN_SPLIT_TIME, - }, - .databit_len[0] = - 1 + 3 + 1 + 8 + - 8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command - .manchester_start_from_space = false, - .decode = infrared_decoder_rc6_decode_manchester, - .encode = infrared_encoder_rc6_encode_manchester, - .interpret = infrared_decoder_rc6_interpret, - .decode_repeat = NULL, - .encode_repeat = NULL, -}; - -const InfraredCommonProtocolSpec protocol_rc5 = { - .timings = - { - .preamble_mark = 0, - .preamble_space = 0, - .bit1_mark = INFRARED_RC5_BIT, - .preamble_tolerance = 0, - .bit_tolerance = INFRARED_RC5_BIT_TOLERANCE, - .silence_time = INFRARED_RC5_SILENCE, - .min_split_time = INFRARED_RC5_MIN_SPLIT_TIME, - }, - .databit_len[0] = 1 + 1 + 1 + 5 + - 6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command - .manchester_start_from_space = true, - .decode = infrared_common_decode_manchester, - .encode = infrared_common_encode_manchester, - .interpret = infrared_decoder_rc5_interpret, - .decode_repeat = NULL, - .encode_repeat = NULL, -}; - -const InfraredCommonProtocolSpec protocol_sirc = { - .timings = - { - .preamble_mark = INFRARED_SIRC_PREAMBLE_MARK, - .preamble_space = INFRARED_SIRC_PREAMBLE_SPACE, - .bit1_mark = INFRARED_SIRC_BIT1_MARK, - .bit1_space = INFRARED_SIRC_BIT1_SPACE, - .bit0_mark = INFRARED_SIRC_BIT0_MARK, - .bit0_space = INFRARED_SIRC_BIT0_SPACE, - .preamble_tolerance = INFRARED_SIRC_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_SIRC_BIT_TOLERANCE, - .silence_time = INFRARED_SIRC_SILENCE, - .min_split_time = INFRARED_SIRC_MIN_SPLIT_TIME, - }, - .databit_len[0] = 20, - .databit_len[1] = 15, - .databit_len[2] = 12, - .no_stop_bit = true, - .decode = infrared_common_decode_pdwm, - .encode = infrared_common_encode_pdwm, - .interpret = infrared_decoder_sirc_interpret, - .decode_repeat = NULL, - .encode_repeat = infrared_encoder_sirc_encode_repeat, -}; - -const InfraredCommonProtocolSpec protocol_kaseikyo = { - .timings = - { - .preamble_mark = INFRARED_KASEIKYO_PREAMBLE_MARK, - .preamble_space = INFRARED_KASEIKYO_PREAMBLE_SPACE, - .bit1_mark = INFRARED_KASEIKYO_BIT1_MARK, - .bit1_space = INFRARED_KASEIKYO_BIT1_SPACE, - .bit0_mark = INFRARED_KASEIKYO_BIT0_MARK, - .bit0_space = INFRARED_KASEIKYO_BIT0_SPACE, - .preamble_tolerance = INFRARED_KASEIKYO_PREAMBLE_TOLERANCE, - .bit_tolerance = INFRARED_KASEIKYO_BIT_TOLERANCE, - .silence_time = INFRARED_KASEIKYO_SILENCE, - .min_split_time = INFRARED_KASEIKYO_MIN_SPLIT_TIME, - }, - .databit_len[0] = 48, - .no_stop_bit = false, - .decode = infrared_common_decode_pdwm, - .encode = infrared_common_encode_pdwm, - .interpret = infrared_decoder_kaseikyo_interpret, - .decode_repeat = NULL, - .encode_repeat = NULL, -}; diff --git a/lib/infrared/encoder_decoder/infrared.c b/lib/infrared/encoder_decoder/infrared.c index 2c5ef0fff..fcfc5da2b 100644 --- a/lib/infrared/encoder_decoder/infrared.c +++ b/lib/infrared/encoder_decoder/infrared.c @@ -1,13 +1,16 @@ #include "infrared.h" -#include -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include + #include -#include -#include "infrared_i.h" -#include +#include +#include +#include + +#include "nec/infrared_protocol_nec.h" +#include "samsung/infrared_protocol_samsung.h" +#include "rc5/infrared_protocol_rc5.h" +#include "rc6/infrared_protocol_rc6.h" +#include "sirc/infrared_protocol_sirc.h" +#include "kaseikyo/infrared_protocol_kaseikyo.h" typedef struct { InfraredAlloc alloc; @@ -36,7 +39,7 @@ struct InfraredEncoderHandler { typedef struct { InfraredEncoders encoder; InfraredDecoders decoder; - InfraredGetProtocolSpec get_protocol_spec; + InfraredGetProtocolVariant get_protocol_variant; } InfraredEncoderDecoder; static const InfraredEncoderDecoder infrared_encoder_decoder[] = { @@ -52,7 +55,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_nec_encode, .reset = infrared_encoder_nec_reset, .free = infrared_encoder_nec_free}, - .get_protocol_spec = infrared_nec_get_spec, + .get_protocol_variant = infrared_protocol_nec_get_variant, }, { .decoder = @@ -66,7 +69,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_samsung32_encode, .reset = infrared_encoder_samsung32_reset, .free = infrared_encoder_samsung32_free}, - .get_protocol_spec = infrared_samsung32_get_spec, + .get_protocol_variant = infrared_protocol_samsung32_get_variant, }, { .decoder = @@ -80,7 +83,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_rc5_encode, .reset = infrared_encoder_rc5_reset, .free = infrared_encoder_rc5_free}, - .get_protocol_spec = infrared_rc5_get_spec, + .get_protocol_variant = infrared_protocol_rc5_get_variant, }, { .decoder = @@ -94,7 +97,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_rc6_encode, .reset = infrared_encoder_rc6_reset, .free = infrared_encoder_rc6_free}, - .get_protocol_spec = infrared_rc6_get_spec, + .get_protocol_variant = infrared_protocol_rc6_get_variant, }, { .decoder = @@ -108,7 +111,7 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_sirc_encode, .reset = infrared_encoder_sirc_reset, .free = infrared_encoder_sirc_free}, - .get_protocol_spec = infrared_sirc_get_spec, + .get_protocol_variant = infrared_protocol_sirc_get_variant, }, { .decoder = @@ -122,13 +125,12 @@ static const InfraredEncoderDecoder infrared_encoder_decoder[] = { .encode = infrared_encoder_kaseikyo_encode, .reset = infrared_encoder_kaseikyo_reset, .free = infrared_encoder_kaseikyo_free}, - .get_protocol_spec = infrared_kaseikyo_get_spec, + .get_protocol_variant = infrared_protocol_kaseikyo_get_variant, }, }; static int infrared_find_index_by_protocol(InfraredProtocol protocol); -static const InfraredProtocolSpecification* - infrared_get_spec_by_protocol(InfraredProtocol protocol); +static const InfraredProtocolVariant* infrared_get_variant_by_protocol(InfraredProtocol protocol); const InfraredMessage* infrared_decode(InfraredDecoderHandler* handler, bool level, uint32_t duration) { @@ -224,7 +226,7 @@ void infrared_free_encoder(InfraredEncoderHandler* handler) { static int infrared_find_index_by_protocol(InfraredProtocol protocol) { for(size_t i = 0; i < COUNT_OF(infrared_encoder_decoder); ++i) { - if(infrared_encoder_decoder[i].get_protocol_spec(protocol)) { + if(infrared_encoder_decoder[i].get_protocol_variant(protocol)) { return i; } } @@ -282,34 +284,37 @@ InfraredProtocol infrared_get_protocol_by_name(const char* protocol_name) { return InfraredProtocolUnknown; } -static const InfraredProtocolSpecification* - infrared_get_spec_by_protocol(InfraredProtocol protocol) { +static const InfraredProtocolVariant* infrared_get_variant_by_protocol(InfraredProtocol protocol) { int index = infrared_find_index_by_protocol(protocol); - const InfraredProtocolSpecification* spec = NULL; + const InfraredProtocolVariant* variant = NULL; if(index >= 0) { - spec = infrared_encoder_decoder[index].get_protocol_spec(protocol); + variant = infrared_encoder_decoder[index].get_protocol_variant(protocol); } - furi_assert(spec); - return spec; + furi_assert(variant); + return variant; } const char* infrared_get_protocol_name(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->name; + return infrared_get_variant_by_protocol(protocol)->name; } uint8_t infrared_get_protocol_address_length(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->address_length; + return infrared_get_variant_by_protocol(protocol)->address_length; } uint8_t infrared_get_protocol_command_length(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->command_length; + return infrared_get_variant_by_protocol(protocol)->command_length; } uint32_t infrared_get_protocol_frequency(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->frequency; + return infrared_get_variant_by_protocol(protocol)->frequency; } float infrared_get_protocol_duty_cycle(InfraredProtocol protocol) { - return infrared_get_spec_by_protocol(protocol)->duty_cycle; + return infrared_get_variant_by_protocol(protocol)->duty_cycle; +} + +size_t infrared_get_protocol_min_repeat_count(InfraredProtocol protocol) { + return infrared_get_variant_by_protocol(protocol)->repeat_count; } diff --git a/lib/infrared/encoder_decoder/infrared.h b/lib/infrared/encoder_decoder/infrared.h index 2c76645ff..3ab46cbbf 100644 --- a/lib/infrared/encoder_decoder/infrared.h +++ b/lib/infrared/encoder_decoder/infrared.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #ifdef __cplusplus @@ -201,6 +202,15 @@ uint32_t infrared_get_protocol_frequency(InfraredProtocol protocol); */ float infrared_get_protocol_duty_cycle(InfraredProtocol protocol); +/** + * Get the minimum count of signal repeats for the selected protocol + * + * \param[in] protocol - protocol to get the repeat count from + * + * \return repeat count + */ +size_t infrared_get_protocol_min_repeat_count(InfraredProtocol protocol); + #ifdef __cplusplus } #endif diff --git a/lib/infrared/encoder_decoder/infrared_i.h b/lib/infrared/encoder_decoder/infrared_i.h index 3a645cede..3efc41cd6 100644 --- a/lib/infrared/encoder_decoder/infrared_i.h +++ b/lib/infrared/encoder_decoder/infrared_i.h @@ -22,9 +22,10 @@ typedef struct { uint8_t command_length; uint32_t frequency; float duty_cycle; -} InfraredProtocolSpecification; + size_t repeat_count; +} InfraredProtocolVariant; -typedef const InfraredProtocolSpecification* (*InfraredGetProtocolSpec)(InfraredProtocol protocol); +typedef const InfraredProtocolVariant* (*InfraredGetProtocolVariant)(InfraredProtocol protocol); typedef void* (*InfraredAlloc)(void); typedef void (*InfraredFree)(void*); diff --git a/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h b/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h deleted file mode 100644 index 6146f7b4e..000000000 --- a/lib/infrared/encoder_decoder/infrared_protocol_defs_i.h +++ /dev/null @@ -1,320 +0,0 @@ -#pragma once - -#include -#include -#include -#include "infrared.h" -#include "common/infrared_common_i.h" - -/*************************************************************************************************** -* NEC protocol description -* https://radioparty.ru/manuals/encyclopedia/213-ircontrol?start=1 -**************************************************************************************************** -* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Stop -* mark space Modulation up to period repeat repeat bit -* mark space -* -* 9000 4500 32 bit + stop bit ...110000 9000 2250 -* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ _ -* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ____________ ___ -* -***************************************************************************************************/ - -#define INFRARED_NEC_PREAMBLE_MARK 9000 -#define INFRARED_NEC_PREAMBLE_SPACE 4500 -#define INFRARED_NEC_BIT1_MARK 560 -#define INFRARED_NEC_BIT1_SPACE 1690 -#define INFRARED_NEC_BIT0_MARK 560 -#define INFRARED_NEC_BIT0_SPACE 560 -#define INFRARED_NEC_REPEAT_PERIOD 110000 -#define INFRARED_NEC_SILENCE INFRARED_NEC_REPEAT_PERIOD -#define INFRARED_NEC_MIN_SPLIT_TIME INFRARED_NEC_REPEAT_PAUSE_MIN -#define INFRARED_NEC_REPEAT_PAUSE_MIN 4000 -#define INFRARED_NEC_REPEAT_PAUSE_MAX 150000 -#define INFRARED_NEC_REPEAT_MARK 9000 -#define INFRARED_NEC_REPEAT_SPACE 2250 -#define INFRARED_NEC_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_NEC_BIT_TOLERANCE 120 // us - -void* infrared_decoder_nec_alloc(void); -void infrared_decoder_nec_reset(void* decoder); -void infrared_decoder_nec_free(void* decoder); -InfraredMessage* infrared_decoder_nec_check_ready(void* decoder); -InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_nec_alloc(void); -InfraredStatus infrared_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level); -void infrared_encoder_nec_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_nec_free(void* encoder_ptr); -bool infrared_decoder_nec_interpret(InfraredCommonDecoder* decoder); -InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder); -InfraredStatus infrared_encoder_nec_encode_repeat( - InfraredCommonEncoder* encoder, - uint32_t* duration, - bool* level); -const InfraredProtocolSpecification* infrared_nec_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_nec; - -/*************************************************************************************************** -* SAMSUNG32 protocol description -* https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG -**************************************************************************************************** -* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Bit1 Stop -* mark space Modulation repeat repeat bit -* mark space -* -* 4500 4500 32 bit + stop bit 40000/100000 4500 4500 -* __________ _ _ _ _ _ _ _ _ _ _ _ ___________ _ _ -* _ __________ __ _ __ __ __ _ _ __ __ _ ________________ ____________ ____ ___ -* -***************************************************************************************************/ - -#define INFRARED_SAMSUNG_PREAMBLE_MARK 4500 -#define INFRARED_SAMSUNG_PREAMBLE_SPACE 4500 -#define INFRARED_SAMSUNG_BIT1_MARK 550 -#define INFRARED_SAMSUNG_BIT1_SPACE 1650 -#define INFRARED_SAMSUNG_BIT0_MARK 550 -#define INFRARED_SAMSUNG_BIT0_SPACE 550 -#define INFRARED_SAMSUNG_REPEAT_PAUSE_MIN 30000 -#define INFRARED_SAMSUNG_REPEAT_PAUSE1 46000 -#define INFRARED_SAMSUNG_REPEAT_PAUSE2 97000 -/* Samsung silence have to be greater than REPEAT MAX - * otherwise there can be problems during unit tests parsing - * of some data. Real tolerances we don't know, but in real life - * silence time should be greater than max repeat time. This is - * because of similar preambule timings for repeat and first messages. */ -#define INFRARED_SAMSUNG_MIN_SPLIT_TIME 5000 -#define INFRARED_SAMSUNG_SILENCE 145000 -#define INFRARED_SAMSUNG_REPEAT_PAUSE_MAX 140000 -#define INFRARED_SAMSUNG_REPEAT_MARK 4500 -#define INFRARED_SAMSUNG_REPEAT_SPACE 4500 -#define INFRARED_SAMSUNG_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_SAMSUNG_BIT_TOLERANCE 120 // us - -void* infrared_decoder_samsung32_alloc(void); -void infrared_decoder_samsung32_reset(void* decoder); -void infrared_decoder_samsung32_free(void* decoder); -InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx); -InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); -InfraredStatus - infrared_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level); -void infrared_encoder_samsung32_reset(void* encoder_ptr, const InfraredMessage* message); -void* infrared_encoder_samsung32_alloc(void); -void infrared_encoder_samsung32_free(void* encoder_ptr); -bool infrared_decoder_samsung32_interpret(InfraredCommonDecoder* decoder); -InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* decoder); -InfraredStatus infrared_encoder_samsung32_encode_repeat( - InfraredCommonEncoder* encoder, - uint32_t* duration, - bool* level); -const InfraredProtocolSpecification* infrared_samsung32_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_samsung32; - -/*************************************************************************************************** -* RC6 protocol description -* https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A -**************************************************************************************************** -* Preamble Manchester/biphase Silence -* mark/space Modulation -* -* 2666 889 444/888 - bit (x2 for toggle bit) 2666 -* -* ________ __ __ __ __ ____ __ __ __ __ __ __ __ __ -* _ _________ ____ __ __ ____ __ __ __ __ __ __ __ __ _______________ -* | 1 | 0 | 0 | 0 | 0 | ... | ... | | -* s m2 m1 m0 T address (MSB) command (MSB) -* -* s - start bit (always 1) -* m0-2 - mode (000 for RC6) -* T - toggle bit, twice longer -* address - 8 bit -* command - 8 bit -***************************************************************************************************/ - -#define INFRARED_RC6_CARRIER_FREQUENCY 36000 -#define INFRARED_RC6_DUTY_CYCLE 0.33 - -#define INFRARED_RC6_PREAMBLE_MARK 2666 -#define INFRARED_RC6_PREAMBLE_SPACE 889 -#define INFRARED_RC6_BIT 444 // half of time-quant for 1 bit -#define INFRARED_RC6_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_RC6_BIT_TOLERANCE 120 // us -/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ -#define INFRARED_RC6_SILENCE (2700 * 10) -#define INFRARED_RC6_MIN_SPLIT_TIME 2700 - -void* infrared_decoder_rc6_alloc(void); -void infrared_decoder_rc6_reset(void* decoder); -void infrared_decoder_rc6_free(void* decoder); -InfraredMessage* infrared_decoder_rc6_check_ready(void* ctx); -InfraredMessage* infrared_decoder_rc6_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_rc6_alloc(void); -void infrared_encoder_rc6_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_rc6_free(void* decoder); -InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); -bool infrared_decoder_rc6_interpret(InfraredCommonDecoder* decoder); -InfraredStatus infrared_decoder_rc6_decode_manchester( - InfraredCommonDecoder* decoder, - bool level, - uint32_t timing); -InfraredStatus infrared_encoder_rc6_encode_manchester( - InfraredCommonEncoder* encoder_ptr, - uint32_t* duration, - bool* polarity); -const InfraredProtocolSpecification* infrared_rc6_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_rc6; - -/*************************************************************************************************** -* RC5 protocol description -* https://www.mikrocontroller.net/articles/IRMP_-_english#RC5_.2B_RC5X -**************************************************************************************************** -* Manchester/biphase -* Modulation -* -* 888/1776 - bit (x2 for toggle bit) -* -* __ ____ __ __ __ __ __ __ __ __ -* __ __ ____ __ __ __ __ __ __ __ _ -* | 1 | 1 | 0 | ... | ... | -* s si T address (MSB) command (MSB) -* -* Note: manchester starts from space timing, so it have to be handled properly -* s - start bit (always 1) -* si - RC5: start bit (always 1), RC5X - 7-th bit of address (in our case always 0) -* T - toggle bit, change it's value every button press -* address - 5 bit -* command - 6/7 bit -***************************************************************************************************/ - -#define INFRARED_RC5_CARRIER_FREQUENCY 36000 -#define INFRARED_RC5_DUTY_CYCLE 0.33 - -#define INFRARED_RC5_PREAMBLE_MARK 0 -#define INFRARED_RC5_PREAMBLE_SPACE 0 -#define INFRARED_RC5_BIT 888 // half of time-quant for 1 bit -#define INFRARED_RC5_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_RC5_BIT_TOLERANCE 120 // us -/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ -#define INFRARED_RC5_SILENCE (2700 * 10) -#define INFRARED_RC5_MIN_SPLIT_TIME 2700 - -void* infrared_decoder_rc5_alloc(void); -void infrared_decoder_rc5_reset(void* decoder); -void infrared_decoder_rc5_free(void* decoder); -InfraredMessage* infrared_decoder_rc5_check_ready(void* ctx); -InfraredMessage* infrared_decoder_rc5_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_rc5_alloc(void); -void infrared_encoder_rc5_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_rc5_free(void* decoder); -InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); -bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder); -const InfraredProtocolSpecification* infrared_rc5_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_rc5; - -/*************************************************************************************************** -* Sony SIRC protocol description -* https://www.sbprojects.net/knowledge/ir/sirc.php -* http://picprojects.org.uk/ -**************************************************************************************************** -* Preamble Preamble Pulse Width Modulation Pause Entirely repeat -* mark space up to period message.. -* -* 2400 600 12/15/20 bits (600,1200) ...45000 2400 600 -* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ __________ _ _ -* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ____________________ __________ _ -* | command | address | -* SIRC | 7b LSB | 5b LSB | -* SIRC15 | 7b LSB | 8b LSB | -* SIRC20 | 7b LSB | 13b LSB | -* -* No way to determine either next message is repeat or not, -* so recognize only fact message received. Sony remotes always send at least 3 messages. -* Assume 8 last extended bits for SIRC20 are address bits. -***************************************************************************************************/ - -#define INFRARED_SIRC_CARRIER_FREQUENCY 40000 -#define INFRARED_SIRC_DUTY_CYCLE 0.33 -#define INFRARED_SIRC_PREAMBLE_MARK 2400 -#define INFRARED_SIRC_PREAMBLE_SPACE 600 -#define INFRARED_SIRC_BIT1_MARK 1200 -#define INFRARED_SIRC_BIT1_SPACE 600 -#define INFRARED_SIRC_BIT0_MARK 600 -#define INFRARED_SIRC_BIT0_SPACE 600 -#define INFRARED_SIRC_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_SIRC_BIT_TOLERANCE 120 // us -#define INFRARED_SIRC_SILENCE 10000 -#define INFRARED_SIRC_MIN_SPLIT_TIME (INFRARED_SIRC_SILENCE - 1000) -#define INFRARED_SIRC_REPEAT_PERIOD 45000 - -void* infrared_decoder_sirc_alloc(void); -void infrared_decoder_sirc_reset(void* decoder); -InfraredMessage* infrared_decoder_sirc_check_ready(void* decoder); -uint32_t infrared_decoder_sirc_get_timeout(void* decoder); -void infrared_decoder_sirc_free(void* decoder); -InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_sirc_alloc(void); -void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_sirc_free(void* decoder); -InfraredStatus infrared_encoder_sirc_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); -bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder); -const InfraredProtocolSpecification* infrared_sirc_get_spec(InfraredProtocol protocol); -InfraredStatus infrared_encoder_sirc_encode_repeat( - InfraredCommonEncoder* encoder, - uint32_t* duration, - bool* level); - -extern const InfraredCommonProtocolSpec protocol_sirc; - -/*************************************************************************************************** -* Kaseikyo protocol description -* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_Kaseikyo.hpp -**************************************************************************************************** -* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble -* mark space Modulation up to period repeat repeat -* mark space -* -* 3360 1665 48 bit ...130000 3456 1728 -* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ -* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________ -* -***************************************************************************************************/ - -#define INFRARED_KASEIKYO_UNIT 432 -#define INFRARED_KASEIKYO_PREAMBLE_MARK (8 * INFRARED_KASEIKYO_UNIT) -#define INFRARED_KASEIKYO_PREAMBLE_SPACE (4 * INFRARED_KASEIKYO_UNIT) -#define INFRARED_KASEIKYO_BIT1_MARK INFRARED_KASEIKYO_UNIT -#define INFRARED_KASEIKYO_BIT1_SPACE (3 * INFRARED_KASEIKYO_UNIT) -#define INFRARED_KASEIKYO_BIT0_MARK INFRARED_KASEIKYO_UNIT -#define INFRARED_KASEIKYO_BIT0_SPACE INFRARED_KASEIKYO_UNIT -#define INFRARED_KASEIKYO_REPEAT_PERIOD 130000 -#define INFRARED_KASEIKYO_SILENCE INFRARED_KASEIKYO_REPEAT_PERIOD -#define INFRARED_KASEIKYO_MIN_SPLIT_TIME INFRARED_KASEIKYO_REPEAT_PAUSE_MIN -#define INFRARED_KASEIKYO_REPEAT_PAUSE_MIN 4000 -#define INFRARED_KASEIKYO_REPEAT_PAUSE_MAX 150000 -#define INFRARED_KASEIKYO_REPEAT_MARK INFRARED_KASEIKYO_PREAMBLE_MARK -#define INFRARED_KASEIKYO_REPEAT_SPACE (INFRARED_KASEIKYO_REPEAT_PERIOD - 56000) -#define INFRARED_KASEIKYO_PREAMBLE_TOLERANCE 200 // us -#define INFRARED_KASEIKYO_BIT_TOLERANCE 120 // us - -void* infrared_decoder_kaseikyo_alloc(void); -void infrared_decoder_kaseikyo_reset(void* decoder); -void infrared_decoder_kaseikyo_free(void* decoder); -InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* decoder); -InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration); -void* infrared_encoder_kaseikyo_alloc(void); -InfraredStatus - infrared_encoder_kaseikyo_encode(void* encoder_ptr, uint32_t* duration, bool* level); -void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message); -void infrared_encoder_kaseikyo_free(void* encoder_ptr); -bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder); -InfraredStatus infrared_decoder_kaseikyo_decode_repeat(InfraredCommonDecoder* decoder); -InfraredStatus infrared_encoder_kaseikyo_encode_repeat( - InfraredCommonEncoder* encoder, - uint32_t* duration, - bool* level); -const InfraredProtocolSpecification* infrared_kaseikyo_get_spec(InfraredProtocol protocol); - -extern const InfraredCommonProtocolSpec protocol_kaseikyo; diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c index b8db81d7e..e85a89652 100644 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_decoder_kaseikyo.c @@ -1,9 +1,5 @@ -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_kaseikyo_i.h" +#include InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* ctx) { return infrared_common_decoder_check_ready(ctx); @@ -38,7 +34,7 @@ bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder) { } void* infrared_decoder_kaseikyo_alloc(void) { - return infrared_common_decoder_alloc(&protocol_kaseikyo); + return infrared_common_decoder_alloc(&infrared_protocol_kaseikyo); } InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration) { diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c index 5814c7255..618fc3bab 100644 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_encoder_kaseikyo.c @@ -1,9 +1,5 @@ +#include "infrared_protocol_kaseikyo_i.h" #include -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message) { furi_assert(encoder_ptr); @@ -32,7 +28,7 @@ void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* m } void* infrared_encoder_kaseikyo_alloc(void) { - return infrared_common_encoder_alloc(&protocol_kaseikyo); + return infrared_common_encoder_alloc(&infrared_protocol_kaseikyo); } void infrared_encoder_kaseikyo_free(void* encoder_ptr) { diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c deleted file mode 100644 index 87c86c7b3..000000000 --- a/lib/infrared/encoder_decoder/kaseikyo/infrared_kaseikyo_spec.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_kaseikyo_protocol_specification = { - .name = "Kaseikyo", - .address_length = 26, - .command_length = 10, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_kaseikyo_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolKaseikyo) - return &infrared_kaseikyo_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c new file mode 100644 index 000000000..0c61be3bf --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.c @@ -0,0 +1,40 @@ +#include "infrared_protocol_kaseikyo_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_kaseikyo = { + .timings = + { + .preamble_mark = INFRARED_KASEIKYO_PREAMBLE_MARK, + .preamble_space = INFRARED_KASEIKYO_PREAMBLE_SPACE, + .bit1_mark = INFRARED_KASEIKYO_BIT1_MARK, + .bit1_space = INFRARED_KASEIKYO_BIT1_SPACE, + .bit0_mark = INFRARED_KASEIKYO_BIT0_MARK, + .bit0_space = INFRARED_KASEIKYO_BIT0_SPACE, + .preamble_tolerance = INFRARED_KASEIKYO_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_KASEIKYO_BIT_TOLERANCE, + .silence_time = INFRARED_KASEIKYO_SILENCE, + .min_split_time = INFRARED_KASEIKYO_MIN_SPLIT_TIME, + }, + .databit_len[0] = 48, + .no_stop_bit = false, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_kaseikyo_interpret, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_kaseikyo = { + .name = "Kaseikyo", + .address_length = 26, + .command_length = 10, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_KASEIKYO_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_kaseikyo_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolKaseikyo) + return &infrared_protocol_variant_kaseikyo; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h new file mode 100644 index 000000000..61ff0ca1c --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* Kaseikyo protocol description +* https://github.com/Arduino-IRremote/Arduino-IRremote/blob/master/src/ir_Kaseikyo.hpp +**************************************************************************************************** +* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble +* mark space Modulation up to period repeat repeat +* mark space +* +* 3360 1665 48 bit ...130000 3456 1728 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ___________ +* +***************************************************************************************************/ + +void* infrared_decoder_kaseikyo_alloc(void); +void infrared_decoder_kaseikyo_reset(void* decoder); +void infrared_decoder_kaseikyo_free(void* decoder); +InfraredMessage* infrared_decoder_kaseikyo_check_ready(void* decoder); +InfraredMessage* infrared_decoder_kaseikyo_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_kaseikyo_alloc(void); +InfraredStatus + infrared_encoder_kaseikyo_encode(void* encoder_ptr, uint32_t* duration, bool* level); +void infrared_encoder_kaseikyo_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_kaseikyo_free(void* encoder_ptr); + +const InfraredProtocolVariant* infrared_protocol_kaseikyo_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h new file mode 100644 index 000000000..bee116c4d --- /dev/null +++ b/lib/infrared/encoder_decoder/kaseikyo/infrared_protocol_kaseikyo_i.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_KASEIKYO_UNIT 432 +#define INFRARED_KASEIKYO_PREAMBLE_MARK (8 * INFRARED_KASEIKYO_UNIT) +#define INFRARED_KASEIKYO_PREAMBLE_SPACE (4 * INFRARED_KASEIKYO_UNIT) +#define INFRARED_KASEIKYO_BIT1_MARK INFRARED_KASEIKYO_UNIT +#define INFRARED_KASEIKYO_BIT1_SPACE (3 * INFRARED_KASEIKYO_UNIT) +#define INFRARED_KASEIKYO_BIT0_MARK INFRARED_KASEIKYO_UNIT +#define INFRARED_KASEIKYO_BIT0_SPACE INFRARED_KASEIKYO_UNIT +#define INFRARED_KASEIKYO_REPEAT_PERIOD 130000 +#define INFRARED_KASEIKYO_SILENCE INFRARED_KASEIKYO_REPEAT_PERIOD +#define INFRARED_KASEIKYO_MIN_SPLIT_TIME INFRARED_KASEIKYO_REPEAT_PAUSE_MIN +#define INFRARED_KASEIKYO_REPEAT_PAUSE_MIN 4000 +#define INFRARED_KASEIKYO_REPEAT_PAUSE_MAX 150000 +#define INFRARED_KASEIKYO_REPEAT_COUNT_MIN 1 +#define INFRARED_KASEIKYO_REPEAT_MARK INFRARED_KASEIKYO_PREAMBLE_MARK +#define INFRARED_KASEIKYO_REPEAT_SPACE (INFRARED_KASEIKYO_REPEAT_PERIOD - 56000) +#define INFRARED_KASEIKYO_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_KASEIKYO_BIT_TOLERANCE 120 // us + +extern const InfraredCommonProtocolSpec infrared_protocol_kaseikyo; + +bool infrared_decoder_kaseikyo_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_kaseikyo_decode_repeat(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_kaseikyo_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); diff --git a/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c b/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c index 3ad14a7ab..91384d702 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_decoder_nec.c @@ -1,10 +1,5 @@ -#include "common/infrared_common_i.h" -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_nec_i.h" +#include InfraredMessage* infrared_decoder_nec_check_ready(void* ctx) { return infrared_common_decoder_check_ready(ctx); @@ -86,7 +81,7 @@ InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder } void* infrared_decoder_nec_alloc(void) { - return infrared_common_decoder_alloc(&protocol_nec); + return infrared_common_decoder_alloc(&infrared_protocol_nec); } InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration) { diff --git a/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c b/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c index d0039c330..87f815142 100644 --- a/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c +++ b/lib/infrared/encoder_decoder/nec/infrared_encoder_nec.c @@ -1,10 +1,7 @@ +#include "infrared_protocol_nec_i.h" + +#include #include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include static const uint32_t repeat_timings[] = { INFRARED_NEC_REPEAT_PERIOD - INFRARED_NEC_REPEAT_MARK - INFRARED_NEC_REPEAT_SPACE - @@ -81,7 +78,7 @@ InfraredStatus infrared_encoder_nec_encode_repeat( } void* infrared_encoder_nec_alloc(void) { - return infrared_common_encoder_alloc(&protocol_nec); + return infrared_common_encoder_alloc(&infrared_protocol_nec); } void infrared_encoder_nec_free(void* encoder_ptr) { diff --git a/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c b/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c deleted file mode 100644 index 16cab8b5f..000000000 --- a/lib/infrared/encoder_decoder/nec/infrared_nec_spec.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_nec_protocol_specification = { - .name = "NEC", - .address_length = 8, - .command_length = 8, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_necext_protocol_specification = { - .name = "NECext", - .address_length = 16, - .command_length = 16, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_nec42_protocol_specification = { - .name = "NEC42", - .address_length = 13, - .command_length = 8, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_nec42ext_protocol_specification = { - .name = "NEC42ext", - .address_length = 26, - .command_length = 16, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_nec_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolNEC) - return &infrared_nec_protocol_specification; - else if(protocol == InfraredProtocolNECext) - return &infrared_necext_protocol_specification; - else if(protocol == InfraredProtocolNEC42) - return &infrared_nec42_protocol_specification; - else if(protocol == InfraredProtocolNEC42ext) - return &infrared_nec42ext_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c new file mode 100644 index 000000000..3444f78b6 --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.c @@ -0,0 +1,74 @@ +#include "infrared_protocol_nec_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_nec = { + .timings = + { + .preamble_mark = INFRARED_NEC_PREAMBLE_MARK, + .preamble_space = INFRARED_NEC_PREAMBLE_SPACE, + .bit1_mark = INFRARED_NEC_BIT1_MARK, + .bit1_space = INFRARED_NEC_BIT1_SPACE, + .bit0_mark = INFRARED_NEC_BIT0_MARK, + .bit0_space = INFRARED_NEC_BIT0_SPACE, + .preamble_tolerance = INFRARED_NEC_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_NEC_BIT_TOLERANCE, + .silence_time = INFRARED_NEC_SILENCE, + .min_split_time = INFRARED_NEC_MIN_SPLIT_TIME, + }, + .databit_len[0] = 42, + .databit_len[1] = 32, + .no_stop_bit = false, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_nec_interpret, + .decode_repeat = infrared_decoder_nec_decode_repeat, + .encode_repeat = infrared_encoder_nec_encode_repeat, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_nec = { + .name = "NEC", + .address_length = 8, + .command_length = 8, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_necext = { + .name = "NECext", + .address_length = 16, + .command_length = 16, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_nec42 = { + .name = "NEC42", + .address_length = 13, + .command_length = 8, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_nec42ext = { + .name = "NEC42ext", + .address_length = 26, + .command_length = 16, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_NEC_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_nec_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolNEC) + return &infrared_protocol_variant_nec; + else if(protocol == InfraredProtocolNECext) + return &infrared_protocol_variant_necext; + else if(protocol == InfraredProtocolNEC42) + return &infrared_protocol_variant_nec42; + else if(protocol == InfraredProtocolNEC42ext) + return &infrared_protocol_variant_nec42ext; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h new file mode 100644 index 000000000..559e31fda --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec.h @@ -0,0 +1,30 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* NEC protocol description +* https://radioparty.ru/manuals/encyclopedia/213-ircontrol?start=1 +**************************************************************************************************** +* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Stop +* mark space Modulation up to period repeat repeat bit +* mark space +* +* 9000 4500 32 bit + stop bit ...110000 9000 2250 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ ___________ _ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ________________ ____________ ___ +* +***************************************************************************************************/ + +void* infrared_decoder_nec_alloc(void); +void infrared_decoder_nec_reset(void* decoder); +void infrared_decoder_nec_free(void* decoder); +InfraredMessage* infrared_decoder_nec_check_ready(void* decoder); +InfraredMessage* infrared_decoder_nec_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_nec_alloc(void); +InfraredStatus infrared_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level); +void infrared_encoder_nec_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_nec_free(void* encoder_ptr); + +const InfraredProtocolVariant* infrared_protocol_nec_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h new file mode 100644 index 000000000..05df1f474 --- /dev/null +++ b/lib/infrared/encoder_decoder/nec/infrared_protocol_nec_i.h @@ -0,0 +1,29 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_NEC_PREAMBLE_MARK 9000 +#define INFRARED_NEC_PREAMBLE_SPACE 4500 +#define INFRARED_NEC_BIT1_MARK 560 +#define INFRARED_NEC_BIT1_SPACE 1690 +#define INFRARED_NEC_BIT0_MARK 560 +#define INFRARED_NEC_BIT0_SPACE 560 +#define INFRARED_NEC_REPEAT_PERIOD 110000 +#define INFRARED_NEC_SILENCE INFRARED_NEC_REPEAT_PERIOD +#define INFRARED_NEC_MIN_SPLIT_TIME INFRARED_NEC_REPEAT_PAUSE_MIN +#define INFRARED_NEC_REPEAT_PAUSE_MIN 4000 +#define INFRARED_NEC_REPEAT_PAUSE_MAX 150000 +#define INFRARED_NEC_REPEAT_COUNT_MIN 1 +#define INFRARED_NEC_REPEAT_MARK 9000 +#define INFRARED_NEC_REPEAT_SPACE 2250 +#define INFRARED_NEC_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_NEC_BIT_TOLERANCE 120 // us + +extern const InfraredCommonProtocolSpec infrared_protocol_nec; + +bool infrared_decoder_nec_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_nec_decode_repeat(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_nec_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c index 6b4a7c2e3..1b2f2f301 100644 --- a/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c +++ b/lib/infrared/encoder_decoder/rc5/infrared_decoder_rc5.c @@ -1,10 +1,7 @@ -#include "infrared.h" -#include -#include -#include -#include -#include "../infrared_i.h" -#include "../infrared_protocol_defs_i.h" +#include "infrared_protocol_rc5_i.h" + +#include +#include typedef struct { InfraredCommonDecoder* common_decoder; @@ -60,7 +57,7 @@ bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder) { void* infrared_decoder_rc5_alloc(void) { InfraredRc5Decoder* decoder = malloc(sizeof(InfraredRc5Decoder)); decoder->toggle = false; - decoder->common_decoder = infrared_common_decoder_alloc(&protocol_rc5); + decoder->common_decoder = infrared_common_decoder_alloc(&infrared_protocol_rc5); decoder->common_decoder->context = decoder; return decoder; } diff --git a/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c index 7b55cdc44..df47fb7c4 100644 --- a/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c +++ b/lib/infrared/encoder_decoder/rc5/infrared_encoder_rc5.c @@ -1,9 +1,7 @@ -#include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include "../infrared_i.h" +#include "infrared_protocol_rc5_i.h" + +#include +#include typedef struct InfraredEncoderRC5 { InfraredCommonEncoder* common_encoder; @@ -41,7 +39,7 @@ InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration void* infrared_encoder_rc5_alloc(void) { InfraredEncoderRC5* encoder = malloc(sizeof(InfraredEncoderRC5)); - encoder->common_encoder = infrared_common_encoder_alloc(&protocol_rc5); + encoder->common_encoder = infrared_common_encoder_alloc(&infrared_protocol_rc5); encoder->toggle_bit = false; return encoder; } diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c new file mode 100644 index 000000000..bc7e299fd --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.c @@ -0,0 +1,49 @@ +#include "infrared_protocol_rc5_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_rc5 = { + .timings = + { + .preamble_mark = 0, + .preamble_space = 0, + .bit1_mark = INFRARED_RC5_BIT, + .preamble_tolerance = 0, + .bit_tolerance = INFRARED_RC5_BIT_TOLERANCE, + .silence_time = INFRARED_RC5_SILENCE, + .min_split_time = INFRARED_RC5_MIN_SPLIT_TIME, + }, + .databit_len[0] = 1 + 1 + 1 + 5 + + 6, // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command + .manchester_start_from_space = true, + .decode = infrared_common_decode_manchester, + .encode = infrared_common_encode_manchester, + .interpret = infrared_decoder_rc5_interpret, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_rc5 = { + .name = "RC5", + .address_length = 5, + .command_length = 6, + .frequency = INFRARED_RC5_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_RC5_DUTY_CYCLE, + .repeat_count = INFRARED_RC5_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_rc5x = { + .name = "RC5X", + .address_length = 5, + .command_length = 7, + .frequency = INFRARED_RC5_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_RC5_DUTY_CYCLE, + .repeat_count = INFRARED_RC5_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_rc5_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolRC5) + return &infrared_protocol_variant_rc5; + else if(protocol == InfraredProtocolRC5X) + return &infrared_protocol_variant_rc5x; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h new file mode 100644 index 000000000..9dd5802a9 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5.h @@ -0,0 +1,38 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* RC5 protocol description +* https://www.mikrocontroller.net/articles/IRMP_-_english#RC5_.2B_RC5X +**************************************************************************************************** +* Manchester/biphase +* Modulation +* +* 888/1776 - bit (x2 for toggle bit) +* +* __ ____ __ __ __ __ __ __ __ __ +* __ __ ____ __ __ __ __ __ __ __ _ +* | 1 | 1 | 0 | ... | ... | +* s si T address (MSB) command (MSB) +* +* Note: manchester starts from space timing, so it have to be handled properly +* s - start bit (always 1) +* si - RC5: start bit (always 1), RC5X - 7-th bit of address (in our case always 0) +* T - toggle bit, change it's value every button press +* address - 5 bit +* command - 6/7 bit +***************************************************************************************************/ + +void* infrared_decoder_rc5_alloc(void); +void infrared_decoder_rc5_reset(void* decoder); +void infrared_decoder_rc5_free(void* decoder); +InfraredMessage* infrared_decoder_rc5_check_ready(void* ctx); +InfraredMessage* infrared_decoder_rc5_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_rc5_alloc(void); +void infrared_encoder_rc5_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_rc5_free(void* decoder); +InfraredStatus infrared_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); + +const InfraredProtocolVariant* infrared_protocol_rc5_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h new file mode 100644 index 000000000..b906c369e --- /dev/null +++ b/lib/infrared/encoder_decoder/rc5/infrared_protocol_rc5_i.h @@ -0,0 +1,20 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_RC5_CARRIER_FREQUENCY 36000 +#define INFRARED_RC5_DUTY_CYCLE 0.33 + +#define INFRARED_RC5_PREAMBLE_MARK 0 +#define INFRARED_RC5_PREAMBLE_SPACE 0 +#define INFRARED_RC5_BIT 888 // half of time-quant for 1 bit +#define INFRARED_RC5_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_RC5_BIT_TOLERANCE 120 // us +/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ +#define INFRARED_RC5_SILENCE (2700 * 10) +#define INFRARED_RC5_MIN_SPLIT_TIME 2700 +#define INFRARED_RC5_REPEAT_COUNT_MIN 1 + +extern const InfraredCommonProtocolSpec infrared_protocol_rc5; + +bool infrared_decoder_rc5_interpret(InfraredCommonDecoder* decoder); diff --git a/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c b/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c deleted file mode 100644 index 25ea230ef..000000000 --- a/lib/infrared/encoder_decoder/rc5/infrared_rc5_spec.c +++ /dev/null @@ -1,27 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_rc5_protocol_specification = { - .name = "RC5", - .address_length = 5, - .command_length = 6, - .frequency = INFRARED_RC5_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_RC5_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_rc5x_protocol_specification = { - .name = "RC5X", - .address_length = 5, - .command_length = 7, - .frequency = INFRARED_RC5_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_RC5_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_rc5_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolRC5) - return &infrared_rc5_protocol_specification; - else if(protocol == InfraredProtocolRC5X) - return &infrared_rc5x_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c index 13d3e5364..b70f7ceb8 100644 --- a/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c +++ b/lib/infrared/encoder_decoder/rc6/infrared_decoder_rc6.c @@ -1,10 +1,7 @@ -#include "infrared.h" -#include -#include -#include -#include -#include "../infrared_i.h" -#include "../infrared_protocol_defs_i.h" +#include "infrared_protocol_rc6_i.h" + +#include +#include typedef struct { InfraredCommonDecoder* common_decoder; @@ -93,7 +90,7 @@ InfraredStatus infrared_decoder_rc6_decode_manchester( void* infrared_decoder_rc6_alloc(void) { InfraredRc6Decoder* decoder = malloc(sizeof(InfraredRc6Decoder)); decoder->toggle = false; - decoder->common_decoder = infrared_common_decoder_alloc(&protocol_rc6); + decoder->common_decoder = infrared_common_decoder_alloc(&infrared_protocol_rc6); decoder->common_decoder->context = decoder; return decoder; } diff --git a/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c index f1240b17a..d13a204ea 100644 --- a/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c +++ b/lib/infrared/encoder_decoder/rc6/infrared_encoder_rc6.c @@ -1,9 +1,7 @@ -#include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include "infrared_protocol_defs_i.h" -#include -#include "../infrared_i.h" +#include "infrared_protocol_rc6_i.h" + +#include +#include typedef struct InfraredEncoderRC6 { InfraredCommonEncoder* common_encoder; @@ -35,7 +33,7 @@ InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration void* infrared_encoder_rc6_alloc(void) { InfraredEncoderRC6* encoder = malloc(sizeof(InfraredEncoderRC6)); - encoder->common_encoder = infrared_common_encoder_alloc(&protocol_rc6); + encoder->common_encoder = infrared_common_encoder_alloc(&infrared_protocol_rc6); encoder->toggle_bit = false; return encoder; } diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c new file mode 100644 index 000000000..40a187d85 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.c @@ -0,0 +1,39 @@ +#include "infrared_protocol_rc6_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_rc6 = { + .timings = + { + .preamble_mark = INFRARED_RC6_PREAMBLE_MARK, + .preamble_space = INFRARED_RC6_PREAMBLE_SPACE, + .bit1_mark = INFRARED_RC6_BIT, + .preamble_tolerance = INFRARED_RC6_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_RC6_BIT_TOLERANCE, + .silence_time = INFRARED_RC6_SILENCE, + .min_split_time = INFRARED_RC6_MIN_SPLIT_TIME, + }, + .databit_len[0] = + 1 + 3 + 1 + 8 + + 8, // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command + .manchester_start_from_space = false, + .decode = infrared_decoder_rc6_decode_manchester, + .encode = infrared_encoder_rc6_encode_manchester, + .interpret = infrared_decoder_rc6_interpret, + .decode_repeat = NULL, + .encode_repeat = NULL, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_rc6 = { + .name = "RC6", + .address_length = 8, + .command_length = 8, + .frequency = INFRARED_RC6_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_RC6_DUTY_CYCLE, + .repeat_count = INFRARED_RC6_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_rc6_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolRC6) + return &infrared_protocol_variant_rc6; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h new file mode 100644 index 000000000..f0b163411 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6.h @@ -0,0 +1,37 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* RC6 protocol description +* https://www.mikrocontroller.net/articles/IRMP_-_english#RC6_.2B_RC6A +**************************************************************************************************** +* Preamble Manchester/biphase Silence +* mark/space Modulation +* +* 2666 889 444/888 - bit (x2 for toggle bit) 2666 +* +* ________ __ __ __ __ ____ __ __ __ __ __ __ __ __ +* _ _________ ____ __ __ ____ __ __ __ __ __ __ __ __ _______________ +* | 1 | 0 | 0 | 0 | 0 | ... | ... | | +* s m2 m1 m0 T address (MSB) command (MSB) +* +* s - start bit (always 1) +* m0-2 - mode (000 for RC6) +* T - toggle bit, twice longer +* address - 8 bit +* command - 8 bit +***************************************************************************************************/ + +void* infrared_decoder_rc6_alloc(void); +void infrared_decoder_rc6_reset(void* decoder); +void infrared_decoder_rc6_free(void* decoder); +InfraredMessage* infrared_decoder_rc6_check_ready(void* ctx); +InfraredMessage* infrared_decoder_rc6_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_rc6_alloc(void); +void infrared_encoder_rc6_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_rc6_free(void* decoder); +InfraredStatus infrared_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); + +const InfraredProtocolVariant* infrared_protocol_rc6_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h new file mode 100644 index 000000000..06aa2a6a5 --- /dev/null +++ b/lib/infrared/encoder_decoder/rc6/infrared_protocol_rc6_i.h @@ -0,0 +1,28 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_RC6_CARRIER_FREQUENCY 36000 +#define INFRARED_RC6_DUTY_CYCLE 0.33 + +#define INFRARED_RC6_PREAMBLE_MARK 2666 +#define INFRARED_RC6_PREAMBLE_SPACE 889 +#define INFRARED_RC6_BIT 444 // half of time-quant for 1 bit +#define INFRARED_RC6_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_RC6_BIT_TOLERANCE 120 // us +/* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ +#define INFRARED_RC6_SILENCE (2700 * 10) +#define INFRARED_RC6_MIN_SPLIT_TIME 2700 +#define INFRARED_RC6_REPEAT_COUNT_MIN 1 + +extern const InfraredCommonProtocolSpec infrared_protocol_rc6; + +bool infrared_decoder_rc6_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_rc6_decode_manchester( + InfraredCommonDecoder* decoder, + bool level, + uint32_t timing); +InfraredStatus infrared_encoder_rc6_encode_manchester( + InfraredCommonEncoder* encoder_ptr, + uint32_t* duration, + bool* polarity); diff --git a/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c b/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c deleted file mode 100644 index 9e0ba7462..000000000 --- a/lib/infrared/encoder_decoder/rc6/infrared_rc6_spec.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_rc6_protocol_specification = { - .name = "RC6", - .address_length = 8, - .command_length = 8, - .frequency = INFRARED_RC6_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_RC6_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_rc6_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolRC6) - return &infrared_rc6_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c index e8cd3b05c..32881d3c9 100644 --- a/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c +++ b/lib/infrared/encoder_decoder/samsung/infrared_decoder_samsung.c @@ -1,9 +1,5 @@ -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_samsung_i.h" +#include InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx) { return infrared_common_decoder_check_ready(ctx); @@ -57,7 +53,7 @@ InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* d } void* infrared_decoder_samsung32_alloc(void) { - return infrared_common_decoder_alloc(&protocol_samsung32); + return infrared_common_decoder_alloc(&infrared_protocol_samsung32); } InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration) { diff --git a/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c index 75b037f00..3aed50656 100644 --- a/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c +++ b/lib/infrared/encoder_decoder/samsung/infrared_encoder_samsung.c @@ -1,9 +1,7 @@ +#include "infrared_protocol_samsung_i.h" + #include -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include +#include static const uint32_t repeat_timings[] = { INFRARED_SAMSUNG_REPEAT_PAUSE2, @@ -58,7 +56,7 @@ InfraredStatus infrared_encoder_samsung32_encode_repeat( } void* infrared_encoder_samsung32_alloc(void) { - return infrared_common_encoder_alloc(&protocol_samsung32); + return infrared_common_encoder_alloc(&infrared_protocol_samsung32); } void infrared_encoder_samsung32_free(void* encoder_ptr) { diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c new file mode 100644 index 000000000..ca78726ac --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.c @@ -0,0 +1,40 @@ +#include "infrared_protocol_samsung_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_samsung32 = { + .timings = + { + .preamble_mark = INFRARED_SAMSUNG_PREAMBLE_MARK, + .preamble_space = INFRARED_SAMSUNG_PREAMBLE_SPACE, + .bit1_mark = INFRARED_SAMSUNG_BIT1_MARK, + .bit1_space = INFRARED_SAMSUNG_BIT1_SPACE, + .bit0_mark = INFRARED_SAMSUNG_BIT0_MARK, + .bit0_space = INFRARED_SAMSUNG_BIT0_SPACE, + .preamble_tolerance = INFRARED_SAMSUNG_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_SAMSUNG_BIT_TOLERANCE, + .silence_time = INFRARED_SAMSUNG_SILENCE, + .min_split_time = INFRARED_SAMSUNG_MIN_SPLIT_TIME, + }, + .databit_len[0] = 32, + .no_stop_bit = false, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_samsung32_interpret, + .decode_repeat = infrared_decoder_samsung32_decode_repeat, + .encode_repeat = infrared_encoder_samsung32_encode_repeat, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_samsung32 = { + .name = "Samsung32", + .address_length = 8, + .command_length = 8, + .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, + .repeat_count = INFRARED_SAMSUNG_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_samsung32_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolSamsung32) + return &infrared_protocol_variant_samsung32; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h new file mode 100644 index 000000000..9abcb2e3e --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung.h @@ -0,0 +1,31 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* SAMSUNG32 protocol description +* https://www.mikrocontroller.net/articles/IRMP_-_english#SAMSUNG +**************************************************************************************************** +* Preamble Preamble Pulse Distance/Width Pause Preamble Preamble Bit1 Stop +* mark space Modulation repeat repeat bit +* mark space +* +* 4500 4500 32 bit + stop bit 40000/100000 4500 4500 +* __________ _ _ _ _ _ _ _ _ _ _ _ ___________ _ _ +* _ __________ __ _ __ __ __ _ _ __ __ _ ________________ ____________ ____ ___ +* +***************************************************************************************************/ + +void* infrared_decoder_samsung32_alloc(void); +void infrared_decoder_samsung32_reset(void* decoder); +void infrared_decoder_samsung32_free(void* decoder); +InfraredMessage* infrared_decoder_samsung32_check_ready(void* ctx); +InfraredMessage* infrared_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); + +InfraredStatus + infrared_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level); +void infrared_encoder_samsung32_reset(void* encoder_ptr, const InfraredMessage* message); +void* infrared_encoder_samsung32_alloc(void); +void infrared_encoder_samsung32_free(void* encoder_ptr); + +const InfraredProtocolVariant* infrared_protocol_samsung32_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h new file mode 100644 index 000000000..b85384942 --- /dev/null +++ b/lib/infrared/encoder_decoder/samsung/infrared_protocol_samsung_i.h @@ -0,0 +1,35 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_SAMSUNG_PREAMBLE_MARK 4500 +#define INFRARED_SAMSUNG_PREAMBLE_SPACE 4500 +#define INFRARED_SAMSUNG_BIT1_MARK 550 +#define INFRARED_SAMSUNG_BIT1_SPACE 1650 +#define INFRARED_SAMSUNG_BIT0_MARK 550 +#define INFRARED_SAMSUNG_BIT0_SPACE 550 +#define INFRARED_SAMSUNG_REPEAT_PAUSE_MIN 30000 +#define INFRARED_SAMSUNG_REPEAT_PAUSE_MAX 140000 +#define INFRARED_SAMSUNG_REPEAT_PAUSE1 46000 +#define INFRARED_SAMSUNG_REPEAT_PAUSE2 97000 +#define INFRARED_SAMSUNG_REPEAT_COUNT_MIN 1 +/* Samsung silence have to be greater than REPEAT MAX + * otherwise there can be problems during unit tests parsing + * of some data. Real tolerances we don't know, but in real life + * silence time should be greater than max repeat time. This is + * because of similar preambule timings for repeat and first messages. */ +#define INFRARED_SAMSUNG_MIN_SPLIT_TIME 5000 +#define INFRARED_SAMSUNG_SILENCE 145000 +#define INFRARED_SAMSUNG_REPEAT_MARK 4500 +#define INFRARED_SAMSUNG_REPEAT_SPACE 4500 +#define INFRARED_SAMSUNG_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_SAMSUNG_BIT_TOLERANCE 120 // us + +bool infrared_decoder_samsung32_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_decoder_samsung32_decode_repeat(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_samsung32_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); + +extern const InfraredCommonProtocolSpec infrared_protocol_samsung32; diff --git a/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c b/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c deleted file mode 100644 index f4cbf699e..000000000 --- a/lib/infrared/encoder_decoder/samsung/infrared_samsung_spec.c +++ /dev/null @@ -1,17 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_samsung32_protocol_specification = { - .name = "Samsung32", - .address_length = 8, - .command_length = 8, - .frequency = INFRARED_COMMON_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_COMMON_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_samsung32_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolSamsung32) - return &infrared_samsung32_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c index 45f06c942..fc18a183c 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_decoder_sirc.c @@ -1,10 +1,5 @@ -#include "common/infrared_common_i.h" -#include "infrared.h" -#include "infrared_protocol_defs_i.h" -#include -#include -#include -#include "../infrared_i.h" +#include "infrared_protocol_sirc_i.h" +#include InfraredMessage* infrared_decoder_sirc_check_ready(void* ctx) { return infrared_common_decoder_check_ready(ctx); @@ -44,7 +39,7 @@ bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder) { } void* infrared_decoder_sirc_alloc(void) { - return infrared_common_decoder_alloc(&protocol_sirc); + return infrared_common_decoder_alloc(&infrared_protocol_sirc); } InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration) { diff --git a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c index 2c2bda1af..6adf2235c 100644 --- a/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c +++ b/lib/infrared/encoder_decoder/sirc/infrared_encoder_sirc.c @@ -1,10 +1,5 @@ +#include "infrared_protocol_sirc_i.h" #include -#include "infrared.h" -#include "common/infrared_common_i.h" -#include -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" -#include void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message) { furi_assert(encoder_ptr); @@ -53,7 +48,7 @@ InfraredStatus infrared_encoder_sirc_encode_repeat( } void* infrared_encoder_sirc_alloc(void) { - return infrared_common_encoder_alloc(&protocol_sirc); + return infrared_common_encoder_alloc(&infrared_protocol_sirc); } void infrared_encoder_sirc_free(void* encoder_ptr) { diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c new file mode 100644 index 000000000..b527fba98 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.c @@ -0,0 +1,64 @@ +#include "infrared_protocol_sirc_i.h" + +const InfraredCommonProtocolSpec infrared_protocol_sirc = { + .timings = + { + .preamble_mark = INFRARED_SIRC_PREAMBLE_MARK, + .preamble_space = INFRARED_SIRC_PREAMBLE_SPACE, + .bit1_mark = INFRARED_SIRC_BIT1_MARK, + .bit1_space = INFRARED_SIRC_BIT1_SPACE, + .bit0_mark = INFRARED_SIRC_BIT0_MARK, + .bit0_space = INFRARED_SIRC_BIT0_SPACE, + .preamble_tolerance = INFRARED_SIRC_PREAMBLE_TOLERANCE, + .bit_tolerance = INFRARED_SIRC_BIT_TOLERANCE, + .silence_time = INFRARED_SIRC_SILENCE, + .min_split_time = INFRARED_SIRC_MIN_SPLIT_TIME, + }, + .databit_len[0] = 20, + .databit_len[1] = 15, + .databit_len[2] = 12, + .no_stop_bit = true, + .decode = infrared_common_decode_pdwm, + .encode = infrared_common_encode_pdwm, + .interpret = infrared_decoder_sirc_interpret, + .decode_repeat = NULL, + .encode_repeat = infrared_encoder_sirc_encode_repeat, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_sirc = { + .name = "SIRC", + .address_length = 5, + .command_length = 7, + .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, + .repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_sirc15 = { + .name = "SIRC15", + .address_length = 8, + .command_length = 7, + .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, + .repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN, +}; + +static const InfraredProtocolVariant infrared_protocol_variant_sirc20 = { + .name = "SIRC20", + .address_length = 13, + .command_length = 7, + .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, + .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, + .repeat_count = INFRARED_SIRC_REPEAT_COUNT_MIN, +}; + +const InfraredProtocolVariant* infrared_protocol_sirc_get_variant(InfraredProtocol protocol) { + if(protocol == InfraredProtocolSIRC) + return &infrared_protocol_variant_sirc; + else if(protocol == InfraredProtocolSIRC15) + return &infrared_protocol_variant_sirc15; + else if(protocol == InfraredProtocolSIRC20) + return &infrared_protocol_variant_sirc20; + else + return NULL; +} diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h new file mode 100644 index 000000000..0c3bcd8a2 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc.h @@ -0,0 +1,37 @@ +#pragma once + +#include "../infrared_i.h" + +/*************************************************************************************************** +* Sony SIRC protocol description +* https://www.sbprojects.net/knowledge/ir/sirc.php +* http://picprojects.org.uk/ +**************************************************************************************************** +* Preamble Preamble Pulse Width Modulation Pause Entirely repeat +* mark space up to period message.. +* +* 2400 600 12/15/20 bits (600,1200) ...45000 2400 600 +* __________ _ _ _ _ _ _ _ _ _ _ _ _ _ __________ _ _ +* ____ __________ _ _ _ __ __ __ _ _ __ __ _ _ ____________________ __________ _ +* | command | address | +* SIRC | 7b LSB | 5b LSB | +* SIRC15 | 7b LSB | 8b LSB | +* SIRC20 | 7b LSB | 13b LSB | +* +* No way to determine either next message is repeat or not, +* so recognize only fact message received. Sony remotes always send at least 3 messages. +* Assume 8 last extended bits for SIRC20 are address bits. +***************************************************************************************************/ + +void* infrared_decoder_sirc_alloc(void); +void infrared_decoder_sirc_reset(void* decoder); +InfraredMessage* infrared_decoder_sirc_check_ready(void* decoder); +void infrared_decoder_sirc_free(void* decoder); +InfraredMessage* infrared_decoder_sirc_decode(void* decoder, bool level, uint32_t duration); + +void* infrared_encoder_sirc_alloc(void); +void infrared_encoder_sirc_reset(void* encoder_ptr, const InfraredMessage* message); +void infrared_encoder_sirc_free(void* decoder); +InfraredStatus infrared_encoder_sirc_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); + +const InfraredProtocolVariant* infrared_protocol_sirc_get_variant(InfraredProtocol protocol); diff --git a/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h new file mode 100644 index 000000000..e38be9bc8 --- /dev/null +++ b/lib/infrared/encoder_decoder/sirc/infrared_protocol_sirc_i.h @@ -0,0 +1,26 @@ +#pragma once + +#include "../common/infrared_common_i.h" + +#define INFRARED_SIRC_CARRIER_FREQUENCY 40000 +#define INFRARED_SIRC_DUTY_CYCLE 0.33 +#define INFRARED_SIRC_PREAMBLE_MARK 2400 +#define INFRARED_SIRC_PREAMBLE_SPACE 600 +#define INFRARED_SIRC_BIT1_MARK 1200 +#define INFRARED_SIRC_BIT1_SPACE 600 +#define INFRARED_SIRC_BIT0_MARK 600 +#define INFRARED_SIRC_BIT0_SPACE 600 +#define INFRARED_SIRC_PREAMBLE_TOLERANCE 200 // us +#define INFRARED_SIRC_BIT_TOLERANCE 120 // us +#define INFRARED_SIRC_SILENCE 10000 +#define INFRARED_SIRC_MIN_SPLIT_TIME (INFRARED_SIRC_SILENCE - 1000) +#define INFRARED_SIRC_REPEAT_PERIOD 45000 +#define INFRARED_SIRC_REPEAT_COUNT_MIN 3 + +extern const InfraredCommonProtocolSpec infrared_protocol_sirc; + +bool infrared_decoder_sirc_interpret(InfraredCommonDecoder* decoder); +InfraredStatus infrared_encoder_sirc_encode_repeat( + InfraredCommonEncoder* encoder, + uint32_t* duration, + bool* level); diff --git a/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c b/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c deleted file mode 100644 index 9bf35908e..000000000 --- a/lib/infrared/encoder_decoder/sirc/infrared_sirc_spec.c +++ /dev/null @@ -1,37 +0,0 @@ -#include "../infrared_i.h" -#include "infrared_protocol_defs_i.h" - -static const InfraredProtocolSpecification infrared_sirc_protocol_specification = { - .name = "SIRC", - .address_length = 5, - .command_length = 7, - .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_sirc15_protocol_specification = { - .name = "SIRC15", - .address_length = 8, - .command_length = 7, - .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, -}; - -static const InfraredProtocolSpecification infrared_sirc20_protocol_specification = { - .name = "SIRC20", - .address_length = 13, - .command_length = 7, - .frequency = INFRARED_SIRC_CARRIER_FREQUENCY, - .duty_cycle = INFRARED_SIRC_DUTY_CYCLE, -}; - -const InfraredProtocolSpecification* infrared_sirc_get_spec(InfraredProtocol protocol) { - if(protocol == InfraredProtocolSIRC) - return &infrared_sirc_protocol_specification; - else if(protocol == InfraredProtocolSIRC15) - return &infrared_sirc15_protocol_specification; - else if(protocol == InfraredProtocolSIRC20) - return &infrared_sirc20_protocol_specification; - else - return NULL; -} diff --git a/lib/infrared/worker/infrared_transmit.c b/lib/infrared/worker/infrared_transmit.c index 1a5083019..113fb6324 100644 --- a/lib/infrared/worker/infrared_transmit.c +++ b/lib/infrared/worker/infrared_transmit.c @@ -101,7 +101,8 @@ void infrared_send(const InfraredMessage* message, int times) { InfraredEncoderHandler* handler = infrared_alloc_encoder(); infrared_reset_encoder(handler, message); - infrared_tx_number_of_transmissions = times; + infrared_tx_number_of_transmissions = + MAX((int)infrared_get_protocol_min_repeat_count(message->protocol), times); uint32_t frequency = infrared_get_protocol_frequency(message->protocol); float duty_cycle = infrared_get_protocol_duty_cycle(message->protocol); diff --git a/lib/infrared/worker/infrared_worker.c b/lib/infrared/worker/infrared_worker.c index 033dba525..5add1413e 100644 --- a/lib/infrared/worker/infrared_worker.c +++ b/lib/infrared/worker/infrared_worker.c @@ -1,13 +1,10 @@ +#include "infrared_worker.h" + +#include +#include + #include #include -#include "sys/_stdint.h" -#include "infrared_worker.h" -#include -#include -#include -#include -#include -#include #include @@ -471,18 +468,23 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { furi_assert(instance->state == InfraredWorkerStateStartTx); furi_assert(thread_context); + size_t repeats_left = + instance->signal.decoded ? + infrared_get_protocol_min_repeat_count(instance->signal.message.protocol) : + 1; uint32_t events = 0; - bool new_data_available = true; - bool exit = false; - exit = !infrared_get_new_signal(instance); - furi_assert(!exit); + bool exit_pending = false; - while(!exit) { + bool running = infrared_get_new_signal(instance); + furi_assert(running); + + while(running) { switch(instance->state) { case InfraredWorkerStateStartTx: + --repeats_left; /* The first message does not result in TX_MESSAGE_SENT event for some reason */ instance->tx.need_reinitialization = false; - new_data_available = infrared_worker_tx_fill_buffer(instance); + const bool new_data_available = infrared_worker_tx_fill_buffer(instance); furi_hal_infrared_async_tx_start(instance->tx.frequency, instance->tx.duty_cycle); if(!new_data_available) { @@ -496,7 +498,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { break; case InfraredWorkerStateStopTx: furi_hal_infrared_async_tx_stop(); - exit = true; + running = false; break; case InfraredWorkerStateWaitTxEnd: furi_hal_infrared_async_tx_wait_termination(); @@ -504,18 +506,18 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { events = furi_thread_flags_get(); if(events & INFRARED_WORKER_EXIT) { - exit = true; + running = false; break; } break; case InfraredWorkerStateRunTx: - events = furi_thread_flags_wait(INFRARED_WORKER_ALL_TX_EVENTS, 0, FuriWaitForever); + events = furi_thread_flags_wait( + INFRARED_WORKER_ALL_TX_EVENTS, FuriFlagWaitAny, FuriWaitForever); furi_check(events & INFRARED_WORKER_ALL_TX_EVENTS); /* at least one caught */ if(events & INFRARED_WORKER_EXIT) { - instance->state = InfraredWorkerStateStopTx; - break; + exit_pending = true; } if(events & INFRARED_WORKER_TX_FILL_BUFFER) { @@ -527,9 +529,19 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { } if(events & INFRARED_WORKER_TX_MESSAGE_SENT) { - if(instance->tx.message_sent_callback) + if(repeats_left > 0) { + --repeats_left; + } + + if(instance->tx.message_sent_callback) { instance->tx.message_sent_callback(instance->tx.message_sent_context); + } } + + if(exit_pending && repeats_left == 0) { + instance->state = InfraredWorkerStateStopTx; + } + break; default: furi_assert(0);