struct fir_filter { | struct fir_filter { | ||||
short *coeffs; | 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. | // index of current filter. Start with the low pass. |
coeff_p = cp; | coeff_p = cp; | ||||
// Initialize FIR instance (ARM DSP Math Library) | // Initialize FIR instance (ARM DSP Math Library) | ||||
if (coeff_p && (coeff_p != FIR_PASSTHRU) && n_coeffs <= FIR_MAX_COEFFS) { | 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) { | void end(void) { |
<p>Receive 16 bit quad (4) channel audio from two | <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> | <a href="http://www.pjrc.com/store/teensy3_audio.html" target="_blank">audio shields</a> | ||||
or another I2S devices, using I2S master mode.</p> | or another I2S devices, using I2S master mode.</p> | ||||
<p align=center><img src="img/audioshield_quad_in.jpg"></p> | |||||
</div> | </div> | ||||
<h3>Audio Connections</h3> | <h3>Audio Connections</h3> | ||||
<table class=doc align=center cellpadding=3> | <table class=doc align=center cellpadding=3> | ||||
<h3>Summary</h3> | <h3>Summary</h3> | ||||
<div class=tooltipinfo> | <div class=tooltipinfo> | ||||
<p>Transmit quad (4) channel 16 bit audio, using I2S master mode.</p> | <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> | </div> | ||||
<h3>Audio Connections</h3> | <h3>Audio Connections</h3> | ||||
<table class=doc align=center cellpadding=3> | <table class=doc align=center cellpadding=3> | ||||
<h3>Functions</h3> | <h3>Functions</h3> | ||||
<p class=func><span class=keyword>delay</span>(channel, milliseconds);</p> | <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 | <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 | is rounded to the nearest sample. Each channel can be configured for | ||||
any delay. There is no requirement to configure the "taps" in increasing | any delay. There is no requirement to configure the "taps" in increasing | ||||
delay order. | delay order. | ||||
<h3>Functions</h3> | <h3>Functions</h3> | ||||
<p class=func><span class=keyword>delay</span>(channel, milliseconds);</p> | <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 | <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 | is rounded to the nearest sample. Each channel can be configured for | ||||
any delay. There is no requirement to configure the "taps" in increasing | any delay. There is no requirement to configure the "taps" in increasing | ||||
delay order. | delay order. | ||||
<h3>Examples</h3> | <h3>Examples</h3> | ||||
<p class=exam>File > Examples > Audio > Effects > Filter_FIR | <p class=exam>File > Examples > Audio > Effects > Filter_FIR | ||||
</p> | </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> | <h3>Notes</h3> | ||||
<p>FIR filters requires more CPU time than Biquad (IIR), but they can | <p>FIR filters requires more CPU time than Biquad (IIR), but they can | ||||
implement filters with better phase response. | implement filters with better phase response. | ||||
supported filter length is 200 points. | supported filter length is 200 points. | ||||
</p> | </p> | ||||
<p>The free | <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 | 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). | frequency to 44117 HZ (it defaults to only 2000 Hz) and the output type to "int" (16 bit). | ||||
</p> | </p> |
bool AudioInputI2SQuad::update_responsibility = false; | bool AudioInputI2SQuad::update_responsibility = false; | ||||
DMAChannel AudioInputI2SQuad::dma(false); | DMAChannel AudioInputI2SQuad::dma(false); | ||||
#if defined(__MK20DX256__) | |||||
#if defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
void AudioInputI2SQuad::begin(void) | void AudioInputI2SQuad::begin(void) | ||||
{ | { |
{ | { | ||||
"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": [ | ||||
"examples/*/*.ino", | "examples/*/*.ino", | ||||
"examples/*/*/*.ino" | "examples/*/*/*.ino" |
* SOFTWARE. | * SOFTWARE. | ||||
*/ | */ | ||||
#if defined(__MK20DX128__) || defined(__MK20DX256__) | |||||
#if defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK64FX512__) || defined(__MK66FX1M0__) | |||||
.cpu cortex-m4 | .cpu cortex-m4 | ||||
.syntax unified | .syntax unified |
#include "output_dac.h" | #include "output_dac.h" | ||||
#include "utility/pdb.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]; | DMAMEM static uint16_t dac_buffer[AUDIO_BLOCK_SAMPLES*2]; | ||||
audio_block_t * AudioOutputAnalog::block_left_1st = NULL; | audio_block_t * AudioOutputAnalog::block_left_1st = NULL; |
#elif F_CPU == 168000000 | #elif F_CPU == 168000000 | ||||
#define MCLK_MULT 8 | #define MCLK_MULT 8 | ||||
#define MCLK_DIV 119 | #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 | #elif F_CPU == 16000000 | ||||
#define MCLK_MULT 12 | #define MCLK_MULT 12 | ||||
#define MCLK_DIV 17 | #define MCLK_DIV 17 | ||||
// enable MCLK output | // enable MCLK output | ||||
I2S0_MCR = I2S_MCR_MICS(MCLK_SRC) | I2S_MCR_MOE; | 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)); | I2S0_MDR = I2S_MDR_FRACT((MCLK_MULT-1)) | I2S_MDR_DIVIDE((MCLK_DIV-1)); | ||||
// configure transmitter | // configure transmitter |
#include "output_i2s_quad.h" | #include "output_i2s_quad.h" | ||||
#include "memcpy_audio.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_ch1_1st = NULL; | ||||
audio_block_t * AudioOutputI2SQuad::block_ch2_1st = NULL; | audio_block_t * AudioOutputI2SQuad::block_ch2_1st = NULL; | ||||
#elif F_CPU == 168000000 | #elif F_CPU == 168000000 | ||||
#define MCLK_MULT 8 | #define MCLK_MULT 8 | ||||
#define MCLK_DIV 119 | #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 | #elif F_CPU == 16000000 | ||||
#define MCLK_MULT 12 | #define MCLK_MULT 12 | ||||
#define MCLK_DIV 17 | #define MCLK_DIV 17 | ||||
// enable MCLK output | // enable MCLK output | ||||
I2S0_MCR = I2S_MCR_MICS(MCLK_SRC) | I2S_MCR_MOE; | 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)); | I2S0_MDR = I2S_MDR_FRACT((MCLK_MULT-1)) | I2S_MDR_DIVIDE((MCLK_DIV-1)); | ||||
// configure transmitter | // configure transmitter |
#elif F_CPU == 168000000 | #elif F_CPU == 168000000 | ||||
#define MCLK_MULT 8 | #define MCLK_MULT 8 | ||||
#define MCLK_DIV 119 | #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 | #elif F_CPU == 16000000 | ||||
#define MCLK_MULT 12 | #define MCLK_MULT 12 | ||||
#define MCLK_DIV 17 | #define MCLK_DIV 17 | ||||
// enable MCLK output | // enable MCLK output | ||||
I2S0_MCR = I2S_MCR_MICS(MCLK_SRC) | I2S_MCR_MOE; | 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)); | I2S0_MDR = I2S_MDR_FRACT((MCLK_MULT-1)) | I2S_MDR_DIVIDE((MCLK_DIV-1)); | ||||
// configure transmitter | // configure transmitter |
return out; | 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 | #endif |