Add selectable discriminator filter type.
[bertos.git] / bertos / net / afsk.c
index c73cf8585a47aa0e218605c33a2112268f57a5b6..2472861cebba58247ccd6a822659d0cfa52979f4 100644 (file)
@@ -37,6 +37,8 @@
  */
 
 #include "afsk.h"
+#include <net/ax25.h>
+
 #include "cfg/cfg_afsk.h"
 #include "hw/hw_afsk.h"
 
@@ -169,13 +171,14 @@ static void hdlc_parse(bool bit)
        /* HDLC Flag */
        if (demod_bits == HDLC_FLAG)
        {
-               if (!fifo_isfull_locked(&rx_fifo))
+               if (!fifo_isfull(&rx_fifo))
                {
                        fifo_push(&rx_fifo, HDLC_FLAG);
                        hdlc_rxstart = true;
                }
                else
                        hdlc_rxstart = false;
+
                hdlc_currchar = 0;
                hdlc_bit_idx = 0;
                return;
@@ -202,13 +205,15 @@ static void hdlc_parse(bool bit)
        {
                if ((hdlc_currchar == HDLC_FLAG
                        || hdlc_currchar == HDLC_RESET
-                       || hdlc_currchar == AFSK_ESC)
-                       && !fifo_isfull_locked(&rx_fifo))
-                       fifo_push(&rx_fifo, AFSK_ESC);
-               else
-                       hdlc_rxstart = false;
+                       || hdlc_currchar == AX25_ESC))
+               {
+                       if (!fifo_isfull(&rx_fifo))
+                               fifo_push(&rx_fifo, AX25_ESC);
+                       else
+                               hdlc_rxstart = false;
+               }
 
-               if (!fifo_isfull_locked(&rx_fifo))
+               if (!fifo_isfull(&rx_fifo))
                        fifo_push(&rx_fifo, hdlc_currchar);
                else
                        hdlc_rxstart = false;
@@ -236,23 +241,38 @@ DEFINE_AFSK_ADC_ISR()
 
        /*
         * Frequency discrimination is achieved by simply multiplying
-        * the sample with a delayed sample of (bits per sample) / 2.
-        * Then the signal is lowpass filtered with a first order, 600 Hz
-        * Butterworth filter.
+        * the sample with a delayed sample of (samples per bit) / 2.
+        * Then the signal is lowpass filtered with a first order,
+        * 600 Hz filter. The filter implementation is selectable
+        * through the CONFIG_AFSK_FILTER config variable.
         */
 
        iir_x[0] = iir_x[1];
-       iir_x[1] = ((int8_t)fifo_pop(&delay_fifo) * curr_sample) >> 2;
+
+       #if (CONFIG_AFSK_FILTER == AFSK_BUTTERWORTH) || (CONFIG_AFSK_FILTER == AFSK_CHEBYSHEV)
+               iir_x[1] = ((int8_t)fifo_pop(&delay_fifo) * curr_sample) >> 2;
+       #else
+               #error Filter type not found!
+       #endif
+
        iir_y[0] = iir_y[1];
 
-       /*
-        * This strange sum + shift is an optimization for 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);
+       #if CONFIG_AFSK_FILTER == AFSK_BUTTERWORTH
+               /*
+                * This strange sum + shift is an optimization for 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);
+       #elif CONFIG_AFSK_FILTER == AFSK_CHEBYSHEV
+               /*
+                * This should be (iir_y[0] * 0.438) but
+                * (iir_y[0] >> 1) is a faster approximation :-)
+                */
+               iir_y[1] = iir_x[0] + iir_x[1] + (iir_y[0] >> 1);
+       #endif
 
        /* Save this sampled bit in a delay line */
        sampled_bits <<= 1;
@@ -292,7 +312,9 @@ DEFINE_AFSK_ADC_ISR()
                hdlc_parse(!EDGE_FOUND(found_bits));
        }
 
+
        AFSK_STROBE_OFF();
+       AFSK_ADC_IRQ_END();
 }
 
 /* True while modem sends data */
@@ -326,6 +348,7 @@ DEFINE_AFSK_DAC_ISR()
                        {
                                AFSK_DAC_IRQ_STOP();
                                sending = false;
+                               AFSK_DAC_IRQ_END();
                                return;
                        }
                        else
@@ -341,12 +364,13 @@ DEFINE_AFSK_DAC_ISR()
                                curr_out = fifo_pop(&tx_fifo);
 
                                /* Handle char escape */
-                               if (curr_out == AFSK_ESC)
+                               if (curr_out == AX25_ESC)
                                {
                                        if (fifo_isempty(&tx_fifo))
                                        {
                                                AFSK_DAC_IRQ_STOP();
                                                sending = false;
+                                               AFSK_DAC_IRQ_END();
                                                return;
                                        }
                                        else
@@ -406,6 +430,7 @@ DEFINE_AFSK_DAC_ISR()
 
        AFSK_SET_DAC(sin_sample(phase_acc));
        sample_count--;
+       AFSK_DAC_IRQ_END();
 }
 
 
@@ -423,7 +448,7 @@ static size_t afsk_read(UNUSED_ARG(KFile *, fd), void *_buf, size_t size)
                ticks_t start = timer_clock();
                #endif
 
-               do
+               while (fifo_isempty_locked(&rx_fifo));
                {
                        cpu_relax();
                        #if CONFIG_AFSK_RXTIMEOUT != -1
@@ -431,7 +456,6 @@ static size_t afsk_read(UNUSED_ARG(KFile *, fd), void *_buf, size_t size)
                                return buf - (uint8_t *)_buf;
                        #endif
                }
-               while (fifo_isempty_locked(&rx_fifo));
 
                *buf++ = fifo_pop_locked(&rx_fifo);
        }
@@ -479,6 +503,7 @@ void afsk_init(Afsk *af)
        fifo_init(&tx_fifo, tx_buf, sizeof(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));