| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340 |
- /*
- This file was taken from the project:
- https://github.com/DarkFlippers/unleashed-firmware
- The original project is licensed under the GNU GPLv3
- Modifications made:
- - Added function infrared_signal_transmit_times()
- */
- #include "infrared_signal.h"
- #include <stdlib.h>
- #include <string.h>
- #include <core/check.h>
- #include <infrared_worker.h>
- #include <infrared_transmit.h>
- #define TAG "InfraredSignal"
- struct InfraredSignal {
- bool is_raw;
- union {
- InfraredMessage message;
- InfraredRawSignal raw;
- } payload;
- };
- static void infrared_signal_clear_timings(InfraredSignal* signal) {
- if(signal->is_raw) {
- free(signal->payload.raw.timings);
- signal->payload.raw.timings_size = 0;
- signal->payload.raw.timings = NULL;
- }
- }
- static bool infrared_signal_is_message_valid(InfraredMessage* message) {
- if(!infrared_is_protocol_valid(message->protocol)) {
- FURI_LOG_E(TAG, "Unknown protocol");
- return false;
- }
- uint32_t address_length = infrared_get_protocol_address_length(message->protocol);
- uint32_t address_mask = (1UL << address_length) - 1;
- if(message->address != (message->address & address_mask)) {
- FURI_LOG_E(
- TAG,
- "Address is out of range (mask 0x%08lX): 0x%lX\r\n",
- address_mask,
- message->address);
- return false;
- }
- uint32_t command_length = infrared_get_protocol_command_length(message->protocol);
- uint32_t command_mask = (1UL << command_length) - 1;
- if(message->command != (message->command & command_mask)) {
- FURI_LOG_E(
- TAG,
- "Command is out of range (mask 0x%08lX): 0x%lX\r\n",
- command_mask,
- message->command);
- return false;
- }
- return true;
- }
- static bool infrared_signal_is_raw_valid(InfraredRawSignal* raw) {
- if((raw->frequency > INFRARED_MAX_FREQUENCY) || (raw->frequency < INFRARED_MIN_FREQUENCY)) {
- FURI_LOG_E(
- TAG,
- "Frequency is out of range (%X - %X): %lX",
- INFRARED_MIN_FREQUENCY,
- INFRARED_MAX_FREQUENCY,
- raw->frequency);
- return false;
- } else if((raw->duty_cycle <= 0) || (raw->duty_cycle > 1)) {
- FURI_LOG_E(TAG, "Duty cycle is out of range (0 - 1): %f", (double)raw->duty_cycle);
- return false;
- } else if((raw->timings_size <= 0) || (raw->timings_size > MAX_TIMINGS_AMOUNT)) {
- FURI_LOG_E(
- TAG,
- "Timings amount is out of range (0 - %X): %zX",
- MAX_TIMINGS_AMOUNT,
- raw->timings_size);
- return false;
- }
- return true;
- }
- static inline bool infrared_signal_save_message(InfraredMessage* message, FlipperFormat* ff) {
- const char* protocol_name = infrared_get_protocol_name(message->protocol);
- return flipper_format_write_string_cstr(ff, "type", "parsed") &&
- flipper_format_write_string_cstr(ff, "protocol", protocol_name) &&
- flipper_format_write_hex(ff, "address", (uint8_t*)&message->address, 4) &&
- flipper_format_write_hex(ff, "command", (uint8_t*)&message->command, 4);
- }
- static inline bool infrared_signal_save_raw(InfraredRawSignal* raw, FlipperFormat* ff) {
- furi_assert(raw->timings_size <= MAX_TIMINGS_AMOUNT);
- return flipper_format_write_string_cstr(ff, "type", "raw") &&
- flipper_format_write_uint32(ff, "frequency", &raw->frequency, 1) &&
- flipper_format_write_float(ff, "duty_cycle", &raw->duty_cycle, 1) &&
- flipper_format_write_uint32(ff, "data", raw->timings, raw->timings_size);
- }
- static inline bool infrared_signal_read_message(InfraredSignal* signal, FlipperFormat* ff) {
- FuriString* buf;
- buf = furi_string_alloc();
- bool success = false;
- do {
- if(!flipper_format_read_string(ff, "protocol", buf)) break;
- InfraredMessage message;
- message.protocol = infrared_get_protocol_by_name(furi_string_get_cstr(buf));
- success = flipper_format_read_hex(ff, "address", (uint8_t*)&message.address, 4) &&
- flipper_format_read_hex(ff, "command", (uint8_t*)&message.command, 4) &&
- infrared_signal_is_message_valid(&message);
- if(!success) break;
- infrared_signal_set_message(signal, &message);
- } while(0);
- furi_string_free(buf);
- return success;
- }
- static inline bool infrared_signal_read_raw(InfraredSignal* signal, FlipperFormat* ff) {
- uint32_t timings_size, frequency;
- float duty_cycle;
- bool success = flipper_format_read_uint32(ff, "frequency", &frequency, 1) &&
- flipper_format_read_float(ff, "duty_cycle", &duty_cycle, 1) &&
- flipper_format_get_value_count(ff, "data", &timings_size);
- if(!success || timings_size > MAX_TIMINGS_AMOUNT) {
- return false;
- }
- uint32_t* timings = malloc(sizeof(uint32_t) * timings_size);
- success = flipper_format_read_uint32(ff, "data", timings, timings_size);
- if(success) {
- infrared_signal_set_raw_signal(signal, timings, timings_size, frequency, duty_cycle);
- }
- free(timings);
- return success;
- }
- static bool infrared_signal_read_body(InfraredSignal* signal, FlipperFormat* ff) {
- FuriString* tmp = furi_string_alloc();
- bool success = false;
- do {
- if(!flipper_format_read_string(ff, "type", tmp)) break;
- if(furi_string_equal(tmp, "raw")) {
- success = infrared_signal_read_raw(signal, ff);
- } else if(furi_string_equal(tmp, "parsed")) {
- success = infrared_signal_read_message(signal, ff);
- } else {
- FURI_LOG_E(TAG, "Unknown signal type");
- }
- } while(false);
- furi_string_free(tmp);
- return success;
- }
- InfraredSignal* infrared_signal_alloc() {
- InfraredSignal* signal = malloc(sizeof(InfraredSignal));
- signal->is_raw = false;
- signal->payload.message.protocol = InfraredProtocolUnknown;
- return signal;
- }
- void infrared_signal_free(InfraredSignal* signal) {
- infrared_signal_clear_timings(signal);
- free(signal);
- }
- bool infrared_signal_is_raw(InfraredSignal* signal) {
- return signal->is_raw;
- }
- bool infrared_signal_is_valid(InfraredSignal* signal) {
- return signal->is_raw ? infrared_signal_is_raw_valid(&signal->payload.raw) :
- infrared_signal_is_message_valid(&signal->payload.message);
- }
- void infrared_signal_set_signal(InfraredSignal* signal, const InfraredSignal* other) {
- if(other->is_raw) {
- const InfraredRawSignal* raw = &other->payload.raw;
- infrared_signal_set_raw_signal(
- signal, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle);
- } else {
- const InfraredMessage* message = &other->payload.message;
- infrared_signal_set_message(signal, message);
- }
- }
- void infrared_signal_set_raw_signal(
- InfraredSignal* signal,
- const uint32_t* timings,
- size_t timings_size,
- uint32_t frequency,
- float duty_cycle) {
- infrared_signal_clear_timings(signal);
- // If the frequency is out of bounds, set it to the closest bound same for duty cycle
- // TODO: Should we return error instead? Also infrared_signal_is_valid is used only in CLI for some reason?!
- if(frequency > INFRARED_MAX_FREQUENCY) {
- frequency = INFRARED_MAX_FREQUENCY;
- } else if(frequency < INFRARED_MIN_FREQUENCY) {
- frequency = INFRARED_MIN_FREQUENCY;
- }
- if((duty_cycle <= (float)0) || (duty_cycle > (float)1)) {
- duty_cycle = (float)0.33;
- }
- // In case of timings out of bounds we just call return
- if((timings_size <= 0) || (timings_size > MAX_TIMINGS_AMOUNT)) {
- return;
- }
- signal->is_raw = true;
- signal->payload.raw.timings_size = timings_size;
- signal->payload.raw.frequency = frequency;
- signal->payload.raw.duty_cycle = duty_cycle;
- signal->payload.raw.timings = malloc(timings_size * sizeof(uint32_t));
- memcpy(signal->payload.raw.timings, timings, timings_size * sizeof(uint32_t));
- }
- InfraredRawSignal* infrared_signal_get_raw_signal(InfraredSignal* signal) {
- furi_assert(signal->is_raw);
- return &signal->payload.raw;
- }
- void infrared_signal_set_message(InfraredSignal* signal, const InfraredMessage* message) {
- infrared_signal_clear_timings(signal);
- signal->is_raw = false;
- signal->payload.message = *message;
- }
- InfraredMessage* infrared_signal_get_message(InfraredSignal* signal) {
- furi_assert(!signal->is_raw);
- return &signal->payload.message;
- }
- bool infrared_signal_save(InfraredSignal* signal, FlipperFormat* ff, const char* name) {
- if(!flipper_format_write_comment_cstr(ff, "") ||
- !flipper_format_write_string_cstr(ff, "name", name)) {
- return false;
- } else if(signal->is_raw) {
- return infrared_signal_save_raw(&signal->payload.raw, ff);
- } else {
- return infrared_signal_save_message(&signal->payload.message, ff);
- }
- }
- bool infrared_signal_read(InfraredSignal* signal, FlipperFormat* ff, FuriString* name) {
- FuriString* tmp = furi_string_alloc();
- bool success = false;
- do {
- if(!flipper_format_read_string(ff, "name", tmp)) break;
- furi_string_set(name, tmp);
- if(!infrared_signal_read_body(signal, ff)) break;
- success = true;
- } while(0);
- furi_string_free(tmp);
- return success;
- }
- bool infrared_signal_search_and_read(
- InfraredSignal* signal,
- FlipperFormat* ff,
- const FuriString* name) {
- bool success = false;
- FuriString* tmp = furi_string_alloc();
- do {
- bool is_name_found = false;
- while(flipper_format_read_string(ff, "name", tmp)) {
- is_name_found = furi_string_equal(name, tmp);
- if(is_name_found) break;
- }
- if(!is_name_found) break; //-V547
- if(!infrared_signal_read_body(signal, ff)) break; //-V779
- success = true;
- } while(false);
- furi_string_free(tmp);
- return success;
- }
- void infrared_signal_transmit(InfraredSignal* signal) {
- if(signal->is_raw) {
- InfraredRawSignal* raw_signal = &signal->payload.raw;
- infrared_send_raw_ext(
- raw_signal->timings,
- raw_signal->timings_size,
- true,
- raw_signal->frequency,
- raw_signal->duty_cycle);
- } else {
- InfraredMessage* message = &signal->payload.message;
- infrared_send(message, 1);
- }
- }
- void infrared_signal_transmit_times(InfraredSignal* signal, int times) {
- if(signal->is_raw) {
- InfraredRawSignal* raw_signal = &signal->payload.raw;
- infrared_send_raw_ext(
- raw_signal->timings,
- raw_signal->timings_size,
- true,
- raw_signal->frequency,
- raw_signal->duty_cycle);
- } else {
- InfraredMessage* message = &signal->payload.message;
- infrared_send(message, times);
- }
- }
|