@@ -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 |