Fix doc.
[bertos.git] / bertos / net / afsk.c
index f8f29f9da395df7b525ab1cd8327e3d514a12ba9..2b7fe0bedaa5df37b4e18e8f6283cae1f13e2073 100644 (file)
 
 #include <cfg/module.h>
 
+#define LOG_LEVEL   AFSK_LOG_LEVEL
+#define LOG_FORMAT  AFSK_LOG_FORMAT
+#include <cfg/log.h>
+
 #include <cpu/power.h>
+#include <cpu/pgm.h>
 #include <struct/fifobuf.h>
 
 #include <string.h> /* memset */
@@ -74,9 +79,8 @@ STATIC_ASSERT(!(CONFIG_AFSK_DAC_SAMPLERATE % BITRATE));
  * The rest of the wave is computed from this first quarter.
  * This table is used to generate the modulated data.
  */
-static const uint8_t sin_table[] =
+static const uint8_t PROGMEM sin_table[] =
 {
-       //TODO put in flash!
        128, 129, 131, 132, 134, 135, 137, 138, 140, 142, 143, 145, 146, 148, 149, 151,
        152, 154, 155, 157, 158, 160, 162, 163, 165, 166, 167, 169, 170, 172, 173, 175,
        176, 178, 179, 181, 182, 183, 185, 186, 188, 189, 190, 192, 193, 194, 196, 197,
@@ -101,16 +105,34 @@ INLINE uint8_t sin_sample(uint16_t idx)
        ASSERT(idx < SIN_LEN);
        uint16_t new_idx = idx % (SIN_LEN / 2);
        new_idx = (new_idx >= (SIN_LEN / 4)) ? (SIN_LEN / 2 - new_idx - 1) : new_idx;
-       return (idx >= (SIN_LEN / 2)) ? (255 - sin_table[new_idx]) : sin_table[new_idx];
+
+       #if CPU_HARVARD
+               uint8_t data = pgm_read_char(&sin_table[new_idx]);
+       #else
+               uint8_t data = sin_table[new_idx];
+       #endif
+
+       return (idx >= (SIN_LEN / 2)) ? (255 - data) : data;
 }
 
 
 #define BIT_DIFFER(bitline1, bitline2) (((bitline1) ^ (bitline2)) & 0x01)
 #define EDGE_FOUND(bitline)            BIT_DIFFER((bitline), (bitline) >> 1)
 
-
-static void hdlc_parse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
+/**
+ * High-Level Data Link Control parsing function.
+ * Parse bitstream in order to find characters.
+ *
+ * \param hdlc HDLC context.
+ * \param bit  current bit to be parsed.
+ * \param fifo FIFO buffer used to push characters.
+ *
+ * \return true if all is ok, false if the fifo is full.
+ */
+static bool hdlc_parse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
 {
+       bool ret = true;
+
        hdlc->demod_bits <<= 1;
        hdlc->demod_bits |= bit ? 1 : 0;
 
@@ -123,26 +145,29 @@ static void hdlc_parse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
                        hdlc->rxstart = true;
                }
                else
+               {
+                       ret = false;
                        hdlc->rxstart = false;
+               }
 
                hdlc->currchar = 0;
                hdlc->bit_idx = 0;
-               return;
+               return ret;
        }
 
        /* Reset */
        if ((hdlc->demod_bits & HDLC_RESET) == HDLC_RESET)
        {
                hdlc->rxstart = false;
-               return;
+               return ret;
        }
 
        if (!hdlc->rxstart)
-               return;
+               return ret;
 
        /* Stuffed bit */
        if ((hdlc->demod_bits & 0x3f) == 0x3e)
-               return;
+               return ret;
 
        if (hdlc->demod_bits & 0x01)
                hdlc->currchar |= 0x80;
@@ -156,20 +181,27 @@ static void hdlc_parse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
                        if (!fifo_isfull(fifo))
                                fifo_push(fifo, AX25_ESC);
                        else
+                       {
                                hdlc->rxstart = false;
+                               ret = false;
+                       }
                }
 
                if (!fifo_isfull(fifo))
                        fifo_push(fifo, hdlc->currchar);
                else
+               {
                        hdlc->rxstart = false;
+                       ret = false;
+               }
 
                hdlc->currchar = 0;
                hdlc->bit_idx = 0;
-               return;
        }
+       else
+               hdlc->currchar >>= 1;
 
-       hdlc->currchar >>= 1;
+       return ret;
 }
 
 
@@ -177,7 +209,7 @@ static void hdlc_parse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
  * ADC ISR callback.
  * This function has to be called by the ADC ISR when a sample of the configured
  * channel is available.
- * \param af Afsk context to operate one (\see Afsk).
+ * \param af Afsk context to operate on.
  * \param curr_sample current sample from the ADC.
  */
 void afsk_adc_isr(Afsk *af, int8_t curr_sample)
@@ -277,7 +309,8 @@ void afsk_adc_isr(Afsk *af, int8_t curr_sample)
                 * NRZI coding: if 2 consecutive bits have the same value
                 * a 1 is received, otherwise it's a 0.
                 */
-               hdlc_parse(&af->hdlc, !EDGE_FOUND(af->found_bits), &af->rx_fifo);
+               if (!hdlc_parse(&af->hdlc, !EDGE_FOUND(af->found_bits), &af->rx_fifo))
+                       af->status |= AFSK_RXFIFO_OVERRUN;
        }
 
 
@@ -307,13 +340,14 @@ static void afsk_txStart(Afsk *af)
  * This function has to be called by the DAC ISR when a sample of the configured
  * channel has been converted out.
  *
- * \param af Afsk context to operate one (\see Afsk).
+ * \param af Afsk context to operate on.
  *
- * \note The next DAC output sample is supplied by the Afsk driver through calling
- *        the AFSK_DAC_SET() callback.
+ * \return The next DAC output sample.
  */
-void afsk_dac_isr(Afsk *af)
+uint8_t afsk_dac_isr(Afsk *af)
 {
+       AFSK_STROBE_ON();
+
        /* Check if we are at a start of a sample cycle */
        if (af->sample_count == 0)
        {
@@ -324,12 +358,13 @@ void afsk_dac_isr(Afsk *af)
                        {
                                AFSK_DAC_IRQ_STOP(af->dac_ch);
                                af->sending = false;
-                               return;
+                               AFSK_STROBE_OFF();
+                               return 0;
                        }
                        else
                        {
                                /*
-                                * If we have just finished af->sending an unstuffed byte,
+                                * If we have just finished sending an unstuffed byte,
                                 * reset bitstuff counter.
                                 */
                                if (!af->bit_stuff)
@@ -363,7 +398,8 @@ void afsk_dac_isr(Afsk *af)
                                        {
                                                AFSK_DAC_IRQ_STOP(af->dac_ch);
                                                af->sending = false;
-                                               return;
+                                               AFSK_STROBE_OFF();
+                                               return 0;
                                        }
                                        else
                                                af->curr_out = fifo_pop(&af->tx_fifo);
@@ -395,7 +431,7 @@ void afsk_dac_isr(Afsk *af)
                                /*
                                 * Transmit a 1:
                                 * - Stay on the previous tone
-                                * - Increace bit stuff count
+                                * - Increase bit stuff counter
                                 */
                                af->stuff_cnt++;
                        }
@@ -403,7 +439,7 @@ void afsk_dac_isr(Afsk *af)
                        {
                                /*
                                 * Transmit a 0:
-                                * - Reset bit stuff count
+                                * - Reset bit stuff counter
                                 * - Switch tone
                                 */
                                af->stuff_cnt = 0;
@@ -420,8 +456,9 @@ void afsk_dac_isr(Afsk *af)
        af->phase_acc += af->phase_inc;
        af->phase_acc %= SIN_LEN;
 
-       AFSK_DAC_SET(af->dac_ch, sin_sample(af->phase_acc));
        af->sample_count--;
+       AFSK_STROBE_OFF();
+       return sin_sample(af->phase_acc);
 }
 
 
@@ -480,10 +517,25 @@ static int afsk_flush(KFile *fd)
        return 0;
 }
 
+static int afsk_error(KFile *fd)
+{
+       Afsk *af = AFSK_CAST(fd);
+       int err;
+
+       ATOMIC(err = af->status);
+       return err;
+}
+
+static void afsk_clearerr(KFile *fd)
+{
+       Afsk *af = AFSK_CAST(fd);
+       ATOMIC(af->status = 0);
+}
+
 
 /**
  * Initialize an AFSK1200 modem.
- * \param af Afsk context to operate one (\see Afsk).
+ * \param af Afsk context to operate on.
  * \param adc_ch  ADC channel used by the demodulator.
  * \param dac_ch  DAC channel used by the modulator.
  */
@@ -508,11 +560,13 @@ void afsk_init(Afsk *af, int adc_ch, int dac_ch)
        AFSK_ADC_INIT(adc_ch, af);
        AFSK_DAC_INIT(dac_ch, af);
        AFSK_STROBE_INIT();
-       kprintf("MARK_INC %d, SPACE_INC %d\n", MARK_INC, SPACE_INC);
+       LOG_INFO("MARK_INC %d, SPACE_INC %d\n", MARK_INC, SPACE_INC);
 
        DB(af->fd._type = KFT_AFSK);
        af->fd.write = afsk_write;
        af->fd.read = afsk_read;
        af->fd.flush = afsk_flush;
+       af->fd.error = afsk_error;
+       af->fd.clearerr = afsk_clearerr;
        af->phase_inc = MARK_INC;
 }