-
Постов
2 650 -
Зарегистрирован
-
Победитель дней
2
Весь контент repstosw
-
8051 число циклов выполнения инструкции
repstosw опубликовал тема в В помощь начинающему
Нужно прецезионно(равными интервалами) организовать считывание из 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 -
Перечитал посты. Не нашёл как нормировать отсчёты мгновенной частоты. Кроме как что их надо как-то нормировать: Пока сделал Rail-to-Rail Clipper: отсекаю значения всё что выше от 1/4 максимального размаха. Потому что при отсутсвии полезного сигнала, амплитуды шумов в 4 раза выше, чем полезный сигнал. Есть ещё возможность установить по-больше усиление в Si4463 - отсчёты фазы будут больше. Цепочка такая: Отсчёты фазы => отсчёты частоты => Клипирование => Масштабирование => Корень приподнятого косинуса => Блок синхронизации => Бинарный слайсер Декодирование пакета работает правильно. Можно ли улучшить? Второй вопрос: возвращаясь к мягким отсчётам битов. Сейчас слайсер режет сигнал на биты. Как теперь найти "мягкое значение" для каждого бита? Вернуться к отсчётам частоты и времени максимума символа, найденного фильтром косинуса? Или как?
-
OK, ещё раз перечитаю посты в теме. От 10 до 13 отсчётов на один информационный бит Да. Заметил. При больших значениях синхронизатор уходит в расколбас и комп повисает намертво, симуляция останавливается. Удалось заставить синхронизатор правильно работать. А также сдетектил синхро-слово и сформировал пакеты.
-
Попробовал фильтр корня приподнятого косинуса. После определённых настроек теперь число горбов с выхода этого фильтра показывает число смежных бит в сигнале. Красный - выход с фильтра косинуса Синий - исходные отсчёты, полученные как разность фаз (снятые с Si4463) Зелёный - слайсер Надеюсь, оно теперь будет являться хорошей пищей для Symbol Sync.
-
Поигрался в GNU Radio. Завёл свои отсчёты фазы в программу, привёл к нужному типу данных и нашёл мгновенную частоту как разность фаз. На этом лыжи дальше не едут: не получается восстановить частоту символов с помощью штатного блока Symbol Sync. У меня на каждый бит приходится 10...12 отсчётов, это и задаю в программе, но восстановленный поток битов вообще и близко не похож на исходный: Binary Slicer и то правильно работает, в отличие от Symbol Sync. Пробовал записать выходной поток бит после слайсера в файл: в момент преамбулы, запись бит "1" и "0" содержит по 10..12 отсчётов - по понятным причинам. Собственно 2 вопроса: 1) А точно Symbol Sync может работать именно на моих отсчётах сигнала? Может требуется какая-та предварительная обработка сигнала? 2) Возможно ли выровнять число отсчётов на бит уже после слайсера? Мне кажется, так даже будет логичнее - выровнять длительность каждого бита.
-
Хотел поставить себе 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 спасибо за ответы!
-
Требование к целому числу отсчётов - это для выходных данных, которые подаются на интерполятор? Или это интерполятор выдаёт целое число отсчётов? В приведённых последних картинках, у меня на 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 отсчётами на бит.
-
1. Документации нет и не будет 2. В качестве донора - сорцы Линукса, у-бута и прочие вещи. 3. Мозговой штурм. Эксперименты. 4. Кое-что даже удаётся сделать по куцему даташиту (GPIO, PWM, I2S, LRADC) Но в основном - жёсткий секс с Линуксом 🐥
-
Всё ещё впереди! ))) Сделал детектор паттерна преамбулы и нахождение синхрослова. И выпарсил данные наконец-то и проверил их. Все три пакета правильные. Корона не жмёт? :)))
-
Пока не смотрел ИХ фильтра на 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 ...
-
Удалил повторяющиеся отсчёты из raw-файла. Теперь соседние отсчёты фазы различны, и мгновенная частота не возвращается к нулю несколько раз. Очевидно, для скорости 50 кбит/с было пересемплирование. И теперь на 1 бит приходится 12-13 отсчётов всегда: Насколько высок потенциал для нахождения мягких решений?
-
Скорость взятия отсчётов зависит программы, насколько быстро она может читать регистр. С учётом кольцевой буферизации, DMA и одинакового интервала взятия отсчётов - 20 машинных циклов 8051, больше, чем 1 300 000 отсчётов за 1 секунду - не получить.
-
Да. Возвраты к нулю происходят от того что иногда соседние отсчёты фазы одинаковы (на скорости 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 бит?
-
Прочитайте название темы. Причём тут замирания? Нужно получить битовый поток из сигнала модулятора. Про замирания - в других темах. Пока мне нужно оценить, насколько полезно может быть применение отсчётов мгновенной фазы для моих целей. Мои цели - отказаться от встроенного модема 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 обработанные отсчёты фазы (мгновенная частота) смотрятся веселее: снизу - отсчёты фазы:
-
Пока занят более приоритетными задачами.
-
🤣🤣🤣 Ну не успевает он отрисовать за время VBLANK, поэтому и видите полоску сверху (или снизу, если полярность синхронизации проинвертирована). Попробуйте в настройках TCON пересчитать времянки так, чтобы увеличить ширину VSYNC-пульса. Или грубо FPS в 2 раза меньше сделайте. 20 мс >> T vblank И да: сделайте двойную буферизацию и переключайте адрес отображения видеопамяти (переключать адрес надо по VSYNC или вообще в прерывании от TCON): пока вы будете смотреть на одну страницу, во второй процессор будет рисовать. И времени будет всяко-больше, до следующего обновления дисплея. P.S. У меня во всех приложениях работа с отображением графики строго синхронна с обновлением дисплея
-
Почитал ваши сообщения на другом форуме: https://www.radioscanner.ru/forum/topic42854.html Вы постоянно занимаетесь тем, что из мухи раздуваете слона. Одни заумные рассуждения и только. Практического толку от таких рассуждений - ноль. Как говорится, у одного хобби пытаться что-то делать. А у другого - гнуть пальцы и демонстрировать свою крутость.
-
Какие следующие шаги должны быть? Нужно засинхронизироваться и начать по выборкам определять биты. Сделал полифазный фильтр, работающий в сторону апсемплинга. Код брал на гитхабе. Вышла лажа: отсчёты делает некорректно. Попробовал ресемплинг в Audacity - довольно неплохо 4:1. Как теперь найти интервал взятия отсчётов и нужна ли энергия битов? Пробовал вручную найти интервал выборки - получается уход постоянно:
-
Проверил. Эта сумма квадратов всегда равна единице. Выкинул её. График без изменений. Облегчило конвеер вычислений. Почему-то сразу вспомнил основное тригонометрическое тождество...
-
Сделал замеры. На битовой скорости 625 кБит/c получается 2,19 отсчётов. Грубо - 2 отсчёта на символ. Ни о каких мягких решениях нельзя говорить при таком битрейте. Но для скоростей десятки килобит в секунду сгодится. Всё из-за ограниченной пропускной способности SPI: максимально работает на половине тактовой частоты кварца: 37.5/2 = 18.75 МГц. Дальше только усекать разрядность выборок и толкать в байт. ЕМНИП для мягких решений достаточно трёх бит, остальное лишнее. Попробовал ещё включить логарифмическую визуализацию - с ней красивше смотрится: Вверху - через квадратуры, внизу - через разность. И что там в первом GSM смотреть? Слишком много всего написано, и не факт что найду нужное. К тому же я не припомню, чтобы первый GSM решал вопросы скоростей выше 0,5 МБит/c
-
Соединил ВЧ входы двух устройств через аттенюатор -30 дБ. Мощность -10 дБм. Снял фазу сигнала. Результат ничем не отличается от сигнала, принятого с эфира. Потому что оба устройства находятся рядом. И всё-же КМК форма сигнала, найденная через квадратуры и раскрытую производную арктангенса лучше смотрится, чем производная с раскрытого арктангенса. Проще говоря, рисунок ниже - лучше (нет АМ и меньше заусенцев): И кстати, почему когда передаётся преамбула, видно на графике, что частота слегка подплющивается периодически? Ну тоесть она как бы слегка частотно-модулированная визуально. Выровнял чтения регистра фазы. Теперь отсчёты фазы бирутся через одинаковый временной интервал. Стало лучше. Но выбросы всёравно остались.
-
Сигнал принимаю по эфиру со второго трансивера Si4463. Модемы настроены одинаково. Модуляция, как я уже писал - пока выбрана 2FSK, битрейт 625 кбит/c. Si4463 разогнана немного: припаял кварц 37.5 МГц вместо шатного кварца30 МГц. Это позволило на 25% увеличить битрейт и увеличить скорость SPI до 15 МГц. До этого сделал стандартно обработку пакетов в дуплексном режиме. На два MJPEG кадра 160x240 + два потока сжатого звука хватает. Прикрутил коррекцию ошибок - длинный RS-кодек, исправляющий до 10...12.5% ошибок в пакете . Коррекция ошибок помогает когда сигнал сильно слабый (проверял). Чем слабже сигнал, тем больший % пакетов исправляется коррекцией. Вот статистика для выходной мощности 0,1 мВт (-10 дБм): из принятых 2160 пакетов - 602 пакета пришли битыми - они успешно исправлены, и 54 битых пакета с невозможностью исправить. ! - пакет пришёл без ошибок * - пакет с ошибками, успешно восстановлен ? - пакет исправить не удалось. перемещение по комнатам с приёмопередатчиком в руках.
-
Заработал нормально 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-бит с скругление с + на -.
-
Unwrap не получается сделать так, чтобы он правильно работал: он ползёт куда-то вверх, и не всегда срабатывает - оставляются переполнения. Может в MATLAB оно и работает превосходно, но Си-шный алгоритм даёт фигню мягко говоря... К тому же, если размотанная фаза будет постоянно ползти, то и 32 бит скоро может не хватить.
-
Задача решена. Нашёл синхро-слово после преамбулы, которое передаю (преамбула 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 кбит/с. Так что-ли? Мне пока интересно софтово это сделать. Уже вычислил. Нормированные, правда. Но в моём случае амплитуда не нужна.