2021-07-08 18:20:13 +00:00
|
|
|
#include "irda.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <furi.h>
|
2022-01-05 16:10:18 +00:00
|
|
|
#include <furi_hal_irda.h>
|
|
|
|
#include <furi_hal_delay.h>
|
2021-07-08 18:20:13 +00:00
|
|
|
|
2021-08-05 21:11:35 +00:00
|
|
|
static uint32_t irda_tx_number_of_transmissions = 0;
|
|
|
|
static uint32_t irda_tx_raw_timings_index = 0;
|
|
|
|
static uint32_t irda_tx_raw_timings_number = 0;
|
|
|
|
static uint32_t irda_tx_raw_start_from_mark = 0;
|
|
|
|
static bool irda_tx_raw_add_silence = false;
|
2021-07-16 16:43:54 +00:00
|
|
|
|
2022-01-05 16:10:18 +00:00
|
|
|
FuriHalIrdaTxGetDataState
|
|
|
|
irda_get_raw_data_callback(void* context, uint32_t* duration, bool* level) {
|
2021-08-05 21:11:35 +00:00
|
|
|
furi_assert(duration);
|
|
|
|
furi_assert(level);
|
|
|
|
furi_assert(context);
|
|
|
|
|
2021-08-08 18:03:25 +00:00
|
|
|
FuriHalIrdaTxGetDataState state = FuriHalIrdaTxGetDataStateOk;
|
2021-08-05 21:11:35 +00:00
|
|
|
const uint32_t* timings = context;
|
|
|
|
|
2022-01-05 16:10:18 +00:00
|
|
|
if(irda_tx_raw_add_silence && (irda_tx_raw_timings_index == 0)) {
|
2021-08-05 21:11:35 +00:00
|
|
|
irda_tx_raw_add_silence = false;
|
|
|
|
*level = false;
|
2021-08-11 17:51:06 +00:00
|
|
|
*duration = IRDA_RAW_TX_TIMING_DELAY_US;
|
2021-07-08 18:20:13 +00:00
|
|
|
} else {
|
2021-08-05 21:11:35 +00:00
|
|
|
*level = irda_tx_raw_start_from_mark ^ (irda_tx_raw_timings_index % 2);
|
|
|
|
*duration = timings[irda_tx_raw_timings_index++];
|
2021-07-08 18:20:13 +00:00
|
|
|
}
|
|
|
|
|
2022-01-05 16:10:18 +00:00
|
|
|
if(irda_tx_raw_timings_number == irda_tx_raw_timings_index) {
|
2021-08-08 18:03:25 +00:00
|
|
|
state = FuriHalIrdaTxGetDataStateLastDone;
|
2021-07-16 16:43:54 +00:00
|
|
|
}
|
2021-08-05 21:11:35 +00:00
|
|
|
|
|
|
|
return state;
|
|
|
|
}
|
|
|
|
|
2022-01-05 16:10:18 +00:00
|
|
|
void irda_send_raw_ext(
|
|
|
|
const uint32_t timings[],
|
|
|
|
uint32_t timings_cnt,
|
|
|
|
bool start_from_mark,
|
|
|
|
uint32_t frequency,
|
|
|
|
float duty_cycle) {
|
2021-08-05 21:11:35 +00:00
|
|
|
furi_assert(timings);
|
|
|
|
|
|
|
|
irda_tx_raw_start_from_mark = start_from_mark;
|
|
|
|
irda_tx_raw_timings_index = 0;
|
|
|
|
irda_tx_raw_timings_number = timings_cnt;
|
|
|
|
irda_tx_raw_add_silence = start_from_mark;
|
2022-01-05 16:10:18 +00:00
|
|
|
furi_hal_irda_async_tx_set_data_isr_callback(irda_get_raw_data_callback, (void*)timings);
|
2021-08-08 18:03:25 +00:00
|
|
|
furi_hal_irda_async_tx_start(frequency, duty_cycle);
|
|
|
|
furi_hal_irda_async_tx_wait_termination();
|
2021-08-05 21:11:35 +00:00
|
|
|
|
2021-08-08 18:03:25 +00:00
|
|
|
furi_assert(!furi_hal_irda_is_busy());
|
2021-07-16 16:43:54 +00:00
|
|
|
}
|
|
|
|
|
2021-07-08 18:20:13 +00:00
|
|
|
void irda_send_raw(const uint32_t timings[], uint32_t timings_cnt, bool start_from_mark) {
|
2022-01-05 16:10:18 +00:00
|
|
|
irda_send_raw_ext(
|
|
|
|
timings,
|
|
|
|
timings_cnt,
|
|
|
|
start_from_mark,
|
|
|
|
IRDA_COMMON_CARRIER_FREQUENCY,
|
|
|
|
IRDA_COMMON_DUTY_CYCLE);
|
2021-08-05 21:11:35 +00:00
|
|
|
}
|
|
|
|
|
2022-01-05 16:10:18 +00:00
|
|
|
FuriHalIrdaTxGetDataState irda_get_data_callback(void* context, uint32_t* duration, bool* level) {
|
2021-08-19 00:18:42 +00:00
|
|
|
FuriHalIrdaTxGetDataState state = FuriHalIrdaTxGetDataStateLastDone;
|
2021-08-05 21:11:35 +00:00
|
|
|
IrdaEncoderHandler* handler = context;
|
|
|
|
IrdaStatus status = IrdaStatusError;
|
|
|
|
|
2022-01-05 16:10:18 +00:00
|
|
|
if(irda_tx_number_of_transmissions > 0) {
|
2021-08-05 21:11:35 +00:00
|
|
|
status = irda_encode(handler, duration, level);
|
|
|
|
}
|
|
|
|
|
2022-01-05 16:10:18 +00:00
|
|
|
if(status == IrdaStatusError) {
|
2021-08-19 00:18:42 +00:00
|
|
|
state = FuriHalIrdaTxGetDataStateLastDone;
|
|
|
|
*duration = 0;
|
|
|
|
*level = 0;
|
2022-01-05 16:10:18 +00:00
|
|
|
} else if(status == IrdaStatusOk) {
|
2021-08-08 18:03:25 +00:00
|
|
|
state = FuriHalIrdaTxGetDataStateOk;
|
2022-01-05 16:10:18 +00:00
|
|
|
} else if(status == IrdaStatusDone) {
|
2021-08-08 18:03:25 +00:00
|
|
|
state = FuriHalIrdaTxGetDataStateDone;
|
2022-01-05 16:10:18 +00:00
|
|
|
if(--irda_tx_number_of_transmissions == 0) {
|
2021-08-08 18:03:25 +00:00
|
|
|
state = FuriHalIrdaTxGetDataStateLastDone;
|
2021-08-05 21:11:35 +00:00
|
|
|
}
|
|
|
|
} else {
|
2021-09-15 09:59:49 +00:00
|
|
|
furi_crash(NULL);
|
2021-07-08 18:20:13 +00:00
|
|
|
}
|
2021-08-05 21:11:35 +00:00
|
|
|
|
|
|
|
return state;
|
2021-07-08 18:20:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void irda_send(const IrdaMessage* message, int times) {
|
|
|
|
furi_assert(message);
|
2021-08-05 21:11:35 +00:00
|
|
|
furi_assert(times);
|
2021-07-08 18:20:13 +00:00
|
|
|
furi_assert(irda_is_protocol_valid(message->protocol));
|
|
|
|
|
|
|
|
IrdaEncoderHandler* handler = irda_alloc_encoder();
|
|
|
|
irda_reset_encoder(handler, message);
|
2021-08-05 21:11:35 +00:00
|
|
|
irda_tx_number_of_transmissions = times;
|
2021-07-08 18:20:13 +00:00
|
|
|
|
2021-08-19 00:18:42 +00:00
|
|
|
uint32_t frequency = irda_get_protocol_frequency(message->protocol);
|
|
|
|
float duty_cycle = irda_get_protocol_duty_cycle(message->protocol);
|
|
|
|
|
2021-08-08 18:03:25 +00:00
|
|
|
furi_hal_irda_async_tx_set_data_isr_callback(irda_get_data_callback, handler);
|
2021-08-19 00:18:42 +00:00
|
|
|
furi_hal_irda_async_tx_start(frequency, duty_cycle);
|
2021-08-08 18:03:25 +00:00
|
|
|
furi_hal_irda_async_tx_wait_termination();
|
2021-07-08 18:20:13 +00:00
|
|
|
|
|
|
|
irda_free_encoder(handler);
|
2021-08-05 21:11:35 +00:00
|
|
|
|
2021-08-08 18:03:25 +00:00
|
|
|
furi_assert(!furi_hal_irda_is_busy());
|
2021-07-08 18:20:13 +00:00
|
|
|
}
|