Hello all..
I have realised that the spdif out works with T4 so I have been comparing output_spdif.cpp to output_adat.cpp and making changes trying to get it working. I have persuaded it to compile but I just get noise in the left channel at the moment with WavFilePlayer and an ADAT output.
I think the issue is that I need to set 8 words per frame here but I dont know how...
Here is the full edited output_adat.cpp...
feel free to tell me if I am miles off the mark and waisting my time! -A
I have realised that the spdif out works with T4 so I have been comparing output_spdif.cpp to output_adat.cpp and making changes trying to get it working. I have persuaded it to compile but I just get noise in the left channel at the moment with WavFilePlayer and an ADAT output.
I think the issue is that I need to set 8 words per frame here but I dont know how...
Code:
// fix..4 Words per Frame 32 Bit Word-Length -> 128 Bit Frame-Length, MSB First:
// i want.. 8 Words per Frame 32 Bit Word-Length -> 256 Bit Frame-Length, MSB First:
I2S1_TCR4 = I2S_TCR4_FRSZ(3) | I2S_TCR4_SYWD(0) | I2S_TCR4_MF | I2S_TCR4_FSP | I2S_TCR4_FSD;
I2S1_TCR5 = I2S_TCR5_WNW(31) | I2S_TCR5_W0W(31) | I2S_TCR5_FBT(31);
Here is the full edited output_adat.cpp...
Code:
/* ADAT for Teensy 3.X
* Copyright (c) 2017, Ernstjan Freriks,
* Thanks to Frank Bösing & KPC & Paul Stoffregen!
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice, development funding notice, and this permission
* notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#include <Arduino.h>
#include "output_adat.h"
#include "utility/imxrt_hw.h"
#if defined(KINETISK) || defined(__IMXRT1052__) || defined(__IMXRT1062__) //AAA
audio_block_t * AudioOutputADAT::block_ch1_1st = NULL;
audio_block_t * AudioOutputADAT::block_ch2_1st = NULL;
audio_block_t * AudioOutputADAT::block_ch3_1st = NULL;
audio_block_t * AudioOutputADAT::block_ch4_1st = NULL;
audio_block_t * AudioOutputADAT::block_ch5_1st = NULL;
audio_block_t * AudioOutputADAT::block_ch6_1st = NULL;
audio_block_t * AudioOutputADAT::block_ch7_1st = NULL;
audio_block_t * AudioOutputADAT::block_ch8_1st = NULL;
audio_block_t * AudioOutputADAT::block_ch1_2nd = NULL;
audio_block_t * AudioOutputADAT::block_ch2_2nd = NULL;
audio_block_t * AudioOutputADAT::block_ch3_2nd = NULL;
audio_block_t * AudioOutputADAT::block_ch4_2nd = NULL;
audio_block_t * AudioOutputADAT::block_ch5_2nd = NULL;
audio_block_t * AudioOutputADAT::block_ch6_2nd = NULL;
audio_block_t * AudioOutputADAT::block_ch7_2nd = NULL;
audio_block_t * AudioOutputADAT::block_ch8_2nd = NULL;
uint16_t AudioOutputADAT::ch1_offset = 0;
uint16_t AudioOutputADAT::ch2_offset = 0;
uint16_t AudioOutputADAT::ch3_offset = 0;
uint16_t AudioOutputADAT::ch4_offset = 0;
uint16_t AudioOutputADAT::ch5_offset = 0;
uint16_t AudioOutputADAT::ch6_offset = 0;
uint16_t AudioOutputADAT::ch7_offset = 0;
uint16_t AudioOutputADAT::ch8_offset = 0;
bool AudioOutputADAT::update_responsibility = false;
//uint32_t AudioOutputADAT::vucp = VUCP_VALID;
DMAMEM static uint32_t ADAT_tx_buffer[AUDIO_BLOCK_SAMPLES * 8]; //4 KB, AUDIO_BLOCK_SAMPLES is usually 128
DMAChannel AudioOutputADAT::dma(false);
static const uint32_t zerodata[AUDIO_BLOCK_SAMPLES/4] = {0};
// These are the lookup tables. There are four of them so that the remainder of the 32 bit result can easily be XORred with the next 8 bits.
static const uint32_t LookupTable_firstword[256] = { 0x0, 0x1ffffff, 0x3ffffff, 0x2000000, 0x7ffffff, 0x6000000, 0x4000000, 0x5ffffff, 0xfffffff, 0xe000000, 0xc000000, 0xdffffff, 0x8000000, 0x9ffffff, 0xbffffff, 0xa000000, 0x1fffffff, 0x1e000000, 0x1c000000, 0x1dffffff, 0x18000000, 0x19ffffff, 0x1bffffff, 0x1a000000, 0x10000000, 0x11ffffff, 0x13ffffff, 0x12000000, 0x17ffffff, 0x16000000, 0x14000000, 0x15ffffff, 0x3fffffff, 0x3e000000, 0x3c000000, 0x3dffffff, 0x38000000, 0x39ffffff, 0x3bffffff, 0x3a000000, 0x30000000, 0x31ffffff, 0x33ffffff, 0x32000000, 0x37ffffff, 0x36000000, 0x34000000, 0x35ffffff, 0x20000000, 0x21ffffff, 0x23ffffff, 0x22000000, 0x27ffffff, 0x26000000, 0x24000000, 0x25ffffff, 0x2fffffff, 0x2e000000, 0x2c000000, 0x2dffffff, 0x28000000, 0x29ffffff, 0x2bffffff, 0x2a000000, 0x7fffffff, 0x7e000000, 0x7c000000, 0x7dffffff, 0x78000000, 0x79ffffff, 0x7bffffff, 0x7a000000, 0x70000000, 0x71ffffff, 0x73ffffff, 0x72000000, 0x77ffffff, 0x76000000, 0x74000000, 0x75ffffff, 0x60000000, 0x61ffffff, 0x63ffffff, 0x62000000, 0x67ffffff, 0x66000000, 0x64000000, 0x65ffffff, 0x6fffffff, 0x6e000000, 0x6c000000, 0x6dffffff, 0x68000000, 0x69ffffff, 0x6bffffff, 0x6a000000, 0x40000000, 0x41ffffff, 0x43ffffff, 0x42000000, 0x47ffffff, 0x46000000, 0x44000000, 0x45ffffff, 0x4fffffff, 0x4e000000, 0x4c000000, 0x4dffffff, 0x48000000, 0x49ffffff, 0x4bffffff, 0x4a000000, 0x5fffffff, 0x5e000000, 0x5c000000, 0x5dffffff, 0x58000000, 0x59ffffff, 0x5bffffff, 0x5a000000, 0x50000000, 0x51ffffff, 0x53ffffff, 0x52000000, 0x57ffffff, 0x56000000, 0x54000000, 0x55ffffff, 0xffffffff, 0xfe000000, 0xfc000000, 0xfdffffff, 0xf8000000, 0xf9ffffff, 0xfbffffff, 0xfa000000, 0xf0000000, 0xf1ffffff, 0xf3ffffff, 0xf2000000, 0xf7ffffff, 0xf6000000, 0xf4000000, 0xf5ffffff, 0xe0000000, 0xe1ffffff, 0xe3ffffff, 0xe2000000, 0xe7ffffff, 0xe6000000, 0xe4000000, 0xe5ffffff, 0xefffffff, 0xee000000, 0xec000000, 0xedffffff, 0xe8000000, 0xe9ffffff, 0xebffffff, 0xea000000, 0xc0000000, 0xc1ffffff, 0xc3ffffff, 0xc2000000, 0xc7ffffff, 0xc6000000, 0xc4000000, 0xc5ffffff, 0xcfffffff, 0xce000000, 0xcc000000, 0xcdffffff, 0xc8000000, 0xc9ffffff, 0xcbffffff, 0xca000000, 0xdfffffff, 0xde000000, 0xdc000000, 0xddffffff, 0xd8000000, 0xd9ffffff, 0xdbffffff, 0xda000000, 0xd0000000, 0xd1ffffff, 0xd3ffffff, 0xd2000000, 0xd7ffffff, 0xd6000000, 0xd4000000, 0xd5ffffff, 0x80000000, 0x81ffffff, 0x83ffffff, 0x82000000, 0x87ffffff, 0x86000000, 0x84000000, 0x85ffffff, 0x8fffffff, 0x8e000000, 0x8c000000, 0x8dffffff, 0x88000000, 0x89ffffff, 0x8bffffff, 0x8a000000, 0x9fffffff, 0x9e000000, 0x9c000000, 0x9dffffff, 0x98000000, 0x99ffffff, 0x9bffffff, 0x9a000000, 0x90000000, 0x91ffffff, 0x93ffffff, 0x92000000, 0x97ffffff, 0x96000000, 0x94000000, 0x95ffffff, 0xbfffffff, 0xbe000000, 0xbc000000, 0xbdffffff, 0xb8000000, 0xb9ffffff, 0xbbffffff, 0xba000000, 0xb0000000, 0xb1ffffff, 0xb3ffffff, 0xb2000000, 0xb7ffffff, 0xb6000000, 0xb4000000, 0xb5ffffff, 0xa0000000, 0xa1ffffff, 0xa3ffffff, 0xa2000000, 0xa7ffffff, 0xa6000000, 0xa4000000, 0xa5ffffff, 0xafffffff, 0xae000000, 0xac000000, 0xadffffff, 0xa8000000, 0xa9ffffff, 0xabffffff, 0xaa000000};
static const uint32_t LookupTable_secondword[256] = { 0x0, 0x1ffff, 0x3ffff, 0x20000, 0x7ffff, 0x60000, 0x40000, 0x5ffff, 0xfffff, 0xe0000, 0xc0000, 0xdffff, 0x80000, 0x9ffff, 0xbffff, 0xa0000, 0x1fffff, 0x1e0000, 0x1c0000, 0x1dffff, 0x180000, 0x19ffff, 0x1bffff, 0x1a0000, 0x100000, 0x11ffff, 0x13ffff, 0x120000, 0x17ffff, 0x160000, 0x140000, 0x15ffff, 0x3fffff, 0x3e0000, 0x3c0000, 0x3dffff, 0x380000, 0x39ffff, 0x3bffff, 0x3a0000, 0x300000, 0x31ffff, 0x33ffff, 0x320000, 0x37ffff, 0x360000, 0x340000, 0x35ffff, 0x200000, 0x21ffff, 0x23ffff, 0x220000, 0x27ffff, 0x260000, 0x240000, 0x25ffff, 0x2fffff, 0x2e0000, 0x2c0000, 0x2dffff, 0x280000, 0x29ffff, 0x2bffff, 0x2a0000, 0x7fffff, 0x7e0000, 0x7c0000, 0x7dffff, 0x780000, 0x79ffff, 0x7bffff, 0x7a0000, 0x700000, 0x71ffff, 0x73ffff, 0x720000, 0x77ffff, 0x760000, 0x740000, 0x75ffff, 0x600000, 0x61ffff, 0x63ffff, 0x620000, 0x67ffff, 0x660000, 0x640000, 0x65ffff, 0x6fffff, 0x6e0000, 0x6c0000, 0x6dffff, 0x680000, 0x69ffff, 0x6bffff, 0x6a0000, 0x400000, 0x41ffff, 0x43ffff, 0x420000, 0x47ffff, 0x460000, 0x440000, 0x45ffff, 0x4fffff, 0x4e0000, 0x4c0000, 0x4dffff, 0x480000, 0x49ffff, 0x4bffff, 0x4a0000, 0x5fffff, 0x5e0000, 0x5c0000, 0x5dffff, 0x580000, 0x59ffff, 0x5bffff, 0x5a0000, 0x500000, 0x51ffff, 0x53ffff, 0x520000, 0x57ffff, 0x560000, 0x540000, 0x55ffff, 0xffffff, 0xfe0000, 0xfc0000, 0xfdffff, 0xf80000, 0xf9ffff, 0xfbffff, 0xfa0000, 0xf00000, 0xf1ffff, 0xf3ffff, 0xf20000, 0xf7ffff, 0xf60000, 0xf40000, 0xf5ffff, 0xe00000, 0xe1ffff, 0xe3ffff, 0xe20000, 0xe7ffff, 0xe60000, 0xe40000, 0xe5ffff, 0xefffff, 0xee0000, 0xec0000, 0xedffff, 0xe80000, 0xe9ffff, 0xebffff, 0xea0000, 0xc00000, 0xc1ffff, 0xc3ffff, 0xc20000, 0xc7ffff, 0xc60000, 0xc40000, 0xc5ffff, 0xcfffff, 0xce0000, 0xcc0000, 0xcdffff, 0xc80000, 0xc9ffff, 0xcbffff, 0xca0000, 0xdfffff, 0xde0000, 0xdc0000, 0xddffff, 0xd80000, 0xd9ffff, 0xdbffff, 0xda0000, 0xd00000, 0xd1ffff, 0xd3ffff, 0xd20000, 0xd7ffff, 0xd60000, 0xd40000, 0xd5ffff, 0x800000, 0x81ffff, 0x83ffff, 0x820000, 0x87ffff, 0x860000, 0x840000, 0x85ffff, 0x8fffff, 0x8e0000, 0x8c0000, 0x8dffff, 0x880000, 0x89ffff, 0x8bffff, 0x8a0000, 0x9fffff, 0x9e0000, 0x9c0000, 0x9dffff, 0x980000, 0x99ffff, 0x9bffff, 0x9a0000, 0x900000, 0x91ffff, 0x93ffff, 0x920000, 0x97ffff, 0x960000, 0x940000, 0x95ffff, 0xbfffff, 0xbe0000, 0xbc0000, 0xbdffff, 0xb80000, 0xb9ffff, 0xbbffff, 0xba0000, 0xb00000, 0xb1ffff, 0xb3ffff, 0xb20000, 0xb7ffff, 0xb60000, 0xb40000, 0xb5ffff, 0xa00000, 0xa1ffff, 0xa3ffff, 0xa20000, 0xa7ffff, 0xa60000, 0xa40000, 0xa5ffff, 0xafffff, 0xae0000, 0xac0000, 0xadffff, 0xa80000, 0xa9ffff, 0xabffff, 0xaa0000};
static const uint32_t LookupTable_thirdword[256] = { 0x0, 0x1ff, 0x3ff, 0x200, 0x7ff, 0x600, 0x400, 0x5ff, 0xfff, 0xe00, 0xc00, 0xdff, 0x800, 0x9ff, 0xbff, 0xa00, 0x1fff, 0x1e00, 0x1c00, 0x1dff, 0x1800, 0x19ff, 0x1bff, 0x1a00, 0x1000, 0x11ff, 0x13ff, 0x1200, 0x17ff, 0x1600, 0x1400, 0x15ff, 0x3fff, 0x3e00, 0x3c00, 0x3dff, 0x3800, 0x39ff, 0x3bff, 0x3a00, 0x3000, 0x31ff, 0x33ff, 0x3200, 0x37ff, 0x3600, 0x3400, 0x35ff, 0x2000, 0x21ff, 0x23ff, 0x2200, 0x27ff, 0x2600, 0x2400, 0x25ff, 0x2fff, 0x2e00, 0x2c00, 0x2dff, 0x2800, 0x29ff, 0x2bff, 0x2a00, 0x7fff, 0x7e00, 0x7c00, 0x7dff, 0x7800, 0x79ff, 0x7bff, 0x7a00, 0x7000, 0x71ff, 0x73ff, 0x7200, 0x77ff, 0x7600, 0x7400, 0x75ff, 0x6000, 0x61ff, 0x63ff, 0x6200, 0x67ff, 0x6600, 0x6400, 0x65ff, 0x6fff, 0x6e00, 0x6c00, 0x6dff, 0x6800, 0x69ff, 0x6bff, 0x6a00, 0x4000, 0x41ff, 0x43ff, 0x4200, 0x47ff, 0x4600, 0x4400, 0x45ff, 0x4fff, 0x4e00, 0x4c00, 0x4dff, 0x4800, 0x49ff, 0x4bff, 0x4a00, 0x5fff, 0x5e00, 0x5c00, 0x5dff, 0x5800, 0x59ff, 0x5bff, 0x5a00, 0x5000, 0x51ff, 0x53ff, 0x5200, 0x57ff, 0x5600, 0x5400, 0x55ff, 0xffff, 0xfe00, 0xfc00, 0xfdff, 0xf800, 0xf9ff, 0xfbff, 0xfa00, 0xf000, 0xf1ff, 0xf3ff, 0xf200, 0xf7ff, 0xf600, 0xf400, 0xf5ff, 0xe000, 0xe1ff, 0xe3ff, 0xe200, 0xe7ff, 0xe600, 0xe400, 0xe5ff, 0xefff, 0xee00, 0xec00, 0xedff, 0xe800, 0xe9ff, 0xebff, 0xea00, 0xc000, 0xc1ff, 0xc3ff, 0xc200, 0xc7ff, 0xc600, 0xc400, 0xc5ff, 0xcfff, 0xce00, 0xcc00, 0xcdff, 0xc800, 0xc9ff, 0xcbff, 0xca00, 0xdfff, 0xde00, 0xdc00, 0xddff, 0xd800, 0xd9ff, 0xdbff, 0xda00, 0xd000, 0xd1ff, 0xd3ff, 0xd200, 0xd7ff, 0xd600, 0xd400, 0xd5ff, 0x8000, 0x81ff, 0x83ff, 0x8200, 0x87ff, 0x8600, 0x8400, 0x85ff, 0x8fff, 0x8e00, 0x8c00, 0x8dff, 0x8800, 0x89ff, 0x8bff, 0x8a00, 0x9fff, 0x9e00, 0x9c00, 0x9dff, 0x9800, 0x99ff, 0x9bff, 0x9a00, 0x9000, 0x91ff, 0x93ff, 0x9200, 0x97ff, 0x9600, 0x9400, 0x95ff, 0xbfff, 0xbe00, 0xbc00, 0xbdff, 0xb800, 0xb9ff, 0xbbff, 0xba00, 0xb000, 0xb1ff, 0xb3ff, 0xb200, 0xb7ff, 0xb600, 0xb400, 0xb5ff, 0xa000, 0xa1ff, 0xa3ff, 0xa200, 0xa7ff, 0xa600, 0xa400, 0xa5ff, 0xafff, 0xae00, 0xac00, 0xadff, 0xa800, 0xa9ff, 0xabff, 0xaa00};
static const uint32_t LookupTable_fourthword[256] = { 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5, 0xf, 0xe, 0xc, 0xd, 0x8, 0x9, 0xb, 0xa, 0x1f, 0x1e, 0x1c, 0x1d, 0x18, 0x19, 0x1b, 0x1a, 0x10, 0x11, 0x13, 0x12, 0x17, 0x16, 0x14, 0x15, 0x3f, 0x3e, 0x3c, 0x3d, 0x38, 0x39, 0x3b, 0x3a, 0x30, 0x31, 0x33, 0x32, 0x37, 0x36, 0x34, 0x35, 0x20, 0x21, 0x23, 0x22, 0x27, 0x26, 0x24, 0x25, 0x2f, 0x2e, 0x2c, 0x2d, 0x28, 0x29, 0x2b, 0x2a, 0x7f, 0x7e, 0x7c, 0x7d, 0x78, 0x79, 0x7b, 0x7a, 0x70, 0x71, 0x73, 0x72, 0x77, 0x76, 0x74, 0x75, 0x60, 0x61, 0x63, 0x62, 0x67, 0x66, 0x64, 0x65, 0x6f, 0x6e, 0x6c, 0x6d, 0x68, 0x69, 0x6b, 0x6a, 0x40, 0x41, 0x43, 0x42, 0x47, 0x46, 0x44, 0x45, 0x4f, 0x4e, 0x4c, 0x4d, 0x48, 0x49, 0x4b, 0x4a, 0x5f, 0x5e, 0x5c, 0x5d, 0x58, 0x59, 0x5b, 0x5a, 0x50, 0x51, 0x53, 0x52, 0x57, 0x56, 0x54, 0x55, 0xff, 0xfe, 0xfc, 0xfd, 0xf8, 0xf9, 0xfb, 0xfa, 0xf0, 0xf1, 0xf3, 0xf2, 0xf7, 0xf6, 0xf4, 0xf5, 0xe0, 0xe1, 0xe3, 0xe2, 0xe7, 0xe6, 0xe4, 0xe5, 0xef, 0xee, 0xec, 0xed, 0xe8, 0xe9, 0xeb, 0xea, 0xc0, 0xc1, 0xc3, 0xc2, 0xc7, 0xc6, 0xc4, 0xc5, 0xcf, 0xce, 0xcc, 0xcd, 0xc8, 0xc9, 0xcb, 0xca, 0xdf, 0xde, 0xdc, 0xdd, 0xd8, 0xd9, 0xdb, 0xda, 0xd0, 0xd1, 0xd3, 0xd2, 0xd7, 0xd6, 0xd4, 0xd5, 0x80, 0x81, 0x83, 0x82, 0x87, 0x86, 0x84, 0x85, 0x8f, 0x8e, 0x8c, 0x8d, 0x88, 0x89, 0x8b, 0x8a, 0x9f, 0x9e, 0x9c, 0x9d, 0x98, 0x99, 0x9b, 0x9a, 0x90, 0x91, 0x93, 0x92, 0x97, 0x96, 0x94, 0x95, 0xbf, 0xbe, 0xbc, 0xbd, 0xb8, 0xb9, 0xbb, 0xba, 0xb0, 0xb1, 0xb3, 0xb2, 0xb7, 0xb6, 0xb4, 0xb5, 0xa0, 0xa1, 0xa3, 0xa2, 0xa7, 0xa6, 0xa4, 0xa5, 0xaf, 0xae, 0xac, 0xad, 0xa8, 0xa9, 0xab, 0xaa};
void AudioOutputADAT::begin(void)
{
dma.begin(true); // Allocate the DMA channel first
block_ch1_1st = NULL;
block_ch2_1st = NULL;
block_ch3_1st = NULL;
block_ch4_1st = NULL;
block_ch5_1st = NULL;
block_ch6_1st = NULL;
block_ch7_1st = NULL;
block_ch8_1st = NULL;
// TODO: should we set & clear the I2S_TCSR_SR bit here?
config_ADAT();
#if defined(KINETISK)
CORE_PIN22_CONFIG = PORT_PCR_MUX(6); // pin 22, PTC1, I2S0_TXD0
const int nbytes_mlno = 2 * 8; // 16 Bytes per minor loop
dma.TCD->SADDR = ADAT_tx_buffer;
dma.TCD->SOFF = 4;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2); //transfersize 2 = 32 bit, 5 = 32 byte
dma.TCD->NBYTES_MLNO = nbytes_mlno;
dma.TCD->SLAST = -sizeof(ADAT_tx_buffer);
dma.TCD->DADDR = &I2S0_TDR0;
dma.TCD->DOFF = 0;
dma.TCD->CITER_ELINKNO = sizeof(ADAT_tx_buffer) / nbytes_mlno;
dma.TCD->DLASTSGA = 0;
dma.TCD->BITER_ELINKNO = sizeof(ADAT_tx_buffer) / nbytes_mlno;
dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_I2S0_TX);
update_responsibility = update_setup();
dma.enable();
I2S0_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE | I2S_TCSR_FR;
dma.attachInterrupt(isr);
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
#if defined(__IMXRT1052__)
CORE_PIN6_CONFIG = 3; //1:TX_DATA0
#elif defined(__IMXRT1062__)
CORE_PIN7_CONFIG = 3; //1:TX_DATA0
#endif
const int nbytes_mlno = 2 * 8; // 16 Bytes per minor loop
dma.TCD->SADDR = ADAT_tx_buffer;
dma.TCD->SOFF = 4;
dma.TCD->ATTR = DMA_TCD_ATTR_SSIZE(2) | DMA_TCD_ATTR_DSIZE(2);
dma.TCD->NBYTES_MLNO = nbytes_mlno;
dma.TCD->SLAST = -sizeof(ADAT_tx_buffer);
dma.TCD->DADDR = &I2S1_TDR0;
dma.TCD->DOFF = 0;
dma.TCD->CITER_ELINKNO = sizeof(ADAT_tx_buffer) / nbytes_mlno;
dma.TCD->DLASTSGA = 0;
dma.TCD->BITER_ELINKNO = sizeof(ADAT_tx_buffer) / nbytes_mlno;
dma.TCD->CSR = DMA_TCD_CSR_INTHALF | DMA_TCD_CSR_INTMAJOR;
dma.triggerAtHardwareEvent(DMAMUX_SOURCE_SAI1_TX);
update_responsibility = update_setup();
dma.enable();
I2S1_RCSR |= I2S_RCSR_RE;
I2S1_TCSR |= I2S_TCSR_TE | I2S_TCSR_BCE | I2S_TCSR_FRDE | I2S_TCSR_FR;
dma.attachInterrupt(isr);
#endif
}
/*
https://ackspace.nl/wiki/ADAT_project
https://github.com/xcore/sc_adat/blob/master/module_adat_tx/src/adat_tx_port.xc
for information about the clock:
http://cache.freescale.com/files/32bit/doc/app_note/AN4800.pdf
We need a bitrate twice as high as the SPDIF example.
Because BITCLK can not be the same as MCLK, but only half of MCLK, we need a 2*MCLK (so for 44100 samplerate we need 88200 MCLK)
*/
void AudioOutputADAT::isr(void)
{
const int16_t *src1, *src2, *src3, *src4,*src5, *src6, *src7, *src8;
const int16_t *zeros = (const int16_t *)zerodata;
uint32_t *end, *dest;
uint32_t saddr;
uint32_t sample1, sample2, sample3, sample4, sample5, sample6, sample7, sample8;
static uint32_t previousnrzi_highlow = 0; //this is used for the NZRI encoding to remember the last state.
// if the result of the lookup table LSB is other than this lastbit, the result of the lookup table must be inverted.
//static bool previousframeinverted=false;
saddr = (uint32_t)(dma.TCD->SADDR);
dma.clearInterrupt();
if (saddr < (uint32_t)ADAT_tx_buffer + sizeof(ADAT_tx_buffer) / 2) {
// DMA is transmitting the first half of the buffer
// so we must fill the second half
dest = (uint32_t *)&ADAT_tx_buffer[AUDIO_BLOCK_SAMPLES * 8/2];
end = (uint32_t *)&ADAT_tx_buffer[AUDIO_BLOCK_SAMPLES * 8];
if (AudioOutputADAT::update_responsibility) AudioStream::update_all();
} else {
// DMA is transmitting the second half of the buffer
// so we must fill the first half
dest = (uint32_t *)ADAT_tx_buffer;
end = (uint32_t *)&ADAT_tx_buffer[AUDIO_BLOCK_SAMPLES * 8/2];
}
src1 = (block_ch1_1st) ? block_ch1_1st->data + ch1_offset : zeros;
src2 = (block_ch2_1st) ? block_ch2_1st->data + ch2_offset : zeros;
src3 = (block_ch3_1st) ? block_ch3_1st->data + ch3_offset : zeros;
src4 = (block_ch4_1st) ? block_ch4_1st->data + ch4_offset : zeros;
src5 = (block_ch5_1st) ? block_ch5_1st->data + ch5_offset : zeros;
src6 = (block_ch6_1st) ? block_ch6_1st->data + ch6_offset : zeros;
src7 = (block_ch7_1st) ? block_ch7_1st->data + ch7_offset : zeros;
src8 = (block_ch8_1st) ? block_ch8_1st->data + ch8_offset : zeros;
//Non-NZRI encoded 'empty' ADAT Frame
/*
*(dest+0) = 0b10000100001000010000100001000010; // bit 0-31
*(dest+1) = 0b00010000100001000010000100001000; // bit 32-63
*(dest+2) = 0b01000010000100001000010000100001; // bit 64-95
*(dest+3) = 0b00001000010000100001000010000100; // bit 96-127
*(dest+4) = 0b00100001000010000100001000010000; // bit 128-159
*(dest+5) = 0b10000100001000010000100001000010; // bit 160-191
*(dest+6) = 0b00010000100001000010000100001000; // bit 192-223
*(dest+7) = 0b01000010000100001000000000010000; // bit 224-255
dest+=8;
*/
/*
//NZRI encoded 'empty' ADAT Frame
*(dest+0) = 0b11111000001111100000111110000011; // bit 0-31
*(dest+1) = 0b11100000111110000011111000001111; // bit 32-63
*(dest+2) = 0b10000011111000001111100000111110; // bit 64-95
*(dest+3) = 0b00001111100000111110000011111000; // bit 96-127
*(dest+4) = 0b00111110000011111000001111100000; // bit 128-159
*(dest+5) = 0b11111000001111100000111110000011; // bit 160-191
*(dest+6) = 0b11100000111110000011111000001111; // bit 192-223
*(dest+7) = 0b10000011111000001111111111100000; // bit 224-255
dest+=8;
*/
do
{
sample1 = (*src1++);
sample2 = (*src2++);
sample3 = (*src3++);
sample4 = (*src4++);
sample5 = (*src5++);
sample6 = (*src6++);
sample7 = (*src7++);
sample8 = (*src8++);
uint32_t value;
uint32_t nzrivalue;
value= 0b10000100001000010000100001000010 /* bit 0-31 */
// b00000000000000001000000000000000 // start of 16 bit sample
| ((sample1<<15)&0b01111000000000000000000000000000)
| ((sample1<<14)&0b00000011110000000000000000000000)
| ((sample1<<13)&0b00000000000111100000000000000000)
| ((sample1<<12)&0b00000000000000001111000000000000)
| ((sample2>>15)&0b00000000000000000000000000000001)
;
nzrivalue = previousnrzi_highlow ^ (LookupTable_firstword[(byte)(value >> 24)] ^ LookupTable_secondword[(byte)(value >> 16)] ^ LookupTable_thirdword[(byte)(value >> 8)] ^ LookupTable_fourthword[(byte)value]);
*(dest+0) = nzrivalue;
previousnrzi_highlow = ((nzrivalue & 0b1) == 0b1) ? ~0U : 0U;
value = 0b00010000100001000010000100001000 /* bit 32-63 */
// b00000000000000001000100010001000 // start of 16 bit sample
| ((sample2<<17)&0b11100000000000000000000000000000)
| ((sample2<<16)&0b00001111000000000000000000000000)
| ((sample2<<15)&0b00000000011110000000000000000000)
| ((sample2<<14)&0b00000000000000111100000000000000)
| ((sample3>>13)&0b00000000000000000000000000000111)
;
nzrivalue = previousnrzi_highlow ^ (LookupTable_firstword[(byte)(value >> 24)] ^ LookupTable_secondword[(byte)(value >> 16)] ^ LookupTable_thirdword[(byte)(value >> 8)] ^ LookupTable_fourthword[(byte)value]);
*(dest+1) = nzrivalue;
previousnrzi_highlow = ((nzrivalue & 0b1) == 0b1) ? ~0U : 0U;
value = 0b01000010000100001000010000100001 /* bit 64-95 */
// b00000000000000001000000000000000 // start of 16 bit sample
| ((sample3<<19)&0b10000000000000000000000000000000)
| ((sample3<<18)&0b00111100000000000000000000000000)
| ((sample3<<17)&0b00000001111000000000000000000000)
| ((sample3<<16)&0b00000000000011110000000000000000)
| ((sample4>>11)&0b00000000000000000000000000011110)
;
nzrivalue = previousnrzi_highlow ^ (LookupTable_firstword[(byte)(value >> 24)] ^ LookupTable_secondword[(byte)(value >> 16)] ^ LookupTable_thirdword[(byte)(value >> 8)] ^ LookupTable_fourthword[(byte)value]);
*(dest+2) = nzrivalue;
previousnrzi_highlow = ((nzrivalue & 0b1) == 0b1) ? ~0U : 0U;
value = 0b00001000010000100001000010000100 /* bit 96-127 */
// b00000000000000001000100010001000 // start of 16 bit sample
| ((sample4<<20)&0b11110000000000000000000000000000)
| ((sample4<<19)&0b00000111100000000000000000000000)
| ((sample4<<18)&0b00000000001111000000000000000000)
| ((sample5>>9 )&0b00000000000000000000000001111000)
| ((sample5>>10)&0b00000000000000000000000000000011)
;
nzrivalue = previousnrzi_highlow ^ (LookupTable_firstword[(byte)(value >> 24)] ^ LookupTable_secondword[(byte)(value >> 16)] ^ LookupTable_thirdword[(byte)(value >> 8)] ^ LookupTable_fourthword[(byte)value]);
*(dest+3) = nzrivalue;
previousnrzi_highlow = ((nzrivalue & 0b1) == 0b1) ? ~0U : 0U;
value = 0b00100001000010000100001000010000 /* bit 128-159 */
// b00000000000000001000100010001000 // start of 16 bit sample
| ((sample5<<22)&0b11000000000000000000000000000000)
| ((sample5<<21)&0b00011110000000000000000000000000)
| ((sample5<<20)&0b00000000111100000000000000000000)
| ((sample6>>7 )&0b00000000000000000000000111100000)
| ((sample6>>8 )&0b00000000000000000000000000001111)
;
nzrivalue = previousnrzi_highlow ^ (LookupTable_firstword[(byte)(value >> 24)] ^ LookupTable_secondword[(byte)(value >> 16)] ^ LookupTable_thirdword[(byte)(value >> 8)] ^ LookupTable_fourthword[(byte)value]);
*(dest+4) = nzrivalue;
previousnrzi_highlow = ((nzrivalue & 0b1) == 0b1) ? ~0U : 0U;
value = 0b10000100001000010000100001000010 /* bit 160-191 */
// b00000000000000001000100010001000 // start of 16 bit sample
| ((sample6<<23)&0b01111000000000000000000000000000)
| ((sample6<<22)&0b00000011110000000000000000000000)
| ((sample7>>5 )&0b00000000000000000000011110000000)
| ((sample7>>6 )&0b00000000000000000000000000111100)
| ((sample7>>7 )&0b00000000000000000000000000000001)
;
nzrivalue = previousnrzi_highlow ^ (LookupTable_firstword[(byte)(value >> 24)] ^ LookupTable_secondword[(byte)(value >> 16)] ^ LookupTable_thirdword[(byte)(value >> 8)] ^ LookupTable_fourthword[(byte)value]);
*(dest+5) = nzrivalue;
previousnrzi_highlow = ((nzrivalue & 0b1) == 0b1) ? ~0U : 0U;
value = 0b00010000100001000010000100001000 /* bit 192-223 */
// b00000000000000001000100010001000 // start of 16 bit sample
| ((sample7<<25)&0b11100000000000000000000000000000)
| ((sample7<<24)&0b00001111000000000000000000000000)
| ((sample8>>3 )&0b00000000000000000001111000000000)
| ((sample8>>4 )&0b00000000000000000000000011110000)
| ((sample8>>5 )&0b00000000000000000000000000000111)
;
nzrivalue = previousnrzi_highlow ^ (LookupTable_firstword[(byte)(value >> 24)] ^ LookupTable_secondword[(byte)(value >> 16)] ^ LookupTable_thirdword[(byte)(value >> 8)] ^ LookupTable_fourthword[(byte)value]);
*(dest+6) = nzrivalue;
previousnrzi_highlow = ((nzrivalue & 0b1) == 0b1) ? ~0U : 0U;
value = 0b01000010000100001000000000010000 /* bit 224-255 */
// b00000000000000001000100010001000 // start of 16 bit sample
| ((sample8<<27)&0b10000000000000000000000000000000)
| ((sample8<<26)&0b00111100000000000000000000000000)
;
nzrivalue = previousnrzi_highlow ^ (LookupTable_firstword[(byte)(value >> 24)] ^ LookupTable_secondword[(byte)(value >> 16)] ^ LookupTable_thirdword[(byte)(value >> 8)] ^ LookupTable_fourthword[(byte)value]);
*(dest+7) = nzrivalue;
previousnrzi_highlow = ((nzrivalue & 0b1) == 0b1) ? ~0U : 0U;
dest+=8;
} while (dest < end);
/*
block = AudioOutputADAT::block_ch1_1st;
if (block) {
offset = AudioOutputADAT::ch1_offset;
src = &block->data[offset];
do {
sample = (uint32_t)*src++;
} while (dest < end);
offset += AUDIO_BLOCK_SAMPLES/2;
if (offset < AUDIO_BLOCK_SAMPLES) {
AudioOutputADAT::ch1_offset = offset;
} else {
AudioOutputADAT::ch1_offset = 0;
AudioStream::release(block);
AudioOutputADAT::block_ch1_1st = AudioOutputADAT::block_ch1_2nd;
AudioOutputADAT::block_ch1_2nd = NULL;
}
} else {
sample = 0;
do {
// *(dest+0) = 0b11111000001111100000111110000011; // bit 0-31
// *(dest+1) = 0b11100000111110000011111000001111; // bit 32-63
// *(dest+2) = 0b10000011111000001111100000111110; // bit 64-95
// *(dest+3) = 0b00001111100000111110000011111000; // bit 96-127
// *(dest+4) = 0b00111110000011111000001111100000; // bit 128-159
// *(dest+5) = 0b11111000001111100000111110000011; // bit 160-191
// *(dest+6) = 0b11100000111110000011111000001111; // bit 192-223
// *(dest+7) = 0b10000011111000001111111111100000; // bit 224-255
dest+=8;
} while (dest < end);
}
dest -= AUDIO_BLOCK_SAMPLES * 8/2 - 8/2;
block = AudioOutputADAT::block_ch2_1st;
if (block) {
offset = AudioOutputADAT::ch2_offset;
src = &block->data[offset];
do {
sample = *src++;
// *(dest+0) = 0b00111110000011111000001111100000; // bit 128-159
// *(dest+1) = 0b11111000001111100000111110000011; // bit 160-191
// *(dest+2) = 0b11100000111110000011111000001111; // bit 192-223
// *(dest+3) = 0b10000011111000001111111111100000; // bit 224-255
dest+=8;
} while (dest < end);
offset += AUDIO_BLOCK_SAMPLES/2;
if (offset < AUDIO_BLOCK_SAMPLES) {
AudioOutputADAT::ch2_offset = offset;
} else {
AudioOutputADAT::ch2_offset = 0;
AudioStream::release(block);
AudioOutputADAT::block_ch2_1st = AudioOutputADAT::block_ch2_2nd;
AudioOutputADAT::block_ch2_2nd = NULL;
}
} else {
// *(dest+0) = 0b00111110000011111000001111100000; // bit 128-159
// *(dest+1) = 0b11111000001111100000111110000011; // bit 160-191
// *(dest+2) = 0b11100000111110000011111000001111; // bit 192-223
// *(dest+3) = 0b10000011111000001111111111100000; // bit 224-255
dest+=8;
}*/
if (block_ch1_1st) {
if (ch1_offset == 0) {
ch1_offset = AUDIO_BLOCK_SAMPLES/2;
} else {
ch1_offset = 0;
release(block_ch1_1st);
block_ch1_1st = block_ch1_2nd;
block_ch1_2nd = NULL;
}
}
if (block_ch2_1st) {
if (ch2_offset == 0) {
ch2_offset = AUDIO_BLOCK_SAMPLES/2;
} else {
ch2_offset = 0;
release(block_ch2_1st);
block_ch2_1st = block_ch2_2nd;
block_ch2_2nd = NULL;
}
}
if (block_ch3_1st) {
if (ch3_offset == 0) {
ch3_offset = AUDIO_BLOCK_SAMPLES/2;
} else {
ch3_offset = 0;
release(block_ch3_1st);
block_ch3_1st = block_ch3_2nd;
block_ch3_2nd = NULL;
}
}
if (block_ch4_1st) {
if (ch4_offset == 0) {
ch4_offset = AUDIO_BLOCK_SAMPLES/2;
} else {
ch4_offset = 0;
release(block_ch4_1st);
block_ch4_1st = block_ch4_2nd;
block_ch4_2nd = NULL;
}
}
if (block_ch5_1st) {
if (ch5_offset == 0) {
ch5_offset = AUDIO_BLOCK_SAMPLES/2;
} else {
ch5_offset = 0;
release(block_ch5_1st);
block_ch5_1st = block_ch5_2nd;
block_ch5_2nd = NULL;
}
}
if (block_ch6_1st) {
if (ch6_offset == 0) {
ch6_offset = AUDIO_BLOCK_SAMPLES/2;
} else {
ch6_offset = 0;
release(block_ch6_1st);
block_ch6_1st = block_ch6_2nd;
block_ch6_2nd = NULL;
}
}
if (block_ch7_1st) {
if (ch7_offset == 0) {
ch7_offset = AUDIO_BLOCK_SAMPLES/2;
} else {
ch7_offset = 0;
release(block_ch7_1st);
block_ch7_1st = block_ch7_2nd;
block_ch7_2nd = NULL;
}
}
if (block_ch8_1st) {
if (ch8_offset == 0) {
ch8_offset = AUDIO_BLOCK_SAMPLES/2;
} else {
ch8_offset = 0;
release(block_ch8_1st);
block_ch8_1st = block_ch8_2nd;
block_ch8_2nd = NULL;
}
}
}
void AudioOutputADAT::mute_PCM(const bool mute)
{
//vucp = mute?VUCP_INVALID:VUCP_VALID;
//#TODO
}
void AudioOutputADAT::update(void)
{
audio_block_t *block, *tmp;
block = receiveReadOnly(0); // input 0 = channel 1
if (block) {
__disable_irq();
if (block_ch1_1st == NULL) {
block_ch1_1st = block;
ch1_offset = 0;
__enable_irq();
} else if (block_ch1_2nd == NULL) {
block_ch1_2nd = block;
__enable_irq();
} else {
tmp = block_ch1_1st;
block_ch1_1st = block_ch1_2nd;
block_ch1_2nd = block;
ch1_offset = 0;
__enable_irq();
release(tmp);
}
}
block = receiveReadOnly(1); // input 1 = channel 2
if (block) {
__disable_irq();
if (block_ch2_1st == NULL) {
block_ch2_1st = block;
ch2_offset = 0;
__enable_irq();
} else if (block_ch2_2nd == NULL) {
block_ch2_2nd = block;
__enable_irq();
} else {
tmp = block_ch2_1st;
block_ch2_1st = block_ch2_2nd;
block_ch2_2nd = block;
ch2_offset = 0;
__enable_irq();
release(tmp);
}
}
block = receiveReadOnly(2); // channel 3
if (block) {
__disable_irq();
if (block_ch3_1st == NULL) {
block_ch3_1st = block;
ch3_offset = 0;
__enable_irq();
} else if (block_ch3_2nd == NULL) {
block_ch3_2nd = block;
__enable_irq();
} else {
tmp = block_ch3_1st;
block_ch3_1st = block_ch3_2nd;
block_ch3_2nd = block;
ch3_offset = 0;
__enable_irq();
release(tmp);
}
}
block = receiveReadOnly(3); // channel 4
if (block) {
__disable_irq();
if (block_ch4_1st == NULL) {
block_ch4_1st = block;
ch4_offset = 0;
__enable_irq();
} else if (block_ch4_2nd == NULL) {
block_ch4_2nd = block;
__enable_irq();
} else {
tmp = block_ch4_1st;
block_ch4_1st = block_ch4_2nd;
block_ch4_2nd = block;
ch4_offset = 0;
__enable_irq();
release(tmp);
}
}
block = receiveReadOnly(4); // channel 5
if (block) {
__disable_irq();
if (block_ch5_1st == NULL) {
block_ch5_1st = block;
ch5_offset = 0;
__enable_irq();
} else if (block_ch5_2nd == NULL) {
block_ch5_2nd = block;
__enable_irq();
} else {
tmp = block_ch5_1st;
block_ch5_1st = block_ch5_2nd;
block_ch5_2nd = block;
ch5_offset = 0;
__enable_irq();
release(tmp);
}
}
block = receiveReadOnly(5); // channel 6
if (block) {
__disable_irq();
if (block_ch6_1st == NULL) {
block_ch6_1st = block;
ch6_offset = 0;
__enable_irq();
} else if (block_ch6_2nd == NULL) {
block_ch6_2nd = block;
__enable_irq();
} else {
tmp = block_ch6_1st;
block_ch6_1st = block_ch6_2nd;
block_ch6_2nd = block;
ch6_offset = 0;
__enable_irq();
release(tmp);
}
}
block = receiveReadOnly(6); // channel 7
if (block) {
__disable_irq();
if (block_ch7_1st == NULL) {
block_ch7_1st = block;
ch7_offset = 0;
__enable_irq();
} else if (block_ch7_2nd == NULL) {
block_ch7_2nd = block;
__enable_irq();
} else {
tmp = block_ch7_1st;
block_ch7_1st = block_ch7_2nd;
block_ch7_2nd = block;
ch7_offset = 0;
__enable_irq();
release(tmp);
}
}
block = receiveReadOnly(7); // channel 8
if (block) {
__disable_irq();
if (block_ch8_1st == NULL) {
block_ch8_1st = block;
ch8_offset = 0;
__enable_irq();
} else if (block_ch8_2nd == NULL) {
block_ch8_2nd = block;
__enable_irq();
} else {
tmp = block_ch8_1st;
block_ch8_1st = block_ch8_2nd;
block_ch8_2nd = block;
ch8_offset = 0;
__enable_irq();
release(tmp);
}
}
}
#ifndef MCLK_SRC
#if F_CPU >= 20000000
#define MCLK_SRC 3 // the PLL
#else
#define MCLK_SRC 0 // system clock
#endif
#endif
void AudioOutputADAT::config_ADAT(void)
{
#if defined(KINETISK)
SIM_SCGC6 |= SIM_SCGC6_I2S;
SIM_SCGC7 |= SIM_SCGC7_DMA;
SIM_SCGC6 |= SIM_SCGC6_DMAMUX;
// 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
I2S0_TMR = 0;
I2S0_TCR1 = I2S_TCR1_TFW(1); // watermark
I2S0_TCR2 = I2S_TCR2_SYNC(0) | I2S_TCR2_MSEL(1) | I2S_TCR2_BCD | I2S_TCR2_DIV(0);
I2S0_TCR3 = I2S_TCR3_TCE;
//8 Words per Frame 32 Bit Word-Length -> 256 Bit Frame-Length, MSB First:
I2S0_TCR4 = I2S_TCR4_FRSZ(7) | I2S_TCR4_SYWD(0) | I2S_TCR4_MF | I2S_TCR4_FSP | I2S_TCR4_FSD;
I2S0_TCR5 = I2S_TCR5_WNW(31) | I2S_TCR5_W0W(31) | I2S_TCR5_FBT(31);
I2S0_RCSR = 0;
#if 0
// configure pin mux for 3 clock signals (debug only)
CORE_PIN23_CONFIG = PORT_PCR_MUX(6); // pin 23, PTC2, I2S0_TX_FS (LRCLK) 44.1kHz
CORE_PIN9_CONFIG = PORT_PCR_MUX(6); // pin 9, PTC3, I2S0_TX_BCLK 5.6 MHz
//CORE_PIN11_CONFIG = PORT_PCR_MUX(6); // pin 11, PTC6, I2S0_MCLK 11.43MHz
#endif
#elif defined(__IMXRT1052__) || defined(__IMXRT1062__)
CCM_CCGR5 |= CCM_CCGR5_SAI1(CCM_CCGR_ON);
//PLL:
int fs = AUDIO_SAMPLE_RATE_EXACT;
// PLL between 27*24 = 648MHz und 54*24=1296MHz
int n1 = 4; //SAI prescaler 4 => (n1*n2) = multiple of 4
int n2 = 1 + (24000000 * 27) / (fs * 256 * n1);
double C = ((double)fs * 256 * n1 * n2) / 24000000;
int c0 = C;
int c2 = 10000;
int c1 = C * c2 - (c0 * c2);
set_audioClock(c0, c1, c2);
CCM_CSCMR1 = (CCM_CSCMR1 & ~(CCM_CSCMR1_SAI1_CLK_SEL_MASK))
| CCM_CSCMR1_SAI1_CLK_SEL(2); // &0x03 // (0,1,2): PLL3PFD0, PLL5, PLL4
CCM_CS1CDR = (CCM_CS1CDR & ~(CCM_CS1CDR_SAI1_CLK_PRED_MASK | CCM_CS1CDR_SAI1_CLK_PODF_MASK))
| CCM_CS1CDR_SAI1_CLK_PRED(n1-1) // &0x07
| CCM_CS1CDR_SAI1_CLK_PODF(n2-1); // &0x3f
IOMUXC_GPR_GPR1 = (IOMUXC_GPR_GPR1 & ~(IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL_MASK))
| (IOMUXC_GPR_GPR1_SAI1_MCLK_DIR | IOMUXC_GPR_GPR1_SAI1_MCLK1_SEL(0)); //Select MCLK
int rsync = 0;
int tsync = 1;
// configure transmitter
I2S1_TMR = 0;
I2S1_TCR1 = I2S_TCR1_RFW(0); // watermark
I2S1_TCR2 = I2S_TCR2_SYNC(tsync) | I2S_TCR2_MSEL(1) | I2S_TCR2_BCD | I2S_TCR2_DIV(0);
I2S1_TCR3 = I2S_TCR3_TCE;
// fix..4 Words per Frame 32 Bit Word-Length -> 128 Bit Frame-Length, MSB First:
// i want.. 8 Words per Frame 32 Bit Word-Length -> 256 Bit Frame-Length, MSB First:
I2S1_TCR4 = I2S_TCR4_FRSZ(3) | I2S_TCR4_SYWD(0) | I2S_TCR4_MF | I2S_TCR4_FSP | I2S_TCR4_FSD;
I2S1_TCR5 = I2S_TCR5_WNW(31) | I2S_TCR5_W0W(31) | I2S_TCR5_FBT(31);
//I2S1_RCSR = 0;
I2S1_RMR = 0;
//I2S1_RCSR = (1<<25); //Reset
I2S1_RCR1 = I2S_RCR1_RFW(0);
I2S1_RCR2 = I2S_RCR2_SYNC(rsync) | I2S_TCR2_MSEL(1) | I2S_TCR2_BCD | I2S_TCR2_DIV(0);
I2S1_RCR3 = I2S_RCR3_RCE;
I2S1_RCR4 = I2S_TCR4_FRSZ(3) | I2S_TCR4_SYWD(0) | I2S_TCR4_MF | I2S_TCR4_FSP | I2S_TCR4_FSD;
I2S1_RCR5 = I2S_TCR5_WNW(31) | I2S_TCR5_W0W(31) | I2S_TCR5_FBT(31);
#if 0
//debug only:
CORE_PIN23_CONFIG = 3; //1:MCLK 11.43MHz
CORE_PIN21_CONFIG = 3; //1:RX_BCLK 5.6 MHz
CORE_PIN20_CONFIG = 3; //1:RX_SYNC 44.1 KHz
// CORE_PIN6_CONFIG = 3; //1:TX_DATA0
// CORE_PIN7_CONFIG = 3; //1:RX_DATA0
#endif
#endif
}
/*
https://forum.pjrc.com/threads/38753-Discussion-about-a-simple-way-to-change-the-sample-rate
*/
/*#if defined(KINETISK) //AAA this needs attentuion as im sure it will break KINETISK
void AudioOutputADAT::setI2SFreq(int freq) {
typedef struct {
uint8_t mult;
uint16_t div;
} tmclk;
const int numfreqs = 14;
const int samplefreqs[numfreqs] = { 8000, 11025, 16000, 22050, 32000, 44100, (int) 44117.64706 , 48000, 88200, (int) (44117.64706 * 2.0), 96000, 176400,(int) (44117.64706 * 4.0), 192000};
#if (F_PLL==16000000)
const tmclk clkArr[numfreqs] = {{16, 125}, {148, 839}, {32, 125}, {145, 411}, {64, 125}, {151, 214}, {12, 17}, {96, 125}, {151, 107}, {24, 17}, {192, 125}, {127, 45}, {48, 17}, {255, 83} };
#elif (F_PLL==72000000)
const tmclk clkArr[numfreqs] = {{32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {128, 1125}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375}, {249, 397}, {32, 51}, {185, 271} };
#elif (F_PLL==96000000)
const tmclk clkArr[numfreqs] = {{8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {32, 375}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125}, {151, 321}, {8, 17}, {64, 125} };
#elif (F_PLL==120000000)
const tmclk clkArr[numfreqs] = {{32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {128, 1875}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625}, {178, 473}, {32, 85}, {145, 354} };
#elif (F_PLL==144000000)
const tmclk clkArr[numfreqs] = {{16, 1125}, {49, 2500}, {32, 1125}, {49, 1250}, {64, 1125}, {49, 625}, {4, 51}, {32, 375}, {98, 625}, {8, 51}, {64, 375}, {196, 625}, {16, 51}, {128, 375} };
#elif (F_PLL==168000000)
const tmclk clkArr[numfreqs] = {{32, 2625}, {21, 1250}, {64, 2625}, {21, 625}, {128, 2625}, {42, 625}, {8, 119}, {64, 875}, {84, 625}, {16, 119}, {128, 875}, {168, 625}, {32, 119}, {189, 646} };
#elif (F_PLL==180000000)
const tmclk clkArr[numfreqs] = {{46, 4043}, {49, 3125}, {73, 3208}, {98, 3125}, {183, 4021}, {196, 3125}, {16, 255}, {128, 1875}, {107, 853}, {32, 255}, {219, 1604}, {214, 853}, {64, 255}, {219, 802} };
#elif (F_PLL==192000000)
const tmclk clkArr[numfreqs] = {{4, 375}, {37, 2517}, {8, 375}, {73, 2483}, {16, 375}, {147, 2500}, {1, 17}, {8, 125}, {147, 1250}, {2, 17}, {16, 125}, {147, 625}, {4, 17}, {32, 125} };
#elif (F_PLL==216000000)
const tmclk clkArr[numfreqs] = {{32, 3375}, {49, 3750}, {64, 3375}, {49, 1875}, {128, 3375}, {98, 1875}, {8, 153}, {64, 1125}, {196, 1875}, {16, 153}, {128, 1125}, {226, 1081}, {32, 153}, {147, 646} };
#elif (F_PLL==240000000)
const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
#elif (F_PLL==256000000)
// TODO: fix these...
const tmclk clkArr[numfreqs] = {{16, 1875}, {29, 2466}, {32, 1875}, {89, 3784}, {64, 1875}, {147, 3125}, {4, 85}, {32, 625}, {205, 2179}, {8, 85}, {64, 625}, {89, 473}, {16, 85}, {128, 625} };
#endif
for (int f = 0; f < numfreqs; f++) {
if ( freq == samplefreqs[f] ) {
while (I2S0_MCR & I2S_MCR_DUF) ;
I2S0_MDR = I2S_MDR_FRACT((clkArr[f].mult - 1)) | I2S_MDR_DIVIDE((clkArr[f].div - 1));
return;
}
}
} #endif */
#elif defined(KINETISL)
void AudioOutputADAT::update(void)
{
audio_block_t *block;
block = receiveReadOnly(0); // input 0 = ch1 channel
if (block) release(block);
block = receiveReadOnly(1); // input 1 = ch2 channel
if (block) release(block);
block = receiveReadOnly(2); // input 2 = ch3 channel
if (block) release(block);
block = receiveReadOnly(3); // input 3 = ch4 channel
if (block) release(block);
block = receiveReadOnly(4); // input 4 = ch5 channel
if (block) release(block);
block = receiveReadOnly(5); // input 5 = ch6 channel
if (block) release(block);
block = receiveReadOnly(6); // input 6 = ch7 channel
if (block) release(block);
block = receiveReadOnly(7); // input 7 = ch8 channel
if (block) release(block);
}
#endif
feel free to tell me if I am miles off the mark and waisting my time! -A