| #include "analyze_tonedetect.h" | #include "analyze_tonedetect.h" | ||||
| #include "utility/dspinst.h" | #include "utility/dspinst.h" | ||||
| #if defined(KINETISK) | |||||
| static inline int32_t multiply_32x32_rshift30(int32_t a, int32_t b) __attribute__((always_inline)); | static inline int32_t multiply_32x32_rshift30(int32_t a, int32_t b) __attribute__((always_inline)); | ||||
| static inline int32_t multiply_32x32_rshift30(int32_t a, int32_t b) | static inline int32_t multiply_32x32_rshift30(int32_t a, int32_t b) | ||||
| { | { | ||||
| trigger = (uint32_t)len * thresh; | trigger = (uint32_t)len * thresh; | ||||
| trigger = multiply_32x32_rshift32(trigger, trigger); | trigger = multiply_32x32_rshift32(trigger, trigger); | ||||
| Serial.printf("bool: power=%d, trig=%d\n", power, trigger); | |||||
| //Serial.printf("bool: power=%d, trig=%d\n", power, trigger); | |||||
| return (power >= trigger); | return (power >= trigger); | ||||
| // TODO: this should really remember if it's retuned true previously, | // TODO: this should really remember if it's retuned true previously, | ||||
| // so it can give a single true response each time a tone is seen. | // so it can give a single true response each time a tone is seen. | ||||
| } | } | ||||
| #elif defined(KINETISL) | |||||
| void AudioAnalyzeToneDetect::update(void) | |||||
| { | |||||
| audio_block_t *block; | |||||
| block = receiveReadOnly(); | |||||
| if (block) release(block); | |||||
| } | |||||
| #endif | |||||
| void AudioEffectMultiply::update(void) | void AudioEffectMultiply::update(void) | ||||
| { | { | ||||
| #if defined(KINETISK) | |||||
| audio_block_t *blocka, *blockb; | audio_block_t *blocka, *blockb; | ||||
| uint32_t *pa, *pb, *end; | uint32_t *pa, *pb, *end; | ||||
| uint32_t a12, a34; //, a56, a78; | uint32_t a12, a34; //, a56, a78; | ||||
| transmit(blocka); | transmit(blocka); | ||||
| release(blocka); | release(blocka); | ||||
| release(blockb); | release(blockb); | ||||
| #elif defined(KINETISL) | |||||
| audio_block_t *block; | |||||
| block = receiveReadOnly(0); | |||||
| if (block) release(block); | |||||
| block = receiveReadOnly(1); | |||||
| if (block) release(block); | |||||
| #endif | |||||
| } | } | ||||
| #include "filter_biquad.h" | #include "filter_biquad.h" | ||||
| #include "utility/dspinst.h" | #include "utility/dspinst.h" | ||||
| #if defined(KINETISK) | |||||
| void AudioFilterBiquad::update(void) | void AudioFilterBiquad::update(void) | ||||
| { | { | ||||
| audio_block_t *block; | audio_block_t *block; | ||||
| sum = signed_multiply_accumulate_32x16b(sum, a1, out2); | sum = signed_multiply_accumulate_32x16b(sum, a1, out2); | ||||
| sum = signed_multiply_accumulate_32x16t(sum, a2, aprev); | sum = signed_multiply_accumulate_32x16t(sum, a2, aprev); | ||||
| bprev = in2; | bprev = in2; | ||||
| aprev = pack_16x16( | |||||
| aprev = pack_16b_16b( | |||||
| signed_saturate_rshift(sum, 16, 14), out2); | signed_saturate_rshift(sum, 16, 14), out2); | ||||
| sum &= 0x3FFF; | sum &= 0x3FFF; | ||||
| bprev = in2; | bprev = in2; | ||||
| *dest &= 0x80000000; | *dest &= 0x80000000; | ||||
| __enable_irq(); | __enable_irq(); | ||||
| } | } | ||||
| #elif defined(KINETISL) | |||||
| void AudioFilterBiquad::update(void) | |||||
| { | |||||
| audio_block_t *block; | |||||
| block = receiveReadOnly(); | |||||
| if (block) release(block); | |||||
| } | |||||
| #endif |
| // no audible difference. | // no audible difference. | ||||
| //#define IMPROVE_EXPONENTIAL_ACCURACY | //#define IMPROVE_EXPONENTIAL_ACCURACY | ||||
| #if defined(KINETISK) | |||||
| void AudioFilterStateVariable::update_fixed(const int16_t *in, | void AudioFilterStateVariable::update_fixed(const int16_t *in, | ||||
| int16_t *lp, int16_t *bp, int16_t *hp) | int16_t *lp, int16_t *bp, int16_t *hp) | ||||
| { | { | ||||
| return; | return; | ||||
| } | } | ||||
| #elif defined(KINETISL) | |||||
| void AudioFilterStateVariable::update(void) | |||||
| { | |||||
| audio_block_t *block; | |||||
| block = receiveReadOnly(0); | |||||
| if (block) release(block); | |||||
| block = receiveReadOnly(1); | |||||
| if (block) release(block); | |||||
| } | |||||
| #endif | |||||
| AudioOutputI2S::config_i2s(); | AudioOutputI2S::config_i2s(); | ||||
| CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0 | CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0 | ||||
| #if defined(KINETISK) | |||||
| dma.TCD->SADDR = &I2S0_RDR0; | dma.TCD->SADDR = &I2S0_RDR0; | ||||
| dma.TCD->SOFF = 0; | dma.TCD->SOFF = 0; | ||||
| dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); | dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); | ||||
| dma.TCD->DLASTSGA = -sizeof(i2s_rx_buffer); | dma.TCD->DLASTSGA = -sizeof(i2s_rx_buffer); | ||||
| dma.TCD->BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2; | dma.TCD->BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2; | ||||
| dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; | dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; | ||||
| #endif | |||||
| dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX); | dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX); | ||||
| update_responsibility = update_setup(); | update_responsibility = update_setup(); | ||||
| dma.enable(); | dma.enable(); | ||||
| audio_block_t *left, *right; | audio_block_t *left, *right; | ||||
| //digitalWriteFast(3, HIGH); | //digitalWriteFast(3, HIGH); | ||||
| #if defined(KINETISK) | |||||
| daddr = (uint32_t)(dma.TCD->DADDR); | daddr = (uint32_t)(dma.TCD->DADDR); | ||||
| #endif | |||||
| dma.clearInterrupt(); | dma.clearInterrupt(); | ||||
| if (daddr < (uint32_t)i2s_rx_buffer + sizeof(i2s_rx_buffer) / 2) { | if (daddr < (uint32_t)i2s_rx_buffer + sizeof(i2s_rx_buffer) / 2) { | ||||
| AudioOutputI2Sslave::config_i2s(); | AudioOutputI2Sslave::config_i2s(); | ||||
| CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0 | CORE_PIN13_CONFIG = PORT_PCR_MUX(4); // pin 13, PTC5, I2S0_RXD0 | ||||
| #if defined(KINETISK) | |||||
| dma.TCD->SADDR = &I2S0_RDR0; | dma.TCD->SADDR = &I2S0_RDR0; | ||||
| dma.TCD->SOFF = 0; | dma.TCD->SOFF = 0; | ||||
| dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); | dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(1) | DMA_TCD_ATTR_DSIZE(1); | ||||
| dma.TCD->DLASTSGA = -sizeof(i2s_rx_buffer); | dma.TCD->DLASTSGA = -sizeof(i2s_rx_buffer); | ||||
| dma.TCD->BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2; | dma.TCD->BITER_ELINKNO = sizeof(i2s_rx_buffer) / 2; | ||||
| dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; | dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR; | ||||
| #endif | |||||
| dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX); | dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_RX); | ||||
| update_responsibility = update_setup(); | update_responsibility = update_setup(); | ||||
| dma.enable(); | dma.enable(); |
| // TODO: this code assumes F_BUS is 48 MHz. | // TODO: this code assumes F_BUS is 48 MHz. | ||||
| // supporting other speeds is not easy, but should be done someday | // supporting other speeds is not easy, but should be done someday | ||||
| #if defined(KINETISK) | |||||
| void AudioOutputPWM::begin(void) | void AudioOutputPWM::begin(void) | ||||
| { | { | ||||
| dma.begin(true); // Allocate the DMA channel first | dma.begin(true); // Allocate the DMA channel first | ||||
| // biter = sizeof(buffer) / 8 (no minor loop linking) | // biter = sizeof(buffer) / 8 (no minor loop linking) | ||||
| #elif defined(KINETISL) | |||||
| void AudioOutputPWM::update(void) | |||||
| { | |||||
| audio_block_t *block; | |||||
| block = receiveReadOnly(); | |||||
| if (block) release(block); | |||||
| } | |||||
| #endif |
| #include "output_spdif.h" | #include "output_spdif.h" | ||||
| #if defined(KINETISK) | |||||
| #define PREAMBLE_B (0xE8) //11101000 | #define PREAMBLE_B (0xE8) //11101000 | ||||
| #define PREAMBLE_M (0xE2) //11100010 | #define PREAMBLE_M (0xE2) //11100010 | ||||
| #define PREAMBLE_W (0xE4) //11100100 | #define PREAMBLE_W (0xE4) //11100100 | ||||
| // CORE_PIN11_CONFIG = PORT_PCR_MUX(6); // pin 11, PTC6, I2S0_MCLK | // CORE_PIN11_CONFIG = PORT_PCR_MUX(6); // pin 11, PTC6, I2S0_MCLK | ||||
| #endif | #endif | ||||
| } | } | ||||
| #elif defined(KINETISL) | |||||
| void AudioOutputSPDIF::update(void) | |||||
| { | |||||
| audio_block_t *block; | |||||
| block = receiveReadOnly(0); // input 0 = left channel | |||||
| if (block) release(block); | |||||
| block = receiveReadOnly(1); // input 1 = right channel | |||||
| if (block) release(block); | |||||
| } | |||||
| #endif |
| scale = (ph >> 8) & 0xFFFF; | scale = (ph >> 8) & 0xFFFF; | ||||
| val2 *= scale; | val2 *= scale; | ||||
| val1 *= 0xFFFF - scale; | val1 *= 0xFFFF - scale; | ||||
| //block->data[i] = (((val1 + val2) >> 16) * magnitude) >> 16; | |||||
| #if defined(KINETISK) | |||||
| block->data[i] = multiply_32x32_rshift32(val1 + val2, magnitude); | block->data[i] = multiply_32x32_rshift32(val1 + val2, magnitude); | ||||
| #elif defined(KINETISL) | |||||
| block->data[i] = (((val1 + val2) >> 16) * magnitude) >> 16; | |||||
| #endif | |||||
| ph += inc; | ph += inc; | ||||
| } | } | ||||
| phase_accumulator = ph; | phase_accumulator = ph; | ||||
| } | } | ||||
| #if defined(KINETISK) | |||||
| void AudioSynthWaveformSineModulated::update(void) | void AudioSynthWaveformSineModulated::update(void) | ||||
| { | { | ||||
| audio_block_t *block, *modinput; | audio_block_t *block, *modinput; | ||||
| release(block); | release(block); | ||||
| } | } | ||||
| #elif defined(KINETISL) | |||||
| void AudioSynthWaveformSineModulated::update(void) | |||||
| { | |||||
| audio_block_t *block; | |||||
| block = receiveReadOnly(); | |||||
| if (block) release(block); | |||||
| } | |||||
| #endif | |||||
| end = p + AUDIO_BLOCK_SAMPLES/2; | end = p + AUDIO_BLOCK_SAMPLES/2; | ||||
| lo = seed; | lo = seed; | ||||
| do { | do { | ||||
| #if defined(KINETISK) | |||||
| hi = multiply_16bx16t(16807, lo); // 16807 * (lo >> 16) | hi = multiply_16bx16t(16807, lo); // 16807 * (lo >> 16) | ||||
| lo = 16807 * (lo & 0xFFFF); | lo = 16807 * (lo & 0xFFFF); | ||||
| lo += (hi & 0x7FFF) << 16; | lo += (hi & 0x7FFF) << 16; | ||||
| val2 = pack_16b_16b(n2, n1); | val2 = pack_16b_16b(n2, n1); | ||||
| *p++ = val1; | *p++ = val1; | ||||
| *p++ = val2; | *p++ = val2; | ||||
| #elif defined(KINETISL) | |||||
| hi = 16807 * (lo >> 16); | |||||
| lo = 16807 * (lo & 0xFFFF); | |||||
| lo += (hi & 0x7FFF) << 16; | |||||
| lo += hi >> 15; | |||||
| lo = (lo & 0x7FFFFFFF) + (lo >> 31); | |||||
| n1 = signed_multiply_32x16b(gain, lo); | |||||
| hi = 16807 * (lo >> 16); | |||||
| lo = 16807 * (lo & 0xFFFF); | |||||
| lo += (hi & 0x7FFF) << 16; | |||||
| lo += hi >> 15; | |||||
| lo = (lo & 0x7FFFFFFF) + (lo >> 31); | |||||
| n2 = signed_multiply_32x16b(gain, lo); | |||||
| val1 = pack_16b_16b(n2, n1); | |||||
| *p++ = val1; | |||||
| #endif | |||||
| } while (p < end); | } while (p < end); | ||||
| seed = lo; | seed = lo; | ||||
| transmit(block); | transmit(block); |