Перейти к содержанию
    

repstosw

Участник
  • Постов

    2 650
  • Зарегистрирован

  • Победитель дней

    2

Весь контент repstosw


  1. Нужно прецезионно(равными интервалами) организовать считывание из SFR регистра и вывести сигнал на ножку. Не могу найти достоверные растактовки для инструкций ядра 8051. Встречаются разночтения: в одних источниках пишут, что инструкция DJNZ занимает 2/4 цикла в зависимости от результата, а других - в обоих случаях 2 цикла. Интересуют именно число циклов, без привязки к конкретной частоте. У меня недоверие и вопросы: как может инструкция с условным переходом выполняться одинаковое число тактов? Там всегда будет 2 значения циклов - в случае если переход выполнен, и в случае если перехода не будет. В частности меня интересует число циклов выполнения следующих инструкций: mov A,SFR movx @DPTR,A inc DPTR nop ;1 цикл djnz R2,Label mov A,#0x15 movx @R1,A clr A ;1 цикл ? mov R2,#0x18 sjmp Label
  2. Перечитал посты. Не нашёл как нормировать отсчёты мгновенной частоты. Кроме как что их надо как-то нормировать: Пока сделал Rail-to-Rail Clipper: отсекаю значения всё что выше от 1/4 максимального размаха. Потому что при отсутсвии полезного сигнала, амплитуды шумов в 4 раза выше, чем полезный сигнал. Есть ещё возможность установить по-больше усиление в Si4463 - отсчёты фазы будут больше. Цепочка такая: Отсчёты фазы => отсчёты частоты => Клипирование => Масштабирование => Корень приподнятого косинуса => Блок синхронизации => Бинарный слайсер Декодирование пакета работает правильно. Можно ли улучшить? Второй вопрос: возвращаясь к мягким отсчётам битов. Сейчас слайсер режет сигнал на биты. Как теперь найти "мягкое значение" для каждого бита? Вернуться к отсчётам частоты и времени максимума символа, найденного фильтром косинуса? Или как?
  3. OK, ещё раз перечитаю посты в теме. От 10 до 13 отсчётов на один информационный бит Да. Заметил. При больших значениях синхронизатор уходит в расколбас и комп повисает намертво, симуляция останавливается. Удалось заставить синхронизатор правильно работать. А также сдетектил синхро-слово и сформировал пакеты.
  4. Попробовал фильтр корня приподнятого косинуса. После определённых настроек теперь число горбов с выхода этого фильтра показывает число смежных бит в сигнале. Красный - выход с фильтра косинуса Синий - исходные отсчёты, полученные как разность фаз (снятые с Si4463) Зелёный - слайсер Надеюсь, оно теперь будет являться хорошей пищей для Symbol Sync.
  5. Поигрался в GNU Radio. Завёл свои отсчёты фазы в программу, привёл к нужному типу данных и нашёл мгновенную частоту как разность фаз. На этом лыжи дальше не едут: не получается восстановить частоту символов с помощью штатного блока Symbol Sync. У меня на каждый бит приходится 10...12 отсчётов, это и задаю в программе, но восстановленный поток битов вообще и близко не похож на исходный: Binary Slicer и то правильно работает, в отличие от Symbol Sync. Пробовал записать выходной поток бит после слайсера в файл: в момент преамбулы, запись бит "1" и "0" содержит по 10..12 отсчётов - по понятным причинам. Собственно 2 вопроса: 1) А точно Symbol Sync может работать именно на моих отсчётах сигнала? Может требуется какая-та предварительная обработка сигнала? 2) Возможно ли выровнять число отсчётов на бит уже после слайсера? Мне кажется, так даже будет логичнее - выровнять длительность каждого бита.
  6. Хотел поставить себе MATLAB последней версии(2023) Trial, но к сожаелению под Win7 он не идёт. А Matlab 6.5 и 2011R - слишком стары, и они не тянут свежие примеры: отстутствует компонент comm.*. Попробовал запускать модели от petrov в своих матлабах, они открываются, но при симуляции валится много ворнингов. Проблема в кривости моих Matlab'ов или в отсутствии знаний как правильно запускать модели. Смотрел в сторону Octave. Разочаровался что под него примеров мало. Ищу примеры Symbol Clock Recovery. Принял решение остановиться на GNU Radio. Он бесплатен и не выёживается на моём ПК. Для Matlab (крякнутые версии) приходится переводить часы назад, иначе не запускается. А когда переводишь часы назад - интернет не работает (SSL-сертификаты). Поэтому остаётся либо GNU Radio, либо через Python фреймворк работать. Под них куча примеров. GNU Radio хорош ещё тем, что генерит сорцы на Си и сам открытый - можно на раздербан пустить - в плане вытащить алгоритм/фильтры... petrov, komah спасибо за ответы!
  7. Требование к целому числу отсчётов - это для выходных данных, которые подаются на интерполятор? Или это интерполятор выдаёт целое число отсчётов? В приведённых последних картинках, у меня на 1 символ может приходиться 11...13 отсчётов. Что делать? Опять же - какое число отсчётов на символ имеется ввиду? До- или после- интерполятора? Прочтитал про TED Гарднера, увидел на картинках, что для его использования - последовательность данных должна иметь 2 отсчета на символ. Питается он этими отсчётами после интерполятора, исходя из структурной схемы, которая приведена в статье Чхоудхури. Получается мне нужен ресемплер в режиме дециматора что-ли? Чтобы свои 11..13 отсчётов превратить в 2 отсчёта для TED? Чё-то каша в голве у меня, пазл не складывается. И вообще, с какими отсчётами мне работать? С фазой или с мгновенной частотой? Если с фазой, то насколько критичны разрывы фазы? Надо ли делать unwrap перед входом на интерполятор. Проще говоря - у меня есть отсчёты фазы , будем пока считать matched Filter внутри микросхемы трансивера. Что подавать на интерполятор? Тоже непонятно. В статье ДВЕ структурные схемы: с одним интерполятором и с двумя. Какую надо использовать? И собственно, что мы этой схемой пытаемся достичь? Чтобы число отсчётов на каждый символ было одинаковым и постоянным? Зачем это нужно для 2FSK? Её можно декодировать даже на глаз, не применяя сложные схемы по стабилизации символьной скорости. При условии, если число отсчётов на символ достаточно большое - в моём случае 11..13 отсчётов. Такое даже ребёнок сдекодирует. Амплитуды там вообще по барабану, это же не КАМ-256 какой-нибудь, а всего лишь 2 FSK. Там только накапливать отсчёты с одинаковым знаком, резать их на биты, а остаток при смене полярности - решать: преобразовывать ли в бит или пропускать... Реализацию на Си я давал уже здесь. Алгоритм работает на моём сигнале. Что за БИХ фильтр? RC-цепочка интегратор? Какая у него реализация - функция выхода от входа описанная в алгоритмах - какая? Есть ли окно для эффекта памяти, какие коэффициенты? Откуда взялись 83 вх и 10 вых отсчётов? Почему именно столько надо? Опять же - зачем для 2FSK восстанавливать тактовую? Когда биты хорошо детектятся визуально перепадами и номинальным числом отсчётов 11..13 ? Всё что меньше - шум и мусор, всё что больше - режется на последовательности из одинаковых бит. И там он вообще 2 схемы привёл. И расписал в общих чертах алгоритм. И самого главного нет - где имплементация на каком-нибудь языке? На Си предпочтительнее. Я вот например - не понимаю как должен быть программно описан matching Filter p(-n*Ts). предполагаю что это приподнятый косинус с которого квадратный корень... Пока у меня в голове каша, если честно. И непонятно вообще - нужно ли в моём случае это делать с 2FSK с 10 отсчётами на бит.
  8. 1. Документации нет и не будет 2. В качестве донора - сорцы Линукса, у-бута и прочие вещи. 3. Мозговой штурм. Эксперименты. 4. Кое-что даже удаётся сделать по куцему даташиту (GPIO, PWM, I2S, LRADC) Но в основном - жёсткий секс с Линуксом 🐥
  9. Всё ещё впереди! ))) Сделал детектор паттерна преамбулы и нахождение синхрослова. И выпарсил данные наконец-то и проверил их. Все три пакета правильные. Корона не жмёт? :)))
  10. Пока не смотрел ИХ фильтра на GFSK и FSK. Сделал свой битовый синхронизатор, по крайней мере преамбулу и синхрослово ищет без ошибок : //BitStream Engine u32 b=0; u32 counter0=0; u32 counter1=0; #define THR 12 #define DEL 2 for(u32 i=0;i<SIZE;i++) { if(BufferOut[i]>0) //'1' { if(counter0) { if(counter0>=THR-DEL)bitstream[b++]='0'; counter0=0; } counter1++; if(counter1==THR) { bitstream[b++]='1'; counter1=0; } } else if(BufferOut[i]<0) //'0' { if(counter1) { if(counter1>=THR-DEL)bitstream[b++]='1'; counter1=0; } counter0++; if(counter0==THR) { bitstream[b++]='0'; counter0=0; } } } ... Preamble (64 bytes "0101..."): 0101010101010101010101010101010101010101010101010101010101010101 0101010101010101010101010101010101010101010101010101010101010101 0101010101010101010101010101010101010101010101010101010101010101 0101010101010101010101010101010101010101010101010101010101010101 0101010101010101010101010101010101010101010101010101010101010101 0101010101010101010101010101010101010101010101010101010101010101 0101010101010101010101010101010101010101010101010101010101010101 0101010101010101010101010101010101010101010101010101010101010101 Sync: 0101 => 5 1010 => A 0000 => 0 1111 => F 1011 => B 1110 => E 0110 => 6 0110 => 6 Data (0,1,2,3,...,255): 00000000 00000001 00000010 00000011 00000100 00000101 00000110 00000111 00001000 00001001 00001010 00001011 00001100 00001101 00001110 00001111 ...
  11. Удалил повторяющиеся отсчёты из raw-файла. Теперь соседние отсчёты фазы различны, и мгновенная частота не возвращается к нулю несколько раз. Очевидно, для скорости 50 кбит/с было пересемплирование. И теперь на 1 бит приходится 12-13 отсчётов всегда: Насколько высок потенциал для нахождения мягких решений?
  12. Скорость взятия отсчётов зависит программы, насколько быстро она может читать регистр. С учётом кольцевой буферизации, DMA и одинакового интервала взятия отсчётов - 20 машинных циклов 8051, больше, чем 1 300 000 отсчётов за 1 секунду - не получить.
  13. Да. Возвраты к нулю происходят от того что иногда соседние отсчёты фазы одинаковы (на скорости 50 кбит/с): Пофиксил отсчёты: +0+, -0-, +00+, -00-. Значения в нулях - нашёл интерполяцией. Вот так вышло (рисунок внизу): Для +0+ и -0-: //Step 1: Kill -0- for(u32 t=0;t<SIZE;t++)if((s[t]<0)&&(s[t-1]==0)&&(s[t-2]<0)) { y[t-1]=(s[t]+s[t-2])/2; //-2147483648.0/2; } for(u32 t=0;t<SIZE;t++)if((s[t]>0)&&(s[t-1]==0)&&(s[t-2]>0)) { y[t-1]=(s[t]+s[t-2])/2; //2147483647.0/2; } Для +00+ и -00-: //Step 2: Kill -00- for(u32 t=0;t<SIZE;t++)if((s[t]<0)&&(s[t-1]==0)&&(s[t-2]==0)&&(s[t-3]<0)) { float k=(s[t]-s[t-3])/3; y[t-2]=s[t-3]+k*1; y[t-1]=s[t-3]+k*2; } for(u32 t=0;t<SIZE;t++)if((s[t]>0)&&(s[t-1]==0)&&(s[t-2]==0)&&(s[t-3]>0)) { float k=(s[t]-s[t-3])/3; y[t-2]=s[t-3]+k*1; y[t-1]=s[t-3]+k*2; } Каким фильтром это можно сделать? ФНЧ боюсь срежет скаты, будет плохо. А если ноль между минусами превратить в минимум, а ноль между плюсами - в максимум, то получается прямо закраски битов данных дискретно. В логарифмической шкале ещё лучше: Мусор слева: Уже можно детектор преамбулы писать! :))) Кстати, что есть мягкое решение для одного бита? Нормированная площадь отсчётов на 1 бит?
  14. Прочитайте название темы. Причём тут замирания? Нужно получить битовый поток из сигнала модулятора. Про замирания - в других темах. Пока мне нужно оценить, насколько полезно может быть применение отсчётов мгновенной фазы для моих целей. Мои цели - отказаться от встроенного модема Si4463 и научиться находить битовый поток с отсчётов фазы демодулятора. Задача как я понял, не тривиальная. При этом мне нужны не просто биты в виде 0 и 1, а результат в виде мягких решений: [0.0...1.0], для того, чтобы загнать это на LDPC или Турбо-код. Хочу поиграться с мягким выходом демодулятора и оценить насколько FEC на мягких решениях более эффективна, чем FEC на жёстких решениях, которая уже работает. Тоесть, если разбить на под-этапы: 1) Получение сигнала мгновенной частоты с отсчётов фаз 2) Обработка сигнала (фильтрация, клиппинг, интерполяция,...) 3) Обнаружение преамбулы, нахождение тактовой частоты потока бит (сколько отсчётов на бит - среднее, и плюс-минус) 4) Нахождение синхрослова 5) Получение мягких решений для каждого бита, коррекция тактовой частоты битового потока (на базе алгоритмов корелляции, предсказания, ...) Нужна конкретика, а не общие слова... Тот же эквалайзер Витерби. Я ничего по нему не нашёл, кроме как хвалебные оды о том, какой он хорош. А где микросхема этого эквалайзера? А программная реализация? Или может мне сразу выломать кусок с сотовой БС и использовать готовую плату? К тому же, ЕМНИП эквалайзер Витерби борется с частотно-селективными замираниями. А у меня плоские замирания. Так что нужен он мне или нет - ещё большой вопрос. И MIMO - это тоже мимо для моих целей. Ставить 4 антенны на передачу (привет, матрица Аламоути!) или на приём - как-то не хочется. У трубки телефона - 1 сотовая антенна. И отсылка к книгам Скляра - это тоже ни о чём. Нужен - номер раздела, параграф, название. Конкретика. Какой фильтр посмотреть, как подчистить шумы, как получить мгновенную частоту битовых отсчётов и тому подобное. Формализую задачу. raw-файл отсчётов фазы (не обработан - прямой забор с демодулятора): https://dropmefiles.com/aNLMd Дано: raw-файл с отсчётами фазы, снятыми с демодулятора Si4463. Каждый отсчёт хранится в байте. Каждый отсчёт 7-битный знаковый: -64...+63. Причём знаковый бит - 6-й, а не 7-й (7-й бит пустой и всегда равен 0) В файле есть участки с принятым пакетом, который содержит: преамбулу 64 байта, синхрослово 32 байта (значение 0x5A0FBE66 ) и 6080 байт PayLoad (байты от 0 до 255, по возрастанию, повторяются). Параметры модема: модуляция 2FSK, скорость 50 кбит/c, девиация частоты +/-25 кГц, полоса пропускания приемника: 150 кГц. Надо: получить буфер бит данных (6080*8) мягких решений в диапазоне от 0.0 до 1.0. Допускается использовать мгновенные отсчёты и окна фиксированного размера (для оконных функций, фреймов). Тоесть - обработка данных в оффлайне. на 50 кбит/c обработанные отсчёты фазы (мгновенная частота) смотрятся веселее: снизу - отсчёты фазы:
  15. 🤣🤣🤣 Ну не успевает он отрисовать за время VBLANK, поэтому и видите полоску сверху (или снизу, если полярность синхронизации проинвертирована). Попробуйте в настройках TCON пересчитать времянки так, чтобы увеличить ширину VSYNC-пульса. Или грубо FPS в 2 раза меньше сделайте. 20 мс >> T vblank И да: сделайте двойную буферизацию и переключайте адрес отображения видеопамяти (переключать адрес надо по VSYNC или вообще в прерывании от TCON): пока вы будете смотреть на одну страницу, во второй процессор будет рисовать. И времени будет всяко-больше, до следующего обновления дисплея. P.S. У меня во всех приложениях работа с отображением графики строго синхронна с обновлением дисплея
  16. Почитал ваши сообщения на другом форуме: https://www.radioscanner.ru/forum/topic42854.html Вы постоянно занимаетесь тем, что из мухи раздуваете слона. Одни заумные рассуждения и только. Практического толку от таких рассуждений - ноль. Как говорится, у одного хобби пытаться что-то делать. А у другого - гнуть пальцы и демонстрировать свою крутость.
  17. Какие следующие шаги должны быть? Нужно засинхронизироваться и начать по выборкам определять биты. Сделал полифазный фильтр, работающий в сторону апсемплинга. Код брал на гитхабе. Вышла лажа: отсчёты делает некорректно. Попробовал ресемплинг в Audacity - довольно неплохо 4:1. Как теперь найти интервал взятия отсчётов и нужна ли энергия битов? Пробовал вручную найти интервал выборки - получается уход постоянно:
  18. Проверил. Эта сумма квадратов всегда равна единице. Выкинул её. График без изменений. Облегчило конвеер вычислений. Почему-то сразу вспомнил основное тригонометрическое тождество...
  19. Сделал замеры. На битовой скорости 625 кБит/c получается 2,19 отсчётов. Грубо - 2 отсчёта на символ. Ни о каких мягких решениях нельзя говорить при таком битрейте. Но для скоростей десятки килобит в секунду сгодится. Всё из-за ограниченной пропускной способности SPI: максимально работает на половине тактовой частоты кварца: 37.5/2 = 18.75 МГц. Дальше только усекать разрядность выборок и толкать в байт. ЕМНИП для мягких решений достаточно трёх бит, остальное лишнее. Попробовал ещё включить логарифмическую визуализацию - с ней красивше смотрится: Вверху - через квадратуры, внизу - через разность. И что там в первом GSM смотреть? Слишком много всего написано, и не факт что найду нужное. К тому же я не припомню, чтобы первый GSM решал вопросы скоростей выше 0,5 МБит/c
  20. Соединил ВЧ входы двух устройств через аттенюатор -30 дБ. Мощность -10 дБм. Снял фазу сигнала. Результат ничем не отличается от сигнала, принятого с эфира. Потому что оба устройства находятся рядом. И всё-же КМК форма сигнала, найденная через квадратуры и раскрытую производную арктангенса лучше смотрится, чем производная с раскрытого арктангенса. Проще говоря, рисунок ниже - лучше (нет АМ и меньше заусенцев): И кстати, почему когда передаётся преамбула, видно на графике, что частота слегка подплющивается периодически? Ну тоесть она как бы слегка частотно-модулированная визуально. Выровнял чтения регистра фазы. Теперь отсчёты фазы бирутся через одинаковый временной интервал. Стало лучше. Но выбросы всёравно остались.
  21. Сигнал принимаю по эфиру со второго трансивера Si4463. Модемы настроены одинаково. Модуляция, как я уже писал - пока выбрана 2FSK, битрейт 625 кбит/c. Si4463 разогнана немного: припаял кварц 37.5 МГц вместо шатного кварца30 МГц. Это позволило на 25% увеличить битрейт и увеличить скорость SPI до 15 МГц. До этого сделал стандартно обработку пакетов в дуплексном режиме. На два MJPEG кадра 160x240 + два потока сжатого звука хватает. Прикрутил коррекцию ошибок - длинный RS-кодек, исправляющий до 10...12.5% ошибок в пакете . Коррекция ошибок помогает когда сигнал сильно слабый (проверял). Чем слабже сигнал, тем больший % пакетов исправляется коррекцией. Вот статистика для выходной мощности 0,1 мВт (-10 дБм): из принятых 2160 пакетов - 602 пакета пришли битыми - они успешно исправлены, и 54 битых пакета с невозможностью исправить. ! - пакет пришёл без ошибок * - пакет с ошибками, успешно восстановлен ? - пакет исправить не удалось. перемещение по комнатам с приёмопередатчиком в руках.
  22. Заработал нормально diff (unwrap ( ) ) Нужно было диапазон -64...+63 привести к 8 битному. Иначе скругление разницы не работало. Пока просто умножил на 2: диапазон -128... +126. Правильнее надо -128...+127 s8 BufferIn[SIZE]; s8 BufferOut[SIZE]; BufferOut[0]=0; for(int i=1;i<SIZE;i++) { BufferOut[i]=2*(BufferIn[i]-BufferIn[i-1]); } Выбросы как я понимаю из-за погрешностий интервала взятия отсчётов. При нахождении разницы unwrap не нужен. Так как происходит переполнение 8-бит с скругление с + на -.
  23. Unwrap не получается сделать так, чтобы он правильно работал: он ползёт куда-то вверх, и не всегда срабатывает - оставляются переполнения. Может в MATLAB оно и работает превосходно, но Си-шный алгоритм даёт фигню мягко говоря... К тому же, если размотанная фаза будет постоянно ползти, то и 32 бит скоро может не хватить.
  24. Задача решена. Нашёл синхро-слово после преамбулы, которое передаю (преамбула 010101...0101, синхрослово: 0x5A0FBE66 - в эфире: 01011010 00001111 10111110 01100110). Скорость 0.5 МБит/c, модуляция 2FSK: Очень помогла вот эта статья: https://ru.dsplib.org/content/signal_fm_demod/signal_fm_demod.html В ней написано, как получить мгновенную частоту FM-сигнала и как избавиться от разрывов арктангенса. По мгновенным отсчётам фазы, вначеле построил I- и Q- сигналы. Их магнитуда условно принята M=1, так как амплитудная составляющая предполагается постоянной при угловой модуляции (ЧМ, ФМ) а также включено АРУ в приёмнике. Затем нашёл мгновенные значения модулирующей частоты по формуле из статьи: Весь конвеер: Packet - исходные отсчёты фазы (полученные из Si4463 с помощью программы-эксплоита, и переданные на хост-контроллер для записи данных). OutI - синфазная составляющая, найденная по отсчётам фазы: I(o)=M*cos(o) OutQ - квадратурная составляющая, найденная по отсчётам фазы: Q(o)=M*sin(o) OutF - итоговая модулирующая частота, по которой ищется синхро-слово и пакет за ним. Программа на Сях (накидал на скорую руку): #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> #include "Type.h" #define SIZE 32538 s8 BufferIn[SIZE]; float BufferOutI[SIZE]; float BufferOutQ[SIZE]; float BufferOutF[SIZE]; int main(void) { FILE *f=fopen("Packet.raw","rb"); fread(BufferIn,SIZE,1,f); fclose(f); for(int i=0;i<SIZE;i++) { s8 o=BufferIn[i]; float fi=((float)o)*M_PI/64; if(fi<-M_PI)fi=-M_PI; else if(fi>+M_PI)fi=+M_PI; float I=cosf(fi); float Q=sinf(fi); BufferOutI[i]=I; BufferOutQ[i]=Q; } BufferOutF[0]=0.0F; for(int i=1;i<SIZE;i++) { float dI=BufferOutI[i]-BufferOutI[i-1]; float dQ=BufferOutQ[i]-BufferOutQ[i-1]; BufferOutF[i]=((dQ*BufferOutI[i])-(dI*BufferOutQ[i]))/((BufferOutI[i]*BufferOutI[i])+(BufferOutQ[i]*BufferOutQ[i])); } f=fopen("outI.raw","wb"); fwrite(BufferOutI,SIZE,sizeof(float),f); fclose(f); f=fopen("outQ.raw","wb"); fwrite(BufferOutQ,SIZE,sizeof(float),f); fclose(f); f=fopen("outF.raw","wb"); fwrite(BufferOutF,SIZE,sizeof(float),f); fclose(f); } Пока есть небольшой джиттер. Я могу позволить себе до 8 отсчётов на символ максимум при символьной скорости до 625 кбит/с. Так что-ли? Мне пока интересно софтово это сделать. Уже вычислил. Нормированные, правда. Но в моём случае амплитуда не нужна.
×
×
  • Создать...