| @@ -62,7 +62,7 @@ AudioControlSGTL5000 audioShield; | |||
| struct fir_filter { | |||
| short *coeffs; | |||
| short num_coeffs; | |||
| short num_coeffs; // num_coeffs must be an even number, 4 or higher | |||
| }; | |||
| // index of current filter. Start with the low pass. | |||
| @@ -41,8 +41,11 @@ public: | |||
| coeff_p = cp; | |||
| // Initialize FIR instance (ARM DSP Math Library) | |||
| if (coeff_p && (coeff_p != FIR_PASSTHRU) && n_coeffs <= FIR_MAX_COEFFS) { | |||
| arm_fir_init_q15(&fir_inst, n_coeffs, (q15_t *)coeff_p, | |||
| &StateQ15[0], AUDIO_BLOCK_SAMPLES); | |||
| if (arm_fir_init_q15(&fir_inst, n_coeffs, (q15_t *)coeff_p, | |||
| &StateQ15[0], AUDIO_BLOCK_SAMPLES) != ARM_MATH_SUCCESS) { | |||
| // n_coeffs must be an even number, 4 or larger | |||
| coeff_p = NULL; | |||
| } | |||
| } | |||
| } | |||
| void end(void) { | |||
| @@ -468,6 +468,7 @@ span.mainfunction {color: #993300; font-weight: bolder} | |||
| <p>Receive 16 bit quad (4) channel audio from two | |||
| <a href="http://www.pjrc.com/store/teensy3_audio.html" target="_blank">audio shields</a> | |||
| or another I2S devices, using I2S master mode.</p> | |||
| <p align=center><img src="img/audioshield_quad_in.jpg"></p> | |||
| </div> | |||
| <h3>Audio Connections</h3> | |||
| <table class=doc align=center cellpadding=3> | |||
| @@ -665,6 +666,7 @@ span.mainfunction {color: #993300; font-weight: bolder} | |||
| <h3>Summary</h3> | |||
| <div class=tooltipinfo> | |||
| <p>Transmit quad (4) channel 16 bit audio, using I2S master mode.</p> | |||
| <p align=center><img src="img/audioshield_quad_out.jpg"></p> | |||
| </div> | |||
| <h3>Audio Connections</h3> | |||
| <table class=doc align=center cellpadding=3> | |||
| @@ -1909,7 +1911,7 @@ double s_freq = .0625;</p> | |||
| <h3>Functions</h3> | |||
| <p class=func><span class=keyword>delay</span>(channel, milliseconds);</p> | |||
| <p class=desc>Set output channel (0 to 7) to delay the signals by | |||
| milliseconds. The maximum delay is approx 333 ms. The actual delay | |||
| milliseconds. The maximum delay is approx 425 ms. The actual delay | |||
| is rounded to the nearest sample. Each channel can be configured for | |||
| any delay. There is no requirement to configure the "taps" in increasing | |||
| delay order. | |||
| @@ -1958,7 +1960,8 @@ double s_freq = .0625;</p> | |||
| <h3>Functions</h3> | |||
| <p class=func><span class=keyword>delay</span>(channel, milliseconds);</p> | |||
| <p class=desc>Set output channel (0 to 7) to delay the signals by | |||
| milliseconds. The maximum delay is approx 333 ms. The actual delay | |||
| milliseconds. The maximum delay is approx 1.5 seconds for each 23LC1024 chip. | |||
| The actual delay | |||
| is rounded to the nearest sample. Each channel can be configured for | |||
| any delay. There is no requirement to configure the "taps" in increasing | |||
| delay order. | |||
| @@ -2218,6 +2221,18 @@ double s_freq = .0625;</p> | |||
| <h3>Examples</h3> | |||
| <p class=exam>File > Examples > Audio > Effects > Filter_FIR | |||
| </p> | |||
| <h3>Known Issues</h3> | |||
| <p>Your filter's impulse response array must have an even length. If you have | |||
| add odd number of taps, you must add an extra zero to increase the length | |||
| to an even number. | |||
| </p> | |||
| <p>The minimum number of taps is 4. If you use less, add extra zeros to increase | |||
| the length to 4. | |||
| </p> | |||
| <p>The impulse response must be given in reverse order. Many filters have | |||
| symetrical impluse response, making this a non-issue. If your filter has | |||
| a non-symetrical response, make sure the data is in reverse time order. | |||
| </p> | |||
| <h3>Notes</h3> | |||
| <p>FIR filters requires more CPU time than Biquad (IIR), but they can | |||
| implement filters with better phase response. | |||
| @@ -2226,7 +2241,7 @@ double s_freq = .0625;</p> | |||
| supported filter length is 200 points. | |||
| </p> | |||
| <p>The free | |||
| <a href="http://t-filter.appspot.com/fir/index.html" target="_blank"> TFilter Design Tool</a> | |||
| <a href="http://t-filter.engineerjs.com/" target="_blank"> TFilter Design Tool</a> | |||
| can be used to create the impulse response array. Be sure to set the sampling | |||
| frequency to 44117 HZ (it defaults to only 2000 Hz) and the output type to "int" (16 bit). | |||
| </p> | |||
| @@ -36,7 +36,7 @@ uint16_t AudioInputI2SQuad::block_offset = 0; | |||
| bool AudioInputI2SQuad::update_responsibility = false; | |||
| DMAChannel AudioInputI2SQuad::dma(false); | |||
| #if defined(__MK20DX256__) | |||
| #if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||
| void AudioInputI2SQuad::begin(void) | |||
| { | |||
| @@ -1,28 +1,27 @@ | |||
| { | |||
| "name": "Audio", | |||
| "frameworks": "Arduino", | |||
| "platforms": "Teensy", | |||
| "keywords": "sound, audio, FFT, filter, effect", | |||
| "description": "Teensy Audio Library", | |||
| "url": "http://www.pjrc.com/teensy/td_libs_Audio.html", | |||
| "downloadUrl": "https://github.com/PaulStoffregen/Audio/archive/master.zip", | |||
| "version": "1.03", | |||
| "exclude": "extras", | |||
| "authors": | |||
| { | |||
| "name": "Paul Stoffregen", | |||
| "maintainer": true | |||
| }, | |||
| "repository": | |||
| { | |||
| "type": "git", | |||
| "url": "https://github.com/PaulStoffregen/Audio" | |||
| }, | |||
| "dependencies": | |||
| { | |||
| "name": "SerialFlash", | |||
| "frameworks": "arduino" | |||
| }, | |||
| "name": "Audio", | |||
| "frameworks": "Arduino", | |||
| "platforms": "Teensy", | |||
| "keywords": "sound, audio, FFT, filter, effect", | |||
| "description": "Teensy Audio Library", | |||
| "url": "http://www.pjrc.com/teensy/td_libs_Audio.html", | |||
| "version": "1.03", | |||
| "exclude": "extras", | |||
| "authors": | |||
| { | |||
| "name": "Paul Stoffregen", | |||
| "maintainer": true | |||
| }, | |||
| "repository": | |||
| { | |||
| "type": "git", | |||
| "url": "https://github.com/PaulStoffregen/Audio" | |||
| }, | |||
| "dependencies": | |||
| { | |||
| "name": "SerialFlash", | |||
| "frameworks": "arduino" | |||
| }, | |||
| "examples": [ | |||
| "examples/*/*.ino", | |||
| "examples/*/*/*.ino" | |||
| @@ -27,7 +27,7 @@ | |||
| * SOFTWARE. | |||
| */ | |||
| #if defined(__MK20DX128__) || defined(__MK20DX256__) | |||
| #if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||
| .cpu cortex-m4 | |||
| .syntax unified | |||
| @@ -27,7 +27,7 @@ | |||
| #include "output_dac.h" | |||
| #include "utility/pdb.h" | |||
| #if defined(__MK20DX256__) | |||
| #if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||
| DMAMEM static uint16_t dac_buffer[AUDIO_BLOCK_SAMPLES*2]; | |||
| audio_block_t * AudioOutputAnalog::block_left_1st = NULL; | |||
| @@ -267,6 +267,12 @@ void AudioOutputI2S::update(void) | |||
| #elif F_CPU == 168000000 | |||
| #define MCLK_MULT 8 | |||
| #define MCLK_DIV 119 | |||
| #elif F_CPU == 180000000 | |||
| #define MCLK_MULT 16 | |||
| #define MCLK_DIV 255 | |||
| #elif F_CPU == 192000000 | |||
| #define MCLK_MULT 1 | |||
| #define MCLK_DIV 17 | |||
| #elif F_CPU == 16000000 | |||
| #define MCLK_MULT 12 | |||
| #define MCLK_DIV 17 | |||
| @@ -292,6 +298,7 @@ void AudioOutputI2S::config_i2s(void) | |||
| // enable MCLK output | |||
| I2S0_MCR = I2S_MCR_MICS(MCLK_SRC) | I2S_MCR_MOE; | |||
| while (I2S0_MCR & I2S_MCR_DUF) ; | |||
| I2S0_MDR = I2S_MDR_FRACT((MCLK_MULT-1)) | I2S_MDR_DIVIDE((MCLK_DIV-1)); | |||
| // configure transmitter | |||
| @@ -27,7 +27,7 @@ | |||
| #include "output_i2s_quad.h" | |||
| #include "memcpy_audio.h" | |||
| #if defined(__MK20DX256__) | |||
| #if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||
| audio_block_t * AudioOutputI2SQuad::block_ch1_1st = NULL; | |||
| audio_block_t * AudioOutputI2SQuad::block_ch2_1st = NULL; | |||
| @@ -262,6 +262,12 @@ void AudioOutputI2SQuad::update(void) | |||
| #elif F_CPU == 168000000 | |||
| #define MCLK_MULT 8 | |||
| #define MCLK_DIV 119 | |||
| #elif F_CPU == 180000000 | |||
| #define MCLK_MULT 16 | |||
| #define MCLK_DIV 255 | |||
| #elif F_CPU == 192000000 | |||
| #define MCLK_MULT 1 | |||
| #define MCLK_DIV 17 | |||
| #elif F_CPU == 16000000 | |||
| #define MCLK_MULT 12 | |||
| #define MCLK_DIV 17 | |||
| @@ -287,6 +293,7 @@ void AudioOutputI2SQuad::config_i2s(void) | |||
| // enable MCLK output | |||
| I2S0_MCR = I2S_MCR_MICS(MCLK_SRC) | I2S_MCR_MOE; | |||
| while (I2S0_MCR & I2S_MCR_DUF) ; | |||
| I2S0_MDR = I2S_MDR_FRACT((MCLK_MULT-1)) | I2S_MDR_DIVIDE((MCLK_DIV-1)); | |||
| // configure transmitter | |||
| @@ -315,6 +315,12 @@ void AudioOutputSPDIF::update(void) | |||
| #elif F_CPU == 168000000 | |||
| #define MCLK_MULT 8 | |||
| #define MCLK_DIV 119 | |||
| #elif F_CPU == 180000000 | |||
| #define MCLK_MULT 16 | |||
| #define MCLK_DIV 255 | |||
| #elif F_CPU == 192000000 | |||
| #define MCLK_MULT 1 | |||
| #define MCLK_DIV 17 | |||
| #elif F_CPU == 16000000 | |||
| #define MCLK_MULT 12 | |||
| #define MCLK_DIV 17 | |||
| @@ -337,6 +343,7 @@ void AudioOutputSPDIF::config_SPDIF(void) | |||
| // enable MCLK output | |||
| I2S0_MCR = I2S_MCR_MICS(MCLK_SRC) | I2S_MCR_MOE; | |||
| while (I2S0_MCR & I2S_MCR_DUF) ; | |||
| I2S0_MDR = I2S_MDR_FRACT((MCLK_MULT-1)) | I2S_MDR_DIVIDE((MCLK_DIV-1)); | |||
| // configure transmitter | |||
| @@ -333,6 +333,23 @@ static inline int32_t substract_32_saturate(uint32_t a, uint32_t b) | |||
| return out; | |||
| } | |||
| //get Q from PSR | |||
| static inline uint32_t get_q_psr(void) __attribute__((always_inline, unused)); | |||
| static inline uint32_t get_q_psr(void) | |||
| { | |||
| uint32_t out; | |||
| asm volatile("mrs %0, APSR" : "=r" (out)); | |||
| return (out & 0x8000000)>>27; | |||
| } | |||
| //clear Q BIT in PSR | |||
| static inline void clr_q_psr(void) __attribute__((always_inline, unused)); | |||
| static inline void clr_q_psr(void) | |||
| { | |||
| uint32_t t; | |||
| asm volatile("mrs %0,APSR " : "=r" (t)); | |||
| asm volatile("bfc %0, #27, #1" : "=r" (t)); | |||
| asm volatile("msr APSR_nzcvq,%0" : "=r" (t)); | |||
| } | |||
| #endif | |||