波形识别: 
waveEncode: 字符转换成波形;
waveDecode:将波形转换成字符;

无线通信实现传输信息

完整源码: 

waveEncode.c

#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>

#include <math.h>
#include "waveRecog.h"

 static signed char crc_8_ccitt(signed char* msg, int len) 
 {
    int crc =  0xFF;  
    int polynomial = 0x07;  
    signed char bit, c7;
    int b = 0, i = 0;
    
    for (b = 0; b < len; b++) 
    {
        for (i = 0; i < 8; i++) 
        {
            bit = ((msg[b] >> (7 - i) & 1) == 1)?1:0;
            c7 = ((crc >> 7 & 1) == 1)?1:0;
            crc <<= 1;
            if (c7 ^ bit)
                crc ^= polynomial;
        }
    }
    crc &= CRC_BIT;
    return (signed char)crc;
}

// 浮点的正弦波转成整数
void float2Byte(double* sequence, int length, signed char* result)
{
    int i = 0;
    for(i=0; i < length; i++)
    {
        result[i] = (signed char)((sequence[i] * FLOAT_TO_BYTE_BASE));
    }
}

// 两端磨平,降低两端的权值,凸出中间部分权重,提高准确率
void smoothBurst(double* input, int length)
{
    int peaks = (int)(length /40);
    int i = 0;
    for (i=0; i<length; i++)
    {
        if (i < peaks)
        {
            input[i] = input[i]  * i /peaks ;
        } 
        else if ( i > length - peaks)
        {
            input[i] = input[i] * (length - i - 1)/peaks;
        }
    }
}

// 头部用于调相的正弦波
void phaseSequence(signed char* output)
{
    double signal[SAMPLES_PER_BURST]; 
    double innerMultiplier =  (HEAD_SCH_FREQUENCY* 2 * M_PI)/ SAMPLING_RATE ;
    int i = 0;
    for(i = 0; i < SAMPLES_PER_BURST; i++){
      signal[i] =  cos(innerMultiplier * i); 
    }

    smoothBurst(signal, SAMPLES_PER_BURST);
    float2Byte(signal, SAMPLES_PER_BURST, output);
}

// 信号调制
void encodeBurst(char input, signed char* output)
{
    double signal[SAMPLES_PER_BURST];
    int k = 0;
    int l = 0;
    double innerMultiplier = 0.0;
    memset(signal, 0, sizeof(double)*SAMPLES_PER_BURST);
    
    // 8种频率的信号调制到一起, CA(载波聚合)?
    for(k = 0; k < BITS_PER_BYTE; k++)
    {
        if( ((input >> k) & 0x1) == 0 )
        { 
            continue;
        }
        innerMultiplier = (2 * M_PI) / g_iFrequencies[k];
        for(l = 0; l < SAMPLES_PER_BURST; l++){
            signal[l] = signal[l] + ((cos(innerMultiplier * l)/BITS_PER_BYTE)); 
        }
    }
    smoothBurst(signal, SAMPLES_PER_BURST);   
    float2Byte(signal,SAMPLES_PER_BURST, output);
    return ;
}

void encodeStream(char* input, int lengthOfInput, signed char* outputresult, int* lengthOfOutput)
{
    int i=0;
    int j=0;
    int ioutPos = 0;
    signed char crc;
    signed char *output = outputresult;
    #ifdef SUPPORT_NOISE
    //用当前时间点初始化随机种子,防止每次运行的结果都相同,  可以用于产生噪声
    time_t tm;
    time(&tm);
    unsigned int nSeed =(unsigned int)tm;
    srand(nSeed);
    #endif

    memset(&output[ioutPos], 0, SAMPLES_PER_BURST);  //初始化一段全0脉冲
    ioutPos += SAMPLES_PER_BURST;
    
    phaseSequence(&output[ioutPos]);  //产生一个固定频率的正弦波, 用于解码调相的脉冲序列
    ioutPos += SAMPLES_PER_BURST;

    encodeBurst(HEAD_0, &output[ioutPos]);  //头部脉冲
    ioutPos += SAMPLES_PER_BURST;
    
    encodeBurst(HEAD_1, &output[ioutPos]);  // 头部脉冲
    ioutPos += SAMPLES_PER_BURST;
    
    for(i=0;i<lengthOfInput;i++)
    {
        encodeBurst(input[i], &output[ioutPos]);  // 内容脉冲
        ioutPos += SAMPLES_PER_BURST;
    }
    
    crc = crc_8_ccitt((signed char*)input, lengthOfInput);
    encodeBurst(crc, &output[ioutPos]);  // crc校验脉冲
    ioutPos += SAMPLES_PER_BURST;
    
    encodeBurst(0, &output[ioutPos]);   // 尾部冗余量
    ioutPos += SAMPLES_PER_BURST; 

    *lengthOfOutput = ioutPos;
    return ;
}

int main()
{
    FILE *fp        = NULL;
    char fileName[64] = "inputWave.pcm";
    char input[] = "abcdefghijklmnopqrstuvwxyz 0123456789 ~!@#$%^&*()_+{}:";
    int lengthOfInput = strlen(input);
    int lengthOfOutput = 0;
    int iWriteLen = 0;

    char *output = (char *)malloc(SAMPLES_PER_BURST*(8+sizeof(input)));
    if(NULL == output)
    {
        TRACE_ERROR("No Mem!");
        return -1;
    }
    memset(output, 0 ,SAMPLES_PER_BURST*(8+sizeof(input)));
    
    fp = fopen(fileName,"wb");
    if(NULL == fp)
    {
        TRACE_ERROR("Create %s Failed!", fileName);
        free(output);
        return -2;
    }
    
    encodeStream(input,lengthOfInput,output,&lengthOfOutput);
    if(lengthOfOutput > 0)
    {
        iWriteLen = fwrite(output,1,lengthOfOutput,fp);
        if(iWriteLen != lengthOfOutput)
        {
            TRACE_WARN("File write error input length is %d, write length is %d",lengthOfOutput , iWriteLen);
        }
    }
    else
    {
        TRACE_ERROR("Encode error!");
    }
    fclose(fp);
    free(output);
    TRACE_INFO("Encode %s ok...",input);
    return 0;
}

waveDecode.c

#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <math.h>
#include "waveRecog.h"

#define RECOG_THRESHOLD   (0.53) //0.4

static signed char crc_8_ccitt(signed char* msg, int len) 
{
    int crc =  0xFF;  
    int polynomial = 0x07;  
    signed char bit, c7;
    int b = 0, i = 0;
    
    for (b = 0; b < len; b++) 
    {
        for (i = 0; i < 8; i++) 
        {
            bit = ((msg[b] >> (7 - i) & 1) == 1)?1:0;
            c7 = ((crc >> 7 & 1) == 1)?1:0;
            crc <<= 1;
            if (c7 ^ bit)
                crc ^= polynomial;
        }
    }
    crc &= CRC_BIT;
    return (signed char)crc;
}

double complexCalculate(signed char *signal, int lengthofsignal, double u)
{
    int i = 0;
    double realSum = 0;
    double imaginarySum = 0;
    double realUnit = 0;
    double imaginaryUnit = 0;
    // 滤波    积分
    for(i = 0; i < lengthofsignal; i ++)
    {
        realUnit = cos(i * u) * signal[i] ;
        imaginaryUnit = sin(i * u) * signal[i];  // 防止相位相差180
        realSum = realSum + realUnit;
        
        imaginarySum = imaginarySum + imaginaryUnit;
    }
    // 均衡
    double realAve = realSum/lengthofsignal;
    double imaginaryAve = imaginarySum/lengthofsignal; 

    return sqrt( (realAve * realAve) + (imaginaryAve * imaginaryAve) );
}


double complexDetect(signed char *signal, int lengthofsignal, int index)
{
    // 特征频点
    double innerMultiplier = (2 * M_PI) / g_iFrequencies[index];
    // 滤波积分
    return complexCalculate(signal, lengthofsignal, innerMultiplier);
}

double complexHead(signed char *signal, int lengthofsignal)
{
    // 头部频点
    double u = 2 * M_PI * HEAD_SCH_FREQUENCY / SAMPLING_RATE;

    //滤波积分
    return complexCalculate(signal, lengthofsignal, u);
}

int streamdecode(double *StartSignals, int lengthofStartSignals, signed char *pcm_buf8,  int lengthofpcmbuf8, signed char *decoded, int lengthofDecoded)
{     
    int i = 0;
    int j = 0;
    int k = 0;
    int kk = 0;
    int durations = lengthofpcmbuf8/SAMPLES_PER_BURST;
    double signal[BITS_PER_BYTE * BYTES_PER_BURST][durations];
    // 该Burst所有信道的原始信号能量
    for(i=0; i < durations; i++)
    {
        for( j = 0; j < BITS_PER_BYTE * BYTES_PER_BURST; j++)
        {
            signal[j][i] = complexDetect(pcm_buf8 + SAMPLES_PER_BURST*i, SAMPLES_PER_BURST, j);
        }
    }
 
    //归一化信号 
    for( i = 0; i < (BITS_PER_BYTE * BYTES_PER_BURST); i++)
    {
        for( j = 0; j < durations; j++)
        {
            signal[i][j] = signal[i][j] / StartSignals[i];
        }
    }

    int ivalue = 0;
    for( i = 0; i < durations; i++)
    {
        for( k = 0; k < BYTES_PER_BURST; k++)
        {
            signed char value = 0;
            for(j = 0; j < BITS_PER_BYTE; j++)
            {
                // 归一化后的能量大于RECOG_THRESHOLD(0.53 理论上是0.5) 就检测到该信道为1,否则为0
                if(signal[(k * BITS_PER_BYTE) + j][i] > RECOG_THRESHOLD)
                { 
                    value = (signed char)(value | ( 1 << j));
                }

                // 信道噪声比较大, 信道能量在 RECOG_THRESHOLD 左右
                /* TODO 信道差的处理
                        两种猜测,0和1,   后面做CRC的时候分别传入校验即可,但是质量差的点太多也无法恢复,如传输CRC的的信号质量差怎么办
                */      
                if((signal[(k * BITS_PER_BYTE) + j][i] > (RECOG_THRESHOLD - 0.1) && (signal[(k * BITS_PER_BYTE) + j][i] < (RECOG_THRESHOLD + 0.1))))
                {
                  TRACE_WARN("Bad quality: %d:%f     %d \n",j,signal[(k * BITS_PER_BYTE) + j][i],ivalue);
                }
            }

            // 得出信号值
            *(decoded+kk)=value;
            kk++;
            // 函数调用问题
            if(kk > lengthofDecoded)
            {
                TRACE_ERROR("Decoded size is not enough\n");
                return -1;
            }
        }
    }

    return 0;
}

static int findHead(char* signal, int lengthofsignal, int granularity)
{
    int maxCorrelationIndex = -1;
    double maxCorrelation = -1;  // 如果噪声大,这个点可以调节,需要更多的噪声环境测量出一个合适的阈值
    double acceptedSignal = 0.01;
    int i=0;
 
    for(i = 0; i <= lengthofsignal - SAMPLES_PER_BURST; i += granularity)
    { 
        double corr = complexHead(signal+i,SAMPLES_PER_BURST);
        if (corr > maxCorrelation)
        {
            // 如果频率匹配且相位正确,那从这一点开始的积分的结果最大
            maxCorrelation = corr;
            maxCorrelationIndex = i;
        }
    }
    
    // 最大能量都小于可接受的能量  
    if (maxCorrelation < acceptedSignal && maxCorrelation > -1){
        maxCorrelationIndex = -1;
    }
    return maxCorrelationIndex;
}

int main()
{
    int headIndex = 0;
    int i = 0;
    int iNeedLen = 0, ireadLen = 0,iPos = 0;
    int iGotHead = 0;
    int iBufSize =  SAMPLES_PER_BURST * HEAD_LEN;
    int ioutIndex = 0;
    int iFilePos = 0;
    unsigned char outStream[128];

    double startSignals[BITS_PER_BYTE] = {0,0,0,0,0,0,0,0};
    signed char *pcm_buf8 = NULL;
    FILE *fp = NULL;
    char fileName[] = "inputWave.pcm";
    fp = fopen(fileName,"rb");
    if (NULL == fp)
    {
        TRACE_ERROR("Open %s failed!",fileName);
        return -1;
    }
    pcm_buf8 = (signed char *)malloc(iBufSize);
    if(NULL == pcm_buf8)
    {
        TRACE_ERROR("No Mem!");
        fclose(fp);
        return -2;
    }

    while(1)
    {
        iNeedLen =  iBufSize - iPos;
        if (iNeedLen)
        {
            ireadLen = fread(&pcm_buf8[iPos],1,iNeedLen,fp);
            if((ireadLen != iNeedLen) && (0 == (iPos + ireadLen)))
            {
                TRACE_WARN("Read file, Can't get enough data, expert:%d read :%d \n",iNeedLen,ireadLen);
                break ;
            }
            iFilePos += ireadLen;
            iPos += ireadLen;
        }
        
        if(0 == iGotHead)
        {
            // 以20个样点为单位步进找到头部,步进越小查找的相位越精确
            headIndex = findHead(pcm_buf8,iPos,20);
            if(0 == headIndex)  //检测到头
            {
                TRACE_INFO("Find head ");
                // 头部信息的两个字节为0xAA(10101010) 0x55(01010101)
                // 得到到所有物理信道,便于后面做归一化
                for( i= 1; i < BITS_PER_BYTE ; i+=2)
                {
                    startSignals[i] = complexDetect(pcm_buf8 + SAMPLES_PER_BURST, SAMPLES_PER_BURST, i);
                }
                for( i= 0; i < BITS_PER_BYTE; i+=2)
                {
                    startSignals[i] = complexDetect(pcm_buf8 +(SAMPLES_PER_BURST*2), SAMPLES_PER_BURST, i);
                }
                // TODO   这里其实也可以把 头部两个字节(0xAA 和0x55)解析出来   ,头部解析出来就不需要 memmove

                iGotHead = 1;
            }
            else if(0 < headIndex) //可能检测到头的位置,在某个位置有个能量极值点
            {
                TRACE_INFO("May Be Get Head ");
                
            }
            else //未检测到任何信息
            {
                TRACE_INFO("No any Data , Have Read:%d headIndex:%d",iFilePos,headIndex);
            }
            iPos -= SAMPLES_PER_BURST;
            if (iPos > 0)
                memmove(pcm_buf8, pcm_buf8 + SAMPLES_PER_BURST, iPos);
            continue;
        }

        streamdecode(startSignals,BITS_PER_BYTE,pcm_buf8,SAMPLES_PER_BURST,&(outStream[ioutIndex]),1);
        iPos -= SAMPLES_PER_BURST;
        // 这里可以把buf里面的内容都解析出来就不用 memmove
        if (iPos > 0)
            memmove(pcm_buf8, pcm_buf8 + SAMPLES_PER_BURST, iPos);
        
        TRACE_INFO("%d.Get 0x%x[%c] ",ioutIndex,outStream[ioutIndex],outStream[ioutIndex]);
        if(outStream[ioutIndex])
        {
            ioutIndex += 1;
            continue;
        }
        
        if(ioutIndex <= 1+HEAD_INFO_LEN)
        {
            TRACE_ERROR("Can't Get any info! File Pos:%d",iFilePos);
        }
        
//        TRACE_INFO("%x  CRC:%x \n\n", outStream[ioutIndex - 1],(unsigned char)crc_8_ccitt(&outStream[HEAD_INFO_LEN], ioutIndex-1-HEAD_INFO_LEN));
        if (outStream[ioutIndex - 1] == (unsigned char)crc_8_ccitt(&outStream[HEAD_INFO_LEN], ioutIndex-1-HEAD_INFO_LEN))
        {
            outStream[ioutIndex-1] = 0; 
            TRACE_INFO("outstring is %s  ", &outStream[HEAD_INFO_LEN]);
        }
        else
        {
            TRACE_WARN("CRC error outstring is %s  ", &outStream[HEAD_INFO_LEN]);
        }
        break;
    }
        
    fclose(fp);
    free(pcm_buf8);
    return (0);
}

TODO: 

1. 增加载波数量 - 即增加物理通道数量

2. 提高载波频率 - 即提高负载

3. 跳频 - 提高抗干扰能力

4. 增加高能基波 - 相当于加入干扰因子