├── AM_demod.cpp ├── AM_demod.h ├── H_0_8kHz.h ├── H_45_11kHz.h ├── H_45_1_8kHz.h ├── H_45_2_6kHz.h ├── H_45_3_6kHz.h ├── H_45_4_4kHz.h ├── H_45_6_5kHz.h ├── H_45_8kHz.h ├── H_90_8kHz.h ├── H_m45_11kHz.h ├── H_m45_1_8kHz.h ├── H_m45_2_6kHz.h ├── H_m45_3_6kHz.h ├── H_m45_4_4kHz.h ├── H_m45_6_5kHz.h ├── H_m45_8kHz.h ├── README.md ├── Schedule.h ├── Teensy.SDR.Documentation.DD4WH.pdf ├── Teensy_SDR.ino ├── agc.cpp ├── analyze_fft256iq.cpp ├── analyze_fft256iq.h ├── display.cpp ├── display.h ├── filters.cpp ├── filters.h ├── fir_18.h ├── fir_26.h ├── fir_36.h ├── fir_44.h ├── fir_65.h ├── fir_80.h ├── freq_conv.cpp ├── freq_conv.h ├── iir_110.h ├── iir_18.h ├── iir_23.h ├── iir_26.h ├── iir_31.h ├── iir_36.h ├── iir_40.h ├── iir_44.h ├── iir_54.h ├── iir_65.h ├── iir_80.h └── licence.txt /AM_demod.cpp: -------------------------------------------------------------------------------- 1 | /* Audio Library for Teensy 3.X 2 | * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com 3 | * 4 | * Development of this audio library was funded by PJRC.COM, LLC by sales of 5 | * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop 6 | * open source software by purchasing Teensy or other PJRC products. 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice, development funding notice, and this permission 16 | * notice shall be included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include "AM_demod.h" 28 | 29 | 30 | void AMDemod::update(void) 31 | { 32 | if (!pass) return; 33 | 34 | audio_block_t *blocki, *blockq; 35 | int16_t *pi, *pq, *end; 36 | int32_t sum; 37 | 38 | blocki = receiveWritable(0); // receives I, end result is written in channel 0 39 | blockq = receiveReadOnly(1); // receives Q 40 | 41 | if (!blocki) { 42 | if (blockq) release(blockq); 43 | return; 44 | } 45 | 46 | if (!blockq) { 47 | release(blocki); 48 | return; 49 | } 50 | 51 | pi = (int16_t *)(blocki->data); 52 | pq = (int16_t *)(blockq->data); 53 | end = pi + AUDIO_BLOCK_SAMPLES; 54 | 55 | while (pi < end) { 56 | // square and sum I and Q 57 | sum = *pi * *pi; 58 | sum += *pq * *pq; 59 | // The result of squaring a 1.15 is 2.30. 60 | // Shift the sum up one bit to make it 1.31 (Q31) 61 | // and then that becomes the input to the arm sqrt function 62 | sum <<= 1; 63 | arm_sqrt_q31((q31_t)sum,(q31_t *) &sum); 64 | // The result is in the high order 16 bits of sum 65 | *pi++ = sum >> 16; 66 | pq++; 67 | } 68 | transmit(blocki); 69 | release(blocki); 70 | release(blockq); 71 | } 72 | 73 | -------------------------------------------------------------------------------- /AM_demod.h: -------------------------------------------------------------------------------- 1 | /* Audio Library for Teensy 3.X 2 | * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com 3 | * 4 | * Development of this audio library was funded by PJRC.COM, LLC by sales of 5 | * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop 6 | * open source software by purchasing Teensy or other PJRC products. 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice, development funding notice, and this permission 16 | * notice shall be included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | 28 | 29 | 30 | #ifndef AM_demod_h_ 31 | #define AM_demod_h_ 32 | #include "AudioStream.h" 33 | #include "utility/dspinst.h" 34 | #include "arm_math.h" 35 | 36 | class AMDemod : public AudioStream 37 | { 38 | public: 39 | AMDemod() : AudioStream(2, inputQueueArray), pass(1) { } 40 | void passthrough(bool p) { 41 | pass = p; 42 | } 43 | virtual void update(void); 44 | private: 45 | audio_block_t *inputQueueArray[2]; 46 | bool pass; 47 | }; 48 | 49 | #endif 50 | -------------------------------------------------------------------------------- /H_0_8kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter 0 degrees 8 kHz BW centred at 3.68 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 4.11.2015 13 | 14 | 15 | -1.118028595, 16 | -1.282384471, 17 | -0.471760313, 18 | 0.202471193, 19 | -0.530155315, 20 | -2.096468405, 21 | -2.625251546, 22 | -1.720186949, 23 | -1.149971973, 24 | -1.873406596, 25 | -2.228455845, 26 | -1.21992744, 27 | -1.771906176, 28 | -6.384647842, 29 | -9.946485726, 30 | -3.91484373, 31 | 8.298773718, 32 | 8.158570274, 33 | -13.9660515, 34 | -34.98136488, 35 | -19.18361676, 36 | 27.71955649, 37 | 45.50909275, 38 | -9.39576964, 39 | -85.35542965, 40 | -74.18687271, 41 | 43.28791358, 42 | 130.4756398, 43 | 43.26454404, 44 | -153.2250175, 45 | -206.2327801, 46 | 12.15902822, 47 | 271.6529313, 48 | 204.8674098, 49 | -196.7739431, 50 | -455.8221591, 51 | -151.6648753, 52 | 451.2727031, 53 | 573.4468843, 54 | -116.12468, 55 | -882.6996162, 56 | -637.1151634, 57 | 622.9483749, 58 | 1430.476994, 59 | 389.4811928, 60 | -1823.137796, 61 | -2458.697871, 62 | 728.8542644, 63 | 6759.689581, 64 | 11619.97089, 65 | 11619.97089, 66 | 6759.689581, 67 | 728.8542644, 68 | -2458.697871, 69 | -1823.137796, 70 | 389.4811928, 71 | 1430.476994, 72 | 622.9483749, 73 | -637.1151634, 74 | -882.6996162, 75 | -116.12468, 76 | 573.4468843, 77 | 451.2727031, 78 | -151.6648753, 79 | -455.8221591, 80 | -196.7739431, 81 | 204.8674098, 82 | 271.6529313, 83 | 12.15902822, 84 | -206.2327801, 85 | -153.2250175, 86 | 43.26454404, 87 | 130.4756398, 88 | 43.28791358, 89 | -74.18687271, 90 | -85.35542965, 91 | -9.39576964, 92 | 45.50909275, 93 | 27.71955649, 94 | -19.18361676, 95 | -34.98136488, 96 | -13.9660515, 97 | 8.158570274, 98 | 8.298773718, 99 | -3.91484373, 100 | -9.946485726, 101 | -6.384647842, 102 | -1.771906176, 103 | -1.21992744, 104 | -2.228455845, 105 | -1.873406596, 106 | -1.149971973, 107 | -1.720186949, 108 | -2.625251546, 109 | -2.096468405, 110 | -0.530155315, 111 | 0.202471193, 112 | -0.471760313, 113 | -1.282384471, 114 | -1.118028595 115 | 116 | -------------------------------------------------------------------------------- /H_45_11kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter -45 degrees 11 kHz BW quasi LPF 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 12.2.2016 13 | 14 | 3.940884316, 15 | 4.098248981, 16 | 6.135497413, 17 | 8.509178315, 18 | 8.717549752, 19 | 9.249534502, 20 | 12.58160357, 21 | 15.50958453, 22 | 16.55874166, 23 | 19.01549163, 24 | 22.07762721, 25 | 24.0464777, 26 | 29.90755654, 27 | 37.03273381, 28 | 34.19958512, 29 | 33.06049844, 30 | 53.5560537, 31 | 68.37696308, 32 | 46.8403169, 33 | 41.60685468, 34 | 95.8892844, 35 | 119.1668968, 36 | 55.56995208, 37 | 50.18344113, 38 | 170.2731402, 39 | 195.9717384, 40 | 53.39790532, 41 | 62.81124597, 42 | 297.0435216, 43 | 305.7506089, 44 | 30.94510115, 45 | 90.13385621, 46 | 508.1968284, 47 | 458.0383308, 48 | -23.70045263, 49 | 155.2357918, 50 | 862.4177547, 51 | 674.1768321, 52 | -128.3828858, 53 | 310.7506256, 54 | 1503.255448, 55 | 1024.310858, 56 | -327.5563334, 57 | 720.2175094, 58 | 2980.896185, 59 | 1857.86905, 60 | -866.6322336, 61 | 2535.364595, 62 | 11745.20674, 63 | 15007.47097, 64 | 6031.450296, 65 | -5299.463564, 66 | -7093.42431, 67 | -1818.408727, 68 | 526.3958177, 69 | -1671.028804, 70 | -2575.305981, 71 | -693.9470763, 72 | 144.6715194, 73 | -1031.558983, 74 | -1413.612069, 75 | -368.2022395, 76 | -10.75939603, 77 | -715.1414869, 78 | -854.7889892, 79 | -229.1790177, 80 | -85.69958164, 81 | -503.1259578, 82 | -528.9063939, 83 | -160.7628939, 84 | -114.7412396, 85 | -346.3493304, 86 | -326.4345649, 87 | -122.2494637, 88 | -114.8365213, 89 | -229.4300731, 90 | -199.3250733, 91 | -95.77515468, 92 | -98.33807423, 93 | -145.031656, 94 | -120.2973714, 95 | -73.67990907, 96 | -74.9101393, 97 | -87.13409276, 98 | -71.70414144, 99 | -53.64478675, 100 | -51.3936885, 101 | -49.62710273, 102 | -41.86965803, 103 | -35.90595893, 104 | -31.71843242, 105 | -26.63628722, 106 | -23.39106879, 107 | -21.4213101, 108 | -17.32187958, 109 | -13.18494618, 110 | -11.88178533, 111 | -10.81444631, 112 | -7.948154051, 113 | -5.594289936 114 | 115 | -------------------------------------------------------------------------------- /H_45_1_8kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter +45 degrees 2.4 kHz BW centred at 0.662 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 30.10.2015 13 | 14 | 15 | 6.169149086, 16 | 7.762161934, 17 | 9.678414571, 18 | 11.97181026, 19 | 14.66903055, 20 | 17.7566592, 21 | 21.17581099, 22 | 24.8286344, 23 | 28.59939309, 24 | 32.38994243, 25 | 36.16565198, 26 | 40.00382538, 27 | 44.13330589, 28 | 48.95218076, 29 | 55.01115333, 30 | 62.95376806, 31 | 73.41127505, 32 | 86.85891582, 33 | 103.4505744, 34 | 122.8583218, 35 | 144.1503576, 36 | 165.7432526, 37 | 185.4606946, 38 | 200.7204433, 39 | 208.8543188, 40 | 207.5444211, 41 | 195.3352116, 42 | 172.1592168, 43 | 139.7979372, 44 | 102.1927621, 45 | 65.526028, 46 | 38.01099104, 47 | 29.36058223, 48 | 49.94546417, 49 | 109.6972779, 50 | 216.8568894, 51 | 376.70322, 52 | 590.4196493, 53 | 854.2572976, 54 | 1159.135347, 55 | 1490.778551, 56 | 1830.43486, 57 | 2156.148127, 58 | 2444.49065, 59 | 2672.597195, 60 | 2820.2951, 61 | 2872.101329, 62 | 2818.86112, 63 | 2658.83496, 64 | 2398.097812, 65 | 2050.190027, 66 | 1635.044018, 67 | 1177.293565, 68 | 704.1431657, 69 | 243.0238712, 70 | -180.7165199, 71 | -545.8496202, 72 | -836.8268234, 73 | -1044.721995, 74 | -1167.489741, 75 | -1209.5525, 76 | -1180.804262, 77 | -1095.178632, 78 | -968.9675055, 79 | -819.0901417, 80 | -661.5008591, 81 | -509.8902531, 82 | -374.7856368, 83 | -263.0990108, 84 | -178.1133736, 85 | -119.8480284, 86 | -85.70647949, 87 | -71.2899744, 88 | -71.25654397, 89 | -80.11787969, 90 | -92.89092522, 91 | -105.5527781, 92 | -115.2811119, 93 | -120.4929751, 94 | -120.7187045, 95 | -116.3625192, 96 | -108.4064742, 97 | -98.11072917, 98 | -86.75255196, 99 | -75.43187354, 100 | -64.95543062, 101 | -55.79717649, 102 | -48.121628, 103 | -41.85021153, 104 | -36.74864066, 105 | -32.51530148, 106 | -28.85540288, 107 | -25.53187854, 108 | -22.39034457, 109 | -19.36071589, 110 | -16.44166146, 111 | -13.67567667, 112 | -11.12232257, 113 | -8.835580968, 114 | -6.848914072 115 | 116 | -------------------------------------------------------------------------------- /H_45_2_6kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter +45 degrees 2.8 kHz centred at 1.1 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 30.10.2015 13 | 14 | 6.611657604, 15 | 8.582345627, 16 | 10.78199001, 17 | 13.12616626, 18 | 15.53449297, 19 | 17.97132535, 20 | 20.4833112, 21 | 23.21755438, 22 | 26.40563827, 23 | 30.30625053, 24 | 35.11191162, 25 | 40.84059905, 26 | 47.2464471, 27 | 53.79005262, 28 | 59.70386353, 29 | 64.16966966, 30 | 66.59499666, 31 | 66.93897472, 32 | 66.00521915, 33 | 65.6002298, 34 | 68.4604564, 35 | 77.88494462, 36 | 97.07206447, 37 | 128.2389145, 38 | 171.6839803, 39 | 225.0164147, 40 | 282.7979317, 41 | 336.8103909, 42 | 377.0689701, 43 | 393.5565795, 44 | 378.4833265, 45 | 328.7099964, 46 | 247.8559854, 47 | 147.5754399, 48 | 47.55333512, 49 | -26.05123028, 50 | -43.72462626, 51 | 23.0159275, 52 | 196.5622197, 53 | 488.2894701, 54 | 894.6634694, 55 | 1395.205121, 56 | 1952.898514, 57 | 2517.255612, 58 | 3029.803404, 59 | 3431.317802, 60 | 3669.776984, 61 | 3707.817056, 62 | 3528.489237, 63 | 3138.346454, 64 | 2567.294386, 65 | 1865.158245, 66 | 1095.450552, 67 | 327.2805716, 68 | -373.3591967, 69 | -951.6121901, 70 | -1369.908249, 71 | -1611.408836, 72 | -1680.377683, 73 | -1599.616754, 74 | -1405.566523, 75 | -1141.999975, 76 | -853.3904754, 77 | -578.9900793, 78 | -348.4390731, 79 | -179.3921969, 80 | -77.26247812, 81 | -36.82366369, 82 | -45.13902546, 83 | -85.13761936, 84 | -139.1506394, 85 | -191.8345856, 86 | -232.1073943, 87 | -253.9596238, 88 | -256.225816, 89 | -241.5711365, 90 | -215.0413694, 91 | -182.5350922, 92 | -149.4973287, 93 | -120.0282992, 94 | -96.47848502, 95 | -79.48988635, 96 | -68.36362125, 97 | -61.59606488, 98 | -57.42896361, 99 | -54.29407651, 100 | -51.08550275, 101 | -47.24761449, 102 | -42.71078173, 103 | -37.7332309, 104 | -32.71359164, 105 | -28.02817094, 106 | -23.92620843, 107 | -20.49279361, 108 | -17.66923525, 109 | -15.30854418, 110 | -13.24051182, 111 | -11.32525903, 112 | -9.483069906, 113 | -7.698292841 114 | 115 | -------------------------------------------------------------------------------- /H_45_3_6kHz.h: -------------------------------------------------------------------------------- 1 | // hilbert filter pair generated by Iowa Hills Software Hilbert tool 2 | // 45 degree shift 3 | // Bandwidth 3.60kHz, Fc=1.76kHz, 20Hz -6dB, 3.8kHz -6dB 4 | // Sampl f 44117 5 | // Num Taps 100 6 | // DD4WH 29.10.2015 7 | 8 | 3.78337329, 9 | 5.160887617, 10 | 6.905115864, 11 | 8.874981259, 12 | 10.85496704, 13 | 12.66443699, 14 | 14.28284387, 15 | 15.91954177, 16 | 17.96432365, 17 | 20.8031621, 18 | 24.55947766, 19 | 28.89082754, 20 | 32.99217451, 21 | 35.89990095, 22 | 37.05778833, 23 | 36.94131154, 24 | 37.41612538, 25 | 41.51024568, 26 | 52.45075847, 27 | 72.1290943, 28 | 99.50958536, 29 | 129.7274333, 30 | 154.5839367, 31 | 164.7669744, 32 | 153.4657989, 33 | 120.3178193, 34 | 74.11995044, 35 | 32.74314106, 36 | 19.3507752, 37 | 55.24814847, 38 | 151.1334913, 39 | 299.659575, 40 | 472.524464, 41 | 624.4709288, 42 | 704.6394141, 43 | 673.1688726, 44 | 518.5786483, 45 | 270.1818886, 46 | 0.235623067, 47 | -187.1234948, 48 | -179.3628122, 49 | 113.4415272, 50 | 728.1258916, 51 | 1627.570922, 52 | 2696.861508, 53 | 3759.755151, 54 | 4613.186703, 55 | 5072.170167, 56 | 5013.935458, 57 | 4409.644491, 58 | 3334.871169, 59 | 1955.491601, 60 | 492.1771637, 61 | -827.5853983, 62 | -1817.77798, 63 | -2370.437878, 64 | -2472.020293, 65 | -2196.702741, 66 | -1679.995309, 67 | -1080.9287, 68 | -543.3866144, 69 | -166.3579884, 70 | 10.52043767, 71 | 4.57200784, 72 | -126.0215978, 73 | -305.6441846, 74 | -464.5741928, 75 | -556.0096948, 76 | -563.3689529, 77 | -497.7713549, 78 | -388.4001791, 79 | -269.9678681, 80 | -171.5032267, 81 | -109.4232825, 82 | -85.95174767, 83 | -92.10828026, 84 | -113.2780073, 85 | -135.0360867, 86 | -147.3718879, 87 | -146.4098449, 88 | -133.7447348, 89 | -114.2478841, 90 | -93.47710923, 91 | -75.65276972, 92 | -62.7102446, 93 | -54.43003551, 94 | -49.27247725, 95 | -45.40286383, 96 | -41.47519301, 97 | -36.96005775, 98 | -32.03813458, 99 | -27.24138061, 100 | -23.06824481, 101 | -19.74134791, 102 | -17.16692753, 103 | -15.05288342, 104 | -13.0867025, 105 | -11.07639512, 106 | -9.000690664, 107 | -6.969695578 108 | 109 | -------------------------------------------------------------------------------- /H_45_4_4kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter +45 degrees 4.4 kHz BW centred at 1.95 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 29.11.2015 13 | 14 | 15 | 6.509437479, 16 | 8.701141959, 17 | 11.25266191, 18 | 13.85770103, 19 | 16.24138295, 20 | 18.3820833, 21 | 20.60577107, 22 | 23.43462644, 23 | 27.22903282, 24 | 31.8457592, 25 | 36.60842518, 26 | 40.74896566, 27 | 44.15733731, 28 | 47.94978685, 29 | 54.2847411, 30 | 65.18253862, 31 | 80.7630921, 32 | 97.9544968, 33 | 110.874957, 34 | 113.4459517, 35 | 103.4881983, 36 | 86.21510505, 37 | 74.55191993, 38 | 84.70808446, 39 | 127.8132532, 40 | 201.1813276, 41 | 284.3156959, 42 | 343.7714, 43 | 347.2222251, 44 | 281.8920153, 45 | 168.4693634, 46 | 61.36605223, 47 | 30.91412412, 48 | 131.5762989, 49 | 368.8553084, 50 | 681.7674175, 51 | 954.2230065, 52 | 1057.460291, 53 | 910.7905335, 54 | 535.9903237, 55 | 78.16281223, 56 | -224.2373418, 57 | -117.7739814, 58 | 563.6628595, 59 | 1811.597791, 60 | 3409.21859, 61 | 4972.4099, 62 | 6058.734721, 63 | 6309.576793, 64 | 5574.771622, 65 | 3972.681199, 66 | 1861.277602, 67 | -271.2178163, 68 | -1957.439963, 69 | -2889.895068, 70 | -2999.892509, 71 | -2452.457023, 72 | -1565.387891, 73 | -687.7073961, 74 | -84.41276335, 75 | 132.7594105, 76 | 10.47711934, 77 | -297.1007839, 78 | -607.4886449, 79 | -783.1447725, 80 | -772.5905401, 81 | -610.0766125, 82 | -382.3281734, 83 | -182.2259722, 84 | -70.54435729, 85 | -59.30232252, 86 | -118.6373042, 87 | -199.0341911, 88 | -256.1843226, 89 | -267.5382217, 90 | -235.6625729, 91 | -180.2866913, 92 | -125.3087319, 93 | -87.63700845, 94 | -72.17467912, 95 | -73.42011939, 96 | -81.09257249, 97 | -86.10719706, 98 | -84.11104801, 99 | -75.72419935, 100 | -64.41969846, 101 | -53.80815385, 102 | -45.83030757, 103 | -40.44011136, 104 | -36.42720761, 105 | -32.55684725, 106 | -28.30476366, 107 | -23.91592185, 108 | -19.97629547, 109 | -16.90383427, 110 | -14.68898232, 111 | -12.97233085, 112 | -11.32212519, 113 | -9.492005554, 114 | -7.508954678 115 | 116 | -------------------------------------------------------------------------------- /H_45_6_5kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter +45 degrees 6.5 kHz BW centred at 3.01 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 29.11.2015 13 | 14 | 6.986059956, 15 | 7.998018718, 16 | 9.570156016, 17 | 12.28639981, 18 | 15.84990465, 19 | 19.22255407, 20 | 21.74130102, 21 | 24.00358922, 22 | 27.27438298, 23 | 31.8597577, 24 | 36.51785518, 25 | 40.17716132, 26 | 44.22088902, 27 | 51.8686323, 28 | 63.87592248, 29 | 75.04597226, 30 | 77.51711618, 31 | 70.40225757, 32 | 66.0515101, 33 | 82.28667582, 34 | 122.8437037, 35 | 164.7679, 36 | 172.1556842, 37 | 132.3777536, 38 | 81.90100609, 39 | 86.72127832, 40 | 180.7125082, 41 | 314.9378794, 42 | 379.1173255, 43 | 298.5513015, 44 | 127.6020484, 45 | 37.21636106, 46 | 174.0808953, 47 | 499.0281937, 48 | 768.286897, 49 | 721.6144623, 50 | 345.5755264, 51 | -35.73821545, 52 | 14.45367463, 53 | 640.1875821, 54 | 1459.388693, 55 | 1782.627908, 56 | 1201.799901, 57 | 94.17274997, 58 | -447.9304544, 59 | 651.5936703, 60 | 3534.466798, 61 | 7027.631681, 62 | 9203.069632, 63 | 8583.606606, 64 | 5165.725241, 65 | 504.7419505, 66 | -3231.953515, 67 | -4588.477726, 68 | -3605.56346, 69 | -1574.131822, 70 | -25.84031603, 71 | 261.6914517, 72 | -427.535548, 73 | -1218.129038, 74 | -1413.035526, 75 | -953.5807307, 76 | -302.8308272, 77 | 33.81361981, 78 | -91.76315242, 79 | -438.5426022, 80 | -654.3534844, 81 | -576.6686454, 82 | -314.5099439, 83 | -97.04314884, 84 | -63.42621133, 85 | -175.174775, 86 | -291.3849677, 87 | -306.384711, 88 | -223.6464423, 89 | -123.07449, 90 | -76.30613979, 91 | -92.47612337, 92 | -129.6705641, 93 | -143.7919151, 94 | -124.0439061, 95 | -90.30093823, 96 | -66.64995717, 97 | -60.66094905, 98 | -63.54918731, 99 | -63.7184974, 100 | -57.38663648, 101 | -48.3028136, 102 | -41.04196175, 103 | -36.44381807, 104 | -32.57057491, 105 | -28.05514556, 106 | -23.51223372, 107 | -20.18207363, 108 | -18.17033843, 109 | -16.38934674, 110 | -13.8877426, 111 | -10.81586798, 112 | -8.06634229, 113 | -6.245566115 114 | 115 | 116 | -------------------------------------------------------------------------------- /H_45_8kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter -45 degrees 8 kHz BW centred at 3.42 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 30.10.2015 13 | 14 | 15 | 6.633414101, 16 | 7.756349934, 17 | 9.953725805, 18 | 13.23489298, 19 | 16.43501445, 20 | 18.58134262, 21 | 20.32317346, 22 | 23.26005726, 23 | 27.7406422, 24 | 32.31915601, 25 | 36.17206786, 26 | 41.03514226, 27 | 48.73521458, 28 | 56.80050081, 29 | 59.73095394, 30 | 57.53439641, 31 | 60.73708002, 32 | 80.32499506, 33 | 109.7132147, 34 | 123.4701756, 35 | 104.9496856, 36 | 76.45063258, 37 | 87.75432551, 38 | 158.8479049, 39 | 237.5898291, 40 | 239.2293489, 41 | 148.1768903, 42 | 67.72890127, 43 | 129.4338743, 44 | 330.2996117, 45 | 487.7868716, 46 | 413.6302613, 47 | 154.7573904, 48 | 11.93669573, 49 | 240.3158505, 50 | 712.9672236, 51 | 961.6367407, 52 | 658.1749528, 53 | 68.3250261, 54 | -92.24233931, 55 | 600.6446691, 56 | 1667.944907, 57 | 2023.183108, 58 | 1098.293271, 59 | -262.1348649, 60 | -219.1384403, 61 | 2422.634946, 62 | 6768.91137, 63 | 10076.72575, 64 | 9751.147509, 65 | 5489.346886, 66 | -324.9965994, 67 | -4395.162478, 68 | -4959.263398, 69 | -2859.92455, 70 | -474.7090779, 71 | 367.4926217, 72 | -371.4335924, 73 | -1412.451323, 74 | -1606.618571, 75 | -906.3414745, 76 | -118.829315, 77 | 55.18196792, 78 | -347.0566111, 79 | -759.227485, 80 | -746.3355762, 81 | -386.8387341, 82 | -75.25863486, 83 | -68.2836477, 84 | -271.3673698, 85 | -415.1875201, 86 | -357.5182479, 87 | -187.0796801, 88 | -77.96173935, 89 | -99.75252347, 90 | -179.5155525, 91 | -211.7646949, 92 | -168.579145, 93 | -102.7083499, 94 | -72.05351461, 95 | -82.87667803, 96 | -101.209276, 97 | -99.19327901, 98 | -79.25838213, 99 | -60.12088926, 100 | -52.27068551, 101 | -51.32110208, 102 | -48.94766549, 103 | -43.07683776, 104 | -36.91752236, 105 | -32.61231093, 106 | -29.01903665, 107 | -24.64839091, 108 | -20.1269693, 109 | -17.0015871, 110 | -15.3868056, 111 | -13.87584898, 112 | -11.43669504, 113 | -8.534503433, 114 | -6.268219696 115 | 116 | -------------------------------------------------------------------------------- /H_90_8kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter 90 degrees 8 kHz BW centred at 3.42 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 4.11.2015 13 | 14 | 15 | 10.32453233, 16 | 12.85594973, 17 | 14.74217533, 18 | 16.98629445, 19 | 20.88247026, 20 | 26.1279941, 21 | 31.0091884, 22 | 34.85854562, 23 | 39.1753574, 24 | 45.24620385, 25 | 51.83200512, 26 | 57.42325191, 27 | 64.20121315, 28 | 75.90838559, 29 | 90.12319205, 30 | 97.51423586, 31 | 95.0040962, 32 | 97.06501391, 33 | 122.4537261, 34 | 164.2887647, 35 | 185.6344638, 36 | 162.8838859, 37 | 131.1328482, 38 | 159.0937599, 39 | 259.112288, 40 | 342.7500023, 41 | 310.2064036, 42 | 194.1607497, 43 | 164.5335127, 44 | 333.6003428, 45 | 573.1437502, 46 | 613.411185, 47 | 378.7623783, 48 | 159.9996687, 49 | 325.977589, 50 | 834.0594846, 51 | 1161.427301, 52 | 881.5684101, 53 | 284.9354007, 54 | 205.4483447, 55 | 1052.318749, 56 | 2120.497983, 57 | 2191.674725, 58 | 1026.2394, 59 | 75.01052677, 60 | 1261.223744, 61 | 4757.271899, 62 | 8107.638494, 63 | 8011.142995, 64 | 3366.752586, 65 | -3366.752586, 66 | -8011.142995, 67 | -8107.638494, 68 | -4757.271899, 69 | -1261.223744, 70 | -75.01052677, 71 | -1026.2394, 72 | -2191.674725, 73 | -2120.497983, 74 | -1052.318749, 75 | -205.4483447, 76 | -284.9354007, 77 | -881.5684101, 78 | -1161.427301, 79 | -834.0594846, 80 | -325.977589, 81 | -159.9996687, 82 | -378.7623783, 83 | -613.411185, 84 | -573.1437502, 85 | -333.6003428, 86 | -164.5335127, 87 | -194.1607497, 88 | -310.2064036, 89 | -342.7500023, 90 | -259.112288, 91 | -159.0937599, 92 | -131.1328482, 93 | -162.8838859, 94 | -185.6344638, 95 | -164.2887647, 96 | -122.4537261, 97 | -97.06501391, 98 | -95.0040962, 99 | -97.51423586, 100 | -90.12319205, 101 | -75.90838559, 102 | -64.20121315, 103 | -57.42325191, 104 | -51.83200512, 105 | -45.24620385, 106 | -39.1753574, 107 | -34.85854562, 108 | -31.0091884, 109 | -26.1279941, 110 | -20.88247026, 111 | -16.98629445, 112 | -14.74217533, 113 | -12.85594973, 114 | -10.32453233 115 | 116 | -------------------------------------------------------------------------------- /H_m45_11kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter -45 degrees 11kHz BW quasi-LPF 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 12.2.2016 13 | 14 | 15 | -5.594289936, 16 | -7.948154051, 17 | -10.81444631, 18 | -11.88178533, 19 | -13.18494618, 20 | -17.32187958, 21 | -21.4213101, 22 | -23.39106879, 23 | -26.63628722, 24 | -31.71843242, 25 | -35.90595893, 26 | -41.86965803, 27 | -49.62710273, 28 | -51.3936885, 29 | -53.64478675, 30 | -71.70414144, 31 | -87.13409276, 32 | -74.9101393, 33 | -73.67990907, 34 | -120.2973714, 35 | -145.031656, 36 | -98.33807423, 37 | -95.77515468, 38 | -199.3250733, 39 | -229.4300731, 40 | -114.8365213, 41 | -122.2494637, 42 | -326.4345649, 43 | -346.3493304, 44 | -114.7412396, 45 | -160.7628939, 46 | -528.9063939, 47 | -503.1259578, 48 | -85.69958164, 49 | -229.1790177, 50 | -854.7889892, 51 | -715.1414869, 52 | -10.75939603, 53 | -368.2022395, 54 | -1413.612069, 55 | -1031.558983, 56 | 144.6715194, 57 | -693.9470763, 58 | -2575.305981, 59 | -1671.028804, 60 | 526.3958177, 61 | -1818.408727, 62 | -7093.42431, 63 | -5299.463564, 64 | 6031.450296, 65 | 15007.47097, 66 | 11745.20674, 67 | 2535.364595, 68 | -866.6322336, 69 | 1857.86905, 70 | 2980.896185, 71 | 720.2175094, 72 | -327.5563334, 73 | 1024.310858, 74 | 1503.255448, 75 | 310.7506256, 76 | -128.3828858, 77 | 674.1768321, 78 | 862.4177547, 79 | 155.2357918, 80 | -23.70045263, 81 | 458.0383308, 82 | 508.1968284, 83 | 90.13385621, 84 | 30.94510115, 85 | 305.7506089, 86 | 297.0435216, 87 | 62.81124597, 88 | 53.39790532, 89 | 195.9717384, 90 | 170.2731402, 91 | 50.18344113, 92 | 55.56995208, 93 | 119.1668968, 94 | 95.8892844, 95 | 41.60685468, 96 | 46.8403169, 97 | 68.37696308, 98 | 53.5560537, 99 | 33.06049844, 100 | 34.19958512, 101 | 37.03273381, 102 | 29.90755654, 103 | 24.0464777, 104 | 22.07762721, 105 | 19.01549163, 106 | 16.55874166, 107 | 15.50958453, 108 | 12.58160357, 109 | 9.249534502, 110 | 8.717549752, 111 | 8.509178315, 112 | 6.135497413, 113 | 4.098248981, 114 | 3.940884316 115 | 116 | -------------------------------------------------------------------------------- /H_m45_1_8kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter -45 degrees 2.4 kHz centred at 0.662 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 30.10.2015 13 | 14 | -6.848914072, 15 | -8.835580968, 16 | -11.12232257, 17 | -13.67567667, 18 | -16.44166146, 19 | -19.36071589, 20 | -22.39034457, 21 | -25.53187854, 22 | -28.85540288, 23 | -32.51530148, 24 | -36.74864066, 25 | -41.85021153, 26 | -48.121628, 27 | -55.79717649, 28 | -64.95543062, 29 | -75.43187354, 30 | -86.75255196, 31 | -98.11072917, 32 | -108.4064742, 33 | -116.3625192, 34 | -120.7187045, 35 | -120.4929751, 36 | -115.2811119, 37 | -105.5527781, 38 | -92.89092522, 39 | -80.11787969, 40 | -71.25654397, 41 | -71.2899744, 42 | -85.70647949, 43 | -119.8480284, 44 | -178.1133736, 45 | -263.0990108, 46 | -374.7856368, 47 | -509.8902531, 48 | -661.5008591, 49 | -819.0901417, 50 | -968.9675055, 51 | -1095.178632, 52 | -1180.804262, 53 | -1209.5525, 54 | -1167.489741, 55 | -1044.721995, 56 | -836.8268234, 57 | -545.8496202, 58 | -180.7165199, 59 | 243.0238712, 60 | 704.1431657, 61 | 1177.293565, 62 | 1635.044018, 63 | 2050.190027, 64 | 2398.097812, 65 | 2658.83496, 66 | 2818.86112, 67 | 2872.101329, 68 | 2820.2951, 69 | 2672.597195, 70 | 2444.49065, 71 | 2156.148127, 72 | 1830.43486, 73 | 1490.778551, 74 | 1159.135347, 75 | 854.2572976, 76 | 590.4196493, 77 | 376.70322, 78 | 216.8568894, 79 | 109.6972779, 80 | 49.94546417, 81 | 29.36058223, 82 | 38.01099104, 83 | 65.526028, 84 | 102.1927621, 85 | 139.7979372, 86 | 172.1592168, 87 | 195.3352116, 88 | 207.5444211, 89 | 208.8543188, 90 | 200.7204433, 91 | 185.4606946, 92 | 165.7432526, 93 | 144.1503576, 94 | 122.8583218, 95 | 103.4505744, 96 | 86.85891582, 97 | 73.41127505, 98 | 62.95376806, 99 | 55.01115333, 100 | 48.95218076, 101 | 44.13330589, 102 | 40.00382538, 103 | 36.16565198, 104 | 32.38994243, 105 | 28.59939309, 106 | 24.8286344, 107 | 21.17581099, 108 | 17.7566592, 109 | 14.66903055, 110 | 11.97181026, 111 | 9.678414571, 112 | 7.762161934, 113 | 6.169149086 114 | 115 | 116 | -------------------------------------------------------------------------------- /H_m45_2_6kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter -45 degrees 2.8 kHz centred at 1.1 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 30.10.2015 13 | 14 | 15 | -7.698292841, 16 | -9.483069906, 17 | -11.32525903, 18 | -13.24051182, 19 | -15.30854418, 20 | -17.66923525, 21 | -20.49279361, 22 | -23.92620843, 23 | -28.02817094, 24 | -32.71359164, 25 | -37.7332309, 26 | -42.71078173, 27 | -47.24761449, 28 | -51.08550275, 29 | -54.29407651, 30 | -57.42896361, 31 | -61.59606488, 32 | -68.36362125, 33 | -79.48988635, 34 | -96.47848502, 35 | -120.0282992, 36 | -149.4973287, 37 | -182.5350922, 38 | -215.0413694, 39 | -241.5711365, 40 | -256.225816, 41 | -253.9596238, 42 | -232.1073943, 43 | -191.8345856, 44 | -139.1506394, 45 | -85.13761936, 46 | -45.13902546, 47 | -36.82366369, 48 | -77.26247812, 49 | -179.3921969, 50 | -348.4390731, 51 | -578.9900793, 52 | -853.3904754, 53 | -1141.999975, 54 | -1405.566523, 55 | -1599.616754, 56 | -1680.377683, 57 | -1611.408836, 58 | -1369.908249, 59 | -951.6121901, 60 | -373.3591967, 61 | 327.2805716, 62 | 1095.450552, 63 | 1865.158245, 64 | 2567.294386, 65 | 3138.346454, 66 | 3528.489237, 67 | 3707.817056, 68 | 3669.776984, 69 | 3431.317802, 70 | 3029.803404, 71 | 2517.255612, 72 | 1952.898514, 73 | 1395.205121, 74 | 894.6634694, 75 | 488.2894701, 76 | 196.5622197, 77 | 23.0159275, 78 | -43.72462626, 79 | -26.05123028, 80 | 47.55333512, 81 | 147.5754399, 82 | 247.8559854, 83 | 328.7099964, 84 | 378.4833265, 85 | 393.5565795, 86 | 377.0689701, 87 | 336.8103909, 88 | 282.7979317, 89 | 225.0164147, 90 | 171.6839803, 91 | 128.2389145, 92 | 97.07206447, 93 | 77.88494462, 94 | 68.4604564, 95 | 65.6002298, 96 | 66.00521915, 97 | 66.93897472, 98 | 66.59499666, 99 | 64.16966966, 100 | 59.70386353, 101 | 53.79005262, 102 | 47.2464471, 103 | 40.84059905, 104 | 35.11191162, 105 | 30.30625053, 106 | 26.40563827, 107 | 23.21755438, 108 | 20.4833112, 109 | 17.97132535, 110 | 15.53449297, 111 | 13.12616626, 112 | 10.78199001, 113 | 8.582345627, 114 | 6.611657604 115 | 116 | -------------------------------------------------------------------------------- /H_m45_3_6kHz.h: -------------------------------------------------------------------------------- 1 | // hilbert filter pair generated by Iowa Hills Software Hilbert tool 2 | // - 45 degree shift 3 | // Bandwidth 3.60kHz, Fc=1.76kHz, 20Hz -6dB, 3.8kHz -6dB 4 | // Sampl f 44117 5 | // Num Taps 100 6 | // DD4WH 29.10.2015 7 | 8 | -6.969695578, 9 | -9.000690664, 10 | -11.07639512, 11 | -13.0867025, 12 | -15.05288342, 13 | -17.16692753, 14 | -19.74134791, 15 | -23.06824481, 16 | -27.24138061, 17 | -32.03813458, 18 | -36.96005775, 19 | -41.47519301, 20 | -45.40286383, 21 | -49.27247725, 22 | -54.43003551, 23 | -62.7102446, 24 | -75.65276972, 25 | -93.47710923, 26 | -114.2478841, 27 | -133.7447348, 28 | -146.4098449, 29 | -147.3718879, 30 | -135.0360867, 31 | -113.2780073, 32 | -92.10828026, 33 | -85.95174767, 34 | -109.4232825, 35 | -171.5032267, 36 | -269.9678681, 37 | -388.4001791, 38 | -497.7713549, 39 | -563.3689529, 40 | -556.0096948, 41 | -464.5741928, 42 | -305.6441846, 43 | -126.0215978, 44 | 4.57200784, 45 | 10.52043767, 46 | -166.3579884, 47 | -543.3866144, 48 | -1080.9287, 49 | -1679.995309, 50 | -2196.702741, 51 | -2472.020293, 52 | -2370.437878, 53 | -1817.77798, 54 | -827.5853983, 55 | 492.1771637, 56 | 1955.491601, 57 | 3334.871169, 58 | 4409.644491, 59 | 5013.935458, 60 | 5072.170167, 61 | 4613.186703, 62 | 3759.755151, 63 | 2696.861508, 64 | 1627.570922, 65 | 728.1258916, 66 | 113.4415272, 67 | -179.3628122, 68 | -187.1234948, 69 | 0.235623066, 70 | 270.1818886, 71 | 518.5786483, 72 | 673.1688726, 73 | 704.6394141, 74 | 624.4709288, 75 | 472.524464, 76 | 299.659575, 77 | 151.1334913, 78 | 55.24814847, 79 | 19.3507752, 80 | 32.74314106, 81 | 74.11995044, 82 | 120.3178193, 83 | 153.4657989, 84 | 164.7669744, 85 | 154.5839367, 86 | 129.7274333, 87 | 99.50958536, 88 | 72.1290943, 89 | 52.45075847, 90 | 41.51024568, 91 | 37.41612538, 92 | 36.94131154, 93 | 37.05778833, 94 | 35.89990095, 95 | 32.99217451, 96 | 28.89082754, 97 | 24.55947766, 98 | 20.8031621, 99 | 17.96432365, 100 | 15.91954177, 101 | 14.28284387, 102 | 12.66443699, 103 | 10.85496704, 104 | 8.874981259, 105 | 6.905115864, 106 | 5.160887617, 107 | 3.78337329 108 | 109 | -------------------------------------------------------------------------------- /H_m45_4_4kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter -45 degrees 4.4 kHz BW centred at 1.95 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 29.11.2015 13 | 14 | -7.508954678, 15 | -9.492005554, 16 | -11.32212519, 17 | -12.97233085, 18 | -14.68898232, 19 | -16.90383427, 20 | -19.97629547, 21 | -23.91592185, 22 | -28.30476366, 23 | -32.55684725, 24 | -36.42720761, 25 | -40.44011136, 26 | -45.83030757, 27 | -53.80815385, 28 | -64.41969846, 29 | -75.72419935, 30 | -84.11104801, 31 | -86.10719706, 32 | -81.09257249, 33 | -73.42011939, 34 | -72.17467912, 35 | -87.63700845, 36 | -125.3087319, 37 | -180.2866913, 38 | -235.6625729, 39 | -267.5382217, 40 | -256.1843226, 41 | -199.0341911, 42 | -118.6373042, 43 | -59.30232252, 44 | -70.54435729, 45 | -182.2259722, 46 | -382.3281734, 47 | -610.0766125, 48 | -772.5905401, 49 | -783.1447725, 50 | -607.4886449, 51 | -297.1007839, 52 | 10.47711934, 53 | 132.7594105, 54 | -84.41276335, 55 | -687.7073961, 56 | -1565.387891, 57 | -2452.457023, 58 | -2999.892509, 59 | -2889.895068, 60 | -1957.439963, 61 | -271.2178163, 62 | 1861.277602, 63 | 3972.681199, 64 | 5574.771622, 65 | 6309.576793, 66 | 6058.734721, 67 | 4972.4099, 68 | 3409.21859, 69 | 1811.597791, 70 | 563.6628595, 71 | -117.7739814, 72 | -224.2373418, 73 | 78.16281223, 74 | 535.9903237, 75 | 910.7905335, 76 | 1057.460291, 77 | 954.2230065, 78 | 681.7674175, 79 | 368.8553084, 80 | 131.5762989, 81 | 30.91412412, 82 | 61.36605223, 83 | 168.4693634, 84 | 281.8920153, 85 | 347.2222251, 86 | 343.7714, 87 | 284.3156959, 88 | 201.1813276, 89 | 127.8132532, 90 | 84.70808446, 91 | 74.55191993, 92 | 86.21510505, 93 | 103.4881983, 94 | 113.4459517, 95 | 110.874957, 96 | 97.9544968, 97 | 80.7630921, 98 | 65.18253862, 99 | 54.2847411, 100 | 47.94978685, 101 | 44.15733731, 102 | 40.74896566, 103 | 36.60842518, 104 | 31.8457592, 105 | 27.22903282, 106 | 23.43462644, 107 | 20.60577107, 108 | 18.3820833, 109 | 16.24138295, 110 | 13.85770103, 111 | 11.25266191, 112 | 8.701141959, 113 | 6.509437479 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /H_m45_6_5kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter -45 degrees 6.5 kHz centred at 3.01 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 29.11.2015 13 | 14 | -6.245566115, 15 | -8.06634229, 16 | -10.81586798, 17 | -13.8877426, 18 | -16.38934674, 19 | -18.17033843, 20 | -20.18207363, 21 | -23.51223372, 22 | -28.05514556, 23 | -32.57057491, 24 | -36.44381807, 25 | -41.04196175, 26 | -48.3028136, 27 | -57.38663648, 28 | -63.7184974, 29 | -63.54918731, 30 | -60.66094905, 31 | -66.64995717, 32 | -90.30093823, 33 | -124.0439061, 34 | -143.7919151, 35 | -129.6705641, 36 | -92.47612337, 37 | -76.30613979, 38 | -123.07449, 39 | -223.6464423, 40 | -306.384711, 41 | -291.3849677, 42 | -175.174775, 43 | -63.42621133, 44 | -97.04314884, 45 | -314.5099439, 46 | -576.6686454, 47 | -654.3534844, 48 | -438.5426022, 49 | -91.76315242, 50 | 33.81361981, 51 | -302.8308272, 52 | -953.5807307, 53 | -1413.035526, 54 | -1218.129038, 55 | -427.535548, 56 | 261.6914517, 57 | -25.84031603, 58 | -1574.131822, 59 | -3605.56346, 60 | -4588.477726, 61 | -3231.953515, 62 | 504.7419505, 63 | 5165.725241, 64 | 8583.606606, 65 | 9203.069632, 66 | 7027.631681, 67 | 3534.466798, 68 | 651.5936703, 69 | -447.9304544, 70 | 94.17274997, 71 | 1201.799901, 72 | 1782.627908, 73 | 1459.388693, 74 | 640.1875821, 75 | 14.45367463, 76 | -35.73821545, 77 | 345.5755264, 78 | 721.6144623, 79 | 768.286897, 80 | 499.0281937, 81 | 174.0808953, 82 | 37.21636106, 83 | 127.6020484, 84 | 298.5513015, 85 | 379.1173255, 86 | 314.9378794, 87 | 180.7125082, 88 | 86.72127832, 89 | 81.90100609, 90 | 132.3777536, 91 | 172.1556842, 92 | 164.7679, 93 | 122.8437037, 94 | 82.28667582, 95 | 66.0515101, 96 | 70.40225757, 97 | 77.51711618, 98 | 75.04597226, 99 | 63.87592248, 100 | 51.8686323, 101 | 44.22088902, 102 | 40.17716132, 103 | 36.51785518, 104 | 31.8597577, 105 | 27.27438298, 106 | 24.00358922, 107 | 21.74130102, 108 | 19.22255407, 109 | 15.84990465, 110 | 12.28639981, 111 | 9.570156016, 112 | 7.998018718, 113 | 6.986059956 114 | 115 | -------------------------------------------------------------------------------- /H_m45_8kHz.h: -------------------------------------------------------------------------------- 1 | // Hilbert filter -45 degrees 8 kHz BW centred at 3.42 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills Hilbert Filter Designer 5 | // 6 | // 7 | // 100 taps 8 | // 9 | // Window Kaiser 10 | // 11 | 12 | // DD4WH 30.10.2015 13 | 14 | 15 | -6.268219696, 16 | -8.534503433, 17 | -11.43669504, 18 | -13.87584898, 19 | -15.3868056, 20 | -17.0015871, 21 | -20.1269693, 22 | -24.64839091, 23 | -29.01903665, 24 | -32.61231093, 25 | -36.91752236, 26 | -43.07683776, 27 | -48.94766549, 28 | -51.32110208, 29 | -52.27068551, 30 | -60.12088926, 31 | -79.25838213, 32 | -99.19327901, 33 | -101.209276, 34 | -82.87667803, 35 | -72.05351461, 36 | -102.7083499, 37 | -168.579145, 38 | -211.7646949, 39 | -179.5155525, 40 | -99.75252347, 41 | -77.96173935, 42 | -187.0796801, 43 | -357.5182479, 44 | -415.1875201, 45 | -271.3673698, 46 | -68.2836477, 47 | -75.25863486, 48 | -386.8387341, 49 | -746.3355762, 50 | -759.227485, 51 | -347.0566111, 52 | 55.18196792, 53 | -118.829315, 54 | -906.3414745, 55 | -1606.618571, 56 | -1412.451323, 57 | -371.4335924, 58 | 367.4926217, 59 | -474.7090779, 60 | -2859.92455, 61 | -4959.263398, 62 | -4395.162478, 63 | -324.9965994, 64 | 5489.346886, 65 | 9751.147509, 66 | 10076.72575, 67 | 6768.91137, 68 | 2422.634946, 69 | -219.1384403, 70 | -262.1348649, 71 | 1098.293271, 72 | 2023.183108, 73 | 1667.944907, 74 | 600.6446691, 75 | -92.24233931, 76 | 68.3250261, 77 | 658.1749528, 78 | 961.6367407, 79 | 712.9672236, 80 | 240.3158505, 81 | 11.93669573, 82 | 154.7573904, 83 | 413.6302613, 84 | 487.7868716, 85 | 330.2996117, 86 | 129.4338743, 87 | 67.72890127, 88 | 148.1768903, 89 | 239.2293489, 90 | 237.5898291, 91 | 158.8479049, 92 | 87.75432551, 93 | 76.45063258, 94 | 104.9496856, 95 | 123.4701756, 96 | 109.7132147, 97 | 80.32499506, 98 | 60.73708002, 99 | 57.53439641, 100 | 59.73095394, 101 | 56.80050081, 102 | 48.73521458, 103 | 41.03514226, 104 | 36.17206786, 105 | 32.31915601, 106 | 27.7406422, 107 | 23.26005726, 108 | 20.32317346, 109 | 18.58134262, 110 | 16.43501445, 111 | 13.23489298, 112 | 9.953725805, 113 | 7.756349934, 114 | 6.633414101 115 | 116 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Teensy_SDR 2 | Software defined radio using Teensy 3.1, Teensy Audio shield and Softrock 3 | 4 | This is a software defined radio using the Arduino compatible Teensy 3.1 and audio shield from PJRC. 5 | It takes advantage of the audio library supplied by PJRC to implement the audio signal processing chain. 6 | 7 | Dependencies - most of these libraries are available from PJRC and can be installed with the Teensyduino package: 8 | 9 | Audio - Teensy Audio library V1.02, 10 | SD (not used but needed for the audio libraries to compile), 11 | SPI, 12 | Wire, 13 | Metro, 14 | Bounce, 15 | Encoder, 16 | SI5351 (github.com/NT7S/Si5351), 17 | Adafruit Graphics library (adafruit.com), 18 | Driver for your display - I used a Banggood knockoff of the AdaFruit 1.8" TFT 19 | 20 | Changelog: 21 | Jan 2015 - first public release, RX only 22 | March 2015 - CW and SSB TX mode added, band swiching added, general cleanup of the code 23 | April 9 2015 - added the driver for the Banggood 1.8" display and a slightly modded SI5351 library for the Teensy which has no eeprom 24 | - move these to your Arduino/libraries folder 25 | 26 | NOTE: code compiles OK with Arduino 1.61 and Teensyduino 1.21 BUT sometimes image is not suppressed as evidenced 27 | by signals moving both ways when you tune. Seems that if you recompile and reload once or twice its fine until 28 | the next time you recompile and flash the code. Tool chain bug ??? 29 | 30 | TODO: 31 | - fix software AGC which no longer works after port to audio lib 1.02 32 | - S Meter needs improvement 33 | - UI improvements - configuration settings etc 34 | - clean up display code - remove direct x,y references to allow easier modifications 35 | 36 | project blog: rheslip.blogspot.com 37 | 38 | -------------------------------------------------------------------------------- /Schedule.h: -------------------------------------------------------------------------------- 1 | // Example schedule 2 | 5900 BUL english EU NEWS 1845-1900 3 | 5905 CHN russian China R Int. 1400-1500 4 | 5905 CHN english Deutsche Welle 0300-0400 5 | 6 | 7 | -------------------------------------------------------------------------------- /Teensy.SDR.Documentation.DD4WH.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DD4WH/Teensy-SDR-Rx/604e869c1a3ddf9f0c1d11a3293e7fdd24fc2d43/Teensy.SDR.Documentation.DD4WH.pdf -------------------------------------------------------------------------------- /agc.cpp: -------------------------------------------------------------------------------- 1 | // soft AGC and S meter display by Loftur E. Jónasson TF3LJ/VE2LJX 6/14 2 | // 3 | 4 | #include 5 | #include 6 | 7 | #include // LCD Core graphics library 8 | //#include // 1.8" TFT Module using Samsung S6D02A1 chip 9 | #include // Hardware-specific library 10 | 11 | //extern Adafruit_QDTech tft; 12 | extern Adafruit_ST7735 tft; 13 | 14 | extern AudioMixer4 Audioselector_I; // Summer (add inputs) 15 | extern AudioMixer4 Audioselector_Q; // Summer (add inputs) 16 | extern AudioAnalyzePeak AGCpeak; // Measure Audio Peak for AGC use 17 | extern AudioAnalyzePeak Smeter; // Measure Audio Peak for S meter 18 | 19 | Metro l_ms = Metro(1); // Set up a 1ms Metro 20 | Metro lcd_upd2=Metro(500); // Set up a Metro for S-meter display 21 | 22 | float sample[10]; // A ringbuffer of samples (has to be larger than AGCattack) 23 | 24 | float AGCgain=1; // Initial AGC gain. 1 = unity gain, 32768.0 max, 0.00004 min 25 | #define AGCMAX 2 26 | float AGCnomVal = 0.5; // Nominal Output (32768 max) 27 | const int32_t AGCattack = 2; // AGC Hang time (milliseconds) before reducing gain 28 | const int32_t AGChang = 30; // AGC Hang time before increasing gain 29 | const double AGCslope = 1.05; // Relative gain change 30 | 31 | 32 | // 33 | // Automatic Gain Control function 34 | // 35 | void agc(void) 36 | { 37 | static uint8_t i; 38 | static uint16_t hangtimer; 39 | uint8_t j,k; 40 | float s_sample; // Raw signal strength (max per 1ms) 41 | float samp; // AGC feedback loop sample strength (max per 1ms) 42 | float temp; // yeah, just a temp value 43 | float uv, dbuv, s, v, dbm;// microvolts, db-microvolts, s-units, volts, dbm, sold = old S-meter value, deltas = abs difference between sold and s 44 | char string[80]; // print format stuff 45 | 46 | if (l_ms.check() == 1) 47 | { 48 | // R this code is probably broken with the new audio library 49 | // Collect S-meter data 50 | if (Smeter.available()) s_sample = Smeter.read(); // Highest sample within 1 millisecond 51 | // AGC: Collect current 1ms peak at output and feed to a ringbuffer 52 | sample[i++] = samp = AGCpeak.read(); 53 | 54 | if (i >= AGCattack) i=0; 55 | 56 | // Check if we need to reduce gain 57 | for(j=0,k=0;j AGCnomVal) k++; 60 | } 61 | 62 | // We need to reduce gain 63 | if ((k == AGCattack) || ((k>0) && (hangtimer>=AGChang))) // Activate AGCattack 64 | { 65 | // find largest value 66 | temp = 0; 67 | for(j=0;j temp) temp = sample[j]; 70 | } 71 | 72 | // Instant reduction to appropriate value 73 | AGCgain = AGCgain * AGCnomVal/temp; 74 | // Reset hang timer 75 | hangtimer = 0; 76 | } 77 | 78 | // Increment hangtimer while level is lower than nominal 79 | else if(samp < AGCnomVal) hangtimer++; 80 | 81 | if (hangtimer >= AGChang) // We need to ramp up the gain 82 | { 83 | Audioselector_I.gain(0, AGCgain * AGCslope); 84 | Audioselector_Q.gain(0, AGCgain * AGCslope); 85 | } 86 | 87 | if (AGCgain > AGCMAX) AGCgain=AGCMAX; // limit the gain 88 | 89 | Audioselector_I.gain(0,AGCgain); // Adjust AGC gain 90 | Audioselector_Q.gain(0,AGCgain); // Adjust AGC gain 91 | // 92 | // Print stuff to LCD 93 | // 94 | if (lcd_upd2.check() == 1) 95 | { 96 | // Calculate S units. 50uV = S9 97 | 98 | uv = s_sample*1000; // microvolts, roughly calibrated 99 | v = s_sample / 1000; 100 | dbm = 10 * log10 (v*v*20); 101 | if (v==0) {dbm=-143;}; 102 | dbuv = 20.0*log10(uv); 103 | s = 1.0 + (14.0 + dbuv)/6.0; 104 | 105 | if (s <0.0) s=0.0; 106 | if (s>9.0) 107 | { 108 | dbuv = dbuv - 34.0; 109 | s = 9.0; 110 | } 111 | else dbuv = 0; 112 | // Print S units 113 | tft.fillRect(0, 105, 70, 7,ST7735_BLACK); 114 | tft.setCursor(0, 105); 115 | if (dbuv == 0) sprintf(string,"S:%1.0f",s); 116 | else { 117 | sprintf(string,"S:9+%02.0f dB",dbuv); 118 | 119 | } 120 | tft.print(string); 121 | tft.fillRect(100,105, 50, 7,ST7735_BLACK); 122 | tft.setCursor(100,105); 123 | sprintf(string,"%04.0f dBm",dbm); 124 | tft.print(string); 125 | 126 | if(0) // Debug stuff 127 | { 128 | // Print AGC loop parameters 129 | tft.fillRect(0, 105, 159, 7,ST7735_BLACK); 130 | tft.setCursor(0, 105); 131 | sprintf(string,"pk:%f g:%f",Smeter.read(), AGCgain); 132 | tft.print(string); 133 | } 134 | } 135 | } 136 | } 137 | 138 | -------------------------------------------------------------------------------- /analyze_fft256iq.cpp: -------------------------------------------------------------------------------- 1 | /* Audio Library for Teensy 3.X 2 | * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com 3 | * 4 | * Development of this audio library was funded by PJRC.COM, LLC by sales of 5 | * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop 6 | * open source software by purchasing Teensy or other PJRC products. 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice, development funding notice, and this permission 16 | * notice shall be included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include "analyze_fft256iq.h" 28 | #include "utility/sqrt_integer.h" 29 | #include "utility/dspinst.h" 30 | 31 | 32 | // 140312 - PAH - slightly faster copy 33 | static void copy_to_fft_buffer(void *destination, const void *source1, const void *source2) 34 | { 35 | const uint16_t *src1 = (const uint16_t *)source1; 36 | const uint16_t *src2 = (const uint16_t *)source2; 37 | uint32_t *dst = (uint32_t *)destination; 38 | 39 | for (int i=0; i < AUDIO_BLOCK_SAMPLES; i++) { 40 | 41 | *dst++ = *src1++ | ((*src2++) <<16); 42 | } 43 | } 44 | 45 | static void apply_window_to_fft_buffer(void *buffer, const void *window) 46 | { 47 | int16_t *buf = (int16_t *)buffer; 48 | const int16_t *win = (int16_t *)window;; 49 | 50 | for (int i=0; i < 256; i++) { 51 | 52 | buf[0] = (buf[0] * *win) >> 15; 53 | buf[1] = (buf[1] * *win) >> 15; 54 | buf += 2; 55 | win++; 56 | } 57 | 58 | } 59 | 60 | void AudioAnalyzeFFT256IQ::update(void) 61 | { 62 | audio_block_t *block_i,*block_q; 63 | 64 | 65 | block_i=receiveReadOnly(0); 66 | block_q=receiveReadOnly(1); 67 | if (!block_i || !block_q ) return; 68 | if (!prevblock_i || !prevblock_q) { 69 | prevblock_i = block_i; 70 | prevblock_q = block_q; 71 | return; 72 | } 73 | copy_to_fft_buffer(buffer, prevblock_i->data,prevblock_q->data); 74 | copy_to_fft_buffer(buffer+256, block_i->data,block_q->data); 75 | 76 | if (window) apply_window_to_fft_buffer(buffer, window); 77 | arm_cfft_radix4_q15(&fft_inst, buffer); 78 | 79 | // G. Heinzel's paper says we're supposed to average the magnitude 80 | // squared, then do the square root at the end. 81 | if (count == 0) { 82 | for (int i=0; i < 256; i++) { 83 | uint32_t tmp = *((uint32_t *)buffer + i); 84 | uint32_t magsq = multiply_16tx16t_add_16bx16b(tmp, tmp); 85 | sum[i] = magsq / naverage; 86 | } 87 | } else { 88 | for (int i=0; i < 256; i++) { 89 | uint32_t tmp = *((uint32_t *)buffer + i); 90 | uint32_t magsq = multiply_16tx16t_add_16bx16b(tmp, tmp); 91 | sum[i] += magsq / naverage; 92 | } 93 | } 94 | if (++count == naverage) { 95 | count = 0; 96 | 97 | 98 | 99 | 100 | 101 | for (int i = 0; i < 256; i++) { 102 | output[255 - (i ^ 128)] = sqrt_uint32_approx(sum[i]); 103 | } 104 | 105 | 106 | 107 | outputflag = true; 108 | } 109 | release(prevblock_i); 110 | release(prevblock_q); 111 | prevblock_i = block_i; 112 | prevblock_q = block_q; 113 | } 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /analyze_fft256iq.h: -------------------------------------------------------------------------------- 1 | /* Audio Library for Teensy 3.X 2 | * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com 3 | * 4 | * Development of this audio library was funded by PJRC.COM, LLC by sales of 5 | * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop 6 | * open source software by purchasing Teensy or other PJRC products. 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice, development funding notice, and this permission 16 | * notice shall be included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef analyze_fft256iq_h_ 28 | #define analyze_fft256iq_h_ 29 | 30 | #include "AudioStream.h" 31 | #include "arm_math.h" 32 | 33 | // windows.c 34 | extern "C" { 35 | extern const int16_t AudioWindowHanning256[]; 36 | extern const int16_t AudioWindowBartlett256[]; 37 | extern const int16_t AudioWindowBlackman256[]; 38 | extern const int16_t AudioWindowFlattop256[]; 39 | extern const int16_t AudioWindowBlackmanHarris256[]; 40 | extern const int16_t AudioWindowNuttall256[]; 41 | extern const int16_t AudioWindowBlackmanNuttall256[]; 42 | extern const int16_t AudioWindowWelch256[]; 43 | extern const int16_t AudioWindowHamming256[]; 44 | extern const int16_t AudioWindowCosine256[]; 45 | extern const int16_t AudioWindowTukey256[]; 46 | } 47 | 48 | class AudioAnalyzeFFT256IQ : public AudioStream 49 | { 50 | public: 51 | AudioAnalyzeFFT256IQ() : AudioStream(2, inputQueueArray), 52 | window(AudioWindowBlackmanNuttall256), prevblock_i(NULL), prevblock_q(NULL),count(0), 53 | naverage(8), outputflag(false) { 54 | arm_cfft_radix4_init_q15(&fft_inst, 256, 0, 1); 55 | } 56 | 57 | bool available() { 58 | if (outputflag == true) { 59 | outputflag = false; 60 | return true; 61 | } 62 | return false; 63 | } 64 | 65 | float read(unsigned int binNumber) { 66 | if (binNumber > 255) return 0.0; 67 | return (float)(output[binNumber]) * (1.0 / 16384.0); 68 | } 69 | 70 | float read(unsigned int binFirst, unsigned int binLast) { 71 | if (binFirst > binLast) { 72 | unsigned int tmp = binLast; 73 | binLast = binFirst; 74 | binFirst = tmp; 75 | } 76 | if (binFirst > 255) return 0.0; 77 | if (binLast > 255) binLast = 255; 78 | uint32_t sum = 0; 79 | do { 80 | sum += output[binFirst++]; 81 | } while (binFirst < binLast); 82 | return (float)sum * (1.0 / 16384.0); 83 | } 84 | 85 | void averageTogether(uint8_t n) { 86 | if (n == 0) n = 1; 87 | naverage = n; 88 | } 89 | 90 | void windowFunction(const int16_t *w) { 91 | window = w; 92 | } 93 | 94 | virtual void update(void); 95 | uint16_t output[256] __attribute__ ((aligned (4))); 96 | private: 97 | const int16_t *window; 98 | audio_block_t *prevblock_i,*prevblock_q; 99 | int16_t buffer[512] __attribute__ ((aligned (4))); 100 | uint32_t sum[256]; 101 | uint8_t count; 102 | uint8_t naverage; 103 | volatile bool outputflag; 104 | audio_block_t *inputQueueArray[2]; 105 | arm_cfft_radix4_instance_q15 fft_inst; 106 | }; 107 | 108 | #endif 109 | 110 | -------------------------------------------------------------------------------- /display.cpp: -------------------------------------------------------------------------------- 1 | // code for the TFT display 2 | 3 | #include "analyze_fft256iq.h" 4 | #include 5 | #include "display.h" 6 | #include 7 | #include // LCD Core graphics library 8 | //#include // 1.8" TFT Module using Samsung S6D02A1 chip 9 | #include // Hardware-specific library 10 | //extern Adafruit_QDTech tft; 11 | extern Adafruit_ST7735 tft; 12 | #define pos 50 // position of spectrum display, has to be < 124 13 | #define pos_version 119 // position of version number printing 14 | #define pos_x_tunestep 100 15 | #define pos_y_tunestep 119 // = pos_y_menu 91 16 | #define pos_x_frequency 21 //100 17 | #define pos_y_frequency 61 //119 18 | #define pos_x_smeter 5 19 | #define pos_y_smeter 94 20 | #define s_w 10 21 | #define notchpos 2 22 | #define notchL 15 23 | #define notchColour YELLOW 24 | //#define pos_centre_f 58 // Rx below IF, IF = 5515 25 | int pos_centre_f = 98; // Rx above IF, IF = 5515 26 | #define spectrum_span 44.118 27 | #define font_width 12 28 | uint8_t sch = 0; 29 | bool freq_flag = 0; 30 | 31 | extern AudioAnalyzeFFT256IQ myFFT; 32 | 33 | float uv, uvold, dbuv, dbm, s;// microvolts, db-microvolts, s-units, volts, dbm, sold = old S-meter value, deltas = abs difference between sold and s 34 | float dbmold = 0; 35 | char string[80]; 36 | int le, bwhelp, left, lsb; 37 | int pixelold[160] = {0}; 38 | int pixelnew[160]; 39 | int oldnotchF = 10000; 40 | uint8_t digits_old [] = {9,9,9,9,9,9,9,9,9,9}; 41 | 42 | Metro Smetertimer = Metro(50); 43 | 44 | //extern AudioAnalyzeFFT256 myFFT; // FFT for Spectrum Display 45 | 46 | void init_display(void) { 47 | tft.initR(INITR_BLACKTAB); 48 | } 49 | 50 | void setup_display(void) { 51 | 52 | // initialize the LCD display 53 | // tft.init(); 54 | // tft.initR(INITR_BLACKTAB); // initialize a S6D02A1S chip, black tab 55 | tft.setRotation(1); 56 | tft.fillScreen(BLACK); //BLACK); 57 | //tft.fillRect(0, pos, 160, 128-pos, BLACK); // erase old string 58 | tft.setCursor(0, 119); 59 | tft.setTextColor(WHITE); 60 | tft.setTextWrap(true); 61 | // tft.print("DD4WH SDR 5.00"); 62 | 63 | // Show mid screen tune position 64 | tft.drawFastVLine(pos_centre_f, 0,pos+1, RED); //WHITE); 65 | // tft.drawFastHLine(0, pos,79, YELLOW);// WHITE); 66 | //tft.drawFastHLine(81, pos,79, YELLOW); 67 | 68 | // draw S-Meter layout 69 | tft.drawFastHLine (pos_x_smeter, pos_y_smeter-1, 9*s_w, WHITE); 70 | tft.drawFastHLine (pos_x_smeter, pos_y_smeter+3, 9*s_w, WHITE); 71 | tft.fillRect(pos_x_smeter, pos_y_smeter-3, 2, 2, WHITE); 72 | tft.fillRect(pos_x_smeter+8*s_w, pos_y_smeter-3, 2, 2, WHITE); 73 | tft.fillRect(pos_x_smeter+2*s_w, pos_y_smeter-3, 2, 2, WHITE); 74 | tft.fillRect(pos_x_smeter+4*s_w, pos_y_smeter-3, 2, 2, WHITE); 75 | tft.fillRect(pos_x_smeter+6*s_w, pos_y_smeter-3, 2, 2, WHITE); 76 | tft.fillRect(pos_x_smeter+7*s_w, pos_y_smeter-4, 2, 3, WHITE); 77 | tft.fillRect(pos_x_smeter+3*s_w, pos_y_smeter-4, 2, 3, WHITE); 78 | tft.fillRect(pos_x_smeter+5*s_w, pos_y_smeter-4, 2, 3, WHITE); 79 | tft.fillRect(pos_x_smeter+s_w, pos_y_smeter-4, 2, 3, WHITE); 80 | tft.fillRect(pos_x_smeter+9*s_w, pos_y_smeter-4, 2, 3, WHITE); 81 | tft.drawFastHLine (pos_x_smeter+9*s_w, pos_y_smeter-1, 3*s_w*2+2, GREEN); 82 | tft.drawFastHLine (pos_x_smeter+9*s_w, pos_y_smeter+3, 3*s_w*2+2, GREEN); 83 | tft.fillRect(pos_x_smeter+11*s_w, pos_y_smeter-4, 2, 3, GREEN); 84 | tft.fillRect(pos_x_smeter+13*s_w, pos_y_smeter-4, 2, 3, GREEN); 85 | tft.fillRect(pos_x_smeter+15*s_w, pos_y_smeter-4, 2, 3, GREEN); 86 | tft.drawFastVLine (pos_x_smeter-1, pos_y_smeter-1, 5, WHITE); 87 | tft.drawFastVLine (pos_x_smeter+15*s_w+2, pos_y_smeter-1, 5, GREEN); 88 | 89 | tft.setCursor(pos_x_smeter - 4, pos_y_smeter - 13); 90 | tft.setTextColor(WHITE); 91 | tft.setTextWrap(true); 92 | tft.print("S 1"); 93 | tft.setCursor(pos_x_smeter + 28, pos_y_smeter - 13); 94 | tft.print("3"); 95 | tft.setCursor(pos_x_smeter + 48, pos_y_smeter - 13); 96 | tft.print("5"); 97 | tft.setCursor(pos_x_smeter + 68, pos_y_smeter - 13); 98 | tft.print("7"); 99 | tft.setCursor(pos_x_smeter + 88, pos_y_smeter - 13); 100 | tft.print("9"); 101 | tft.setCursor(pos_x_smeter + 120, pos_y_smeter - 13); 102 | tft.print("+20dB"); 103 | 104 | } // end void setupdisplay 105 | 106 | // draw the spectrum display 107 | // this version draws 1/10 of the spectrum per call but we run it 10x the speed 108 | // this allows other stuff to run without blocking for so long 109 | 110 | void show_spectrum(float line_gain, float LPFcoeff) { 111 | static int startx=0, endx; 112 | endx=startx+16; 113 | int scale=3; 114 | float avg = 0.0; 115 | // Draw spectrum display 116 | for (int16_t x=startx; x < endx; x+=1) { 117 | 118 | if ((x > 1) && (x < 159)) 119 | // moving window - weighted average of 5 points of the spectrum to smooth spectrum in the frequency domain 120 | // weights: x: 50% , x-1/x+1: 36%, x+2/x-2: 14% 121 | avg = myFFT.output[(x)*16/10]*0.5 + myFFT.output[(x-1)*16/10]*0.18 + myFFT.output[(x-2)*16/10]*0.07 + myFFT.output[(x+1)*16/10]*0.18 + myFFT.output[(x+2)*16/10]*0.07; 122 | else 123 | avg = myFFT.output[(x)*16/10]; 124 | // pixelnew[x] = LPFcoeff * 2 * sqrt (abs(myFFT.output[(x)*16/10])*scale) + (1 - LPFcoeff) * pixelold[x]; 125 | // low pass filtering of the spectrum pixels to smooth/slow down spectrum in the time domain 126 | // experimental LPF for spectrum: ynew = LPCoeff * x + (1-LPCoeff) * yprevious; here: A = 0.3 to 0.5 seems to be a good idea 127 | pixelnew[x] = LPFcoeff * 2 * sqrt (abs(avg)*scale) + (1 - LPFcoeff) * pixelold[x]; 128 | 129 | /* for (int16_t i=0; x < 5; x+=1) { 130 | 131 | pixelnew[x+i] = 2 * sqrt (abs(myFFT.output[(x+i)*16/10])*scale); 132 | if (pixelnew[x+i] > pos-1) pixelnew[x+i] = pos-1; 133 | } 134 | */ 135 | // int bar=2 * sqrt (abs(myFFT.output[x*16/10])*scale); 136 | // if (bar >pos-1) bar=pos-1; 137 | 138 | if(x != pos_centre_f) { 139 | // common way: draw bars 140 | // tft.drawFastVLine(x, pos-1-bar,bar, BLUE); // GREEN); 141 | // tft.drawFastVLine(x, 0, pos-1-bar, WHITE); //BLACK); 142 | // alternate way: draw pixels 143 | // only plot pixel, if at a new position 144 | if (pixelold[x] != pixelnew[x]) { 145 | tft.drawPixel(x, pos-1-pixelold[x], BLACK); // delete old pixel 146 | tft.drawPixel(x, pos-1-pixelnew[x], WHITE); // write new pixel 147 | pixelold[x] = pixelnew[x]; } 148 | /* if (pixelnew[x] > 5 * (pixelnew[x+1] + pixelnew[x-1])) { 149 | tft.drawFastVLine(x, pos-1-pixelnew[x], pixelnew[x], BLUE); 150 | tft.drawFastVLine(x, 0, pos-1- pixelnew[x], BLACK); 151 | } 152 | */ } 153 | } 154 | 155 | 156 | 157 | // Calculate S units. 50uV = S9 158 | //if (0) { 159 | if (Smetertimer.check()==1) { 160 | uv = myFFT.output[159]+myFFT.output[160]+myFFT.output[161]+myFFT.output[162]+myFFT.output[158]+myFFT.output[157]+myFFT.output[156]; // measure signal strength of carrier of AM Transmission at exact frequency 161 | // low pass filtering for Smeter values 162 | uv = 0.1 * uv + 0.9 * uvold; 163 | 164 | if (uv == 0) dbm = -130; 165 | else { 166 | dbm = 20*log10(uv)-83.5-25.7-1.5*line_gain;} //dbm standardized to 15.26Hz Receiver Bandwidth 167 | 168 | // constant 83.5dB determined empirically by measuring a carrier with a Perseus SDR 169 | // and comparing the output of the Teensy FFT 170 | // 25.7dB is INA163 gain in frontend 171 | //dbm measurement on the Perseus standardized to RBW of 15.26Hz 172 | // float vol = analogRead(15); 173 | // vol = vol / 1023.0; 174 | // now calculate S-value from dbm 175 | s = 9.0 + ((dbm + 73.0) / 6.0); 176 | if (s <0.0) s=0.0; 177 | if ( s > 9.0) 178 | { 179 | dbuv = dbm + 73.0; 180 | s = 9.0; 181 | } 182 | else dbuv = 0.0; 183 | 184 | // Print S units 185 | //s=roundf(s); 186 | /* tft.fillRect(0,105, 50, 7,ST7735_BLACK); 187 | tft.fillRect(0,105, 160, 7,ST7735_BLACK); 188 | tft.setCursor(100,105); 189 | // sprintf(string,"%04.0f FFT",uv); 190 | // sprintf(string,"%04.0f dbm",dbm); 191 | sprintf(string,"%02.0f",s); 192 | tft.print(string); 193 | tft.setCursor(0,105); 194 | // sprintf(string,"%04.0f FFT",uv); 195 | sprintf(string,"%04.0f dbm",dbm); 196 | tft.print(string); 197 | */ 198 | tft.drawFastHLine(pos_x_smeter, pos_y_smeter, s*s_w+1, BLUE); 199 | tft.drawFastHLine(pos_x_smeter+s*s_w+1, pos_y_smeter, (9*s_w+1)-s*s_w+1, BLACK); 200 | 201 | tft.drawFastHLine(pos_x_smeter, pos_y_smeter+1, s*s_w+1, WHITE); 202 | tft.drawFastHLine(pos_x_smeter+s*s_w+1, pos_y_smeter+1, (9*s_w+1)-s*s_w+1, BLACK); 203 | tft.drawFastHLine(pos_x_smeter, pos_y_smeter+2, s*s_w+1, BLUE); 204 | tft.drawFastHLine(pos_x_smeter+s*s_w+1, pos_y_smeter+2, (9*s_w+1)-s*s_w+1, BLACK); 205 | 206 | // tft.drawFastHLine(pos_x_smeter, pos_y_smeter+3, s*s_w+1, BLUE); 207 | // tft.drawFastHLine(pos_x_smeter+s*s_w+1, pos_y_smeter+3, (9*s_w+1)-s*s_w+1, BLACK); 208 | 209 | if(dbuv>30) dbuv=30; 210 | tft.drawFastHLine(pos_x_smeter+9*s_w+1, pos_y_smeter, (dbuv/5)*s_w+1, RED); 211 | tft.drawFastHLine(pos_x_smeter+9*s_w+(dbuv/5)*s_w+1, pos_y_smeter, (6*s_w+1)-(dbuv/5)*s_w, BLACK); 212 | tft.drawFastHLine(pos_x_smeter+9*s_w+1, pos_y_smeter+1, (dbuv/5)*s_w+1, RED); 213 | tft.drawFastHLine(pos_x_smeter+9*s_w+(dbuv/5)*s_w+1, pos_y_smeter+1, (6*s_w+1)-(dbuv/5)*s_w, BLACK); 214 | tft.drawFastHLine(pos_x_smeter+9*s_w+1, pos_y_smeter+2, (dbuv/5)*s_w+1, RED); 215 | tft.drawFastHLine(pos_x_smeter+9*s_w+(dbuv/5)*s_w+1, pos_y_smeter+2, (6*s_w+1)-(dbuv/5)*s_w, BLACK); 216 | 217 | // tft.drawFastHLine(pos_x_smeter+9*s_w+1, pos_y_smeter+3, (dbuv/5)*s_w+1, RED); 218 | // tft.drawFastHLine(pos_x_smeter+9*s_w+(dbuv/5)*s_w+1, pos_y_smeter+3, (6*s_w+1)-(dbuv/5)*s_w, BLACK); 219 | 220 | 221 | // tft.fillRect(0, 105, 70, 7,ST7735_BLACK); 222 | // tft.setCursor(0, 105); 223 | // if (dbuv == 0) sprintf(string,"S:%1.0f",s); 224 | // else { 225 | // sprintf(string,"S:9+%02.0f dB",dbuv); 226 | 227 | // } 228 | // tft.print(string); 229 | // tft.fillRect(100,105, 50, 7,ST7735_BLACK); 230 | // tft.setCursor(100,105); 231 | // sprintf(string,"%04.0f dBm",dbm); 232 | // tft.print(string); 233 | uvold = uv; 234 | } // end if (Smeter Timer) 235 | 236 | startx+=16; 237 | if(startx >=160) startx=0; 238 | 239 | 240 | //digitalWrite(DEBUG_PIN,0); // 241 | } 242 | 243 | /* old draw routine 244 | // draw the spectrum display 245 | 246 | void show_spectrum(void) { 247 | 248 | int scale=1; 249 | for (int16_t x=0; x < 160; x+=2) 250 | { 251 | int bar=abs(myFFT.output[x*8/10])/scale; 252 | if (bar >60) bar=60; 253 | if(x!=80) 254 | { 255 | tft.drawFastVLine(x, 60-bar,bar, GREEN); 256 | tft.drawFastVLine(x, 0, 60-bar, BLACK); 257 | } 258 | } 259 | } 260 | */ 261 | 262 | void show_waterfall(void) { 263 | // experimental waterfall display for CW - 264 | // this should probably be on a faster timer since it needs to run as fast as possible to catch CW edges 265 | // FFT bins are 22khz/128=171hz wide 266 | // cw peak should be around 11.6khz - 267 | static uint16_t waterfall[80]; // array for simple waterfall display 268 | static uint8_t w_index=0,w_avg; 269 | waterfall[w_index]=0; 270 | for (uint8_t y=66;y<67;++y) // sum of bin powers near cursor - usb only 271 | waterfall[w_index]+=(uint8_t)(abs(myFFT.output[y])); // store bin power readings in circular buffer 272 | waterfall[w_index]|= (waterfall[w_index]<<5 |waterfall[w_index]<<11); // make it colorful 273 | int8_t p=w_index; 274 | for (uint8_t x=158;x>0;x-=2) { 275 | tft.fillRect(x,65,2,4,waterfall[p]); 276 | if (--p<0 ) p=79; 277 | } 278 | if (++w_index >=80) w_index=0; 279 | } 280 | 281 | 282 | 283 | void show_bandwidth (int M, long int FU, long int FL) { 284 | 285 | tft.drawFastHLine(0,pos+1,160, BLACK); // erase old indicator 286 | tft.drawFastHLine(0,pos+2,160, BLACK); // erase old indicator 287 | tft.drawFastHLine(0,pos+3,160, BLACK); // erase old indicator 288 | tft.drawFastHLine(0,pos,160, BLACK); // erase old indicator 289 | 290 | bwhelp = FU /100; 291 | int leU = bwhelp*16/spectrum_span; 292 | bwhelp = FL /100; 293 | int leL = bwhelp*16/spectrum_span; 294 | float kHz = (FU + FL) / 1000.0; 295 | 296 | switch (M) { 297 | case 0: //AM 298 | tft.fillRect(4, pos_y_frequency-3, 32, 8, BLACK); // erase old string 299 | tft.setTextColor(GREEN); 300 | tft.setCursor(4, pos_y_frequency-3); 301 | tft.print("AM"); 302 | break; 303 | case 3: //DSB 304 | tft.fillRect(4, pos_y_frequency-3, 32, 8, BLACK); // erase old string 305 | tft.setTextColor(GREEN); 306 | tft.setCursor(4, pos_y_frequency-3); 307 | tft.print("DSB"); 308 | break; 309 | case 4: //StereoAM 310 | tft.fillRect(4, pos_y_frequency-3, 32, 8, BLACK); // erase old string 311 | tft.setTextColor(GREEN); 312 | tft.setCursor(4, pos_y_frequency-3); 313 | tft.print("SteAM"); 314 | break; 315 | 316 | case 2: //LSB 317 | tft.fillRect(4, pos_y_frequency-3, 32, 8, BLACK); // erase old string 318 | tft.setTextColor(GREEN); 319 | tft.setCursor(4, pos_y_frequency-3); 320 | tft.print("LSB"); 321 | break; 322 | case 1: //USB 323 | tft.fillRect(4, pos_y_frequency-3, 32, 8, BLACK); // erase old string 324 | tft.setTextColor(GREEN); 325 | tft.setCursor(4, pos_y_frequency-3); 326 | tft.print("USB"); 327 | break; 328 | } // end switch 329 | //print bandwidth ! 330 | tft.fillRect(4, pos_y_frequency+7, 32, 8, BLACK); // erase old string 331 | tft.setCursor(4, pos_y_frequency+7); 332 | sprintf(string,"%02.1fk",kHz); 333 | tft.print(string); 334 | tft.setTextColor(WHITE); // set text color to white for other print routines not to get confused ;-) 335 | // draw upper sideband indicator 336 | tft.drawFastHLine(pos_centre_f, pos+1, leU, RED); 337 | tft.drawFastHLine(pos_centre_f, pos+2, leU, RED); 338 | tft.drawFastHLine(pos_centre_f, pos+3, leU, RED); 339 | tft.drawFastHLine(pos_centre_f, pos, leU, RED); 340 | // draw lower sideband indicator 341 | left = pos_centre_f - leL; 342 | tft.drawFastHLine(left+1, pos+1, leL, RED); 343 | tft.drawFastHLine(left+1, pos+2, leL, RED); 344 | tft.drawFastHLine(left+1,pos+3, leL, RED); 345 | tft.drawFastHLine(left+1,pos, leL, RED); 346 | 347 | tft.fillRect(pos_centre_f + 160/spectrum_span * 5, pos, 2, 3, YELLOW); // erase old string 348 | tft.fillRect(pos_centre_f + 160/spectrum_span * 10, pos, 2, 4, YELLOW); // erase old string 349 | tft.fillRect(pos_centre_f - 160/spectrum_span * 5, pos, 2, 3, YELLOW); // erase old string 350 | tft.fillRect(pos_centre_f - 160/spectrum_span * 10, pos, 2, 4, YELLOW); // erase old string 351 | tft.fillRect(pos_centre_f - 160/spectrum_span * 15, pos, 2, 3, YELLOW); // erase old string 352 | tft.fillRect(pos_centre_f + 160/spectrum_span * 15, pos, 2, 3, YELLOW); // erase old string 353 | tft.fillRect(pos_centre_f - 160/spectrum_span * 20, pos, 2, 4, YELLOW); // erase old string 354 | tft.fillRect(pos_centre_f - 160/spectrum_span * 25, pos, 2, 3, YELLOW); // erase old string 355 | tft.fillRect(pos_centre_f - 160/spectrum_span * 30, pos, 2, 4, YELLOW); // erase old string 356 | } 357 | 358 | 359 | 360 | 361 | void show_tunestep(String S) { // show band 362 | char string[80]; 363 | tft.fillRect(pos_x_tunestep, pos_y_tunestep, 60, 8, BLACK); // erase old string 364 | tft.setTextColor(WHITE); 365 | tft.setCursor(pos_x_tunestep, pos_y_tunestep); 366 | tft.print(S); 367 | } 368 | 369 | // show radio mode 370 | void show_radiomode(String mode) { 371 | // tft.fillRect(125, 85, 30, 7, BLACK); // erase old string 372 | // tft.setTextColor(WHITE); 373 | // tft.setCursor(125, 85); 374 | // tft.print(mode); 375 | } 376 | 377 | void show_band(String bandname) { // show band 378 | // tft.fillRect(100, 85, 19, 7, BLACK); // erase old string 379 | // tft.setTextColor(WHITE); 380 | // tft.setCursor(100, 85); 381 | // tft.print(bandname); 382 | } 383 | 384 | void show_notch(int notchF, int MODE) { 385 | // pos_centre_f is the x position of the Rx centre 386 | // pos is the y position of the spectrum display 387 | // notch display should be at x = pos_centre_f +- notch frequency and y = 20 388 | // LSB: 389 | pos_centre_f+=1; // = pos_centre_f + 1; 390 | // delete old indicator 391 | tft.drawFastVLine(pos_centre_f + 1 + 160/spectrum_span * oldnotchF / 1000, notchpos, notchL, BLACK); 392 | tft.drawFastVLine(pos_centre_f + 160/spectrum_span * oldnotchF / 1000, notchpos, notchL, BLACK); 393 | tft.drawFastVLine(pos_centre_f -1 + 160/spectrum_span * oldnotchF / 1000, notchpos, notchL, BLACK); 394 | tft.drawFastHLine(pos_centre_f -4 + 160/spectrum_span * oldnotchF / 1000, notchpos+notchL, 9, BLACK); 395 | tft.drawFastHLine(pos_centre_f -3 + 160/spectrum_span * oldnotchF / 1000, notchpos+notchL + 1, 7, BLACK); 396 | tft.drawFastHLine(pos_centre_f -2 + 160/spectrum_span * oldnotchF / 1000, notchpos+notchL + 2, 5, BLACK); 397 | tft.drawFastHLine(pos_centre_f -1 + 160/spectrum_span * oldnotchF / 1000, notchpos+notchL + 3, 3, BLACK); 398 | tft.drawFastVLine(pos_centre_f + 160/spectrum_span * oldnotchF / 1000, notchpos+notchL + 4, 2, BLACK); 399 | 400 | tft.drawFastVLine(pos_centre_f +1 - 160/spectrum_span * oldnotchF / 1000, notchpos, notchL, BLACK); 401 | tft.drawFastVLine(pos_centre_f - 160/spectrum_span * oldnotchF / 1000, notchpos, notchL, BLACK); 402 | tft.drawFastVLine(pos_centre_f -1 - 160/spectrum_span * oldnotchF / 1000, notchpos, notchL, BLACK); 403 | tft.drawFastHLine(pos_centre_f -4 - 160/spectrum_span * oldnotchF / 1000, notchpos+notchL, 9, BLACK); 404 | tft.drawFastHLine(pos_centre_f -3 - 160/spectrum_span * oldnotchF / 1000, notchpos+notchL + 1, 7, BLACK); 405 | tft.drawFastHLine(pos_centre_f -2 - 160/spectrum_span * oldnotchF / 1000, notchpos+notchL + 2, 5, BLACK); 406 | tft.drawFastHLine(pos_centre_f -1 - 160/spectrum_span * oldnotchF / 1000, notchpos+notchL + 3, 3, BLACK); 407 | tft.drawFastVLine(pos_centre_f - 160/spectrum_span * oldnotchF / 1000, notchpos+notchL + 4, 2, BLACK); 408 | // Show mid screen tune position 409 | tft.drawFastVLine(pos_centre_f - 1, 0,pos+1, RED); //WHITE); 410 | 411 | if (notchF >= 400 || notchF <= -400) { 412 | // draw new indicator according to mode 413 | switch (MODE) { 414 | case 2: //modeLSB: 415 | tft.drawFastVLine(pos_centre_f + 1 - 160/spectrum_span * notchF / -1000, notchpos, notchL, notchColour); 416 | tft.drawFastVLine(pos_centre_f - 160/spectrum_span * notchF / -1000, notchpos, notchL, notchColour); 417 | tft.drawFastVLine(pos_centre_f -1 - 160/spectrum_span * notchF / -1000, notchpos, notchL, notchColour); 418 | tft.drawFastHLine(pos_centre_f -4 - 160/spectrum_span * notchF / -1000, notchpos+notchL, 9, notchColour); 419 | tft.drawFastHLine(pos_centre_f -3 - 160/spectrum_span * notchF / -1000, notchpos+notchL + 1, 7, notchColour); 420 | tft.drawFastHLine(pos_centre_f -2 - 160/spectrum_span * notchF / -1000, notchpos+notchL + 2, 5, notchColour); 421 | tft.drawFastHLine(pos_centre_f -1 - 160/spectrum_span * notchF / -1000, notchpos+notchL + 3, 3, notchColour); 422 | tft.drawFastVLine(pos_centre_f - 160/spectrum_span * notchF / -1000, notchpos+notchL + 4, 2, notchColour); 423 | break; 424 | case 1: //modeUSB: 425 | tft.drawFastVLine(pos_centre_f +1 + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 426 | tft.drawFastVLine(pos_centre_f + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 427 | tft.drawFastVLine(pos_centre_f -1 + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 428 | tft.drawFastHLine(pos_centre_f -4 + 160/spectrum_span * notchF / 1000, notchpos+notchL, 9, notchColour); 429 | tft.drawFastHLine(pos_centre_f -3 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 1, 7, notchColour); 430 | tft.drawFastHLine(pos_centre_f -2 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 2, 5, notchColour); 431 | tft.drawFastHLine(pos_centre_f -1 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 3, 3, notchColour); 432 | tft.drawFastVLine(pos_centre_f + 160/spectrum_span * notchF / 1000, notchpos+notchL + 4, 2, notchColour); 433 | break; 434 | case 0: // modeAM: 435 | tft.drawFastVLine(pos_centre_f + 1 + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 436 | tft.drawFastVLine(pos_centre_f + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 437 | tft.drawFastVLine(pos_centre_f - 1 + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 438 | tft.drawFastHLine(pos_centre_f -4 + 160/spectrum_span * notchF / 1000, notchpos+notchL, 9, notchColour); 439 | tft.drawFastHLine(pos_centre_f -3 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 1, 7, notchColour); 440 | tft.drawFastHLine(pos_centre_f -2 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 2, 5, notchColour); 441 | tft.drawFastHLine(pos_centre_f -1 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 3, 3, notchColour); 442 | tft.drawFastVLine(pos_centre_f + 160/spectrum_span * notchF / 1000, notchpos+notchL + 4, 2, notchColour); 443 | 444 | tft.drawFastVLine(pos_centre_f + 1 - 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 445 | tft.drawFastVLine(pos_centre_f - 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 446 | tft.drawFastVLine(pos_centre_f - 1 - 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 447 | tft.drawFastHLine(pos_centre_f -4 - 160/spectrum_span * notchF / 1000, notchpos+notchL, 9, notchColour); 448 | tft.drawFastHLine(pos_centre_f -3 - 160/spectrum_span * notchF / 1000, notchpos+notchL + 1, 7, notchColour); 449 | tft.drawFastHLine(pos_centre_f -2 - 160/spectrum_span * notchF / 1000, notchpos+notchL + 2, 5, notchColour); 450 | tft.drawFastHLine(pos_centre_f -1 - 160/spectrum_span * notchF / 1000, notchpos+notchL + 3, 3, notchColour); 451 | tft.drawFastVLine(pos_centre_f - 160/spectrum_span * notchF / 1000, notchpos+notchL + 4, 2, notchColour); 452 | break; 453 | case 3: //modeDSB: 454 | case 4: //modeStereoAM: 455 | if (notchF <=-400) { 456 | tft.drawFastVLine(pos_centre_f + 1 - 160/spectrum_span * notchF / -1000, notchpos, notchL, notchColour); 457 | tft.drawFastVLine(pos_centre_f - 160/spectrum_span * notchF / -1000, notchpos, notchL, notchColour); 458 | tft.drawFastVLine(pos_centre_f - 1 - 160/spectrum_span * notchF / -1000, notchpos, notchL, notchColour); 459 | tft.drawFastHLine(pos_centre_f -4 - 160/spectrum_span * notchF / -1000, notchpos+notchL, 9, notchColour); 460 | tft.drawFastHLine(pos_centre_f -3 - 160/spectrum_span * notchF / -1000, notchpos+notchL + 1, 7, notchColour); 461 | tft.drawFastHLine(pos_centre_f -2 - 160/spectrum_span * notchF / -1000, notchpos+notchL + 2, 5, notchColour); 462 | tft.drawFastHLine(pos_centre_f -1 - 160/spectrum_span * notchF / -1000, notchpos+notchL + 3, 3, notchColour); 463 | tft.drawFastVLine(pos_centre_f - 160/spectrum_span * notchF / -1000, notchpos+notchL + 4, 2, notchColour); 464 | } 465 | if (notchF >=400) { 466 | tft.drawFastVLine(pos_centre_f + 1 + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 467 | tft.drawFastVLine(pos_centre_f + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 468 | tft.drawFastVLine(pos_centre_f - 1 + 160/spectrum_span * notchF / 1000, notchpos, notchL, notchColour); 469 | tft.drawFastHLine(pos_centre_f -4 + 160/spectrum_span * notchF / 1000, notchpos+notchL, 9, notchColour); 470 | tft.drawFastHLine(pos_centre_f -3 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 1, 7, notchColour); 471 | tft.drawFastHLine(pos_centre_f -2 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 2, 5, notchColour); 472 | tft.drawFastHLine(pos_centre_f -1 + 160/spectrum_span * notchF / 1000, notchpos+notchL + 3, 3, notchColour); 473 | tft.drawFastVLine(pos_centre_f + 160/spectrum_span * notchF / 1000, notchpos+notchL + 4, 2, notchColour); 474 | } 475 | break; 476 | } 477 | } 478 | oldnotchF = notchF; 479 | pos_centre_f-=1; // = pos_centre_f - 1; 480 | } // end void show_notch 481 | 482 | 483 | int ExtractDigit(long int n, int k) { 484 | switch (k) { 485 | case 0: return n%10; 486 | case 1: return n/10%10; 487 | case 2: return n/100%10; 488 | case 3: return n/1000%10; 489 | case 4: return n/10000%10; 490 | case 5: return n/100000%10; 491 | case 6: return n/1000000%10; 492 | case 7: return n/10000000%10; 493 | case 8: return n/100000000%10; 494 | } 495 | } 496 | 497 | 498 | 499 | // show frequency 500 | void show_frequency(long int freq) { 501 | tft.setTextSize(2); 502 | tft.setTextColor(WHITE); 503 | uint8_t zaehler; 504 | uint8_t digits[10]; 505 | zaehler = 8; 506 | 507 | while (zaehler--) { 508 | digits[zaehler] = ExtractDigit (freq, zaehler); 509 | // Serial.print(digits[zaehler]); 510 | // Serial.print("."); 511 | // 7: 10Mhz, 6: 1Mhz, 5: 100khz, 4: 10khz, 3: 1khz, 2: 100Hz, 1: 10Hz, 0: 1Hz 512 | } 513 | // Serial.print("xxxxxxxxxxxxx"); 514 | 515 | zaehler = 8; 516 | while (zaehler--) { // counts from 7 to 0 517 | if (zaehler < 6) sch = 7; // (khz) 518 | if (zaehler < 3) sch = 14; // (Hz) 519 | if (digits[zaehler] != digits_old[zaehler] || !freq_flag) { // digit has changed (or frequency is displayed for the first time after power on) 520 | if (zaehler == 7) { 521 | sch = 0; 522 | tft.setCursor(pos_x_frequency + font_width * (8-zaehler) + sch,pos_y_frequency); // set print position 523 | tft.fillRect(pos_x_frequency + font_width * (8-zaehler) + sch,pos_y_frequency, font_width,16,BLACK); // delete old digit 524 | if (digits[7] != 0) tft.print(digits[zaehler]); // write new digit in white 525 | } 526 | if (zaehler == 6) { 527 | sch = 0; 528 | tft.setCursor(pos_x_frequency + font_width * (8-zaehler) + sch,pos_y_frequency); // set print position 529 | tft.fillRect(pos_x_frequency + font_width * (8-zaehler) + sch,pos_y_frequency, font_width,16,BLACK); // delete old digit 530 | if (digits[6]!=0 || digits[7] != 0) tft.print(digits[zaehler]); // write new digit in white 531 | } 532 | if (zaehler == 5) { 533 | sch = 7; 534 | tft.setCursor(pos_x_frequency + font_width * (8-zaehler) + sch,pos_y_frequency); // set print position 535 | tft.fillRect(pos_x_frequency + font_width * (8-zaehler) + sch,pos_y_frequency, font_width,16,BLACK); // delete old digit 536 | if (digits[5] != 0 || digits[6]!=0 || digits[7] != 0) tft.print(digits[zaehler]); // write new digit in white 537 | } 538 | 539 | if (zaehler < 5) { 540 | // print the digit 541 | tft.setCursor(pos_x_frequency + font_width * (8-zaehler) + sch,pos_y_frequency); // set print position 542 | tft.fillRect(pos_x_frequency + font_width * (8-zaehler) + sch,pos_y_frequency, font_width,16,BLACK); // delete old digit 543 | tft.print(digits[zaehler]); // write new digit in white 544 | } 545 | digits_old[zaehler] = digits[zaehler]; 546 | } 547 | } 548 | 549 | tft.setTextSize(1); 550 | if (digits[7] == 0 && digits[6] == 0) 551 | tft.fillRect(pos_x_frequency + font_width * 3,pos_y_frequency + 11, 3, 3, BLACK); 552 | else tft.fillRect(pos_x_frequency + font_width * 3,pos_y_frequency + 11, 3, 3, YELLOW); 553 | tft.fillRect(pos_x_frequency + font_width * 7 -4, pos_y_frequency + 11, 3, 3, YELLOW); 554 | if (!freq_flag) { 555 | tft.setCursor(pos_x_frequency + font_width * 9 + 16,pos_y_frequency + 7); // set print position 556 | tft.setTextColor(GREEN); 557 | tft.print("Hz"); 558 | } 559 | freq_flag = 1; 560 | tft.setTextColor(WHITE); 561 | 562 | } // END VOID SHOW-FREQUENCY 563 | 564 | 565 | -------------------------------------------------------------------------------- /display.h: -------------------------------------------------------------------------------- 1 | // TFT stuff - change these defs for your specific LCD 2 | #define BLACK ST7735_BLACK 3 | #define WHITE ST7735_WHITE 4 | #define RED ST7735_RED 5 | #define GREEN ST7735_GREEN 6 | #define YELLOW ST7735_YELLOW 7 | #define BLUE ST7735_BLUE 8 | 9 | /* 10 | #define LSB_18 0 11 | #define USB_18 1 12 | #define AM_18 2 13 | #define LSB_26 3 14 | #define USB_26 4 15 | #define AM_26 5 16 | #define LSB_36 6 17 | #define USB_36 7 18 | #define AM_36 8 19 | #define LSB_44 9 20 | #define USB_44 10 21 | #define AM_44 11 22 | #define LSB_65 12 23 | #define USB_65 13 24 | #define AM_65 14 25 | #define LSB_80 15 26 | #define USB_80 16 27 | #define AM_80 17 28 | #define LSB_80_90 18 29 | #define USB_80_90 19 30 | #define AM_80_90 20 31 | */ 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /filters.cpp: -------------------------------------------------------------------------------- 1 | #include "filters.h" 2 | 3 | extern const short fir18[]; 4 | extern const short fir26[]; 5 | extern const short fir36[]; 6 | extern const short fir44[]; 7 | extern const short fir65[]; 8 | extern const short fir80[]; 9 | 10 | const short fir18[BPF_COEFFS] = { 11 | #include "fir_18.h" 12 | }; 13 | const short fir26[BPF_COEFFS] = { 14 | #include "fir_26.h" 15 | }; 16 | const short fir36[BPF_COEFFS] = { 17 | #include "fir_36.h" 18 | }; 19 | const short fir44[BPF_COEFFS] = { 20 | #include "fir_44.h" 21 | }; 22 | const short fir65[BPF_COEFFS] = { 23 | #include "fir_65.h" 24 | }; 25 | const short fir80[BPF_COEFFS] = { 26 | #include "fir_80.h" 27 | }; 28 | 29 | const short H_45_1_8kHz[HILBERT_COEFFS] = { 30 | #include "H_45_1_8kHz.h" 31 | }; 32 | const short H_m45_1_8kHz[HILBERT_COEFFS] = { 33 | #include "H_m45_1_8kHz.h" 34 | }; 35 | const short H_45_2_6kHz[HILBERT_COEFFS] = { 36 | #include "H_45_2_6kHz.h" 37 | }; 38 | const short H_m45_2_6kHz[HILBERT_COEFFS] = { 39 | #include "H_m45_2_6kHz.h" 40 | }; 41 | const short H_45_3_6kHz[HILBERT_COEFFS] = { 42 | #include "H_45_3_6kHz.h" 43 | }; 44 | const short H_m45_3_6kHz[HILBERT_COEFFS] = { 45 | #include "H_m45_3_6kHz.h" 46 | }; 47 | const short H_45_4_4kHz[HILBERT_COEFFS] = { 48 | #include "H_45_4_4kHz.h" 49 | }; 50 | const short H_m45_4_4kHz[HILBERT_COEFFS] = { 51 | #include "H_m45_4_4kHz.h" 52 | }; 53 | const short H_45_6_5kHz[HILBERT_COEFFS] = { 54 | #include "H_45_6_5kHz.h" 55 | }; 56 | const short H_m45_6_5kHz[HILBERT_COEFFS] = { 57 | #include "H_m45_6_5kHz.h" 58 | }; 59 | const short H_45_8kHz[HILBERT_COEFFS] = { 60 | #include "H_45_8kHz.h" 61 | }; 62 | const short H_m45_8kHz[HILBERT_COEFFS] = { 63 | #include "H_m45_8kHz.h" 64 | }; 65 | const short H_45_11kHz[HILBERT_COEFFS] = { 66 | #include "H_45_11kHz.h" 67 | }; 68 | const short H_m45_11kHz[HILBERT_COEFFS] = { 69 | #include "H_m45_11kHz.h" 70 | }; 71 | 72 | const short H_0_8kHz[HILBERT_COEFFS] = { 73 | #include "H_0_8kHz.h" 74 | }; 75 | const short H_90_8kHz[HILBERT_COEFFS] = { 76 | #include "H_90_8kHz.h" 77 | }; 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /filters.h: -------------------------------------------------------------------------------- 1 | // Number of coefficients 2 | 3 | #define HILBERT_COEFFS 100 4 | 5 | extern const short H_45_1_8kHz[]; 6 | extern const short H_m45_1_8kHz[]; 7 | extern const short H_45_2_6kHz[]; 8 | extern const short H_m45_2_6kHz[]; 9 | extern const short H_45_3_6kHz[]; 10 | extern const short H_m45_3_6kHz[]; 11 | extern const short H_45_4_4kHz[]; 12 | extern const short H_m45_4_4kHz[]; 13 | extern const short H_45_6_5kHz[]; 14 | extern const short H_m45_6_5kHz[]; 15 | extern const short H_45_8kHz[]; 16 | extern const short H_m45_8kHz[]; 17 | extern const short H_45_11kHz[]; 18 | extern const short H_m45_11kHz[]; 19 | extern const short H_0_8kHz[]; 20 | extern const short H_90_8kHz[]; 21 | 22 | 23 | #define BPF_COEFFS 66 24 | extern const short fir18[]; 25 | extern const short fir26[]; 26 | extern const short fir36[]; 27 | extern const short fir44[]; 28 | extern const short fir65[]; 29 | extern const short fir80[]; 30 | 31 | // IIR filters 32 | //#define biquad_stages 6 33 | /*extern double IIR_44_Coeffs_0[]; 34 | extern double IIR_44_Coeffs_1[]; 35 | extern double IIR_44_Coeffs_2[]; 36 | extern double IIR_44_Coeffs_3[]; 37 | extern double IIR_44_Coeffs_4[]; 38 | extern double IIR_44_Coeffs_5[]; 39 | */ 40 | 41 | -------------------------------------------------------------------------------- /fir_18.h: -------------------------------------------------------------------------------- 1 | // DD4WH 2 | // LPF DC - 1.8kHz 3 | // Parameters generated using Iowa Hills FIR Filter Designer 4 | // 5 | // 6 | // 66 taps 7 | // 8 | // Window off 9 | // Parks McClellan 10 | 11 | 9.299441866, 12 | 16.74781696, 13 | 25.80724755, 14 | 40.47982508, 15 | 53.79197069, 16 | 69.29403049, 17 | 79.81187103, 18 | 86.62233013, 19 | 82.73027132, 20 | 68.49327542, 21 | 38.54010883, 22 | -5.583080169, 23 | -65.67373886, 24 | -136.8280938, 25 | -215.8081372, 26 | -293.3667232, 27 | -361.4043424, 28 | -407.4525083, 29 | -420.991244, 30 | -389.725924, 31 | -305.0705477, 32 | -159.5805819, 33 | 48.64385019, 34 | 318.1140328, 35 | 640.9503688, 36 | 1005.244186, 37 | 1393.646585, 38 | 1786.147562, 39 | 2160.088633, 40 | 2493.099141, 41 | 2763.995248, 42 | 2955.299726, 43 | 3054.248644, 44 | 3054.248644, 45 | 2955.299726, 46 | 2763.995248, 47 | 2493.099141, 48 | 2160.088633, 49 | 1786.147562, 50 | 1393.646585, 51 | 1005.244186, 52 | 640.9503688, 53 | 318.1140328, 54 | 48.64385019, 55 | -159.5805819, 56 | -305.0705477, 57 | -389.725924, 58 | -420.991244, 59 | -407.4525083, 60 | -361.4043424, 61 | -293.3667232, 62 | -215.8081372, 63 | -136.8280938, 64 | -65.67373886, 65 | -5.583080169, 66 | 38.54010883, 67 | 68.49327542, 68 | 82.73027132, 69 | 86.62233013, 70 | 79.81187103, 71 | 69.29403049, 72 | 53.79197069, 73 | 40.47982508, 74 | 25.80724755, 75 | 16.74781696, 76 | 9.299441866 77 | 78 | -------------------------------------------------------------------------------- /fir_26.h: -------------------------------------------------------------------------------- 1 | // DD4WH 2 | // LPF DC - 2.4kHz 3 | // Parameters generated using Iowa Hills FIR Filter Designer 4 | // 5 | // 6 | // 66 taps 7 | // 8 | // Window off 9 | // Parks McClellan 10 | 11 | -12.54396008, 12 | -18.98644895, 13 | -29.47939609, 14 | -39.46002254, 15 | -45.90475594, 16 | -45.2848674, 17 | -34.197298, 18 | -10.32169337, 19 | 26.62667291, 20 | 74.06976236, 21 | 126.1847062, 22 | 174.0437616, 23 | 206.5335654, 24 | 211.9958717, 25 | 180.4266544, 26 | 105.9483986, 27 | -10.87715739, 28 | -161.3721063, 29 | -328.1492175, 30 | -485.9186149, 31 | -603.7961646, 32 | -648.9670845, 33 | -591.2888504, 34 | -408.2204747, 35 | -89.29072613, 36 | 360.6655203, 37 | 920.1510716, 38 | 1551.919229, 39 | 2206.210844, 40 | 2826.00418, 41 | 3353.623209, 42 | 3737.797326, 43 | 3940.148885, 44 | 3940.148885, 45 | 3737.797326, 46 | 3353.623209, 47 | 2826.00418, 48 | 2206.210844, 49 | 1551.919229, 50 | 920.1510716, 51 | 360.6655203, 52 | -89.29072613, 53 | -408.2204747, 54 | -591.2888504, 55 | -648.9670845, 56 | -603.7961646, 57 | -485.9186149, 58 | -328.1492175, 59 | -161.3721063, 60 | -10.87715739, 61 | 105.9483986, 62 | 180.4266544, 63 | 211.9958717, 64 | 206.5335654, 65 | 174.0437616, 66 | 126.1847062, 67 | 74.06976236, 68 | 26.62667291, 69 | -10.32169337, 70 | -34.197298, 71 | -45.2848674, 72 | -45.90475594, 73 | -39.46002254, 74 | -29.47939609, 75 | -18.98644895, 76 | -12.54396008 77 | 78 | -------------------------------------------------------------------------------- /fir_36.h: -------------------------------------------------------------------------------- 1 | // fir_lsb_44 2 | // Lowpass Filter by DD4WH DC to 3.6kHz, 3 | // (sampling rate 44.117 kHz) 4 | // 29.10.2015 5 | // Parameters generated using Iowa Hills FIR Filter Designer 6 | // 66 taps 7 | // Window off 8 | // Parks McClellan 9 | // 10 | 11 | -12.84963301, 12 | -14.03741957, 13 | -13.40139073, 14 | -3.632956693, 15 | 16.88507849, 16 | 45.28360944, 17 | 73.45343713, 18 | 89.22748606, 19 | 80.0968851, 20 | 38.4763929, 21 | -33.03596387, 22 | -118.820004, 23 | -191.8078123, 24 | -220.1747099, 25 | -178.1423548, 26 | -57.84469672, 27 | 122.0628014, 28 | 315.2052879, 29 | 456.1755615, 30 | 478.4870886, 31 | 337.7776717, 32 | 33.4788915, 33 | -378.7006808, 34 | -789.4745507, 35 | -1055.961515, 36 | -1035.780505, 37 | -627.1467052, 38 | 196.0867735, 39 | 1365.336328, 40 | 2721.406588, 41 | 4042.951094, 42 | 5093.409388, 43 | 5674.879965, 44 | 5674.879965, 45 | 5093.409388, 46 | 4042.951094, 47 | 2721.406588, 48 | 1365.336328, 49 | 196.0867735, 50 | -627.1467052, 51 | -1035.780505, 52 | -1055.961515, 53 | -789.4745507, 54 | -378.7006808, 55 | 33.4788915, 56 | 337.7776717, 57 | 478.4870886, 58 | 456.1755615, 59 | 315.2052879, 60 | 122.0628014, 61 | -57.84469672, 62 | -178.1423548, 63 | -220.1747099, 64 | -191.8078123, 65 | -118.820004, 66 | -33.03596387, 67 | 38.4763929, 68 | 80.0968851, 69 | 89.22748606, 70 | 73.45343713, 71 | 45.28360944, 72 | 16.88507849, 73 | -3.632956693, 74 | -13.40139073, 75 | -14.03741957, 76 | -12.84963301 77 | 78 | -------------------------------------------------------------------------------- /fir_44.h: -------------------------------------------------------------------------------- 1 | // fir_44 2 | // Filter by DD4WH DC to 4.4 kHz 3 | // (sampling rate 44.117 kHz) 4 | // 30.10.2015 5 | // Parameters generated using Iowa Hills FIR Filter Designer 6 | // 66 taps 7 | // Window off 8 | // Parks McClellan 9 | // 10 | 11 | 12 | 14.15667226, 13 | 20.8673345, 14 | 23.79106926, 15 | 13.50458767, 16 | -12.8559916, 17 | -49.54632495, 18 | -81.27192098, 19 | -87.94274368, 20 | -54.48049524, 21 | 18.23289754, 22 | 107.3049752, 23 | 172.117536, 24 | 170.1622231, 25 | 79.41432912, 26 | -82.94671473, 27 | -256.7939315, 28 | -356.901491, 29 | -309.3217959, 30 | -92.63310348, 31 | 235.6862293, 32 | 545.0210635, 33 | 675.1002398, 34 | 505.6867647, 35 | 25.87702068, 36 | -628.94386, 37 | -1195.917869, 38 | -1362.117879, 39 | -878.2442392, 40 | 332.5590119, 41 | 2115.353134, 42 | 4102.92398, 43 | 5814.716441, 44 | 6804.393684, 45 | 6804.393684, 46 | 5814.716441, 47 | 4102.92398, 48 | 2115.353134, 49 | 332.5590119, 50 | -878.2442392, 51 | -1362.117879, 52 | -1195.917869, 53 | -628.94386, 54 | 25.87702068, 55 | 505.6867647, 56 | 675.1002398, 57 | 545.0210635, 58 | 235.6862293, 59 | -92.63310348, 60 | -309.3217959, 61 | -356.901491, 62 | -256.7939315, 63 | -82.94671473, 64 | 79.41432912, 65 | 170.1622231, 66 | 172.117536, 67 | 107.3049752, 68 | 18.23289754, 69 | -54.48049524, 70 | -87.94274368, 71 | -81.27192098, 72 | -49.54632495, 73 | -12.8559916, 74 | 13.50458767, 75 | 23.79106926, 76 | 20.8673345, 77 | 14.15667226 78 | 79 | -------------------------------------------------------------------------------- /fir_65.h: -------------------------------------------------------------------------------- 1 | // fir_44 2 | // Filter by DD4WH DC to 6.5 kHz 3 | // (sampling rate 44.117 kHz) 4 | // 30.10.2015 5 | // Parameters generated using Iowa Hills FIR Filter Designer 6 | // 66 taps 7 | // Window off 8 | // Parks McClellan 9 | // 10 | 11 | -17.00317033, 12 | -27.50040778, 13 | -21.86155628, 14 | 10.44785478, 15 | 53.12046776, 16 | 67.99124471, 17 | 26.41143994, 18 | -53.86109701, 19 | -106.2543995, 20 | -65.64438142, 21 | 61.71347494, 22 | 177.1214822, 23 | 158.2494211, 24 | -22.45198813, 25 | -236.9842528, 26 | -281.139096, 27 | -57.29286429, 28 | 293.751689, 29 | 461.0507567, 30 | 222.7489423, 31 | -306.9739619, 32 | -691.074828, 33 | -503.6522826, 34 | 249.5994476, 35 | 1004.285488, 36 | 1005.905179, 37 | -30.49142015, 38 | -1486.73536, 39 | -2070.1255, 40 | -665.0021385, 41 | 2756.686934, 42 | 6868.870634, 43 | 9662.180624, 44 | 9662.180624, 45 | 6868.870634, 46 | 2756.686934, 47 | -665.0021385, 48 | -2070.1255, 49 | -1486.73536, 50 | -30.49142015, 51 | 1005.905179, 52 | 1004.285488, 53 | 249.5994476, 54 | -503.6522826, 55 | -691.074828, 56 | -306.9739619, 57 | 222.7489423, 58 | 461.0507567, 59 | 293.751689, 60 | -57.29286429, 61 | -281.139096, 62 | -236.9842528, 63 | -22.45198813, 64 | 158.2494211, 65 | 177.1214822, 66 | 61.71347494, 67 | -65.64438142, 68 | -106.2543995, 69 | -53.86109701, 70 | 26.41143994, 71 | 67.99124471, 72 | 53.12046776, 73 | 10.44785478, 74 | -21.86155628, 75 | -27.50040778, 76 | -17.00317033 77 | 78 | -------------------------------------------------------------------------------- /fir_80.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 8.0 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4 | // Parameters generated using Iowa Hills FIR Filter Designer 5 | // 66 taps 6 | // Window off 7 | // Parks McClellan 8 | 9 | 10 | -11.54588562, 11 | -37.74909487, 12 | -36.33709109, 13 | 0.329428, 14 | 50.39226121, 15 | 46.31327058, 16 | -27.73409679, 17 | -93.48179352, 18 | -49.46985485, 19 | 84.05062015, 20 | 146.4828721, 21 | 20.26145239, 22 | -179.2297369, 23 | -189.4801985, 24 | 67.36139552, 25 | 310.058127, 26 | 187.7322935, 27 | -238.3453386, 28 | -455.17524, 29 | -91.74890724, 30 | 511.2072546, 31 | 570.5562238, 32 | -165.535439, 33 | -900.031052, 34 | -581.9209832, 35 | 697.9218785, 36 | 1445.031268, 37 | 340.4916562, 38 | -1855.485608, 39 | -2414.271182, 40 | 810.933808, 41 | 6791.035667, 42 | 11578.1778, 43 | 11578.1778, 44 | 6791.035667, 45 | 810.933808, 46 | -2414.271182, 47 | -1855.485608, 48 | 340.4916562, 49 | 1445.031268, 50 | 697.9218785, 51 | -581.9209832, 52 | -900.031052, 53 | -165.535439, 54 | 570.5562238, 55 | 511.2072546, 56 | -91.74890724, 57 | -455.17524, 58 | -238.3453386, 59 | 187.7322935, 60 | 310.058127, 61 | 67.36139552, 62 | -189.4801985, 63 | -179.2297369, 64 | 20.26145239, 65 | 146.4828721, 66 | 84.05062015, 67 | -49.46985485, 68 | -93.48179352, 69 | -27.73409679, 70 | 46.31327058, 71 | 50.39226121, 72 | 0.329428, 73 | -36.33709109, 74 | -37.74909487, 75 | -11.54588562 76 | 77 | -------------------------------------------------------------------------------- /freq_conv.cpp: -------------------------------------------------------------------------------- 1 | /* Audio Library for Teensy 3.X 2 | * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com 3 | * 4 | * Development of this audio library was funded by PJRC.COM, LLC by sales of 5 | * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop 6 | * open source software by purchasing Teensy or other PJRC products. 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice, development funding notice, and this permission 16 | * notice shall be included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include "freq_conv.h" 28 | #include "arm_math.h" 29 | 30 | void AudioEffectFreqConv::update(void) 31 | { 32 | audio_block_t *blockI, *blockQ; 33 | audio_block_t *blockA, *blockB, *blockC, *blockD; 34 | 35 | // blockI = receiveReadOnly(0); 36 | // blockQ = receiveReadOnly(1); 37 | blockI = receiveWritable(0); 38 | blockQ = receiveWritable(1); 39 | 40 | if (!blockI) { 41 | if (blockQ) release(blockQ); 42 | return; 43 | } 44 | if (!blockQ) { 45 | release(blockI); 46 | return; 47 | } 48 | 49 | if (!pass) 50 | { 51 | transmit(blockI, 0); 52 | transmit(blockQ, 1); 53 | release(blockI); 54 | release(blockQ); 55 | return; 56 | } 57 | 58 | blockA = allocate(); 59 | blockB = allocate(); 60 | blockC = allocate(); 61 | blockD = allocate(); 62 | 63 | 64 | if (blockA && blockB && blockC && blockD) 65 | { 66 | 67 | if (!dir) 68 | { 69 | // A = I * sinQ 70 | arm_mult_q15((q15_t *)blockI->data, ( q15_t *) Osc_Q_buffer_i, (q15_t *)blockA->data, AUDIO_BLOCK_SAMPLES); 71 | // B = Q * sinI 72 | arm_mult_q15((q15_t *)blockQ->data, ( q15_t *) Osc_I_buffer_i , (q15_t *)blockB->data, AUDIO_BLOCK_SAMPLES); 73 | // C = Q * sinQ 74 | arm_mult_q15((q15_t *)blockQ->data, ( q15_t *) Osc_Q_buffer_i, (q15_t *)blockC->data, AUDIO_BLOCK_SAMPLES); 75 | // D = I * sinI 76 | arm_mult_q15((q15_t *)blockI->data, ( q15_t *) Osc_I_buffer_i , (q15_t *)blockD->data, AUDIO_BLOCK_SAMPLES); 77 | // I = A + B 78 | // arm_add_q15((q15_t *)blockA->data, (q15_t *)blockB->data, (q15_t *)blockA->data, AUDIO_BLOCK_SAMPLES); // summation for I channel 79 | arm_add_q15((q15_t *)blockA->data, (q15_t *)blockB->data, (q15_t *)blockI->data, AUDIO_BLOCK_SAMPLES); // summation for I channel 80 | release(blockB); // 81 | // Q = C - D 82 | // arm_sub_q15((q15_t *)blockC->data, (q15_t *)blockD->data, (q15_t *)blockC->data, AUDIO_BLOCK_SAMPLES); // difference for Q channel 83 | arm_sub_q15((q15_t *)blockC->data, (q15_t *)blockD->data, (q15_t *)blockQ->data, AUDIO_BLOCK_SAMPLES); // difference for Q channel 84 | release(blockD); 85 | } 86 | else 87 | { 88 | // A = Q * sinQ 89 | arm_mult_q15((q15_t *)blockQ->data, ( q15_t *) Osc_Q_buffer_i, (q15_t *)blockA->data, AUDIO_BLOCK_SAMPLES); 90 | // B = I * sinI 91 | arm_mult_q15((q15_t *)blockI->data, ( q15_t *) Osc_I_buffer_i , (q15_t *)blockB->data, AUDIO_BLOCK_SAMPLES); 92 | // C = I * sinQ 93 | arm_mult_q15((q15_t *)blockI->data, ( q15_t *) Osc_Q_buffer_i, (q15_t *)blockC->data, AUDIO_BLOCK_SAMPLES); 94 | // D = Q * sinI 95 | arm_mult_q15((q15_t *)blockQ->data, ( q15_t *) Osc_I_buffer_i , (q15_t *)blockD->data, AUDIO_BLOCK_SAMPLES); 96 | // Q = A + B 97 | // arm_add_q15((q15_t *)blockA->data, (q15_t *)blockB->data, (q15_t *)blockC->data, AUDIO_BLOCK_SAMPLES); // summation for I channel 98 | arm_add_q15((q15_t *)blockA->data, (q15_t *)blockB->data, (q15_t *)blockQ->data, AUDIO_BLOCK_SAMPLES); // summation for Q channel !!! 99 | release(blockB); 100 | // I = C - D 101 | // arm_sub_q15((q15_t *)blockC->data, (q15_t *)blockD->data, (q15_t *)blockA->data, AUDIO_BLOCK_SAMPLES); // difference for Q channel 102 | arm_sub_q15((q15_t *)blockC->data, (q15_t *)blockD->data, (q15_t *)blockI->data, AUDIO_BLOCK_SAMPLES); // difference for I channel !!! 103 | release(blockD); 104 | } 105 | // transmit(blockA, 0); 106 | // transmit(blockC, 1); 107 | transmit(blockI, 0); 108 | transmit(blockQ, 1); 109 | release(blockA); 110 | release(blockC); 111 | } 112 | release(blockI); 113 | release(blockQ); 114 | 115 | 116 | } 117 | 118 | -------------------------------------------------------------------------------- /freq_conv.h: -------------------------------------------------------------------------------- 1 | /* Audio Library for Teensy 3.X 2 | * Copyright (c) 2014, Paul Stoffregen, paul@pjrc.com 3 | * 4 | * Development of this audio library was funded by PJRC.COM, LLC by sales of 5 | * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop 6 | * open source software by purchasing Teensy or other PJRC products. 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice, development funding notice, and this permission 16 | * notice shall be included in all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifndef freq_conv_h_ 28 | #define freq_conv_h_ 29 | 30 | #include "AudioStream.h" 31 | #include "arm_math.h" 32 | 33 | extern q15_t Osc_Q_buffer_i[AUDIO_BLOCK_SAMPLES]; 34 | extern q15_t Osc_I_buffer_i[AUDIO_BLOCK_SAMPLES]; 35 | 36 | class AudioEffectFreqConv: public AudioStream 37 | { 38 | public: 39 | AudioEffectFreqConv() : AudioStream(2, inputQueueArray), dir(0), pass(1) { } 40 | 41 | void direction(bool d) { 42 | dir = d; 43 | } 44 | 45 | void passthrough(bool p) { 46 | pass = p; 47 | } 48 | 49 | 50 | virtual void update(void); 51 | private: 52 | audio_block_t *inputQueueArray[2]; 53 | 54 | bool dir,pass; 55 | 56 | }; 57 | 58 | #endif 59 | -------------------------------------------------------------------------------- /iir_110.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 11.0 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 12.2.2016 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order Inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | 9 | // coefficients must be in order: B0, B1, B2, A1, A2 (A0 is always equal to 1) 10 | // unlike output by Iowa Hils IIR Filter Designer ! 11 | 12 | const double IIR_110_Coeffs_0[] = 13 | { 14 | 15 | 0.475780268916932259, 16 | 0.373028495120374948, 17 | 0.475780268916932259, 18 | 0.287219208685271454, 19 | 0.037369824268968011 20 | }; 21 | 22 | const double IIR_110_Coeffs_1[] = 23 | { 24 | 25 | 0.449751723274657622, 26 | 0.469708113552961881, 27 | 0.449751723274657622, 28 | 0.212781928336632037, 29 | 0.156429631765645144 30 | }; 31 | 32 | const double IIR_110_Coeffs_2[] = 33 | { 34 | 35 | 0.424433344934997681, 36 | 0.640184306422222793, 37 | 0.424433344934997681, 38 | 0.102040329398599611, 39 | 0.387010666893618627 40 | }; 41 | 42 | const double IIR_110_Coeffs_3[] = 43 | { 44 | 45 | 0.447171439600465070, 46 | 0.863957628409256384, 47 | 0.447171439600465070, 48 | 0.012475725320821696, 49 | 0.745824782289364885 50 | }; 51 | 52 | 53 | -------------------------------------------------------------------------------- /iir_18.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 1.8 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 19.11.2015 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order Inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | 9 | // coefficients must be in order: B0, B1, B2, A1, A0 10 | // unlike output by Iowa Hils IIR Filter Designer ! 11 | 12 | const double IIR_18_Coeffs_0[] = 13 | { 0.588593506625137985, 14 | -1.090926182879769610, 15 | 0.588593506625137985, 16 | -1.427338275114299120, 17 | 0.513599105484805585 18 | 19 | }; 20 | 21 | const double IIR_18_Coeffs_1[] = 22 | { 0.382265051089020314, 23 | -0.687681842220833062, 24 | 0.382265051089020314, 25 | -1.555795677703446730, 26 | 0.632643937660654299 27 | 28 | }; 29 | 30 | const double IIR_18_Coeffs_2[] = 31 | { 0.159034432461012065, 32 | -0.250658999244488701, 33 | 0.159034432461012065, 34 | -1.717277645294771780, 35 | 0.784687510972307267 36 | 37 | }; 38 | 39 | const double IIR_18_Coeffs_3[] = 40 | { 0.032598425578464235, 41 | -0.001288965017620658, 42 | 0.032598425578464235, 43 | -1.864412283394368600, 44 | 0.928320169533676576 45 | 46 | }; 47 | 48 | 49 | -------------------------------------------------------------------------------- /iir_23.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 2.3 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 12.2.2016 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order Inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | // The array of coefficients is in order: B0, B1, B2, A1, A2. Each coefficient must be less than 2.0 and greater than -2.0. The array should be type double. 9 | // unlike output by Iowa Hils IIR Filter Designer ! 10 | 11 | const double IIR_23_Coeffs_0[] = 12 | { 13 | 0.556634885877411167, 14 | -0.982394942387879166, 15 | 0.556634885877411167, 16 | -1.293229054331558770, 17 | 0.424103883698501938 18 | }; 19 | 20 | const double IIR_23_Coeffs_1[] = 21 | { 22 | 0.370855554804624066, 23 | -0.623115921672821593, 24 | 0.370855554804624066, 25 | -1.438992167193630540, 26 | 0.557587355130057083 27 | }; 28 | 29 | const double IIR_23_Coeffs_2[] = 30 | { 31 | 0.163146395659582527, 32 | -0.219974175714333725, 33 | 0.163146395659582527, 34 | -1.628671322541833670, 35 | 0.734989938146665023 36 | }; 37 | 38 | const double IIR_23_Coeffs_3[] = 39 | { 40 | 0.042001889342496573, 41 | 0.018843591374682236, 42 | 0.042001889342496573, 43 | -1.807131802969797580, 44 | 0.909979173029472954 45 | 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /iir_26.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 2.6 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 19.11.2015 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order Inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | 9 | // coefficients must be in order: B0, B1, B2, A1, A0 10 | // unlike output by Iowa Hils IIR Filter Designer ! 11 | 12 | const double IIR_26_Coeffs_0[] = 13 | { 0.540171118036528397, 14 | -0.919885858364284048, 15 | 0.540171118036528397, 16 | -1.216564577638121310, 17 | 0.377020955346894171 18 | 19 | }; 20 | 21 | const double IIR_26_Coeffs_1[] = 22 | { 0.365427800890789467, 23 | -0.584085107562330563, 24 | 0.365427800890789467, 25 | -1.370139944133233590, 26 | 0.516910438352482071 27 | 28 | }; 29 | 30 | const double IIR_26_Coeffs_2[] = 31 | { 0.166507245228244061, 32 | -0.199806854365357778, 33 | 0.166507245228244061, 34 | -1.573830827104126360, 35 | 0.707038463195256650 36 | 37 | }; 38 | 39 | const double IIR_26_Coeffs_3[] = 40 | { 0.048669380653841535, 41 | 0.033035018012432818, 42 | 0.048669380653841535, 43 | -1.768940357874658530, 44 | 0.899314137194774377 45 | 46 | }; 47 | 48 | -------------------------------------------------------------------------------- /iir_31.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 3.1 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 12.2.2016 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order Inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | // 9 | // The array of coefficients is in order: B0, B1, B2, A1, A2. Each coefficient must be less than 2.0 and greater than -2.0. The array should be type double. 10 | // unlike output by Iowa Hils IIR Filter Designer ! 11 | 12 | const double IIR_31_Coeffs_0[] = 13 | { 14 | 0.516676615096921532, 15 | -0.819792954551865849, 16 | 0.516676615096921532, 17 | -1.094656125530478310, 18 | 0.308216401172455579, 19 | }; 20 | 21 | const double IIR_31_Coeffs_1[] = 22 | { 23 | 0.358508197603467582, 24 | -0.518847077512281984, 25 | 0.358508197603467582, 26 | -1.257630547496234370, 27 | 0.455799865190887388 28 | }; 29 | 30 | const double IIR_31_Coeffs_2[] = 31 | { 32 | 0.173478188104338238, 33 | -0.163591138608289915, 34 | 0.173478188104338238, 35 | -1.480176015318265480, 36 | 0.663541252918652180 37 | }; 38 | 39 | const double IIR_31_Coeffs_3[] = 40 | { 41 | 0.061411582893547395, 42 | 0.060040463689562951, 43 | 0.061411582893547395, 44 | -1.699310973939165190, 45 | 0.882174603415822989 46 | }; 47 | 48 | /* 49 | // ELLIPTIC filter coefficients 50 | // works, but with an unpleasant and annoying hiss sound! 51 | const double IIR_31_Coeffs_0[] = 52 | { 53 | 0.211735067967220886, 54 | -0.365798354728391173, 55 | 0.211735067967220886, 56 | -1.568543543770871020, 57 | 0.626215324976921672 58 | }; 59 | 60 | const double IIR_31_Coeffs_1[] = 61 | { 62 | 0.326582053814130580, 63 | -0.544927310238951357, 64 | 0.326582053814130580, 65 | -1.640791514445660180, 66 | 0.749028311834969984 67 | }; 68 | 69 | const double IIR_31_Coeffs_2[] = 70 | { 71 | 0.274329980165261500, 72 | -0.390258125345878171, 73 | 0.274329980165261500, 74 | -1.718502911800378290, 75 | 0.876904746785023170 76 | }; 77 | 78 | const double IIR_31_Coeffs_3[] = 79 | { 80 | 0.085499318375426445, 81 | 0.014729186060807581, 82 | 0.085499318375426445, 83 | -1.778873148815911740, 84 | 0.964600971627572412 85 | }; 86 | */ 87 | 88 | -------------------------------------------------------------------------------- /iir_36.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 3.6 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 19.11.2015 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order Inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | 9 | // coefficients must be in order: B0, B1, B2, A1, A0 10 | // unlike output by Iowa Hils IIR Filter Designer ! 11 | 12 | const double IIR_36_Coeffs_0[] = 13 | { 0.497500055005770048, 14 | -0.724503794330950246, 15 | 0.497500055005770048 , 16 | -0.979544815675165492, 17 | 0.250041131355755342 18 | 19 | }; 20 | 21 | const double IIR_36_Coeffs_1[] = 22 | { 0.353976527533391316, 23 | -0.453688678098041753, 24 | 0.353976527533391316, 25 | -1.148103335906009100, 26 | 0.402367712874749928 27 | 28 | }; 29 | 30 | const double IIR_36_Coeffs_2[] = 31 | { 0.182011681178916945, 32 | -0.124512696361030420, 33 | 0.182011681178916945, 34 | -1.384335079136399080, 35 | 0.623845745133202567 36 | 37 | }; 38 | 39 | const double IIR_36_Coeffs_3[] = 40 | { 0.076075894745040659, 41 | 0.090996222607221261, 42 | 0.076075894745040659, 43 | -1.622758218022206660, 44 | 0.865906230119509068 45 | 46 | }; 47 | 48 | 49 | -------------------------------------------------------------------------------- /iir_40.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 4.0 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 12.2.2016 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | //const uint16_t IIR_44_numStages = 6; 9 | // coefficients must be in order: B0, B1, B2, A1, A2 10 | // unlike output by Iowa Hils IIR Filter Designer ! 11 | 12 | const double IIR_40_Coeffs_0[] = 13 | { 14 | 0.484810408275220817, 15 | -0.651221487101388163, 16 | 0.484810408275220817, 17 | -0.891628778714572134, 18 | 0.210028108163625632 19 | }; 20 | 21 | const double IIR_40_Coeffs_1[] = 22 | { 23 | 0.351872869530550469, 24 | -0.401617388625892080, 25 | 0.351872869530550469, 26 | -1.062389411661841750, 27 | 0.364517762097050613 28 | }; 29 | 30 | const double IIR_40_Coeffs_2[] = 31 | { 32 | 0.189882490696338585, 33 | -0.091345663765967006, 34 | 0.189882490696338585, 35 | -1.306231903874912840, 36 | 0.594651221501622862 37 | }; 38 | 39 | const double IIR_40_Coeffs_3[] = 40 | { 41 | 0.089146208826620985, 42 | 0.118511599523885514, 43 | 0.089146208826620985, 44 | -1.556718436850091260, 45 | 0.853522454027218824 46 | }; 47 | 48 | /* 49 | // ELLIPTIC filter coefficients 50 | // works, but with an unpleasant and annoying hiss sound! 51 | 52 | const double IIR_40_Coeffs_0[] = 53 | { 54 | 0.147439714070734695, 55 | -0.234713625844170160, 56 | 0.147439714070734695, 57 | -1.594339282170066820, 58 | 0.654505084467365883 59 | }; 60 | 61 | const double IIR_40_Coeffs_1[] = 62 | { 63 | 0.343454259640266046, 64 | -0.522129062081838513, 65 | 0.343454259640266046, 66 | -1.616431618662758530, 67 | 0.781211075861452220 68 | }; 69 | 70 | const double IIR_40_Coeffs_2[] = 71 | { 72 | 0.334664568130310369, 73 | -0.408981103587607198, 74 | 0.334664568130310369, 75 | -1.640858864246826920, 76 | 0.901206896919840461 77 | }; 78 | 79 | const double IIR_40_Coeffs_3[] = 80 | { 81 | 0.124019274640942659, 82 | 0.058934416406060730, 83 | 0.124019274640942659, 84 | -1.666344616468945490, 85 | 0.973317582156891459 86 | }; 87 | */ 88 | -------------------------------------------------------------------------------- /iir_44.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 4.4 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 4.11.2015 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | 9 | //#ifndef __IIR_44 10 | //#define __IIR_44 11 | 12 | //const uint16_t IIR_44_numStages = 6; 13 | // coefficients must be in order: B0, B1, B2, A1, A2 14 | // unlike output by Iowa Hils IIR Filter Designer ! 15 | 16 | const double IIR_44_Coeffs_0[] = 17 | { 0.474319601705361138, 18 | -0.581215670666504036, 19 | 0.474319601705361138, 20 | -0.808127484363303061, 21 | 0.175551017107521246 22 | 23 | }; 24 | 25 | const double IIR_44_Coeffs_1[] = 26 | { 0.350995225349848505, 27 | -0.350332220679905326, 28 | 0.350995225349848505, 29 | -0.979397333344850574, 30 | 0.331055563364642369 31 | 32 | }; 33 | 34 | const double IIR_44_Coeffs_2[] = 35 | { 0.198494408209874185, 36 | -0.057104157615077124, 37 | 0.198494408209874185, 38 | -1.228105729229502780, 39 | 0.567990388034173899 40 | 41 | }; 42 | 43 | const double IIR_44_Coeffs_3[] = 44 | { 0.103160902362084875, 45 | 0.147956900687732512, 46 | 0.103160902362084875, 47 | -1.487595160516167910, 48 | 0.841873865928070120 49 | 50 | }; 51 | 52 | const double IIR_44_Coeffs_4[] = 53 | { 54 | }; 55 | 56 | const double IIR_44_Coeffs_5[] = 57 | { 58 | }; 59 | 60 | 61 | 62 | -------------------------------------------------------------------------------- /iir_54.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 5.4 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 12.2.2015 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | 9 | //const uint16_t IIR_44_numStages = 6; 10 | // coefficients must be in order: B0, B1, B2, A1, A2 11 | // unlike output by Iowa Hils IIR Filter Designer ! 12 | 13 | const double IIR_54_Coeffs_0[] = 14 | { 15 | 0.455538551190282137, 16 | -0.414177993916487353, 17 | 0.455538551190282137, 18 | -0.610743068556704460, 19 | 0.107642177020781438 20 | }; 21 | 22 | const double IIR_54_Coeffs_1[] = 23 | { 24 | 0.353406693953235374, 25 | -0.222163021852471249, 26 | 0.353406693953235374, 27 | -0.777493307668655653, 28 | 0.262143673722655013 29 | }; 30 | 31 | const double IIR_54_Coeffs_2[] = 32 | { 33 | 0.223479292310269140, 34 | 0.034735385615843543, 35 | 0.223479292310269140, 36 | -1.028293644763743850, 37 | 0.509987615000125571 38 | }; 39 | 40 | const double IIR_54_Coeffs_3[] = 41 | { 42 | 0.142940195575829515, 43 | 0.231304531888519099, 44 | 0.142940195575829515, 45 | -1.298067623920669660, 46 | 0.815252546960847924 47 | }; 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /iir_65.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 6.5 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 19.11.2015 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | 9 | // coefficients must be in order: B0, B1, B2, A1, A0 10 | // unlike output by Iowa Hils IIR Filter Designer ! 11 | 12 | const double IIR_65_Coeffs_0[] = 13 | { 0.445119281930485944, 14 | -0.243610640430697772, 15 | 0.445119281930485944, 16 | -0.411785925396654373, 17 | 0.058413848826928544 18 | 19 | }; 20 | 21 | const double IIR_65_Coeffs_1[] = 22 | { 23 | 0.362456736578711081, 24 | -0.083459034199268298, 25 | 0.362456736578711081, 26 | -0.566693840638351265, 27 | 0.208148279596505087 28 | 29 | }; 30 | 31 | const double IIR_65_Coeffs_2[] = 32 | { 33 | 0.255577093998374916, 34 | 0.143064449302430508, 35 | 0.255577093998374916, 36 | -0.806154514990846782, 37 | 0.460373152290027121 38 | 39 | }; 40 | 41 | const double IIR_65_Coeffs_3[] = 42 | { 0.193131988951157629, 43 | 0.336144435105818207, 44 | 0.193131988951157629, 45 | -1.068348948044986150, 46 | 0.790757361053119667 47 | 48 | 49 | }; 50 | 51 | 52 | -------------------------------------------------------------------------------- /iir_80.h: -------------------------------------------------------------------------------- 1 | // DD4WH LPF DC - 8.0 kHz 2 | // (sampling rate 44.117 kHz) 3 | // 19.11.2015 4 | // Parameters generated using Iowa Hills IIR Filter Designer 5 | // 8th order Inv Cheby Lowpass (4-stage cascaded biquad) 6 | // 7 | // 8 | 9 | // coefficients must be in order: B0, B1, B2, A1, A0 10 | // unlike output by Iowa Hils IIR Filter Designer ! 11 | 12 | const double IIR_80_Coeffs_0[] = 13 | { 14 | 0.446434382700681365, 15 | 0.041146041523810628, 16 | 0.446434382700681365 , 17 | -0.085183554385348359, 18 | 0.019198361310521727 19 | 20 | }; 21 | 22 | const double IIR_80_Coeffs_1[] = 23 | { 0.392327036556695707, 24 | 0.163354017793623490, 25 | 0.392327036556695707, 26 | -0.208051255444550665, 27 | 0.156059346351565598 28 | 29 | 30 | }; 31 | 32 | const double IIR_80_Coeffs_2[] = 33 | { 0.323849872722823229, 34 | 0.354465982397823676, 35 | 0.323849872722823229, 36 | -0.401716599174288980, 37 | 0.403882327017759224 38 | 39 | 40 | }; 41 | 42 | const double IIR_80_Coeffs_3[] = 43 | { 0.298069389947243191, 44 | 0.554619294245409900, 45 | 0.298069389947243191, 46 | -0.608875813894889872, 47 | 0.759633888034786153 48 | }; 49 | 50 | 51 | -------------------------------------------------------------------------------- /licence.txt: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | --------------------------------------------------------------------------------