Skip to content

Commit

Permalink
[FL-3322] Infrared: respect carrier frequency and duty cycle settings (
Browse files Browse the repository at this point in the history
…#2677)

* Make infrared_worker respect carrier frequency and duty cycle
* Update comments

Co-authored-by: あく <alleteam@gmail.com>
  • Loading branch information
gsurkov and skotopes authored May 25, 2023
1 parent faa14cf commit ed1ebf9
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 27 deletions.
3 changes: 2 additions & 1 deletion applications/main/infrared/infrared.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,8 @@ void infrared_tx_start_signal(Infrared* infrared, InfraredSignal* signal) {

if(infrared_signal_is_raw(signal)) {
InfraredRawSignal* raw = infrared_signal_get_raw_signal(signal);
infrared_worker_set_raw_signal(infrared->worker, raw->timings, raw->timings_size);
infrared_worker_set_raw_signal(
infrared->worker, raw->timings, raw->timings_size, raw->frequency, raw->duty_cycle);
} else {
InfraredMessage* message = infrared_signal_get_message(signal);
infrared_worker_set_decoded_signal(infrared->worker, message);
Expand Down
2 changes: 1 addition & 1 deletion firmware/targets/f18/api_symbols.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,26.3,,
Version,+,27.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
Expand Down
4 changes: 2 additions & 2 deletions firmware/targets/f7/api_symbols.csv
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,26.3,,
Version,+,27.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
Expand Down Expand Up @@ -1715,7 +1715,7 @@ Function,+,infrared_worker_rx_set_received_signal_callback,void,"InfraredWorker*
Function,+,infrared_worker_rx_start,void,InfraredWorker*
Function,+,infrared_worker_rx_stop,void,InfraredWorker*
Function,+,infrared_worker_set_decoded_signal,void,"InfraredWorker*, const InfraredMessage*"
Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t"
Function,+,infrared_worker_set_raw_signal,void,"InfraredWorker*, const uint32_t*, size_t, uint32_t, float"
Function,+,infrared_worker_signal_is_decoded,_Bool,const InfraredWorkerSignal*
Function,+,infrared_worker_tx_get_signal_steady_callback,InfraredWorkerGetSignalResponse,"void*, InfraredWorker*"
Function,+,infrared_worker_tx_set_get_signal_callback,void,"InfraredWorker*, InfraredWorkerGetSignalCallback, void*"
Expand Down
14 changes: 5 additions & 9 deletions firmware/targets/f7/furi_hal/furi_hal_infrared.c
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
#include <furi_hal_infrared.h>
#include <core/check.h>
#include "stm32wbxx_ll_dma.h"
#include "sys/_stdint.h"
#include <furi_hal_interrupt.h>
#include <furi_hal_resources.h>

Expand All @@ -13,11 +12,10 @@
#include <furi.h>
#include <math.h>

#define INFRARED_TX_DEBUG 0
// #define INFRARED_TX_DEBUG

#if INFRARED_TX_DEBUG == 1
#define gpio_infrared_tx gpio_infrared_tx_debug
const GpioPin gpio_infrared_tx_debug = {.port = GPIOA, .pin = GpioModeAnalog};
#if defined INFRARED_TX_DEBUG
#define gpio_infrared_tx gpio_ext_pa7
#endif

#define INFRARED_TIM_TX_DMA_BUFFER_SIZE 200
Expand Down Expand Up @@ -330,8 +328,6 @@ static void furi_hal_infrared_tx_dma_isr() {
}

static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cycle) {
/* LL_DBGMCU_APB2_GRP1_FreezePeriph(LL_DBGMCU_APB2_GRP1_TIM1_STOP); */

LL_TIM_DisableCounter(TIM1);
LL_TIM_SetRepetitionCounter(TIM1, 0);
LL_TIM_SetCounter(TIM1, 0);
Expand All @@ -340,7 +336,7 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc
LL_TIM_EnableARRPreload(TIM1);
LL_TIM_SetAutoReload(
TIM1, __LL_TIM_CALC_ARR(SystemCoreClock, LL_TIM_GetPrescaler(TIM1), freq));
#if INFRARED_TX_DEBUG == 1
#if defined INFRARED_TX_DEBUG
LL_TIM_OC_SetCompareCH1(TIM1, ((LL_TIM_GetAutoReload(TIM1) + 1) * (1 - duty_cycle)));
LL_TIM_OC_EnablePreload(TIM1, LL_TIM_CHANNEL_CH1);
/* LL_TIM_OCMODE_PWM2 set by DMA */
Expand Down Expand Up @@ -370,7 +366,7 @@ static void furi_hal_infrared_configure_tim_pwm_tx(uint32_t freq, float duty_cyc

static void furi_hal_infrared_configure_tim_cmgr2_dma_tx(void) {
LL_DMA_InitTypeDef dma_config = {0};
#if INFRARED_TX_DEBUG == 1
#if defined INFRARED_TX_DEBUG
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->CCMR1);
#else
dma_config.PeriphOrM2MSrcAddress = (uint32_t) & (TIM1->CCMR2);
Expand Down
32 changes: 21 additions & 11 deletions lib/infrared/worker/infrared_worker.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,12 @@ struct InfraredWorkerSignal {
size_t timings_cnt;
union {
InfraredMessage message;
/* +1 is for pause we add at the beginning */
uint32_t timings[MAX_TIMINGS_AMOUNT + 1];
struct {
/* +1 is for pause we add at the beginning */
uint32_t timings[MAX_TIMINGS_AMOUNT + 1];
uint32_t frequency;
float duty_cycle;
} raw;
};
};

Expand Down Expand Up @@ -146,7 +150,7 @@ static void
}

if(instance->signal.timings_cnt < MAX_TIMINGS_AMOUNT) {
instance->signal.timings[instance->signal.timings_cnt] = duration;
instance->signal.raw.timings[instance->signal.timings_cnt] = duration;
++instance->signal.timings_cnt;
} else {
uint32_t flags_set = furi_thread_flags_set(
Expand Down Expand Up @@ -300,7 +304,7 @@ void infrared_worker_get_raw_signal(
furi_assert(timings);
furi_assert(timings_cnt);

*timings = signal->timings;
*timings = signal->raw.timings;
*timings_cnt = signal->timings_cnt;
}

Expand Down Expand Up @@ -390,8 +394,8 @@ static bool infrared_get_new_signal(InfraredWorker* instance) {
infrared_get_protocol_duty_cycle(instance->signal.message.protocol);
} else {
furi_assert(instance->signal.timings_cnt > 1);
new_tx_frequency = INFRARED_COMMON_CARRIER_FREQUENCY;
new_tx_duty_cycle = INFRARED_COMMON_DUTY_CYCLE;
new_tx_frequency = instance->signal.raw.frequency;
new_tx_duty_cycle = instance->signal.raw.duty_cycle;
}

instance->tx.tx_raw_cnt = 0;
Expand Down Expand Up @@ -426,7 +430,7 @@ static bool infrared_worker_tx_fill_buffer(InfraredWorker* instance) {
if(instance->signal.decoded) {
status = infrared_encode(instance->infrared_encoder, &timing.duration, &timing.level);
} else {
timing.duration = instance->signal.timings[instance->tx.tx_raw_cnt];
timing.duration = instance->signal.raw.timings[instance->tx.tx_raw_cnt];
/* raw always starts from Mark, but we fill it with space delay at start */
timing.level = (instance->tx.tx_raw_cnt % 2);
++instance->tx.tx_raw_cnt;
Expand Down Expand Up @@ -597,15 +601,21 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared
void infrared_worker_set_raw_signal(
InfraredWorker* instance,
const uint32_t* timings,
size_t timings_cnt) {
size_t timings_cnt,
uint32_t frequency,
float duty_cycle) {
furi_assert(instance);
furi_assert(timings);
furi_assert(timings_cnt > 0);
size_t max_copy_num = COUNT_OF(instance->signal.timings) - 1;
furi_assert((frequency <= INFRARED_MAX_FREQUENCY) && (frequency >= INFRARED_MIN_FREQUENCY));
furi_assert((duty_cycle < 1.0f) && (duty_cycle > 0.0f));
size_t max_copy_num = COUNT_OF(instance->signal.raw.timings) - 1;
furi_check(timings_cnt <= max_copy_num);

instance->signal.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US;
memcpy(&instance->signal.timings[1], timings, timings_cnt * sizeof(uint32_t));
instance->signal.raw.frequency = frequency;
instance->signal.raw.duty_cycle = duty_cycle;
instance->signal.raw.timings[0] = INFRARED_RAW_TX_TIMING_DELAY_US;
memcpy(&instance->signal.raw.timings[1], timings, timings_cnt * sizeof(uint32_t));
instance->signal.decoded = false;
instance->signal.timings_cnt = timings_cnt + 1;
}
Expand Down
10 changes: 7 additions & 3 deletions lib/infrared/worker/infrared_worker.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ void infrared_worker_tx_set_signal_sent_callback(
/** Callback to pass to infrared_worker_tx_set_get_signal_callback() if signal
* is steady and will not be changed between infrared_worker start and stop.
* Before starting transmission, desired steady signal must be set with
* infrared_worker_make_decoded_signal() or infrared_worker_make_raw_signal().
* infrared_worker_set_decoded_signal() or infrared_worker_set_raw_signal().
*
* This function should not be implicitly called.
* This function should not be called directly.
*
* @param[in] context - context
* @param[out] instance - InfraredWorker instance
Expand Down Expand Up @@ -172,11 +172,15 @@ void infrared_worker_set_decoded_signal(InfraredWorker* instance, const Infrared
* @param[out] instance - InfraredWorker instance
* @param[in] timings - array of raw timings
* @param[in] timings_cnt - size of array of raw timings
* @param[in] frequency - carrier frequency in Hertz
* @param[in] duty_cycle - carrier duty cycle (0.0 - 1.0)
*/
void infrared_worker_set_raw_signal(
InfraredWorker* instance,
const uint32_t* timings,
size_t timings_cnt);
size_t timings_cnt,
uint32_t frequency,
float duty_cycle);

#ifdef __cplusplus
}
Expand Down

0 comments on commit ed1ebf9

Please sign in to comment.