提交 fcc912a9 authored 作者: Anthony Minessale's avatar Anthony Minessale

add mod_fsk

上级 62941f69
BASE=../../../..
LOCAL_SOURCES=fsk.c uart.c fsk_callerid.c
LOCAL_OBJS=fsk.o uart.o fsk_callerid.o
include $(BASE)/build/modmake.rules
差异被折叠。
/*
* 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 __FSK_H__
#define __FSK_H__
#include "uart.h"
typedef struct {
int freq_space; /* Frequency of the 0 bit */
int freq_mark; /* Frequency of the 1 bit */
int baud_rate; /* baud rate for the modem */
} fsk_modem_definition_t;
/* Must be kept in sync with fsk_modem_definitions array in fsk.c */
/* V.23 definitions: http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-V.23 */
typedef enum {
FSK_V23_FORWARD_MODE1 = 0, /* Maximum 600 bps for long haul */
FSK_V23_FORWARD_MODE2, /* Standard 1200 bps V.23 */
FSK_V23_BACKWARD, /* 75 bps return path for V.23 */
FSK_BELL202 /* Bell 202 half-duplex 1200 bps */
} fsk_modem_types_t;
typedef enum {
FSK_STATE_CHANSEIZE = 0,
FSK_STATE_CARRIERSIG,
FSK_STATE_DATA
} fsk_state_t;
typedef struct dsp_fsk_attr_s
{
int sample_rate; /* sample rate in HZ */
bithandler_func_t bithandler; /* bit handler */
void *bithandler_arg; /* arbitrary ID passed to bithandler as first argument */
bytehandler_func_t bytehandler; /* byte handler */
void *bytehandler_arg; /* arbitrary ID passed to bytehandler as first argument */
} dsp_fsk_attr_t;
typedef struct
{
fsk_state_t state;
dsp_fsk_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 last_bit;
int downsampling_count; /* number of samples to skip */
int current_downsample; /* current skip count */
int conscutive_state_bits; /* number of bits in a row that matches the pattern for the current state */
} dsp_fsk_handle_t;
/*
* Function prototypes
*
* General calling order is:
* a) create the attributes structure (dsp_fsk_attr_init)
* b) initialize fields in the attributes structure (dsp_fsk_attr_set_*)
* c) create a Bell-202 handle (dsp_fsk_create)
* d) feed samples through the handler (dsp_fsk_sample)
*/
void dsp_fsk_attr_init(dsp_fsk_attr_t *attributes);
bithandler_func_t dsp_fsk_attr_get_bithandler(dsp_fsk_attr_t *attributes, void **bithandler_arg);
void dsp_fsk_attr_set_bithandler(dsp_fsk_attr_t *attributes, bithandler_func_t bithandler, void *bithandler_arg);
bytehandler_func_t dsp_fsk_attr_get_bytehandler(dsp_fsk_attr_t *attributes, void **bytehandler_arg);
void dsp_fsk_attr_set_bytehandler(dsp_fsk_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg);
int dsp_fsk_attr_get_samplerate(dsp_fsk_attr_t *attributes);
int dsp_fsk_attr_set_samplerate(dsp_fsk_attr_t *attributes, int samplerate);
dsp_fsk_handle_t * dsp_fsk_create(dsp_fsk_attr_t *attributes);
void dsp_fsk_destroy(dsp_fsk_handle_t **handle);
void dsp_fsk_sample(dsp_fsk_handle_t *handle, double normalized_sample);
extern fsk_modem_definition_t fsk_modem_definitions[];
#endif
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
* mod_fsk -- FSK data transfer
*
*/
#include "switch.h"
#include "fsk_callerid.h"
void bitstream_init(bitstream_t *bsp, uint8_t *data, uint32_t datalen, endian_t endian, uint8_t ss)
{
memset(bsp, 0, sizeof(*bsp));
bsp->data = data;
bsp->datalen = datalen;
bsp->endian = endian;
bsp->ss = ss;
if (endian < 0) {
bsp->top = bsp->bit_index = 7;
bsp->bot = 0;
} else {
bsp->top = bsp->bit_index = 0;
bsp->bot = 7;
}
}
int8_t bitstream_get_bit(bitstream_t *bsp)
{
int8_t bit = -1;
if (bsp->byte_index >= bsp->datalen) {
goto done;
}
if (bsp->ss) {
if (!bsp->ssv) {
bsp->ssv = 1;
return 0;
} else if (bsp->ssv == 2) {
bsp->byte_index++;
bsp->ssv = 0;
return 1;
}
}
bit = (bsp->data[bsp->byte_index] >> (bsp->bit_index)) & 1;
if (bsp->bit_index == bsp->bot) {
bsp->bit_index = bsp->top;
if (bsp->ss) {
bsp->ssv = 2;
goto done;
}
if (++bsp->byte_index > bsp->datalen) {
bit = -1;
goto done;
}
} else {
bsp->bit_index = bsp->bit_index + bsp->endian;
}
done:
return bit;
}
static void fsk_byte_handler (void *x, int data)
{
fsk_data_state_t *state = (fsk_data_state_t *) x;
uint8_t byte = (uint8_t)data;
top:
if (state->init == 3) {
return;
}
if (state->dlen) {
goto add_byte;
}
if (state->bpos == 1) {
state->blen = byte;
if ((uint32_t)(state->dlen = state->bpos + byte + 2) > state->bufsize) {
state->dlen = state->bufsize;
}
goto top;
}
add_byte:
if (state->bpos <= state->dlen) {
state->buf[state->bpos++] = byte;
} else {
state->init = 3;
}
}
switch_status_t fsk_data_init(fsk_data_state_t *state, uint8_t *data, uint32_t datalen)
{
memset(state, 0, sizeof(*state));
state->buf = data;
state->bufsize = datalen;
state->bpos = 2;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t fsk_data_add_sdmf(fsk_data_state_t *state, const char *date, char *number)
{
size_t dlen = strlen(date);
size_t nlen = strlen(number);
state->buf[0] = CID_TYPE_SDMF;
memcpy(&state->buf[state->bpos], date, dlen);
state->bpos += dlen;
memcpy(&state->buf[state->bpos], number, nlen);
state->bpos += nlen;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t fsk_data_add_mdmf(fsk_data_state_t *state, mdmf_type_t type, const uint8_t *data, uint32_t datalen)
{
state->buf[0] = CID_TYPE_MDMF;
state->buf[state->bpos++] = type;
state->buf[state->bpos++] = (uint8_t)datalen;
memcpy(&state->buf[state->bpos], data, datalen);
state->bpos += datalen;
return SWITCH_STATUS_SUCCESS;
}
switch_status_t fsk_data_add_checksum(fsk_data_state_t *state)
{
uint32_t i;
uint8_t check = 0;
state->buf[1] = (uint8_t)(state->bpos - 2);
for (i = 0; i < state->bpos; i++) {
check = check + state->buf[i];
}
state->checksum = state->buf[state->bpos] = (uint8_t)(256 - check);
state->bpos++;
state->dlen = state->bpos;
state->blen = state->buf[1];
return SWITCH_STATUS_SUCCESS;
}
switch_status_t fsk_data_parse(fsk_data_state_t *state, size_t *type, char **data, size_t *len)
{
size_t i;
int sum = 0;
top:
if (state->checksum != 0 || state->ppos >= state->dlen - 1) {
return SWITCH_STATUS_FALSE;
}
if (!state->ppos) {
for(i = 0; i < state->bpos; i++) {
sum += state->buf[i];
}
state->checksum = sum % 256;
state->ppos = 2;
if (state->buf[0] != CID_TYPE_MDMF && state->buf[0] != CID_TYPE_SDMF) {
state->checksum = -1;
}
goto top;
}
if (state->buf[0] == CID_TYPE_SDMF) {
/* convert sdmf to mdmf so we don't need 2 parsers */
if (state->ppos == 2) {
*type = MDMF_DATETIME;
*len = 8;
} else {
if (state->buf[state->ppos] == 'P' || state->buf[state->ppos] == 'O') {
*type = MDMF_NO_NUM;
*len = 1;
} else {
*type = MDMF_PHONE_NUM;
*len = state->blen - 8;
}
}
*data = (char *)&state->buf[state->ppos];
state->ppos += *len;
return SWITCH_STATUS_SUCCESS;
} else if (state->buf[0] == CID_TYPE_MDMF) {
*type = state->buf[state->ppos++];
*len = state->buf[state->ppos++];
*data = (char *)&state->buf[state->ppos];
state->ppos += *len;
return SWITCH_STATUS_SUCCESS;
}
return SWITCH_STATUS_FALSE;
}
switch_status_t fsk_demod_feed(fsk_data_state_t *state, int16_t *data, size_t samples)
{
uint32_t x;
int16_t *sp = data;
if (state->init == 3) {
return SWITCH_STATUS_FALSE;
}
for (x = 0; x < samples; x++) {
dsp_fsk_sample (state->fsk1200_handle, (double) *sp++ / 32767.0);
if (state->dlen && state->bpos >= state->dlen) {
state->init = 3;
return SWITCH_STATUS_FALSE;
}
}
return SWITCH_STATUS_SUCCESS;
}
switch_status_t fsk_demod_destroy(fsk_data_state_t *state)
{
dsp_fsk_destroy(&state->fsk1200_handle);
memset(state, 0, sizeof(*state));
return SWITCH_STATUS_SUCCESS;
}
int fsk_demod_init(fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize)
{
dsp_fsk_attr_t fsk1200_attr;
if (state->fsk1200_handle) {
dsp_fsk_destroy(&state->fsk1200_handle);
}
memset(state, 0, sizeof(*state));
memset(buf, 0, bufsize);
state->buf = buf;
state->bufsize = bufsize;
dsp_fsk_attr_init (&fsk1200_attr);
dsp_fsk_attr_set_samplerate (&fsk1200_attr, rate);
dsp_fsk_attr_set_bytehandler (&fsk1200_attr, fsk_byte_handler, state);
state->fsk1200_handle = dsp_fsk_create (&fsk1200_attr);
if (state->fsk1200_handle == NULL) {
return SWITCH_STATUS_FALSE;
}
return SWITCH_STATUS_SUCCESS;
}
size_t fsk_modulator_generate_bit(fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, size_t buflen)
{
size_t i;
for(i = 0 ; i < buflen; i++) {
fsk_trans->bit_accum += fsk_trans->bit_factor;
if (fsk_trans->bit_accum >= FSK_MOD_FACTOR) {
fsk_trans->bit_accum -= (FSK_MOD_FACTOR + fsk_trans->bit_factor);
break;
}
buf[i] = teletone_dds_state_modulate_sample(&fsk_trans->dds, bit);
}
return i;
}
int32_t fsk_modulator_generate_carrier_bits(fsk_modulator_t *fsk_trans, uint32_t bits)
{
uint32_t i = 0;
size_t r = 0;
int8_t bit = 1;
for (i = 0; i < bits; i++) {
if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) {
if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) {
break;
}
} else {
break;
}
}
return i;
}
void fsk_modulator_generate_chan_sieze(fsk_modulator_t *fsk_trans)
{
uint32_t i = 0;
size_t r = 0;
int8_t bit = 0;
for (i = 0; i < fsk_trans->chan_sieze_bits; i++) {
if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) {
if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) {
break;
}
} else {
break;
}
bit = !bit;
}
}
void fsk_modulator_send_data(fsk_modulator_t *fsk_trans)
{
size_t r = 0;
int8_t bit = 0;
while((bit = bitstream_get_bit(&fsk_trans->bs)) > -1) {
if ((r = fsk_modulator_generate_bit(fsk_trans, bit, fsk_trans->sample_buffer, sizeof(fsk_trans->sample_buffer) / 2))) {
if (fsk_trans->write_sample_callback(fsk_trans->sample_buffer, r, fsk_trans->user_data) != SWITCH_STATUS_SUCCESS) {
break;
}
} else {
break;
}
}
}
switch_status_t fsk_modulator_init(fsk_modulator_t *fsk_trans,
fsk_modem_types_t modem_type,
uint32_t sample_rate,
fsk_data_state_t *fsk_data,
float db_level,
uint32_t carrier_bits_start,
uint32_t carrier_bits_stop,
uint32_t chan_sieze_bits,
fsk_write_sample_t write_sample_callback,
void *user_data)
{
memset(fsk_trans, 0, sizeof(*fsk_trans));
fsk_trans->modem_type = modem_type;
teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_space, sample_rate, 0);
teletone_dds_state_set_tone(&fsk_trans->dds, fsk_modem_definitions[fsk_trans->modem_type].freq_mark, sample_rate, 1);
fsk_trans->bit_factor = (uint32_t)((fsk_modem_definitions[fsk_trans->modem_type].baud_rate * FSK_MOD_FACTOR) / (float)sample_rate);
fsk_trans->samples_per_bit = (uint32_t) (sample_rate / fsk_modem_definitions[fsk_trans->modem_type].baud_rate);
fsk_trans->est_bytes = (int32_t)(((fsk_data->dlen * 10) + carrier_bits_start + carrier_bits_stop + chan_sieze_bits) * ((fsk_trans->samples_per_bit + 1) * 2));
fsk_trans->bit_accum = 0;
fsk_trans->fsk_data = fsk_data;
teletone_dds_state_set_tx_level(&fsk_trans->dds, db_level);
bitstream_init(&fsk_trans->bs, fsk_trans->fsk_data->buf, (uint32_t)fsk_trans->fsk_data->dlen, ENDIAN_BIG, 1);
fsk_trans->carrier_bits_start = carrier_bits_start;
fsk_trans->carrier_bits_stop = carrier_bits_stop;
fsk_trans->chan_sieze_bits = chan_sieze_bits;
fsk_trans->write_sample_callback = write_sample_callback;
fsk_trans->user_data = user_data;
return SWITCH_STATUS_SUCCESS;
}
/*
* FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
* Copyright (C) 2005-2011, Anthony Minessale II <anthm@freeswitch.org>
*
* Version: MPL 1.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
*
* The Initial Developer of the Original Code is
* Anthony Minessale II <anthm@freeswitch.org>
* Portions created by the Initial Developer are Copyright (C)
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Anthony Minessale II <anthm@freeswitch.org>
*
* mod_fsk -- FSK data transfer
*
*/
#ifndef __FSK_CALLER_ID_H
#define __FSK_CALLER_ID_H
SWITCH_BEGIN_EXTERN_C
#include "fsk.h"
#include "uart.h"
#define FSK_MOD_FACTOR 0x10000
typedef enum {
ENDIAN_BIG = 1,
ENDIAN_LITTLE = -1
} endian_t;
typedef enum {
CID_TYPE_SDMF = 0x04,
CID_TYPE_MDMF = 0x80
} cid_type_t;
typedef enum {
MDMF_DATETIME = 1,
MDMF_PHONE_NUM = 2,
MDMF_DDN = 3,
MDMF_NO_NUM = 4,
MDMF_PHONE_NAME = 7,
MDMF_NO_NAME = 8,
MDMF_ALT_ROUTE = 9,
MDMF_NAME_VALUE = 10,
MDMF_INVALID = 11
} mdmf_type_t;
struct bitstream {
uint8_t *data;
uint32_t datalen;
uint32_t byte_index;
uint8_t bit_index;
int8_t endian;
uint8_t top;
uint8_t bot;
uint8_t ss;
uint8_t ssv;
};
struct fsk_data_state {
dsp_fsk_handle_t *fsk1200_handle;
uint8_t init;
uint8_t *buf;
size_t bufsize;
size_t blen;
size_t bpos;
size_t dlen;
size_t ppos;
int checksum;
};
typedef struct bitstream bitstream_t;
typedef struct fsk_data_state fsk_data_state_t;
typedef switch_status_t (*fsk_write_sample_t)(int16_t *buf, size_t buflen, void *user_data);
struct fsk_modulator {
teletone_dds_state_t dds;
bitstream_t bs;
uint32_t carrier_bits_start;
uint32_t carrier_bits_stop;
uint32_t chan_sieze_bits;
uint32_t bit_factor;
uint32_t bit_accum;
uint32_t sample_counter;
int32_t samples_per_bit;
int32_t est_bytes;
fsk_modem_types_t modem_type;
fsk_data_state_t *fsk_data;
fsk_write_sample_t write_sample_callback;
void *user_data;
int16_t sample_buffer[64];
};
typedef int (*fsk_data_decoder_t)(fsk_data_state_t *state);
typedef void (*logger_t)(const char *file, const char *func, int line, int level, const char *fmt, ...);
typedef struct fsk_modulator fsk_modulator_t;
switch_status_t fsk_data_init(fsk_data_state_t *state, uint8_t *data, uint32_t datalen);
void bitstream_init(bitstream_t *bsp, uint8_t *data, uint32_t datalen, endian_t endian, uint8_t ss);
int8_t bitstream_get_bit(bitstream_t *bsp);
switch_status_t fsk_data_add_mdmf(fsk_data_state_t *state, mdmf_type_t type, const uint8_t *data, uint32_t datalen);
switch_status_t fsk_data_add_checksum(fsk_data_state_t *state);
switch_status_t fsk_data_parse(fsk_data_state_t *state, size_t *type, char **data, size_t *len);
switch_status_t fsk_demod_feed(fsk_data_state_t *state, int16_t *data, size_t samples);
switch_status_t fsk_demod_destroy(fsk_data_state_t *state);
int fsk_demod_init(fsk_data_state_t *state, int rate, uint8_t *buf, size_t bufsize);
size_t fsk_modulator_generate_bit(fsk_modulator_t *fsk_trans, int8_t bit, int16_t *buf, size_t buflen);
int32_t fsk_modulator_generate_carrier_bits(fsk_modulator_t *fsk_trans, uint32_t bits);
void fsk_modulator_generate_chan_sieze(fsk_modulator_t *fsk_trans);
void fsk_modulator_send_data(fsk_modulator_t *fsk_trans);
switch_status_t fsk_modulator_init(fsk_modulator_t *fsk_trans,
fsk_modem_types_t modem_type,
uint32_t sample_rate,
fsk_data_state_t *fsk_data,
float db_level,
uint32_t carrier_bits_start,
uint32_t carrier_bits_stop,
uint32_t chan_sieze_bits,
fsk_write_sample_t write_sample_callback,
void *user_data);
#define fsk_modulator_send_all(_it) fsk_modulator_generate_chan_sieze(_it); \
fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_start); \
fsk_modulator_send_data(_it); \
fsk_modulator_generate_carrier_bits(_it, _it->carrier_bits_stop)
SWITCH_END_EXTERN_C
#endif
差异被折叠。
/*
* 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>
#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.
*/
bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attr, void **bytehandler_arg)
{
*bytehandler_arg = attr->bytehandler_arg;
return attr->bytehandler;
}
void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attr, bytehandler_func_t bytehandler, 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) {
memset(handle, 0, sizeof (*handle));
/* fill the attributes member */
memcpy(&handle->attr, attr, sizeof (*attr));
}
return handle;
}
void dsp_uart_destroy(dsp_uart_handle_t **handle)
{
if (*handle) {
free(*handle);
*handle = NULL;
}
}
void dsp_uart_bit_handler(void *x, int bit)
{
dsp_uart_handle_t *handle = (dsp_uart_handle_t *) x;
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... */
}
/*
* 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 void (*bytehandler_func_t) (void *, int);
typedef void (*bithandler_func_t) (void *, int);
typedef struct dsp_uart_attr_s
{
bytehandler_func_t bytehandler; /* 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 bits through dsp_uart_bit_handler
*/
void dsp_uart_attr_init(dsp_uart_attr_t *attributes);
bytehandler_func_t dsp_uart_attr_get_bytehandler(dsp_uart_attr_t *attributes, void **bytehandler_arg);
void dsp_uart_attr_set_bytehandler(dsp_uart_attr_t *attributes, bytehandler_func_t bytehandler, void *bytehandler_arg);
dsp_uart_handle_t * dsp_uart_create(dsp_uart_attr_t *attributes);
void dsp_uart_destroy(dsp_uart_handle_t **handle);
void dsp_uart_bit_handler(void *handle, int bit);
#endif
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论