Простейшей схемой модуляции будет амплитудная модуляция (технически для цифровой области это будет называться Amplitude Shift Keying). Возьмите фиксированную частоту (скажем, 10 кГц), вашу "несущую", и используйте биты в ваших двоичных данных, чтобы включить и выключить ее. Если ваша скорость передачи данных составляет 10 бит в секунду, вы будете включать и выключать сигнал 10 кГц с этой скоростью. Демодуляция будет (необязательным) фильтром 10 кГц с последующим сравнением с пороговым значением. Это довольно простая схема для реализации. Как правило, чем выше частота сигнала и доступная полоса пропускания, тем быстрее вы можете включать и выключать этот сигнал.
Очень классное / забавное приложение здесь - кодировать / декодировать как азбуку Морзе и видеть, как быстро вы можете идти.
FSK, переключение между двумя частотами более эффективно в полосе пропускания и более устойчиво к шуму, но сделает демодулятор более сложным, поскольку вам нужно различать две частоты.
Усовершенствованная схема модуляции, такая как Фазовая манипуляция хороша для получения максимальной скорости передачи данных для данной полосы пропускания и отношения сигнал / шум, но их сложнее реализовать. Аналоговые телефонные модемы должны были работать с определенной полосой пропускания (например, всего 3 кГц) и шумовыми ограничениями. Если вам нужно получить максимально возможную скорость передачи данных с учетом полосы пропускания и ограничений по шуму, то это путь.
Для фактических примеров кода усовершенствованных схем модуляции я бы изучил замечания по применению от поставщиков DSP (таких как TI и Analog Devices ), поскольку они были общими приложениями для DSP.
Внедрение модема D-QPSK PI / 4 Shift с использованием TMS320C50
QPSK модуляция демистифицирована
Внедрение передатчика и приемника VSP на TMS320C50 DSP
Еще один очень простой и не очень эффективный метод - использовать DTMF. Это тоны, генерируемые телефонными клавиатурами, где каждый символ представляет собой комбинацию двух частот. Если вы Google, вы найдете много исходного кода. В зависимости от вашего приложения / требований это может быть простое решение.
Давайте углубимся в некоторые простые детали реализации схемы, что-то вроде кода Морзе, который я упоминал ранее. Мы можем использовать «точку» для 0 и «тире» для 1. Преимущество схемы типа Морзе состоит в том, что она также решает проблему кадрирования, поскольку вы можете ресинхронизировать свою выборку после каждого пробела. Для простоты давайте выберем частоту «Несущая волна». на 11 кГц и предположим, что ваш выходной сигнал составляет 44 кГц, 16 бит, моно. Мы также будем использовать прямоугольную волну, которая будет создавать гармоники, но нам все равно. Если 11 кГц выше частотной характеристики вашего микрофона, то просто разделите все частоты на 2 Например, мы выберем некоторый произвольный уровень 10000, и поэтому наш сигнал «вкл» выглядит следующим образом:
{10000, 10000, 0, 0, 10000, 10000, 0, 0, 10000, 0, 0, ...} // 4 samples = 11Khz period
и наша "выключенная" форма волны - это всего лишь нули. Я оставляю кодирование этой части в качестве отрывка для читателя.
И так у нас есть что-то вроде:
const int dot_samples = 400; // ~10ms - speed up later
const int space_samples = 400; // ~10ms
const int dash_samples = 800; // ~20ms
void encode( uint8_t* source, int length, int16_t* target ) // assumes enough room in target
{
for(int i=0; i<length; i++)
{
for(int j=0; j<8; j++)
{
if((source[i]>>j) & 1) // If data bit is 1 we'll encode a dot
{
generate_on(&target, dash_samples); // Generate ON wave for n samples and update target ptr
}
else // otherwise a dash
{
generate_on(&target, dot_samples); // Generate ON wave for n samples and update target ptr
}
generate_off(&target, space_samples); // Generate zeros
}
}
}
Декодер немного сложнее, но вот схема:
- Опционально полосовой фильтр дискретизированного сигнала около 11 кГц. Это улучшит производительность в шумной обстановке. КИХ-фильтры довольно просты, и есть несколько онлайн-апплетов, которые сгенерируют этот фильтр для вас.
- Порог сигнала. Каждое значение выше 1/2 максимальной амплитуды равно 1, каждое значение ниже равно 0. Это предполагает, что вы сэмплировали весь сигнал. Если это в режиме реального времени, вы либо выбираете фиксированный порог, либо выполняете какую-то автоматическую регулировку усиления, где вы отслеживаете максимальный уровень сигнала в течение некоторого времени.
- Сканирование для начала точки или тире.Вы, вероятно, хотите увидеть хотя бы определенное число единиц в периоде точек, чтобы считать выборки точкой.Затем продолжайте сканирование, чтобы увидеть, если это тире.Не ожидайте идеального сигнала - вы увидите несколько 0 в середине ваших 1 и несколько 1 в середине ваших 0.Если шумов мало, то отличить периоды «включения» от периодов «отключения» должно быть довольно просто.Если вы видите тире, нажмите 1 бит в буфере, если точка нажмите ноль.