├── README.md
├── ESP_DSP
└── ESP32FIR
│ ├── mix.wav
│ ├── 400Hz2m.wav
│ ├── BLEscan.png
│ ├── ESP32_FIR.PNG
│ ├── sineWAV.wav
│ ├── firLibrary.zip
│ ├── esp-dsp-master.zip
│ ├── images
│ ├── BLEscan.PNG
│ ├── ESP32_FIR.PNG
│ └── RealTimeAudioProcessor.png
│ ├── design
│ ├── ESP32_FIR.JPG
│ ├── TTGO_T8_1_7.png
│ ├── 400HzBandstopFilterGraph.png
│ ├── HighPass400_850FilterGraph.png
│ ├── RealTime Audio Processor.jpeg
│ └── PM8403_Super Mini PAM8403 DC 5V 2 Channel USB Digital Audio Amplifier Board Module 2 3W Volume Control with Potentionmeter.pdf
│ ├── RealTimeAudioProcessor.png
│ ├── esp32-micro-sdcard-master.zip
│ ├── dsp_err.h
│ ├── dsps_fir_init_f32.c
│ ├── dsp_err_codes.h
│ ├── dsps_fir_f32_ansi.c
│ ├── fdaHPcoefs.h
│ ├── fdaBScoefs.h
│ ├── README.md
│ ├── dsps_fir.h
│ ├── ESP32DACWaveforms
│ ├── TwoCoreTalkThru
│ │ └── TwoCoreTalkThru.ino
│ ├── TwoCoreSweepESP32
│ │ └── TwoCoreSweepESP32.ino
│ ├── TwoCoreTwoToneESP32
│ │ └── TwoCoreTwoToneESP32.ino
│ └── TwoCoreSineESP32
│ │ └── TwoCoreSineESP32.ino
│ ├── ESP32FIR.ino
│ └── tmwtypes.h
└── LICENSE
/README.md:
--------------------------------------------------------------------------------
1 | # ESP_DSP
2 | Real-Time Digital Signal Processing on the ESP32
3 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/mix.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/mix.wav
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/400Hz2m.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/400Hz2m.wav
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/BLEscan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/BLEscan.png
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/ESP32_FIR.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/ESP32_FIR.PNG
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/sineWAV.wav:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/sineWAV.wav
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/firLibrary.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/firLibrary.zip
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/esp-dsp-master.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/esp-dsp-master.zip
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/images/BLEscan.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/images/BLEscan.PNG
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/design/ESP32_FIR.JPG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/design/ESP32_FIR.JPG
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/images/ESP32_FIR.PNG:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/images/ESP32_FIR.PNG
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/design/TTGO_T8_1_7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/design/TTGO_T8_1_7.png
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/RealTimeAudioProcessor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/RealTimeAudioProcessor.png
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/esp32-micro-sdcard-master.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/esp32-micro-sdcard-master.zip
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/images/RealTimeAudioProcessor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/images/RealTimeAudioProcessor.png
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/design/400HzBandstopFilterGraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/design/400HzBandstopFilterGraph.png
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/design/HighPass400_850FilterGraph.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/design/HighPass400_850FilterGraph.png
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/design/RealTime Audio Processor.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/design/RealTime Audio Processor.jpeg
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/design/PM8403_Super Mini PAM8403 DC 5V 2 Channel USB Digital Audio Amplifier Board Module 2 3W Volume Control with Potentionmeter.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bobh/ESP_DSP/HEAD/ESP_DSP/ESP32FIR/design/PM8403_Super Mini PAM8403 DC 5V 2 Channel USB Digital Audio Amplifier Board Module 2 3W Volume Control with Potentionmeter.pdf
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/dsp_err.h:
--------------------------------------------------------------------------------
1 | // Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 |
16 | #ifndef _DSP_ERR_H_
17 | #define _DSP_ERR_H_
18 |
19 | #include "stdint.h"
20 | #include "esp_err.h"
21 | #include "dsp_err_codes.h"
22 |
23 | #endif // _DSP_ERR_H_
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/dsps_fir_init_f32.c:
--------------------------------------------------------------------------------
1 | // Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "dsps_fir.h"
16 |
17 |
18 | esp_err_t dsps_fir_init_f32(fir_f32_t *fir, float *coeffs, float *delay, int N)
19 | {
20 | fir->coeffs = coeffs;
21 | fir->delay = delay;
22 | fir->N = N;
23 | fir->pos = 0;
24 |
25 | for (int i = 0 ; i < N; i++) {
26 | fir->delay[i] = 0;
27 | }
28 | return ESP_OK;
29 | }
30 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/dsp_err_codes.h:
--------------------------------------------------------------------------------
1 | // Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef _dsp_error_codes_H_
16 | #define _dsp_error_codes_H_
17 |
18 | #define DSP_OK 0 // For internal use only. Please use ESP_OK instead
19 | #define ESP_ERR_DSP_BASE 0x70000
20 | #define ESP_ERR_DSP_INVALID_LENGTH (ESP_ERR_DSP_BASE + 1)
21 | #define ESP_ERR_DSP_INVALID_PARAM (ESP_ERR_DSP_BASE + 2)
22 | #define ESP_ERR_DSP_PARAM_OUTOFRANGE (ESP_ERR_DSP_BASE + 3)
23 | #define ESP_ERR_DSP_UNINITIALIZED (ESP_ERR_DSP_BASE + 4)
24 | #define ESP_ERR_DSP_REINITIALIZED (ESP_ERR_DSP_BASE + 5)
25 |
26 |
27 | #endif // _dsp_error_codes_H_
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/dsps_fir_f32_ansi.c:
--------------------------------------------------------------------------------
1 | // Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #include "dsps_fir.h"
16 |
17 | esp_err_t dsps_fir_f32_ansi(fir_f32_t *fir, const float *input, float *output, int len)
18 | {
19 | for (int i = 0 ; i < len ; i++) {
20 | float acc = 0;
21 | int coeff_pos = fir->N - 1;
22 | fir->delay[fir->pos] = input[i];
23 | fir->pos++;
24 | if (fir->pos >= fir->N) {
25 | fir->pos = 0;
26 | }
27 | for (int n = fir->pos; n < fir->N ; n++) {
28 | acc += fir->coeffs[coeff_pos--] * fir->delay[n];
29 | }
30 | for (int n = 0; n < fir->pos ; n++) {
31 | acc += fir->coeffs[coeff_pos--] * fir->delay[n];
32 | }
33 | output[i] = acc;
34 | }
35 | return ESP_OK;
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/fdaHPcoefs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool
3 | * Generated by MATLAB(R) 9.4 and Signal Processing Toolbox 8.0.
4 | * Generated on: 26-Jan-2020 13:57:49
5 | */
6 |
7 | /*
8 | * Discrete-Time FIR Filter (real)
9 | * -------------------------------
10 | * Filter Structure : Direct-Form FIR
11 | * Filter Length : 51
12 | * Stable : Yes
13 | * Linear Phase : Yes (Type 1)
14 | */
15 |
16 | /* General type conversion for MATLAB generated C-code */
17 | #include "tmwtypes.h"
18 | /*
19 | * Expected path to tmwtypes.h
20 | * /Applications/MATLAB_R2018a.app/extern/include/tmwtypes.h
21 | */
22 | /*
23 | * Warning - Filter coefficients were truncated to fit specified data type.
24 | * The resulting response may not match generated theoretical response.
25 | * Use the Filter Design & Analysis Tool to design accurate
26 | * single-precision filter coefficients.
27 | */
28 | const int BL = 51;
29 | const real32_T B[51] = {
30 | 0.00756539451, -0.01149180066,-0.004271964077,0.0003535575815, 0.003802435007,
31 | 0.006187047344, 0.006911808625, 0.005282577127, 0.001192335272,-0.004611292854,
32 | -0.01044458337, -0.01406532526, -0.01344149839,-0.007485062815, 0.003263459308,
33 | 0.01636486501, 0.0277939178, 0.0328727141, 0.02743673138, 0.009163923562,
34 | -0.02150698006, -0.06104771048, -0.1033860892, -0.1411015838, -0.1671450883,
35 | 0.8235622644, -0.1671450883, -0.1411015838, -0.1033860892, -0.06104771048,
36 | -0.02150698006, 0.009163923562, 0.02743673138, 0.0328727141, 0.0277939178,
37 | 0.01636486501, 0.003263459308,-0.007485062815, -0.01344149839, -0.01406532526,
38 | -0.01044458337,-0.004611292854, 0.001192335272, 0.005282577127, 0.006911808625,
39 | 0.006187047344, 0.003802435007,0.0003535575815,-0.004271964077, -0.01149180066,
40 | 0.00756539451
41 | };
42 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/fdaBScoefs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Filter Coefficients (C Source) generated by the Filter Design and Analysis Tool
3 | * Generated by MATLAB(R) 9.4 and Signal Processing Toolbox 8.0.
4 | * Generated on: 25-Jan-2020 10:24:49
5 | */
6 |
7 | /*
8 | * Discrete-Time FIR Filter (real)
9 | * -------------------------------
10 | * Filter Structure : Direct-Form FIR
11 | * Filter Length : 121
12 | * Stable : Yes
13 | * Linear Phase : Yes (Type 1)
14 | */
15 |
16 | /* General type conversion for MATLAB generated C-code */
17 | #include "tmwtypes.h"
18 | /*
19 | * Expected path to tmwtypes.h
20 | * /Applications/MATLAB_R2018a.app/extern/include/tmwtypes.h
21 | */
22 | /*
23 | * Warning - Filter coefficients were truncated to fit specified data type.
24 | * The resulting response may not match generated theoretical response.
25 | * Use the Filter Design & Analysis Tool to design accurate
26 | * single-precision filter coefficients.
27 | */
28 | const int BL = 121;
29 | const real32_T B[121] = {
30 | -0.02191321366,-0.001977184555,-0.001466839924,-0.0006470786757,0.0003265612177,
31 | 0.001247174107, 0.001927313744, 0.002221651841, 0.002069424139, 0.001525712316,
32 | 0.0007507968694,-1.337562662e-05,-0.0004856224696,-0.0004075112811,0.0003994250437,
33 | 0.001983487047, 0.004231323488, 0.006872389, 0.009512691759, 0.01169616915,
34 | 0.0129874507, 0.01305404957, 0.01173774991, 0.009101052769, 0.005431375466,
35 | 0.001205577399,-0.002984318649,-0.006536464673,-0.008948790841,-0.009918907657,
36 | -0.009416198358,-0.007701143157, -0.00529480027,-0.002893649507,-0.001230120892,
37 | -0.0009249171126,-0.002346839057,-0.005496154539,-0.009985642508, -0.01508209947,
38 | -0.01964506879, -0.02255456336, -0.02270268835, -0.0192877762, -0.01202154532,
39 | -0.001184959547, 0.01229436789, 0.0269222986, 0.04082841799, 0.05200551823,
40 | 0.05860314518, 0.05922214314, 0.05315371603, 0.0405389443, 0.02240726165,
41 | 0.0005799630308, -0.02254076116, -0.04427792877, -0.06203589961, -0.07365033031,
42 | 0.9223114252, -0.07365033031, -0.06203589961, -0.04427792877, -0.02254076116,
43 | 0.0005799630308, 0.02240726165, 0.0405389443, 0.05315371603, 0.05922214314,
44 | 0.05860314518, 0.05200551823, 0.04082841799, 0.0269222986, 0.01229436789,
45 | -0.001184959547, -0.01202154532, -0.0192877762, -0.02270268835, -0.02255456336,
46 | -0.01964506879, -0.01508209947,-0.009985642508,-0.005496154539,-0.002346839057,
47 | -0.0009249171126,-0.001230120892,-0.002893649507, -0.00529480027,-0.007701143157,
48 | -0.009416198358,-0.009918907657,-0.008948790841,-0.006536464673,-0.002984318649,
49 | 0.001205577399, 0.005431375466, 0.009101052769, 0.01173774991, 0.01305404957,
50 | 0.0129874507, 0.01169616915, 0.009512691759, 0.006872389, 0.004231323488,
51 | 0.001983487047,0.0003994250437,-0.0004075112811,-0.0004856224696,-1.337562662e-05,
52 | 0.0007507968694, 0.001525712316, 0.002069424139, 0.002221651841, 0.001927313744,
53 | 0.001247174107,0.0003265612177,-0.0006470786757,-0.001466839924,-0.001977184555,
54 | -0.02191321366
55 | };
56 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/README.md:
--------------------------------------------------------------------------------
1 |
Dual Core FIR Filter for the ESP32
2 |
3 | This Arduino IDE compatible program uses the FIR filter library funtion in ANSI C from [Espressif DSP Library](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-library.html#espressif-dsp-library) to perform Real-Time Digital Signal Processing.
4 |
5 | The goal of this project is to evaluate the ESP32 processor and gain experience with the Espressif Digital Signal Processing Library of functions.
6 | The inexpensive hardware approach coupled with the familiar Arduino IDE simplifies experimenting and facilitates learning to code DSP applications.
7 |
8 |
9 |
10 | The single-precision floating point filter coefficients are created in MATLAB or [on-line](http://t-filter.engineerjs.com) and examples are included for BandStop and HighPass filtering.
11 | Sample test input signal files are also included.
12 |
13 |
14 | NOTE: The micro-sdcard interface library must be installed manually in the Arduino IDE.
15 |
16 | [Installing Additional Arduino Libraries](https://www.arduino.cc/en/guide/libraries)
17 |
18 | Sketch->Include Library->Add .ZIP Library esp32-micro-sdcard-master.zip -- Check include library menu
19 |
20 | Input test signals for processing may be created in the PC program [Audacity](https://www.audacityteam.org), transferred to a micro-sdcard, and installed in the ESP32 board.
21 | Samples are then read by the ESP32 from a file on the micro-sdcard as if they came from an ADC (Analog to Digital Converter),
22 | filtered by the DSP algorithm, and then output in Real-Time through the ESP32's DAC (Digital to Analog Converter) and heard on the speaker.
23 |
24 | Format for Audacity export: WAV format,
25 | 8000 sps, single-track mono, WAV (Microsoft) signed 16-bit PCM. The SD card is formatted as FAT32.
26 | REMEMBER to actually move the wav file to the micro-sdcard from the PC.
27 |
28 | The ESP32 development hardware is the LILYGO® TTGO T8 V1.7 [ESP32 Module](https://www.tindie.com/products/ttgo/lilygor-ttgo-t8-v17-esp32-module/)
29 |
30 | Real-Time Samples at 8Ksps for voice audio range (< 4KHz) and computer game (tune style) low fidelity music. Not for high fidelity music.
31 |
32 | To keep cost and complexity down, no switches or displays are included with the hardware design. Instead, program interfacing is accomplished over a BLE (Bluetooth Low Energy) wireless link.
33 | Free phone apps from LightBlue or Nordic nRF Connect (iOS and Google play stores) are used to "Peak and Poke" program options to the filter program running on the ESP32. **See details below**.
34 |
35 | Time permitting, I will demonstrate more of the Espressif DSP Library functions and also multi-rate filters from the Orfanidis book. These will be documented on my blog [dspobjects.com](https://www.dspobjects.com)
36 |
37 | __________________________________________________________________
38 |
39 | 
40 |
41 |
42 |
43 | __________________________________________________________________
44 |
45 |
46 |
47 |
48 |
49 |
50 | DSP Done Dirt Cheap
51 | __________________________________________________________________
52 |
53 |
54 |
55 |
56 | **BLE Scan**
57 | The filter is switched in/out programmatically over a
58 | Bluetooth Low Energy (BLE) wireless link.
59 | A write of a value to characteristic
60 | "beb5483e-36e1-4688-b7f5-ea07361b26a8" toggles the filter in/out
61 | Use free phone apps from LightBlue or nRF Connect (Nordic) to
62 | write values over BLE to the ESP32.
63 |
64 | From either app, connect to BLE peripheral advertising name "DSP_FILTER"
65 |
66 |
67 | **LightBlue** app: Upper Right--Change "Hex" to "UTF-8 String"--Write new value--then any character entered and written toggles the 400 Hz Bandstop/LowPass filter On/Off
68 |
69 | **nRF Connect** app: After connect, slide to "Advertised Services" Window--tap the UP arrow--select UTF-8 Tab--enter any character--tap write
70 |
71 | In the /ESP32DACWaveforms/TwoCoreSineESP32 program enter a positive integer frequency between 300 and 2000 to switch sine wave frequency.
72 |
73 |
74 | [700 Hz Bandpass Filter Demo] (https://www.youtube.com/watch?v=p_xYwLlHv3Y&feature=youtu.be)
75 |
76 | __________________________________________________________________
77 |
78 | ref:
79 |
80 | [Espressif DSP Library](https://docs.espressif.com/projects/esp-dsp/en/latest/esp-dsp-library.html#espressif-dsp-library)
81 |
82 | [How to use Arduino ESP32 I2S (external DAC and built-in DAC) to play wav music file from sdcard](http://www.iotsharing.com/2017/07/how-to-use-arduino-esp32-i2s-to-play-wav-music-from-sdcard.html)
83 |
84 | [Installing Additional Arduino Libraries](https://www.arduino.cc/en/guide/libraries)
85 |
86 | [esp32 arduino ide](https://github.com/espressif/arduino-esp32)
87 |
88 | [DSP library for ESP-IDF](https://github.com/espressif/esp-dsp)
89 |
90 |
91 | [dspobjects.com](https://www.dspobjects.com)
92 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/dsps_fir.h:
--------------------------------------------------------------------------------
1 | // Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD
2 | //
3 | // Licensed under the Apache License, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // http://www.apache.org/licenses/LICENSE-2.0
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 |
15 | #ifndef _dsps_fir_H_
16 | #define _dsps_fir_H_
17 |
18 |
19 | #include "dsp_err.h"
20 |
21 |
22 | #ifdef __cplusplus
23 | extern "C"
24 | {
25 | #endif
26 |
27 | /**
28 | * @brief Data struct of f32 fir filter
29 | *
30 | * This structure used by filter internally. User should access this structure only in case of
31 | * extensions for the DSP Library.
32 | * All fields of this structure initialized by dsps_fir_init_f32(...) function.
33 | */
34 | typedef struct fir_f32_s {
35 | float *coeffs; /*!< Pointer to the coefficient buffer.*/
36 | float *delay; /*!< Pointer to the delay line buffer.*/
37 | int N; /*!< FIR filter coefficients amount.*/
38 | int pos; /*!< Position in delay line.*/
39 | int decim; /*!< Decimation factor.*/
40 | int d_pos; /*!< Actual decimation counter.*/
41 | } fir_f32_t;
42 |
43 | /**
44 | * @brief initialize structure for 32 bit FIR filter
45 | *
46 | * Function initialize structure for 32 bit floating point FIR filter
47 | * The implementation use ANSI C and could be compiled and run on any platform
48 | *
49 | * @param fir: pointer to fir filter structure, that must be preallocated
50 | * @param coeffs: array with FIR filter coefficients. Must be length N
51 | * @param delay: array for FIR filter delay line. Must be length N
52 | * @param N: FIR filter length. Length of coeffs and delay arrays.
53 | *
54 | * @return
55 | * - ESP_OK on success
56 | * - One of the error codes from DSP library
57 | */
58 | esp_err_t dsps_fir_init_f32(fir_f32_t *fir, float *coeffs, float *delay, int N);
59 |
60 | /**
61 | * @brief initialize structure for 32 bit Decimation FIR filter
62 | * Function initialize structure for 32 bit floating point FIR filter with decimation
63 | * The implementation use ANSI C and could be compiled and run on any platform
64 | *
65 | * @param fir: pointer to fir filter structure, that must be preallocated
66 | * @param coeffs: array with FIR filter coefficients. Must be length N
67 | * @param delay: array for FIR filter delay line. Must be length N
68 | * @param N: FIR filter length. Length of coeffs and delay arrays.
69 | * @param decim: decimation factor.
70 | * @param start_pos: initial value of decimation counter. Must be [0..d)
71 | *
72 | * @return
73 | * - ESP_OK on success
74 | * - One of the error codes from DSP library
75 | */
76 | esp_err_t dsps_fird_init_f32(fir_f32_t *fir, float *coeffs, float *delay, int N, int decim, int start_pos);
77 |
78 |
79 | /**@{*/
80 | /**
81 | * @brief FIR filter
82 | *
83 | * Function implements FIR filter
84 | * The extension (_ansi) use ANSI C and could be compiled and run on any platform.
85 | * The extension (_ae32) is optimized for ESP32 chip.
86 | *
87 | * @param fir: pointer to fir filter structure, that must be initialized before
88 | * @param[in] input: input array
89 | * @param[out] output: array with result of FIR filter
90 | * @param[in] len: length of input and result arrays
91 | *
92 | * @return
93 | * - ESP_OK on success
94 | * - One of the error codes from DSP library
95 | */
96 | esp_err_t dsps_fir_f32_ansi(fir_f32_t *fir, const float *input, float *output, int len);
97 | esp_err_t dsps_fir_f32_ae32(fir_f32_t *fir, const float *input, float *output, int len);
98 | /**@}*/
99 |
100 | /**@{*/
101 | /**
102 | * @brief Decimation FIR filter
103 | *
104 | * Function implements FIR filter with decimation
105 | * The extension (_ansi) use ANSI C and could be compiled and run on any platform.
106 | * The extension (_ae32) is optimized for ESP32 chip.
107 | *
108 | * @param fir: pointer to fir filter structure, that must be initialized before
109 | * @param input: input array
110 | * @param output: array with result of FIR filter
111 | * @param len: length of input and result arrays
112 | *
113 | * @return: function returns amount of samples stored to the output array
114 | * depends on the previous state value could be [0..len/decimation]
115 | */
116 | int dsps_fird_f32_ansi(fir_f32_t *fir, const float *input, float *output, int len);
117 | int dsps_fird_f32_ae32(fir_f32_t *fir, const float *input, float *output, int len);
118 | /**@}*/
119 |
120 |
121 | #ifdef __cplusplus
122 | }
123 | #endif
124 |
125 | #ifdef CONFIG_DSP_OPTIMIZED
126 | #define dsps_fir_f32 dsps_fir_f32_ae32
127 | #define dsps_fird_f32 dsps_fird_f32_ae32
128 | #endif
129 | #ifdef CONFIG_DSP_ANSI
130 | #define dsps_fir_f32 dsps_fir_f32_ansi
131 | #define dsps_fird_f32 dsps_fird_f32_ansi
132 | #endif
133 |
134 | #endif // _dsps_fir_H_
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/ESP32DACWaveforms/TwoCoreTalkThru/TwoCoreTalkThru.ino:
--------------------------------------------------------------------------------
1 |
2 | // Created by bobolink
3 | // twitter: @wm6h
4 | // rev: 20180304
5 |
6 | /*
7 | Two core ESP-32 Arduino real-time audio demo.
8 | Tested on Espressif ESP32 Dev board
9 | Rev. 1 silicon
10 | Real-Time Samples at 8Ksps for voice audio range (< 4KHz).
11 | Not for music.
12 | Compatible with Arduino IDE
13 |
14 | talk through
15 | */
16 |
17 | #include
18 | #include
19 |
20 | //int LED_BUILTIN = 5;
21 | int LED_BUILTIN_TTGO = 21;
22 |
23 |
24 | const uint16_t N = 1024; // should be a power of 2 for FFTs
25 | // Determines how long the Application Processor can run for
26 | // real-time applications
27 | // or how long the Application has to write the samples to
28 | // a ring buffer for non-real time applications.
29 | // Latency, analog input to output, is a function of N.
30 |
31 | // we create complex numbers here for convenience
32 | // could be done in frame processing
33 | volatile double realPing[N];
34 | volatile double imagPing[N];
35 | volatile double realPong[N];
36 | volatile double imagPong[N];
37 |
38 | // Do frame processing in floats for better dynamic range.
39 | // At last stage, scale floats to range -1.0 to +1.0
40 | // then convert to unsigned char. Mult by 127 and
41 | // adding 128 to map +1.0 -- -1.0 to 0-255 for
42 | // output to 8-bit unsigned DAC
43 |
44 | // we create analytic IQ input samples
45 | // but we only output real numbers!
46 | volatile unsigned char outRealPing[N];
47 | volatile unsigned char outRealPong[N];
48 |
49 |
50 | float volume = 1.0;
51 | int frameCNT = 0;
52 |
53 | portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
54 |
55 | // this is Core 1's variable.
56 | // Core 0 will operate on the other buffer
57 | volatile boolean pingCore1 = true;
58 |
59 | volatile boolean sampling = false;
60 | volatile boolean outputEnable = true;
61 |
62 | TaskHandle_t Task1;
63 | SemaphoreHandle_t newFrame;
64 |
65 | esp_err_t result;
66 |
67 |
68 | void IRAM_ATTR onTimer()
69 | {
70 |
71 | portENTER_CRITICAL_ISR(&timerMux);
72 | sampling = true;
73 | portEXIT_CRITICAL_ISR(&timerMux);
74 |
75 | }
76 |
77 | void setup()
78 | {
79 |
80 | // initialize digital pin LED_BUILTIN as an output.
81 | pinMode(LED_BUILTIN_TTGO, OUTPUT);
82 |
83 | Serial.begin(115200);
84 |
85 | newFrame = xSemaphoreCreateMutex();
86 |
87 |
88 | xTaskCreatePinnedToCore(
89 | frameProcessing,
90 | "FrameProcessing",
91 | 1000,
92 | NULL,
93 | 1,
94 | &Task1,
95 | 0);
96 |
97 | delay(500); // needed to start-up task1
98 |
99 |
100 | // zero the DAC buffers
101 | for (int i = 0; i < N; ++i)
102 | {
103 | outRealPing[i] = 0;
104 | outRealPong[i] = 0;
105 |
106 | }
107 |
108 | // this almost matches the output resolution
109 | // all channels are GPIOs 32-39
110 | result = adc1_config_width(ADC_WIDTH_9Bit);
111 | // complete with Apple type error message
112 | if (result != ESP_OK)
113 | {
114 | Serial.println("Error, an unknown error occurred");
115 | }
116 |
117 | // this might allow 3.3VDC on the mic
118 | // pin 34
119 | result = adc1_config_channel_atten( ADC1_CHANNEL_6, ADC_ATTEN_11db);
120 | if (result != ESP_OK)
121 | {
122 | Serial.println("Error, an unknown error occurred");
123 | }
124 |
125 | Serial.print("Setup: Executing on core ");
126 | Serial.println(xPortGetCoreID());
127 |
128 |
129 | hw_timer_t* timer = timerBegin(0, 80, true);
130 | timerAttachInterrupt(timer, &onTimer, true);
131 | timerAlarmWrite(timer, 125, true); // sampling frequency 8kHz
132 | timerAlarmEnable(timer);
133 |
134 | }
135 |
136 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
137 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
138 | // This Task runs on Core: 1
139 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
140 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
141 |
142 | // ||||||||||||||||||
143 | // Sample Service
144 | // ||||||||||||||||||
145 | void loop()
146 | {
147 | for (int i = 0; i < N; ++i)
148 | {
149 | while (!sampling);
150 |
151 | portENTER_CRITICAL(&timerMux);
152 | sampling = false;
153 | portEXIT_CRITICAL(&timerMux);
154 |
155 | digitalWrite(LED_BUILTIN_TTGO, HIGH);
156 | if (pingCore1 == true)
157 | {
158 | // configured for 9 bits with an 11 dB pad
159 | // drop one bit to give 8 to match the output
160 | realPing[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
161 | imagPing[i] = 0.0;
162 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
163 | // for VDD_A 3.3V, to 2.59V
164 | if (outputEnable == true)
165 | { // GPIO pin 25 of the ESP32.
166 | // This is the output of DAC1
167 | //dacWrite(25, outRealPing[i]);
168 | dacWrite(26, outRealPing[i]);// pin 26 on TTGO T8
169 | }
170 | }
171 | else
172 | {
173 | // drop one bit to give 8 to match the output
174 | realPong[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
175 | imagPong[i] = 0.0;
176 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
177 | // for VDD_A 3.3V, to 2.59V
178 | if (outputEnable == true)
179 | { // for VDD_A 3.3V, to 2.59V
180 | //dacWrite(25, outRealPong[i]);
181 | dacWrite(26, outRealPong[i]);// pin 26 on TTGO T8
182 | }
183 | } // end single sample processing
184 | digitalWrite(LED_BUILTIN_TTGO, LOW);
185 | } // end N samples processing
186 |
187 | // swap working buffer
188 | pingCore1 = !pingCore1;
189 | // give the old buffer to frame processing
190 | xSemaphoreGive(newFrame);
191 | } // end sample service task
192 |
193 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
194 | // 1111111111111111111111111111111111111111111111111111111111111
195 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
196 |
197 |
198 |
199 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
200 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
201 | // This Task runs on Core: 0
202 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
203 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
204 | // Frame processing
205 | // Runs every N samples
206 |
207 | void frameProcessing( void* parameter )
208 | {
209 | Serial.print("Frame Processing: Executing on core ");
210 | Serial.println(xPortGetCoreID());
211 |
212 | for (;;) // this is required, normally put in by
213 | { // Arduino IDE
214 |
215 | float outVal;
216 | int lm;
217 |
218 | outputEnable = true;
219 |
220 | // "Arf! Arf!"
221 | // pet the watchdog.
222 | vTaskDelay(10);
223 |
224 | // wait for the ping-pong buffer swap
225 | // indicating frame processing should begin
226 | // Core 1 has the timer resolution and is in charge of buffers
227 | xSemaphoreTake(newFrame, portMAX_DELAY);
228 |
229 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++
230 | // ++++++++++++++++++++++++++++++++++++++++++++++++++++
231 | // frame processing takes place here:
232 | for (int i = 0; i < N; ++i)
233 | {
234 | // NOTE:
235 | // this variable belongs to core 1 -- use the other buffer
236 | // If core 1 is ping, we are pong
237 | if (pingCore1 == true)
238 | {
239 | outVal = realPong[i] * 0.008; // scale float to +/- 1.0
240 | outRealPong[i] = (unsigned char) (outVal * 127.0 + 128.0);
241 | }
242 | else
243 | {
244 | outVal = realPing[i] * 0.008; // scale float to +/- 1.0
245 | outRealPing[i] = (unsigned char) (outVal * 127.0 + 128.0);
246 | }
247 | }// end frame processing of N samples
248 | } // end Arduino task loop
249 | }
250 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
251 | // 0000000000000000000000000000000000000000000000000000000000000
252 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
253 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/ESP32DACWaveforms/TwoCoreSweepESP32/TwoCoreSweepESP32.ino:
--------------------------------------------------------------------------------
1 |
2 | // Created by bobolink
3 | // twitter: @wm6h
4 | // rev: 20180304
5 |
6 |
7 | /*
8 | Two core ESP-32 Arduino real-time audio demo.
9 | Tested on Espressif ESP32 Dev board
10 | Rev. 1 silicon
11 | Real-Time Samples at 8Ksps for voice audio range (< 4KHz).
12 | Not for music.
13 | Compatible with Arduino IDE
14 |
15 | Continuous phase frequency sweep test signal
16 | (300--3000 Hz in 5 sec., repeated)
17 | */
18 |
19 | #include
20 | #include
21 |
22 | //int LED_BUILTIN = 5;
23 |
24 | const uint16_t N = 1024; // should be a power of 2 for FFTs
25 | // Determines how long the Application Processor can run for
26 | // real-time applications
27 | // or how long the Application has to write the samples to
28 | // a ring buffer for non-real time applications.
29 | // Latency, input to output, is a function of N.
30 |
31 | // we create complex numbers here for convenience
32 | // could be done in frame processing
33 | volatile double realPing[N];
34 | volatile double imagPing[N];
35 | volatile double realPong[N];
36 | volatile double imagPong[N];
37 |
38 | // Do frame processing in floats for better dynamic range.
39 | // At last stage, scale floats to range -1.0 to +1.0
40 | // then convert to unsigned char. Mult by 127 and
41 | // adding 128 to map +1.0 -- -1.0 to 0-255 for
42 | // output to 8-bit unsigned DAC
43 |
44 | // we create analytic IQ input samples
45 | // but we only output real numbers
46 | volatile unsigned char outRealPing[N];
47 | volatile unsigned char outRealPong[N];
48 |
49 | const float Pi = 3.14159;
50 | float fangle = 0.0;
51 | float sampleRateHz = 8000.0;
52 | float testFreqHz = 300.0;
53 | // phase increment per sample
54 | const float phase = 2.0 * Pi * (testFreqHz / sampleRateHz);
55 |
56 | float phi = 0;
57 | float f0 = 300; //initial frequency (Hz)
58 | float f1 = 3000; // final frequency (Hz)--keep below 4KHz
59 | float tSweep = 5; //duration of sweep (s)
60 | float f = f0;
61 |
62 | // how long do divides take?
63 | // should we multiple by reciprocal in Frame processing?
64 | float fDelta = (f1 - f0) / (sampleRateHz * tSweep);
65 | float delta = 2.0 * Pi * (f / sampleRateHz);
66 | float t = 1/sampleRateHz;
67 |
68 | float volume = 0.5;
69 |
70 | portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
71 |
72 | // this is Core 1's variable.
73 | // Core 0 will operate on the other buffer
74 | volatile boolean pingCore1 = true;
75 |
76 | volatile boolean sampling = false;
77 | volatile boolean outputEnable = true;
78 |
79 | TaskHandle_t Task1;
80 | SemaphoreHandle_t newFrame;
81 |
82 | esp_err_t result;
83 |
84 | void IRAM_ATTR onTimer()
85 | {
86 |
87 | portENTER_CRITICAL_ISR(&timerMux);
88 | sampling = true;
89 | portEXIT_CRITICAL_ISR(&timerMux);
90 |
91 | }
92 |
93 | void setup()
94 | {
95 |
96 | // initialize digital pin LED_BUILTIN as an output.
97 | //pinMode(LED_BUILTIN, OUTPUT);
98 |
99 | // Serial.begin(115200);
100 |
101 | newFrame = xSemaphoreCreateMutex();
102 |
103 |
104 | xTaskCreatePinnedToCore(
105 | frameProcessing,
106 | "FrameProcessing",
107 | 1000,
108 | NULL,
109 | 1,
110 | &Task1,
111 | 0);
112 |
113 | delay(500); // needed to start-up task1
114 |
115 |
116 | // zero the DAC buffers
117 | for (int i = 0; i < N; ++i)
118 | {
119 | outRealPing[i] = 0;
120 | outRealPong[i] = 0;
121 |
122 | }
123 |
124 | // this almost matches the output resolution
125 | // all channels GPIOs 32-39
126 | result = adc1_config_width(ADC_WIDTH_9Bit);
127 | // complete with Apple type error message
128 | if (result != ESP_OK)
129 | {
130 | Serial.println("Error, an unknown error occurred");
131 | }
132 |
133 | // this might allow 3.3VDC on the mic
134 | // pin 34
135 | result = adc1_config_channel_atten( ADC1_CHANNEL_6, ADC_ATTEN_11db);
136 | if (result != ESP_OK)
137 | {
138 | Serial.println("Error, an unknown error occurred");
139 | }
140 |
141 | hw_timer_t* timer = timerBegin(0, 80, true);
142 | timerAttachInterrupt(timer, &onTimer, true);
143 | timerAlarmWrite(timer, 125, true); // sampling frequency 8kHz
144 | timerAlarmEnable(timer);
145 |
146 | }
147 |
148 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
149 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
150 | // This Task runs on Core: 1
151 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
152 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
153 |
154 | // ||||||||||||||||||
155 | // Sample Service
156 | // ||||||||||||||||||
157 | void loop()
158 | {
159 | for (int i = 0; i < N; ++i)
160 | {
161 | while (!sampling);
162 |
163 | portENTER_CRITICAL(&timerMux);
164 | sampling = false;
165 | portEXIT_CRITICAL(&timerMux);
166 |
167 | //digitalWrite(LED_BUILTIN, HIGH);
168 | if (pingCore1 == true)
169 | {
170 | // configured for 9 bits with an 11 dB pad
171 | // drop one bit to give 8 to match the output
172 | realPing[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
173 | imagPing[i] = 0.0;
174 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
175 | // for VDD_A 3.3V, to 2.59V
176 | if (outputEnable == true)
177 | { // GPIO pin 25 of the ESP32.
178 | // This is the output of DAC1
179 | dacWrite(26, outRealPing[i]);
180 | }
181 | }
182 | else
183 | {
184 | // drop one bit to give 8 to match the output
185 | realPong[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
186 | imagPong[i] = 0.0;
187 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
188 | // for VDD_A 3.3V, to 2.59V
189 | if (outputEnable == true)
190 | { // for VDD_A 3.3V, to 2.59V
191 | dacWrite(26, outRealPong[i]);
192 | }
193 | } // end single sample processing
194 | //digitalWrite(LED_BUILTIN, LOW);
195 |
196 | } // end N samples processing
197 |
198 | // swap working buffer
199 | pingCore1 = !pingCore1;
200 | // give the old buffer to frame processing
201 | xSemaphoreGive(newFrame);
202 | } // end sample service task
203 |
204 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
205 | // 1111111111111111111111111111111111111111111111111111111111111
206 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
207 |
208 |
209 |
210 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
211 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
212 | // This Task runs on Core: 0
213 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
214 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
215 | // Frame processing
216 | // Runs every N samples
217 |
218 | void frameProcessing( void* parameter )
219 | {
220 | for (;;) // this is required, normally put in by
221 | { // Arduino IDE
222 |
223 | float outVal;
224 |
225 | outputEnable = true;
226 |
227 | // "Arf! Arf!"
228 | // pet the watchdog.
229 | vTaskDelay(10);
230 | // wait for the ping-pong buffer swap
231 | // indicating frame processing should begin
232 | // Core 1 has the timer resolution and is in charge of buffers
233 | xSemaphoreTake(newFrame, portMAX_DELAY);
234 |
235 | // frame processing takes place here:
236 | for (int i = 0; i < N; ++i)
237 | {
238 | phi = 0;
239 | outVal = sinf(phi) * volume;
240 |
241 |
242 | phi += delta;
243 |
244 |
245 | f += fDelta;
246 | if(f >= f1)
247 | {
248 | f = f0;
249 | phi = 0;
250 | }
251 |
252 | // multiply instead of divide
253 | // for speed?
254 | delta = 2 * Pi * f * t;
255 |
256 | // NOTE:
257 | // this variable belongs to core 1 -- use the other buffer
258 | // If core 1 is ping, we are pong
259 | if (pingCore1 == true)
260 | {
261 | outRealPong[i] = (unsigned char) (outVal * 127.0 + 128.0);
262 |
263 | }
264 | else
265 | {
266 | outRealPing[i] = (unsigned char) (outVal * 127.0 + 128.0);
267 |
268 | }
269 |
270 | }// end frame processing of N samples
271 |
272 | } // end Arduino task loop
273 | }
274 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
275 | // 0000000000000000000000000000000000000000000000000000000000000
276 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
277 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/ESP32DACWaveforms/TwoCoreTwoToneESP32/TwoCoreTwoToneESP32.ino:
--------------------------------------------------------------------------------
1 |
2 | // Created by bobolink
3 | // twitter: @wm6h
4 | // rev: 20180304
5 |
6 | /*
7 | Two core ESP-32 Arduino real-time audio demo.
8 | Tested on Espressif ESP32 Dev board
9 | Rev. 1 silicon
10 | Real-Time Samples at 8Ksps for voice audio range (< 4KHz).
11 | Not for music.
12 | Compatible with Arduino IDE
13 | */
14 |
15 | /*
16 | * Generates an old-time telephone dial tone
17 | * With two tones (350 and 440 Hz).
18 | *
19 | * this example points out that
20 | * a computed value must be scaled properly to stay within the
21 | * +0.1 to -0.1 range as to not overload the 8-bit DAC.
22 | * When the two numbers within range are added,
23 | * they will exceed +/- 1.0 and must be divided by two.
24 | * Three numbers added must be divided by 3, etc.
25 | */
26 |
27 | #include
28 | #include
29 |
30 | //int LED_BUILTIN = 5;
31 |
32 | const uint16_t N = 1024; // should be a power of 2 for FFTs
33 | // Determines how long the Application Processor can run for
34 | // real-time applications
35 | // or how long the Application has to write the samples to
36 | // a ring buffer for non-real time applications.
37 | // Latency, input to output, is a function of N.
38 |
39 | // we create complex numbers here for convenience
40 | // could be done in frame processing
41 | volatile double realPing[N];
42 | volatile double imagPing[N];
43 | volatile double realPong[N];
44 | volatile double imagPong[N];
45 |
46 | // Do frame processing in floats for better dynamic range.
47 | // At last stage, scale floats to range -1.0 to +1.0
48 | // then convert to unsigned char. Mult by 127 and
49 | // adding 128 to map +1.0 -- -1.0 to 0-255 for
50 | // output to 8-bit unsigned DAC
51 |
52 | // we create analytic IQ input samples
53 | // but we only output real numbers
54 | volatile unsigned char outRealPing[N];
55 | volatile unsigned char outRealPong[N];
56 |
57 | const float Pi = 3.14159;
58 | float theta1 = 0.0;
59 | float theta2 = 0.0;
60 | float sampleRateHz = 8000.0;
61 | float testFreqHz1 = 350.0;
62 | float testFreqHz2 = 440.0;
63 | const float theta_increment1 = 2.0 * Pi * (testFreqHz1 / sampleRateHz);
64 | const float theta_increment2 = 2.0 * Pi * (testFreqHz2 / sampleRateHz);
65 |
66 | float volume = 1.0;
67 |
68 | portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
69 |
70 | // this is Core 1's variable.
71 | // Core 0 will operate on the other buffer
72 | volatile boolean pingCore1 = true;
73 |
74 | volatile boolean sampling = false;
75 | volatile boolean outputEnable = true;
76 |
77 | TaskHandle_t Task1;
78 | SemaphoreHandle_t newFrame;
79 |
80 | esp_err_t result;
81 |
82 | void IRAM_ATTR onTimer()
83 | {
84 |
85 | portENTER_CRITICAL_ISR(&timerMux);
86 | sampling = true;
87 | portEXIT_CRITICAL_ISR(&timerMux);
88 |
89 | }
90 |
91 | void setup()
92 | {
93 |
94 | // initialize digital pin LED_BUILTIN as an output.
95 | pinMode(LED_BUILTIN, OUTPUT);
96 |
97 | Serial.begin(115200);
98 |
99 | newFrame = xSemaphoreCreateMutex();
100 |
101 |
102 | xTaskCreatePinnedToCore(
103 | frameProcessing,
104 | "FrameProcessing",
105 | 1000,
106 | NULL,
107 | 1,
108 | &Task1,
109 | 0);
110 |
111 | delay(500); // needed to start-up task1
112 |
113 |
114 | // zero the DAC buffers
115 | for (int i = 0; i < N; ++i)
116 | {
117 | outRealPing[i] = 0;
118 | outRealPong[i] = 0;
119 |
120 | }
121 |
122 | // this almost matches the output resolution
123 | // all channels GPIOs 32-39
124 | result = adc1_config_width(ADC_WIDTH_9Bit);
125 | // complete with Apple type error message
126 | if (result != ESP_OK)
127 | {
128 | Serial.println("Error, an unknown error occurred");
129 | }
130 |
131 | // this might allow 3.3VDC on the mic
132 | // pin 34
133 | result = adc1_config_channel_atten( ADC1_CHANNEL_6, ADC_ATTEN_11db);
134 | if (result != ESP_OK)
135 | {
136 | Serial.println("Error, an unknown error occurred");
137 | }
138 |
139 | hw_timer_t* timer = timerBegin(0, 80, true);
140 | timerAttachInterrupt(timer, &onTimer, true);
141 | timerAlarmWrite(timer, 125, true); // sampling frequency 8kHz
142 | timerAlarmEnable(timer);
143 |
144 | }
145 |
146 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
147 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
148 | // This Task runs on Core: 1
149 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
150 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
151 |
152 | // ||||||||||||||||||
153 | // Sample Service
154 | // ||||||||||||||||||
155 | void loop()
156 | {
157 | for (int i = 0; i < N; ++i)
158 | {
159 | while (!sampling);
160 |
161 | portENTER_CRITICAL(&timerMux);
162 | sampling = false;
163 | portEXIT_CRITICAL(&timerMux);
164 |
165 | digitalWrite(LED_BUILTIN, HIGH);
166 | if (pingCore1 == true)
167 | {
168 | // configured for 9 bits with an 11 dB pad
169 | // drop one bit to give 8 to match the output
170 | realPing[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
171 | imagPing[i] = 0.0;
172 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
173 | // for VDD_A 3.3V, to 2.59V
174 | if (outputEnable == true)
175 | { // GPIO pin 25 of the ESP32.
176 | // This is the output of DAC1
177 | dacWrite(26, outRealPing[i]);
178 | }
179 | }
180 | else
181 | {
182 | // drop one bit to give 8 to match the output
183 | realPong[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
184 | imagPong[i] = 0.0;
185 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
186 | // for VDD_A 3.3V, to 2.59V
187 | if (outputEnable == true)
188 | { // for VDD_A 3.3V, to 2.59V
189 | dacWrite(26, outRealPong[i]);
190 | }
191 | } // end single sample processing
192 | digitalWrite(LED_BUILTIN, LOW);
193 | } // end N samples processing
194 |
195 | // swap working buffer
196 | pingCore1 = !pingCore1;
197 | // give the old buffer to frame processing
198 | xSemaphoreGive(newFrame);
199 | } // end sample service task
200 |
201 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
202 | // 1111111111111111111111111111111111111111111111111111111111111
203 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
204 |
205 |
206 |
207 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
208 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
209 | // This Task runs on Core: 0
210 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
211 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
212 | // Frame processing
213 | // Runs every N samples
214 |
215 | void frameProcessing( void* parameter )
216 | {
217 | for (;;) // this is required, normally put in by
218 | { // Arduino IDE
219 |
220 | float outVal;
221 |
222 | outputEnable = true;
223 |
224 | // "Arf! Arf!"
225 | // pet the watchdog.
226 | vTaskDelay(10);
227 |
228 | // wait for the ping-pong buffer swap
229 | // indicating frame processing should begin
230 | // Core 1 has the timer resolution and is in charge of buffers
231 | xSemaphoreTake(newFrame, portMAX_DELAY);
232 |
233 | // frame processing takes place here:
234 | for (int i = 0; i < N; ++i)
235 | {
236 | // the point of this example is to point out that
237 | // a computed value must be scaled properly to stay within the
238 | // +0.1 to -0.1 range to not overload the 8-bit DAC.
239 | // When the two numbers are added, they exceed +/- 1.0
240 | // and must be divided by two (mult by 0.5). Three numbers added must
241 | // be divided by 3, etc.
242 | outVal = (sinf(theta1) + sinf(theta2)) * 0.5 * volume;
243 |
244 | theta1 += theta_increment1;
245 | if (theta1 > 2.0 * Pi)
246 | {
247 | theta1 -= 2.0 * Pi;
248 | }
249 |
250 | theta2 += theta_increment2;
251 | if (theta2 > 2.0 * Pi)
252 | {
253 | theta2 -= 2.0 * Pi;
254 | }
255 | // NOTE:
256 | // this variable belongs to core 1 -- use the other buffer
257 | // If core 1 is ping, we are pong
258 | if (pingCore1 == true)
259 | {
260 | outRealPong[i] = (unsigned char) (outVal * 127.0 + 128.0);
261 | }
262 | else
263 | {
264 | outRealPing[i] = (unsigned char) (outVal * 127.0 + 128.0);
265 | }
266 |
267 | }// end frame processing of N samples
268 |
269 | } // end Arduino task loop
270 | }
271 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
272 | // 0000000000000000000000000000000000000000000000000000000000000
273 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
274 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/ESP32DACWaveforms/TwoCoreSineESP32/TwoCoreSineESP32.ino:
--------------------------------------------------------------------------------
1 |
2 | // Created by bobolink
3 | // twitter: @wm6h
4 | // rev: 20180304
5 |
6 | /*
7 | Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
8 | Ported to Arduino ESP32 by Evandro Copercini
9 | */
10 |
11 | #include
12 | #include
13 | #include
14 |
15 | /*
16 | Two core ESP-32 Arduino real-time audio demo.
17 | Tested on Espressif ESP32 Dev board
18 | Rev. 1 silicon
19 | Real-Time Samples at 8Ksps for voice audio range (< 4KHz).
20 | Not for music.
21 | Compatible with Arduino IDE
22 |
23 | Generates a sine wave
24 | */
25 |
26 | #include
27 | #include
28 |
29 |
30 | #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
31 | #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
32 |
33 | //int LED_BUILTIN = 5;
34 | int LED_BUILTIN_TTGO = 21;
35 |
36 | const uint16_t N = 1024; // should be a power of 2 for FFTs
37 | // Determines how long the Application Processor can run for
38 | // real-time applications
39 | // or how long the Application has to write the samples to
40 | // a ring buffer for non-real time applications.
41 | // Latency, input to output, is a function of N.
42 |
43 |
44 | // we create complex numbers here for convenience
45 | // could be done in frame processing
46 | volatile double realPing[N];
47 | volatile double imagPing[N];
48 | volatile double realPong[N];
49 | volatile double imagPong[N];
50 |
51 | // Do frame processing in floats for better dynamic range.
52 | // At last stage, scale floats to range -1.0 to +1.0
53 | // then convert to unsigned char. Mult by 127 and
54 | // adding 128 to map +1.0 -- -1.0 to 0-255 for
55 | // output to 8-bit unsigned DAC
56 |
57 | // we create analytic IQ input samples
58 | // but we only output real numbers
59 | volatile unsigned char outRealPing[N];
60 | volatile unsigned char outRealPong[N];
61 |
62 | const float Pi = 3.14159;
63 | float theta = 0.0;
64 | float sampleRateHz = 8000.0;
65 | float testFreqHz = 1000.0;
66 | //const float theta_increment = 2.0 * Pi * (testFreqHz / sampleRateHz);
67 | float theta_increment;
68 |
69 |
70 | float volume = 0.5;
71 |
72 | portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
73 |
74 | // this is Core 1's variable.
75 | // Core 0 will operate on the other buffer
76 | volatile boolean pingCore1 = true;
77 |
78 | volatile boolean sampling = false;
79 | volatile boolean outputEnable = true;
80 |
81 |
82 | TaskHandle_t Task1;
83 | SemaphoreHandle_t newFrame;
84 |
85 | esp_err_t result;
86 |
87 | void IRAM_ATTR onTimer()
88 | {
89 |
90 | portENTER_CRITICAL_ISR(&timerMux);
91 | sampling = true;
92 | portEXIT_CRITICAL_ISR(&timerMux);
93 |
94 | }
95 |
96 | class MyCallbacks: public BLECharacteristicCallbacks {
97 | void onWrite(BLECharacteristic *pCharacteristic) {
98 | std::string value = pCharacteristic->getValue();
99 |
100 | // not very safe code
101 | char tempc[4];
102 |
103 |
104 | if (value.length() > 0) {
105 | Serial.println("*********");
106 | Serial.print("New value: ");
107 | for (int i = 0; i < value.length(); i++)
108 | {
109 | //Serial.print(value[i]);
110 | tempc[i] = value[i];
111 | }
112 |
113 | //float f = (float) atof(tempc);
114 | float f = strtod(tempc,NULL);
115 | if( (f>30) && (f<=3000) )
116 | testFreqHz = f;
117 |
118 | Serial.println(f);
119 | Serial.println("*********");
120 | }
121 | }
122 | };
123 |
124 |
125 | void setup()
126 | {
127 |
128 | // initialize digital pin LED_BUILTIN as an output.
129 | pinMode(LED_BUILTIN_TTGO, OUTPUT);
130 |
131 | Serial.begin(115200);
132 |
133 | newFrame = xSemaphoreCreateMutex();
134 |
135 |
136 | xTaskCreatePinnedToCore(
137 | frameProcessing,
138 | "FrameProcessing",
139 | 1000,
140 | NULL,
141 | 1,
142 | &Task1,
143 | 0);
144 |
145 | delay(500); // needed to start-up task1
146 | // from Mr. Spiess' video
147 |
148 | // zero the DAC buffers
149 | for (int i = 0; i < N; ++i)
150 | {
151 | outRealPing[i] = 0;
152 | outRealPong[i] = 0;
153 |
154 | }
155 |
156 | // this almost matches the output resolution
157 | // all channels GPIOs 32-39
158 | result = adc1_config_width(ADC_WIDTH_9Bit);
159 | // complete with Apple type error message
160 | if (result != ESP_OK)
161 | {
162 | Serial.println("Error, an unknown error occurred");
163 | }
164 |
165 | // this might allow 3.3VDC on the mic
166 | // pin 34
167 | result = adc1_config_channel_atten( ADC1_CHANNEL_6, ADC_ATTEN_11db);
168 | if (result != ESP_OK)
169 | {
170 | Serial.println("Error, an unknown error occurred");
171 | }
172 |
173 |
174 |
175 |
176 | BLEDevice::init("MyESP32");
177 | BLEServer *pServer = BLEDevice::createServer();
178 |
179 | BLEService *pService = pServer->createService(SERVICE_UUID);
180 |
181 | BLECharacteristic *pCharacteristic = pService->createCharacteristic(
182 | CHARACTERISTIC_UUID,
183 | BLECharacteristic::PROPERTY_READ |
184 | BLECharacteristic::PROPERTY_WRITE
185 | );
186 |
187 | pCharacteristic->setCallbacks(new MyCallbacks());
188 |
189 | pCharacteristic->setValue("Hello World");
190 | pService->start();
191 |
192 | BLEAdvertising *pAdvertising = pServer->getAdvertising();
193 | pAdvertising->start();
194 |
195 |
196 |
197 |
198 | Serial.print("Setup: Executing on core ");
199 | Serial.println(xPortGetCoreID());
200 |
201 | hw_timer_t* timer = timerBegin(0, 80, true);
202 | timerAttachInterrupt(timer, &onTimer, true);
203 | timerAlarmWrite(timer, 125, true); // sampling frequency 8kHz
204 | timerAlarmEnable(timer);
205 |
206 | }
207 |
208 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
209 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
210 | // This Task runs on Core: 1
211 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
212 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
213 |
214 | // ||||||||||||||||||
215 | // Sample Service
216 | // ||||||||||||||||||
217 | void loop()
218 | {
219 | for (int i = 0; i < N; ++i)
220 | {
221 | while (!sampling);
222 |
223 | portENTER_CRITICAL(&timerMux);
224 | sampling = false;
225 | portEXIT_CRITICAL(&timerMux);
226 |
227 | //digitalWrite(LED_BUILTIN_TTGO, HIGH);
228 | if (pingCore1 == true)
229 | {
230 | // configured for 9 bits with an 11 dB pad
231 | // drop one bit to give 8 to match the output
232 | realPing[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
233 | imagPing[i] = 0.0;
234 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
235 | // for VDD_A 3.3V, to 2.59V
236 | if (outputEnable == true)
237 | { // GPIO pin 25 of the ESP32.
238 | // This is the output of DAC1
239 | //dacWrite(25, outRealPing[i]);
240 | dacWrite(26, outRealPing[i]);//pin 26 TTGO T8
241 | }
242 | }
243 | else
244 | {
245 | // drop one bit to give 8 to match the output
246 | realPong[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
247 | imagPong[i] = 0.0;
248 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
249 | // for VDD_A 3.3V, to 2.59V
250 | if (outputEnable == true)
251 | { // for VDD_A 3.3V, to 2.59V
252 | //dacWrite(25, outRealPong[i]);
253 | dacWrite(26, outRealPong[i]);//pin 26 TTGO T8
254 | }
255 | } // end single sample processing
256 | //digitalWrite(LED_BUILTIN_TTGO, LOW);
257 | } // end N samples processing
258 |
259 | // swap working buffer
260 | pingCore1 = !pingCore1;
261 | // give the old buffer to frame processing
262 | xSemaphoreGive(newFrame);
263 | } // end sample service task
264 |
265 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
266 | // 1111111111111111111111111111111111111111111111111111111111111
267 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
268 |
269 |
270 |
271 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
272 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
273 | // This Task runs on Core: 0
274 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
275 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
276 | // Frame processing
277 | // Runs every N samples
278 |
279 | void frameProcessing( void* parameter )
280 | {
281 | Serial.print("Frame Processing: Executing on core ");
282 | Serial.println(xPortGetCoreID());
283 |
284 | for (;;) // this is required, normally put in by
285 | { // Arduino IDE
286 |
287 | float outVal;
288 |
289 | outputEnable = true;
290 |
291 | // "Arf! Arf!"
292 | // pet the watchdog.
293 | vTaskDelay(10);
294 |
295 | // wait for the ping-pong buffer swap
296 | // indicating frame processing should begin
297 | // Core 1 has the timer resolution and is in charge of buffers
298 | xSemaphoreTake(newFrame, portMAX_DELAY);
299 |
300 | digitalWrite(LED_BUILTIN_TTGO, HIGH);
301 | // don't need to give it back
302 | //xSemaphoreGive(newFrame);
303 | theta_increment = 2.0 * Pi * (testFreqHz * 0.000125);
304 |
305 | // frame processing takes place here:
306 | for (int i = 0; i < N; ++i)
307 | {
308 | outVal = sinf(theta) * volume;
309 | theta += theta_increment;
310 | if (theta > 2.0 * Pi)
311 | {
312 | theta -= 2.0 * Pi;
313 | }
314 | // NOTE:
315 | // this variable belongs to core 1 -- use the other buffer
316 | // If core 1 is ping, we are pong
317 | if (pingCore1 == true)
318 | {
319 | outRealPong[i] = (unsigned char) (outVal * 127.0 + 128.0);
320 | }
321 | else
322 | {
323 | outRealPing[i] = (unsigned char) (outVal * 127.0 + 128.0);
324 | }
325 |
326 | }// end frame processing of N samples
327 |
328 | digitalWrite(LED_BUILTIN_TTGO, LOW);
329 | // this processing takes 2.24 msec.
330 | // out of 128 msec. available to the Frame
331 | // 125 usec * 1024 = 128 msec.
332 | // 1.75% loaded
333 | //
334 | } // end Arduino task loop
335 | }
336 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
337 | // 0000000000000000000000000000000000000000000000000000000000000
338 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
339 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "[]"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright [yyyy] [name of copyright owner]
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/ESP32FIR.ino:
--------------------------------------------------------------------------------
1 |
2 | // Created by bobolink
3 | // twitter: @wm6h
4 | // rev: 20200126
5 |
6 | // Copyright 2020 WM6H
7 | //
8 | // Licensed under the Apache License, Version 2.0 (the "License");
9 | // you may not use this file except in compliance with the License.
10 | // You may obtain a copy of the License at
11 | //
12 | // http://www.apache.org/licenses/LICENSE-2.0
13 | //
14 | // Unless required by applicable law or agreed to in writing, software
15 | // distributed under the License is distributed on an "AS IS" BASIS,
16 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 | // See the License for the specific language governing permissions and
18 | // limitations under the License.
19 |
20 | /* NOTE:
21 | * You need to specify the file name of the wav file on the SD card
22 | * you want to pass through the FIR filter
23 | * Also, which 400 Hz filter you want to use-- the bandstop or high pass filter--
24 | * by including the desired filer coefficient file.
25 | * See STEP 1 and STEP 2 below
26 | */
27 |
28 | /*
29 | Two core ESP-32 Arduino real-time audio demo.
30 | Tested on Espressif ESP32 Dev board
31 | Rev. 1 silicon
32 | Real-Time Samples at 8Ksps for voice audio range (< 4KHz).
33 | Not for high fidelity music.
34 | Compatible with Arduino IDE
35 |
36 | Updated to read input test signals from sd card on a
37 | TTGO T8 Development card
38 | Added FIR filter
39 | SD card file is: 8Ksps, mono, WAV (Microsoft) signed 16-bit PCM
40 | FAT32 formatted SD Card
41 |
42 | http://www.iotsharing.com/2017/07/how-to-use-arduino-esp32-i2s-to-play-wav-music-from-sdcard.html
43 |
44 | NOTE:
45 | SDCARD interface library must be installed manually.
46 |
47 | Installing Additional Arduino Libraries
48 | https://www.arduino.cc/en/guide/libraries
49 |
50 | Found in top directory
51 | Sketch->Include Library->Add .ZIP Library “esp32-micro-sdcard-master.zip”
52 | #include
53 |
54 | */
55 |
56 | #include
57 | #include
58 |
59 | //STEP 1
60 | //*******************************************************************
61 | // Initialize "SDcardFileName" with the SD Card file you want to play
62 | // Uncomment one of these:
63 |
64 | // a 30 sec 1000 Hz tone
65 | // String SDcardFileName = "sineWAV.wav";
66 |
67 | // 2 min of 400 Hz plus 1000Hz
68 | // enable 400Hz filter to eliminate interference
69 | String SDcardFileName = "mix.wav";
70 |
71 | // 400Hz tone for 2 minutes
72 | // if the 400Hz StopBand or HighPass filter is in,
73 | // no sound should be heard
74 | //String SDcardFileName = "400Hz2m.wav";
75 |
76 | //*******************************************************************
77 | /*
78 | Based on Neil Kolban example for IDF:
79 | https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleWrite.cpp
80 | Ported to Arduino ESP32 by Evandro Copercini
81 | */
82 |
83 | #include
84 | #include
85 | #include
86 |
87 | //\||||||||||||||||||||||||||
88 | #include
89 |
90 | // minimum library includes for the FIR filter
91 | #include "dsp_err.h"
92 | #include "dsp_err_codes.h"
93 |
94 | #include "dsps_fir.h"
95 |
96 | //STEP 2
97 | //*******************************************************************
98 | // Include only one of these FIR filters
99 | // Bandstop or HighPass
100 | // see ./design/ directory for filter frequency plots
101 |
102 | // 400Hz filters:
103 | //#include "fdaBScoefs.h"//(length 121) 40 dB attenuation BandStop
104 | #include "fdaHPcoefs.h" //(length 51) 60 dB attenuation HighPass
105 |
106 | // filter is switched in/out programmatically over a
107 | // Bluetooth Low Energy (BLE) wireless link.
108 | // A write of a value to characteristic
109 | // "beb5483e-36e1-4688-b7f5-ea07361b26a8" toggles the filter in/out
110 | // Use free phone app from LightBlue or nRF Connect (Nordic) to
111 | // write values.
112 |
113 | // Connect to BLE peripheral advertising name "DSP_FILTER"
114 |
115 | //*******************************************************************
116 |
117 |
118 | // BL is the coefficient name Matlab gives
119 | #define NTAPS BL-1
120 |
121 | #define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
122 | #define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
123 | //\||||||||||||||||||||||||||
124 |
125 | //#include "driver/i2s.h"
126 | //#include "freertos/queue.h"
127 |
128 | /* variables hold file, state of process wav file and wav file properties */
129 | File root;
130 | bool wavPlaying = false;
131 | bool LoopBack = true;//start with input copied to output to hear tone
132 | // then switch in the filter over BLE
133 |
134 |
135 |
136 | #define CCCC(c1, c2, c3, c4) ((c4 << 24) | (c3 << 16) | (c2 << 8) | c1)
137 |
138 | /* these are data structures to process wav file */
139 | typedef enum headerState_e {
140 | HEADER_RIFF, HEADER_FMT, HEADER_DATA, DATA, OUT_OF_DATA
141 | } headerState_t;
142 |
143 | typedef struct wavRiff_s {
144 | uint32_t chunkID;
145 | uint32_t chunkSize;
146 | uint32_t format;
147 | } wavRiff_t;
148 |
149 | typedef struct wavProperties_s {
150 | uint32_t chunkID;
151 | uint32_t chunkSize;
152 | uint16_t audioFormat;
153 | uint16_t numChannels;
154 | uint32_t sampleRate;
155 | uint32_t byteRate;
156 | uint16_t blockAlign;
157 | uint16_t bitsPerSample;
158 | } wavProperties_t;
159 |
160 | headerState_t state = HEADER_RIFF;
161 | wavProperties_t wavProps;
162 | // convert little endian to big endian 4 byte int
163 | uint32_t overall_size = 0;
164 | unsigned char buffer4[4];
165 |
166 |
167 | const uint16_t N = 1024; // should be a power of 2 for FFTs
168 | // Determines how long the Application Processor can run for
169 | // real-time applications
170 | // or how long the Application has to write the samples to
171 | // a ring buffer for non-real time applications.
172 | // Latency, input to output, is a function of N.
173 |
174 | //\||||||||||||||||||||||||||
175 | // x[] is input to the filter
176 | float x[N];
177 | // y[] is output of the filter and routed to the DAC
178 | float y[N];
179 |
180 | float coeffs[NTAPS];
181 | float history[NTAPS];
182 | int len;
183 | int fir_len;
184 | unsigned int startTEST = 0;
185 | unsigned int endTEST = 0;
186 | float totalTEST;
187 |
188 | fir_f32_t fir1;
189 |
190 | //\||||||||||||||||||||||||||
191 |
192 | void debug(uint8_t *buf, int len)
193 | {
194 | for (int i = 0; i < len; i++) {
195 | Serial.print(buf[i], HEX);
196 | Serial.print("\t");
197 | }
198 | Serial.println();
199 | }
200 |
201 | /* read 4 bytes of data from wav file */
202 | int read4bytes(File file, uint32_t *chunkId) {
203 | int n = file.read((uint8_t *)chunkId, sizeof(uint32_t));
204 | return n;
205 | }
206 |
207 | int readbyte(File file, uint8_t *chunkId) {
208 | int n = file.read((uint8_t *)chunkId, sizeof(uint8_t));
209 | return n;
210 | }
211 |
212 | /* these are function to process wav file */
213 | int readRiff(File file, wavRiff_t *wavRiff) {
214 | int n = file.read((uint8_t *)wavRiff, sizeof(wavRiff_t));
215 | return n;
216 | }
217 | int readProps(File file, wavProperties_t *wavProps) {
218 | int n = file.read((uint8_t *)wavProps, sizeof(wavProperties_t));
219 | return n;
220 | }
221 |
222 |
223 | int LED_BUILTIN_TTGO = 21;
224 |
225 | // we create complex numbers here for convenience
226 | // could be done in frame processing
227 | volatile float realPing[N];
228 | volatile float imagPing[N];
229 | volatile float realPong[N];
230 | volatile float imagPong[N];
231 |
232 | // Do frame processing in floats for better dynamic range.
233 | // At last stage, scale floats to range -1.0 to +1.0
234 | // then convert to unsigned char. Mult by 127 and
235 | // adding 128 to map +1.0 -- -1.0 to 0-255 for
236 | // output to 8-bit unsigned DAC
237 |
238 | // we create analytic IQ input samples
239 | // but we only output real numbers because, well you know,
240 | // they're real
241 | volatile unsigned char outRealPing[N];
242 | volatile unsigned char outRealPong[N];
243 |
244 | float volume;
245 |
246 | portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
247 |
248 | // this is Core 1's variable.
249 | // Core 0 will operate on the other buffer
250 | volatile boolean pingCore1 = true;
251 |
252 | volatile boolean sampling = false;
253 | volatile boolean outputEnable = true;
254 |
255 |
256 | TaskHandle_t Task1;
257 | SemaphoreHandle_t newFrame;
258 |
259 | esp_err_t result;
260 |
261 | unsigned char __Temp_wav[] = {
262 | 0x00, 0x00
263 | };
264 |
265 |
266 | unsigned int sampleCNT = 0;
267 |
268 | void IRAM_ATTR onTimer()
269 | {
270 |
271 | portENTER_CRITICAL_ISR(&timerMux);
272 | sampling = true;
273 | portEXIT_CRITICAL_ISR(&timerMux);
274 |
275 | }
276 |
277 | class MyCallbacks: public BLECharacteristicCallbacks
278 | {
279 | void onWrite(BLECharacteristic *pCharacteristic)
280 | {
281 | std::string value = pCharacteristic->getValue();
282 |
283 | if (value.length() > 0)
284 | {
285 | LoopBack = LoopBack ? false : true;
286 | }
287 | }
288 | };
289 |
290 |
291 | void setup()
292 | {
293 |
294 | // initialize digital pin LED_BUILTIN as an output.
295 | pinMode(LED_BUILTIN_TTGO, OUTPUT);//it's green
296 | digitalWrite(LED_BUILTIN_TTGO, LOW);
297 |
298 | Serial.begin(115200);
299 |
300 | Serial.print("Initializing SD card...");
301 |
302 | // if (!SD.begin(32, 14, 12, 27)) {
303 | if (!SD.begin(13, 15, 2, 14)) { // for TTGO T8 hardware
304 | Serial.println("initialization failed!");
305 | return;
306 | }
307 |
308 | Serial.println("initialization done.");
309 | Serial.print("MOSI = "); Serial.println(MOSI);
310 | Serial.print("MISO = "); Serial.println(MISO);
311 | Serial.print("SCK = "); Serial.println(SCK);
312 | Serial.print("SS = "); Serial.println(SS);
313 |
314 |
315 | /* open specified wav file and process it */
316 | root = SD.open(SDcardFileName.c_str ());
317 | Serial.println(SDcardFileName.c_str ());
318 |
319 | if (root)
320 | { // we found the file, is it mono wave format?
321 | int c = 0;
322 | int n;
323 | wavRiff_t wavRiff;
324 | n = readRiff(root, &wavRiff);
325 | if (n == sizeof(wavRiff_t)) {
326 | if (wavRiff.chunkID == CCCC('R', 'I', 'F', 'F') && wavRiff.format == CCCC('W', 'A', 'V', 'E')) {
327 | Serial.println("HEADER_RIFF");
328 | }
329 | }
330 |
331 | n = readProps(root, &wavProps);
332 | if (n == sizeof(wavProperties_t)) {
333 | Serial.println("WAVE PROPERTIES");
334 | }
335 |
336 | uint32_t chunkId, chunkSize;
337 | n = read4bytes(root, &chunkId);
338 | if (n == 4) {
339 | if (chunkId == CCCC('d', 'a', 't', 'a'))
340 | {
341 | Serial.println("HEADER_DATA");
342 | }
343 | }
344 | //++++++++++++++++++++++++++++++++++++++++=
345 | // read the 4 bytes chunk size
346 | n = read4bytes(root, &chunkSize);
347 | if (n == 4) {
348 |
349 | Serial.println("chunkSize:");
350 | Serial.println(chunkSize);
351 | Serial.println("prepare data");
352 | wavPlaying = true;
353 | }
354 | //++++++++++++++++++++++++++++++++++++++++=
355 | /* after processing wav file, it is time to process audio data */
356 | }
357 | else
358 | {
359 | Serial.println("error opening wav file");
360 | wavPlaying = false;
361 | }
362 |
363 |
364 | //\||||||||||||||||||||||||||
365 | len = sizeof(x) / sizeof(float);
366 | fir_len = (sizeof(B) / sizeof(float)) - 1; //order v.s. length
367 | // initialize the coefficients with the Matlab designed values
368 | for (int i = 0 ; i < fir_len ; i++)
369 | {
370 | coeffs[i] = B[i];
371 | }
372 |
373 | // initialize the fir filter struct using library function
374 | dsps_fir_init_f32(&fir1, coeffs, history, fir_len);
375 | //\||||||||||||||||||||||||||
376 |
377 | Serial.println("initialization done.");
378 | delay(1000);
379 |
380 | newFrame = xSemaphoreCreateMutex();
381 |
382 | xTaskCreatePinnedToCore(
383 | frameProcessing,
384 | "FrameProcessing",
385 | 1000,
386 | NULL,
387 | 1,
388 | &Task1,
389 | 0);
390 |
391 | delay(500); // needed to start-up task1
392 | // from Mr. Spiess' video
393 |
394 | // zero the DAC buffers
395 | for (int i = 0; i < N; ++i)
396 | {
397 | outRealPing[i] = 0;
398 | outRealPong[i] = 0;
399 |
400 | }
401 |
402 | // this almost matches the output resolution
403 | // all channels GPIOs 32-39
404 | result = adc1_config_width(ADC_WIDTH_9Bit);
405 | // complete with Apple type error message
406 | if (result != ESP_OK)
407 | {
408 | Serial.println("Error, an unknown error occurred");
409 | }
410 |
411 | // this might allow 3.3VDC on the mic
412 | // pin 34
413 | result = adc1_config_channel_atten( ADC1_CHANNEL_6, ADC_ATTEN_11db);
414 | if (result != ESP_OK)
415 | {
416 | Serial.println("Error, an unknown error occurred");
417 | }
418 |
419 | //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
420 | BLEDevice::init("DSP_FILTER");
421 | BLEServer *pServer = BLEDevice::createServer();
422 |
423 | BLEService *pService = pServer->createService(SERVICE_UUID);
424 |
425 | BLECharacteristic *pCharacteristic = pService->createCharacteristic(
426 | CHARACTERISTIC_UUID,
427 | BLECharacteristic::PROPERTY_READ |
428 | BLECharacteristic::PROPERTY_WRITE
429 | );
430 |
431 | pCharacteristic->setCallbacks(new MyCallbacks());
432 |
433 | pCharacteristic->setValue("Hello World");
434 | pService->start();
435 |
436 | BLEAdvertising *pAdvertising = pServer->getAdvertising();
437 | pAdvertising->start();
438 | //|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
439 |
440 | Serial.print("Arduino Loop(): Executing on core ");
441 | Serial.println(xPortGetCoreID());
442 |
443 | //Sart the Sample Clock
444 | hw_timer_t* timer = timerBegin(0, 80, true);
445 | timerAttachInterrupt(timer, &onTimer, true);
446 | timerAlarmWrite(timer, 125, true); // sampling frequency 8kHz
447 | timerAlarmEnable(timer);
448 |
449 | }
450 |
451 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
452 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
453 | // This Task runs on Core: 1
454 | // Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1Core1
455 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
456 |
457 | // ||||||||||||||||||
458 | // Sample Service
459 | // ||||||||||||||||||
460 | void loop()
461 | {
462 | for (int i = 0; i < N; ++i)
463 | {
464 | while (!sampling);
465 |
466 | portENTER_CRITICAL(&timerMux);
467 | sampling = false;
468 | portEXIT_CRITICAL(&timerMux);
469 |
470 | if (pingCore1 == true)
471 | {
472 | // configured for 9 bits with an 11 dB pad
473 | // drop one bit to give 8 to match the output
474 | realPing[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
475 | imagPing[i] = 0.0;
476 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
477 | // for VDD_A 3.3V, to 2.59V
478 | if (outputEnable == true)
479 | { // GPIO pin 25 of the ESP32.
480 | // This is the output of DAC1
481 | //dacWrite(25, outRealPing[i]);
482 | // DAC1 on the TTGO T8 is 26
483 | dacWrite(26, outRealPing[i]);
484 | }
485 | }
486 | else
487 | {
488 | // drop one bit to give 8 to match the output
489 | realPong[i] = (float) (((byte)((adc1_get_voltage(ADC1_CHANNEL_6) >> 1) & 0xFF)) - 128.0);
490 | imagPong[i] = 0.0;
491 | // DAC output is 8-bit unsigned. Maximum (255) corresponds
492 | // for VDD_A 3.3V, to 2.59V
493 | if (outputEnable == true)
494 | { // for VDD_A 3.3V, to 2.59V
495 | //dacWrite(25, outRealPong[i]);
496 | // DAC1 on the TTGO T8
497 | dacWrite(26, outRealPong[i]);
498 | }
499 | } // end single sample processing
500 | //digitalWrite(LED_BUILTIN_TTGO, LOW);
501 | } // end N samples processing
502 |
503 | // swap working buffer
504 | pingCore1 = !pingCore1;
505 | // give the old buffer to frame processing
506 | xSemaphoreGive(newFrame);
507 | } // end sample service task
508 |
509 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
510 | // 1111111111111111111111111111111111111111111111111111111111111
511 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
512 |
513 |
514 |
515 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
516 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
517 | // This Task runs on Core: 0
518 | // Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0Core0
519 | // |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
520 | // Frame processing
521 | // Runs every N samples
522 |
523 | void frameProcessing( void* parameter )
524 | {
525 | int n;
526 | uint8_t data;
527 |
528 | Serial.print("Frame Processing: Executing on core ");
529 | Serial.println(xPortGetCoreID());
530 |
531 | for (;;) // this is required, normally put in by
532 | { // Arduino IDE
533 |
534 | int16_t outVal;
535 | float outValf;
536 | uint16_t sample;
537 |
538 | //startTEST = xthal_get_ccount();
539 | volume = 2.0;
540 | outputEnable = true;
541 |
542 | // "Arf! Arf!"
543 | // pet the watchdog.
544 | vTaskDelay(10);
545 |
546 | // wait for the ping-pong buffer swap
547 | // indicating frame processing should begin
548 | // Core 1 has the timer resolution and is in charge of buffers
549 | // We are Core 0
550 | xSemaphoreTake(newFrame, portMAX_DELAY);
551 |
552 | // start "wav playing" LED
553 | digitalWrite(LED_BUILTIN_TTGO, HIGH);
554 |
555 | //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\
556 | //||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||\
557 |
558 | int tempi;
559 |
560 | // copy/format PCM data from SD Card to filter input array
561 | // this simulates reading a buffered ADC in real time
562 | for (int i = 0; i < N; ++i) // read a frame of input signal
563 | {
564 |
565 | if (root.available())
566 | { // some kind of byte swapped Intel Hex format
567 | tempi = readbyte(root, &data);
568 | __Temp_wav[0] = data;
569 |
570 | tempi = readbyte(root, &data);
571 | __Temp_wav[1] = data;
572 |
573 | outVal = (int16_t) ((__Temp_wav[0]) | (__Temp_wav[1] << 8));
574 | x[i] = ((float)outVal * 0.000015259) * volume;
575 | }
576 | else
577 | {
578 | root.close();
579 | wavPlaying = false;
580 | // stop "wav playing" LED
581 | digitalWrite(LED_BUILTIN_TTGO, LOW);
582 | }
583 | }// end frame processing of N samples
584 |
585 | // finished reading a frame of input samples
586 |
587 | // run the filter at the frame, update history
588 | if (LoopBack == false)
589 | { // no loopback. run the filter
590 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
591 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
592 | dsps_fir_f32_ansi(&fir1, x, y, len);
593 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
594 | //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
595 | }
596 | else
597 | {
598 | // loopback test
599 | // LoopBack variable controlled over BLE
600 | for (int i = 0; i < N; ++i) // copy input direct to output
601 | { // skip the filter
602 | y[i] = x[i];
603 | }
604 | }
605 | //||||||||||||||||||||||||||||||||||
606 | // Output to DAC
607 | // output a frame of filtered samples
608 | for (int i = 0; i < N; ++i)
609 | {
610 | // NOTE:
611 | // this variable belongs to core 1 -- use the other buffer
612 | // If core 1 is ping, we are pong
613 | if (pingCore1 == true)
614 | { // PING time
615 | //convert to DAC format
616 | if (wavPlaying == true)
617 | {
618 | outRealPong[i] = (unsigned char) ((y[i] * 127.0) + 128.0);
619 | }
620 | else
621 | { // not playing wav, output a zero
622 | outRealPong[i] = (unsigned char) 0;
623 | }
624 | }
625 | else
626 | { // PONG time
627 | //convert to DAC format
628 | if (wavPlaying == true)
629 | {
630 | outRealPing[i] = (unsigned char) ((y[i] * 127.0) + 128.0);
631 | }
632 | else
633 | { // not playing wav, output a zero
634 | outRealPing[i] = (unsigned char) 0;
635 | }
636 | }
637 |
638 | }// end frame processing of N samples
639 |
640 | // this processing takes x msec.
641 | // out of 128 msec. available to the Frame
642 | // 125 usec * 1024 = 128 msec.
643 | // y% loaded
644 | //
645 | //endTEST = xthal_get_ccount();
646 | //totalTEST = endTEST - startTEST;
647 | //ESP_LOGI(TAG, "dsps_fir_f32_ansi - %f per sample for for %i coefficients,
648 | //%f per tap \n", cycles, fir_len, cycles / (float)fir_len);
649 |
650 |
651 | // end of frame processing
652 | } // end Arduino task loop
653 | }
654 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
655 | // 0000000000000000000000000000000000000000000000000000000000000
656 | // /\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
657 |
--------------------------------------------------------------------------------
/ESP_DSP/ESP32FIR/tmwtypes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 1984-2016 The MathWorks, Inc.
3 | * All Rights Reserved.
4 | */
5 |
6 | #if defined(_MSC_VER)
7 | # pragma once
8 | #endif
9 | #if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 3))
10 | # pragma once
11 | #endif
12 |
13 | #ifndef tmwtypes_h
14 | #define tmwtypes_h
15 |
16 | #ifndef __TMWTYPES__
17 | #define __TMWTYPES__
18 | /*
19 | * File : tmwtypes.h
20 | * Abstract:
21 | * Data types for use with MATLAB/SIMULINK and the Real-Time Workshop.
22 | *
23 | * When compiling stand-alone model code, data types can be overridden
24 | * via compiler switches.
25 | *
26 | * Define NO_FLOATS to eliminate reference to real_T, etc.
27 | */
28 |
29 | #include
30 |
31 | #ifdef __APPLE_CC__
32 | #include
33 | #endif
34 |
35 | #define LOGICAL_IS_A_TYPE
36 | #define SPARSE_GENERALIZATION
37 |
38 | #ifdef NO_FLOATS
39 | # define double double_not_allowed
40 | # define float float_not_allowed
41 | #endif /*NO_FLOATS*/
42 |
43 | #ifndef NO_FLOATS
44 |
45 | #ifndef __MWERKS__
46 | # ifdef __STDC__
47 | # include
48 | # else
49 | # define FLT_MANT_DIG 24
50 | # define DBL_MANT_DIG 53
51 | # endif
52 | #endif
53 |
54 | #endif /*NO_FLOATS*/
55 |
56 | /*
57 | * The following data types cannot be overridden when building MEX files.
58 | */
59 | #ifdef MATLAB_MEX_FILE
60 | # undef CHARACTER_T
61 | # undef INTEGER_T
62 | # undef BOOLEAN_T
63 | # undef REAL_T
64 | # undef TIME_T
65 | #endif
66 |
67 | /*
68 | * The uchar_T, ushort_T and ulong_T types are needed for compilers which do
69 | * not allow defines to be specified, at the command line, with spaces in them.
70 | */
71 |
72 | typedef unsigned char uchar_T;
73 | typedef unsigned short ushort_T;
74 | typedef unsigned long ulong_T;
75 |
76 | #if (defined(_MSC_VER) && _MSC_VER >= 1500) \
77 | || defined(__x86_64__) || defined(__LP64__) \
78 | || defined(__LCC64__)
79 |
80 | typedef unsigned long long ulonglong_T;
81 | #endif
82 |
83 |
84 |
85 | /*=======================================================================*
86 | * Fixed width word size data types: *
87 | * int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
88 | * uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
89 | * real32_T, real64_T - 32 and 64 bit floating point numbers *
90 | *=======================================================================*/
91 |
92 | /* When used with Real Time Workshop generated code, this
93 | * header file can be used with a variety of compilers.
94 | *
95 | * The compiler could be for an 8 bit embedded processor that
96 | * only had 8 bits per integer and 16 bits per long.
97 | * In that example, a 32 bit integer size is not even available.
98 | * This header file should be robust to that.
99 | *
100 | * For the case of an 8 bit processor, the preprocessor
101 | * may be limited to 16 bit math like its target. That limitation
102 | * would mean that 32 bit comparisons can't be done accurately.
103 | * To increase robustness to this, comparisons are done against
104 | * smaller values first. An inaccurate 32 bit comparison isn't
105 | * attempted if the 16 bit comparison has already succeeded.
106 | *
107 | * Limitations on preprocessor math can also be stricter than
108 | * for the target. There are known cases where a compiler
109 | * targeting processors with 64 bit longs can't do accurate
110 | * preprocessor comparisons on more than 32 bits.
111 | */
112 |
113 | /* Determine the number of bits for int, long, short, and char.
114 | * If one fails to be determined, set the number of bits to -1
115 | */
116 |
117 | #ifndef TMW_BITS_PER_INT
118 | # if INT_MAX == 0x7FL
119 | # define TMW_BITS_PER_INT 8
120 | # elif INT_MAX == 0x7FFFL
121 | # define TMW_BITS_PER_INT 16
122 | # elif INT_MAX == 0x7FFFFFFFL
123 | # define TMW_BITS_PER_INT 32
124 | # else
125 | # define TMW_BITS_PER_INT -1
126 | # endif
127 | #endif
128 |
129 | #ifndef TMW_BITS_PER_LONG
130 | # if LONG_MAX == 0x7FL
131 | # define TMW_BITS_PER_LONG 8
132 | # elif LONG_MAX == 0x7FFFL
133 | # define TMW_BITS_PER_LONG 16
134 | # elif LONG_MAX == 0x7FFFFFFFL
135 | # define TMW_BITS_PER_LONG 32
136 | # else
137 | # define TMW_BITS_PER_LONG -1
138 | # endif
139 | #endif
140 |
141 | #ifndef TMW_BITS_PER_SHRT
142 | # if SHRT_MAX == 0x7FL
143 | # define TMW_BITS_PER_SHRT 8
144 | # elif SHRT_MAX == 0x7FFFL
145 | # define TMW_BITS_PER_SHRT 16
146 | # elif SHRT_MAX == 0x7FFFFFFFL
147 | # define TMW_BITS_PER_SHRT 32
148 | # else
149 | # define TMW_BITS_PER_SHRT -1
150 | # endif
151 | #endif
152 |
153 | #ifndef TMW_BITS_PER_SCHAR
154 | # if SCHAR_MAX == 0x7FL
155 | # define TMW_BITS_PER_SCHAR 8
156 | # elif SCHAR_MAX == 0x7FFFL
157 | # define TMW_BITS_PER_SCHAR 16
158 | # elif SCHAR_MAX == 0x7FFFFFFFL
159 | # define TMW_BITS_PER_SCHAR 32
160 | # else
161 | # define TMW_BITS_PER_SCHAR -1
162 | # endif
163 | #endif
164 |
165 | #ifndef TMW_CHAR_SIGNED
166 | # if SCHAR_MAX == CHAR_MAX
167 | # define TMW_CHAR_SIGNED 1
168 | # else
169 | # define TMW_CHAR_SIGNED 0
170 | # endif
171 | #endif
172 |
173 | /* It is common for one or more of the integer types
174 | * to be the same size. For example, on many embedded
175 | * processors, both shorts and ints are 16 bits. On
176 | * processors used for workstations, it is quite common
177 | * for both int and long to be 32 bits.
178 | * When there is more than one choice for typdef'ing
179 | * a portable type like int16_T or uint32_T, in
180 | * concept, it should not matter which choice is made.
181 | * However, some style guides and some code checking
182 | * tools do identify and complain about seemingly
183 | * irrelevant differences. For example, a code
184 | * checking tool may complain about an implicit
185 | * conversion from int to short even though both
186 | * are 16 bits. To reduce these types of
187 | * complaints, it is best to make int the
188 | * preferred choice when more than one is available.
189 | */
190 |
191 | #ifndef INT8_T
192 | # if TMW_BITS_PER_INT == 8
193 | # define INT8_T int
194 | # elif TMW_BITS_PER_LONG == 8
195 | # define INT8_T long
196 | # elif TMW_BITS_PER_SCHAR == 8
197 | # define INT8_T signed char
198 | # elif TMW_BITS_PER_SHRT == 8
199 | # define INT8_T short
200 | # endif
201 | #endif
202 | #ifdef INT8_T
203 | typedef INT8_T int8_T;
204 | #endif
205 |
206 | #ifndef UINT8_T
207 | # if TMW_BITS_PER_INT == 8
208 | # define UINT8_T unsigned int
209 | # elif TMW_BITS_PER_LONG == 8
210 | # define UINT8_T unsigned long
211 | # elif TMW_BITS_PER_SCHAR == 8
212 | # define UINT8_T unsigned char
213 | # elif TMW_BITS_PER_SHRT == 8
214 | # define UINT8_T unsigned short
215 | # endif
216 | #endif
217 | #ifdef UINT8_T
218 | typedef UINT8_T uint8_T;
219 | #endif
220 |
221 |
222 | #ifndef INT16_T
223 | # if TMW_BITS_PER_INT == 16
224 | # define INT16_T int
225 | # elif TMW_BITS_PER_LONG == 16
226 | # define INT16_T long
227 | # elif TMW_BITS_PER_SCHAR == 16
228 | # define INT16_T signed char
229 | # elif TMW_BITS_PER_SHRT == 16
230 | # define INT16_T short
231 | # endif
232 | #endif
233 | #ifdef INT16_T
234 | typedef INT16_T int16_T;
235 | #endif
236 |
237 |
238 | #ifndef UINT16_T
239 | # if TMW_BITS_PER_INT == 16
240 | # define UINT16_T unsigned int
241 | # elif TMW_BITS_PER_LONG == 16
242 | # define UINT16_T unsigned long
243 | # elif TMW_BITS_PER_SCHAR == 16
244 | # define UINT16_T unsigned char
245 | # elif TMW_BITS_PER_SHRT == 16
246 | # define UINT16_T unsigned short
247 | # endif
248 | #endif
249 | #ifdef UINT16_T
250 | typedef UINT16_T uint16_T;
251 | #endif
252 |
253 |
254 | #ifndef INT32_T
255 | # if TMW_BITS_PER_INT == 32
256 | # define INT32_T int
257 | # elif TMW_BITS_PER_LONG == 32
258 | # define INT32_T long
259 | # elif TMW_BITS_PER_SCHAR == 32
260 | # define INT32_T signed char
261 | # elif TMW_BITS_PER_SHRT == 32
262 | # define INT32_T short
263 | # endif
264 | #endif
265 | #ifdef INT32_T
266 | typedef INT32_T int32_T;
267 | #endif
268 |
269 |
270 | #ifndef UINT32_T
271 | # if TMW_BITS_PER_INT == 32
272 | # define UINT32_T unsigned int
273 | # elif TMW_BITS_PER_LONG == 32
274 | # define UINT32_T unsigned long
275 | # elif TMW_BITS_PER_SCHAR == 32
276 | # define UINT32_T unsigned char
277 | # elif TMW_BITS_PER_SHRT == 32
278 | # define UINT32_T unsigned short
279 | # endif
280 | #endif
281 | #ifdef UINT32_T
282 | typedef UINT32_T uint32_T;
283 | #endif
284 |
285 | /* The following is used to emulate smaller integer types when only
286 | * larger types are available. For example, compilers for TI C3x/C4x DSPs
287 | * define char and short to be 32 bits, so 8 and 16 bits are not directly
288 | * available. This target is commonly used with RTW rapid prototyping.
289 | * Other DSPs define char to be 16 bits, so 8 bits is not directly
290 | * available.
291 | */
292 | #ifndef INT8_T
293 | # ifdef INT16_T
294 | # define INT8_T INT16_T
295 | typedef INT8_T int8_T;
296 | # else
297 | # ifdef INT32_T
298 | # define INT8_T INT32_T
299 | typedef INT8_T int8_T;
300 | # endif
301 | # endif
302 | #endif
303 |
304 | #ifndef UINT8_T
305 | # ifdef UINT16_T
306 | # define UINT8_T UINT16_T
307 | typedef UINT8_T uint8_T;
308 | # else
309 | # ifdef UINT32_T
310 | # define UINT8_T UINT32_T
311 | typedef UINT8_T uint8_T;
312 | # endif
313 | # endif
314 | #endif
315 |
316 | #ifndef INT16_T
317 | # ifdef INT32_T
318 | # define INT16_T INT32_T
319 | typedef INT16_T int16_T;
320 | # endif
321 | #endif
322 |
323 | #ifndef UINT16_T
324 | # ifdef UINT32_T
325 | # define UINT16_T UINT32_T
326 | typedef UINT16_T uint16_T;
327 | # endif
328 | #endif
329 |
330 |
331 | #ifndef NO_FLOATS
332 |
333 | #ifndef REAL32_T
334 | # ifndef __MWERKS__
335 | # if FLT_MANT_DIG >= 23
336 | # define REAL32_T float
337 | # endif
338 | # else
339 | # define REAL32_T float
340 | # endif
341 | #endif
342 | #ifdef REAL32_T
343 | typedef REAL32_T real32_T;
344 | #endif
345 |
346 |
347 | #ifndef REAL64_T
348 | # ifndef __MWERKS__
349 | # if DBL_MANT_DIG >= 52
350 | # define REAL64_T double
351 | # endif
352 | # else
353 | # define REAL64_T double
354 | # endif
355 | #endif
356 | #ifdef REAL64_T
357 | typedef REAL64_T real64_T;
358 | #endif
359 |
360 | #endif /* NO_FLOATS*/
361 |
362 | /*=======================================================================*
363 | * Fixed width word size data types: *
364 | * int64_T - signed 64 bit integers *
365 | * uint64_T - unsigned 64 bit integers *
366 | *=======================================================================*/
367 |
368 |
369 |
370 | #ifndef INT64_T
371 | # if defined(__APPLE__)
372 | # define INT64_T long long
373 | # define FMT64 "ll"
374 | # if defined(__LP64__) && !defined(INT_TYPE_64_IS_LONG)
375 | # define INT_TYPE_64_IS_LONG
376 | # endif
377 | # elif (defined(__x86_64__) || defined(__LP64__))&& !defined(__MINGW64__)
378 | # define INT64_T long
379 | # define FMT64 "l"
380 | # if !defined(INT_TYPE_64_IS_LONG)
381 | # define INT_TYPE_64_IS_LONG
382 | # endif
383 | # elif defined(_MSC_VER) || (defined(__BORLANDC__) && __BORLANDC__ >= 0x530) \
384 | || (defined(__WATCOMC__) && __WATCOMC__ >= 1100)
385 | # define INT64_T __int64
386 | # define FMT64 "I64"
387 | # elif defined(__GNUC__) || defined(TMW_ENABLE_INT64) \
388 | || defined(__LCC64__)
389 | # define INT64_T long long
390 | # define FMT64 "ll"
391 | # endif
392 | #endif
393 |
394 |
395 |
396 | #if defined(INT64_T)
397 | # if defined(__GNUC__) && \
398 | ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >=9)))
399 | __extension__
400 | # endif
401 | typedef INT64_T int64_T;
402 | #endif
403 |
404 |
405 |
406 | #ifndef UINT64_T
407 | # if defined(__APPLE__)
408 | # define UINT64_T unsigned long long
409 | # define FMT64 "ll"
410 | # if defined(__LP64__) && !defined(INT_TYPE_64_IS_LONG)
411 | # define INT_TYPE_64_IS_LONG
412 | # endif
413 | # elif (defined(__x86_64__) || defined(__LP64__))&& !defined(__MINGW64__)
414 | # define UINT64_T unsigned long
415 | # define FMT64 "l"
416 | # if !defined(INT_TYPE_64_IS_LONG)
417 | # define INT_TYPE_64_IS_LONG
418 | # endif
419 | # elif defined(_MSC_VER) || (defined(__BORLANDC__) && __BORLANDC__ >= 0x530) \
420 | || (defined(__WATCOMC__) && __WATCOMC__ >= 1100)
421 | # define UINT64_T unsigned __int64
422 | # define FMT64 "I64"
423 | # elif defined(__GNUC__) || defined(TMW_ENABLE_INT64) \
424 | || defined(__LCC64__)
425 | # define UINT64_T unsigned long long
426 | # define FMT64 "ll"
427 | # endif
428 | #endif
429 |
430 | #if defined(_WIN64) || (defined(__APPLE__) && defined(__LP64__)) \
431 | || defined(__x86_64__) \
432 | || defined(__LP64__)
433 | # define INT_TYPE_64_IS_SUPPORTED
434 | #endif
435 |
436 | #if defined(UINT64_T)
437 | # if defined(__GNUC__) && \
438 | ((__GNUC__ > 2) || ((__GNUC__ == 2) && (__GNUC_MINOR__ >=9)))
439 | __extension__
440 | # endif
441 | typedef UINT64_T uint64_T;
442 | #endif
443 |
444 | /*===========================================================================*
445 | * Format string modifiers for using size_t variables in printf statements. *
446 | *===========================================================================*/
447 |
448 | #ifndef FMT_SIZE_T
449 | # if (defined( __GNUC__ ) || defined(_STDC_C99))&& !defined(__MINGW64__)
450 | # define FMT_SIZE_T "z"
451 | # elif defined (__WATCOMC__)
452 | # define FMT_SIZE_T "l"
453 | # elif defined (_WIN32 )
454 | # define FMT_SIZE_T "I"
455 | # else
456 | # define FMT_SIZE_T "l"
457 | # endif
458 | #endif
459 |
460 | #ifndef FMT_PTRDIFF_T
461 | # if defined(__APPLE__)
462 | # define FMT_PTRDIFF_T "l"
463 | # elif defined( __GNUC__ ) || defined(_STDC_C99)
464 | # define FMT_PTRDIFF_T "t"
465 | # elif defined (__WATCOMC__)
466 | # define FMT_PTRDIFF_T "l"
467 | # elif defined (_WIN32 )
468 | # define FMT_PTRDIFF_T "I"
469 | # else
470 | # define FMT_PTRDIFF_T "l"
471 | # endif
472 | #endif
473 |
474 | /*===========================================================================*
475 | * General or logical data types where the word size is not guaranteed. *
476 | * real_T - possible settings include real32_T or real64_T *
477 | * time_T - possible settings include real32_T or real64_T *
478 | * boolean_T *
479 | * char_T *
480 | * int_T *
481 | * uint_T *
482 | * byte_T *
483 | *===========================================================================*/
484 |
485 | #ifndef NO_FLOATS
486 |
487 | #ifndef REAL_T
488 | # ifdef REAL64_T
489 | # define REAL_T real64_T
490 | # else
491 | # ifdef REAL32_T
492 | # define REAL_T real32_T
493 | # endif
494 | # endif
495 | #endif
496 | #ifdef REAL_T
497 | typedef REAL_T real_T;
498 | #endif
499 |
500 | #ifndef TIME_T
501 | # ifdef REAL_T
502 | # define TIME_T real_T
503 | # endif
504 | #endif
505 | #ifdef TIME_T
506 | typedef TIME_T time_T;
507 | #endif
508 |
509 | #endif /* NO_FLOATS */
510 |
511 | #ifndef BOOLEAN_T
512 | # if defined(UINT8_T)
513 | # define BOOLEAN_T UINT8_T
514 | # else
515 | # define BOOLEAN_T unsigned int
516 | # endif
517 | #endif
518 | typedef BOOLEAN_T boolean_T;
519 |
520 |
521 | #ifndef CHARACTER_T
522 | # define CHARACTER_T char
523 | #endif
524 | typedef CHARACTER_T char_T;
525 |
526 |
527 | #ifndef INTEGER_T
528 | # define INTEGER_T int
529 | #endif
530 | typedef INTEGER_T int_T;
531 |
532 |
533 | #ifndef UINTEGER_T
534 | # define UINTEGER_T unsigned
535 | #endif
536 | typedef UINTEGER_T uint_T;
537 |
538 |
539 | #ifndef BYTE_T
540 | # define BYTE_T unsigned char
541 | #endif
542 | typedef BYTE_T byte_T;
543 |
544 |
545 | /*===========================================================================*
546 | * Define Complex Structures *
547 | *===========================================================================*/
548 | #ifndef NO_FLOATS
549 |
550 | #ifndef CREAL32_T
551 | # ifdef REAL32_T
552 | typedef struct {
553 | real32_T re, im;
554 | } creal32_T;
555 | # define CREAL32_T creal32_T
556 | # endif
557 | #endif
558 |
559 | #ifndef CREAL64_T
560 | # ifdef REAL64_T
561 | typedef struct {
562 | real64_T re, im;
563 | } creal64_T;
564 | # define CREAL64_T creal64_T
565 | # endif
566 | #endif
567 |
568 | #ifndef CREAL_T
569 | # ifdef REAL_T
570 | typedef struct {
571 | real_T re, im;
572 | } creal_T;
573 | # define CREAL_T creal_T
574 | # endif
575 | #endif
576 |
577 | #endif /* NO_FLOATS */
578 |
579 | #ifndef CINT8_T
580 | # ifdef INT8_T
581 | typedef struct {
582 | int8_T re, im;
583 | } cint8_T;
584 | # define CINT8_T cint8_T
585 | # endif
586 | #endif
587 |
588 | #ifndef CUINT8_T
589 | # ifdef UINT8_T
590 | typedef struct {
591 | uint8_T re, im;
592 | } cuint8_T;
593 | # define CUINT8_T cuint8_T
594 | # endif
595 | #endif
596 |
597 | #ifndef CINT16_T
598 | # ifdef INT16_T
599 | typedef struct {
600 | int16_T re, im;
601 | } cint16_T;
602 | # define CINT16_T cint16_T
603 | # endif
604 | #endif
605 |
606 | #ifndef CUINT16_T
607 | # ifdef UINT16_T
608 | typedef struct {
609 | uint16_T re, im;
610 | } cuint16_T;
611 | # define CUINT16_T cuint16_T
612 | # endif
613 | #endif
614 |
615 | #ifndef CINT32_T
616 | # ifdef INT32_T
617 | typedef struct {
618 | int32_T re, im;
619 | } cint32_T;
620 | # define CINT32_T cint32_T
621 | # endif
622 | #endif
623 |
624 | #ifndef CUINT32_T
625 | # ifdef UINT32_T
626 | typedef struct {
627 | uint32_T re, im;
628 | } cuint32_T;
629 | # define CUINT32_T cuint32_T
630 | # endif
631 | #endif
632 |
633 | #ifndef CINT64_T
634 | # ifdef INT64_T
635 | typedef struct {
636 | int64_T re, im;
637 | } cint64_T;
638 | # define CINT64_T cint64_T
639 | # endif
640 | #endif
641 |
642 | #ifndef CUINT64_T
643 | # ifdef UINT64_T
644 | typedef struct {
645 | uint64_T re, im;
646 | } cuint64_T;
647 | # define CUINT64_T cuint64_T
648 | # endif
649 | #endif
650 |
651 | /*=======================================================================*
652 | * Min and Max: *
653 | * int8_T, int16_T, int32_T - signed 8, 16, or 32 bit integers *
654 | * uint8_T, uint16_T, uint32_T - unsigned 8, 16, or 32 bit integers *
655 | *=======================================================================*/
656 |
657 | #define MAX_int8_T ((int8_T)(127)) /* 127 */
658 | #define MIN_int8_T ((int8_T)(-128)) /* -128 */
659 | #define MAX_uint8_T ((uint8_T)(255)) /* 255 */
660 | #define MIN_uint8_T ((uint8_T)(0))
661 |
662 | #define MAX_int16_T ((int16_T)(32767)) /* 32767 */
663 | #define MIN_int16_T ((int16_T)(-32768)) /* -32768 */
664 | #define MAX_uint16_T ((uint16_T)(65535)) /* 65535 */
665 | #define MIN_uint16_T ((uint16_T)(0))
666 |
667 | #define MAX_int32_T ((int32_T)(2147483647)) /* 2147483647 */
668 | #define MIN_int32_T ((int32_T)(-2147483647-1)) /* -2147483648 */
669 | #define MAX_uint32_T ((uint32_T)(0xFFFFFFFFU)) /* 4294967295 */
670 | #define MIN_uint32_T ((uint32_T)(0))
671 |
672 | #if defined(_MSC_VER) || (defined(__BORLANDC__) && __BORLANDC__ >= 0x530) \
673 | || (defined(__WATCOMC__) && __WATCOMC__ >= 1100) \
674 | || defined(__LCC64__)
675 | # ifdef INT64_T
676 | # define MAX_int64_T ((int64_T)(9223372036854775807LL))
677 | # define MIN_int64_T ((int64_T)(-9223372036854775807LL-1LL))
678 | # endif
679 | # ifdef UINT64_T
680 | # define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFULL))
681 | # define MIN_uint64_T ((uint64_T)(0))
682 | # endif
683 | #else
684 | # ifdef INT64_T
685 | # ifdef INT_TYPE_64_IS_LONG
686 | # define MAX_int64_T ((int64_T)(9223372036854775807L))
687 | # define MIN_int64_T ((int64_T)(-9223372036854775807L-1L))
688 | # else
689 | # define MAX_int64_T ((int64_T)(9223372036854775807LL))
690 | # define MIN_int64_T ((int64_T)(-9223372036854775807LL-1LL))
691 | # endif
692 | # endif
693 | # ifdef UINT64_T
694 | # ifdef INT_TYPE_64_IS_LONG
695 | # define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFUL))
696 | # define MIN_uint64_T ((uint64_T)(0))
697 | # else
698 | # define MAX_uint64_T ((uint64_T)(0xFFFFFFFFFFFFFFFFULL))
699 | # define MIN_uint64_T ((uint64_T)(0))
700 | # endif
701 | # endif
702 | #endif
703 |
704 | #ifdef _MSC_VER
705 | /* Conversion from unsigned __int64 to double is not implemented in windows
706 | * and results in a compile error, thus the value must first be cast to
707 | * signed __int64, and then to double.
708 | *
709 | * If the 64 bit int value is greater than 2^63-1, which is the signed int64 max,
710 | * the macro below provides a workaround for casting a uint64 value to a double
711 | * in windows.
712 | */
713 | # define uint64_to_double(u) ( ((u) > _I64_MAX) ? \
714 | (double)(__int64)((u) - _I64_MAX - 1) + (double)_I64_MAX + 1: \
715 | (double)(__int64)(u) )
716 |
717 | /* The following inline function should only be used in the macro double_to_uint64,
718 | * as it only handles the specfic range of double between 2^63 and 2^64-1 */
719 | __forceinline
720 | uint64_T double_to_uint64_helper(double d) {
721 | union double_to_uint64_union_type {
722 | double dd;
723 | uint64_T i64;
724 | } di;
725 | di.dd = d;
726 | return (((di.i64 & 0x000fffffffffffff) | 0x0010000000000000) << 11);
727 | }
728 |
729 | /* The largest double value that can be cast to uint64 in windows is the
730 | * signed int64 max, which is 2^63-1. The macro below provides
731 | * a workaround for casting large double values to uint64 in windows.
732 | */
733 | /* The magic number 18446744073709551616.0 is 2^64 */
734 | /* The magic number 9223372036854775808.0 is 2^63 */
735 | # define double_to_uint64(d) ( ((d) >= 18446744073709551616.0) ? \
736 | 0xffffffffffffffffULL : \
737 | ((d) >= 0.0) ? \
738 | ((d) >= 9223372036854775808.0) ? \
739 | double_to_uint64_helper(d) : \
740 | (unsigned __int64)(d) : \
741 | 0ULL )
742 | #else
743 | # define uint64_to_double(u) ((double)(u))
744 | # if defined(__BORLANDC__) || defined(__WATCOMC__) || defined(__TICCSC__)
745 | /* double_to_uint64 defined only for MSVC and UNIX */
746 | # else
747 | # define double_to_uint64(d) ( ((d) >= 18446744073709551616.0) ? \
748 | (unsigned long long) 0xffffffffffffffffULL : \
749 | ((d) >= 0) ? (unsigned long long)(d) : (unsigned long long) 0 )
750 | # endif
751 | #endif
752 |
753 | #if !defined(__cplusplus) && !defined(__bool_true_false_are_defined)
754 |
755 | #ifndef _bool_T
756 | #define _bool_T
757 |
758 | typedef boolean_T bool;
759 |
760 | #ifndef false
761 | #define false (0)
762 | #endif
763 | #ifndef true
764 | #define true (1)
765 | #endif
766 |
767 | #endif /* _bool_T */
768 |
769 | #endif /* !__cplusplus */
770 |
771 | /*
772 | * This software assumes that the code is being compiled on a target using a
773 | * 2's complement representation for signed integer values.
774 | */
775 | #if ((SCHAR_MIN + 1) != -SCHAR_MAX)
776 | #error "This code must be compiled using a 2's complement representation for signed integer values"
777 | #endif
778 |
779 | /*
780 | * Maximum length of a MATLAB identifier (function/variable/model)
781 | * including the null-termination character.
782 | */
783 | #define TMW_NAME_LENGTH_MAX 64
784 |
785 | /*
786 | * Maximum values for indices and dimensions
787 | */
788 | #include
789 |
790 | #ifdef MX_COMPAT_32
791 | typedef int mwSize;
792 | typedef int mwIndex;
793 | typedef int mwSignedIndex;
794 | #else
795 | typedef size_t mwSize; /* unsigned pointer-width integer */
796 | typedef size_t mwIndex; /* unsigned pointer-width integer */
797 | typedef ptrdiff_t mwSignedIndex; /* a signed pointer-width integer */
798 | #endif
799 |
800 | #if (defined(_LP64) || defined(_WIN64)) && !defined(MX_COMPAT_32)
801 | /* Currently 2^48 based on hardware limitations */
802 | # define MWSIZE_MAX 281474976710655UL
803 | # define MWINDEX_MAX 281474976710655UL
804 | # define MWSINDEX_MAX 281474976710655L
805 | # define MWSINDEX_MIN -281474976710655L
806 | #else
807 | # define MWSIZE_MAX 2147483647UL
808 | # define MWINDEX_MAX 2147483647UL
809 | # define MWSINDEX_MAX 2147483647L
810 | # define MWSINDEX_MIN -2147483647L
811 | #endif
812 | #define MWSIZE_MIN 0UL
813 | #define MWINDEX_MIN 0UL
814 |
815 | /** UTF-16 character type */
816 |
817 | #if (defined(__cplusplus) && (__cplusplus >= 201103L)) || (defined(_HAS_CHAR16_T_LANGUAGE_SUPPORT) && _HAS_CHAR16_T_LANGUAGE_SUPPORT)
818 | typedef char16_t CHAR16_T;
819 | #define U16_STRING_LITERAL_PREFIX u
820 | #elif defined(_MSC_VER)
821 | typedef wchar_t CHAR16_T;
822 | #define U16_STRING_LITERAL_PREFIX L
823 | #else
824 | typedef UINT16_T CHAR16_T;
825 | #endif
826 |
827 | #endif /* __TMWTYPES__ */
828 |
829 | #endif /* tmwtypes_h */
830 |
--------------------------------------------------------------------------------