From 0bc2a81c0aab3c89b534415d6f07d07e392260ce Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Sat, 3 Jun 2017 20:47:37 +0200 Subject: o Adding support for reading IR codes. --- src/radio-controller.cpp | 257 ++++++++++++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 102 deletions(-) (limited to 'src') diff --git a/src/radio-controller.cpp b/src/radio-controller.cpp index 0f60717..8b350d2 100644 --- a/src/radio-controller.cpp +++ b/src/radio-controller.cpp @@ -5,11 +5,13 @@ #include "mcu/arm/semihosting.h" #include "mcu/stm32cube/uart.h" #include "mcu/stm32cube/debug.h" +#include "misc.h" using mcu::arm::mutex; extern IWDG_HandleTypeDef hiwdg; extern TIM_HandleTypeDef htim1; +extern TIM_HandleTypeDef htim2; extern UART_HandleTypeDef huart2; mcu::stm32cube::uart::uart_port uart2(&huart2); @@ -20,25 +22,34 @@ struct sample { uint16_t pulse_us; }; -template -class sample_buffer { - sample samples[BufferSize]; +template +class buffer { + T samples[BufferSize]; - volatile unsigned int _size; + volatile unsigned int size_; - bool _first; + bool first_; + int part_; public: void reset() { - _size = 0; - _first = true; + size_ = 0; + first_ = true; + part_ = 1; + } + + bool check_first_part() + { + bool first = part_ == 1; + part_ = first ? 2 : 1; + return first; } bool check_first() { - if (_first) { - _first = false; + if (first_) { + first_ = false; return true; } return false; @@ -47,35 +58,47 @@ public: __always_inline unsigned int size() const { - return _size; + return size_; + } + + __always_inline + bool is_empty() const + { + return size_ == 0; } __always_inline bool is_full() const { - return _size == BufferSize; + return size_ == BufferSize; } __always_inline - void append(sample sample) + void append(T sample) { - if (_size == BufferSize) { + if (size_ == BufferSize) { return; } - samples[_size++] = sample; + samples[size_++] = sample; } __always_inline - sample at(int i) const + T at(int i) const { return samples[i]; } }; -volatile int sample_index; -sample_buffer<10> buffer; -mutex buffer_lock; +template +using sample_buffer = buffer; + +sample_buffer<10> radio_buffer; +mutex radio_buffer_lock; + +sample_buffer<30> ir_buffer; +buffer<100, uint16_t> ir_level_buffer; +mutex ir_buffer_lock; void main_pre_init() { @@ -99,60 +122,23 @@ void main_post_init() printf("Radio Controller\n"); - buffer.reset(); - sample_index = 0; + radio_buffer.reset(); + radio_buffer_lock.unlock(); + ir_buffer.reset(); + ir_level_buffer.reset(); + ir_buffer_lock.unlock(); uart2.enable(); hal_ok(HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1)); + hal_ok(HAL_TIM_Base_Start(&htim2)); + hal_ok(HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1)); + hal_ok(HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2)); } static uint32_t tick_next = 0; //static bool seen_high = false; -#include -#include -#include - -template -struct from_f_cpu_and_time_per_timer_tick { - template - using r = std::ratio; - - using f_cpu = r; - using seconds_per_cpu_tick = r<1, f_cpu::num>; - using seconds_per_timer_tick = SecondsPerTimerTick; - using timer_frequency = r; - -// static constexpr std::intmax_t prescaler = std::ratio_divive::value; - using prescaler_t = std::ratio_divide; - static_assert(prescaler_t::den == 1, "Could not represent the prescaler as an integer"); - static constexpr std::intmax_t prescaler = prescaler_t::num; - - // us_per_timer_tick = seconds_per_timer_tick * 1'000'000 - using us_per_timer_tick_t = typename std::ratio_multiply>::type; - - static constexpr uint16_t us_per_timer_tick = static_cast(us_per_timer_tick_t::num); - - template - __always_inline constexpr - static T to_us(unsigned int count) - { - return T(count * us_per_timer_tick); - } -}; - -using values = from_f_cpu_and_time_per_timer_tick<72'000'000, std::ratio_multiply, std::micro>>; - -//static_assert(values::timer_frequency::num == 200'000, "timer_frequency::num"); -static_assert(values::timer_frequency::den == 1, "timer_frequency::den"); -//static_assert(std::is_same< -// values::timer_frequency, -// std::ratio<200'000, 1>>::value, "Timer frequency is not 200kHz"); -static_assert(values::prescaler == 360, "Timer frequency is not 200kHz"); -static_assert(values::prescaler - 1 == RADIO_RX_TIMER_PRESCALER, "Bad prescaler from STM32CubeMX"); -static_assert(values::us_per_timer_tick == 5, "bad us_per_timer_tick"); - void main_loop() { auto now = HAL_GetTick(); @@ -167,44 +153,64 @@ void main_loop() // seen_high = false; } - if (buffer.is_full()) { - buffer_lock.lock(); + if (radio_buffer.is_full()) { + radio_buffer_lock.lock(); hal_ok(HAL_TIM_IC_Stop_IT(&htim1, TIM_CHANNEL_1)); -// printf("Period:"); -// for (unsigned int i = 0; i < buffer.size(); i++) { -// printf(" %u", buffer.at(i)); -// } -// printf("\n"); - -// dbg.print("Pulse: "); -// for (unsigned int i = 0; i < buffer.size(); i++) { -// auto p = values::to_us(buffer_pulse.at(i)); -// dbg.print(" %05u", p); -// } -// dbg.print("\n"); -// -// dbg.print("Period:"); -// for (unsigned int i = 0; i < buffer.size(); i++) { -// auto p = values::to_us(buffer_period.at(i)); -// dbg.print(" %05u", p); -// } -// dbg.print("\n"); - - dbg.println("Samples"); - for (unsigned int i = 0; i < buffer.size(); i++) { - sample s = buffer.at(i); + /* + dbg.println("Radio"); + for (unsigned int i = 0; i < radio_buffer.size(); i++) { + sample s = radio_buffer.at(i); auto pulse = s.pulse_us; auto period = s.period_us; - dbg.println("%d %d, %d%%", period, pulse, int(pulse / double(period) * 100)); + dbg.println("%d us %d us, %d%%", period, pulse, int(pulse / double(period) * 100)); } dbg.println(); + */ - buffer.reset(); - sample_index = 0; + radio_buffer.reset(); hal_ok(HAL_TIM_IC_Start_IT(&htim1, TIM_CHANNEL_1)); - buffer_lock.unlock(); + radio_buffer_lock.unlock(); + } + + /* + if (ir_buffer.is_full()) { + ir_buffer_lock.lock(); + + hal_ok(HAL_TIM_IC_Stop_IT(&htim2, TIM_CHANNEL_1)); + hal_ok(HAL_TIM_IC_Stop_IT(&htim2, TIM_CHANNEL_2)); + dbg.println("IR"); + for (unsigned int i = 0; i < ir_buffer.size(); i++) { + sample s = ir_buffer.at(i); + auto pulse = s.pulse_us; + auto period = s.period_us; + dbg.println("% 5d us % 5d us, %.02d%%", period, pulse, int(pulse / double(period) * 100)); + } + dbg.println(); + + ir_buffer.reset(); + hal_ok(HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1)); + hal_ok(HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2)); + ir_buffer_lock.unlock(); + } + */ + + if (ir_level_buffer.is_full()) { + ir_buffer_lock.lock(); + + HAL_NVIC_DisableIRQ(TIM2_IRQn); + + dbg.println("IR"); + for (unsigned int i = 0; i < ir_level_buffer.size(); i++) { + uint16_t s = ir_level_buffer.at(i); + dbg.println("% 5d us", s); + } + dbg.println(); + + ir_level_buffer.reset(); + ir_buffer_lock.unlock(); + HAL_NVIC_EnableIRQ(TIM2_IRQn); } // seen_high |= HAL_GPIO_ReadPin(RADIO_RX_GPIO_Port, RADIO_RX_Pin); @@ -214,26 +220,63 @@ void main_loop() //static uint16_t start = 0; -void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) +uint16_t ir_value1, ir_value2; + +static +void ir_rx(TIM_HandleTypeDef *htim) { - if (htim->Channel != HAL_TIM_ACTIVE_CHANNEL_1) { + if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { + debug_pin(2); + } + if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { + debug_pin(3); + } + + if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { + ir_value1 = static_cast(htim->Instance->CCR1); + } else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { + ir_value2 = static_cast(htim->Instance->CCR2); + } + + if (ir_level_buffer.check_first()) { return; } -// if (buffer.check_first()) { + if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) { + ir_level_buffer.append(values::to_us(ir_value1 - ir_value2)); + } else if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_2) { + ir_level_buffer.append(values::to_us(ir_value2)); + } + + /* + if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1 && !ir_buffer.check_first()) { + if (ir_buffer_lock.try_lock()) { + ir_buffer.append({values::to_us(ir_value1), values::to_us(ir_value2)}); + + ir_buffer_lock.unlock(); + } + } + */ +} + +static +void radio_rx(TIM_HandleTypeDef *htim) +{ + if (htim->Channel != HAL_TIM_ACTIVE_CHANNEL_1) { + return; + } +// if (radio_buffer.check_first()) { // return; // } static uint16_t value1, value2; - if (sample_index == 0) { + if (radio_buffer.check_first_part()) { // value1 = static_cast(HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)); value1 = static_cast(htim->Instance->CCR1); - sample_index = 1; } else { // value2 = static_cast(HAL_TIM_ReadCapturedValue(htim, TIM_CHANNEL_1)); - value2 = static_cast(htim->Instance->CCR1); - sample_index = 0; + value2 = static_cast(htim->Instance->CCR2); uint16_t diff; if (value2 > value1) { @@ -244,10 +287,20 @@ void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) return; } - if (buffer_lock.try_lock()) { - buffer.append({values::to_us(0), values::to_us(diff)}); + if (radio_buffer_lock.try_lock()) { + radio_buffer.append({values::to_us(0), values::to_us(diff)}); - buffer_lock.unlock(); + radio_buffer_lock.unlock(); } } } + +void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) +{ + if (htim == &htim1) { + radio_rx(htim); + } + if (htim == &htim2) { + ir_rx(htim); + } +} -- cgit v1.2.3