У меня такой алгоритм: Разбил работу на процесс захвата посылки и процедуру распознавания захваченных посылок. Захват посылки: Изначально процесс захвата посылки ищет тишину на линии не менее заданной, при её обнаружении переходит в состояние "ожидания первого перепада 0->1 или 1->0". После первого перепада переходит в состояние "захват посылки". Выход из этого состояния - по обнаружении тишины на линии не менее T1 мсек. После обнаружения каждого перепада кратковременно переходит в состояние "подавление дребезга" (просто пауза T2 мкс в течение которой состояние линии не анализируется - для ограничения загрузки CPU при ВЧ-помехах на линии). При обнаружении ошибочных состояний (например: превышение максимально допустимого числа перепадов в посылке; превышение общей длительности посылки; нарушение фазы (состояние покоя до посылки и после посылки - разное) и прочих), процесс захвата переходит в состояние "ожидание тишины на линии не менее времени T3" (T3 > T1; T3 - минимальный интервал тишины между двумя посылками ИК-приёмника). Записываю в массив длительности нулей и единиц, начиная от первого перепада 0->1 или 1->0 (знаю что у TSOP состояние покоя - единица вроде, но просто на всякий случай сделал возможность работы на инверсном сигнале) и до обнаружения паузы пороговой длительности. С разрешением 1мкс (можно меньше, точности хватит). Обнаружение заданной паузы T1 - конец посылки, после этого начинаю анализ посылки. Анализ посылки: Приёмник ИК-посылок у меня работает в одном из двух режимов - обучение или детектирование. В режиме обучения каждая новая принятая посылка сравнивается с массивом имеющихся посылок и, если обнаружена похожая, эти посылки сливаются в одну суммарную посылку для которой длительности нулей и единиц рассчитываются как средние между первой и второй сливаемыми посылками. После слияния посылок, анализирую весь остальной массив посылок на похожесть с новой посылкой и, если обнаружена похожая, суммирую эти посылки. И так далее, пока не проверен весь массив накопленных посылок на непохожесть. Это нужно, так как после прибавления к существующей посылке новой посылки, длительности её импульсов меняются и она может оказаться похожей на другую, на которую раньше была не похожа. У меня есть пороговый критерий "похожести". В режиме детектирования, приёмник просто сравнивает новую посылку с массивом имеющихся и, если найдена похожая, выдаёт на выход код виртуальной кнопки назначенной готовой посылке, не сливая её с новой посылкой. Если не найдено похожей - посылка отбрасывается. Алгоритм сравнения посылок на похожесть: Я сравниваю не длительности 0 и 1, а длительности пар 0/1 и 1/0. Это гораздо более надёжный способ как показала практика на многих пультах. Т.е. - процедура сравнения определяет если длительности всех пар 0/1 или длительности всех пар 1/0 двух разных посылок отклоняются не более чем на K друг от друга - посылки похожие. Сейчас у меня K == 5%. Насчёт формата посылок от разных пультов, обнаружил два вида пультов: 1. Для каждой кнопки выдают определённую уникальную посылку, а при длительном удержании - генерят код автоповтора (общий для всех кнопок пульта). 2. Для каждой кнопки имеют две уникальных посылки, при длительном удержании нажатой кнопки повторяют одну посылку, при каждом новом нажатии - выдают другую посылку из пары. Так что при обучении пульту, я задаю либо для каждой виртуальной кнопки одну посылку и один общий код автоповтора для всего пульта; или каждой кнопке назначаю 2 посылки (в этом случае кода автоповтора нет). К тому-же - если у Вас 32 - это максимальное количество 0 и 1 в посылке - это слишком мало. Есть пульты, выдающие несколько десятков импульсов. У меня максимальное количество импульсов в посылке задано ==100 (встречал пульты выдающие около 60 импульсов на посылку, может есть и больше). Описанный алгоритм у меня работает уже несколько лет, проверял с десятком разных пультов - нажатия детектирует почти 100%-но. Не детектируются только нажатия, на которые наложилась помеха. ПО у меня может обучаться и хранить информацию сразу о кнопках нескольких разных пультов (сколько хватит памяти) и детектирует посылки сразу от всех пультов и имеющихся в базе. Эти пульты могут разных типов (тип1 или тип2). Так что наружу процесс детектирования выдаёт сообщение вида: пультM.кнопкаN.флаг_автоповтора(с длительностью). И захватывать посылки надо не по прерыванию на ноге (слишком низкая точность, зависящая от загрузки CPU к тому же), а таймером, работающим в режиме захвата. Тогда разрешение можно поставить любое, хоть 1мкс, хоть меньше (хотя это уже избыточно имхо).
|