Merge branch 'fz-dev' into dev

This commit is contained in:
MX 2023-01-18 18:26:49 +03:00
commit c708a301f5
No known key found for this signature in database
GPG Key ID: 6C4C311DFD4B4AB5
79 changed files with 1133 additions and 847 deletions

View File

@ -1 +1 @@
--rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap

View File

@ -105,6 +105,12 @@
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full"
},
{
"label": "[Debug] Create PVS-Studio report",
"group": "build",
"type": "shell",
"command": "./fbt firmware_pvs"
},
{
"label": "[Debug] Build FAPs",
"group": "build",
@ -138,6 +144,18 @@
"Serial Console"
]
},
{
"label": "[Debug] Build and upload all FAPs to Flipper over USB",
"group": "build",
"type": "shell",
"command": "./fbt fap_deploy"
},
{
"label": "[Release] Build and upload all FAPs to Flipper over USB",
"group": "build",
"type": "shell",
"command": "./fbt COMPACT=1 DEBUG=0 fap_deploy"
},
{
// Press Ctrl+] to quit
"label": "Serial Console",
@ -145,7 +163,7 @@
"command": "./fbt cli",
"group": "none",
"isBackground": true,
"options": {
"options": {
"env": {
"FBT_NO_SYNC": "0"
}
@ -162,4 +180,4 @@
}
}
]
}
}

View File

@ -148,9 +148,12 @@ fap_dist = [
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
),
),
distenv.Install(
f"#/dist/{dist_dir}/apps",
"#/assets/resources/apps",
*(
distenv.Install(
f"#/dist/{dist_dir}/apps/{app_artifact.app.fap_category}",
app_artifact.compact[0],
)
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
),
]
Depends(
@ -165,6 +168,14 @@ Alias("fap_dist", fap_dist)
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
# Copy all faps to device
fap_deploy = distenv.PhonyTarget(
"fap_deploy",
"${PYTHON3} ${ROOT_DIR}/scripts/storage.py send ${SOURCE} /ext/apps",
source=Dir("#/assets/resources/apps"),
)
# Target for bundling core2 package for qFlipper
copro_dist = distenv.CoproBuilder(

View File

@ -31,7 +31,8 @@ void AccessorApp::run(void) {
onewire_host_stop(onewire_host);
}
AccessorApp::AccessorApp() {
AccessorApp::AccessorApp()
: text_store{0} {
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
onewire_host = onewire_host_alloc();
furi_hal_power_enable_otg();

View File

@ -171,9 +171,6 @@ bool WIEGAND::DoWiegandConversion() {
return true;
} else {
_lastWiegand = sysTick;
_bitCount = 0;
_cardTemp = 0;
_cardTempHigh = 0;
return false;
}

View File

@ -2,8 +2,11 @@
#include <gui/canvas.h>
#include <gui/elements.h>
#include <lib/toolbox/float_tools.h>
#include <m-array.h>
#include <furi.h>
#include <inttypes.h>
#include <stdint.h>
struct BtTestParam {
@ -98,16 +101,16 @@ static void bt_test_draw_callback(Canvas* canvas, void* _model) {
elements_scrollbar(canvas, model->position, BtTestParamArray_size(model->params));
canvas_draw_str(canvas, 6, 60, model->message);
if(model->state == BtTestStateStarted) {
if(model->rssi != 0.0f) {
if(!float_is_equal(model->rssi, 0.0f)) {
snprintf(info_str, sizeof(info_str), "RSSI:%3.1f dB", (double)model->rssi);
canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str);
}
} else if(model->state == BtTestStateStopped) {
if(model->packets_num_rx) {
snprintf(info_str, sizeof(info_str), "%ld pack rcv", model->packets_num_rx);
snprintf(info_str, sizeof(info_str), "%" PRIu32 " pack rcv", model->packets_num_rx);
canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str);
} else if(model->packets_num_tx) {
snprintf(info_str, sizeof(info_str), "%ld pack sent", model->packets_num_tx);
snprintf(info_str, sizeof(info_str), "%" PRIu32 " pack sent", model->packets_num_tx);
canvas_draw_str_aligned(canvas, 124, 60, AlignRight, AlignBottom, info_str);
}
}
@ -153,7 +156,7 @@ static bool bt_test_input_callback(InputEvent* event, void* context) {
}
void bt_test_process_up(BtTest* bt_test) {
with_view_model(
with_view_model( // -V658
bt_test->view,
BtTestModel * model,
{

View File

@ -48,7 +48,7 @@ FileBrowserApp* file_browser_app_alloc(char* arg) {
app->file_path = furi_string_alloc();
app->file_browser = file_browser_alloc(app->file_path);
file_browser_configure(app->file_browser, "*", NULL, true, &I_badusb_10px, true);
file_browser_configure(app->file_browser, "*", NULL, true, false, &I_badusb_10px, true);
view_dispatcher_add_view(
app->view_dispatcher, FileBrowserAppViewStart, widget_get_view(app->widget));

View File

@ -1,5 +1,5 @@
App(
appid="sample_apps",
name="Sample apps bundle",
appid="example_apps",
name="Example apps bundle",
apptype=FlipperAppType.METAPACKAGE,
)

View File

@ -75,8 +75,8 @@ static const DuckyKey ducky_keys[] = {
{"BREAK", HID_KEYBOARD_PAUSE},
{"PAUSE", HID_KEYBOARD_PAUSE},
{"CAPSLOCK", HID_KEYBOARD_CAPS_LOCK},
{"DELETE", HID_KEYBOARD_DELETE},
{"BACKSPACE", HID_KEYPAD_BACKSPACE},
{"DELETE", HID_KEYBOARD_DELETE_FORWARD},
{"BACKSPACE", HID_KEYBOARD_DELETE},
{"END", HID_KEYBOARD_END},
{"ESC", HID_KEYBOARD_ESCAPE},
{"ESCAPE", HID_KEYBOARD_ESCAPE},

View File

@ -14,9 +14,12 @@ static const char* uart_ch[] = {"13,14", "15,16"};
static const char* flow_pins[] = {"None", "2,3", "6,7", "16,15"};
static const char* baudrate_mode[] = {"Host"};
static const uint32_t baudrate_list[] = {
1200,
2400,
4800,
9600,
19200,
28800,
38400,
57600,
115200,

View File

@ -56,7 +56,7 @@ static bool desktop_view_slideshow_input(InputEvent* event, void* context) {
instance->callback(DesktopSlideshowCompleted, instance->context);
}
update_view = true;
} else if(event->key == InputKeyOk) {
} else if(event->key == InputKeyOk && instance->timer) {
if(event->type == InputTypePress) {
furi_timer_start(instance->timer, DESKTOP_SLIDESHOW_POWEROFF_SHORT);
} else if(event->type == InputTypeRelease) {

View File

@ -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;
}

View File

@ -29,7 +29,7 @@ typedef struct {
TextInputValidatorCallback validator_callback;
void* validator_callback_context;
FuriString* validator_text;
bool valadator_message_visible;
bool validator_message_visible;
} TextInputModel;
static const uint8_t keyboard_origin_x = 1;
@ -138,7 +138,7 @@ static bool char_is_lowercase(char letter) {
static char char_to_uppercase(const char letter) {
if(letter == '_') {
return 0x20;
} else if(isalpha(letter)) {
} else if(islower(letter)) {
return (letter - 0x20);
} else {
return letter;
@ -254,7 +254,7 @@ static void text_input_view_draw_callback(Canvas* canvas, void* _model) {
}
}
}
if(model->valadator_message_visible) {
if(model->validator_message_visible) {
canvas_set_font(canvas, FontSecondary);
canvas_set_color(canvas, ColorWhite);
canvas_draw_box(canvas, 8, 10, 110, 48);
@ -309,7 +309,9 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b
char selected = get_selected_char(model);
size_t text_length = strlen(model->text_buffer);
if(shift) {
bool toogle_case = text_length == 0;
if(shift) toogle_case = !toogle_case;
if(toogle_case) {
selected = char_to_uppercase(selected);
}
@ -317,7 +319,7 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b
if(model->validator_callback &&
(!model->validator_callback(
model->text_buffer, model->validator_text, model->validator_callback_context))) {
model->valadator_message_visible = true;
model->validator_message_visible = true;
furi_timer_start(text_input->timer, furi_kernel_get_tick_frequency() * 4);
} else if(model->callback != 0 && text_length > 0) {
model->callback(model->callback_context);
@ -329,9 +331,6 @@ static void text_input_handle_ok(TextInput* text_input, TextInputModel* model, b
text_length = 0;
}
if(text_length < (model->text_buffer_size - 1)) {
if(text_length == 0 && char_is_lowercase(selected)) {
selected = char_to_uppercase(selected);
}
model->text_buffer[text_length] = selected;
model->text_buffer[text_length + 1] = 0;
}
@ -349,8 +348,8 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) {
TextInputModel* model = view_get_model(text_input->view);
if((!(event->type == InputTypePress) && !(event->type == InputTypeRelease)) &&
model->valadator_message_visible) {
model->valadator_message_visible = false;
model->validator_message_visible) {
model->validator_message_visible = false;
consumed = true;
} else if(event->type == InputTypeShort) {
consumed = true;
@ -436,7 +435,7 @@ void text_input_timer_callback(void* context) {
with_view_model(
text_input->view,
TextInputModel * model,
{ model->valadator_message_visible = false; },
{ model->validator_message_visible = false; },
true);
}
@ -496,7 +495,7 @@ void text_input_reset(TextInput* text_input) {
model->validator_callback = NULL;
model->validator_callback_context = NULL;
furi_string_reset(model->validator_text);
model->valadator_message_visible = false;
model->validator_message_visible = false;
},
true);
}

View File

@ -91,7 +91,7 @@ void widget_add_string_element(
* @param[in] text Formatted text. The following formats are available:
* "\e#Bold text\e#" - bold font is used
* "\e*Monospaced text\e*" - monospaced font is used
* "\e#Inversed text\e#" - white text on black background
* "\e!Inversed text\e!" - white text on black background
* @param strip_to_dots Strip text to ... if does not fit to width
*/
void widget_add_text_box_element(

View File

@ -19,7 +19,7 @@ extern "C" {
typedef enum {
InputTypePress, /**< Press event, emitted after debounce */
InputTypeRelease, /**< Release event, emitted after debounce */
InputTypeShort, /**< Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */
InputTypeShort, /**< Short event, emitted after InputTypeRelease done within INPUT_LONG_PRESS interval */
InputTypeLong, /**< Long event, emitted after INPUT_LONG_PRESS_COUNTS interval, asynchronous to InputTypeRelease */
InputTypeRepeat, /**< Repeat event, emitted with INPUT_LONG_PRESS_COUNTS period after InputTypeLong event */
InputTypeMAX, /**< Special value for exceptional */

View File

@ -54,13 +54,14 @@ assetsenv.Alias("proto_ver", proto_ver)
# Gather everything into a static lib
assets_parts = (icons, proto, dolphin_blocking, dolphin_internal, proto_ver)
env.Replace(FW_ASSETS_HEADERS=assets_parts)
assetslib = assetsenv.Library("${FW_LIB_NAME}", assets_parts)
assetsenv.Install("${LIB_DIST_DIR}", assetslib)
# Resources for SD card
env.SetDefault(FW_RESOURCES=None)
if assetsenv["IS_BASE_FIRMWARE"]:
# External dolphin animations
dolphin_external = assetsenv.DolphinExtBuilder(
@ -92,8 +93,7 @@ if assetsenv["IS_BASE_FIRMWARE"]:
)
# Exporting resources node to external environment
env["FW_ASSETS_HEADERS"] = assets_parts
env["FW_RESOURCES"] = resources
env.Replace(FW_RESOURCES=resources)
assetsenv.Alias("resources", resources)
Return("assetslib")

View File

@ -79,7 +79,7 @@ STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script fo
ENTER
STRING More information about script syntax can be found here:
ENTER
STRING https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript
STRING https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/BadUsbScriptFormat.md
ENTER
STRING EOF

View File

@ -80,5 +80,5 @@ STRING Flipper Zero BadUSB feature is compatible with USB Rubber Ducky script fo
ENTER
STRING More information about script syntax can be found here:
ENTER
STRING https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Duckyscript
STRING https://github.com/flipperdevices/flipperzero-firmware/blob/dev/documentation/file_formats/BadUsbScriptFormat.md
ENTER

View File

@ -56,6 +56,7 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio
- `get_stlink` - output serial numbers for attached STLink probes. Used for specifying an adapter with `OPENOCD_ADAPTER_SERIAL=...`.
- `lint`, `format` - run clang-format on the C source code to check and reformat it according to the `.clang-format` specs.
- `lint_py`, `format_py` - run [black](https://black.readthedocs.io/en/stable/index.html) on the Python source code, build system files & application manifests.
- `firmware_pvs` - generate a PVS Studio report for the firmware. Requires PVS Studio to be availabe on your system's `PATH`.
- `cli` - start a Flipper CLI session over USB.
### Firmware targets

View File

@ -15,6 +15,7 @@ env = ENV.Clone(
("compilation_db", {"COMPILATIONDB_COMSTR": "\tCDB\t${TARGET}"}),
"fwbin",
"fbt_apps",
"pvsstudio",
],
COMPILATIONDB_USE_ABSPATH=False,
BUILD_DIR=fw_build_meta["build_dir"],
@ -69,6 +70,8 @@ env = ENV.Clone(
],
},
},
SDK_APISYMS=None,
_APP_ICONS=None,
)
@ -128,9 +131,6 @@ if extra_int_apps := GetOption("extra_int_apps"):
fwenv.Append(APPS=extra_int_apps.split(","))
if fwenv["FAP_EXAMPLES"]:
fwenv.Append(APPDIRS=[("applications/examples", False)])
for app_dir, _ in env["APPDIRS"]:
app_dir_node = env.Dir("#").Dir(app_dir)
@ -273,6 +273,24 @@ Precious(fwcdb)
NoClean(fwcdb)
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_cdb", fwcdb)
pvscheck = fwenv.PVSCheck("pvsreport.log", fwcdb)
Depends(
pvscheck,
[
fwenv["FW_VERSION_JSON"],
fwenv["FW_ASSETS_HEADERS"],
fwenv["SDK_APISYMS"],
fwenv["_APP_ICONS"],
],
)
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_pvscheck", pvscheck)
AlwaysBuild(pvscheck)
Precious(pvscheck)
pvsreport = fwenv.PVSReport(None, pvscheck, REPORT_DIR=Dir("pvsreport"))
Alias(fwenv["FIRMWARE_BUILD_CFG"] + "_pvs", pvsreport)
AlwaysBuild(pvsreport)
# If current configuration was explicitly requested, generate compilation database
# and link its directory as build/latest
if should_gen_cdb_and_link_dir(fwenv, BUILD_TARGETS):

View File

@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,11.6,,
Version,+,11.7,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@ -1649,6 +1649,7 @@ Function,+,infrared_get_protocol_by_name,InfraredProtocol,const char*
Function,+,infrared_get_protocol_command_length,uint8_t,InfraredProtocol
Function,+,infrared_get_protocol_duty_cycle,float,InfraredProtocol
Function,+,infrared_get_protocol_frequency,uint32_t,InfraredProtocol
Function,+,infrared_get_protocol_min_repeat_count,size_t,InfraredProtocol
Function,+,infrared_get_protocol_name,const char*,InfraredProtocol
Function,+,infrared_is_protocol_valid,_Bool,InfraredProtocol
Function,+,infrared_reset_decoder,void,InfraredDecoderHandler*

1 entry status name type params
2 Version + 11.6 11.7
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/cli/cli.h
5 Header + applications/services/cli/cli_vcp.h
1649 Function + infrared_get_protocol_command_length uint8_t InfraredProtocol
1650 Function + infrared_get_protocol_duty_cycle float InfraredProtocol
1651 Function + infrared_get_protocol_frequency uint32_t InfraredProtocol
1652 Function + infrared_get_protocol_min_repeat_count size_t InfraredProtocol
1653 Function + infrared_get_protocol_name const char* InfraredProtocol
1654 Function + infrared_is_protocol_valid _Bool InfraredProtocol
1655 Function + infrared_reset_decoder void InfraredDecoderHandler*

View File

@ -93,7 +93,11 @@ extern "C" {
#endif
#ifndef FURI_BIT_CLEAR
#define FURI_BIT_CLEAR(x, n) ((x) &= ~(1UL << (n)))
#define FURI_BIT_CLEAR(x, n) \
({ \
__typeof__(x) _x = (1); \
(x) &= ~(_x << (n)); \
})
#endif
#define FURI_SW_MEMBARRIER() asm volatile("" : : : "memory")

View File

@ -315,6 +315,7 @@ static bool elf_relocate_symbol(ELFFile* elf, Elf32_Addr relAddr, int type, Elf3
FURI_LOG_D(TAG, " R_ARM_ABS32 relocated is 0x%08X", (unsigned int)*((uint32_t*)relAddr));
break;
case R_ARM_THM_PC22:
case R_ARM_CALL:
case R_ARM_THM_JUMP24:
elf_relocate_jmp_call(elf, relAddr, type, symAddr);
FURI_LOG_D(

View File

@ -1,11 +1,8 @@
#include "infrared_common_i.h"
#include <stdlib.h>
#include <core/check.h>
#include <core/common_defines.h>
#include "infrared.h"
#include "infrared_common_i.h"
#include <stdbool.h>
#include <furi.h>
#include "infrared_i.h"
#include <stdint.h>
static void infrared_common_decoder_reset_state(InfraredCommonDecoder* decoder);

View File

@ -1,10 +1,9 @@
#include <core/check.h>
#include "infrared.h"
#include "infrared_common_i.h"
#include <stdbool.h>
#include <furi.h>
#include "infrared_i.h"
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <core/check.h>
#include <core/common_defines.h>
static InfraredStatus
infrared_common_encode_bits(InfraredCommonEncoder* encoder, uint32_t* duration, bool* level) {

View File

@ -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,
};

View File

@ -1,13 +1,16 @@
#include "infrared.h"
#include <core/check.h>
#include "common/infrared_common_i.h"
#include "infrared_protocol_defs_i.h"
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <furi.h>
#include "infrared_i.h"
#include <furi_hal_infrared.h>
#include <string.h>
#include <core/check.h>
#include <core/common_defines.h>
#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;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#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

View File

@ -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*);

View File

@ -1,320 +0,0 @@
#pragma once
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#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;

View File

@ -1,9 +1,5 @@
#include "infrared.h"
#include "infrared_protocol_defs_i.h"
#include <stdbool.h>
#include <stdint.h>
#include <furi.h>
#include "../infrared_i.h"
#include "infrared_protocol_kaseikyo_i.h"
#include <core/check.h>
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) {

View File

@ -1,9 +1,5 @@
#include "infrared_protocol_kaseikyo_i.h"
#include <core/check.h>
#include "common/infrared_common_i.h"
#include <stdint.h>
#include "../infrared_i.h"
#include "infrared_protocol_defs_i.h"
#include <furi.h>
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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -1,10 +1,5 @@
#include "common/infrared_common_i.h"
#include "infrared.h"
#include "infrared_protocol_defs_i.h"
#include <stdbool.h>
#include <stdint.h>
#include <furi.h>
#include "../infrared_i.h"
#include "infrared_protocol_nec_i.h"
#include <core/check.h>
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) {

View File

@ -1,10 +1,7 @@
#include "infrared_protocol_nec_i.h"
#include <core/core_defines.h>
#include <core/check.h>
#include "infrared.h"
#include "common/infrared_common_i.h"
#include <stdint.h>
#include "../infrared_i.h"
#include "infrared_protocol_defs_i.h"
#include <furi.h>
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) {

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -1,10 +1,7 @@
#include "infrared.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <furi.h>
#include "../infrared_i.h"
#include "../infrared_protocol_defs_i.h"
#include "infrared_protocol_rc5_i.h"
#include <stdlib.h>
#include <core/check.h>
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;
}

View File

@ -1,9 +1,7 @@
#include <core/memmgr.h>
#include "infrared.h"
#include "common/infrared_common_i.h"
#include "infrared_protocol_defs_i.h"
#include <stdint.h>
#include "../infrared_i.h"
#include "infrared_protocol_rc5_i.h"
#include <stdlib.h>
#include <core/check.h>
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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -1,10 +1,7 @@
#include "infrared.h"
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <furi.h>
#include "../infrared_i.h"
#include "../infrared_protocol_defs_i.h"
#include "infrared_protocol_rc6_i.h"
#include <stdlib.h>
#include <core/check.h>
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;
}

View File

@ -1,9 +1,7 @@
#include <core/memmgr.h>
#include "infrared.h"
#include "common/infrared_common_i.h"
#include "infrared_protocol_defs_i.h"
#include <stdint.h>
#include "../infrared_i.h"
#include "infrared_protocol_rc6_i.h"
#include <stdlib.h>
#include <core/check.h>
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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -1,9 +1,5 @@
#include "infrared.h"
#include "infrared_protocol_defs_i.h"
#include <stdbool.h>
#include <stdint.h>
#include <furi.h>
#include "../infrared_i.h"
#include "infrared_protocol_samsung_i.h"
#include <core/check.h>
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) {

View File

@ -1,9 +1,7 @@
#include "infrared_protocol_samsung_i.h"
#include <core/check.h>
#include "common/infrared_common_i.h"
#include <stdint.h>
#include "../infrared_i.h"
#include "infrared_protocol_defs_i.h"
#include <furi.h>
#include <core/common_defines.h>
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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -1,10 +1,5 @@
#include "common/infrared_common_i.h"
#include "infrared.h"
#include "infrared_protocol_defs_i.h"
#include <stdbool.h>
#include <stdint.h>
#include <furi.h>
#include "../infrared_i.h"
#include "infrared_protocol_sirc_i.h"
#include <core/check.h>
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) {

View File

@ -1,10 +1,5 @@
#include "infrared_protocol_sirc_i.h"
#include <core/check.h>
#include "infrared.h"
#include "common/infrared_common_i.h"
#include <stdint.h>
#include "../infrared_i.h"
#include "infrared_protocol_defs_i.h"
#include <furi.h>
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) {

View File

@ -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;
}

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -1,13 +1,10 @@
#include "infrared_worker.h"
#include <furi_hal_infrared.h>
#include <float_tools.h>
#include <core/check.h>
#include <core/common_defines.h>
#include "sys/_stdint.h"
#include "infrared_worker.h"
#include <infrared.h>
#include <furi_hal_infrared.h>
#include <limits.h>
#include <stdint.h>
#include <furi.h>
#include <float_tools.h>
#include <notification/notification_messages.h>
@ -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);

View File

@ -244,7 +244,7 @@ LevelDuration protocol_fdx_b_encoder_yield(ProtocolFDXB* protocol) {
static uint64_t protocol_fdx_b_get_national_code(const uint8_t* data) {
uint64_t national_code = bit_lib_get_bits_32(data, 0, 32);
national_code = national_code << 32;
national_code |= bit_lib_get_bits_32(data, 32, 6) << (32 - 6);
national_code |= (uint64_t)bit_lib_get_bits_32(data, 32, 6) << (32 - 6);
bit_lib_reverse_bits((uint8_t*)&national_code, 0, 64);
return national_code;
}

View File

@ -5,8 +5,16 @@
#include <stddef.h>
#define bit_read(value, bit) (((value) >> (bit)) & 0x01)
#define bit_set(value, bit) ((value) |= (1UL << (bit)))
#define bit_clear(value, bit) ((value) &= ~(1UL << (bit)))
#define bit_set(value, bit) \
({ \
__typeof__(value) _one = (1); \
(value) |= (_one << (bit)); \
})
#define bit_clear(value, bit) \
({ \
__typeof__(value) _one = (1); \
(value) &= ~(_one << (bit)); \
})
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))

View File

@ -280,9 +280,9 @@ static bool subghz_protocol_chamb_code_to_bit(uint64_t* data, uint8_t size) {
uint64_t data_tmp = data[0];
uint64_t data_res = 0;
for(uint8_t i = 0; i < size; i++) {
if((data_tmp & 0xF) == CHAMBERLAIN_CODE_BIT_0) {
if((data_tmp & 0xFll) == CHAMBERLAIN_CODE_BIT_0) {
bit_write(data_res, i, 0);
} else if((data_tmp & 0xF) == CHAMBERLAIN_CODE_BIT_1) {
} else if((data_tmp & 0xFll) == CHAMBERLAIN_CODE_BIT_1) {
bit_write(data_res, i, 1);
} else {
return false;

View File

@ -224,7 +224,7 @@ static bool subghz_protocol_secplus_v1_encode(SubGhzProtocolEncoderSecPlus_v1* i
instance->generic.data &= 0xFFFFFFFF00000000;
instance->generic.data |= rolling;
if(rolling > 0xFFFFFFFF) {
if(rolling == 0xFFFFFFFF) {
rolling = 0xE6000000;
}
if(fixed > 0xCFD41B90) {

View File

@ -7,7 +7,7 @@ from SCons.Node import NodeList
import SCons.Warnings
from fbt.elfmanifest import assemble_manifest_data
from fbt.appmanifest import FlipperApplication, FlipperManifestException
from fbt.appmanifest import FlipperApplication, FlipperManifestException, FlipperAppType
from fbt.sdk.cache import SdkCache
from fbt.util import extract_abs_dir_path
@ -32,6 +32,7 @@ def BuildAppElf(env, app):
ext_apps_work_dir = env.subst("$EXT_APPS_WORK_DIR")
app_work_dir = os.path.join(ext_apps_work_dir, app.appid)
env.SetDefault(_APP_ICONS=[])
env.VariantDir(app_work_dir, app._appdir, duplicate=False)
app_env = env.Clone(FAP_SRC_DIR=app._appdir, FAP_WORK_DIR=app_work_dir)
@ -63,6 +64,7 @@ def BuildAppElf(env, app):
icon_bundle_name=f"{app.fap_icon_assets_symbol if app.fap_icon_assets_symbol else app.appid }_icons",
)
app_env.Alias("_fap_icons", fap_icons)
env.Append(_APP_ICONS=[fap_icons])
private_libs = []
@ -232,11 +234,18 @@ def GetExtAppFromPath(env, app_dir):
return app_artifacts
def fap_dist_emitter(target, source, env):
def resources_fap_dist_emitter(target, source, env):
target_dir = target[0]
target = []
for _, app_artifacts in env["EXT_APPS"].items():
# We don't deploy example apps & debug tools with SD card resources
if (
app_artifacts.app.apptype == FlipperAppType.DEBUG
or app_artifacts.app.fap_category == "Examples"
):
continue
source.extend(app_artifacts.compact)
target.append(
target_dir.Dir(app_artifacts.app.fap_category).File(
@ -247,7 +256,7 @@ def fap_dist_emitter(target, source, env):
return (target, source)
def fap_dist_action(target, source, env):
def resources_fap_dist_action(target, source, env):
# FIXME
target_dir = env.Dir("#/assets/resources/apps")
@ -280,10 +289,10 @@ def generate(env, **kw):
BUILDERS={
"FapDist": Builder(
action=Action(
fap_dist_action,
resources_fap_dist_action,
"$FAPDISTCOMSTR",
),
emitter=fap_dist_emitter,
emitter=resources_fap_dist_emitter,
),
"EmbedAppMetadata": Builder(
action=[

View File

@ -11,6 +11,8 @@ Building:
Build all FAP apps
fap_{APPID}, launch_app APPSRC={APPID}:
Build FAP app with appid={APPID}; upload & start it over USB
fap_deploy:
Build and upload all FAP apps over USB
Flashing & debugging:
flash, flash_blackmagic, jflash:
@ -29,6 +31,8 @@ Other:
run linters
format, format_py:
run code formatters
firmware_pvs:
generate a PVS-Studio report
For more targets & info, see documentation/fbt.md
"""

View File

@ -0,0 +1,106 @@
from SCons.Builder import Builder
from SCons.Action import Action
from SCons.Script import Delete, Mkdir, GetBuildFailures
import multiprocessing
import webbrowser
import atexit
import sys
import subprocess
__no_browser = False
def _set_browser_action(target, source, env):
if env["PVSNOBROWSER"]:
global __no_browser
__no_browser = True
def emit_pvsreport(target, source, env):
target_dir = env["REPORT_DIR"]
if env["PLATFORM"] == "win32":
# Report generator on Windows emits to a subfolder of given output folder
target_dir = target_dir.Dir("fullhtml")
return [target_dir.File("index.html")], source
def atexist_handler():
global __no_browser
if __no_browser:
return
for bf in GetBuildFailures():
if bf.node.exists and bf.node.name.endswith(".html"):
# macOS
if sys.platform == "darwin":
subprocess.run(["open", bf.node.abspath])
else:
webbrowser.open(bf.node.abspath)
break
def generate(env):
env.SetDefault(
PVSNCORES=multiprocessing.cpu_count(),
PVSOPTIONS=[
"@.pvsoptions",
"-j${PVSNCORES}",
# "--incremental", # kinda broken on PVS side
],
PVSCONVOPTIONS=[
"-a",
"GA:1,2,3",
"-t",
"fullhtml",
"--indicate-warnings",
],
)
if env["PLATFORM"] == "win32":
env.SetDefault(
PVSCHECKBIN="CompilerCommandsAnalyzer.exe",
PVSCONVBIN="PlogConverter.exe",
)
else:
env.SetDefault(
PVSCHECKBIN="pvs-studio-analyzer",
PVSCONVBIN="plog-converter",
)
if not env["VERBOSE"]:
env.SetDefault(
PVSCHECKCOMSTR="\tPVS\t${TARGET}",
PVSCONVCOMSTR="\tPVSREP\t${TARGET}",
)
env.Append(
BUILDERS={
"PVSCheck": Builder(
action=Action(
'${PVSCHECKBIN} analyze ${PVSOPTIONS} -f "${SOURCE}" -o "${TARGET}"',
"${PVSCHECKCOMSTR}",
),
suffix=".log",
src_suffix=".json",
),
"PVSReport": Builder(
action=Action(
[
Delete("${TARGET.dir}"),
# PlogConverter.exe and plog-converter have different behavior
Mkdir("${TARGET.dir}") if env["PLATFORM"] == "win32" else None,
Action(_set_browser_action, None),
'${PVSCONVBIN} ${PVSCONVOPTIONS} "${SOURCE}" -o "${REPORT_DIR}"',
],
"${PVSCONVCOMSTR}",
),
emitter=emit_pvsreport,
src_suffix=".log",
),
}
)
atexit.register(atexist_handler)
def exists(env):
return True

View File

@ -15,6 +15,13 @@ import serial.tools.list_ports as list_ports
class Main(App):
def init(self):
self.parser.add_argument("-p", "--port", help="CDC Port", default="auto")
self.parser.add_argument(
"-n",
"--no-launch",
dest="launch_app",
action="store_false",
help="Don't launch app",
)
self.parser.add_argument("fap_src_path", help="App file to upload")
self.parser.add_argument(
@ -84,11 +91,14 @@ class Main(App):
self.logger.error(f"Error: upload failed: {storage.last_error}")
return -3
storage.send_and_wait_eol(f'loader open "Applications" {fap_dst_path}\r')
result = storage.read.until(storage.CLI_EOL)
if len(result):
self.logger.error(f"Unexpected response: {result.decode('ascii')}")
return -4
if self.args.launch_app:
storage.send_and_wait_eol(
f'loader open "Applications" {fap_dst_path}\r'
)
result = storage.read.until(storage.CLI_EOL)
if len(result):
self.logger.error(f"Unexpected response: {result.decode('ascii')}")
return -4
return 0
finally:

View File

@ -43,9 +43,11 @@ fbtenv_restore_env()
PYTHONNOUSERSITE="$SAVED_PYTHONNOUSERSITE";
PYTHONPATH="$SAVED_PYTHONPATH";
PYTHONHOME="$SAVED_PYTHONHOME";
unset SAVED_PYTHONNOUSERSITE;
unset SAVED_PYTHONPATH;
unset SAVED_PYTHONHOME;
unset SCRIPT_PATH;
unset FBT_TOOLCHAIN_VERSION;
@ -69,7 +71,7 @@ fbtenv_check_sourced()
return 1;
}
fbtenv_chck_many_source()
fbtenv_check_if_sourced_multiple_times()
{
if ! echo "${PS1:-""}" | grep -qF "[fbt]"; then
if ! echo "${PROMPT:-""}" | grep -qF "[fbt]"; then
@ -285,7 +287,7 @@ fbtenv_main()
fbtenv_restore_env;
return 0;
fi
fbtenv_chck_many_source; # many source it's just a warning
fbtenv_check_if_sourced_multiple_times; # many source it's just a warning
fbtenv_check_script_path || return 1;
fbtenv_check_download_toolchain || return 1;
fbtenv_set_shell_prompt;
@ -293,12 +295,14 @@ fbtenv_main()
PATH="$TOOLCHAIN_ARCH_DIR/bin:$PATH";
PATH="$TOOLCHAIN_ARCH_DIR/protobuf/bin:$PATH";
PATH="$TOOLCHAIN_ARCH_DIR/openocd/bin:$PATH";
SAVED_PYTHONNOUSERSITE="${PYTHONNOUSERSITE:-""}";
SAVED_PYTHONPATH="${PYTHONPATH:-""}";
SAVED_PYTHONHOME="${PYTHONHOME:-""}";
PYTHONNOUSERSITE=1;
PYTHONPATH=;
PYTHONHOME=;
}
fbtenv_main "${1:-""}";

View File

@ -81,16 +81,6 @@ vars.AddVariables(
"7",
],
),
BoolVariable(
"DEBUG_TOOLS",
help="Enable debug tools to be built",
default=False,
),
BoolVariable(
"FAP_EXAMPLES",
help="Enable example applications to be built",
default=False,
),
(
"DIST_SUFFIX",
"Suffix for binaries in build output for dist targets",
@ -242,9 +232,15 @@ vars.AddVariables(
("applications/system", False),
("applications/debug", False),
("applications/plugins", False),
("applications/examples", False),
("applications_user", False),
],
),
BoolVariable(
"PVSNOBROWSER",
help="Don't open browser after generating error repots",
default=False,
),
)
Return("vars")

View File

@ -65,9 +65,8 @@ class FlipperExtAppBuildArtifacts:
apps_to_build_as_faps = [
FlipperAppType.PLUGIN,
FlipperAppType.EXTERNAL,
FlipperAppType.DEBUG,
]
if appenv["DEBUG_TOOLS"]:
apps_to_build_as_faps.append(FlipperAppType.DEBUG)
known_extapps = [
app
@ -143,6 +142,11 @@ sdk_apisyms = appenv.SDKSymGenerator(
"${BUILD_DIR}/assets/compiled/symbols.h", appenv["SDK_DEFINITION"]
)
Alias("api_syms", sdk_apisyms)
ENV.Replace(
SDK_APISYMS=sdk_apisyms,
_APP_ICONS=appenv["_APP_ICONS"],
)
if appenv["FORCE"]:
appenv.AlwaysBuild(sdk_source, sdk_tree, sdk_apicheck, sdk_apisyms)