From a5d199ea6aed560d3b62c41b73d16d500ba51b99 Mon Sep 17 00:00:00 2001 From: batt Date: Sat, 10 Oct 2009 09:13:28 +0000 Subject: [PATCH] Move static varibles in the Afsk structure in order to allow multiple modem instances. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@3056 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/net/afsk.c | 300 +++++++++++++++++++--------------------------- bertos/net/afsk.h | 75 +++++++++++- 2 files changed, 194 insertions(+), 181 deletions(-) diff --git a/bertos/net/afsk.c b/bertos/net/afsk.c index e516a3f3..6fea471b 100644 --- a/bertos/net/afsk.c +++ b/bertos/net/afsk.c @@ -51,11 +51,6 @@ #include /* memset */ -// Demodulator constants -#define SAMPLERATE 9600 -#define BITRATE 1200 - -#define SAMPLEPERBIT (SAMPLERATE / BITRATE) #define PHASE_BIT 8 #define PHASE_INC 1 @@ -74,22 +69,6 @@ STATIC_ASSERT(!(CONFIG_AFSK_DAC_SAMPLERATE % BITRATE)); #define DAC_SAMPLEPERBIT (CONFIG_AFSK_DAC_SAMPLERATE / BITRATE) - -/** Current sample of bit for output data. */ -static uint8_t sample_count; - -/** Current character to be modulated */ -static uint8_t curr_out; - -/** Mask of current modulated bit */ -static uint8_t tx_bit; - -/** True if bit stuff is allowed, false otherwise */ -static bool bit_stuff; - -/** Counter for bit stuffing */ -static uint8_t stuff_cnt; - /** * Sine table for the first quarter of wave. * The rest of the wave is computed from this first quarter. @@ -112,14 +91,6 @@ static const uint8_t sin_table[] = STATIC_ASSERT(sizeof(sin_table) == SIN_LEN / 4); -/** - * DDS phase accumulator for generating modulated data. - */ -static uint16_t phase_acc; - -/** Current phase increment for current modulated bit */ -static uint16_t phase_inc = MARK_INC; - /** * Given the index, this function computes the correct sine sample @@ -134,106 +105,76 @@ INLINE uint8_t sin_sample(uint16_t idx) } -static FIFOBuffer delay_fifo; - -/** - * Buffer for delay FIFO. - * The 1 is added because the FIFO macros need - * 1 byte more to handle a buffer (SAMPLEPERBIT / 2) bytes long. - */ -static int8_t delay_buf[SAMPLEPERBIT / 2 + 1]; - -static FIFOBuffer rx_fifo; -static uint8_t rx_buf[CONFIG_AFSK_RX_BUFLEN]; - -static FIFOBuffer tx_fifo; -static uint8_t tx_buf[CONFIG_AFSK_TX_BUFLEN]; - -static int16_t iir_x[2]; -static int16_t iir_y[2]; - -static uint8_t sampled_bits; -static uint8_t found_bits; -static uint8_t demod_bits; -static int8_t curr_phase; - -static bool hdlc_rxstart; -static uint8_t hdlc_currchar; -static uint8_t hdlc_bit_idx; - #define BIT_DIFFER(bitline1, bitline2) (((bitline1) ^ (bitline2)) & 0x01) #define EDGE_FOUND(bitline) BIT_DIFFER((bitline), (bitline) >> 1) -static uint16_t preamble_len; -static uint16_t trailer_len; -static void hdlc_parse(bool bit) +static void hdlc_parse(Afsk *af, bool bit) { - demod_bits <<= 1; - demod_bits |= bit ? 1 : 0; + af->hdlc_demod_bits <<= 1; + af->hdlc_demod_bits |= bit ? 1 : 0; /* HDLC Flag */ - if (demod_bits == HDLC_FLAG) + if (af->hdlc_demod_bits == HDLC_FLAG) { - if (!fifo_isfull(&rx_fifo)) + if (!fifo_isfull(&af->rx_fifo)) { - fifo_push(&rx_fifo, HDLC_FLAG); - hdlc_rxstart = true; + fifo_push(&af->rx_fifo, HDLC_FLAG); + af->hdlc_rxstart = true; } else - hdlc_rxstart = false; + af->hdlc_rxstart = false; - hdlc_currchar = 0; - hdlc_bit_idx = 0; + af->hdlc_currchar = 0; + af->hdlc_bit_idx = 0; return; } /* Reset */ - if ((demod_bits & HDLC_RESET) == HDLC_RESET) + if ((af->hdlc_demod_bits & HDLC_RESET) == HDLC_RESET) { - hdlc_rxstart = false; + af->hdlc_rxstart = false; return; } - if (!hdlc_rxstart) + if (!af->hdlc_rxstart) return; /* Stuffed bit */ - if ((demod_bits & 0x3f) == 0x3e) + if ((af->hdlc_demod_bits & 0x3f) == 0x3e) return; - if (demod_bits & 0x01) - hdlc_currchar |= 0x80; + if (af->hdlc_demod_bits & 0x01) + af->hdlc_currchar |= 0x80; - if (++hdlc_bit_idx >= 8) + if (++af->hdlc_bit_idx >= 8) { - if ((hdlc_currchar == HDLC_FLAG - || hdlc_currchar == HDLC_RESET - || hdlc_currchar == AX25_ESC)) + if ((af->hdlc_currchar == HDLC_FLAG + || af->hdlc_currchar == HDLC_RESET + || af->hdlc_currchar == AX25_ESC)) { - if (!fifo_isfull(&rx_fifo)) - fifo_push(&rx_fifo, AX25_ESC); + if (!fifo_isfull(&af->rx_fifo)) + fifo_push(&af->rx_fifo, AX25_ESC); else - hdlc_rxstart = false; + af->hdlc_rxstart = false; } - if (!fifo_isfull(&rx_fifo)) - fifo_push(&rx_fifo, hdlc_currchar); + if (!fifo_isfull(&af->rx_fifo)) + fifo_push(&af->rx_fifo, af->hdlc_currchar); else - hdlc_rxstart = false; + af->hdlc_rxstart = false; - hdlc_currchar = 0; - hdlc_bit_idx = 0; + af->hdlc_currchar = 0; + af->hdlc_bit_idx = 0; return; } - hdlc_currchar >>= 1; + af->hdlc_currchar >>= 1; } -DEFINE_AFSK_ADC_ISR() +void afsk_adc_isr(Afsk *af, int8_t curr_sample) { AFSK_STROBE_ON(); - int8_t curr_sample = AFSK_READ_ADC(); /* * Frequency discriminator and LP IIR filter. @@ -251,82 +192,82 @@ DEFINE_AFSK_ADC_ISR() * through the CONFIG_AFSK_FILTER config variable. */ - iir_x[0] = iir_x[1]; + af->iir_x[0] = af->iir_x[1]; #if (CONFIG_AFSK_FILTER == AFSK_BUTTERWORTH) - iir_x[1] = ((int8_t)fifo_pop(&delay_fifo) * curr_sample) >> 2; - //iir_x[1] = ((int8_t)fifo_pop(&delay_fifo) * curr_sample) / 6.027339492; + af->iir_x[1] = ((int8_t)fifo_pop(&af->delay_fifo) * curr_sample) >> 2; + //af->iir_x[1] = ((int8_t)fifo_pop(&af->delay_fifo) * curr_sample) / 6.027339492; #elif (CONFIG_AFSK_FILTER == AFSK_CHEBYSHEV) - iir_x[1] = ((int8_t)fifo_pop(&delay_fifo) * curr_sample) >> 2; - //iir_x[1] = ((int8_t)fifo_pop(&delay_fifo) * curr_sample) / 3.558147322; + af->iir_x[1] = ((int8_t)fifo_pop(&af->delay_fifo) * curr_sample) >> 2; + //af->iir_x[1] = ((int8_t)fifo_pop(&af->delay_fifo) * curr_sample) / 3.558147322; #else #error Filter type not found! #endif - iir_y[0] = iir_y[1]; + af->iir_y[0] = af->iir_y[1]; #if CONFIG_AFSK_FILTER == AFSK_BUTTERWORTH /* - * This strange sum + shift is an optimization for iir_y[0] * 0.668. + * This strange sum + shift is an optimization for af->iir_y[0] * 0.668. * iir * 0.668 ~= (iir * 21) / 32 = * = (iir * 16) / 32 + (iir * 4) / 32 + iir / 32 = * = iir / 2 + iir / 8 + iir / 32 = * = iir >> 1 + iir >> 3 + iir >> 5 */ - iir_y[1] = iir_x[0] + iir_x[1] + (iir_y[0] >> 1) + (iir_y[0] >> 3) + (iir_y[0] >> 5); - //iir_y[1] = iir_x[0] + iir_x[1] + iir_y[0] * 0.6681786379; + af->iir_y[1] = af->iir_x[0] + af->iir_x[1] + (af->iir_y[0] >> 1) + (af->iir_y[0] >> 3) + (af->iir_y[0] >> 5); + //af->iir_y[1] = af->iir_x[0] + af->iir_x[1] + af->iir_y[0] * 0.6681786379; #elif CONFIG_AFSK_FILTER == AFSK_CHEBYSHEV /* - * This should be (iir_y[0] * 0.438) but - * (iir_y[0] >> 1) is a faster approximation :-) + * This should be (af->iir_y[0] * 0.438) but + * (af->iir_y[0] >> 1) is a faster approximation :-) */ - iir_y[1] = iir_x[0] + iir_x[1] + (iir_y[0] >> 1); - //iir_y[1] = iir_x[0] + iir_x[1] + iir_y[0] * 0.4379097269; + af->iir_y[1] = af->iir_x[0] + af->iir_x[1] + (af->iir_y[0] >> 1); + //af->iir_y[1] = af->iir_x[0] + af->iir_x[1] + af->iir_y[0] * 0.4379097269; #endif /* Save this sampled bit in a delay line */ - sampled_bits <<= 1; - sampled_bits |= (iir_y[1] > 0) ? 1 : 0; + af->sampled_bits <<= 1; + af->sampled_bits |= (af->iir_y[1] > 0) ? 1 : 0; - /* Store current ADC sample in the delay_fifo */ - fifo_push(&delay_fifo, curr_sample); + /* Store current ADC sample in the af->delay_fifo */ + fifo_push(&af->delay_fifo, curr_sample); /* If there is an edge, adjust phase sampling */ - if (EDGE_FOUND(sampled_bits)) + if (EDGE_FOUND(af->sampled_bits)) { - if (curr_phase < PHASE_THRES) - curr_phase += PHASE_INC; + if (af->curr_phase < PHASE_THRES) + af->curr_phase += PHASE_INC; else - curr_phase -= PHASE_INC; + af->curr_phase -= PHASE_INC; } - curr_phase += PHASE_BIT; + af->curr_phase += PHASE_BIT; /* sample the bit */ - if (curr_phase >= PHASE_MAX) + if (af->curr_phase >= PHASE_MAX) { - curr_phase %= PHASE_MAX; + af->curr_phase %= PHASE_MAX; /* Shift 1 position in the shift register of the found bits */ - found_bits <<= 1; + af->found_bits <<= 1; /* * Determine bit value by reading the last 3 sampled bits. * If the number of ones is two or greater, the bit value is a 1, * otherwise is a 0. */ - uint8_t bits = sampled_bits & 0x07; + uint8_t bits = af->sampled_bits & 0x07; if (bits == 0x07 // 111, 3 bits set to 1 || bits == 0x06 // 110, 2 bits || bits == 0x05 // 101, 2 bits || bits == 0x03 // 011, 2 bits ) - found_bits |= 1; + af->found_bits |= 1; /* * NRZI coding: if 2 consecutive bits have the same value * a 1 is received, otherwise it's a 0. */ - hdlc_parse(!EDGE_FOUND(found_bits)); + hdlc_parse(af, !EDGE_FOUND(af->found_bits)); } @@ -334,100 +275,97 @@ DEFINE_AFSK_ADC_ISR() AFSK_ADC_IRQ_END(); } -/* True while modem sends data */ -static volatile bool sending; - -static void afsk_txStart(void) +static void afsk_txStart(Afsk *af) { - if (!sending) + if (!af->sending) { - phase_inc = MARK_INC; - phase_acc = 0; - stuff_cnt = 0; - sending = true; - preamble_len = DIV_ROUND(CONFIG_AFSK_PREAMBLE_LEN * BITRATE, 8000); + af->phase_inc = MARK_INC; + af->phase_acc = 0; + af->stuff_cnt = 0; + af->sending = true; + af->preamble_len = DIV_ROUND(CONFIG_AFSK_PREAMBLE_LEN * BITRATE, 8000); AFSK_DAC_IRQ_START(); } - ATOMIC(trailer_len = DIV_ROUND(CONFIG_AFSK_TRAILER_LEN * BITRATE, 8000)); + ATOMIC(af->trailer_len = DIV_ROUND(CONFIG_AFSK_TRAILER_LEN * BITRATE, 8000)); } #define BIT_STUFF_LEN 5 #define SWITCH_TONE(inc) (((inc) == MARK_INC) ? SPACE_INC : MARK_INC) -DEFINE_AFSK_DAC_ISR() +void afsk_dac_isr(Afsk *af) { /* Check if we are at a start of a sample cycle */ - if (sample_count == 0) + if (af->sample_count == 0) { - if (tx_bit == 0) + if (af->tx_bit == 0) { /* We have just finished transimitting a char, get a new one. */ - if (fifo_isempty(&tx_fifo) && trailer_len == 0) + if (fifo_isempty(&af->tx_fifo) && af->trailer_len == 0) { AFSK_DAC_IRQ_STOP(); - sending = false; + af->sending = false; AFSK_DAC_IRQ_END(); return; } else { /* - * If we have just finished sending an unstuffed byte, + * If we have just finished af->sending an unstuffed byte, * reset bitstuff counter. */ - if (!bit_stuff) - stuff_cnt = 0; + if (!af->bit_stuff) + af->stuff_cnt = 0; - bit_stuff = true; + af->bit_stuff = true; /* * Handle preamble and trailer */ - if (preamble_len == 0) + if (af->preamble_len == 0) { - if (fifo_isempty(&tx_fifo)) + if (fifo_isempty(&af->tx_fifo)) { - trailer_len--; - curr_out = HDLC_FLAG; + af->trailer_len--; + af->curr_out = HDLC_FLAG; } else - curr_out = fifo_pop(&tx_fifo); + af->curr_out = fifo_pop(&af->tx_fifo); } else { - preamble_len--; - curr_out = HDLC_FLAG; + af->preamble_len--; + af->curr_out = HDLC_FLAG; } /* Handle char escape */ - if (curr_out == AX25_ESC) + if (af->curr_out == AX25_ESC) { - if (fifo_isempty(&tx_fifo)) + if (fifo_isempty(&af->tx_fifo)) { AFSK_DAC_IRQ_STOP(); - sending = false; + af->sending = false; AFSK_DAC_IRQ_END(); return; } else - curr_out = fifo_pop(&tx_fifo); + af->curr_out = fifo_pop(&af->tx_fifo); } - else if (curr_out == HDLC_FLAG || curr_out == HDLC_RESET) + else if (af->curr_out == HDLC_FLAG || af->curr_out == HDLC_RESET) /* If these chars are not escaped disable bit stuffing */ - bit_stuff = false; + af->bit_stuff = false; } /* Start with LSB mask */ - tx_bit = 0x01; + af->tx_bit = 0x01; } /* check for bit stuffing */ - if (bit_stuff && stuff_cnt >= BIT_STUFF_LEN) + if (af->bit_stuff && af->stuff_cnt >= BIT_STUFF_LEN) { /* If there are more than 5 ones in a row insert a 0 */ - stuff_cnt = 0; + af->stuff_cnt = 0; /* switch tone */ - phase_inc = SWITCH_TONE(phase_inc); + af->phase_inc = SWITCH_TONE(af->phase_inc); } else { @@ -435,14 +373,14 @@ DEFINE_AFSK_DAC_ISR() * NRZI: if we want to transmit a 1 the modulated frequency will stay * unchanged; with a 0, there will be a change in the tone. */ - if (curr_out & tx_bit) + if (af->curr_out & af->tx_bit) { /* * Transmit a 1: * - Stay on the previous tone * - Increace bit stuff count */ - stuff_cnt++; + af->stuff_cnt++; } else { @@ -451,32 +389,33 @@ DEFINE_AFSK_DAC_ISR() * - Reset bit stuff count * - Switch tone */ - stuff_cnt = 0; - phase_inc = SWITCH_TONE(phase_inc); + af->stuff_cnt = 0; + af->phase_inc = SWITCH_TONE(af->phase_inc); } /* Go to the next bit */ - tx_bit <<= 1; + af->tx_bit <<= 1; } - sample_count = DAC_SAMPLEPERBIT; + af->sample_count = DAC_SAMPLEPERBIT; } /* Get new sample and put it out on the DAC */ - phase_acc += phase_inc; - phase_acc %= SIN_LEN; + af->phase_acc += af->phase_inc; + af->phase_acc %= SIN_LEN; - AFSK_SET_DAC(sin_sample(phase_acc)); - sample_count--; + AFSK_SET_DAC(sin_sample(af->phase_acc)); + af->sample_count--; AFSK_DAC_IRQ_END(); } -static size_t afsk_read(UNUSED_ARG(KFile *, fd), void *_buf, size_t size) +static size_t afsk_read(KFile *fd, void *_buf, size_t size) { + Afsk *af = AFSK_CAST(fd); uint8_t *buf = (uint8_t *)_buf; #if CONFIG_AFSK_RXTIMEOUT == 0 - while (size-- && !fifo_isempty_locked(&rx_fifo)) + while (size-- && !fifo_isempty_locked(&af->rx_fifo)) #else while (size--) #endif @@ -485,7 +424,7 @@ static size_t afsk_read(UNUSED_ARG(KFile *, fd), void *_buf, size_t size) ticks_t start = timer_clock(); #endif - while (fifo_isempty_locked(&rx_fifo)); + while (fifo_isempty_locked(&af->rx_fifo)); { cpu_relax(); #if CONFIG_AFSK_RXTIMEOUT != -1 @@ -494,31 +433,33 @@ static size_t afsk_read(UNUSED_ARG(KFile *, fd), void *_buf, size_t size) #endif } - *buf++ = fifo_pop_locked(&rx_fifo); + *buf++ = fifo_pop_locked(&af->rx_fifo); } return buf - (uint8_t *)_buf; } -static size_t afsk_write(UNUSED_ARG(KFile *, fd), const void *_buf, size_t size) +static size_t afsk_write(KFile *fd, const void *_buf, size_t size) { + Afsk *af = AFSK_CAST(fd); const uint8_t *buf = (const uint8_t *)_buf; while (size--) { - while (fifo_isfull_locked(&tx_fifo)) + while (fifo_isfull_locked(&af->tx_fifo)) cpu_relax(); - fifo_push_locked(&tx_fifo, *buf++); - afsk_txStart(); + fifo_push_locked(&af->tx_fifo, *buf++); + afsk_txStart(af); } return buf - (const uint8_t *)_buf; } -static int afsk_flush(UNUSED_ARG(KFile *, fd)) +static int afsk_flush(KFile *fd) { - while (sending) + Afsk *af = AFSK_CAST(fd); + while (af->sending) cpu_relax(); return 0; } @@ -529,23 +470,24 @@ void afsk_init(Afsk *af) #if CONFIG_AFSK_RXTIMEOUT != -1 MOD_CHECK(timer); #endif + memset(af, 0, sizeof(*af)); - fifo_init(&delay_fifo, (uint8_t *)delay_buf, sizeof(delay_buf)); - fifo_init(&rx_fifo, rx_buf, sizeof(rx_buf)); + fifo_init(&af->delay_fifo, (uint8_t *)af->delay_buf, sizeof(af->delay_buf)); + fifo_init(&af->rx_fifo, af->rx_buf, sizeof(af->rx_buf)); /* Fill sample FIFO with 0 */ for (int i = 0; i < SAMPLEPERBIT / 2; i++) - fifo_push(&delay_fifo, 0); + fifo_push(&af->delay_fifo, 0); - fifo_init(&tx_fifo, tx_buf, sizeof(tx_buf)); + fifo_init(&af->tx_fifo, af->tx_buf, sizeof(af->tx_buf)); AFSK_ADC_INIT(); AFSK_STROBE_INIT(); kprintf("MARK_INC %d, SPACE_INC %d\n", MARK_INC, SPACE_INC); - memset(af, 0, sizeof(*af)); DB(af->fd._type = KFT_AFSK); af->fd.write = afsk_write; af->fd.read = afsk_read; af->fd.flush = afsk_flush; + af->phase_inc = MARK_INC; } diff --git a/bertos/net/afsk.h b/bertos/net/afsk.h index dc2cf73a..2f1a2e08 100644 --- a/bertos/net/afsk.h +++ b/bertos/net/afsk.h @@ -44,13 +44,81 @@ #ifndef DRV_AFSK_H #define DRV_AFSK_H +#include "cfg/cfg_afsk.h" +#include "hw/hw_afsk.h" + #include #include -#include "hw/hw_afsk.h" +#include + + +// Demodulator constants +#define SAMPLERATE 9600 +#define BITRATE 1200 + +#define SAMPLEPERBIT (SAMPLERATE / BITRATE) + typedef struct Afsk { - KFile fd; + KFile fd; + + /** Current sample of bit for output data. */ + uint8_t sample_count; + + /** Current character to be modulated */ + uint8_t curr_out; + + /** Mask of current modulated bit */ + uint8_t tx_bit; + + /** True if bit stuff is allowed, false otherwise */ + bool bit_stuff; + + /** Counter for bit stuffing */ + uint8_t stuff_cnt; + /** + * DDS phase accumulator for generating modulated data. + */ + uint16_t phase_acc; + + /** Current phase increment for current modulated bit */ + uint16_t phase_inc; + + /** Delay line used to delay samples by (SAMPLEPERBIT / 2) */ + FIFOBuffer delay_fifo; + + /** + * Buffer for delay FIFO. + * The 1 is added because the FIFO macros need + * 1 byte more to handle a buffer (SAMPLEPERBIT / 2) bytes long. + */ + int8_t delay_buf[SAMPLEPERBIT / 2 + 1]; + + FIFOBuffer rx_fifo; + uint8_t rx_buf[CONFIG_AFSK_RX_BUFLEN]; + + FIFOBuffer tx_fifo; + uint8_t tx_buf[CONFIG_AFSK_TX_BUFLEN]; + + int16_t iir_x[2]; + int16_t iir_y[2]; + + uint8_t sampled_bits; + uint8_t found_bits; + int8_t curr_phase; + + /* True while modem sends data */ + volatile bool sending; + + + bool hdlc_rxstart; + uint8_t hdlc_currchar; + uint8_t hdlc_bit_idx; + uint8_t hdlc_demod_bits; + + uint16_t preamble_len; + uint16_t trailer_len; } Afsk; #define KFT_AFSK MAKE_ID('A', 'F', 'S', 'K') @@ -61,8 +129,11 @@ INLINE Afsk *AFSK_CAST(KFile *fd) return (Afsk *)fd; } +void afsk_adc_isr(Afsk *af, int8_t curr_sample); +void afsk_dac_isr(Afsk *af); void afsk_init(Afsk *af); + /** * \name afsk filter type * $WIZ$ afsk_filter_list = "AFSK_BUTTERWORTH", "AFSK_CHEBYSHEV" -- 2.25.1