afsk.c

Go to the documentation of this file.
00001 
00039 #include "afsk.h"
00040 #include <net/ax25.h>
00041 
00042 #include "cfg/cfg_afsk.h"
00043 #include "hw/hw_afsk.h"
00044 
00045 #include <drv/timer.h>
00046 
00047 #include <cfg/module.h>
00048 
00049 #define LOG_LEVEL   AFSK_LOG_LEVEL
00050 #define LOG_FORMAT  AFSK_LOG_FORMAT
00051 #include <cfg/log.h>
00052 
00053 #include <cpu/power.h>
00054 #include <cpu/pgm.h>
00055 #include <struct/fifobuf.h>
00056 
00057 #include <string.h> /* memset */
00058 
00059 #define PHASE_BIT    8
00060 #define PHASE_INC    1
00061 
00062 #define PHASE_MAX    (SAMPLEPERBIT * PHASE_BIT)
00063 #define PHASE_THRES  (PHASE_MAX / 2) // - PHASE_BIT / 2)
00064 
00065 // Modulator constants
00066 #define MARK_FREQ  1200
00067 #define MARK_INC   (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)MARK_FREQ, CONFIG_AFSK_DAC_SAMPLERATE))
00068 
00069 #define SPACE_FREQ 2200
00070 #define SPACE_INC  (uint16_t)(DIV_ROUND(SIN_LEN * (uint32_t)SPACE_FREQ, CONFIG_AFSK_DAC_SAMPLERATE))
00071 
00072 //Ensure sample rate is a multiple of bit rate
00073 STATIC_ASSERT(!(CONFIG_AFSK_DAC_SAMPLERATE % BITRATE));
00074 
00075 #define DAC_SAMPLEPERBIT (CONFIG_AFSK_DAC_SAMPLERATE / BITRATE)
00076 
00082 static const uint8_t PROGMEM sin_table[] =
00083 {
00084     128, 129, 131, 132, 134, 135, 137, 138, 140, 142, 143, 145, 146, 148, 149, 151,
00085     152, 154, 155, 157, 158, 160, 162, 163, 165, 166, 167, 169, 170, 172, 173, 175,
00086     176, 178, 179, 181, 182, 183, 185, 186, 188, 189, 190, 192, 193, 194, 196, 197,
00087     198, 200, 201, 202, 203, 205, 206, 207, 208, 210, 211, 212, 213, 214, 215, 217,
00088     218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233,
00089     234, 234, 235, 236, 237, 238, 238, 239, 240, 241, 241, 242, 243, 243, 244, 245,
00090     245, 246, 246, 247, 248, 248, 249, 249, 250, 250, 250, 251, 251, 252, 252, 252,
00091     253, 253, 253, 253, 254, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255,
00092 };
00093 
00094 #define SIN_LEN 512 
00095 
00096 STATIC_ASSERT(sizeof(sin_table) == SIN_LEN / 4);
00097 
00098 
00103 INLINE uint8_t sin_sample(uint16_t idx)
00104 {
00105     ASSERT(idx < SIN_LEN);
00106     uint16_t new_idx = idx % (SIN_LEN / 2);
00107     new_idx = (new_idx >= (SIN_LEN / 4)) ? (SIN_LEN / 2 - new_idx - 1) : new_idx;
00108 
00109     #if CPU_HARVARD
00110         uint8_t data = pgm_read_char(&sin_table[new_idx]);
00111     #else
00112         uint8_t data = sin_table[new_idx];
00113     #endif
00114 
00115     return (idx >= (SIN_LEN / 2)) ? (255 - data) : data;
00116 }
00117 
00118 
00119 #define BIT_DIFFER(bitline1, bitline2) (((bitline1) ^ (bitline2)) & 0x01)
00120 #define EDGE_FOUND(bitline)            BIT_DIFFER((bitline), (bitline) >> 1)
00121 
00132 static bool hdlc_parse(Hdlc *hdlc, bool bit, FIFOBuffer *fifo)
00133 {
00134     bool ret = true;
00135 
00136     hdlc->demod_bits <<= 1;
00137     hdlc->demod_bits |= bit ? 1 : 0;
00138 
00139     /* HDLC Flag */
00140     if (hdlc->demod_bits == HDLC_FLAG)
00141     {
00142         if (!fifo_isfull(fifo))
00143         {
00144             fifo_push(fifo, HDLC_FLAG);
00145             hdlc->rxstart = true;
00146         }
00147         else
00148         {
00149             ret = false;
00150             hdlc->rxstart = false;
00151         }
00152 
00153         hdlc->currchar = 0;
00154         hdlc->bit_idx = 0;
00155         return ret;
00156     }
00157 
00158     /* Reset */
00159     if ((hdlc->demod_bits & HDLC_RESET) == HDLC_RESET)
00160     {
00161         hdlc->rxstart = false;
00162         return ret;
00163     }
00164 
00165     if (!hdlc->rxstart)
00166         return ret;
00167 
00168     /* Stuffed bit */
00169     if ((hdlc->demod_bits & 0x3f) == 0x3e)
00170         return ret;
00171 
00172     if (hdlc->demod_bits & 0x01)
00173         hdlc->currchar |= 0x80;
00174 
00175     if (++hdlc->bit_idx >= 8)
00176     {
00177         if ((hdlc->currchar == HDLC_FLAG
00178             || hdlc->currchar == HDLC_RESET
00179             || hdlc->currchar == AX25_ESC))
00180         {
00181             if (!fifo_isfull(fifo))
00182                 fifo_push(fifo, AX25_ESC);
00183             else
00184             {
00185                 hdlc->rxstart = false;
00186                 ret = false;
00187             }
00188         }
00189 
00190         if (!fifo_isfull(fifo))
00191             fifo_push(fifo, hdlc->currchar);
00192         else
00193         {
00194             hdlc->rxstart = false;
00195             ret = false;
00196         }
00197 
00198         hdlc->currchar = 0;
00199         hdlc->bit_idx = 0;
00200     }
00201     else
00202         hdlc->currchar >>= 1;
00203 
00204     return ret;
00205 }
00206 
00207 
00215 void afsk_adc_isr(Afsk *af, int8_t curr_sample)
00216 {
00217     AFSK_STROBE_ON();
00218 
00219     /*
00220      * Frequency discriminator and LP IIR filter.
00221      * This filter is designed to work
00222      * at the given sample rate and bit rate.
00223      */
00224     STATIC_ASSERT(SAMPLERATE == 9600);
00225     STATIC_ASSERT(BITRATE == 1200);
00226 
00227     /*
00228      * Frequency discrimination is achieved by simply multiplying
00229      * the sample with a delayed sample of (samples per bit) / 2.
00230      * Then the signal is lowpass filtered with a first order,
00231      * 600 Hz filter. The filter implementation is selectable
00232      * through the CONFIG_AFSK_FILTER config variable.
00233      */
00234 
00235     af->iir_x[0] = af->iir_x[1];
00236 
00237     #if (CONFIG_AFSK_FILTER == AFSK_BUTTERWORTH)
00238         af->iir_x[1] = ((int8_t)fifo_pop(&af->delay_fifo) * curr_sample) >> 2;
00239         //af->iir_x[1] = ((int8_t)fifo_pop(&af->delay_fifo) * curr_sample) / 6.027339492;
00240     #elif (CONFIG_AFSK_FILTER == AFSK_CHEBYSHEV)
00241         af->iir_x[1] = ((int8_t)fifo_pop(&af->delay_fifo) * curr_sample) >> 2;
00242         //af->iir_x[1] = ((int8_t)fifo_pop(&af->delay_fifo) * curr_sample) / 3.558147322;
00243     #else
00244         #error Filter type not found!
00245     #endif
00246 
00247     af->iir_y[0] = af->iir_y[1];
00248 
00249     #if CONFIG_AFSK_FILTER == AFSK_BUTTERWORTH
00250         /*
00251          * This strange sum + shift is an optimization for af->iir_y[0] * 0.668.
00252          * iir * 0.668 ~= (iir * 21) / 32 =
00253          * = (iir * 16) / 32 + (iir * 4) / 32 + iir / 32 =
00254          * = iir / 2 + iir / 8 + iir / 32 =
00255          * = iir >> 1 + iir >> 3 + iir >> 5
00256          */
00257         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);
00258         //af->iir_y[1] = af->iir_x[0] + af->iir_x[1] + af->iir_y[0] * 0.6681786379;
00259     #elif CONFIG_AFSK_FILTER == AFSK_CHEBYSHEV
00260         /*
00261          * This should be (af->iir_y[0] * 0.438) but
00262          * (af->iir_y[0] >> 1) is a faster approximation :-)
00263          */
00264         af->iir_y[1] = af->iir_x[0] + af->iir_x[1] + (af->iir_y[0] >> 1);
00265         //af->iir_y[1] = af->iir_x[0] + af->iir_x[1] + af->iir_y[0] * 0.4379097269;
00266     #endif
00267 
00268     /* Save this sampled bit in a delay line */
00269     af->sampled_bits <<= 1;
00270     af->sampled_bits |= (af->iir_y[1] > 0) ? 1 : 0;
00271 
00272     /* Store current ADC sample in the af->delay_fifo */
00273     fifo_push(&af->delay_fifo, curr_sample);
00274 
00275     /* If there is an edge, adjust phase sampling */
00276     if (EDGE_FOUND(af->sampled_bits))
00277     {
00278         if (af->curr_phase < PHASE_THRES)
00279             af->curr_phase += PHASE_INC;
00280         else
00281             af->curr_phase -= PHASE_INC;
00282     }
00283     af->curr_phase += PHASE_BIT;
00284 
00285     /* sample the bit */
00286     if (af->curr_phase >= PHASE_MAX)
00287     {
00288         af->curr_phase %= PHASE_MAX;
00289 
00290         /* Shift 1 position in the shift register of the found bits */
00291         af->found_bits <<= 1;
00292 
00293         /*
00294          * Determine bit value by reading the last 3 sampled bits.
00295          * If the number of ones is two or greater, the bit value is a 1,
00296          * otherwise is a 0.
00297          * This algorithm presumes that there are 8 samples per bit.
00298          */
00299         STATIC_ASSERT(SAMPLEPERBIT == 8);
00300         uint8_t bits = af->sampled_bits & 0x07;
00301         if (bits == 0x07 // 111, 3 bits set to 1
00302          || bits == 0x06 // 110, 2 bits
00303          || bits == 0x05 // 101, 2 bits
00304          || bits == 0x03 // 011, 2 bits
00305         )
00306             af->found_bits |= 1;
00307 
00308         /*
00309          * NRZI coding: if 2 consecutive bits have the same value
00310          * a 1 is received, otherwise it's a 0.
00311          */
00312         if (!hdlc_parse(&af->hdlc, !EDGE_FOUND(af->found_bits), &af->rx_fifo))
00313             af->status |= AFSK_RXFIFO_OVERRUN;
00314     }
00315 
00316 
00317     AFSK_STROBE_OFF();
00318 }
00319 
00320 static void afsk_txStart(Afsk *af)
00321 {
00322     if (!af->sending)
00323     {
00324         af->phase_inc = MARK_INC;
00325         af->phase_acc = 0;
00326         af->stuff_cnt = 0;
00327         af->sending = true;
00328         af->preamble_len = DIV_ROUND(CONFIG_AFSK_PREAMBLE_LEN * BITRATE, 8000);
00329         AFSK_DAC_IRQ_START(af->dac_ch);
00330     }
00331     ATOMIC(af->trailer_len  = DIV_ROUND(CONFIG_AFSK_TRAILER_LEN  * BITRATE, 8000));
00332 }
00333 
00334 #define BIT_STUFF_LEN 5
00335 
00336 #define SWITCH_TONE(inc)  (((inc) == MARK_INC) ? SPACE_INC : MARK_INC)
00337 
00347 uint8_t afsk_dac_isr(Afsk *af)
00348 {
00349     AFSK_STROBE_ON();
00350 
00351     /* Check if we are at a start of a sample cycle */
00352     if (af->sample_count == 0)
00353     {
00354         if (af->tx_bit == 0)
00355         {
00356             /* We have just finished transimitting a char, get a new one. */
00357             if (fifo_isempty(&af->tx_fifo) && af->trailer_len == 0)
00358             {
00359                 AFSK_DAC_IRQ_STOP(af->dac_ch);
00360                 af->sending = false;
00361                 AFSK_STROBE_OFF();
00362                 return 0;
00363             }
00364             else
00365             {
00366                 /*
00367                  * If we have just finished sending an unstuffed byte,
00368                  * reset bitstuff counter.
00369                  */
00370                 if (!af->bit_stuff)
00371                     af->stuff_cnt = 0;
00372 
00373                 af->bit_stuff = true;
00374 
00375                 /*
00376                  * Handle preamble and trailer
00377                  */
00378                 if (af->preamble_len == 0)
00379                 {
00380                     if (fifo_isempty(&af->tx_fifo))
00381                     {
00382                         af->trailer_len--;
00383                         af->curr_out = HDLC_FLAG;
00384                     }
00385                     else
00386                         af->curr_out = fifo_pop(&af->tx_fifo);
00387                 }
00388                 else
00389                 {
00390                     af->preamble_len--;
00391                     af->curr_out = HDLC_FLAG;
00392                 }
00393 
00394                 /* Handle char escape */
00395                 if (af->curr_out == AX25_ESC)
00396                 {
00397                     if (fifo_isempty(&af->tx_fifo))
00398                     {
00399                         AFSK_DAC_IRQ_STOP(af->dac_ch);
00400                         af->sending = false;
00401                         AFSK_STROBE_OFF();
00402                         return 0;
00403                     }
00404                     else
00405                         af->curr_out = fifo_pop(&af->tx_fifo);
00406                 }
00407                 else if (af->curr_out == HDLC_FLAG || af->curr_out == HDLC_RESET)
00408                     /* If these chars are not escaped disable bit stuffing */
00409                     af->bit_stuff = false;
00410             }
00411             /* Start with LSB mask */
00412             af->tx_bit = 0x01;
00413         }
00414 
00415         /* check for bit stuffing */
00416         if (af->bit_stuff && af->stuff_cnt >= BIT_STUFF_LEN)
00417         {
00418             /* If there are more than 5 ones in a row insert a 0 */
00419             af->stuff_cnt = 0;
00420             /* switch tone */
00421             af->phase_inc = SWITCH_TONE(af->phase_inc);
00422         }
00423         else
00424         {
00425             /*
00426              * NRZI: if we want to transmit a 1 the modulated frequency will stay
00427              * unchanged; with a 0, there will be a change in the tone.
00428              */
00429             if (af->curr_out & af->tx_bit)
00430             {
00431                 /*
00432                  * Transmit a 1:
00433                  * - Stay on the previous tone
00434                  * - Increase bit stuff counter
00435                  */
00436                 af->stuff_cnt++;
00437             }
00438             else
00439             {
00440                 /*
00441                  * Transmit a 0:
00442                  * - Reset bit stuff counter
00443                  * - Switch tone
00444                  */
00445                 af->stuff_cnt = 0;
00446                 af->phase_inc = SWITCH_TONE(af->phase_inc);
00447             }
00448 
00449             /* Go to the next bit */
00450             af->tx_bit <<= 1;
00451         }
00452         af->sample_count = DAC_SAMPLEPERBIT;
00453     }
00454 
00455     /* Get new sample and put it out on the DAC */
00456     af->phase_acc += af->phase_inc;
00457     af->phase_acc %= SIN_LEN;
00458 
00459     af->sample_count--;
00460     AFSK_STROBE_OFF();
00461     return sin_sample(af->phase_acc);
00462 }
00463 
00464 
00465 static size_t afsk_read(KFile *fd, void *_buf, size_t size)
00466 {
00467     Afsk *af = AFSK_CAST(fd);
00468     uint8_t *buf = (uint8_t *)_buf;
00469 
00470     #if CONFIG_AFSK_RXTIMEOUT == 0
00471     while (size-- && !fifo_isempty_locked(&af->rx_fifo))
00472     #else
00473     while (size--)
00474     #endif
00475     {
00476         #if CONFIG_AFSK_RXTIMEOUT != -1
00477         ticks_t start = timer_clock();
00478         #endif
00479 
00480         while (fifo_isempty_locked(&af->rx_fifo));
00481         {
00482             cpu_relax();
00483             #if CONFIG_AFSK_RXTIMEOUT != -1
00484             if (timer_clock() - start > ms_to_ticks(CONFIG_AFSK_RXTIMEOUT))
00485                 return buf - (uint8_t *)_buf;
00486             #endif
00487         }
00488 
00489         *buf++ = fifo_pop_locked(&af->rx_fifo);
00490     }
00491 
00492     return buf - (uint8_t *)_buf;
00493 }
00494 
00495 static size_t afsk_write(KFile *fd, const void *_buf, size_t size)
00496 {
00497     Afsk *af = AFSK_CAST(fd);
00498     const uint8_t *buf = (const uint8_t *)_buf;
00499 
00500     while (size--)
00501     {
00502         while (fifo_isfull_locked(&af->tx_fifo))
00503             cpu_relax();
00504 
00505         fifo_push_locked(&af->tx_fifo, *buf++);
00506         afsk_txStart(af);
00507     }
00508 
00509     return buf - (const uint8_t *)_buf;
00510 }
00511 
00512 static int afsk_flush(KFile *fd)
00513 {
00514     Afsk *af = AFSK_CAST(fd);
00515     while (af->sending)
00516         cpu_relax();
00517     return 0;
00518 }
00519 
00520 static int afsk_error(KFile *fd)
00521 {
00522     Afsk *af = AFSK_CAST(fd);
00523     int err;
00524 
00525     ATOMIC(err = af->status);
00526     return err;
00527 }
00528 
00529 static void afsk_clearerr(KFile *fd)
00530 {
00531     Afsk *af = AFSK_CAST(fd);
00532     ATOMIC(af->status = 0);
00533 }
00534 
00535 
00542 void afsk_init(Afsk *af, int adc_ch, int dac_ch)
00543 {
00544     #if CONFIG_AFSK_RXTIMEOUT != -1
00545     MOD_CHECK(timer);
00546     #endif
00547     memset(af, 0, sizeof(*af));
00548     af->adc_ch = adc_ch;
00549     af->dac_ch = dac_ch;
00550 
00551     fifo_init(&af->delay_fifo, (uint8_t *)af->delay_buf, sizeof(af->delay_buf));
00552     fifo_init(&af->rx_fifo, af->rx_buf, sizeof(af->rx_buf));
00553 
00554     /* Fill sample FIFO with 0 */
00555     for (int i = 0; i < SAMPLEPERBIT / 2; i++)
00556         fifo_push(&af->delay_fifo, 0);
00557 
00558     fifo_init(&af->tx_fifo, af->tx_buf, sizeof(af->tx_buf));
00559 
00560     AFSK_ADC_INIT(adc_ch, af);
00561     AFSK_DAC_INIT(dac_ch, af);
00562     AFSK_STROBE_INIT();
00563     LOG_INFO("MARK_INC %d, SPACE_INC %d\n", MARK_INC, SPACE_INC);
00564 
00565     DB(af->fd._type = KFT_AFSK);
00566     af->fd.write = afsk_write;
00567     af->fd.read = afsk_read;
00568     af->fd.flush = afsk_flush;
00569     af->fd.error = afsk_error;
00570     af->fd.clearerr = afsk_clearerr;
00571     af->phase_inc = MARK_INC;
00572 }