Ответ 1
Простейшей схемой модуляции будет амплитудная модуляция (технически для цифровой сферы это называется Amplitude Shift Keying). Возьмите фиксированную частоту (допустим, 10 кГц), свою "несущую волну" и используйте биты в своих двоичных данных, чтобы включить и выключить ее. Если скорость передачи данных составляет 10 бит в секунду, вы включаете и выключаете сигнал 10 кГц с такой скоростью. Демодуляция будет (необязательным) фильтром 10 кГц с последующим сравнением с порогом. Это довольно простая схема для реализации. Как правило, чем выше частота сигнала и ваша доступная полоса пропускания, тем быстрее вы можете включать и выключать этот сигнал.
Очень круто/забавное приложение здесь должно было бы кодировать/декодировать как код Морзе и видеть, как быстро вы можете пойти.
FSK, сдвиг между двумя частотами более эффективен в полосе пропускания и более устойчив к шуму, но сделает демодулятор более сложным, поскольку вам нужно различать две частоты.
Расширенная схема модуляции, такая как Phase Shift Keying, хороша в получении максимальной битовой скорости для заданной полосы пропускания и соотношения сигнал/шум, но они сложнее реализовать. Аналоговые телефонные модемы, необходимые для работы с определенной пропускной способностью (например, всего 3 кГц) и ограничениями по шуму. Если вам нужно получить максимально возможную скорость передачи данных с учетом ограничений пропускной способности и шума, то это путь.
Для реальных образцов кода расширенных схем модуляции я бы исследовал записи приложений от поставщиков DSP (например, TI и Analog Devices), поскольку они были распространенными приложениями для DSP.
Внедрение модемного модема PI/4 Shift D-QPSK с использованием TMS320C50
Модуляция QPSK демистифицирована
V.34 Внедрение передатчика и приемника на DSP TMS320C50
Другим очень простым и не очень эффективным методом является использование DTMF. Это тональные сигналы, генерируемые клавиатурами телефонов, где каждый символ представляет собой комбинацию двух частот. Если вы Google, вы найдете много исходного кода. В зависимости от вашего приложения/требований это может быть простым решением.
Давайте погрузиться в некоторые детали реализации простой схемы, что-то вроде кода Морзе, о котором я упоминал ранее. Мы можем использовать "точку" для "0" и "тире" для 1. Преимущество такой же схемы, как и морская схема, заключается в том, что она также решает проблему кадрирования, поскольку вы можете повторно синхронизировать свою выборку после каждого пространства. Для простоты позвольте выбрать частоту "несущей волны" на частоте 11 кГц, и предположим, что ваш волновой выход равен 44 кГц, 16 бит, моно. Мы также будем использовать прямоугольную волну, которая создаст гармоники, но нам все равно. Если 11 кГц превышает частоту вашего микрофона, тогда просто разделите все частоты на 2 например, мы выберем некоторый произвольный уровень 10000, и поэтому наша форма волны "on" будет выглядеть так:
{10000, 10000, 0, 0, 10000, 10000, 0, 0, 10000, 0, 0, ...} // 4 samples = 11Khz period
а наш "выключенный" сигнал - это всего лишь нули. Я оставляю кодировку этой части как excersize для читателя.
И у нас есть что-то вроде:
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 кГц. Это улучшит работу в шумном окружении. Фильтры FIR довольно просты, и есть несколько сетевых апплетов, которые будут создавать фильтр для вас.
- Порог сигнала. Каждое значение выше 1/2 максимальной амплитуды составляет 1, каждое значение ниже 0. Это предполагает, что вы пробовали весь сигнал. Если это в реальном времени, вы либо выбираете фиксированный порог, либо выполняете какое-то автоматическое регулирование усиления, когда вы отслеживаете максимальный уровень сигнала в течение некоторого времени.
- Сканировать начало точки или тире. Вероятно, вы захотите увидеть хотя бы определенное число в один из десяти пунктов, чтобы считать образцы точками. Затем продолжайте сканирование, чтобы убедиться, что это тире. Не ожидайте идеального сигнала - вы увидите несколько 0 в середине вашего 1 и несколько 1 в середине ваших 0. Если есть небольшой шум, то дифференцирование периодов "on" из периодов "off" должно быть довольно простым.
- Затем переверните описанный выше процесс. Если вы видите, что тире нажмите 1 бит в буфер, если точка толкает ноль.