AD9857 IQ DDS Digital Up Converter Experiment using Nucleo F401
Digital Signal Processing for IQ Quadradure Modulation DDS AD9857 using Nucleo F401.
see http://ttrftech.tumblr.com/post/114310226891/
dsp.cpp
- Committer:
- edy555
- Date:
- 2015-03-23
- Revision:
- 6:ed82052bd505
- Parent:
- 5:75c26157a53a
File content as of revision 6:ed82052bd505:
#include "mbed.h" #include "dsp.h" extern Serial pc; int16_t htstat_buf[HILBERT_TRANSFORM_FIRSTATE_LENGTH]; int16_t cap_buf[2][CAPTURE_LEN]; int16_t fir_state[FIRSTATE_LENGTH]; int16_t fir_buf[CAPTURE_LEN]; int16_t cic_buf[CICBUF_LEN]; int16_t dma_buf[2][DMA_DATALEN]; CICState cic; void cic_interpolate_x10(CICState *cic, uint32_t *src, int src_len, uint32_t *dst) { uint32_t p0 = cic->p0; uint32_t s0 = cic->s0; int i; int j = 0; for (i = 0; i < src_len; i++) { uint32_t s = src[i]; uint32_t d0 = __QSUB16(s, p0); s0 = __QADD16(s0, d0); uint32_t s1 = __QADD16(s0, d0); uint32_t s2 = __QADD16(s1, d0); uint32_t s3 = __QADD16(s2, d0); uint32_t s4 = __QADD16(s3, d0); dst[j ] = s0 >> 2; dst[j+1] = s1 >> 2; dst[j+2] = s2 >> 2; dst[j+3] = s3 >> 2; dst[j+4] = s4 >> 2; j += 5; s0 = s4; s0 = __QADD16(s0, d0); s1 = __QADD16(s0, d0); s2 = __QADD16(s1, d0); s3 = __QADD16(s2, d0); s4 = __QADD16(s3, d0); dst[j ] = s0 >> 2; dst[j+1] = s1 >> 2; dst[j+2] = s2 >> 2; dst[j+3] = s3 >> 2; dst[j+4] = s4 >> 2; j += 5; s0 = s4; p0 = s; } cic->s0 = s0; cic->p0 = p0; } const int16_t fir_coeff[8][16] = { { -19, -6, 102, -22, -357, 264, 1798, 2064, 630, -337, -119, 111, 15, -24, 0, 0}, { -13, -20, 76, 51, -311, -29, 1441, 2206, 1037, -231, -223, 96, 45, -25, -6, 0}, { -6, -25, 45, 96, -223, -231, 1037, 2206, 1441, -29, -311, 51, 76, -20, -13, 0}, { 0, -24, 15, 111, -119, -337, 630, 2064, 1798, 264, -357, -22, 102, -6, -19, 0}, { 0, -19, -6, 102, -22, -357, 264, 1798, 2064, 630, -337, -119, 111, 15, -24, 0}, { 0, -13, -20, 76, 51, -311, -29, 1441, 2206, 1037, -231, -223, 96, 45, -25, -6}, { 0, -6, -25, 45, 96, -223, -231, 1037, 2206, 1441, -29, -311, 51, 76, -20, -13}, { 0, 0, -24, 15, 111, -119, -337, 630, 2064, 1798, 264, -357, -22, 102, -6, -19} }; void fir_resample_x4(uint32_t *src_state, uint32_t *dst, int dst_len) { uint32_t *src = src_state; int index = 0; int i; for (i = 0; i < dst_len; i++) { uint32_t *kp = (uint32_t*)fir_coeff[index]; uint32_t acc_i = 0; uint32_t acc_q = 0; // 8cycle x 8 #define CELL(n) do { \ uint32_t k = kp[n]; \ uint32_t p0 = src[n*2]; \ uint32_t p1 = src[n*2+1]; \ uint32_t i01 = __PKHTB(p1, p0, 16); \ uint32_t q01 = __PKHBT(p0, p1, 16); \ acc_i = __SMLAD(k, i01, acc_i); \ acc_q = __SMLAD(k, q01, acc_q); \ } while(0) CELL(0); CELL(1); CELL(2); CELL(3); CELL(4); CELL(5); CELL(6); CELL(7); *dst++ = __PKHTB(__SSAT16(acc_i, 16), __SSAT16(acc_q, 16), 16); index++; if (index >= 8) { index = 0; src += 2; } } for (i = 0; i < FIRSTATE_LENGTH/2; i++) *src_state++ = *src++; } void interpolate_test() { int freq = 1000; int ampl = 3000; int rate = 48000; for (int i = 0; i < CAPTURE_LEN; i++){ cap_buf[0][i*2] = sin(2*3.141592 * i * freq / rate) * ampl; // Lch cap_buf[0][i*2+1] = cos(2*3.141592 * i * freq / rate) * ampl; // Rch } #if 0 for (int i = 0; i < 48; i++){ pc.printf("%d, ", cap_buf[i*2]); } pc.printf("\n\r"); #endif fir_resample_x4((uint32_t *)&cap_buf[0], (uint32_t*)&cic_buf, CICBUF_LEN); cic_interpolate_x10(&cic, (uint32_t*)&cic_buf, CICBUF_LEN, (uint32_t*)dma_buf[0]); fir_resample_x4((uint32_t *)&cap_buf[0], (uint32_t*)&cic_buf, CICBUF_LEN); cic_interpolate_x10(&cic, (uint32_t*)&cic_buf, CICBUF_LEN, (uint32_t*)dma_buf[0]); #if 0 for (int i = 0; i < 48*25/4; i++){ pc.printf("%d, ", cic_buf[i*2]); } pc.printf("\n\r"); #endif #if 0 for (int i = DMA_DATALEN/2-400; i < DMA_DATALEN/2; i++){ pc.printf("%d, ", dma_buf[i*2]); } pc.printf("\n\r"); for (int i = 0; i < 400; i++){ pc.printf("%d, ", dma_buf[i*2]); } pc.printf("\n\r"); #endif } // hilbert transform by 127 taps fir int16_t hilbert127_fir_coeff[32] = { 20848, 6917, 4112, 2897, 2212, 1768, 1454, 1219, 1036, 887, 764, 661, 572, 496, 429, 371, 319, 274, 234, 198, 167, 140, 117, 97, 79, 65, 53, 44, 36, 31, 28, 26 }; void hilbert_transform(uint32_t *src, uint32_t *dst, int dst_len, int sign) { int j; int len = sizeof htstat_buf / sizeof(uint32_t); src -= len; // 240 * (208 + 12) = 52800cycle = 0.62ms@84MHz for (j = 0; j < dst_len; j++) { int i; int32_t acc = 0; #define OFFSET 64 // 16 * (10 + 3) = 208 cycle for (i = 0; i < 32; i += 2) { // 10 cycle uint32_t c = *(uint32_t*)&hilbert127_fir_coeff[i]; uint32_t a0 = src[OFFSET - i*2 - 1]; uint32_t a1 = src[OFFSET - i*2 - 3]; uint32_t b0 = src[OFFSET + i*2 + 1]; uint32_t b1 = src[OFFSET + i*2 + 3]; // fetch only R-ch (top half of word) from 2 successive samples uint32_t a = __PKHTB(a1, a0, 16); // and also do at symmetry samples uint32_t b = __PKHTB(b1, b0, 16); uint32_t d = __QSUB16(b, a); acc = __SMLAD(c, d, acc); } acc *= sign; int32_t real = src[OFFSET]; real /= 2; *dst++ = __PKHTB(real, acc, 16); src++; } } void hilbert_transform_save_fir_state(uint32_t *src_tail) { int len = sizeof htstat_buf / sizeof(uint32_t); uint32_t *dst = (uint32_t*)&htstat_buf[0]; uint32_t *src = src_tail - len; int i; for (i = 0; i < len; i++) { *dst++ = *src++; } } const int16_t cos_sin_table[257][4] = { { -32767, 10, 0, -804 }, { -32757, 29, -804, -804 }, { -32728, 50, -1608, -802 }, { -32678, 69, -2410, -802 }, { -32609, 88, -3212, -799 }, { -32521, 109, -4011, -797 }, { -32412, 127, -4808, -794 }, { -32285, 148, -5602, -791 }, { -32137, 166, -6393, -786 }, { -31971, 186, -7179, -783 }, { -31785, 205, -7962, -777 }, { -31580, 224, -8739, -773 }, { -31356, 243, -9512, -766 }, { -31113, 261, -10278, -761 }, { -30852, 281, -11039, -754 }, { -30571, 298, -11793, -746 }, { -30273, 317, -12539, -740 }, { -29956, 335, -13279, -731 }, { -29621, 353, -14010, -722 }, { -29268, 370, -14732, -714 }, { -28898, 388, -15446, -705 }, { -28510, 405, -16151, -695 }, { -28105, 422, -16846, -684 }, { -27683, 438, -17530, -674 }, { -27245, 455, -18204, -664 }, { -26790, 471, -18868, -651 }, { -26319, 487, -19519, -640 }, { -25832, 503, -20159, -628 }, { -25329, 518, -20787, -616 }, { -24811, 532, -21403, -602 }, { -24279, 548, -22005, -589 }, { -23731, 561, -22594, -576 }, { -23170, 576, -23170, -561 }, { -22594, 589, -23731, -548 }, { -22005, 602, -24279, -532 }, { -21403, 616, -24811, -518 }, { -20787, 628, -25329, -503 }, { -20159, 640, -25832, -487 }, { -19519, 651, -26319, -471 }, { -18868, 664, -26790, -455 }, { -18204, 674, -27245, -438 }, { -17530, 684, -27683, -422 }, { -16846, 695, -28105, -405 }, { -16151, 705, -28510, -388 }, { -15446, 714, -28898, -370 }, { -14732, 722, -29268, -353 }, { -14010, 731, -29621, -335 }, { -13279, 740, -29956, -317 }, { -12539, 746, -30273, -298 }, { -11793, 754, -30571, -281 }, { -11039, 761, -30852, -261 }, { -10278, 766, -31113, -243 }, { -9512, 773, -31356, -224 }, { -8739, 777, -31580, -205 }, { -7962, 783, -31785, -186 }, { -7179, 786, -31971, -166 }, { -6393, 791, -32137, -148 }, { -5602, 794, -32285, -127 }, { -4808, 797, -32412, -109 }, { -4011, 799, -32521, -88 }, { -3212, 802, -32609, -69 }, { -2410, 802, -32678, -50 }, { -1608, 804, -32728, -29 }, { -804, 804, -32757, -10 }, { 0, 804, -32767, 10 }, { 804, 804, -32757, 29 }, { 1608, 802, -32728, 50 }, { 2410, 802, -32678, 69 }, { 3212, 799, -32609, 88 }, { 4011, 797, -32521, 109 }, { 4808, 794, -32412, 127 }, { 5602, 791, -32285, 148 }, { 6393, 786, -32137, 166 }, { 7179, 783, -31971, 186 }, { 7962, 777, -31785, 205 }, { 8739, 773, -31580, 224 }, { 9512, 766, -31356, 243 }, { 10278, 761, -31113, 261 }, { 11039, 754, -30852, 281 }, { 11793, 746, -30571, 298 }, { 12539, 740, -30273, 317 }, { 13279, 731, -29956, 335 }, { 14010, 722, -29621, 353 }, { 14732, 714, -29268, 370 }, { 15446, 705, -28898, 388 }, { 16151, 695, -28510, 405 }, { 16846, 684, -28105, 422 }, { 17530, 674, -27683, 438 }, { 18204, 664, -27245, 455 }, { 18868, 651, -26790, 471 }, { 19519, 640, -26319, 487 }, { 20159, 628, -25832, 503 }, { 20787, 616, -25329, 518 }, { 21403, 602, -24811, 532 }, { 22005, 589, -24279, 548 }, { 22594, 576, -23731, 561 }, { 23170, 561, -23170, 576 }, { 23731, 548, -22594, 589 }, { 24279, 532, -22005, 602 }, { 24811, 518, -21403, 616 }, { 25329, 503, -20787, 628 }, { 25832, 487, -20159, 640 }, { 26319, 471, -19519, 651 }, { 26790, 455, -18868, 664 }, { 27245, 438, -18204, 674 }, { 27683, 422, -17530, 684 }, { 28105, 405, -16846, 695 }, { 28510, 388, -16151, 705 }, { 28898, 370, -15446, 714 }, { 29268, 353, -14732, 722 }, { 29621, 335, -14010, 731 }, { 29956, 317, -13279, 740 }, { 30273, 298, -12539, 746 }, { 30571, 281, -11793, 754 }, { 30852, 261, -11039, 761 }, { 31113, 243, -10278, 766 }, { 31356, 224, -9512, 773 }, { 31580, 205, -8739, 777 }, { 31785, 186, -7962, 783 }, { 31971, 166, -7179, 786 }, { 32137, 148, -6393, 791 }, { 32285, 127, -5602, 794 }, { 32412, 109, -4808, 797 }, { 32521, 88, -4011, 799 }, { 32609, 69, -3212, 802 }, { 32678, 50, -2410, 802 }, { 32728, 29, -1608, 804 }, { 32757, 10, -804, 804 }, { 32767, -10, 0, 804 }, { 32757, -29, 804, 804 }, { 32728, -50, 1608, 802 }, { 32678, -69, 2410, 802 }, { 32609, -88, 3212, 799 }, { 32521, -109, 4011, 797 }, { 32412, -127, 4808, 794 }, { 32285, -148, 5602, 791 }, { 32137, -166, 6393, 786 }, { 31971, -186, 7179, 783 }, { 31785, -205, 7962, 777 }, { 31580, -224, 8739, 773 }, { 31356, -243, 9512, 766 }, { 31113, -261, 10278, 761 }, { 30852, -281, 11039, 754 }, { 30571, -298, 11793, 746 }, { 30273, -317, 12539, 740 }, { 29956, -335, 13279, 731 }, { 29621, -353, 14010, 722 }, { 29268, -370, 14732, 714 }, { 28898, -388, 15446, 705 }, { 28510, -405, 16151, 695 }, { 28105, -422, 16846, 684 }, { 27683, -438, 17530, 674 }, { 27245, -455, 18204, 664 }, { 26790, -471, 18868, 651 }, { 26319, -487, 19519, 640 }, { 25832, -503, 20159, 628 }, { 25329, -518, 20787, 616 }, { 24811, -532, 21403, 602 }, { 24279, -548, 22005, 589 }, { 23731, -561, 22594, 576 }, { 23170, -576, 23170, 561 }, { 22594, -589, 23731, 548 }, { 22005, -602, 24279, 532 }, { 21403, -616, 24811, 518 }, { 20787, -628, 25329, 503 }, { 20159, -640, 25832, 487 }, { 19519, -651, 26319, 471 }, { 18868, -664, 26790, 455 }, { 18204, -674, 27245, 438 }, { 17530, -684, 27683, 422 }, { 16846, -695, 28105, 405 }, { 16151, -705, 28510, 388 }, { 15446, -714, 28898, 370 }, { 14732, -722, 29268, 353 }, { 14010, -731, 29621, 335 }, { 13279, -740, 29956, 317 }, { 12539, -746, 30273, 298 }, { 11793, -754, 30571, 281 }, { 11039, -761, 30852, 261 }, { 10278, -766, 31113, 243 }, { 9512, -773, 31356, 224 }, { 8739, -777, 31580, 205 }, { 7962, -783, 31785, 186 }, { 7179, -786, 31971, 166 }, { 6393, -791, 32137, 148 }, { 5602, -794, 32285, 127 }, { 4808, -797, 32412, 109 }, { 4011, -799, 32521, 88 }, { 3212, -802, 32609, 69 }, { 2410, -802, 32678, 50 }, { 1608, -804, 32728, 29 }, { 804, -804, 32757, 10 }, { 0, -804, 32767, -10 }, { -804, -804, 32757, -29 }, { -1608, -802, 32728, -50 }, { -2410, -802, 32678, -69 }, { -3212, -799, 32609, -88 }, { -4011, -797, 32521, -109 }, { -4808, -794, 32412, -127 }, { -5602, -791, 32285, -148 }, { -6393, -786, 32137, -166 }, { -7179, -783, 31971, -186 }, { -7962, -777, 31785, -205 }, { -8739, -773, 31580, -224 }, { -9512, -766, 31356, -243 }, { -10278, -761, 31113, -261 }, { -11039, -754, 30852, -281 }, { -11793, -746, 30571, -298 }, { -12539, -740, 30273, -317 }, { -13279, -731, 29956, -335 }, { -14010, -722, 29621, -353 }, { -14732, -714, 29268, -370 }, { -15446, -705, 28898, -388 }, { -16151, -695, 28510, -405 }, { -16846, -684, 28105, -422 }, { -17530, -674, 27683, -438 }, { -18204, -664, 27245, -455 }, { -18868, -651, 26790, -471 }, { -19519, -640, 26319, -487 }, { -20159, -628, 25832, -503 }, { -20787, -616, 25329, -518 }, { -21403, -602, 24811, -532 }, { -22005, -589, 24279, -548 }, { -22594, -576, 23731, -561 }, { -23170, -561, 23170, -576 }, { -23731, -548, 22594, -589 }, { -24279, -532, 22005, -602 }, { -24811, -518, 21403, -616 }, { -25329, -503, 20787, -628 }, { -25832, -487, 20159, -640 }, { -26319, -471, 19519, -651 }, { -26790, -455, 18868, -664 }, { -27245, -438, 18204, -674 }, { -27683, -422, 17530, -684 }, { -28105, -405, 16846, -695 }, { -28510, -388, 16151, -705 }, { -28898, -370, 15446, -714 }, { -29268, -353, 14732, -722 }, { -29621, -335, 14010, -731 }, { -29956, -317, 13279, -740 }, { -30273, -298, 12539, -746 }, { -30571, -281, 11793, -754 }, { -30852, -261, 11039, -761 }, { -31113, -243, 10278, -766 }, { -31356, -224, 9512, -773 }, { -31580, -205, 8739, -777 }, { -31785, -186, 7962, -783 }, { -31971, -166, 7179, -786 }, { -32137, -148, 6393, -791 }, { -32285, -127, 5602, -794 }, { -32412, -109, 4808, -797 }, { -32521, -88, 4011, -799 }, { -32609, -69, 3212, -802 }, { -32678, -50, 2410, -802 }, { -32728, -29, 1608, -804 }, { -32757, -10, 804, -804 }, { -32767, -10, 0, 0 } }; static inline uint32_t cos_sin(int16_t x) { int idx = x / 256; int mod = x & 0xff; uint32_t r = __PKHBT(0x0100, mod, 16); uint32_t *e = (uint32_t *)&cos_sin_table[idx+128]; uint32_t cd = e[0]; uint32_t sd = e[1]; int32_t c = __SMUAD(r, cd); int32_t s = __SMUAD(r, sd); c >>= 8; s >>= 8; return __PKHBT(s, c, 16); } FMModState fmmod; void fmmod_init(FMModState *fmmod) { fmmod->phase = 0; } void frequency_modulation(FMModState *fmmod, uint32_t *src, uint32_t *dst, int dst_len) { int j; uint16_t phase = fmmod->phase; for (j = 0; j < dst_len; j++) { uint32_t s = *src++; // fetch only R-ch (top half of word) int16_t x = s >> 16; phase += x; *dst++ = cos_sin(phase); } fmmod->phase = phase; } void amplitude_modulation(uint32_t *src, uint32_t *dst, int dst_len) { int j; for (j = 0; j < dst_len; j++) { uint32_t s = *src++; // fetch only R-ch (top half of word) int16_t x = s >> 16; // add DC and set zero at quadrature x = __SSAT(x + 0x3800, 16); *dst++ = __PKHBT(x, x, 16); } }