Комментарии 71
Все это конечно замечательно. НО зачем?
Цена, размер корпуса да и потребление в этом режиме 32-х битных контроллеров практически те же что и на ATMega.
Почему все так упорно пользуются древними ATMega?
Ну а те кому перестанет хватать мощности ATMega, с полученным багажом знаний уже можно переходить на STM32 и иже с ними.
Сколько всего надо прописать в исходник чтоб заставить хотя бы помигать светодиодом на каком-нибудь STM32?
Немного… (инициализация шаблонно). Если через напрямую в стиле "записать в порт" то практически столько же как на AT DDRD |= _BV(PD0); PORTD &= ~_BV(PD0);
(что не очень хороший стиль. ибо код не переносим может оказаться)
За то проблемы "остается немного времени на анимацию на дисплее" не беспокоят.
#define DBG_LED_PIN GPIO_Pin_13
#define DBG_LED_PORT GPIOC
.....
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
GPIO_InitStructure.GPIO_Pin = DBG_LED_PIN; GPIO_Init(DBG_LED_PORT, &GPIO_InitStructure);
.....
//GPIO_SetBits(DBG_LED_PORT, DBG_LED_PIN); GPIO_ResetBits(DBG_LED_PORT, DBG_LED_PIN);
if ( flip ) {
DBG_LED_PORT->BSRR = DBG_LED_PIN;
} else {
DBG_LED_PORT->BRR = DBG_LED_PIN;
}
И да. "Наверно, с них начинает почти любой embedded разработчик." не совсем правильное утверждение. Если, конечно, под "embedded разработчик" не понимать "я тут светодиодом помигал".
Документация от STM ничем не сложнее чем от Atmel.
Это шаблонный код, кочующий из проект в проект. И не так что бы сложный для понимания.
Если не интересует потребление, то можно вообще все модули включить.
Чем мне не нравится Arduino как концепция… Кто то дернул чью то библиотеку (зачастую корявую и на оптимизированную) и все. Эмбедет разработчик в резюме.
2) Скачать на выбор одну из IDE, которую этот CubeMX умеет.
3) В CubeMX установить (в один клик почти) поддержку желаемого семейства камней.
4) В красивом и безобразно простом GUI интерфейсе выставить какие пины используем.
5) Настроить тактирование (или забить на это, всёравно оно будет настроено), кем и откуда, ну и ввести частоту — куб всё сам сделает
6) Нажать кнопочку Generate
7) Откроется IDE, в которой в цикл while(1) написать что-то типа
HAL_GPIO_TogglePin(MYLED_Port, MYLED_Pin);
HAL_Delay(500);
8) Настроить программатор (тут от IDE зависит) — тоже пара кликов.
9) Нажать кнопочку «Собери мне это и запусти»
10) Насладиться мигающим светодиодом.
С STM32 и их i2c я крупный гемор поимел только один раз — на F103-ей какая-то версия куба ставила включение тактирования в конец инициализации, а не в начало, благодаря чему вылез глюк вида «дотронулся щупом/пальцем при включении — работает, не дотронулся — линия притянута к нулю и не работает».
Вариант «быстренько накидать готовых либ» я не люблю — там бывает очень много не просто индусского кода, а индусского говнокода. Да и когда я мучал множество i2c барахла, то как правило портирование ардуиновской библиотеки особо много времени не занимало.
Из вики:
Wavetable synthesis is fundamentally based on periodic reproduction of an arbitrary, single-cycle waveform.
По сути, тут периодическая функция — это не совсем функция, а как раз таблица значений амплитуды, 256 значений на период. А еще она работает не сама по себе, а в паре с функцией громкости от времени, которая тоже яавляется таблицей значений.
Возможно, существует более подходящий термин, но я его не знаю.
О чо вспомнил!
Весьма кстати интересный альбом с точки зрения минимализма.
Не чиптюн и прочие марио.
Жаль, что автор перестал продавать ассемблированый листинг с албомом и бинарник прошивки я так и не нашел
А то я хотел сделать его альбом в виде кирпича из эпоксидки с солнечной батарей, шоб жило веками. =)
z80.i-demo.pl
shiru.untergrund.net/1bit
randomflux.info/1bit
Для подавления щелчков делал такое простое решение: в момент выключения сэмпла запоминаем последнее выходное значение в переменную, которую добавляем к выводу, как ещё один канал, и плавно приводим её к 0 за короткое время. Если выход стерео, надо по переменной для каждого канала, а для моно хватит и одной на все каналы. То есть не фейдим продолжающий звучать сэмпл по честному (нужны умножения и больше каналов), а как бы компенсируем смещение нулевой амплитуды (нужно условие и декремент).
Решение со щелчками на поверхности, я его даже реализовывал, но оно все-таки просаживало производительность. В какой-то момент я делал рефакторинг кода и оно мешало, убрал. Обратно запиливать не стал. В планах все-таки попробовать плавно уменьшать громкость перед следующей нотой, но там пока не очень очевидно как это сделать хорошо.
По поводу PWM — да, проблема есть. Но в коде именно за вывод звука отвечает драйвер (каталог microsound/devices), можно что-то другое подключить. Covox, например, как советуют ниже.
Следите за фазой на стыке нот
Если посмотреть на существующие проекты, то они бывают нескольких типов:
вы забыли (сомневаюсь, что не знали) COVOX
Использую одну таблицу. Но можно сделать и несколько с той же производительностью. Когда начинает играть следующая нота, то вызывается функция инструмента и там можно выбрать необходимый массив в зависимости от заданой ноты.
Интерполяцию значений между семплами можно включить (директива INTERPOLATE_WAVE), но производительность падает. Решил просто использовать более длинную таблицу в 256 значений, а интерполяцию провести перед помещением данных в таблицу.
Проект на гитхабе, можете попробовать померять.
Укажите 3 канала вместо 5 и можно включить интерполяцию. Или использовать Arduino на 16МГц как самый простой вариант.
Как мне кажется, смысла хранить по таблице для каждой ноты нет. Можно попробовать хранить по таблице на октаву. В каждой следующей уменьшать количество гармоник вдвое путем выбрасывания половины сэмплов а потом интерполировать обратно до 256 сэмплов. Это как самый простой вариант.
Спектрумом повеяло:)
Одну мелодию, там где много инструментов, я брал из своего старого проекта. Помню, что накидал данные в csv (строки — такты, столбцы — команды, подобно трекерной музыке) и потом перегнал в команды простым самописным конвертором. Конвертор уже где-то потерялся, но его не особо сложно написать заново.
Вторую мелодию позаимствовал из проэкта музкальной шкатулки, в ссылках есть. Опять же, наколеночный конвертор, показывать стыдно.
Коротенькие уведомления писал руками и тестировал в wavepot.
Писать конвертор из midi нет желания и вряд ли получится. Слишком специфические инструменты, ограничение на количество каналов и дискретизацию по тактам. Я думаю, что проще из трекерной музыки (например mod) конвертировать, но и там будет специфика.
За статью спасибо.
Пытался делать нечто подобное, но без ШИМ-а аппаратного, чтобы не было привязки к ногам МК, упирается всё конечно в производительность.
На счет занимать МК ещё другими задачами — необязательно, особенно, если делать на Тиньках, можно считать данное решение как «музыкальный сопроцессор», синтезатор. :)
Давно морочюсь идеей, сделать проигрыватель для винила из оптической мышки. В режиме сканера декодить изображение и получать из него звук. Куда копать?
— MCU: ATmega AVR
— Fclk: 16 MHz
— Flash: 8kB
— SRAM: 1kB
— 2 x 8-bit counter/PWM
— 1 x 16-bit counter
Specifications for player routine:
— 4 channel 31 samples modules support
— volume setting 0-64 for each channel
— 2 stereo channels 8-bit PWM output
— software linear interpolation
— selectable output samplerate up to 48kHz
— most used effect commands supported
The basic idea was to create an all-in-one implementation
without use of external components. On-board PWM's are used
as DAC's, the module is kept in Program Flash.
Tha player is written in pure Assembler.
The current release includes conditional compilation
for ATmega16 and ATmega128 (those author has in presence),
but is also designed for very easy compilation for any other ATmega type.
Also, there is a technological clearance for use of external memory,
RS232 interface for communicational purposes etc.
The schematics for this project is very simple. You just power the chip, supply the 16MHz clock to it and have LEFT and RIGHT audio from 8-PWM's. All specific pin numbers depend on chip, that you selected.
Интересный проект, хотя мне не очень понятно как его можно использовать. Слишком уж сложно заставить микроконтроллер делать что-то еще помимо воспроизведения музыки.
К тому же, формат MOD слишком тяжелый для маленьких микроконтроллеров, хоть и намного более универсальный.
А вот если бы его на Arduino портировать, то могло бы быть вполне годно. Там и 32кб флеша и 16МГц кварц из коробки.
Интересно, но тут задачи совсем другие.
В том проекте задача эмулировать чип с определенными характеристиками и для этого выделяются отдельные чипы.
Я же хотел иметь возможность добавить звук в существующие проекты без существенного изменения схемы. А качество звука и количество каналов настраивать по остаточному принципу, в зависимости от того, сколько ресурсов останется.
А такой вопрос в чем проблема ATTiny? Ведь мы всё равно умножаем на число меньше 1 и затухание можно будет релиозовать путем вычитания сдвинутого регистром семпла.
Я не уверен, что правильно понял вопрос. Скорее всего, вы имеете в виду что-то типа:
outSample = instrumentSample — (instrumentSample >> n);
Так не получится, так как:
- При сдвиге вправо значение уменьшается в 2 раза, а мы можем хотеть иметь громкость, например, 87%.
- Если упростить, то один сдвиг соответствует умножению на число, у которого только один бит равен 1, а остальные 0. Если нужно иметь возможность вычислять сэмпл для любого значения громкости, то надо будет делать до 8 сдвигов и мы получим то же умножение, только медленное.
- И вообще, в AVR нет операции сдвига на произвольное количество битов. Можно только на 1 бит влево или на 1 бит вправо.
- Запоминать уменьшеное значение семпла для уменьшения его позже тоже не получится. Wave table находится в програмной памяти и доступна только для чтения. И ее нужно было бы пересчитывать всю. И хранить отдельно для каждого канала.
1.Громкость в 87% примерно равна 1 — 1/8 то есть 3 сдвига, да я правда тут не подумал над тем если у нас число будет меньше чем 1/8.
2.На счет 8 сдвигов как по мне слишком много уже при 4 сдвигах достигается точность в 6,25%, а так как число 8 битное больше делать думаю не будет иметь смысла ну 5 сдвигов ну 3,125%.
3.На счет этого не знал.
А так очень классная статья!!!
Генерация звука на микроконтроллерах AVR методом волновых таблиц с поддержкой полифонии