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
This commit is contained in:
parent
d4fcd8d920
commit
09516082c6
|
@ -461,6 +461,38 @@
|
|||
</File>
|
||||
</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>
|
||||
<Globals>
|
||||
</Globals>
|
||||
|
|
|
@ -0,0 +1,322 @@
|
|||
|
||||
/*
|
||||
* bell202.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 Bell-202 1200-baud FSK decoder, suitable for
|
||||
* use in a library. The general style of the library calls is modeled
|
||||
* after the POSIX pthread_*() functions.
|
||||
*
|
||||
* 2005 03 20 R. Krten created
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "bell202.h"
|
||||
#include "uart.h"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
// local constants
|
||||
#define BELL202_MARK 1200
|
||||
#define BELL202_SPACE 2200
|
||||
#define BELL202_BAUD 1200
|
||||
|
||||
/*
|
||||
* dsp_bell202_attr_init
|
||||
*
|
||||
* Initializes the attributes structure; this must be done before the
|
||||
* attributes structure is used.
|
||||
*/
|
||||
|
||||
void
|
||||
dsp_bell202_attr_init (dsp_bell202_attr_t *attr)
|
||||
{
|
||||
memset (attr, 0, sizeof (*attr));
|
||||
}
|
||||
|
||||
/*
|
||||
* dsp_bell202_attr_get_bithandler
|
||||
* dsp_bell202_attr_set_bithandler
|
||||
* dsp_bell202_attr_get_bytehandler
|
||||
* dsp_bell202_attr_set_bytehandler
|
||||
* dsp_bell202_attr_getsamplerate
|
||||
* dsp_bell202_attr_setsamplerate
|
||||
*
|
||||
* 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_bell202_attr_get_bithandler (dsp_bell202_attr_t *attr, void **bithandler_arg)) (void *, int)
|
||||
{
|
||||
*bithandler_arg = attr -> bithandler_arg;
|
||||
return (attr -> bithandler);
|
||||
}
|
||||
|
||||
void
|
||||
dsp_bell202_attr_set_bithandler (dsp_bell202_attr_t *attr, void (*bithandler) (void *, int ), void *bithandler_arg)
|
||||
{
|
||||
attr -> bithandler = bithandler;
|
||||
attr -> bithandler_arg = bithandler_arg;
|
||||
}
|
||||
|
||||
void (*
|
||||
dsp_bell202_attr_get_bytehandler (dsp_bell202_attr_t *attr, void **bytehandler_arg)) (void *, int)
|
||||
{
|
||||
*bytehandler_arg = attr -> bytehandler_arg;
|
||||
return (attr -> bytehandler);
|
||||
}
|
||||
|
||||
void
|
||||
dsp_bell202_attr_set_bytehandler (dsp_bell202_attr_t *attr, void (*bytehandler) (void *, int ), void *bytehandler_arg)
|
||||
{
|
||||
attr -> bytehandler = bytehandler;
|
||||
attr -> bytehandler_arg = bytehandler_arg;
|
||||
}
|
||||
|
||||
int
|
||||
dsp_bell202_attr_get_samplerate (dsp_bell202_attr_t *attr)
|
||||
{
|
||||
return (attr -> sample_rate);
|
||||
}
|
||||
|
||||
int
|
||||
dsp_bell202_attr_set_samplerate (dsp_bell202_attr_t *attr, int samplerate)
|
||||
{
|
||||
if (samplerate <= 0) {
|
||||
return (-1);
|
||||
}
|
||||
attr -> sample_rate = samplerate;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* dsp_bell202_create
|
||||
*
|
||||
* Creates a handle for subsequent use. The handle is created to contain
|
||||
* a context data structure for use by the sample handler function. The
|
||||
* function expects an initialized attributes structure, and returns the
|
||||
* handle or a NULL if there were errors.
|
||||
*
|
||||
* Once created, the handle can be used until it is destroyed.
|
||||
*/
|
||||
|
||||
dsp_bell202_handle_t *
|
||||
dsp_bell202_create (dsp_bell202_attr_t *attr)
|
||||
{
|
||||
int i;
|
||||
double phi_mark, phi_space;
|
||||
dsp_bell202_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));
|
||||
|
||||
// see if we can do downsampling. We only really need 6 samples to "match"
|
||||
if (attr -> sample_rate / BELL202_MARK > 6) {
|
||||
handle -> downsampling_count = attr -> sample_rate / BELL202_MARK / 6;
|
||||
} else {
|
||||
handle -> downsampling_count = 1;
|
||||
}
|
||||
handle -> current_downsample = 1;
|
||||
|
||||
// calculate the correlate size (number of samples required for slowest wave)
|
||||
handle -> corrsize = attr -> sample_rate / handle -> downsampling_count / BELL202_MARK;
|
||||
|
||||
// allocate the correlation sin/cos arrays and initialize
|
||||
for (i = 0; i < 4; i++) {
|
||||
handle -> correlates [i] = malloc (sizeof (double) * handle -> corrsize);
|
||||
if (handle -> correlates [i] == NULL) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i != 4) { // some failed, back out memory allocations
|
||||
dsp_bell202_destroy (handle);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
// now initialize them
|
||||
phi_mark = 2. * M_PI / ((double) attr -> sample_rate / (double) handle -> downsampling_count / (double) BELL202_MARK);
|
||||
phi_space = 2. * M_PI / ((double) attr -> sample_rate / (double) handle -> downsampling_count / (double) BELL202_SPACE);
|
||||
|
||||
// printf ("phi_mark is %g, phi_space is %g\n", phi_mark, phi_space);
|
||||
for (i = 0; i < handle -> corrsize; i++) {
|
||||
handle -> correlates [0][i] = sin (phi_mark * (double) i);
|
||||
handle -> correlates [1][i] = cos (phi_mark * (double) i);
|
||||
handle -> correlates [2][i] = sin (phi_space * (double) i);
|
||||
handle -> correlates [3][i] = cos (phi_space * (double) i);
|
||||
// printf ("[%2d] MS %10.4f MC %10.4f SS %10.4f SC %10.4f\n", i, handle -> correlates [0][i], handle -> correlates [1][i], handle -> correlates [2][i], handle -> correlates [3][i]);
|
||||
}
|
||||
|
||||
// initialize the ring buffer
|
||||
handle -> buffer = malloc (sizeof (double) * handle -> corrsize);
|
||||
if (handle -> buffer == NULL) { // failed; back out memory allocations
|
||||
dsp_bell202_destroy (handle);
|
||||
return (NULL);
|
||||
}
|
||||
memset (handle -> buffer, 0, sizeof (double) * handle -> corrsize);
|
||||
handle -> ringstart = 0;
|
||||
|
||||
// initalize intra-cell position
|
||||
handle -> cellpos = 0;
|
||||
handle -> celladj = BELL202_BAUD / (double) attr -> sample_rate * (double) handle -> downsampling_count;
|
||||
|
||||
// printf ("corrsize %d celladj %g\n", handle -> corrsize, handle -> celladj);
|
||||
|
||||
// if they have provided a byte handler, add a UART to the processing chain
|
||||
if (handle -> attr.bytehandler) {
|
||||
dsp_uart_attr_t uart_attr;
|
||||
dsp_uart_handle_t *uart_handle;
|
||||
|
||||
dsp_uart_attr_init (&uart_attr);
|
||||
dsp_uart_attr_set_bytehandler (&uart_attr, handle -> attr.bytehandler, handle -> attr.bytehandler_arg);
|
||||
uart_handle = dsp_uart_create (&uart_attr);
|
||||
if (uart_handle == NULL) {
|
||||
dsp_bell202_destroy (handle);
|
||||
return (NULL);
|
||||
}
|
||||
handle -> attr.bithandler = dsp_uart_bit_handler;
|
||||
handle -> attr.bithandler_arg = uart_handle;
|
||||
}
|
||||
|
||||
return (handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* dsp_bell202_destroy
|
||||
*
|
||||
* Destroys a handle, releasing any associated memory. A destroyed handle
|
||||
* should not be used for anything.
|
||||
*/
|
||||
|
||||
void
|
||||
dsp_bell202_destroy (dsp_bell202_handle_t *handle)
|
||||
{
|
||||
int i;
|
||||
|
||||
// if empty handle, just return
|
||||
if (handle == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (handle -> correlates [i] != NULL) {
|
||||
free (handle -> correlates [i]);
|
||||
handle -> correlates [i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle -> buffer != NULL) {
|
||||
free (handle -> buffer);
|
||||
handle -> buffer = NULL;
|
||||
}
|
||||
|
||||
free (handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* dsp_bell202_sample
|
||||
*
|
||||
* This is the main processing entry point. The function accepts a normalized
|
||||
* sample (i.e., one whose range is between -1 and +1). The function performs
|
||||
* the Bell-202 FSK modem decode processing, and, if it detects a valid bit,
|
||||
* will call the bithandler associated with the attributes structure.
|
||||
*
|
||||
* For the Bell-202 standard, a logical zero (space) is 2200 Hz, and a logical
|
||||
* one (mark) is 1200 Hz.
|
||||
*/
|
||||
|
||||
void
|
||||
dsp_bell202_sample (dsp_bell202_handle_t *handle, double normalized_sample)
|
||||
{
|
||||
double val;
|
||||
double factors [4];
|
||||
int i, j;
|
||||
|
||||
// if we can avoid processing samples, do so
|
||||
if (handle -> downsampling_count != 1) {
|
||||
if (handle -> current_downsample < handle -> downsampling_count) {
|
||||
handle -> current_downsample++;
|
||||
return; // throw this sample out
|
||||
}
|
||||
handle -> current_downsample = 1;
|
||||
}
|
||||
|
||||
// store sample in buffer
|
||||
handle -> buffer [handle -> ringstart++] = normalized_sample;
|
||||
if (handle -> ringstart >= handle -> corrsize) {
|
||||
handle -> ringstart = 0;
|
||||
}
|
||||
|
||||
// do the correlation calculation
|
||||
factors [0] = factors [1] = factors [2] = factors [3] = 0; // clear out intermediate sums
|
||||
j = handle -> ringstart;
|
||||
for (i = 0; i < handle -> corrsize; i++) {
|
||||
if (j >= handle -> corrsize) {
|
||||
j = 0;
|
||||
}
|
||||
val = handle -> buffer [j];
|
||||
factors [0] += handle -> correlates [0][i] * val;
|
||||
factors [1] += handle -> correlates [1][i] * val;
|
||||
factors [2] += handle -> correlates [2][i] * val;
|
||||
factors [3] += handle -> correlates [3][i] * val;
|
||||
j++;
|
||||
}
|
||||
|
||||
// store the bit (bit value is comparison of the two sets of correlate factors)
|
||||
handle -> previous_bit = handle -> current_bit;
|
||||
handle -> current_bit = (factors [0] * factors [0] + factors [1] * factors [1] > factors [2] * factors [2] + factors [3] * factors [3]);
|
||||
|
||||
// printf ("Sample %10.4f factors %10.4f %10.4f %10.4f %10.4f (sum %10.4f) previous %d current %d cellpos %10.4f\n", normalized_sample, factors [0], factors [1], factors [2], factors [3], factors [0] * factors [0] + factors [1] * factors [1] - factors [2] * factors [2] - factors [3] * factors [3], handle -> previous_bit, handle -> current_bit, handle -> cellpos);
|
||||
// if there's a transition, we can synchronize the cell position
|
||||
if (handle -> previous_bit != handle -> current_bit) {
|
||||
handle -> cellpos = 0.5; // adjust cell position to be in the middle of the cell
|
||||
}
|
||||
handle -> cellpos += handle -> celladj; // walk the cell along
|
||||
|
||||
if (handle -> cellpos > 1.0) {
|
||||
handle -> cellpos -= 1.0;
|
||||
(*handle -> attr.bithandler) (handle -> attr.bithandler_arg, handle -> current_bit);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
|
||||
/*
|
||||
* 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__
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
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.
|
|
@ -0,0 +1,137 @@
|
|||
|
||||
/*
|
||||
* 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
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
|
||||
/*
|
||||
* 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__
|
||||
|
Loading…
Reference in New Issue