提交 09516082 authored 作者: Michael Jerris's avatar Michael Jerris

Add fsk demodulation code from Robert Krten. Thanks for the contribution!

git-svn-id: http://svn.openzap.org/svn/openzap/trunk@197 a93c3328-9c30-0410-af19-c9cd2b2d52af
上级 d4fcd8d9
...@@ -461,6 +461,38 @@ ...@@ -461,6 +461,38 @@
</File> </File>
</Filter> </Filter>
</Filter> </Filter>
<Filter
Name="Dsp"
>
<File
RelativePath="..\src\dsp\readme.txt"
>
</File>
<Filter
Name="Header Files"
>
<File
RelativePath="..\src\dsp\bell202.h"
>
</File>
<File
RelativePath="..\src\dsp\uart.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
>
<File
RelativePath="..\src\dsp\bell202.c"
>
</File>
<File
RelativePath="..\src\dsp\uart.c"
>
</File>
</Filter>
</Filter>
</Files> </Files>
<Globals> <Globals>
</Globals> </Globals>
......
差异被折叠。
/*
* bell202.h
*
* Copyright (c) 2005 Robert Krten. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This module contains the manifest constants and declarations for
* the Bell-202 1200 baud FSK modem.
*
* 2005 03 20 R. Krten created
*/
#ifndef __BELL202_H__
#define __BELL202_H__
typedef struct dsp_bell202_attr_s
{
int sample_rate; // sample rate in HZ
void (*bithandler) (void *, int); // bit handler
void *bithandler_arg; // arbitrary ID passed to bithandler as first argument
void (*bytehandler) (void *, int); // byte handler
void *bytehandler_arg; // arbitrary ID passed to bytehandler as first argument
} dsp_bell202_attr_t;
typedef struct
{
dsp_bell202_attr_t attr; // attributes structure
double *correlates [4]; // one for each of sin/cos for mark/space
int corrsize; // correlate size (also number of samples in ring buffer)
double *buffer; // sample ring buffer
int ringstart; // ring buffer start offset
double cellpos; // bit cell position
double celladj; // bit cell adjustment for each sample
int previous_bit; // previous bit (for detecting a transition to sync-up cell position)
int current_bit; // current bit
int downsampling_count; // number of samples to skip
int current_downsample; // current skip count
} dsp_bell202_handle_t;
/*
* Function prototypes
*
* General calling order is:
* a) create the attributes structure (dsp_bell202_attr_init)
* b) initialize fields in the attributes structure (dsp_bell202_attr_set_*)
* c) create a Bell-202 handle (dsp_bell202_create)
* d) feed samples through the handler (dsp_bell202_sample)
*/
extern void dsp_bell202_attr_init (dsp_bell202_attr_t *attributes);
extern void (*dsp_bell202_attr_get_bithandler (dsp_bell202_attr_t *attributes, void **bithandler_arg)) (void *, int);
extern void dsp_bell202_attr_set_bithandler (dsp_bell202_attr_t *attributes, void (*bithandler) (void *, int ), void *bithandler_arg);
extern void (*dsp_bell202_attr_get_bytehandler (dsp_bell202_attr_t *attributes, void **bytehandler_arg)) (void *, int);
extern void dsp_bell202_attr_set_bytehandler (dsp_bell202_attr_t *attributes, void (*bytehandler) (void *, int ), void *bytehandler_arg);
extern int dsp_bell202_attr_get_samplerate (dsp_bell202_attr_t *attributes);
extern int dsp_bell202_attr_set_samplerate (dsp_bell202_attr_t *attributes, int samplerate);
extern dsp_bell202_handle_t * dsp_bell202_create (dsp_bell202_attr_t *attributes);
extern void dsp_bell202_destroy (dsp_bell202_handle_t *handle);
extern void dsp_bell202_sample (dsp_bell202_handle_t *handle, double normalized_sample);
#endif // __BELL202_H__
I have only tested the library with samples at 8kHz. It *should* work with arbitrary sample rates; the "optr" variable in the code samples below is the sampling rate in Hz.
The first thing you need to do is initialize a context structure:
dsp_bell202_attr_t fsk1200_attr; // attributes structure for FSK 1200 baud modem
dsp_bell202_handle_t *fsk1200_handle; // context structure for FSK 1200 baud modem
// initialize:
dsp_bell202_attr_init (&fsk1200_attr); // clear attributes structure
dsp_bell202_attr_set_samplerate (&fsk1200_attr, optr); // set sample rate
dsp_bell202_attr_set_bytehandler (&fsk1200_attr, clid_byte_handler, ch); // bind byte handler
// create context:
fsk1200_handle = dsp_bell202_create (&fsk1200_attr);
// error check:
if (fsk1200_handle == NULL) {
fprintf (stderr, "%s: can't dsp_bell202_create, errno %d (%s)\n", progname, errno, strerror (errno));
exit (EXIT_FAILURE);
}
If you are decoding multiple channels, you will need multiple context structures; one per channel.
The attributes ("dsp_bell202_attr_t") do not have to be persistent, but the handle does.
There's even a "dsp_bell202_destroy()" function call to remove the context structure; I don't believe I've ever used it, my stuff hangs around forever.
Then, you need to feed samples into the software modem:
dsp_bell202_sample (fsk1200_handle, (double) sample / 32767.);
It assumes the samples are between -1 and 1 as a double.
It will outcall to your provided "clid_byte_handler()" function, which needs to have a prototype as follows:
void clid_byte_handler (void *x, int data);
The "x" is a context "void *" that you can associate in the fsk1200_handle (great for multiple channels).
This will dribble bytes out to you at 1200 baud.
From there, you are on your own. Canadian caller ID streams are different format than US caller ID streams IIRC. Both are trivial to figure out, as they have lots of ASCII data. I can supply some more code later on the Canadian one if you need it.
Here's a sample of a Canadian caller ID stream from when you called:
00000000: 55 55 55 55 55 55 55 55-55 55 55 55 55 55 55 55 UUUUUUUUUUUUUUUU
00000010: 55 55 D5 80 1D 01 08 30-36 30 31 31 36 31 36 08 UU.....06011616.
00000020: 01 4F 03 0B 31 32 34 38-35 35 35 31 32 31 32 06 .O..12485551212.
00000030: 01 4C D1 85 00 02 54 00-02 C5 60 28 10 0A 80 30 .L....T...`(...0
The "UUUUU" is an alternating series of ones and zeros (which, when combined with the start and stop bits, creates the 0x55 character "U") used to train analog modems.
06011616 is the date and time (JUN 01 16:16), the "O" at 0x21 is an "Out of area"
qualifier for why your name didn't appear, and "1248..." is your DN. The "L" at 0x31 is a long distance qualifier.
/*
* uart.c
*
* Copyright (c) 2005 Robert Krten. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This module contains a simple 8-bit UART, which performs a callback
* with the decoded byte value.
*
* 2005 06 11 R. Krten created
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef _MSC_VER
#include <unistd.h>
#endif
#include <errno.h>
#include "uart.h"
/*
* dsp_uart_attr_init
*
* Initializes the attributes structure; this must be done before the
* attributes structure is used.
*/
void
dsp_uart_attr_init (dsp_uart_attr_t *attr)
{
memset (attr, 0, sizeof (*attr));
}
/*
* dsp_uart_attr_get_bytehandler
* dsp_uart_attr_set_bytehandler
*
* These functions get and set their respective elements from the
* attributes structure. If an error code is returned, it is just
* zero == ok, -1 == fail.
*/
void (*
dsp_uart_attr_get_bytehandler (dsp_uart_attr_t *attr, void **bytehandler_arg)) (void *, int)
{
*bytehandler_arg = attr -> bytehandler_arg;
return (attr -> bytehandler);
}
void
dsp_uart_attr_set_bytehandler (dsp_uart_attr_t *attr, void (*bytehandler) (void *, int ), void *bytehandler_arg)
{
attr -> bytehandler = bytehandler;
attr -> bytehandler_arg = bytehandler_arg;
}
dsp_uart_handle_t *
dsp_uart_create (dsp_uart_attr_t *attr)
{
dsp_uart_handle_t *handle;
handle = malloc (sizeof (*handle));
if (handle == NULL) {
return (handle);
}
memset (handle, 0, sizeof (handle));
// fill the attributes member
memcpy (&handle -> attr, attr, sizeof (*attr));
return (handle);
}
void
dsp_uart_bit_handler (void *x, int bit)
{
dsp_uart_handle_t *handle = (dsp_uart_handle_t *) x;
// printf ("bit %d handle -> have_start %d handle -> data %02X handle -> nbits %d\n", bit, handle -> have_start, handle -> data, handle -> nbits);
if (!handle -> have_start) {
if (bit) {
return; // waiting for start bit (0)
}
handle -> have_start = 1;
handle -> data = 0;
handle -> nbits = 0;
return;
}
handle -> data >>= 1;
handle -> data |= 0x80 * !!bit;
handle -> nbits++;
if (handle -> nbits == 8) {
(*handle -> attr.bytehandler) (handle -> attr.bytehandler_arg, handle -> data);
handle -> nbits = 0;
handle -> data = 0;
handle -> have_start = 0;
// might consider handling errors in the future...
#if 0
} else if (handle -> nbits > 8) {
if (!bit) {
// framing error; expected stop bit (mark, 1)
printf ("FRAME"); fflush (stdout);
} else {
handle -> have_start = 0;
handle -> nbits = 0;
}
#endif
}
}
/*
* uart.h
*
* Copyright (c) 2005 Robert Krten. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* This module contains the manifest constants and declarations for
* the UART module.
*
* 2005 06 19 R. Krten created
*/
#ifndef __UART_H__
#define __UART_H__
typedef struct dsp_uart_attr_s
{
void (*bytehandler) (void *, int); // byte handler
void *bytehandler_arg; // arbitrary ID passed to bytehandler as first argument
} dsp_uart_attr_t;
typedef struct
{
dsp_uart_attr_t attr;
int have_start; // wait for start bit to show up
int data; // data buffer
int nbits; // number of bits accumulated so far
} dsp_uart_handle_t;
/*
* Function prototypes
*
* General calling order is:
* a) create the attributes structure (dsp_uart_attr_init)
* b) initialize fields in the attributes structure (dsp_uart_attr_set_*)
* c) create a Bell-202 handle (dsp_uart_create)
* d) feed samples through the handler (dsp_uart_sample)
*/
extern void dsp_uart_attr_init (dsp_uart_attr_t *attributes);
extern void (*dsp_uart_attr_get_bithandler (dsp_uart_attr_t *attributes, void **bithandler_arg)) (void *, int);
extern void dsp_uart_attr_set_bithandler (dsp_uart_attr_t *attributes, void (*bithandler) (void *, int ), void *bithandler_arg);
extern void (*dsp_uart_attr_get_bytehandler (dsp_uart_attr_t *attributes, void **bytehandler_arg)) (void *, int);
extern void dsp_uart_attr_set_bytehandler (dsp_uart_attr_t *attributes, void (*bytehandler) (void *, int ), void *bytehandler_arg);
extern int dsp_uart_attr_get_samplerate (dsp_uart_attr_t *attributes);
extern int dsp_uart_attr_set_samplerate (dsp_uart_attr_t *attributes, int samplerate);
extern dsp_uart_handle_t * dsp_uart_create (dsp_uart_attr_t *attributes);
extern void dsp_uart_destroy (dsp_uart_handle_t *handle);
extern void dsp_uart_sample (dsp_uart_handle_t *handle, double normalized_sample);
extern void dsp_uart_bit_handler (void *handle, int bit);
#endif // __UART_H__
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论