|
Cortex-M7 кол-во циклов на инструкцию |
|
|
|
 |
Ответов
|
May 3 2017, 08:50
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Genadi Zawidowski @ May 3 2017, 00:09)  Есть код, в котором этот алгоритм применен? Да код там простейший: CODE #define DAC_FS 68000 //[Hz] желаемая частота квантования ЦАП (<=реальной) #define DAC_DIV (TimerAPBCLK(nTIM_dac, H) / DAC_FS) #define DAC_FS_REAL divCeil(TimerAPBCLK(nTIM_dac, H), DAC_DIV) //[Hz] реальная частота квантования ЦАП (>=DAC_FS) [Hz] #define DS_FACTOR 3 //показатель макс.даунсэмплинга #define DS_MAX ((1 << DS_FACTOR) - 1) //макс.даунсэмплинг (макс.возможное отношение частоты сэмплирования mp3-потока к DAC_FS_REAL) static u32 rsmplX; //текущая фаза ресэмплинга; целая часть - старшие DS_FACTOR бит static u32 rsmplFix; //отношение частоты сэмплирования mp3 к частоте DAC_FS_REAL; целая часть - старшие DS_FACTOR бит static u32 rsmplVar; //произведение rsmplFix и переменного коэфф.ресэмплинга, вычисляемого от уровня заполненности inbuf.ring; формат аналогичен rsmplFix static u16 rsmplBSiz; //кол-во пар (левый/правый) сэмплов в rsmplBuf static void ReSmpl() { CPU_SR_ALLOCATE(); uint i0, i1, n, n1 = rsmplBSiz; //n1 - число сэмплов во вх.буфере s16 *psr = &rsmplBuf[0]; //указатель поток вх.сэмплов (сэмплы хранятся парами 16-битных значений для левого/правого канала) while (1) { i1 = sbufW; //индекс записи в кольцевой буфер вых.сэмплов if ((int)(n = (i0 = sbufE) - i1 - 1) < 0) { n = ncell(smplBuf.data) - i1; if (!i0) n--; } //здесь n - число сэмплов ЦАП, которое можно записать в вых.буфер if (!n) { //нет места для записи в smplBuf.data if (afaza == AFAZA_BREAK) return; ENTR_CRT_SECTION(); if (afaza == AFAZA_PREBUF) { i0 = ibufR; if ((int)(n = ibufW - i0) < 0) n += sizeof(inbuf.ring); if (n >= prebufPorog || aoutOn == OTYP_MEM) { afaza = AFAZA_PLAY; EXIT_CRT_SECTION(); TaskChangePrio(PRIO_TASK_AOUT_LOW, PRIO_TASK_AOUT_HIGH); } else EXIT_CRT_SECTION(); } else EXIT_CRT_SECTION(); MboxPend(mboxOut, ms2tkt(20)); continue; } u32 *psw = &smplBuf.data[i1]; //указатель на формируемый поток вых.сэмплов u32 c, c0, c1, ca = rsmplX; do { //здесь собственно - сам цикл ресэмплинга входных отсчётов в выходные n1 -= c = (ca += rsmplVar) >> 32 - DS_FACTOR; psr += c * 2; ca -= c << 32 - DS_FACTOR; c = ca >> 16 - DS_FACTOR; c0 = (psr[2] * (s32)c + psr[0] * (s32)(B16 - c) >> 16) * mp3Volume; //здесь собственно вычисление очередного вых. сэмпла для левого канала (а может правого?  c1 = (psr[3] * (s32)c + psr[1] * (s32)(B16 - c) >> 16) * mp3Volume; //здесь для другого канала *psw++ = (c0 + B23 >> 8 & 0xFFF0) | (c1 + B23 >> 12 << 20); //объединяем и преобразуем в формат 2-канального ЦАП STM32F429 } while (--n && n1 > DS_MAX); rsmplX = ca; i1 = psw - &smplBuf.data[0]; if (i1 >= ncell(smplBuf.data)) i1 = 0; sbufW = i1; if (n1 <= DS_MAX) break; } rsmplBSiz = n1; memmove(&rsmplBuf[0], psr, n1 + 1 << 2); } DAC_FS - можно задать любым какое нравится и поддерживает ЦАП, но желательно близким к частоте вх.потока и если ниже частоты вх.потока, то не более чем в DS_MAX раз; rsmplFix - у меня вычисляется для каждого вх. MP3-фрейма - из него берётся samplerate этого фрейма и получаем значение фиксированного коэфф. ресэмплинга для данного MP3-фрейма; rsmplVar - вычисляется непрерывно - это произведение rsmplFix на коэфф. заполненности основного кольцевого буфера mp3-потока; за счёт этого выполняется согласование скоростей вх.потока (определяемого генератором передатчика) и вых. потока (определяемого тактовой ЦАП); зависимость коэфф. заполненности кольц.буфера - нелинейная. Цитата(Шаманъ @ May 3 2017, 09:01)  Более правильный/точный метод это задействовать таймер TIM2, но руки пока не еще дошли - надо кое-какие нюансы самого ASRC допилить  . Использую простой ФНЧ первого порядка. Его основная задача уменьшить джиттер, поскольку плавают измерения (получается 216048+-100 тактов, надо переходить на аппаратный замер таймером). Имхо - у SOF-фреймов от хоста тоже может быть джиттер. Так что аппаратным или не аппаратным таймером мерять - всё равно значения будут дёргаться - так как погрешность возникает не у Вас. Всё равно придётся усреднять или ФНЧ. Цитата(Шаманъ @ May 3 2017, 09:01)  Алгоритм очень простой - соедините отсчеты линиями, теперь у Вас есть значения сигнала в произвольной точки времени (что собственно для ASRC и нужно)  "Возня" с более сложными алгоритмами фактически сводится к более точной интерполяции сигнала между отсчетами. Кода нет, я этот вариант только покрутил в Матлабе и отказался, т.к. при моих соотношениях частоты дискретизации и сигнала (12кГц:3.5кГц) он дает очень много искажений. Приведённый мной код должен нормально работать при соотношениях вх./вых. частот сэмплирования (коэфф.ресэмплинга) в диапазоне менее: 0.5<K<2. Он конечно будет работать и за пределами этого диапазона, но тогда часть сэмплов будет просто выкидываться (не учитываться в вых.сигнале). Чтобы убрать этот недостаток надо по идее поток вх.сэмплов предварительно прогнать через ФНЧ (а для случая K<=0.5 - предварительно добавить сэмплов в поток так, чтобы стало K>0.5 и потом прогнать через ФНЧ). Но я уже не стал этим заморачиваться, так как и такое качество меня уже устроило
|
|
|
|
|
May 3 2017, 11:56
|
Знающий
   
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839

|
Цитата(jcxz @ May 3 2017, 11:50)  Имхо - у SOF-фреймов от хоста тоже может быть джиттер. Так что аппаратным или не аппаратным таймером мерять - всё равно значения будут дёргаться - так как погрешность возникает не у Вас. Всё равно придётся усреднять или ФНЧ. Да это понятно, но избавиться от дополнительного джиттера (связанного с вызовами прерываний) все же стоит. Переделал на таймер. Не очень удобно оно в STM32 сделано, ну да ладно. С ФНЧ с постоянной времени 0.2с получается теперь так:
В цифрах в среднем джиттер меньше где-то в 1.5..2раза и не зависит от того, что делает девайс - с таймером однозначно лучше. Теперь осталось прикрутить часть со стороны DSP процессора и потом устроить "наведение порядка". Эх, зря я не предусмотрел подачу MCLK на SAI интерфейс от DSP процессора, придется костыли изобретать  ...
|
|
|
|
|
May 3 2017, 13:03
|
Знающий
   
Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839

|
Цитата(jcxz @ May 3 2017, 15:44)  отдавать поток сэмплов как есть, А как отдать его через SAI интерфейс "как есть"? Я ведь его могу затактировать или со стороны DSP, или со стороны управляющего STM32. Оба клока асинхронные относительно клока USB. Придется сделать на STM32 что-то типа FLL, чтобы загнать частоту SAI (в этом случае он будет мастером) в допустимые пределы... В принципе можно и так, боюсь только джиттер у такого решение вылезет большой, скорее всего бОльший, чем если сразу сделать ASRC на STM32 ориентируясь на соотношение частот SAI/USB. Цитата а в DSP делать ресэмплинг на коэфф. равный произведению постоянной и переменной части; переменную часть вычислять от уровня заполненности буфера принимаемых DSP сэмплов; постоянная Вам известна. Тогда и мерить/усреднять ничего не надо - это всё будет делать кольцевой буфер принимаемых сэмплов в DSP. Через отслеживание буфера боюсь нужное качество не получу, или буфер сильно большой придется делать (сейчас дополнительная задержка не превышает 1..2 мс - это 12..24сэмплов).
|
|
|
|
|
May 3 2017, 13:44
|
Гуру
     
Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713

|
Цитата(Шаманъ @ May 3 2017, 15:03)  А как отдать его через SAI интерфейс "как есть"? Я ведь его могу затактировать или со стороны DSP, или со стороны управляющего STM32. Оба клока асинхронные относительно клока USB. Ну и пускай. Скорость SAI сделать такой, чтобы точно хватало для передачи потока при любом соотношении частот с небольшим запасом по скорости. Да, конечно, уровень загрузки кольцевого буфера в DSP будет не стоять, а болтаться у некоего значения - ничего страшного. Цитата(Шаманъ @ May 3 2017, 15:03)  Через отслеживание буфера боюсь нужное качество не получу, или буфер сильно большой придется делать (сейчас дополнительная задержка не превышает 1..2 мс - это 12..24сэмплов). Необходимый размер буфера будет зависеть от размера регулярных "биений" скорости потока сэмплов - надо, чтобы он был заведомо больше этих биений. У меня весь буфер разбит на 3 участка: A, B, C. Размерности участков например такие: A - от 0% до 20% заполненности; B - 20%...80%; C - 80%...100% заполненности (конкретные значения могут быть другие). Участок B - горизонтальный: при нахождении уровня заполненности в нём, переменная часть коэфф. ресэмплинга == 1. Участок A - линейно-наклонный: переменная часть коэфф. ресэмплинга изменяется по линейному закону от 1 до 1-D/100 при смещении указателя заполненности от 20% до 0%. Участок C - линейно-наклонный: переменная часть коэфф. ресэмплинга изменяется по линейному закону от 1 до 1+D/100 при смещении указателя заполненности от 80% до 100%. где D - максимальное значение (в %) переменной части коэфф. ресэмплинга (может быть любое значение, например 10%). Размер участка B выбирается таким, чтобы он полностью поглощал регулярные биения загрузки буфера. Это работает так: При старте вначале идёт пребуферизация (сэмплы только накапливаются в буфер, без выходного потока) до некоторого значения на участке B. Потом включается обычный рабочий режим ресэмплинга. В реале, если частоты генераторов источника и ЦАП идеально совпадают, то уровень заполненности устаканится на некотором значении - будет регулярно болтаться вокруг этого значения на суммарную величину всех джиттеров. Если частоты генераторов различаются в ту или иную сторону, то этот уровень загрузки будет постепенно смещаться в сторону участка A или C (тоже с биениями) и в конце-концов - залезет в A или C, где и устаканится на некотором значении (будет болтаться возле него), до тех пор, пока разница частот не изменится (например из-за влияния температур на генераторы) и тогда может поползти в обратную сторону. Вот примерно так это у меня и работает. Как плюс метода - он не требует никаких дополнительных измерений и устойчив к довольно большому и неравномерному джиттеру (у меня поток сэмплов приходит с TCP-сокета работающего поверх WiFi - поток болтается очень даже произвольно).
|
|
|
|
Сообщений в этой теме
Шаманъ Cortex-M7 кол-во циклов на инструкцию Apr 28 2017, 08:04 Obam В TechRefMan-е на M7 раздела "Instruction Tim... Apr 28 2017, 08:45 =SSN= Цитата(Шаманъ @ Apr 28 2017, 11:04) А ест... Apr 28 2017, 08:59 Шаманъ Цитата(Obam @ Apr 28 2017, 11:45) но есть... Apr 28 2017, 10:36 jcxz Цитата(Шаманъ @ Apr 28 2017, 12:36) Похож... Apr 28 2017, 10:41 Obam Цитата(Шаманъ @ Apr 28 2017, 14:36) Так д... Apr 28 2017, 11:00  jcxz Цитата(Obam @ Apr 28 2017, 13:00) Ну сами... Apr 28 2017, 11:46 Шаманъ Цитата(jcxz @ Apr 28 2017, 13:41) ...если... Apr 28 2017, 11:47 Obam Цитата(Шаманъ @ Apr 28 2017, 15:47) Я ж п... Apr 28 2017, 12:13 jcxz Цитата(Шаманъ @ Apr 28 2017, 13:47) В том... Apr 28 2017, 20:03  Obam Цитата(jcxz @ Apr 29 2017, 00:03) Везёт В... Apr 29 2017, 10:05   jcxz Цитата(Obam @ Apr 29 2017, 12:05) И кто ж... Apr 29 2017, 10:33   adnega Цитата(Obam @ Apr 29 2017, 13:05) И кто ж... Apr 29 2017, 10:34    jcxz Цитата(adnega @ Apr 29 2017, 12:34) В нек... Apr 29 2017, 10:39    Obam Цитата(adnega @ Apr 29 2017, 14:34) В нек... Apr 29 2017, 14:39     adnega Цитата(Obam @ Apr 29 2017, 17:39) А в как... Apr 29 2017, 16:47     jcxz Цитата(Obam @ Apr 29 2017, 16:39) А в как... Apr 29 2017, 20:30      Obam Цитата(jcxz @ Apr 30 2017, 00:30) Что за ... Apr 30 2017, 08:07       adnega Цитата(Obam @ Apr 30 2017, 11:07) а оказы... Apr 30 2017, 09:20 scifi Цитата(Шаманъ @ Apr 28 2017, 13:36) Похож... Apr 28 2017, 13:14 Шаманъ Цитата(scifi @ Apr 28 2017, 16:14) Разреш... Apr 28 2017, 13:41 romas2010 По хорошему надо бы ввести в архитектуру банки рег... Apr 28 2017, 14:51 jcxz Цитата(romas2010 @ Apr 28 2017, 16:51) По... Apr 28 2017, 15:51 Шаманъ Народ, а есть ли какие-нить вменяемые benchmarks п... Apr 28 2017, 17:06 ViKo Обычно было 2 bitband зоны - для переменных в ОЗУ ... Apr 30 2017, 08:39 jcxz Цитата(ViKo @ Apr 30 2017, 10:39) Обычно ... Apr 30 2017, 11:53 Obam Код кроме ядра некому исполнять (; и наличие возмо... Apr 30 2017, 11:36 Шаманъ Сваял ASRC, получилось примерно 4 такта на тап или... May 1 2017, 03:48 scifi Цитата(Шаманъ @ May 1 2017, 06:48) DWT по... May 1 2017, 07:12  Шаманъ Цитата(scifi @ May 1 2017, 10:12) Если по... May 1 2017, 14:08 ig_z QUOTE (Шаманъ @ May 1 2017, 06:48) Сваял ... May 1 2017, 15:08 Genadi Zawidowski У меня перенос части кода в itcm дал устойчивый пр... May 1 2017, 16:51 Шаманъ Цитата(ig_z @ May 1 2017, 18:08) А зачем ... May 1 2017, 19:02 ig_z QUOTE (Genadi Zawidowski @ May 1 2017, 19... May 1 2017, 20:00 KnightIgor Цитата(ig_z @ May 1 2017, 21:00) Это коне... May 2 2017, 13:21 Genadi Zawidowski ЦитатаПоэтому, если у вас есть пример, как воспрои... May 1 2017, 20:26 jcxz Цитата(Genadi Zawidowski @ May 1 2017, 22... May 2 2017, 12:29  Шаманъ Цитата(jcxz @ May 2 2017, 15:29) Как я по... May 2 2017, 12:45   jcxz Цитата(Шаманъ @ May 2 2017, 14:45) DSP пр... May 2 2017, 13:44    Шаманъ Цитата(jcxz @ May 2 2017, 16:44) Так ведь... May 3 2017, 07:01 Шаманъ Цитата(ig_z @ May 1 2017, 23:00) Я постоя... May 2 2017, 12:07 Genadi Zawidowski Можно ли наплевать на спектральные "прострелы... May 3 2017, 07:42 Шаманъ Цитата(Genadi Zawidowski @ May 3 2017, 10... May 3 2017, 08:19 Шаманъ Цитата(Genadi Zawidowski @ May 3 2017, 10... May 3 2017, 09:08 Шаманъ Цитата(jcxz @ May 3 2017, 16:44) Это рабо... May 3 2017, 16:12 jcxz Цитата(Шаманъ @ May 3 2017, 18:12) А поче... May 4 2017, 08:27  Шаманъ Цитата(jcxz @ May 4 2017, 11:27) А зачем ... May 4 2017, 14:03 Шаманъ Ну вот, палки поборол тоже Как и предполагал прич... May 5 2017, 09:47
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|