kopia lustrzana https://github.com/ArjanteMarvelde/uSDR-pico
373 wiersze
19 KiB
C
373 wiersze
19 KiB
C
/* fix_fft.c - Fixed-point in-place DIT Fast Fourier Transform */
|
|
/*
|
|
All data are fixed-point uint16_t integers, in which -32768
|
|
to +32768 represent -1.0 to +1.0 respectively. Integer
|
|
arithmetic is used for speed, instead of the more natural
|
|
floating-point.
|
|
|
|
For the forward FFT (time -> freq), fixed scaling is
|
|
performed to prevent arithmetic overflow, and to map a 0dB
|
|
sine/cosine wave (i.e. amplitude = 32767) to two -6dB freq
|
|
coefficients. The return value is always 0.
|
|
|
|
For the inverse FFT (freq -> time), fixed scaling cannot be
|
|
done, as two 0dB coefficients would sum to a peak amplitude
|
|
of 64K, overflowing the 32k range of the fixed-point integers.
|
|
Thus, the fix_fft() routine performs variable scaling, and
|
|
returns a value which is the number of bits LEFT by which
|
|
the output must be shifted to get the actual amplitude
|
|
(i.e. if fix_fft() returns 3, each value of fr[] and fi[]
|
|
must be multiplied by 8 (2**3) for proper scaling.
|
|
Clearly, this cannot be done within fixed-point uint16_t
|
|
integers. In practice, if the result is to be used as a
|
|
filter, the scale_shift can usually be ignored, as the
|
|
result will be approximately correctly normalized as is.
|
|
|
|
Written by: Tom Roberts 11/8/89
|
|
Made portable: Malcolm Slaney 12/15/94 malcolm@interval.com
|
|
Enhanced: Dimitrios P. Bouras 14 Jun 2006 dbouras@ieee.org
|
|
*/
|
|
/*
|
|
This implementation uses a lookup table for bit reverse sorting,
|
|
which adds 2kbyte to the memory footprint.
|
|
The iFFT range detector has been optimized.
|
|
The bitshifting of signed integers is undefined, so these have been
|
|
replaced by divisions. The compiler will optimize it.
|
|
The size is fixed at 1024.
|
|
*/
|
|
|
|
#include "pico/stdlib.h"
|
|
#include "pico/multicore.h"
|
|
#include "pico/platform.h"
|
|
#include "fix_fft.h"
|
|
|
|
|
|
/** Fixed point Sine lookup table, [-1, 1] == [-32768, 32767] **/
|
|
int16_t Sine[3*FFT_SIZE/4] =
|
|
{
|
|
0, 201, 402, 603, 804, 1005, 1206, 1406,
|
|
1607, 1808, 2009, 2209, 2410, 2610, 2811, 3011,
|
|
3211, 3411, 3611, 3811, 4011, 4210, 4409, 4608,
|
|
4807, 5006, 5205, 5403, 5601, 5799, 5997, 6195,
|
|
6392, 6589, 6786, 6982, 7179, 7375, 7571, 7766,
|
|
7961, 8156, 8351, 8545, 8739, 8932, 9126, 9319,
|
|
9511, 9703, 9895, 10087, 10278, 10469, 10659, 10849,
|
|
11038, 11227, 11416, 11604, 11792, 11980, 12166, 12353,
|
|
12539, 12724, 12909, 13094, 13278, 13462, 13645, 13827,
|
|
14009, 14191, 14372, 14552, 14732, 14911, 15090, 15268,
|
|
15446, 15623, 15799, 15975, 16150, 16325, 16499, 16672,
|
|
16845, 17017, 17189, 17360, 17530, 17699, 17868, 18036,
|
|
18204, 18371, 18537, 18702, 18867, 19031, 19194, 19357,
|
|
19519, 19680, 19840, 20000, 20159, 20317, 20474, 20631,
|
|
20787, 20942, 21096, 21249, 21402, 21554, 21705, 21855,
|
|
22004, 22153, 22301, 22448, 22594, 22739, 22883, 23027,
|
|
23169, 23311, 23452, 23592, 23731, 23869, 24006, 24143,
|
|
24278, 24413, 24546, 24679, 24811, 24942, 25072, 25201,
|
|
25329, 25456, 25582, 25707, 25831, 25954, 26077, 26198,
|
|
26318, 26437, 26556, 26673, 26789, 26905, 27019, 27132,
|
|
27244, 27355, 27466, 27575, 27683, 27790, 27896, 28001,
|
|
28105, 28208, 28309, 28410, 28510, 28608, 28706, 28802,
|
|
28897, 28992, 29085, 29177, 29268, 29358, 29446, 29534,
|
|
29621, 29706, 29790, 29873, 29955, 30036, 30116, 30195,
|
|
30272, 30349, 30424, 30498, 30571, 30643, 30713, 30783,
|
|
30851, 30918, 30984, 31049, 31113, 31175, 31236, 31297,
|
|
31356, 31413, 31470, 31525, 31580, 31633, 31684, 31735,
|
|
31785, 31833, 31880, 31926, 31970, 32014, 32056, 32097,
|
|
32137, 32176, 32213, 32249, 32284, 32318, 32350, 32382,
|
|
32412, 32441, 32468, 32495, 32520, 32544, 32567, 32588,
|
|
32609, 32628, 32646, 32662, 32678, 32692, 32705, 32717,
|
|
32727, 32736, 32744, 32751, 32757, 32761, 32764, 32766,
|
|
32767, 32766, 32764, 32761, 32757, 32751, 32744, 32736,
|
|
32727, 32717, 32705, 32692, 32678, 32662, 32646, 32628,
|
|
32609, 32588, 32567, 32544, 32520, 32495, 32468, 32441,
|
|
32412, 32382, 32350, 32318, 32284, 32249, 32213, 32176,
|
|
32137, 32097, 32056, 32014, 31970, 31926, 31880, 31833,
|
|
31785, 31735, 31684, 31633, 31580, 31525, 31470, 31413,
|
|
31356, 31297, 31236, 31175, 31113, 31049, 30984, 30918,
|
|
30851, 30783, 30713, 30643, 30571, 30498, 30424, 30349,
|
|
30272, 30195, 30116, 30036, 29955, 29873, 29790, 29706,
|
|
29621, 29534, 29446, 29358, 29268, 29177, 29085, 28992,
|
|
28897, 28802, 28706, 28608, 28510, 28410, 28309, 28208,
|
|
28105, 28001, 27896, 27790, 27683, 27575, 27466, 27355,
|
|
27244, 27132, 27019, 26905, 26789, 26673, 26556, 26437,
|
|
26318, 26198, 26077, 25954, 25831, 25707, 25582, 25456,
|
|
25329, 25201, 25072, 24942, 24811, 24679, 24546, 24413,
|
|
24278, 24143, 24006, 23869, 23731, 23592, 23452, 23311,
|
|
23169, 23027, 22883, 22739, 22594, 22448, 22301, 22153,
|
|
22004, 21855, 21705, 21554, 21402, 21249, 21096, 20942,
|
|
20787, 20631, 20474, 20317, 20159, 20000, 19840, 19680,
|
|
19519, 19357, 19194, 19031, 18867, 18702, 18537, 18371,
|
|
18204, 18036, 17868, 17699, 17530, 17360, 17189, 17017,
|
|
16845, 16672, 16499, 16325, 16150, 15975, 15799, 15623,
|
|
15446, 15268, 15090, 14911, 14732, 14552, 14372, 14191,
|
|
14009, 13827, 13645, 13462, 13278, 13094, 12909, 12724,
|
|
12539, 12353, 12166, 11980, 11792, 11604, 11416, 11227,
|
|
11038, 10849, 10659, 10469, 10278, 10087, 9895, 9703,
|
|
9511, 9319, 9126, 8932, 8739, 8545, 8351, 8156,
|
|
7961, 7766, 7571, 7375, 7179, 6982, 6786, 6589,
|
|
6392, 6195, 5997, 5799, 5601, 5403, 5205, 5006,
|
|
4807, 4608, 4409, 4210, 4011, 3811, 3611, 3411,
|
|
3211, 3011, 2811, 2610, 2410, 2209, 2009, 1808,
|
|
1607, 1406, 1206, 1005, 804, 603, 402, 201,
|
|
0, -201, -402, -603, -804, -1005, -1206, -1406,
|
|
-1607, -1808, -2009, -2209, -2410, -2610, -2811, -3011,
|
|
-3211, -3411, -3611, -3811, -4011, -4210, -4409, -4608,
|
|
-4807, -5006, -5205, -5403, -5601, -5799, -5997, -6195,
|
|
-6392, -6589, -6786, -6982, -7179, -7375, -7571, -7766,
|
|
-7961, -8156, -8351, -8545, -8739, -8932, -9126, -9319,
|
|
-9511, -9703, -9895, -10087, -10278, -10469, -10659, -10849,
|
|
-11038, -11227, -11416, -11604, -11792, -11980, -12166, -12353,
|
|
-12539, -12724, -12909, -13094, -13278, -13462, -13645, -13827,
|
|
-14009, -14191, -14372, -14552, -14732, -14911, -15090, -15268,
|
|
-15446, -15623, -15799, -15975, -16150, -16325, -16499, -16672,
|
|
-16845, -17017, -17189, -17360, -17530, -17699, -17868, -18036,
|
|
-18204, -18371, -18537, -18702, -18867, -19031, -19194, -19357,
|
|
-19519, -19680, -19840, -20000, -20159, -20317, -20474, -20631,
|
|
-20787, -20942, -21096, -21249, -21402, -21554, -21705, -21855,
|
|
-22004, -22153, -22301, -22448, -22594, -22739, -22883, -23027,
|
|
-23169, -23311, -23452, -23592, -23731, -23869, -24006, -24143,
|
|
-24278, -24413, -24546, -24679, -24811, -24942, -25072, -25201,
|
|
-25329, -25456, -25582, -25707, -25831, -25954, -26077, -26198,
|
|
-26318, -26437, -26556, -26673, -26789, -26905, -27019, -27132,
|
|
-27244, -27355, -27466, -27575, -27683, -27790, -27896, -28001,
|
|
-28105, -28208, -28309, -28410, -28510, -28608, -28706, -28802,
|
|
-28897, -28992, -29085, -29177, -29268, -29358, -29446, -29534,
|
|
-29621, -29706, -29790, -29873, -29955, -30036, -30116, -30195,
|
|
-30272, -30349, -30424, -30498, -30571, -30643, -30713, -30783,
|
|
-30851, -30918, -30984, -31049, -31113, -31175, -31236, -31297,
|
|
-31356, -31413, -31470, -31525, -31580, -31633, -31684, -31735,
|
|
-31785, -31833, -31880, -31926, -31970, -32014, -32056, -32097,
|
|
-32137, -32176, -32213, -32249, -32284, -32318, -32350, -32382,
|
|
-32412, -32441, -32468, -32495, -32520, -32544, -32567, -32588,
|
|
-32609, -32628, -32646, -32662, -32678, -32692, -32705, -32717,
|
|
-32727, -32736, -32744, -32751, -32757, -32761, -32764, -32766
|
|
};
|
|
|
|
|
|
static int16_t bitrev[FFT_SIZE] =
|
|
{
|
|
0x000, 0x200, 0x100, 0x300, 0x080, 0x280, 0x180, 0x380, 0x040, 0x240, 0x140, 0x340, 0x0c0, 0x2c0, 0x1c0, 0x3c0,
|
|
0x020, 0x220, 0x120, 0x320, 0x0a0, 0x2a0, 0x1a0, 0x3a0, 0x060, 0x260, 0x160, 0x360, 0x0e0, 0x2e0, 0x1e0, 0x3e0,
|
|
0x010, 0x210, 0x110, 0x310, 0x090, 0x290, 0x190, 0x390, 0x050, 0x250, 0x150, 0x350, 0x0d0, 0x2d0, 0x1d0, 0x3d0,
|
|
0x030, 0x230, 0x130, 0x330, 0x0b0, 0x2b0, 0x1b0, 0x3b0, 0x070, 0x270, 0x170, 0x370, 0x0f0, 0x2f0, 0x1f0, 0x3f0,
|
|
0x008, 0x208, 0x108, 0x308, 0x088, 0x288, 0x188, 0x388, 0x048, 0x248, 0x148, 0x348, 0x0c8, 0x2c8, 0x1c8, 0x3c8,
|
|
0x028, 0x228, 0x128, 0x328, 0x0a8, 0x2a8, 0x1a8, 0x3a8, 0x068, 0x268, 0x168, 0x368, 0x0e8, 0x2e8, 0x1e8, 0x3e8,
|
|
0x018, 0x218, 0x118, 0x318, 0x098, 0x298, 0x198, 0x398, 0x058, 0x258, 0x158, 0x358, 0x0d8, 0x2d8, 0x1d8, 0x3d8,
|
|
0x038, 0x238, 0x138, 0x338, 0x0b8, 0x2b8, 0x1b8, 0x3b8, 0x078, 0x278, 0x178, 0x378, 0x0f8, 0x2f8, 0x1f8, 0x3f8,
|
|
0x004, 0x204, 0x104, 0x304, 0x084, 0x284, 0x184, 0x384, 0x044, 0x244, 0x144, 0x344, 0x0c4, 0x2c4, 0x1c4, 0x3c4,
|
|
0x024, 0x224, 0x124, 0x324, 0x0a4, 0x2a4, 0x1a4, 0x3a4, 0x064, 0x264, 0x164, 0x364, 0x0e4, 0x2e4, 0x1e4, 0x3e4,
|
|
0x014, 0x214, 0x114, 0x314, 0x094, 0x294, 0x194, 0x394, 0x054, 0x254, 0x154, 0x354, 0x0d4, 0x2d4, 0x1d4, 0x3d4,
|
|
0x034, 0x234, 0x134, 0x334, 0x0b4, 0x2b4, 0x1b4, 0x3b4, 0x074, 0x274, 0x174, 0x374, 0x0f4, 0x2f4, 0x1f4, 0x3f4,
|
|
0x00c, 0x20c, 0x10c, 0x30c, 0x08c, 0x28c, 0x18c, 0x38c, 0x04c, 0x24c, 0x14c, 0x34c, 0x0cc, 0x2cc, 0x1cc, 0x3cc,
|
|
0x02c, 0x22c, 0x12c, 0x32c, 0x0ac, 0x2ac, 0x1ac, 0x3ac, 0x06c, 0x26c, 0x16c, 0x36c, 0x0ec, 0x2ec, 0x1ec, 0x3ec,
|
|
0x01c, 0x21c, 0x11c, 0x31c, 0x09c, 0x29c, 0x19c, 0x39c, 0x05c, 0x25c, 0x15c, 0x35c, 0x0dc, 0x2dc, 0x1dc, 0x3dc,
|
|
0x03c, 0x23c, 0x13c, 0x33c, 0x0bc, 0x2bc, 0x1bc, 0x3bc, 0x07c, 0x27c, 0x17c, 0x37c, 0x0fc, 0x2fc, 0x1fc, 0x3fc,
|
|
0x002, 0x202, 0x102, 0x302, 0x082, 0x282, 0x182, 0x382, 0x042, 0x242, 0x142, 0x342, 0x0c2, 0x2c2, 0x1c2, 0x3c2,
|
|
0x022, 0x222, 0x122, 0x322, 0x0a2, 0x2a2, 0x1a2, 0x3a2, 0x062, 0x262, 0x162, 0x362, 0x0e2, 0x2e2, 0x1e2, 0x3e2,
|
|
0x012, 0x212, 0x112, 0x312, 0x092, 0x292, 0x192, 0x392, 0x052, 0x252, 0x152, 0x352, 0x0d2, 0x2d2, 0x1d2, 0x3d2,
|
|
0x032, 0x232, 0x132, 0x332, 0x0b2, 0x2b2, 0x1b2, 0x3b2, 0x072, 0x272, 0x172, 0x372, 0x0f2, 0x2f2, 0x1f2, 0x3f2,
|
|
0x00a, 0x20a, 0x10a, 0x30a, 0x08a, 0x28a, 0x18a, 0x38a, 0x04a, 0x24a, 0x14a, 0x34a, 0x0ca, 0x2ca, 0x1ca, 0x3ca,
|
|
0x02a, 0x22a, 0x12a, 0x32a, 0x0aa, 0x2aa, 0x1aa, 0x3aa, 0x06a, 0x26a, 0x16a, 0x36a, 0x0ea, 0x2ea, 0x1ea, 0x3ea,
|
|
0x01a, 0x21a, 0x11a, 0x31a, 0x09a, 0x29a, 0x19a, 0x39a, 0x05a, 0x25a, 0x15a, 0x35a, 0x0da, 0x2da, 0x1da, 0x3da,
|
|
0x03a, 0x23a, 0x13a, 0x33a, 0x0ba, 0x2ba, 0x1ba, 0x3ba, 0x07a, 0x27a, 0x17a, 0x37a, 0x0fa, 0x2fa, 0x1fa, 0x3fa,
|
|
0x006, 0x206, 0x106, 0x306, 0x086, 0x286, 0x186, 0x386, 0x046, 0x246, 0x146, 0x346, 0x0c6, 0x2c6, 0x1c6, 0x3c6,
|
|
0x026, 0x226, 0x126, 0x326, 0x0a6, 0x2a6, 0x1a6, 0x3a6, 0x066, 0x266, 0x166, 0x366, 0x0e6, 0x2e6, 0x1e6, 0x3e6,
|
|
0x016, 0x216, 0x116, 0x316, 0x096, 0x296, 0x196, 0x396, 0x056, 0x256, 0x156, 0x356, 0x0d6, 0x2d6, 0x1d6, 0x3d6,
|
|
0x036, 0x236, 0x136, 0x336, 0x0b6, 0x2b6, 0x1b6, 0x3b6, 0x076, 0x276, 0x176, 0x376, 0x0f6, 0x2f6, 0x1f6, 0x3f6,
|
|
0x00e, 0x20e, 0x10e, 0x30e, 0x08e, 0x28e, 0x18e, 0x38e, 0x04e, 0x24e, 0x14e, 0x34e, 0x0ce, 0x2ce, 0x1ce, 0x3ce,
|
|
0x02e, 0x22e, 0x12e, 0x32e, 0x0ae, 0x2ae, 0x1ae, 0x3ae, 0x06e, 0x26e, 0x16e, 0x36e, 0x0ee, 0x2ee, 0x1ee, 0x3ee,
|
|
0x01e, 0x21e, 0x11e, 0x31e, 0x09e, 0x29e, 0x19e, 0x39e, 0x05e, 0x25e, 0x15e, 0x35e, 0x0de, 0x2de, 0x1de, 0x3de,
|
|
0x03e, 0x23e, 0x13e, 0x33e, 0x0be, 0x2be, 0x1be, 0x3be, 0x07e, 0x27e, 0x17e, 0x37e, 0x0fe, 0x2fe, 0x1fe, 0x3fe,
|
|
0x001, 0x201, 0x101, 0x301, 0x081, 0x281, 0x181, 0x381, 0x041, 0x241, 0x141, 0x341, 0x0c1, 0x2c1, 0x1c1, 0x3c1,
|
|
0x021, 0x221, 0x121, 0x321, 0x0a1, 0x2a1, 0x1a1, 0x3a1, 0x061, 0x261, 0x161, 0x361, 0x0e1, 0x2e1, 0x1e1, 0x3e1,
|
|
0x011, 0x211, 0x111, 0x311, 0x091, 0x291, 0x191, 0x391, 0x051, 0x251, 0x151, 0x351, 0x0d1, 0x2d1, 0x1d1, 0x3d1,
|
|
0x031, 0x231, 0x131, 0x331, 0x0b1, 0x2b1, 0x1b1, 0x3b1, 0x071, 0x271, 0x171, 0x371, 0x0f1, 0x2f1, 0x1f1, 0x3f1,
|
|
0x009, 0x209, 0x109, 0x309, 0x089, 0x289, 0x189, 0x389, 0x049, 0x249, 0x149, 0x349, 0x0c9, 0x2c9, 0x1c9, 0x3c9,
|
|
0x029, 0x229, 0x129, 0x329, 0x0a9, 0x2a9, 0x1a9, 0x3a9, 0x069, 0x269, 0x169, 0x369, 0x0e9, 0x2e9, 0x1e9, 0x3e9,
|
|
0x019, 0x219, 0x119, 0x319, 0x099, 0x299, 0x199, 0x399, 0x059, 0x259, 0x159, 0x359, 0x0d9, 0x2d9, 0x1d9, 0x3d9,
|
|
0x039, 0x239, 0x139, 0x339, 0x0b9, 0x2b9, 0x1b9, 0x3b9, 0x079, 0x279, 0x179, 0x379, 0x0f9, 0x2f9, 0x1f9, 0x3f9,
|
|
0x005, 0x205, 0x105, 0x305, 0x085, 0x285, 0x185, 0x385, 0x045, 0x245, 0x145, 0x345, 0x0c5, 0x2c5, 0x1c5, 0x3c5,
|
|
0x025, 0x225, 0x125, 0x325, 0x0a5, 0x2a5, 0x1a5, 0x3a5, 0x065, 0x265, 0x165, 0x365, 0x0e5, 0x2e5, 0x1e5, 0x3e5,
|
|
0x015, 0x215, 0x115, 0x315, 0x095, 0x295, 0x195, 0x395, 0x055, 0x255, 0x155, 0x355, 0x0d5, 0x2d5, 0x1d5, 0x3d5,
|
|
0x035, 0x235, 0x135, 0x335, 0x0b5, 0x2b5, 0x1b5, 0x3b5, 0x075, 0x275, 0x175, 0x375, 0x0f5, 0x2f5, 0x1f5, 0x3f5,
|
|
0x00d, 0x20d, 0x10d, 0x30d, 0x08d, 0x28d, 0x18d, 0x38d, 0x04d, 0x24d, 0x14d, 0x34d, 0x0cd, 0x2cd, 0x1cd, 0x3cd,
|
|
0x02d, 0x22d, 0x12d, 0x32d, 0x0ad, 0x2ad, 0x1ad, 0x3ad, 0x06d, 0x26d, 0x16d, 0x36d, 0x0ed, 0x2ed, 0x1ed, 0x3ed,
|
|
0x01d, 0x21d, 0x11d, 0x31d, 0x09d, 0x29d, 0x19d, 0x39d, 0x05d, 0x25d, 0x15d, 0x35d, 0x0dd, 0x2dd, 0x1dd, 0x3dd,
|
|
0x03d, 0x23d, 0x13d, 0x33d, 0x0bd, 0x2bd, 0x1bd, 0x3bd, 0x07d, 0x27d, 0x17d, 0x37d, 0x0fd, 0x2fd, 0x1fd, 0x3fd,
|
|
0x003, 0x203, 0x103, 0x303, 0x083, 0x283, 0x183, 0x383, 0x043, 0x243, 0x143, 0x343, 0x0c3, 0x2c3, 0x1c3, 0x3c3,
|
|
0x023, 0x223, 0x123, 0x323, 0x0a3, 0x2a3, 0x1a3, 0x3a3, 0x063, 0x263, 0x163, 0x363, 0x0e3, 0x2e3, 0x1e3, 0x3e3,
|
|
0x013, 0x213, 0x113, 0x313, 0x093, 0x293, 0x193, 0x393, 0x053, 0x253, 0x153, 0x353, 0x0d3, 0x2d3, 0x1d3, 0x3d3,
|
|
0x033, 0x233, 0x133, 0x333, 0x0b3, 0x2b3, 0x1b3, 0x3b3, 0x073, 0x273, 0x173, 0x373, 0x0f3, 0x2f3, 0x1f3, 0x3f3,
|
|
0x00b, 0x20b, 0x10b, 0x30b, 0x08b, 0x28b, 0x18b, 0x38b, 0x04b, 0x24b, 0x14b, 0x34b, 0x0cb, 0x2cb, 0x1cb, 0x3cb,
|
|
0x02b, 0x22b, 0x12b, 0x32b, 0x0ab, 0x2ab, 0x1ab, 0x3ab, 0x06b, 0x26b, 0x16b, 0x36b, 0x0eb, 0x2eb, 0x1eb, 0x3eb,
|
|
0x01b, 0x21b, 0x11b, 0x31b, 0x09b, 0x29b, 0x19b, 0x39b, 0x05b, 0x25b, 0x15b, 0x35b, 0x0db, 0x2db, 0x1db, 0x3db,
|
|
0x03b, 0x23b, 0x13b, 0x33b, 0x0bb, 0x2bb, 0x1bb, 0x3bb, 0x07b, 0x27b, 0x17b, 0x37b, 0x0fb, 0x2fb, 0x1fb, 0x3fb,
|
|
0x007, 0x207, 0x107, 0x307, 0x087, 0x287, 0x187, 0x387, 0x047, 0x247, 0x147, 0x347, 0x0c7, 0x2c7, 0x1c7, 0x3c7,
|
|
0x027, 0x227, 0x127, 0x327, 0x0a7, 0x2a7, 0x1a7, 0x3a7, 0x067, 0x267, 0x167, 0x367, 0x0e7, 0x2e7, 0x1e7, 0x3e7,
|
|
0x017, 0x217, 0x117, 0x317, 0x097, 0x297, 0x197, 0x397, 0x057, 0x257, 0x157, 0x357, 0x0d7, 0x2d7, 0x1d7, 0x3d7,
|
|
0x037, 0x237, 0x137, 0x337, 0x0b7, 0x2b7, 0x1b7, 0x3b7, 0x077, 0x277, 0x177, 0x377, 0x0f7, 0x2f7, 0x1f7, 0x3f7,
|
|
0x00f, 0x20f, 0x10f, 0x30f, 0x08f, 0x28f, 0x18f, 0x38f, 0x04f, 0x24f, 0x14f, 0x34f, 0x0cf, 0x2cf, 0x1cf, 0x3cf,
|
|
0x02f, 0x22f, 0x12f, 0x32f, 0x0af, 0x2af, 0x1af, 0x3af, 0x06f, 0x26f, 0x16f, 0x36f, 0x0ef, 0x2ef, 0x1ef, 0x3ef,
|
|
0x01f, 0x21f, 0x11f, 0x31f, 0x09f, 0x29f, 0x19f, 0x39f, 0x05f, 0x25f, 0x15f, 0x35f, 0x0df, 0x2df, 0x1df, 0x3df,
|
|
0x03f, 0x23f, 0x13f, 0x33f, 0x0bf, 0x2bf, 0x1bf, 0x3bf, 0x07f, 0x27f, 0x17f, 0x37f, 0x0ff, 0x2ff, 0x1ff, 0x3ff
|
|
};
|
|
|
|
|
|
/** FIX_MPY() **/
|
|
/*
|
|
* Assume Q(0,15) notation, 1 sign, 0 int, 15 frac bits
|
|
*/
|
|
int16_t __not_in_flash_func(FIX_MPY)(int16_t a, int16_t b) // Fixed-point mpy and scaling
|
|
{
|
|
int32_t c;
|
|
|
|
c = (int32_t)a * (int32_t)b; // multiply
|
|
c = c + 0x4000; // and round up
|
|
c = c >> 15; // Shift right fractional bits
|
|
return((int16_t)c); // Return scaled product
|
|
}
|
|
|
|
|
|
/** FIX_FFT() **/
|
|
/*
|
|
* fr[] i samples [1024]
|
|
* fi[] q samples [1024]
|
|
* inverse true: iFFT
|
|
* Note: i-FFT could also be calculated by exchanging the arrays for FFT (fxtbook.pdf 21.7)
|
|
*/
|
|
int __not_in_flash_func(fix_fft)(int16_t *fr, int16_t *fi, bool inverse)
|
|
{
|
|
uint16_t i, j, m, k, step, scale;
|
|
bool shift;
|
|
int16_t qr, qi, tr, ti, wr, wi;
|
|
int16_t *bp;
|
|
|
|
/* Decimation in time: re-order samples */
|
|
bp=&bitrev[0];
|
|
for (i=0; i<FFT_SIZE; i++)
|
|
{
|
|
if (*bp > i)
|
|
{
|
|
tr = fr[i]; fr[i] = fr[*bp]; fr[*bp] = tr;
|
|
ti = fi[i]; fi[i] = fi[*bp]; fi[*bp] = ti;
|
|
}
|
|
bp++;
|
|
}
|
|
|
|
|
|
scale = 0;
|
|
step = 1; // Counting up: 1, 2, 4, 8, ...
|
|
/* FFT Stages */
|
|
for (k=FFT_ORDER; k>0; k--) // #cycles: FFT_ORDER
|
|
{
|
|
/* Scaling
|
|
* Variable scaling, depends on current data
|
|
* --> it seems quite CPU intensive to go through complete array
|
|
* FFT_ORDER times, could this be optimized?
|
|
* If always scaling:
|
|
* --> the main loop has log_2(FFT_SIZE) cycles,
|
|
* resulting in an overall factor of 1/FFT_SIZE,
|
|
* distributed over cycles to maximize accuracy.
|
|
*/
|
|
shift = false; // No shift, unless...
|
|
for (i=0; i<FFT_SIZE; ++i) // Range test all samples
|
|
{
|
|
if ((fr[i] > 0x3fff) || (fr[i] < -0x4000) || (fi[i] > 0x3fff) || (fi[i] < -0x4000))
|
|
{
|
|
shift = true;
|
|
scale++;
|
|
break; // Bail out at first detect
|
|
}
|
|
}
|
|
|
|
/* Inner loops resolving the butterflies for each stage*/
|
|
for (m=0; m<step; m++) // #cycles: step
|
|
{
|
|
// Determine wiggle factors
|
|
j = m << (k-1); // 0 <= j < FFT_SIZE/2
|
|
wr = Sine[j+FFT_SIZE/4]; // Real part, i.e. Cosine
|
|
wi = inverse ? Sine[j] : -Sine[j]; // Imaginary part
|
|
|
|
if (shift) { wr = wr/2; wi = wi/2; } // Scale factors by 1/2
|
|
|
|
for (i=m; i<FFT_SIZE; i+=(step*2)) // #cycles: FFT_SIZE/step
|
|
{
|
|
j = i + step; // re-assign j !
|
|
tr = FIX_MPY(wr,fr[j]) - FIX_MPY(wi,fi[j]); // Complex multiply
|
|
ti = FIX_MPY(wr,fi[j]) + FIX_MPY(wi,fr[j]);
|
|
qr = shift ? fr[i]/2 : fr[i];
|
|
qi = shift ? fi[i]/2 : fi[i];
|
|
fr[i] = qr + tr;
|
|
fi[i] = qi + ti;
|
|
fr[j] = qr - tr;
|
|
fi[j] = qi - ti;
|
|
} // #total: FFT_ORDER * step * FFT_SIZE/step
|
|
}
|
|
|
|
step = step<<1;
|
|
}
|
|
return scale;
|
|
}
|
|
|
|
|
|
#ifdef BLAH
|
|
// int16_t contains signed fixed point representation Q(1,14)
|
|
// 1 sign bit, 1 int bit and 14 frac bits
|
|
// precomputed value K represents 0.5
|
|
#define Q 14
|
|
#define K (1 << (Q - 1))
|
|
|
|
// a + b
|
|
int16_t q_add(int16_t a, int16_t b)
|
|
{
|
|
int32_t tmp;
|
|
|
|
tmp = (int32_t)a + (int32_t)b;
|
|
|
|
if (tmp > 0x7FFF) // Clip result
|
|
tmp = 0x7FFF;
|
|
else if (tmp < -0x8000)
|
|
tmp = -0x8000;
|
|
|
|
return (int16_t)tmp;
|
|
}
|
|
|
|
// a - b
|
|
int16_t q_sub(int16_t a, int16_t b)
|
|
{
|
|
return a - b;
|
|
}
|
|
|
|
// a * b
|
|
int16_t q_mul(int16_t a, int16_t b)
|
|
{
|
|
int32_t tmp;
|
|
|
|
tmp = (int32_t)a * (int32_t)b;
|
|
tmp += K; // Rounding; mid values are rounded up
|
|
tmp = tmp >> Q; // Correct by dividing by base
|
|
|
|
if (tmp > 0x7FFF) // Clip result
|
|
tmp = 0x7FFF;
|
|
else if (tmp < -0x8000)
|
|
tmp = -0x8000;
|
|
|
|
return (int16_t)tmp;
|
|
}
|
|
|
|
// a / b
|
|
int16_t q_div(int16_t a, int16_t b)
|
|
{
|
|
int32_t tmp;
|
|
|
|
tmp = (int32_t)a << Q; // Pre multiply with base
|
|
|
|
if ((tmp >= 0 && b >= 0) || (tmp < 0 && b < 0)) // Rounding; mid values are rounded up
|
|
tmp += (b >> 2);
|
|
else // or down...
|
|
tmp -= (b >> 2);
|
|
|
|
return (int16_t)(tmp / b);
|
|
}
|
|
#endif
|