Cách giải điều chế tín hiệu AFSK trong phần mềm


14

Tôi đang cố gắng truyền dữ liệu nhị phân từ thiết bị này sang thiết bị khác qua kênh âm thanh (loa / mic). Tôi sử dụng AFSK (Khóa dịch chuyển tần số âm thanh) như trong Radio Packet, với và hai tần số và . Tôi đã chơi xung quanh một chút trong Ruby và cách thực hiện đầu tiên của tôi chỉ đơn giản là bắt chước một bộ giải mã không liên tục cổ điển, hoạt động tốt, cho đến nay.1200 Baudfmmộtrk= =1200 HzfSpmộtce= =2200 Hz

Vấn đề là, tôi đang cố gắng chuyển cái này sang nền tảng di động, nơi hiệu suất là một mối quan tâm và giải pháp hiện tại của tôi quá chậm. Tôi đã tìm thấy nhiều cách để giải điều chế AFSK trong phần mềm:

  • Trượt DFT (FFT)
  • Bộ lọc trượt Gortzel
  • Giai đoạn khóa vòng
  • Không qua

Con đường để đi là gì? Có quá nhiều lựa chọn để lựa chọn. Tôi chắc chắn có nhiều lựa chọn hơn có sẵn. Có lẽ còn tồn tại những giải pháp tốt hơn những giải pháp tôi nêu ở trên? Có ai đó thậm chí có một ví dụ mã cho tôi? Tôi quan tâm đến

  • Hiệu suất (nên chạy trên Nền tảng di động, giả sử thiết bị iOS hoặc Android)
  • Ổn định (nên có thể xử lý một số tiếng ồn)

Bất kỳ đề xuất và gợi ý được đánh giá rất cao!


3
Tôi nghĩ rằng bạn có khả năng bán khống khả năng của các thiết bị di động mà bạn đang nhắm mục tiêu. Hãy nhớ rằng các thiết bị hiện đại là bộ xử lý đa lõi với tốc độ xung nhịp vượt quá 1 GHz. Việc xử lý tín hiệu <10 ksps với bộ giải mã FSK không nên gây ra vấn đề về hiệu suất. Nhưng không nên có bất kỳ lý do nào khiến cách tiếp cận hiện tại của bạn (nghe có vẻ như tôi lọc / đánh dấu không gian) không thể chạy trong thời gian thực trên nền tảng di động hiện đại. Ngay cả một cách tiếp cận dựa trên PLL phức tạp hơn cũng phải phù hợp thoải mái trong phong bì xử lý của bạn. Tôi muốn hồ sơ mã hiện tại của bạn một chút.
Jason R

Câu trả lời:


9

Tôi nghĩ rằng bạn có thể có được hiệu suất tốt nhất về tỷ lệ lỗi bit bộ giải mã (BER) với vòng lặp khóa pha. Bạn cần nó để được nhanh chóng, mặc dù. Tôi nghĩ rằng đặt cược tốt nhất của bạn cho một thuật toán nhanh mà vẫn thực hiện tốt hợp lý là không giao nhau.

Bên cạnh đó, tôi muốn đề nghị bạn thay đổi 2200 Hz thành 2400 Hz. Một triển khai ngây thơ của sơ đồ 1200/2200 Hz sẽ mang lại sự không liên tục, như đã thấy khoảng hai phần ba trong âm mưu bên dưới, trong đó chuyển đổi 2200 Hz thành 1200 Hz.

1200 Hz và 2200 Hz

Để giảm thiểu băng thông mà bạn đang sử dụng và tránh sự gián đoạn sẽ làm biến dạng tín hiệu bạn sẽ cần phải thực hiện pha liên tục. Tuy nhiên, ngay cả khi bạn thực hiện pha phát liên tục, vẫn sẽ có một vấn đề là các ký hiệu 2200 Hz sẽ không luôn luôn có cùng số giao nhau bằng 0 do các pha khác nhau. Thông thường họ sẽ có bốn điểm giao nhau bằng 0, nhưng đôi khi họ sẽ có ba điểm. Mặt khác, các ký hiệu 1200 Hz sẽ luôn có hai điểm giao nhau bằng 0 vì tốc độ truyền chia đều cho tần số FSK.

Bạn có thể giải quyết cả hai vấn đề này bằng cách thay đổi 2200 Hz thành 2400 Hz. Sau đó, các ký hiệu sẽ luôn bắt đầu và kết thúc ở 0 độ (do đó tự động làm cho chúng liên tục pha) và chúng sẽ luôn có cùng số giao nhau bằng 0 - hai và bốn.

1200 Hz và 2400 Hz


Này Jim, cảm ơn câu trả lời chi tiết của bạn! Bộ điều biến của tôi thực sự làm CPFSK, do đó sự không liên tục không phải là vấn đề. Tôi cố tình chọn 1200 và 2200 Hz vì các sóng hài không trùng nhau nhiều như với bội số của 1200. Hay tôi sai ở đây? PLL nghe có vẻ hay, nhưng tôi thực sự không biết làm thế nào để thực hiện chúng. Bạn có biết bất kỳ nguồn tốt nào về PLL phần mềm không?
Patrick Oscarity

@Patrick Không, bạn đúng là 1200 và 2400 Hz sẽ có các sóng hài chồng lấp. Tuy nhiên, trong bối cảnh không giao nhau, tôi không nghĩ vấn đề hài hòa. Và không, tôi e rằng tôi không biết về một nguồn trực tuyến tốt về PLL.
Jim Clay

Điều này LAF không đúng. AFSK 1200 theo Bell 202, và nó cho biết các âm nên là 1200 và 2200. Sự gián đoạn sẽ không bao giờ xảy ra ở phía máy phát. Kiểm tra bộ điều biến AFSK 1200 mã nguồn mở, việc điều chế được thực hiện bằng cách theo dõi mức tăng pha cho mỗi âm: if tone == LOW thì last_phase + = ph_low khác last_phase + = ph_high endif; next_sample = sin (last_phase);
vz0

5

Tôi đã tạo bộ giải mã cho AFSK (tiêu chuẩn Bell 202) bằng cách sử dụng các máy thu tương quan cho 1200 Hz và 2200 Hz, với kết quả rất tốt.

tộicos

Biên độ kết quả khá độc lập với pha tín hiệu và SNR đầu ra rất tốt.


Đây chính xác là những gì tôi đã thử trước đây và những gì tôi đã gọi là bộ giải điều chế không liên tục cổ điển. Có thể việc thực hiện của tôi là sai, nhưng tôi sợ rằng nó bị tràn bộ đệm do xử lý chậm. Dẫu sao cũng xin cảm ơn!
Patrick Oscarity

0

Trong trường hợp RTTY 45,45 baud, bạn cũng sẽ có các ký hiệu không phải là số nguyên mẫu, do đó bạn cần một hàm có thể được gọi là mỗi mẫu và sau đó báo hiệu giá trị trả về của nó khi ký hiệu đó kết thúc. Và bạn cần một bộ tích lũy pha, giúp kiểm soát hoạt động của pha sóng hình sin.

Để gửi các biểu tượng có độ dài không phải là bội số nguyên của tỷ lệ mẫu, bạn cần hàm này ...

int millisecondTimer(double milliseconds, double samplerate, int resettime)
{

    static int fracsample=0;
    static int counter=0;
    static int retvalue=0;
    static int first=1;
    static double oldmilliseconds=1.0;
    static int whole_samples=0;
    static int samerror=32768;
    if(resettime==1)
    {
        samerror=0;
        counter=0;
        retvalue=1;
        first=1;
    }
    if(first==1 || milliseconds !=oldmilliseconds)
    {
        double samplesneeded=1;
        double wholesamples=0;
        samplesneeded=(samplerate) * (milliseconds /1000.0);
        samerror=(modf(samplesneeded, &wholesamples)) * 32768.0;
        whole_samples=wholesamples;
        first=0;
    }

    if(counter<=whole_samples)
    {
        retvalue=2;
        counter++;
    }
    else
    {
        counter-=whole_samples;
        retvalue=1;
        fracsample+=samerror;
        oldmilliseconds=milliseconds;
        if(fracsample>=32768)
        {
            fracsample-=32768;
            counter--;
        }

    }
    return retvalue;
}

Để sử dụng nó, hãy tạo mẫu sóng hình sin tiếp theo và gọi hàm này, sau đó kiểm tra xem giá trị trả về KHÔNG bằng hai. Nếu nó không bằng hai, hãy chuyển sang biểu tượng tiếp theo và quyết định xem bạn có gửi dấu không gian hay không, sau đó gọi lại hàm này trong khối mã thực thi khi bạn phát hiện ra rằng giá trị trả về không bằng hai.

Và đây là bộ tích lũy pha từ phần sụn Rockbox, với sự thay đổi để cho phép thay đổi biên độ (âm lượng đầy đủ là 32767, âm lượng đầy đủ 180 độ là -32768).

signed short lerpsin(float frequency,signed short amplitude,unsigned long samplerate)
{
    /* 128 sixteen bit sine samples + guard point */
    static unsigned long phase=0;
    unsigned int pos =0;
    unsigned short frac=0;
    static unsigned long step=0;
    static float old_frequency=0;
    signed short diff=0;
    static const signed short sinetab[129] =
    {
        0,   1607,   3211,   4807,   6392,   7961,   9511,  11038,
        12539,  14009,  15446,  16845,  18204,  19519,  20787,  22004,
        23169,  24278,  25329,  26318,  27244,  28105,  28897,  29621,
        30272,  30851,  31356,  31785,  32137,  32412,  32609,  32727,
        32767,  32727,  32609,  32412,  32137,  31785,  31356,  30851,
        30272,  29621,  28897,  28105,  27244,  26318,  25329,  24278,
        23169,  22004,  20787,  19519,  18204,  16845,  15446,  14009,
        12539,  11038,   9511,   7961,   6392,   4807,   3211,   1607,
        0,  -1607,  -3211,  -4807,  -6392,  -7961,  -9511, -11038,
        -12539, -14009, -15446, -16845, -18204, -19519, -20787, -22004,
        -23169, -24278, -25329, -26318, -27244, -28105, -28897, -29621,
        -30272, -30851, -31356, -31785, -32137, -32412, -32609, -32727,
        -32767, -32727, -32609, -32412, -32137, -31785, -31356, -30851,
        -30272, -29621, -28897, -28105, -27244, -26318, -25329, -24278,
        -23169, -22004, -20787, -19519, -18204, -16845, -15446, -14009,
        -12539, -11038, -9511,   -7961,  -6392,  -4807,  -3211,  -1607,
        0,
    };
    if(frequency!=old_frequency)
    {
        step = 0x100000000ull*frequency / samplerate;
    }
    phase+=step;
    pos = phase >> 25;
    frac = (phase & 0x01ffffff) >> 9;
    diff = sinetab[pos + 1] - sinetab[pos];
    old_frequency=frequency;
    return ((-((sinetab[pos] + (frac*diff >> 16)))) * amplitude) >> 15;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.