afsk.c

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