PeeS
PeeS

Reputation: 1164

RTL SDR IQ AM Demodulation

The project i am working now currently is tuning to PMR frequencies and saving audio to a WAV file, however when i receive IQ samples from SDR device, and demodulate to AM - i hear noise only.

Edit, here is the RAW IQ written to WAV file: https://voca.ro/iSRELps4JBg

For demodulation i used this approach:

https://github.com/simonyiszk/minidemod/blob/master/minidemod-wfm-atan.c

However the sound seems to be noise...

  while(get_samples(buffer, buffer_size) == 1)
    {


        // Demodulate to AM
        uint8_t uiAMBuff[buffer_size];

        double i1=0, i2, q1=0, q2;
        short s; // 2 bytes
        double sum=0;
        double dbAmp=0;
        for (int i = 0; i < buffer_size; i+=2)
        {
            // I / Q

            i2=((unsigned char)buffer[i]-127);
            q2=((unsigned char)buffer[i+1]-127);


            double phi1=get_phase(i1,q1);
            double phi2=get_phase(i2,q2);

            double dphi=phi2-phi1;
            if(dphi<-PI) dphi+=2*PI; //dphi below -180°? Let's interpret it in the other direction!
            if(dphi>PI) dphi-=2*PI;  //dphi above 180°? Let's interpret it in the other direction!

            // Now let's use signed 16 bit output rather than 8 bit unsigned.
            s=((SHRT_MAX-1)/PI)*dphi; //Okay so let's get the actual sample. dphi should be between -PI and +PI.

            // Store AM in the buffer that gets written to a WAV file
            uiAMBuff[i]=s;
            uiAMBuff[i+1]=s>>8;

            i1=i2;
            q1=q2;
            // This is to calculate DB
            double y = s/32768.0;
            sum += y * y; 

        }

How to properly demodulate IQ to AM please?

Upvotes: 0

Views: 2570

Answers (2)

PeeS
PeeS

Reputation: 1164

I want to post an answer myself.

Here is how i demodulate IQ (RTLSDR) to AM taking samples from SDR.

uint8_t uiAMBuff[buffer_size];

float sum=0;

for (int i = 0; i < buffer_size; i+=2)
{

    // Get 0 - 255
    int _i=buffer[i];
    int _q=buffer[i+1];

    // This will range : 0 - 32768 (short) 2 bytes
    short amplitude = sqrt((_i*_i)+(_q*_q));
    if(amplitude > 32768) amplitude = 32768;

    // Store in separate buffer (serialize) 2 bytes
    uiAMBuff[i]=amplitude>>0;
    uiAMBuff[i+1]=amplitude>>8;

    // Calculate AM Amplitude which is always 0..1 thats why division by 32768.0
    sum += amplitude / 32768.0;

}

Upvotes: 1

hotpaw2
hotpaw2

Reputation: 70703

Your code is for an FM demodulator (frequency as the derivative of phase, or phase delta in the discrete case). For AM demodulation, you only need to get the magnitude (abs()) of the IQ components, and low pass filter.

Upvotes: 2

Related Questions