#include "IR_Decoder.h" #if defined(ARDUINO_ARCH_STM32) && !defined(HAL_EXTI_MODULE_DISABLED) #include "Arduino.h" /* NVIC_SetPriority — CMSIS, как в IR_Encoder::begin и Car.ino (без HAL-заголовка yyxx). */ /** NVIC для линии EXTI пина (как в Arduino STM32 SrcWrapper interrupt.cpp). */ static IRQn_Type ir_decoder_exti_irqn_for_pin(uint8_t arduino_pin) { #if defined(STM32C0xx) || defined(STM32F0xx) || defined(STM32G0xx) || defined(STM32L0xx) (void)arduino_pin; return (IRQn_Type)(-1); #else const PinName p = digitalPinToPinName(arduino_pin); if (p == NC) { return (IRQn_Type)(-1); } const uint16_t pinmask = STM_GPIO_PIN(p); uint8_t id = 0U; uint16_t pm = pinmask; while (pm != 0x0001U) { pm = (uint16_t)(pm >> 1U); id++; } #if defined(STM32H5xx) || defined(STM32MP1xx) || defined(STM32L5xx) || defined(STM32U5xx) || defined(STM32WBAxx) static const IRQn_Type exti_irqnb[16] = { EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI5_IRQn, EXTI6_IRQn, EXTI7_IRQn, EXTI8_IRQn, EXTI9_IRQn, EXTI10_IRQn, EXTI11_IRQn, EXTI12_IRQn, EXTI13_IRQn, EXTI14_IRQn, EXTI15_IRQn}; #else static const IRQn_Type exti_irqnb[16] = { EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn}; #endif if (id < 16U) { return exti_irqnb[id]; } return (IRQn_Type)(-1); #endif } static void ir_decoder_apply_rx_exti_nvic(uint8_t arduino_pin, uint32_t preempt) { const IRQn_Type irqn = ir_decoder_exti_irqn_for_pin(arduino_pin); if ((int)irqn < 0) { return; } #if !defined(STM32C0xx) && !defined(STM32F0xx) && !defined(STM32G0xx) && !defined(STM32L0xx) NVIC_SetPriority(irqn, preempt); #endif } void IR_Decoder::setReceiveExtiPreemptPriority(uint32_t preempt) { rxExtiPreemptConfigured_ = true; rxExtiPreemptValue_ = preempt; if (extiEnabled_) { ir_decoder_apply_rx_exti_nvic(pin, preempt); } } #endif /* ARDUINO_ARCH_STM32 && !HAL_EXTI_MODULE_DISABLED */ std::list &IR_Decoder::get_dec_list() // определение функции { static std::list dec_list; // статическая локальная переменная return dec_list; // возвращается ссылка на переменную } // IR_Decoder::IR_Decoder() {}; IR_Decoder::IR_Decoder(const uint8_t pin, uint16_t addr, IR_Encoder *encPair, bool enableOnConstruct) : IR_DecoderRaw(pin, addr, encPair) { get_dec_list().push_back(this); if (enableOnConstruct) { enable(); } }; void IR_Decoder::enable() { auto &dec_list = get_dec_list(); if (std::find(dec_list.begin(), dec_list.end(), this) == dec_list.end()) { dec_list.push_back(this); } pinMode(pin, INPUT_PULLUP); attachInterrupt(pin, (*this)(), CHANGE); extiEnabled_ = true; #if defined(ARDUINO_ARCH_STM32) && !defined(HAL_EXTI_MODULE_DISABLED) if (rxExtiPreemptConfigured_) { ir_decoder_apply_rx_exti_nvic(pin, rxExtiPreemptValue_); } #endif } void IR_Decoder::disable() { extiEnabled_ = false; detachInterrupt(pin); pinMode(pin, INPUT); auto &dec_list = get_dec_list(); auto it = std::find(dec_list.begin(), dec_list.end(), this); if (it != dec_list.end()) { dec_list.erase(it); } } std::function IR_Decoder::operator()() { return std::bind(&IR_Decoder::isr, this); } IR_Decoder::~IR_Decoder() { IR_Decoder::get_dec_list().remove(this); } void IR_Decoder::tick() { for (const auto &element : IR_Decoder::get_dec_list()) { element->_tick(); } } void IR_Decoder::_tick() { IR_DecoderRaw::tick(); if (availableRaw()) { isWaitingAcceptSend = false; switch (packInfo.buffer[0] >> 5 & IR_MASK_MSG_TYPE) { case IR_MSG_DATA_ACCEPT: case IR_MSG_DATA_NOACCEPT: gotData.set(&packInfo, id); break; case IR_MSG_BACK: case IR_MSG_BACK_TO: gotBackData.set(&packInfo, id); break; case IR_MSG_REQUEST: gotRequest.set(&packInfo, id); break; case IR_MSG_ACCEPT: gotAccept.set(&packInfo, id); break; default: break; } if (gotData.isAvailable && (gotData.getMsgType() == IR_MSG_DATA_ACCEPT)) { acceptSendTimer = millis(); addrAcceptSendTo = gotData.getAddrFrom(); acceptCustomByte = crc8(gotData.getDataPrt(), 0, gotData.getDataSize(), poly1); if (addrAcceptSendTo && addrAcceptSendTo < IR_Broadcast) isWaitingAcceptSend = true; } gotRaw.set(&packInfo, id); } if (isWaitingAcceptSend && millis() - acceptSendTimer > acceptDelay) { encoder->sendAccept(addrAcceptSendTo, acceptCustomByte); isWaitingAcceptSend = false; } } bool IR_Decoder::isReceive(uint8_t type) { return (msgTypeReceive & 0b11111000) && ((msgTypeReceive & IR_MASK_MSG_TYPE) == type); }