[FL-1696, FL-1685] IRDA: Add RC5, decoder refactoring (#663)
* [FL-1696] IRDA: Split decoders and protocols * IRDA: Restruct directories. * IRDA: fix long timings * [FL-1685] IRDA: Add RC5 Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									ecff31d228
								
							
						
					
					
						commit
						e6d5f4038b
					
				| @ -1,11 +1,12 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include "../minunit.h" | #include "../minunit.h" | ||||||
| #include "irda.h" | #include "irda.h" | ||||||
| #include "irda_common_i.h" | #include "common/irda_common_i.h" | ||||||
| #include "test_data/irda_nec_test_data.srcdata" | #include "test_data/irda_nec_test_data.srcdata" | ||||||
| #include "test_data/irda_necext_test_data.srcdata" | #include "test_data/irda_necext_test_data.srcdata" | ||||||
| #include "test_data/irda_samsung_test_data.srcdata" | #include "test_data/irda_samsung_test_data.srcdata" | ||||||
| #include "test_data/irda_rc6_test_data.srcdata" | #include "test_data/irda_rc6_test_data.srcdata" | ||||||
|  | #include "test_data/irda_rc5_test_data.srcdata" | ||||||
| 
 | 
 | ||||||
| #define RUN_ENCODER(data, expected) \ | #define RUN_ENCODER(data, expected) \ | ||||||
|     run_encoder((data), COUNT_OF(data), (expected), COUNT_OF(expected)) |     run_encoder((data), COUNT_OF(data), (expected), COUNT_OF(expected)) | ||||||
| @ -153,16 +154,19 @@ MU_TEST(test_decoder_samsung32) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MU_TEST(test_mix) { | MU_TEST(test_mix) { | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input2, test_decoder_rc5_expected2); | ||||||
|     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); |     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); | ||||||
|     // can use encoder data for decoding, but can't do opposite
 |     // can use encoder data for decoding, but can't do opposite
 | ||||||
|     RUN_DECODER(test_encoder_rc6_expected1, test_encoder_rc6_input1); |     RUN_DECODER(test_encoder_rc6_expected1, test_encoder_rc6_input1); | ||||||
|     RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); |     RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); | ||||||
|     RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); |     RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); | ||||||
|     RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); |     RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input1, test_decoder_rc5_expected1); | ||||||
|     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); |     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); | ||||||
|     RUN_DECODER(test_decoder_nec_input2, test_decoder_nec_expected2); |     RUN_DECODER(test_decoder_nec_input2, test_decoder_nec_expected2); | ||||||
|     RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); |     RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); | ||||||
|     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); |     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input5, test_decoder_rc5_expected5); | ||||||
|     RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); |     RUN_DECODER(test_decoder_samsung32_input1, test_decoder_samsung32_expected1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -187,6 +191,25 @@ MU_TEST(test_decoder_necext1) { | |||||||
|     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); |     RUN_DECODER(test_decoder_necext_input1, test_decoder_necext_expected1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | MU_TEST(test_decoder_rc5) { | ||||||
|  |     RUN_DECODER(test_decoder_rc5x_input1, test_decoder_rc5x_expected1); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input1, test_decoder_rc5_expected1); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input2, test_decoder_rc5_expected2); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input3, test_decoder_rc5_expected3); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input4, test_decoder_rc5_expected4); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input5, test_decoder_rc5_expected5); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input6, test_decoder_rc5_expected6); | ||||||
|  |     RUN_DECODER(test_decoder_rc5_input_all_repeats, test_decoder_rc5_expected_all_repeats); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MU_TEST(test_encoder_rc5x) { | ||||||
|  |     RUN_ENCODER(test_decoder_rc5x_expected1, test_decoder_rc5x_input1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | MU_TEST(test_encoder_rc5) { | ||||||
|  |     RUN_ENCODER(test_decoder_rc5_expected_all_repeats, test_decoder_rc5_input_all_repeats); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| MU_TEST(test_decoder_rc6) { | MU_TEST(test_decoder_rc6) { | ||||||
|     RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); |     RUN_DECODER(test_decoder_rc6_input1, test_decoder_rc6_expected1); | ||||||
| } | } | ||||||
| @ -200,20 +223,24 @@ MU_TEST(test_encoder_decoder_all) { | |||||||
|     run_encoder_decoder(test_necext_all, COUNT_OF(test_necext_all)); |     run_encoder_decoder(test_necext_all, COUNT_OF(test_necext_all)); | ||||||
|     run_encoder_decoder(test_samsung32_all, COUNT_OF(test_samsung32_all)); |     run_encoder_decoder(test_samsung32_all, COUNT_OF(test_samsung32_all)); | ||||||
|     run_encoder_decoder(test_rc6_all, COUNT_OF(test_rc6_all)); |     run_encoder_decoder(test_rc6_all, COUNT_OF(test_rc6_all)); | ||||||
|  |     run_encoder_decoder(test_rc5_all, COUNT_OF(test_rc5_all)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| MU_TEST_SUITE(test_irda_decoder_encoder) { | MU_TEST_SUITE(test_irda_decoder_encoder) { | ||||||
|     MU_SUITE_CONFIGURE(&test_setup, &test_teardown); |     MU_SUITE_CONFIGURE(&test_setup, &test_teardown); | ||||||
| 
 | 
 | ||||||
|     MU_RUN_TEST(test_encoder_decoder_all); |     MU_RUN_TEST(test_encoder_rc5x); | ||||||
|  |     MU_RUN_TEST(test_encoder_rc5); | ||||||
|  |     MU_RUN_TEST(test_decoder_rc5); | ||||||
|  |     MU_RUN_TEST(test_decoder_rc6); | ||||||
|  |     MU_RUN_TEST(test_encoder_rc6); | ||||||
|     MU_RUN_TEST(test_decoder_unexpected_end_in_sequence); |     MU_RUN_TEST(test_decoder_unexpected_end_in_sequence); | ||||||
|     MU_RUN_TEST(test_decoder_nec1); |     MU_RUN_TEST(test_decoder_nec1); | ||||||
|     MU_RUN_TEST(test_decoder_nec2); |     MU_RUN_TEST(test_decoder_nec2); | ||||||
|     MU_RUN_TEST(test_decoder_samsung32); |     MU_RUN_TEST(test_decoder_samsung32); | ||||||
|     MU_RUN_TEST(test_decoder_necext1); |     MU_RUN_TEST(test_decoder_necext1); | ||||||
|     MU_RUN_TEST(test_mix); |     MU_RUN_TEST(test_mix); | ||||||
|     MU_RUN_TEST(test_decoder_rc6); |     MU_RUN_TEST(test_encoder_decoder_all); | ||||||
|     MU_RUN_TEST(test_encoder_rc6); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int run_minunit_test_irda_decoder_encoder() { | int run_minunit_test_irda_decoder_encoder() { | ||||||
|  | |||||||
| @ -0,0 +1,160 @@ | |||||||
|  | /* | ||||||
|  | _______----__--____----__--____--__----____----__--__--__--__ | ||||||
|  |      | 1 | 0 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | | ||||||
|  |       s1  s2   t |     address       |        command        | | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | const uint32_t test_decoder_rc5x_input1[] = { | ||||||
|  | 27000 + 888, 1776, 888, 888, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_decoder_rc5x_expected1[] = { | ||||||
|  |     {IrdaProtocolRC5X,     0x13,      0x10,  false}, // toggle 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | _______--__----____----__--____--__----____----__--__--__--__ | ||||||
|  |      | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | | ||||||
|  |       s1  s2   t |     address       |        command        | | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | const uint32_t test_decoder_rc5_input1[] = { | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_decoder_rc5_expected1[] = { | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x10,  false}, // toggle 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | _______--__--__--__----__--____--__----____----__--__--__--__ | ||||||
|  |      | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | | ||||||
|  |       s1  s2   t |     address       |        command        | | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | const uint32_t test_decoder_rc5_input2[] = { | ||||||
|  | 27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_decoder_rc5_expected2[] = { | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x10,  false}, // toggle 1 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | _______--__----____----__--____--__----____----__--__--____-- | ||||||
|  |      | 1 | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | | ||||||
|  |       s1  s2   t |     address       |        command        | | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | const uint32_t test_decoder_rc5_input3[] = { | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_decoder_rc5_expected3[] = { | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x11,  false}, // toggle 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | _______--__--__--__----__--____--__----____----__--__--____-- | ||||||
|  |      | 1 | 1 | 1 | 1 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 1 | | ||||||
|  |       s1  s2   t |     address       |        command        | | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | const uint32_t test_decoder_rc5_input4[] = { | ||||||
|  | 27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_decoder_rc5_expected4[] = { | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x11,  false}, // toggle 1 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | _______--__----____--__--__--__--__--__--__--__--__--__--__-- | ||||||
|  |      | 1 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | | ||||||
|  |       s1  s2   t |     address       |        command        | | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | const uint32_t test_decoder_rc5_input5[] = { | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_decoder_rc5_expected5[] = { | ||||||
|  |     {IrdaProtocolRC5,     0x1F,      0x3F,  false}, // toggle 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | /* | ||||||
|  | _______--__--__--__--__--__--__--__--__--__--__--__--__--__-- | ||||||
|  |      | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | | ||||||
|  |       s1  s2   t |     address       |        command        | | ||||||
|  | */ | ||||||
|  | 
 | ||||||
|  | const uint32_t test_decoder_rc5_input6[] = { | ||||||
|  | 27000 + 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_decoder_rc5_expected6[] = { | ||||||
|  |     {IrdaProtocolRC5,     0x1F,      0x3F,  false}, // toggle 1 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | const uint32_t test_decoder_rc5_input_all_repeats[] = { | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, | ||||||
|  | 27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, | ||||||
|  | 27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, | ||||||
|  | 27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 1776, 888, | ||||||
|  | 27000 + 888, 888, 888, 888, 888, 888, 888, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 1776, 888, 888, 1776, 888, 888, 1776, 1776, 1776, 888, 888, 888, 888, 888, 888, | ||||||
|  | 27000 + 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, | ||||||
|  | 27000 + 888, 888, 888, 1776, 1776, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, 888, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_decoder_rc5_expected_all_repeats[] = { | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x11,  false}, // toggle 0 | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x11,  false}, // toggle 1 | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x11,  true},  // toggle 1 | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x11,  true},  // toggle 1 | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x11,  false}, // toggle 0 | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x10,  false}, // toggle 1 | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x10,  false}, // toggle 0 | ||||||
|  |     {IrdaProtocolRC5,     0x13,      0x10,  true},  // toggle 0 | ||||||
|  |     {IrdaProtocolRC5,     0x1F,      0x3F,  false}, // toggle 1 | ||||||
|  |     {IrdaProtocolRC5,     0x1F,      0x3F,  false}, // toggle 0 | ||||||
|  |     {IrdaProtocolRC5,     0x1F,      0x3F,  true},  // toggle 0 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | const IrdaMessage test_rc5_all[] = { | ||||||
|  |     {IrdaProtocolRC5,     0x1F,      0x3F,  false}, | ||||||
|  |     {IrdaProtocolRC5,     0x00,      0x00,  false}, | ||||||
|  |     {IrdaProtocolRC5,     0x10,      0x01,  false}, | ||||||
|  |     {IrdaProtocolRC5,     0x01,      0x20,  false}, | ||||||
|  |     {IrdaProtocolRC5,     0x01,      0x20,  false}, | ||||||
|  |     {IrdaProtocolRC5,     0x01,      0x20,  true}, | ||||||
|  |     {IrdaProtocolRC5,     0x01,      0x20,  true}, | ||||||
|  |     {IrdaProtocolRC5,     0x01,      0x20,  true}, | ||||||
|  |     {IrdaProtocolRC5,     0x01,      0x20,  true}, | ||||||
|  |     {IrdaProtocolRC5,     0x1F,      0x3F,  false}, | ||||||
|  |     {IrdaProtocolRC5,     0x0A,      0x2A,  false}, | ||||||
|  |     {IrdaProtocolRC5,     0x15,      0x15,  false}, | ||||||
|  |     {IrdaProtocolRC5,     0x15,      0x15,  true}, | ||||||
|  | 
 | ||||||
|  |     {IrdaProtocolRC5X,     0x1F,      0x3F,  false}, | ||||||
|  |     {IrdaProtocolRC5X,     0x00,      0x00,  false}, | ||||||
|  |     {IrdaProtocolRC5X,     0x10,      0x01,  false}, | ||||||
|  |     {IrdaProtocolRC5X,     0x01,      0x20,  false}, | ||||||
|  |     {IrdaProtocolRC5X,     0x01,      0x20,  false}, | ||||||
|  |     {IrdaProtocolRC5X,     0x01,      0x20,  true}, | ||||||
|  |     {IrdaProtocolRC5X,     0x01,      0x20,  true}, | ||||||
|  |     {IrdaProtocolRC5X,     0x01,      0x20,  true}, | ||||||
|  |     {IrdaProtocolRC5X,     0x01,      0x20,  true}, | ||||||
|  |     {IrdaProtocolRC5X,     0x1F,      0x3F,  false}, | ||||||
|  |     {IrdaProtocolRC5X,     0x0A,      0x2A,  false}, | ||||||
|  |     {IrdaProtocolRC5X,     0x15,      0x15,  false}, | ||||||
|  |     {IrdaProtocolRC5X,     0x15,      0x15,  true}, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| @ -15,17 +15,17 @@ _____---------______--____--__--__------____--____--__----____--__----__--__--__ | |||||||
| */ | */ | ||||||
| 
 | 
 | ||||||
| const uint32_t test_decoder_rc6_input1[] = { | const uint32_t test_decoder_rc6_input1[] = { | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444 + 888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 444 + 444, 888 + 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 888,   // failed | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const IrdaMessage test_decoder_rc6_expected1[] = { | const IrdaMessage test_decoder_rc6_expected1[] = { | ||||||
| @ -54,14 +54,14 @@ const IrdaMessage test_encoder_rc6_input1[] = { | |||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const uint32_t test_encoder_rc6_expected1[] = { | const uint32_t test_encoder_rc6_expected1[] = { | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 888, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444, 888, 888+444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| 2700, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | 27000, 2666, 889, 444, 888, 444, 444, 444, 444, 444+888, 888, 444, 888, 444, 444, 888, 888, 444, 444, 888, 444, 444, 444, 444, 888, 888, 888, 444, 444, 444, 444, 444, 444, 444, 444, 444, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -471,8 +471,8 @@ static void furi_hal_irda_tx_fill_buffer(uint8_t buf_num, uint8_t polarity_shift | |||||||
|             irda_tim_tx.tx_timing_rest_duration = num_of_impulses - 1; |             irda_tim_tx.tx_timing_rest_duration = num_of_impulses - 1; | ||||||
|             irda_tim_tx.tx_timing_rest_status = status; |             irda_tim_tx.tx_timing_rest_status = status; | ||||||
|             irda_tim_tx.tx_timing_rest_level = level; |             irda_tim_tx.tx_timing_rest_level = level; | ||||||
|             buffer->polarity[polarity_counter] = level ? IRDA_TX_CCMR_HIGH : IRDA_TX_CCMR_LOW; |             --(*size); | ||||||
|             buffer->data[*size] = 0xFFFF; |             --polarity_counter; | ||||||
|             status = FuriHalIrdaTxGetDataStateOk; |             status = FuriHalIrdaTxGetDataStateOk; | ||||||
|         } else { |         } else { | ||||||
|             buffer->polarity[polarity_counter] = level ? IRDA_TX_CCMR_HIGH : IRDA_TX_CCMR_LOW; |             buffer->polarity[polarity_counter] = level ? IRDA_TX_CCMR_HIGH : IRDA_TX_CCMR_LOW; | ||||||
|  | |||||||
| @ -21,6 +21,10 @@ static bool irda_check_preamble(IrdaCommonDecoder* decoder) { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     if (decoder->protocol->timings.preamble_mark == 0) { | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     while ((!result) && (decoder->timings_cnt >= 2)) { |     while ((!result) && (decoder->timings_cnt >= 2)) { | ||||||
|         float preamble_tolerance = decoder->protocol->timings.preamble_tolerance; |         float preamble_tolerance = decoder->protocol->timings.preamble_tolerance; | ||||||
|         uint16_t preamble_mark = decoder->protocol->timings.preamble_mark; |         uint16_t preamble_mark = decoder->protocol->timings.preamble_mark; | ||||||
| @ -94,7 +98,7 @@ IrdaStatus irda_common_decode_pdwm(IrdaCommonDecoder* decoder) { | |||||||
| /* level switch detection goes in middle of time-quant */ | /* level switch detection goes in middle of time-quant */ | ||||||
| IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { | IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { | ||||||
|     furi_assert(decoder); |     furi_assert(decoder); | ||||||
|     IrdaStatus status = IrdaStatusError; |     IrdaStatus status = IrdaStatusOk; | ||||||
|     uint16_t bit = decoder->protocol->timings.bit1_mark; |     uint16_t bit = decoder->protocol->timings.bit1_mark; | ||||||
|     uint16_t tolerance = decoder->protocol->timings.bit_tolerance; |     uint16_t tolerance = decoder->protocol->timings.bit_tolerance; | ||||||
| 
 | 
 | ||||||
| @ -106,12 +110,22 @@ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { | |||||||
|         bool single_timing = MATCH_BIT_TIMING(timing, bit, tolerance); |         bool single_timing = MATCH_BIT_TIMING(timing, bit, tolerance); | ||||||
|         bool double_timing = MATCH_BIT_TIMING(timing, 2*bit, tolerance); |         bool double_timing = MATCH_BIT_TIMING(timing, 2*bit, tolerance); | ||||||
| 
 | 
 | ||||||
|         if((!single_timing && !double_timing) || (double_timing && !*switch_detect)) { |         if(!single_timing && !double_timing) { | ||||||
|             status = IrdaStatusError; |             status = IrdaStatusError; | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if ((decoder->protocol->manchester_start_from_space) && (decoder->databit_cnt == 0)) { | ||||||
|  |             *switch_detect = 1; /* fake as we were previously in the middle of time-quant */ | ||||||
|  |             decoder->data[0] = 0;   /* first captured timing should be Mark */ | ||||||
|  |             ++decoder->databit_cnt; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|         if (*switch_detect == 0) { |         if (*switch_detect == 0) { | ||||||
|  |             if (double_timing) { | ||||||
|  |                 status = IrdaStatusError; | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|             /* only single timing - level switch required in the middle of time-quant */ |             /* only single timing - level switch required in the middle of time-quant */ | ||||||
|             *switch_detect = 1; |             *switch_detect = 1; | ||||||
|         } else { |         } else { | ||||||
| @ -123,6 +137,7 @@ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { | |||||||
|         --decoder->timings_cnt; |         --decoder->timings_cnt; | ||||||
|         shift_left_array(decoder->timings, decoder->timings_cnt, 1); |         shift_left_array(decoder->timings, decoder->timings_cnt, 1); | ||||||
|         status = IrdaStatusOk; |         status = IrdaStatusOk; | ||||||
|  |         bool level = (decoder->level + decoder->timings_cnt) % 2; | ||||||
| 
 | 
 | ||||||
|         if (decoder->databit_cnt < decoder->protocol->databit_len) { |         if (decoder->databit_cnt < decoder->protocol->databit_len) { | ||||||
|             if (*switch_detect) { |             if (*switch_detect) { | ||||||
| @ -130,19 +145,17 @@ IrdaStatus irda_common_decode_manchester(IrdaCommonDecoder* decoder) { | |||||||
|                 uint8_t shift = decoder->databit_cnt % 8;   // LSB first
 |                 uint8_t shift = decoder->databit_cnt % 8;   // LSB first
 | ||||||
|                 if (!shift) |                 if (!shift) | ||||||
|                     decoder->data[index] = 0; |                     decoder->data[index] = 0; | ||||||
|                 bool inverse_level = decoder->protocol->manchester_inverse_level; |                 decoder->data[index] |= (level << shift); | ||||||
|                 uint8_t logic_value = inverse_level ? !decoder->level : decoder->level; |  | ||||||
|                 decoder->data[index] |= (logic_value << shift); |  | ||||||
|                 ++decoder->databit_cnt; |                 ++decoder->databit_cnt; | ||||||
|             } |             } | ||||||
|             if (decoder->databit_cnt == decoder->protocol->databit_len) { |             if (decoder->databit_cnt == decoder->protocol->databit_len) { | ||||||
|                 if (decoder->level) { |                 if (level) { | ||||||
|                     status = IrdaStatusReady; |                     status = IrdaStatusReady; | ||||||
|                     break; |                     break; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } else { |         } else { | ||||||
|             furi_assert(decoder->level); |             furi_assert(level); | ||||||
|             /* cover case: sequence should be stopped after last bit was received */ |             /* cover case: sequence should be stopped after last bit was received */ | ||||||
|             if (single_timing) { |             if (single_timing) { | ||||||
|                 status = IrdaStatusReady; |                 status = IrdaStatusReady; | ||||||
| @ -178,6 +191,7 @@ IrdaMessage* irda_common_decode(IrdaCommonDecoder* decoder, bool level, uint32_t | |||||||
|                 decoder->state = IrdaCommonDecoderStateDecode; |                 decoder->state = IrdaCommonDecoderStateDecode; | ||||||
|                 decoder->databit_cnt = 0; |                 decoder->databit_cnt = 0; | ||||||
|                 decoder->switch_detect = false; |                 decoder->switch_detect = false; | ||||||
|  |                 continue; | ||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
|         case IrdaCommonDecoderStateDecode: |         case IrdaCommonDecoderStateDecode: | ||||||
| @ -243,6 +257,10 @@ void irda_common_decoder_reset_state(IrdaCommonDecoder* common_decoder) { | |||||||
|     common_decoder->databit_cnt = 0; |     common_decoder->databit_cnt = 0; | ||||||
|     common_decoder->switch_detect = false; |     common_decoder->switch_detect = false; | ||||||
|     common_decoder->message.protocol = IrdaProtocolUnknown; |     common_decoder->message.protocol = IrdaProtocolUnknown; | ||||||
|  |     if (common_decoder->protocol->timings.preamble_mark == 0) { | ||||||
|  |         --common_decoder->timings_cnt; | ||||||
|  |         shift_left_array(common_decoder->timings, common_decoder->timings_cnt, 1); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void irda_common_decoder_reset(void* decoder) { | void irda_common_decoder_reset(void* decoder) { | ||||||
| @ -28,10 +28,9 @@ IrdaStatus irda_common_encode_manchester(IrdaCommonEncoder* encoder, uint32_t* d | |||||||
|     uint8_t index = encoder->bits_encoded / 8; |     uint8_t index = encoder->bits_encoded / 8; | ||||||
|     uint8_t shift = encoder->bits_encoded % 8;   // LSB first
 |     uint8_t shift = encoder->bits_encoded % 8;   // LSB first
 | ||||||
|     bool logic_value = !!(encoder->data[index] & (0x01 << shift)); |     bool logic_value = !!(encoder->data[index] & (0x01 << shift)); | ||||||
|     bool inverse = encoder->protocol->manchester_inverse_level; |  | ||||||
|     bool even_timing = !(encoder->timings_encoded % 2); |     bool even_timing = !(encoder->timings_encoded % 2); | ||||||
| 
 | 
 | ||||||
|     *level = even_timing ^ logic_value ^ inverse; |     *level = even_timing ^ logic_value; | ||||||
|     *duration = timings->bit1_mark; |     *duration = timings->bit1_mark; | ||||||
|     if (even_timing)        /* start encoding from space */ |     if (even_timing)        /* start encoding from space */ | ||||||
|         ++encoder->bits_encoded; |         ++encoder->bits_encoded; | ||||||
| @ -20,7 +20,7 @@ typedef IrdaStatus (*IrdaCommonEncode)(IrdaCommonEncoder* encoder, uint32_t* out | |||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     IrdaTimings timings; |     IrdaTimings timings; | ||||||
|     bool     manchester_inverse_level; |     bool     manchester_start_from_space; | ||||||
|     uint32_t databit_len; |     uint32_t databit_len; | ||||||
|     IrdaCommonDecode decode; |     IrdaCommonDecode decode; | ||||||
|     IrdaCommonDecode decode_repeat; |     IrdaCommonDecode decode_repeat; | ||||||
| @ -21,26 +21,6 @@ const IrdaCommonProtocolSpec protocol_nec = { | |||||||
|     .encode_repeat = irda_encoder_nec_encode_repeat, |     .encode_repeat = irda_encoder_nec_encode_repeat, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const IrdaCommonProtocolSpec protocol_necext = { |  | ||||||
|     .timings = { |  | ||||||
|         .preamble_mark = IRDA_NEC_PREAMBULE_MARK, |  | ||||||
|         .preamble_space = IRDA_NEC_PREAMBULE_SPACE, |  | ||||||
|         .bit1_mark = IRDA_NEC_BIT1_MARK, |  | ||||||
|         .bit1_space = IRDA_NEC_BIT1_SPACE, |  | ||||||
|         .bit0_mark = IRDA_NEC_BIT0_MARK, |  | ||||||
|         .bit0_space = IRDA_NEC_BIT0_SPACE, |  | ||||||
|         .preamble_tolerance = IRDA_NEC_PREAMBLE_TOLERANCE, |  | ||||||
|         .bit_tolerance = IRDA_NEC_BIT_TOLERANCE, |  | ||||||
|         .silence_time = IRDA_NEC_SILENCE, |  | ||||||
|     }, |  | ||||||
|     .databit_len = 32, |  | ||||||
|     .decode = irda_common_decode_pdwm, |  | ||||||
|     .encode = irda_common_encode_pdwm, |  | ||||||
|     .interpret = irda_decoder_necext_interpret, |  | ||||||
|     .decode_repeat = irda_decoder_nec_decode_repeat, |  | ||||||
|     .encode_repeat = irda_encoder_nec_encode_repeat, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const IrdaCommonProtocolSpec protocol_samsung32 = { | const IrdaCommonProtocolSpec protocol_samsung32 = { | ||||||
|     .timings = { |     .timings = { | ||||||
|         .preamble_mark = IRDA_SAMSUNG_PREAMBULE_MARK, |         .preamble_mark = IRDA_SAMSUNG_PREAMBULE_MARK, | ||||||
| @ -71,7 +51,7 @@ const IrdaCommonProtocolSpec protocol_rc6 = { | |||||||
|         .silence_time = IRDA_RC6_SILENCE, |         .silence_time = IRDA_RC6_SILENCE, | ||||||
|     }, |     }, | ||||||
|     .databit_len = 1 + 3 + 1 + 8 + 8,   // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command
 |     .databit_len = 1 + 3 + 1 + 8 + 8,   // start_bit + 3 mode bits, + 1 toggle bit (x2 timing) + 8 address + 8 command
 | ||||||
|     .manchester_inverse_level = false, |     .manchester_start_from_space = false, | ||||||
|     .decode = irda_decoder_rc6_decode_manchester, |     .decode = irda_decoder_rc6_decode_manchester, | ||||||
|     .encode = irda_encoder_rc6_encode_manchester, |     .encode = irda_encoder_rc6_encode_manchester, | ||||||
|     .interpret = irda_decoder_rc6_interpret, |     .interpret = irda_decoder_rc6_interpret, | ||||||
| @ -79,3 +59,21 @@ const IrdaCommonProtocolSpec protocol_rc6 = { | |||||||
|     .encode_repeat = NULL, |     .encode_repeat = NULL, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | const IrdaCommonProtocolSpec protocol_rc5 = { | ||||||
|  |     .timings = { | ||||||
|  |         .preamble_mark = 0, | ||||||
|  |         .preamble_space = 0, | ||||||
|  |         .bit1_mark = IRDA_RC5_BIT, | ||||||
|  |         .preamble_tolerance = 0, | ||||||
|  |         .bit_tolerance = IRDA_RC5_BIT_TOLERANCE, | ||||||
|  |         .silence_time = IRDA_RC5_SILENCE, | ||||||
|  |     }, | ||||||
|  |     .databit_len = 1 + 1 + 1 + 5 + 6,   // start_bit + start_bit/command_bit + toggle_bit + 5 address + 6 command
 | ||||||
|  |     .manchester_start_from_space = true, | ||||||
|  |     .decode = irda_common_decode_manchester, | ||||||
|  |     .encode = irda_common_encode_manchester, | ||||||
|  |     .interpret = irda_decoder_rc5_interpret, | ||||||
|  |     .decode_repeat = NULL, | ||||||
|  |     .encode_repeat = NULL, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| @ -1,6 +1,6 @@ | |||||||
| #include "irda.h" | #include "irda.h" | ||||||
| #include "furi/check.h" | #include "furi/check.h" | ||||||
| #include "irda_common_i.h" | #include "common/irda_common_i.h" | ||||||
| #include "irda_protocol_defs_i.h" | #include "irda_protocol_defs_i.h" | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| @ -9,10 +9,6 @@ | |||||||
| #include "irda_i.h" | #include "irda_i.h" | ||||||
| #include <furi-hal-irda.h> | #include <furi-hal-irda.h> | ||||||
| 
 | 
 | ||||||
| struct IrdaDecoderHandler { |  | ||||||
|     void** ctx; |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     IrdaAlloc alloc; |     IrdaAlloc alloc; | ||||||
|     IrdaDecode decode; |     IrdaDecode decode; | ||||||
| @ -27,27 +23,36 @@ typedef struct { | |||||||
|     IrdaFree free; |     IrdaFree free; | ||||||
| } IrdaEncoders; | } IrdaEncoders; | ||||||
| 
 | 
 | ||||||
| typedef struct { | struct IrdaDecoderHandler { | ||||||
|     IrdaProtocol protocol; |     void** ctx; | ||||||
|     const char* name; |  | ||||||
|     IrdaDecoders decoder; |  | ||||||
|     IrdaEncoders encoder; |  | ||||||
|     uint8_t address_length; |  | ||||||
|     uint8_t command_length; |  | ||||||
|     uint32_t frequency; |  | ||||||
|     float duty_cycle; |  | ||||||
| } IrdaProtocolImplementation; |  | ||||||
| 
 |  | ||||||
| struct IrdaEncoderHandler { |  | ||||||
|     void* encoder; |  | ||||||
|     IrdaProtocol protocol; |  | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| // TODO: replace with key-value, Now we refer by enum index, which is dangerous.
 | struct IrdaEncoderHandler { | ||||||
| static const IrdaProtocolImplementation irda_protocols[] = { |     void* handler; | ||||||
|     // #0
 |     const IrdaEncoders* encoder; | ||||||
|     { .protocol = IrdaProtocolNEC, | }; | ||||||
|       .name = "NEC", | 
 | ||||||
|  | typedef struct { | ||||||
|  |     IrdaEncoders encoder; | ||||||
|  |     IrdaDecoders decoder; | ||||||
|  |     IrdaGetProtocolSpec get_protocol_spec; | ||||||
|  | } IrdaEncoderDecoder; | ||||||
|  | 
 | ||||||
|  | static const IrdaEncoderDecoder irda_encoder_decoder[] = { | ||||||
|  |     { | ||||||
|  |       .decoder = { | ||||||
|  |           .alloc = irda_decoder_rc5_alloc, | ||||||
|  |           .decode = irda_decoder_rc5_decode, | ||||||
|  |           .reset = irda_decoder_rc5_reset, | ||||||
|  |           .free = irda_decoder_rc5_free}, | ||||||
|  |       .encoder = { | ||||||
|  |           .alloc = irda_encoder_rc5_alloc, | ||||||
|  |           .encode = irda_encoder_rc5_encode, | ||||||
|  |           .reset = irda_encoder_rc5_reset, | ||||||
|  |           .free = irda_encoder_rc5_free}, | ||||||
|  |       .get_protocol_spec = irda_rc5_get_spec, | ||||||
|  |     }, | ||||||
|  |     { | ||||||
|       .decoder = { |       .decoder = { | ||||||
|           .alloc = irda_decoder_nec_alloc, |           .alloc = irda_decoder_nec_alloc, | ||||||
|           .decode = irda_decoder_nec_decode, |           .decode = irda_decoder_nec_decode, | ||||||
| @ -58,32 +63,9 @@ static const IrdaProtocolImplementation irda_protocols[] = { | |||||||
|           .encode = irda_encoder_nec_encode, |           .encode = irda_encoder_nec_encode, | ||||||
|           .reset = irda_encoder_nec_reset, |           .reset = irda_encoder_nec_reset, | ||||||
|           .free = irda_encoder_nec_free}, |           .free = irda_encoder_nec_free}, | ||||||
|       .address_length = 2, |       .get_protocol_spec = irda_nec_get_spec, | ||||||
|       .command_length = 2, |  | ||||||
|       .frequency = IRDA_COMMON_CARRIER_FREQUENCY, |  | ||||||
|       .duty_cycle = IRDA_COMMON_DUTY_CYCLE, |  | ||||||
|     }, |     }, | ||||||
|     // #1 - have to be after NEC
 |     { | ||||||
|     { .protocol = IrdaProtocolNECext, |  | ||||||
|       .name = "NECext", |  | ||||||
|       .decoder = { |  | ||||||
|           .alloc = irda_decoder_necext_alloc, |  | ||||||
|           .decode = irda_decoder_nec_decode, |  | ||||||
|           .reset = irda_decoder_nec_reset, |  | ||||||
|           .free = irda_decoder_nec_free}, |  | ||||||
|       .encoder = { |  | ||||||
|           .alloc = irda_encoder_necext_alloc, |  | ||||||
|           .encode = irda_encoder_nec_encode, |  | ||||||
|           .reset = irda_encoder_necext_reset, |  | ||||||
|           .free = irda_encoder_nec_free}, |  | ||||||
|       .address_length = 4, |  | ||||||
|       .command_length = 2, |  | ||||||
|       .frequency = IRDA_COMMON_CARRIER_FREQUENCY, |  | ||||||
|       .duty_cycle = IRDA_COMMON_DUTY_CYCLE, |  | ||||||
|     }, |  | ||||||
|     // #2
 |  | ||||||
|     { .protocol = IrdaProtocolSamsung32, |  | ||||||
|       .name ="Samsung32", |  | ||||||
|       .decoder = { |       .decoder = { | ||||||
|           .alloc = irda_decoder_samsung32_alloc, |           .alloc = irda_decoder_samsung32_alloc, | ||||||
|           .decode = irda_decoder_samsung32_decode, |           .decode = irda_decoder_samsung32_decode, | ||||||
| @ -94,14 +76,9 @@ static const IrdaProtocolImplementation irda_protocols[] = { | |||||||
|           .encode = irda_encoder_samsung32_encode, |           .encode = irda_encoder_samsung32_encode, | ||||||
|           .reset = irda_encoder_samsung32_reset, |           .reset = irda_encoder_samsung32_reset, | ||||||
|           .free = irda_encoder_samsung32_free}, |           .free = irda_encoder_samsung32_free}, | ||||||
|       .address_length = 2, |       .get_protocol_spec = irda_samsung32_get_spec, | ||||||
|       .command_length = 2, |  | ||||||
|       .frequency = IRDA_COMMON_CARRIER_FREQUENCY, |  | ||||||
|       .duty_cycle = IRDA_COMMON_DUTY_CYCLE, |  | ||||||
|     }, |     }, | ||||||
|     // #3
 |     { | ||||||
|     { .protocol = IrdaProtocolRC6, |  | ||||||
|       .name = "RC6", |  | ||||||
|       .decoder = { |       .decoder = { | ||||||
|           .alloc = irda_decoder_rc6_alloc, |           .alloc = irda_decoder_rc6_alloc, | ||||||
|           .decode = irda_decoder_rc6_decode, |           .decode = irda_decoder_rc6_decode, | ||||||
| @ -112,10 +89,7 @@ static const IrdaProtocolImplementation irda_protocols[] = { | |||||||
|           .encode = irda_encoder_rc6_encode, |           .encode = irda_encoder_rc6_encode, | ||||||
|           .reset = irda_encoder_rc6_reset, |           .reset = irda_encoder_rc6_reset, | ||||||
|           .free = irda_encoder_rc6_free}, |           .free = irda_encoder_rc6_free}, | ||||||
|       .address_length = 2, |       .get_protocol_spec = irda_rc6_get_spec, | ||||||
|       .command_length = 2, |  | ||||||
|       .frequency = IRDA_COMMON_CARRIER_FREQUENCY, |  | ||||||
|       .duty_cycle = IRDA_COMMON_DUTY_CYCLE, |  | ||||||
|     }, |     }, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -125,11 +99,10 @@ const IrdaMessage* irda_decode(IrdaDecoderHandler* handler, bool level, uint32_t | |||||||
|     IrdaMessage* message = NULL; |     IrdaMessage* message = NULL; | ||||||
|     IrdaMessage* result = NULL; |     IrdaMessage* result = NULL; | ||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { |     for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { | ||||||
|         if (irda_protocols[i].decoder.decode) { |         if (irda_encoder_decoder[i].decoder.decode) { | ||||||
|             message = irda_protocols[i].decoder.decode(handler->ctx[i], level, duration); |             message = irda_encoder_decoder[i].decoder.decode(handler->ctx[i], level, duration); | ||||||
|             if (!result && message) { |             if (!result && message) { | ||||||
|                 message->protocol = irda_protocols[i].protocol; |  | ||||||
|                 result = message; |                 result = message; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| @ -140,12 +113,12 @@ const IrdaMessage* irda_decode(IrdaDecoderHandler* handler, bool level, uint32_t | |||||||
| 
 | 
 | ||||||
| IrdaDecoderHandler* irda_alloc_decoder(void) { | IrdaDecoderHandler* irda_alloc_decoder(void) { | ||||||
|     IrdaDecoderHandler* handler = furi_alloc(sizeof(IrdaDecoderHandler)); |     IrdaDecoderHandler* handler = furi_alloc(sizeof(IrdaDecoderHandler)); | ||||||
|     handler->ctx = furi_alloc(sizeof(void*) * COUNT_OF(irda_protocols)); |     handler->ctx = furi_alloc(sizeof(void*) * COUNT_OF(irda_encoder_decoder)); | ||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { |     for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { | ||||||
|         handler->ctx[i] = 0; |         handler->ctx[i] = 0; | ||||||
|         if (irda_protocols[i].decoder.alloc) |         if (irda_encoder_decoder[i].decoder.alloc) | ||||||
|             handler->ctx[i] = irda_protocols[i].decoder.alloc(); |             handler->ctx[i] = irda_encoder_decoder[i].decoder.alloc(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     return handler; |     return handler; | ||||||
| @ -155,9 +128,9 @@ void irda_free_decoder(IrdaDecoderHandler* handler) { | |||||||
|     furi_assert(handler); |     furi_assert(handler); | ||||||
|     furi_assert(handler->ctx); |     furi_assert(handler->ctx); | ||||||
| 
 | 
 | ||||||
|     for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { |     for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { | ||||||
|         if (irda_protocols[i].decoder.free) |         if (irda_encoder_decoder[i].decoder.free) | ||||||
|             irda_protocols[i].decoder.free(handler->ctx[i]); |             irda_encoder_decoder[i].decoder.free(handler->ctx[i]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     free(handler->ctx); |     free(handler->ctx); | ||||||
| @ -165,114 +138,119 @@ void irda_free_decoder(IrdaDecoderHandler* handler) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void irda_reset_decoder(IrdaDecoderHandler* handler) { | void irda_reset_decoder(IrdaDecoderHandler* handler) { | ||||||
|     for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { |     for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { | ||||||
|         if (irda_protocols[i].decoder.reset) |         if (irda_encoder_decoder[i].decoder.reset) | ||||||
|             irda_protocols[i].decoder.reset(handler->ctx[i]); |             irda_encoder_decoder[i].decoder.reset(handler->ctx[i]); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| IrdaEncoderHandler* irda_alloc_encoder(void) { | IrdaEncoderHandler* irda_alloc_encoder(void) { | ||||||
|     IrdaEncoderHandler* handler = furi_alloc(sizeof(IrdaEncoderHandler)); |     IrdaEncoderHandler* handler = furi_alloc(sizeof(IrdaEncoderHandler)); | ||||||
|  |     handler->handler = NULL; | ||||||
|     handler->encoder = NULL; |     handler->encoder = NULL; | ||||||
|     handler->protocol = IrdaProtocolUnknown; |  | ||||||
|     return handler; |     return handler; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void irda_free_encoder(IrdaEncoderHandler* handler) { | void irda_free_encoder(IrdaEncoderHandler* handler) { | ||||||
|     furi_assert(handler); |     furi_assert(handler); | ||||||
|  |     const IrdaEncoders* encoder = handler->encoder; | ||||||
| 
 | 
 | ||||||
|     if (handler->encoder) { |     if (encoder || handler->handler) { | ||||||
|         furi_assert(irda_is_protocol_valid(handler->protocol)); |         furi_assert(encoder); | ||||||
|         furi_assert(irda_protocols[handler->protocol].encoder.free); |         furi_assert(handler->handler); | ||||||
|         irda_protocols[handler->protocol].encoder.free(handler->encoder); |         furi_assert(encoder->free); | ||||||
|  |         encoder->free(handler->handler); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     free(handler); |     free(handler); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static int irda_find_index_by_protocol(IrdaProtocol protocol) { | ||||||
|  |     for (int i = 0; i < COUNT_OF(irda_encoder_decoder); ++i) { | ||||||
|  |         if (irda_encoder_decoder[i].get_protocol_spec(protocol)) { | ||||||
|  |             return i; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return -1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void irda_reset_encoder(IrdaEncoderHandler* handler, const IrdaMessage* message) { | void irda_reset_encoder(IrdaEncoderHandler* handler, const IrdaMessage* message) { | ||||||
|     furi_assert(handler); |     furi_assert(handler); | ||||||
|     furi_assert(message); |     furi_assert(message); | ||||||
|     furi_assert(irda_is_protocol_valid(message->protocol)); |     int index = irda_find_index_by_protocol(message->protocol); | ||||||
|     furi_assert(irda_protocols[message->protocol].encoder.reset); |     furi_check(index >= 0); | ||||||
|     furi_assert(irda_protocols[message->protocol].encoder.alloc); | 
 | ||||||
|  |     const IrdaEncoders* required_encoder = &irda_encoder_decoder[index].encoder; | ||||||
|  |     furi_assert(required_encoder); | ||||||
|  |     furi_assert(required_encoder->reset); | ||||||
|  |     furi_assert(required_encoder->alloc); | ||||||
| 
 | 
 | ||||||
|     /* Realloc encoder if different protocol set */ |     /* Realloc encoder if different protocol set */ | ||||||
|     if (message->protocol != handler->protocol) { |     if (required_encoder != handler->encoder) { | ||||||
|         if (handler->encoder != NULL) { |         if (handler->handler != NULL) { | ||||||
|             furi_assert(handler->protocol != IrdaProtocolUnknown); |             furi_assert(handler->encoder->free); | ||||||
|             irda_protocols[handler->protocol].encoder.free(handler->encoder); |             handler->encoder->free(handler->handler); | ||||||
|         } |         } | ||||||
|         handler->encoder = irda_protocols[message->protocol].encoder.alloc(); |         handler->encoder = required_encoder; | ||||||
|         handler->protocol = message->protocol; |         handler->handler = handler->encoder->alloc(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     irda_protocols[handler->protocol].encoder.reset(handler->encoder, message); |     handler->encoder->reset(handler->handler, message); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| IrdaStatus irda_encode(IrdaEncoderHandler* handler, uint32_t* duration, bool* level) { | IrdaStatus irda_encode(IrdaEncoderHandler* handler, uint32_t* duration, bool* level) { | ||||||
|     furi_assert(handler); |     furi_assert(handler); | ||||||
|     furi_assert(irda_is_protocol_valid(handler->protocol)); |     furi_assert(duration); | ||||||
|     furi_assert(irda_protocols[handler->protocol].encoder.encode); |     furi_assert(level); | ||||||
|  |     const IrdaEncoders* encoder = handler->encoder; | ||||||
|  |     furi_assert(encoder); | ||||||
|  |     furi_assert(encoder->encode); | ||||||
| 
 | 
 | ||||||
|     IrdaStatus status = irda_protocols[handler->protocol].encoder.encode(handler->encoder, duration, level); |     IrdaStatus status = encoder->encode(handler->handler, duration, level); | ||||||
|     furi_assert(status != IrdaStatusError); |     furi_assert(status != IrdaStatusError); | ||||||
| 
 | 
 | ||||||
|     return status; |     return status; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| bool irda_is_protocol_valid(IrdaProtocol protocol) { | bool irda_is_protocol_valid(IrdaProtocol protocol) { | ||||||
|     return (protocol >= 0) && (protocol < COUNT_OF(irda_protocols)); |     return irda_find_index_by_protocol(protocol) >= 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| IrdaProtocol irda_get_protocol_by_name(const char* protocol_name) { | IrdaProtocol irda_get_protocol_by_name(const char* protocol_name) { | ||||||
|     for (int i = 0; i < COUNT_OF(irda_protocols); ++i) { |     for (IrdaProtocol protocol = 0; protocol < IrdaProtocolMAX; ++protocol) { | ||||||
|         if (!strcmp(irda_protocols[i].name, protocol_name)) |         const char* name = irda_get_protocol_name(protocol); | ||||||
|             return i; |         if (!strcmp(name, protocol_name)) | ||||||
|  |             return protocol; | ||||||
|     } |     } | ||||||
|     furi_assert(0); |  | ||||||
|     return IrdaProtocolUnknown; |     return IrdaProtocolUnknown; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | static const IrdaProtocolSpecification* irda_get_spec_by_protocol(IrdaProtocol protocol) { | ||||||
|  |     int index = irda_find_index_by_protocol(protocol); | ||||||
|  |     furi_check(index >= 0); | ||||||
|  |     const IrdaProtocolSpecification* spec = irda_encoder_decoder[index].get_protocol_spec(protocol); | ||||||
|  |     furi_assert(spec); | ||||||
|  |     return spec; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| const char* irda_get_protocol_name(IrdaProtocol protocol) { | const char* irda_get_protocol_name(IrdaProtocol protocol) { | ||||||
|     furi_assert(irda_is_protocol_valid(protocol)); |     return irda_get_spec_by_protocol(protocol)->name; | ||||||
|     if (irda_is_protocol_valid(protocol)) |  | ||||||
|         return irda_protocols[protocol].name; |  | ||||||
|     else |  | ||||||
|         return "Invalid"; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t irda_get_protocol_address_length(IrdaProtocol protocol) { | uint8_t irda_get_protocol_address_length(IrdaProtocol protocol) { | ||||||
|     furi_assert(irda_is_protocol_valid(protocol)); |     return irda_get_spec_by_protocol(protocol)->address_length; | ||||||
|     if (irda_is_protocol_valid(protocol)) |  | ||||||
|         return irda_protocols[protocol].address_length; |  | ||||||
|     else |  | ||||||
|         return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint8_t irda_get_protocol_command_length(IrdaProtocol protocol) { | uint8_t irda_get_protocol_command_length(IrdaProtocol protocol) { | ||||||
|     furi_assert(irda_is_protocol_valid(protocol)); |     return irda_get_spec_by_protocol(protocol)->command_length; | ||||||
|     if (irda_is_protocol_valid(protocol)) |  | ||||||
|         return irda_protocols[protocol].command_length; |  | ||||||
|     else |  | ||||||
|         return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| uint32_t irda_get_protocol_frequency(IrdaProtocol protocol) { | uint32_t irda_get_protocol_frequency(IrdaProtocol protocol) { | ||||||
|     furi_assert(irda_is_protocol_valid(protocol)); |     return irda_get_spec_by_protocol(protocol)->frequency; | ||||||
|     if (irda_is_protocol_valid(protocol)) |  | ||||||
|         return irda_protocols[protocol].frequency; |  | ||||||
|     else |  | ||||||
|         return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| float irda_get_protocol_duty_cycle(IrdaProtocol protocol) { | float irda_get_protocol_duty_cycle(IrdaProtocol protocol) { | ||||||
|     furi_assert(irda_is_protocol_valid(protocol)); |     return irda_get_spec_by_protocol(protocol)->duty_cycle; | ||||||
|     if (irda_is_protocol_valid(protocol)) |  | ||||||
|         return irda_protocols[protocol].duty_cycle; |  | ||||||
|     else |  | ||||||
|         return 0; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -26,6 +26,9 @@ typedef enum { | |||||||
|     IrdaProtocolNECext = 1, |     IrdaProtocolNECext = 1, | ||||||
|     IrdaProtocolSamsung32 = 2, |     IrdaProtocolSamsung32 = 2, | ||||||
|     IrdaProtocolRC6 = 3, |     IrdaProtocolRC6 = 3, | ||||||
|  |     IrdaProtocolRC5 = 4, | ||||||
|  |     IrdaProtocolRC5X = 5, | ||||||
|  |     IrdaProtocolMAX, | ||||||
| } IrdaProtocol; | } IrdaProtocol; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
| @ -58,6 +61,8 @@ IrdaDecoderHandler* irda_alloc_decoder(void); | |||||||
|  *                          and decoder resets its state and start decoding from the start. |  *                          and decoder resets its state and start decoding from the start. | ||||||
|  * \param[in]   duration    - duration of steady high/low input signal. |  * \param[in]   duration    - duration of steady high/low input signal. | ||||||
|  * \return      if message is ready, returns pointer to decoded message, returns NULL. |  * \return      if message is ready, returns pointer to decoded message, returns NULL. | ||||||
|  |  *              Note: ownership of returned ptr belongs to handler. So pointer is valid | ||||||
|  |  *              up to next irda_free_decoder(), irda_reset_decoder(), irda_decode() calls. | ||||||
|  */ |  */ | ||||||
| const IrdaMessage* irda_decode(IrdaDecoderHandler* handler, bool level, uint32_t duration); | const IrdaMessage* irda_decode(IrdaDecoderHandler* handler, bool level, uint32_t duration); | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -14,6 +14,16 @@ typedef struct { | |||||||
|     uint32_t bit_tolerance; |     uint32_t bit_tolerance; | ||||||
| } IrdaTimings; | } IrdaTimings; | ||||||
| 
 | 
 | ||||||
|  | typedef struct { | ||||||
|  |     const char* name; | ||||||
|  |     uint8_t address_length; | ||||||
|  |     uint8_t command_length; | ||||||
|  |     uint32_t frequency; | ||||||
|  |     float duty_cycle; | ||||||
|  | } IrdaProtocolSpecification; | ||||||
|  | 
 | ||||||
|  | typedef const IrdaProtocolSpecification* (*IrdaGetProtocolSpec) (IrdaProtocol protocol); | ||||||
|  | 
 | ||||||
| typedef void* (*IrdaAlloc) (void); | typedef void* (*IrdaAlloc) (void); | ||||||
| typedef IrdaMessage* (*IrdaDecode) (void* ctx, bool level, uint32_t duration); | typedef IrdaMessage* (*IrdaDecode) (void* ctx, bool level, uint32_t duration); | ||||||
| typedef void (*IrdaReset) (void*); | typedef void (*IrdaReset) (void*); | ||||||
| @ -21,7 +31,6 @@ typedef void (*IrdaFree) (void*); | |||||||
| 
 | 
 | ||||||
| typedef void (*IrdaEncoderReset)(void* encoder, const IrdaMessage* message); | typedef void (*IrdaEncoderReset)(void* encoder, const IrdaMessage* message); | ||||||
| typedef IrdaStatus (*IrdaEncode)(void* encoder, uint32_t* out, bool* polarity); | typedef IrdaStatus (*IrdaEncode)(void* encoder, uint32_t* out, bool* polarity); | ||||||
| typedef IrdaTimings (*IrdaTimingsGet)(void); |  | ||||||
| 
 | 
 | ||||||
| static inline uint8_t reverse(uint8_t value) { | static inline uint8_t reverse(uint8_t value) { | ||||||
|     uint8_t reverse_value = 0; |     uint8_t reverse_value = 0; | ||||||
|  | |||||||
| @ -4,7 +4,7 @@ | |||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include "irda.h" | #include "irda.h" | ||||||
| #include "irda_common_i.h" | #include "common/irda_common_i.h" | ||||||
| 
 | 
 | ||||||
| /***************************************************************************************************
 | /***************************************************************************************************
 | ||||||
| *   NEC protocol description | *   NEC protocol description | ||||||
| @ -40,22 +40,15 @@ void* irda_decoder_nec_alloc(void); | |||||||
| void irda_decoder_nec_reset(void* decoder); | void irda_decoder_nec_reset(void* decoder); | ||||||
| void irda_decoder_nec_free(void* decoder); | void irda_decoder_nec_free(void* decoder); | ||||||
| IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration); | IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration); | ||||||
| 
 |  | ||||||
| void* irda_encoder_nec_alloc(void); | void* irda_encoder_nec_alloc(void); | ||||||
| IrdaStatus irda_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level); | IrdaStatus irda_encoder_nec_encode(void* encoder_ptr, uint32_t* duration, bool* level); | ||||||
| void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message); | void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message); | ||||||
| void irda_encoder_nec_free(void* encoder_ptr); | void irda_encoder_nec_free(void* encoder_ptr); | ||||||
| 
 |  | ||||||
| void* irda_decoder_necext_alloc(void); |  | ||||||
| void* irda_encoder_necext_alloc(void); |  | ||||||
| void irda_encoder_necext_reset(void* encoder_ptr, const IrdaMessage* message); |  | ||||||
| 
 |  | ||||||
| bool irda_decoder_nec_interpret(IrdaCommonDecoder* decoder); | bool irda_decoder_nec_interpret(IrdaCommonDecoder* decoder); | ||||||
| bool irda_decoder_necext_interpret(IrdaCommonDecoder* decoder); |  | ||||||
| IrdaStatus irda_decoder_nec_decode_repeat(IrdaCommonDecoder* decoder); | IrdaStatus irda_decoder_nec_decode_repeat(IrdaCommonDecoder* decoder); | ||||||
| IrdaStatus irda_encoder_nec_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level); | IrdaStatus irda_encoder_nec_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level); | ||||||
|  | const IrdaProtocolSpecification* irda_nec_get_spec(IrdaProtocol protocol); | ||||||
| 
 | 
 | ||||||
| extern const IrdaCommonProtocolSpec protocol_necext; |  | ||||||
| extern const IrdaCommonProtocolSpec protocol_nec; | extern const IrdaCommonProtocolSpec protocol_nec; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| @ -98,15 +91,14 @@ void* irda_decoder_samsung32_alloc(void); | |||||||
| void irda_decoder_samsung32_reset(void* decoder); | void irda_decoder_samsung32_reset(void* decoder); | ||||||
| void irda_decoder_samsung32_free(void* decoder); | void irda_decoder_samsung32_free(void* decoder); | ||||||
| IrdaMessage* irda_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); | IrdaMessage* irda_decoder_samsung32_decode(void* decoder, bool level, uint32_t duration); | ||||||
| 
 |  | ||||||
| IrdaStatus irda_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level); | IrdaStatus irda_encoder_samsung32_encode(void* encoder_ptr, uint32_t* duration, bool* level); | ||||||
| void irda_encoder_samsung32_reset(void* encoder_ptr, const IrdaMessage* message); | void irda_encoder_samsung32_reset(void* encoder_ptr, const IrdaMessage* message); | ||||||
| void* irda_encoder_samsung32_alloc(void); | void* irda_encoder_samsung32_alloc(void); | ||||||
| void irda_encoder_samsung32_free(void* encoder_ptr); | void irda_encoder_samsung32_free(void* encoder_ptr); | ||||||
| 
 |  | ||||||
| bool irda_decoder_samsung32_interpret(IrdaCommonDecoder* decoder); | bool irda_decoder_samsung32_interpret(IrdaCommonDecoder* decoder); | ||||||
| IrdaStatus irda_decoder_samsung32_decode_repeat(IrdaCommonDecoder* decoder); | IrdaStatus irda_decoder_samsung32_decode_repeat(IrdaCommonDecoder* decoder); | ||||||
| IrdaStatus irda_encoder_samsung32_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level); | IrdaStatus irda_encoder_samsung32_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* duration, bool* level); | ||||||
|  | const IrdaProtocolSpecification* irda_samsung32_get_spec(IrdaProtocol protocol); | ||||||
| 
 | 
 | ||||||
| extern const IrdaCommonProtocolSpec protocol_samsung32; | extern const IrdaCommonProtocolSpec protocol_samsung32; | ||||||
| 
 | 
 | ||||||
| @ -132,6 +124,9 @@ extern const IrdaCommonProtocolSpec protocol_samsung32; | |||||||
| *    command - 8 bit | *    command - 8 bit | ||||||
| ***************************************************************************************************/ | ***************************************************************************************************/ | ||||||
| 
 | 
 | ||||||
|  | #define IRDA_RC6_CARRIER_FREQUENCY          36000 | ||||||
|  | #define IRDA_RC6_DUTY_CYCLE                 0.33 | ||||||
|  | 
 | ||||||
| #define IRDA_RC6_PREAMBULE_MARK             2666 | #define IRDA_RC6_PREAMBULE_MARK             2666 | ||||||
| #define IRDA_RC6_PREAMBULE_SPACE            889 | #define IRDA_RC6_PREAMBULE_SPACE            889 | ||||||
| #define IRDA_RC6_BIT                        444     // half of time-quant for 1 bit
 | #define IRDA_RC6_BIT                        444     // half of time-quant for 1 bit
 | ||||||
| @ -148,10 +143,57 @@ void* irda_encoder_rc6_alloc(void); | |||||||
| void irda_encoder_rc6_reset(void* encoder_ptr, const IrdaMessage* message); | void irda_encoder_rc6_reset(void* encoder_ptr, const IrdaMessage* message); | ||||||
| void irda_encoder_rc6_free(void* decoder); | void irda_encoder_rc6_free(void* decoder); | ||||||
| IrdaStatus irda_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); | IrdaStatus irda_encoder_rc6_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); | ||||||
| 
 |  | ||||||
| bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder); | bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder); | ||||||
| IrdaStatus irda_decoder_rc6_decode_manchester(IrdaCommonDecoder* decoder); | IrdaStatus irda_decoder_rc6_decode_manchester(IrdaCommonDecoder* decoder); | ||||||
| IrdaStatus irda_encoder_rc6_encode_manchester(IrdaCommonEncoder* encoder_ptr, uint32_t* duration, bool* polarity); | IrdaStatus irda_encoder_rc6_encode_manchester(IrdaCommonEncoder* encoder_ptr, uint32_t* duration, bool* polarity); | ||||||
|  | const IrdaProtocolSpecification* irda_rc6_get_spec(IrdaProtocol protocol); | ||||||
| 
 | 
 | ||||||
| extern const IrdaCommonProtocolSpec protocol_rc6; | extern const IrdaCommonProtocolSpec 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 - 8 bit | ||||||
|  | *    command - 8 bit | ||||||
|  | ***************************************************************************************************/ | ||||||
|  | 
 | ||||||
|  | #define IRDA_RC5_CARRIER_FREQUENCY          36000 | ||||||
|  | #define IRDA_RC5_DUTY_CYCLE                 0.33 | ||||||
|  | 
 | ||||||
|  | #define IRDA_RC5_PREAMBULE_MARK             0 | ||||||
|  | #define IRDA_RC5_PREAMBULE_SPACE            0 | ||||||
|  | #define IRDA_RC5_BIT                        888     // half of time-quant for 1 bit
 | ||||||
|  | #define IRDA_RC5_PREAMBLE_TOLERANCE         0.07    // percents
 | ||||||
|  | #define IRDA_RC5_BIT_TOLERANCE              120     // us
 | ||||||
|  | /* protocol allows 2700 silence, but it is hard to send 1 message without repeat */ | ||||||
|  | #define IRDA_RC5_SILENCE                    (2700 * 10) | ||||||
|  | 
 | ||||||
|  | void* irda_decoder_rc5_alloc(void); | ||||||
|  | void irda_decoder_rc5_reset(void* decoder); | ||||||
|  | void irda_decoder_rc5_free(void* decoder); | ||||||
|  | IrdaMessage* irda_decoder_rc5_decode(void* decoder, bool level, uint32_t duration); | ||||||
|  | void* irda_encoder_rc5_alloc(void); | ||||||
|  | void irda_encoder_rc5_reset(void* encoder_ptr, const IrdaMessage* message); | ||||||
|  | void irda_encoder_rc5_free(void* decoder); | ||||||
|  | IrdaStatus irda_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* polarity); | ||||||
|  | bool irda_decoder_rc5_interpret(IrdaCommonDecoder* decoder); | ||||||
|  | const IrdaProtocolSpecification* irda_rc5_get_spec(IrdaProtocol protocol); | ||||||
|  | 
 | ||||||
|  | extern const IrdaCommonProtocolSpec protocol_rc5; | ||||||
|  | 
 | ||||||
|  | |||||||
| @ -1,3 +1,4 @@ | |||||||
|  | #include "irda.h" | ||||||
| #include "irda_protocol_defs_i.h" | #include "irda_protocol_defs_i.h" | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| @ -14,27 +15,15 @@ bool irda_decoder_nec_interpret(IrdaCommonDecoder* decoder) { | |||||||
|     uint8_t command = decoder->data[2]; |     uint8_t command = decoder->data[2]; | ||||||
|     uint8_t command_inverse = decoder->data[3]; |     uint8_t command_inverse = decoder->data[3]; | ||||||
| 
 | 
 | ||||||
|     if ((command == (uint8_t) ~command_inverse) && (address == (uint8_t) ~address_inverse)) { |  | ||||||
|         decoder->message.command = command; |  | ||||||
|         decoder->message.address = address; |  | ||||||
|         decoder->message.repeat = false; |  | ||||||
|         result = true; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     return result; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Some NEC's extensions allow 16 bit address
 |  | ||||||
| bool irda_decoder_necext_interpret(IrdaCommonDecoder* decoder) { |  | ||||||
|     furi_assert(decoder); |  | ||||||
| 
 |  | ||||||
|     bool result = false; |  | ||||||
|     uint8_t command = decoder->data[2]; |  | ||||||
|     uint8_t command_inverse = decoder->data[3]; |  | ||||||
| 
 |  | ||||||
|     if (command == (uint8_t) ~command_inverse) { |     if (command == (uint8_t) ~command_inverse) { | ||||||
|         decoder->message.command = command; |         if (address == (uint8_t) ~address_inverse) { | ||||||
|  |             decoder->message.protocol = IrdaProtocolNEC; | ||||||
|  |             decoder->message.address = address; | ||||||
|  |         } else { | ||||||
|  |             decoder->message.protocol = IrdaProtocolNECext; | ||||||
|             decoder->message.address = decoder->data[0] | (decoder->data[1] << 8); |             decoder->message.address = decoder->data[0] | (decoder->data[1] << 8); | ||||||
|  |         } | ||||||
|  |         decoder->message.command = command; | ||||||
|         decoder->message.repeat = false; |         decoder->message.repeat = false; | ||||||
|         result = true; |         result = true; | ||||||
|     } |     } | ||||||
| @ -70,10 +59,6 @@ void* irda_decoder_nec_alloc(void) { | |||||||
|     return irda_common_decoder_alloc(&protocol_nec); |     return irda_common_decoder_alloc(&protocol_nec); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void* irda_decoder_necext_alloc(void) { |  | ||||||
|     return irda_common_decoder_alloc(&protocol_necext); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration) { | IrdaMessage* irda_decoder_nec_decode(void* decoder, bool level, uint32_t duration) { | ||||||
|     return irda_common_decode(decoder, level, duration); |     return irda_common_decode(decoder, level, duration); | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| #include "furi/check.h" | #include "furi/check.h" | ||||||
| #include "irda_common_i.h" | #include "irda.h" | ||||||
|  | #include "common/irda_common_i.h" | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include "../irda_i.h" | #include "../irda_i.h" | ||||||
| #include "irda_protocol_defs_i.h" | #include "irda_protocol_defs_i.h" | ||||||
| @ -14,6 +15,7 @@ static const uint32_t repeat_timings[] = { | |||||||
| 
 | 
 | ||||||
| void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message) { | void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message) { | ||||||
|     furi_assert(encoder_ptr); |     furi_assert(encoder_ptr); | ||||||
|  |     furi_assert(message); | ||||||
| 
 | 
 | ||||||
|     IrdaCommonEncoder* encoder = encoder_ptr; |     IrdaCommonEncoder* encoder = encoder_ptr; | ||||||
|     irda_common_encoder_reset(encoder); |     irda_common_encoder_reset(encoder); | ||||||
| @ -24,24 +26,11 @@ void irda_encoder_nec_reset(void* encoder_ptr, const IrdaMessage* message) { | |||||||
|     uint8_t command_inverse = ~command; |     uint8_t command_inverse = ~command; | ||||||
| 
 | 
 | ||||||
|     uint32_t* data = (void*) encoder->data; |     uint32_t* data = (void*) encoder->data; | ||||||
|     *data |= address; |     if (message->protocol == IrdaProtocolNEC) { | ||||||
|     *data |= address_inverse << 8; |         *data = (address | (address_inverse << 8)); | ||||||
|     *data |= command << 16; |     } else if (message->protocol == IrdaProtocolNECext) { | ||||||
|     *data |= command_inverse << 24; |         *data = (uint16_t) message->address; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
| void irda_encoder_necext_reset(void* encoder_ptr, const IrdaMessage* message) { |  | ||||||
|     furi_assert(encoder_ptr); |  | ||||||
| 
 |  | ||||||
|     IrdaCommonEncoder* encoder = encoder_ptr; |  | ||||||
|     irda_common_encoder_reset(encoder); |  | ||||||
| 
 |  | ||||||
|     uint16_t address = message->address; |  | ||||||
|     uint8_t command = message->command; |  | ||||||
|     uint8_t command_inverse = ~command; |  | ||||||
| 
 |  | ||||||
|     uint32_t* data = (void*) encoder->data; |  | ||||||
|     *data |= address; |  | ||||||
|     *data |= command << 16; |     *data |= command << 16; | ||||||
|     *data |= command_inverse << 24; |     *data |= command_inverse << 24; | ||||||
| } | } | ||||||
| @ -67,10 +56,6 @@ IrdaStatus irda_encoder_nec_encode_repeat(IrdaCommonEncoder* encoder, uint32_t* | |||||||
|     return done ? IrdaStatusDone : IrdaStatusOk; |     return done ? IrdaStatusDone : IrdaStatusOk; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void* irda_encoder_necext_alloc(void) { |  | ||||||
|     return irda_common_encoder_alloc(&protocol_necext); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void* irda_encoder_nec_alloc(void) { | void* irda_encoder_nec_alloc(void) { | ||||||
|     return irda_common_encoder_alloc(&protocol_nec); |     return irda_common_encoder_alloc(&protocol_nec); | ||||||
| } | } | ||||||
|  | |||||||
							
								
								
									
										28
									
								
								lib/irda/encoder_decoder/nec/irda_nec_spec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								lib/irda/encoder_decoder/nec/irda_nec_spec.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | #include "../irda_i.h" | ||||||
|  | #include "irda_protocol_defs_i.h" | ||||||
|  | 
 | ||||||
|  | static const IrdaProtocolSpecification irda_nec_protocol_specification = { | ||||||
|  |       .name = "NEC", | ||||||
|  |       .address_length = 2, | ||||||
|  |       .command_length = 2, | ||||||
|  |       .frequency = IRDA_COMMON_CARRIER_FREQUENCY, | ||||||
|  |       .duty_cycle = IRDA_COMMON_DUTY_CYCLE, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const IrdaProtocolSpecification irda_necext_protocol_specification = { | ||||||
|  |       .name = "NECext", | ||||||
|  |       .address_length = 4, | ||||||
|  |       .command_length = 2, | ||||||
|  |       .frequency = IRDA_COMMON_CARRIER_FREQUENCY, | ||||||
|  |       .duty_cycle = IRDA_COMMON_DUTY_CYCLE, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaProtocolSpecification* irda_nec_get_spec(IrdaProtocol protocol) { | ||||||
|  |     if (protocol == IrdaProtocolNEC) | ||||||
|  |         return &irda_nec_protocol_specification; | ||||||
|  |     else if (protocol == IrdaProtocolNECext) | ||||||
|  |         return &irda_necext_protocol_specification; | ||||||
|  |     else | ||||||
|  |         return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										79
									
								
								lib/irda/encoder_decoder/rc5/irda_decoder_rc5.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								lib/irda/encoder_decoder/rc5/irda_decoder_rc5.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,79 @@ | |||||||
|  | #include "irda.h" | ||||||
|  | #include <stdbool.h> | ||||||
|  | #include <stddef.h> | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <furi.h> | ||||||
|  | #include "../irda_i.h" | ||||||
|  | #include "../irda_protocol_defs_i.h" | ||||||
|  | 
 | ||||||
|  | typedef struct { | ||||||
|  |     IrdaCommonDecoder* common_decoder; | ||||||
|  |     bool toggle; | ||||||
|  | } IrdaRc5Decoder; | ||||||
|  | 
 | ||||||
|  | bool irda_decoder_rc5_interpret(IrdaCommonDecoder* decoder) { | ||||||
|  |     furi_assert(decoder); | ||||||
|  | 
 | ||||||
|  |     bool result = false; | ||||||
|  |     uint32_t* data = (void*) &decoder->data[0]; | ||||||
|  |     /* Manchester (inverse):
 | ||||||
|  |      *      0->1 : 1 | ||||||
|  |      *      1->0 : 0 | ||||||
|  |      */ | ||||||
|  |     decoder->data[0] = ~decoder->data[0]; | ||||||
|  |     decoder->data[1] = ~decoder->data[1]; | ||||||
|  | 
 | ||||||
|  |     // MSB first
 | ||||||
|  |     uint8_t address = reverse((uint8_t) decoder->data[0]) & 0x1F; | ||||||
|  |     uint8_t command = (reverse((uint8_t) decoder->data[1]) >> 2) & 0x3F; | ||||||
|  |     bool start_bit1 = *data & 0x01; | ||||||
|  |     bool start_bit2 = *data & 0x02; | ||||||
|  |     bool toggle = !!(*data & 0x04); | ||||||
|  | 
 | ||||||
|  |     if (start_bit1 == 1) { | ||||||
|  |         IrdaProtocol protocol = start_bit2 ? IrdaProtocolRC5 : IrdaProtocolRC5X; | ||||||
|  |         IrdaMessage* message = &decoder->message; | ||||||
|  |         IrdaRc5Decoder *rc5_decoder = decoder->context; | ||||||
|  |         bool *prev_toggle = &rc5_decoder->toggle; | ||||||
|  |         if ((message->address == address) | ||||||
|  |             && (message->command == command) | ||||||
|  |             && (message->protocol == protocol)) { | ||||||
|  |             message->repeat = (toggle == *prev_toggle); | ||||||
|  |         } else { | ||||||
|  |             message->repeat = false; | ||||||
|  |         } | ||||||
|  |         *prev_toggle = toggle; | ||||||
|  |         message->command = command; | ||||||
|  |         message->address = address; | ||||||
|  |         message->protocol = protocol; | ||||||
|  | 
 | ||||||
|  |         result = true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void* irda_decoder_rc5_alloc(void) { | ||||||
|  |     IrdaRc5Decoder* decoder = furi_alloc(sizeof(IrdaRc5Decoder)); | ||||||
|  |     decoder->toggle = false; | ||||||
|  |     decoder->common_decoder = irda_common_decoder_alloc(&protocol_rc5); | ||||||
|  |     irda_common_decoder_set_context(decoder->common_decoder, decoder); | ||||||
|  |     return decoder; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaMessage* irda_decoder_rc5_decode(void* decoder, bool level, uint32_t duration) { | ||||||
|  |     IrdaRc5Decoder* decoder_rc5 = decoder; | ||||||
|  |     return irda_common_decode(decoder_rc5->common_decoder, level, duration); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void irda_decoder_rc5_free(void* decoder) { | ||||||
|  |     IrdaRc5Decoder* decoder_rc5 = decoder; | ||||||
|  |     irda_common_decoder_free(decoder_rc5->common_decoder); | ||||||
|  |     free(decoder_rc5); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void irda_decoder_rc5_reset(void* decoder) { | ||||||
|  |     IrdaRc5Decoder* decoder_rc5 = decoder; | ||||||
|  |     irda_common_decoder_reset(decoder_rc5->common_decoder); | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										55
									
								
								lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								lib/irda/encoder_decoder/rc5/irda_encoder_rc5.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,55 @@ | |||||||
|  | #include "furi/memmgr.h" | ||||||
|  | #include "irda.h" | ||||||
|  | #include "common/irda_common_i.h" | ||||||
|  | #include "irda_protocol_defs_i.h" | ||||||
|  | #include <stdint.h> | ||||||
|  | #include "../irda_i.h" | ||||||
|  | 
 | ||||||
|  | typedef struct IrdaEncoderRC5 { | ||||||
|  |     IrdaCommonEncoder* common_encoder; | ||||||
|  |     bool toggle_bit; | ||||||
|  | } IrdaEncoderRC5; | ||||||
|  | 
 | ||||||
|  | void irda_encoder_rc5_reset(void* encoder_ptr, const IrdaMessage* message) { | ||||||
|  |     furi_assert(encoder_ptr); | ||||||
|  | 
 | ||||||
|  |     IrdaEncoderRC5* encoder = encoder_ptr; | ||||||
|  |     IrdaCommonEncoder* common_encoder = encoder->common_encoder; | ||||||
|  |     irda_common_encoder_reset(common_encoder); | ||||||
|  | 
 | ||||||
|  |     uint32_t* data = (void*) common_encoder->data; | ||||||
|  |     /* RC5 */ | ||||||
|  |     *data |= 0x01;    // start bit
 | ||||||
|  |     if (message->protocol == IrdaProtocolRC5) { | ||||||
|  |         *data |= 0x02;    // start bit
 | ||||||
|  |     } | ||||||
|  |     *data |= encoder->toggle_bit ? 0x04 : 0; | ||||||
|  |     *data |= (reverse(message->address) >> 3) << 3; /* address 5 bit */ | ||||||
|  |     *data |= (reverse(message->command) >> 2) << 8; /* command 6 bit */ | ||||||
|  | 
 | ||||||
|  |     common_encoder->data[0] = ~common_encoder->data[0]; | ||||||
|  |     common_encoder->data[1] = ~common_encoder->data[1]; | ||||||
|  | 
 | ||||||
|  |     encoder->toggle_bit ^= 1; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | IrdaStatus irda_encoder_rc5_encode(void* encoder_ptr, uint32_t* duration, bool* level) { | ||||||
|  |     IrdaEncoderRC5* encoder = encoder_ptr; | ||||||
|  |     return irda_common_encode(encoder->common_encoder, duration, level); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void* irda_encoder_rc5_alloc(void) { | ||||||
|  |     IrdaEncoderRC5* encoder = furi_alloc(sizeof(IrdaEncoderRC5)); | ||||||
|  |     encoder->common_encoder = irda_common_encoder_alloc(&protocol_rc5); | ||||||
|  |     encoder->toggle_bit = false; | ||||||
|  |     return encoder; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void irda_encoder_rc5_free(void* encoder_ptr) { | ||||||
|  |     furi_assert(encoder_ptr); | ||||||
|  | 
 | ||||||
|  |     IrdaEncoderRC5* encoder = encoder_ptr; | ||||||
|  |     free(encoder->common_encoder); | ||||||
|  |     free(encoder); | ||||||
|  | } | ||||||
|  | 
 | ||||||
							
								
								
									
										28
									
								
								lib/irda/encoder_decoder/rc5/irda_rc5_spec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								lib/irda/encoder_decoder/rc5/irda_rc5_spec.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,28 @@ | |||||||
|  | #include "../irda_i.h" | ||||||
|  | #include "irda_protocol_defs_i.h" | ||||||
|  | 
 | ||||||
|  | static const IrdaProtocolSpecification irda_rc5_protocol_specification = { | ||||||
|  |       .name = "RC5", | ||||||
|  |       .address_length = 2, | ||||||
|  |       .command_length = 2, | ||||||
|  |       .frequency = IRDA_RC5_CARRIER_FREQUENCY, | ||||||
|  |       .duty_cycle = IRDA_RC5_DUTY_CYCLE, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | static const IrdaProtocolSpecification irda_rc5x_protocol_specification = { | ||||||
|  |       .name = "RC5X", | ||||||
|  |       .address_length = 2, | ||||||
|  |       .command_length = 2, | ||||||
|  |       .frequency = IRDA_RC5_CARRIER_FREQUENCY, | ||||||
|  |       .duty_cycle = IRDA_RC5_DUTY_CYCLE, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaProtocolSpecification* irda_rc5_get_spec(IrdaProtocol protocol) { | ||||||
|  |     if (protocol == IrdaProtocolRC5) | ||||||
|  |         return &irda_rc5_protocol_specification; | ||||||
|  |     else if (protocol == IrdaProtocolRC5X) | ||||||
|  |         return &irda_rc5x_protocol_specification; | ||||||
|  |     else | ||||||
|  |         return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -37,6 +37,7 @@ bool irda_decoder_rc6_interpret(IrdaCommonDecoder* decoder) { | |||||||
|         *prev_toggle = toggle; |         *prev_toggle = toggle; | ||||||
|         message->command = command; |         message->command = command; | ||||||
|         message->address = address; |         message->address = address; | ||||||
|  |         message->protocol = IrdaProtocolRC6; | ||||||
|         result = true; |         result = true; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| #include "furi/memmgr.h" | #include "furi/memmgr.h" | ||||||
| #include "irda.h" | #include "irda.h" | ||||||
| #include "irda_common_i.h" | #include "common/irda_common_i.h" | ||||||
| #include "irda_protocol_defs_i.h" | #include "irda_protocol_defs_i.h" | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include "../irda_i.h" | #include "../irda_i.h" | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								lib/irda/encoder_decoder/rc6/irda_rc6_spec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/irda/encoder_decoder/rc6/irda_rc6_spec.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | #include "../irda_i.h" | ||||||
|  | #include "irda_protocol_defs_i.h" | ||||||
|  | 
 | ||||||
|  | static const IrdaProtocolSpecification irda_rc6_protocol_specification = { | ||||||
|  |       .name = "RC6", | ||||||
|  |       .address_length = 2, | ||||||
|  |       .command_length = 2, | ||||||
|  |       .frequency = IRDA_RC6_CARRIER_FREQUENCY, | ||||||
|  |       .duty_cycle = IRDA_RC6_DUTY_CYCLE, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaProtocolSpecification* irda_rc6_get_spec(IrdaProtocol protocol) { | ||||||
|  |     if (protocol == IrdaProtocolRC6) | ||||||
|  |         return &irda_rc6_protocol_specification; | ||||||
|  |     else | ||||||
|  |         return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| @ -1,3 +1,4 @@ | |||||||
|  | #include "irda.h" | ||||||
| #include "irda_protocol_defs_i.h" | #include "irda_protocol_defs_i.h" | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| @ -17,6 +18,7 @@ bool irda_decoder_samsung32_interpret(IrdaCommonDecoder* decoder) { | |||||||
|     if ((address1 == address2) && (command == (uint8_t) ~command_inverse)) { |     if ((address1 == address2) && (command == (uint8_t) ~command_inverse)) { | ||||||
|         decoder->message.command = command; |         decoder->message.command = command; | ||||||
|         decoder->message.address = address1; |         decoder->message.address = address1; | ||||||
|  |         decoder->message.protocol = IrdaProtocolSamsung32; | ||||||
|         decoder->message.repeat = false; |         decoder->message.repeat = false; | ||||||
|         result = true; |         result = true; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| #include "furi/check.h" | #include "furi/check.h" | ||||||
| #include "irda_common_i.h" | #include "common/irda_common_i.h" | ||||||
| #include <stdint.h> | #include <stdint.h> | ||||||
| #include "../irda_i.h" | #include "../irda_i.h" | ||||||
| #include "irda_protocol_defs_i.h" | #include "irda_protocol_defs_i.h" | ||||||
|  | |||||||
							
								
								
									
										18
									
								
								lib/irda/encoder_decoder/samsung/irda_samsung_spec.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								lib/irda/encoder_decoder/samsung/irda_samsung_spec.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,18 @@ | |||||||
|  | #include "../irda_i.h" | ||||||
|  | #include "irda_protocol_defs_i.h" | ||||||
|  | 
 | ||||||
|  | static const IrdaProtocolSpecification irda_samsung32_protocol_specification = { | ||||||
|  |       .name = "Samsung32", | ||||||
|  |       .address_length = 2, | ||||||
|  |       .command_length = 2, | ||||||
|  |       .frequency = IRDA_COMMON_CARRIER_FREQUENCY, | ||||||
|  |       .duty_cycle = IRDA_COMMON_DUTY_CYCLE, | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | const IrdaProtocolSpecification* irda_samsung32_get_spec(IrdaProtocol protocol) { | ||||||
|  |     if (protocol == IrdaProtocolSamsung32) | ||||||
|  |         return &irda_samsung32_protocol_specification; | ||||||
|  |     else | ||||||
|  |         return NULL; | ||||||
|  | } | ||||||
|  | 
 | ||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Albert Kharisov
						Albert Kharisov