komah 4 10 марта Опубликовано 10 марта · Жалоба 7 часов назад, repstosw сказал: Я не знаю внутренней структуры демодулятора Si4463. Но предполагаю, что он квадратурный. И я уже писал что модуляция 4GFSK. И мне нужен выходной поток бит, вытащенных из отсчётов квадратурного демодулятора. Что не ясно? Задача внезапно заиграла новыми красками. Так у Вас же частотный детектор уже есть в микросхеме. Вы с ее помощью хотите что-то другое принимать? При чем здесь тогда 4GFSK. Или нужен битовый поток с детектора без пакетной синхронизации? И можно пояснить, почему 7 бит? И та запись, которая на картинке, это все-таки вход частотного детектора или выход? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
komah 4 10 марта Опубликовано 10 марта · Жалоба 7 часов назад, repstosw сказал: Дальнейшие изыскания сводятся к выбору жесткого интервала между опросами SFR-регистра фазы: по таймеру или привязка к растактовкам ядра 8051.. Ну это к тактовой синхронизации не относится. Там интервал между взятием отсчетов должен быть привязан к длительности символа. И в зависимости от ошибки синхронизации корректироваться как длительность интервала, так и момент взятия. Если все-таки предполагается, что считываются значения фазы отсчетов, то для частотного детектора интервал между ними должен быть постоянным и без всяких пропусков. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
komah 4 10 марта Опубликовано 10 марта · Жалоба 8 часов назад, repstosw сказал: Каким образом без ЦОС вы получите битовый поток с отсчётов ЧФД, который ещё и подвергается коррекции ошибок LDPC? Посмотрел другие темы, пазл сложился. Нужно получить мягкие решения с выхода демодулятора для декодера LDPC. И есть доступ к внутреннему регистру, хранящему значение фазы текущего отсчета. 1. При считывании фазу рвать нельзя. Можно пропускать отсчеты, но равномерно. И нужно понимать, сколько отсчетов на символ будет в итоге. 2. Unwrap - это не так просто, как кажется. Предположим, один отсчет имеет значение 32, следующий -32. Чему равна дельта? 3. Декодеру LDPC мягкие решения не обязательны. В Вашей теме я про bit-flipping отвечал. Либо их можно просто сделать из жестких ). Кстати, если есть значение RSSI, можно грубо ОСШ оценить. Это все для декодера полезно. Короче, если трансивер уже умеет ЧМ демодулировать, этого вполне достаточно. 1 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 10 марта Опубликовано 10 марта · Жалоба 23 minutes ago, komah said: Посмотрел другие темы, пазл сложился. Нужно получить мягкие решения с выхода демодулятора для декодера LDPC. И есть доступ к внутреннему регистру, хранящему значение фазы текущего отсчета. Да. Всё верно. Есть регистр PHASE_OUT, который хранит отсчёты фазы в знаковом 7-битном формате. Причём регистр доступен только асинхронно - я не нашёл никаких дополнительных сведений о синхронизации для забора данных с него. Возможно, это даже не демодулятор, а АЦП после смесителя. Серия инструкций MOV для чтения этого регистра ядром 8051 даёт до 4-х одинаковых подряд значений. На практике всё грустно: удалось передавать непрерывным потоком эти данные управляющему процессору со скоростью до 128 отсчётов за 0.11 мс. 27 minutes ago, komah said: 2. Unwrap - это не так просто, как кажется. Предположим, один отсчет имеет значение 32, следующий -32. Чему равна дельта? Я уже мозг взорвал этими разрывами фазы, но так ничего толкового не увидел. Проще говоря, как из асинхронно взятых отсчётов мгновенных значений фазы вытащить биты? Для упрощения перешёл пока на 2FSK. Пока делал так: отсчёты от 0 до +63 - это мягкие решения от 0 до 1. Тоже и отрицательный диапазон: от 0 до -64 - это мягкие 0..1. Но на графике лажа получается: я не вижу преамбулы и синхрослова. Причём отбеливания всякие пока выключил. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rloc 57 10 марта Опубликовано 10 марта · Жалоба В 08.03.2024 в 11:55, repstosw сказал: Одно непонятно - как взять производную.. По идее - это разница между соседними отсчётами. Но не сшивается в точках переполнения. Интересно, как они выполнили условие непрерывности? Мгновенную частоту можно считать не как разность фаз, а как фазу между двумя квадратурами в терминах Matlab: freq = atan2(x1*conj(x2))*fclk/2/pi или, что тоже самое freq = angle(x1*conj(x2))*fclk/2/pi где x1, x2 - соседние комплексные квадратуры, conj - функция комплексного сопряжения, fclk - частота следования квадратур. Способ несколько приближенный, с учетом того, что искомая частота freq много меньше fclk. В противном случае необходима дополнительная компенсация на sinc (sin(x)/x) Прошу прощения, если уже упоминали, беглым взглядом не нашел. И стоит признать, указанный способ нахождения мгновенной частоты далеко не единственный. Тут можно найти еще несколько: https://dsp.stackexchange.com/questions/24487/calculate-and-interpret-the-instantaneous-frequency Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 10 марта Опубликовано 10 марта · Жалоба 2 minutes ago, rloc said: Мгновенную частоту можно считать не как разность фаз, а как фазу между двумя квадратурами в терминах Matlab: Нет доступа к квадратурам. Есть только фаза со знаком в виде дискретных значений [-64.. + 63]. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
petrov 7 10 марта Опубликовано 10 марта · Жалоба repstosw Как это не нужны? Каким образом без ЦОС вы получите битовый поток с отсчётов ЧФД, который ещё и подвергается коррекции ошибок LDPC? Таким же образом как и в Si4463, процессоры и программизм не имеют никакого отношения к ЦОС и цифровой схемотехнике. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rloc 57 10 марта Опубликовано 10 марта · Жалоба 2 минуты назад, repstosw сказал: Нет доступа к квадратурам Вычислите ) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
komah 4 10 марта Опубликовано 10 марта · Жалоба 48 минут назад, repstosw сказал: Проще говоря, как из асинхронно взятых отсчётов мгновенных значений фазы вытащить биты? Из взятых асинхронно - только если есть гарантия, что количество полученных отсчетов на символ всегда одинаковое. Я бы с мягкими решениями просто не заморачивался. Не нужны они они для dmr. Если полностью приемник реализовать предстоит, то демодулятор там - 3% работы. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
komah 4 10 марта Опубликовано 10 марта (изменено) · Жалоба 2 часа назад, repstosw сказал: Проще говоря, как из асинхронно взятых отсчётов мгновенных значений фазы вытащить биты? 1. Считываем значения фазы из регистра с фиксированной частотой. Чем чаще - тем лучше. Если набег фазы между считанными значениями близок к PI/2 (32), отказываемся от этой затеи. При известной символьной скорости считаем, сколько отсчетов приходится на символ. 2. Для считанных значений делаем unwrap, хотя бы как в примере, который Вы приводили. Находим разность между соседними отсчетами. При наличии шумов в сигнале, на выходе в любом случае будут выбросы из-за перескока фазы на 2PI. 3. Фильтруем полученный сигнал. Лучше согласованным фильтром. Смотрим на результат. На графике должны быть видны явно различимые импульсы. Из-за межсимвольной интерференции их амплитуда будет непостоянной, но четыре интервала значений должны быть различимы. Если нет - отказываемся... 4. Теперь самое интересное. Тактовая синхронизация. Для принятия решения о значении символа нужно выбрать отсчет, находящийся на пике импульса. Если отсчетов на символ много и это целое число - существуют более-менее простые алгоритмы. В противном случае нужна интерполяция. Можно совместить с фильтрацией из предыдущего пункта. Схема называется pfb - polyphase filter bank. В принципе, есть готовые решения под разное железо, но за ними еще куча всего обычно тянется. 5. Выдаем значения отсчетов с выхода тактового синхронизатора как мягкие решения. Если нужны решения по битам, а не по символам - строим таблицу и по ней перекодируем. Изменено 10 марта пользователем komah Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 10 марта Опубликовано 10 марта (изменено) · Жалоба Задача решена. Нашёл синхро-слово после преамбулы, которое передаю (преамбула 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); } 1 hour ago, komah said: 4. Теперь самое интересное. Тактовая синхронизация. Для принятия решения о значении символа нужно выбрать отсчет, находящийся на пике импульса. Если отсчетов на символ много и это целое число - существуют более-менее простые алгоритмы. В противном случае нужна интерполяция. Можно совместить с фильтрацией из предыдущего пункта. Схема называется pfb - polyphase filter bank. В принципе, есть готовые решения под разное железо, но за ними еще куча всего обычно тянется. Пока есть небольшой джиттер. Я могу позволить себе до 8 отсчётов на символ максимум при символьной скорости до 625 кбит/с. 2 hours ago, petrov said: Таким же образом как и в Si4463, процессоры и программизм не имеют никакого отношения к ЦОС и цифровой схемотехнике. Так что-ли? Мне пока интересно софтово это сделать. 2 hours ago, rloc said: Вычислите ) Уже вычислил. Нормированные, правда. Но в моём случае амплитуда не нужна. Изменено 10 марта пользователем repstosw Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
komah 4 10 марта Опубликовано 10 марта · Жалоба 18 минут назад, repstosw сказал: По мгновенным отсчётам фазы, вначеле построил I- и Q- сигналы. Это лишнее, unwrap достаточно. Сейчас вы двойную работу делаете, а формула без арктангенса все равно хуже, чем 3 часа назад, rloc сказал: angle(x1*conj(x2)) Выход частотного детектора нужно поделить на (h * M_PI), где h - индекс модуляции. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
repstosw 18 10 марта Опубликовано 10 марта · Жалоба 1 hour ago, komah said: Это лишнее, unwrap достаточно. Сейчас вы двойную работу делаете, а формула без арктангенса все равно хуже, чем Unwrap не получается сделать так, чтобы он правильно работал: он ползёт куда-то вверх, и не всегда срабатывает - оставляются переполнения. Может в MATLAB оно и работает превосходно, но Си-шный алгоритм даёт фигню мягко говоря... К тому же, если размотанная фаза будет постоянно ползти, то и 32 бит скоро может не хватить. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
petrov 7 10 марта Опубликовано 10 марта · Жалоба repstosw Ещё много открытий будет, если делать как следует, даже в этом примитивном демодулятре это лишь небольшая часть, но в итоге и он не годится. Уже писал, что стоит поучиться на чужом опыте, первый GSM близок, можно посмотреть, какие задачи там люди решали. Интересно - это здорово, но быстрее делать то, что действительно нужно для настоящего решения задачи, без помех программизма, копания в ненужных вещах. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
rloc 57 10 марта Опубликовано 10 марта · Жалоба 2 часа назад, repstosw сказал: Уже вычислил. Формула f3(t) в приведенной выше ссылке, всего 5 вариантов, включая atan2, который считается ничуть не медленнее пары операций перемножения при соответствующей оптимизации (легко проверить в Matlab). 1 час назад, komah сказал: Выход частотного детектора нужно поделить на (h * M_PI), где h - индекс модуляции. Поправил в исходном сообщении нормировку. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться