#include #include #include #include #include #include "xperipherals_adat.h" // 256-Bit ADAT Packet // // The packet structure below shows [Channel Number]:[Sample Bit Pos] for audio samples. // The 256-bit sequence is NRZI encoded when transmitting and NRZI decoded when receiving. // Samples are serialized MSB first (:00 represents MSB and :23 represents LSB) // // Note: Bit stuffing with 'ones' every fifth bit and NRZI encoding prevents long runs // of zeros. The zero's at the end of the frame are used for frame synchronization. // // 0 |one |0:00|0:01|0:02|0:03|one |0:04|0:05|0:06|0:07|one |0:08|0:09|0:10|0:11|one | // |0:12|0:13|0:14|0:15|one |0:16|0:17|0:18|0:19|one |0:20|0:21|0:22|0:23|one |1:00| // 1 |1:01|1:02|1:03|one |1:04|1:05|1:06|1:07|one |1:08|1:09|1:10|1:11|one |1:12|1:13| // |1:14|1:15|one |1:16|1:17|1:18|1:19|one |1:20|1:21|1:22|1:23|one |2:00|2:01|2:02| // 2 |2:03|one |2:04|2:05|2:06|2:07|one |2:08|2:09|2:10|2:11|one |2:12|2:13|2:14|2:15| // |one |2:16|2:17|2:18|2:19|one |2:20|2:21|2:22|2:23|one |3:00|3:01|3:02|3:03|one | // 3 |3:04|3:05|3:06|3:07|one |3:08|3:09|3:10|3:11|one |3:12|3:13|3:14|3:15|one |3:16| // |3:17|3:18|3:19|one |3:20|3:21|3:22|3:23|one |4:00|4:01|4:02|4:03|one |4:04|4:05| // 4 |4:06|4:07|one |4:08|4:09|4:10|4:11|one |4:12|4:13|4:14|4:15|one |4:16|4:17|4:18| // |4:19|one |4:20|4:21|4:22|4:23|one |5:00|5:01|5:02|5:03|one |5:04|5:05|5:06|5:07| // 5 |one |5:08|5:09|5:10|5:11|one |5:12|5:13|5:14|5:15|one |5:16|5:17|5:18|5:19|one | // |5:20|5:21|5:22|5:23|one |6:00|6:01|6:02|6:03|one |6:04|6:05|6:06|6:07|one |6:08| // 6 |6:09|6:10|6:11|one |6:12|6:13|6:14|6:15|one |6:16|6:17|6:18|6:19|one |6:20|6:21| // |6:22|6:23|one |7:00|7:01|7:02|7:03|one |7:04|7:05|7:06|7:07|one |7:08|7:09|7:10| // 7 |7:11|one |7:12|7:13|7:14|7:15|one |7:16|7:17|7:18|7:19|one |7:20|7:21|7:22|7:23| // |one |zero|zero|zero|zero|zero|zero|zero|zero|zero|zero|one |usr0|usr1|usr2|usr3| #ifdef XSTREAMM_IO__ADAT_TX_2 on tile[XPERIPHERALS_ADAT_TX_2__TILE_NUMBER] : out buffered port:32 _xperipherals_adat_tx_2__port_txd = XPERIPHERALS_ADAT_TX_2__TXD_PORT; static xuint _bclk_divider; static xuint _encode_lut1[256]; static xbyte _encode_lut2[256]; static xuint _enc_word; //static xuint _tx_carry; //static xuint _tx_stage; static xuint _slot_number; static xuint _step_number = 0; void xperipherals_adat_tx_2__initialize( xuint bclk_divider ) { _bclk_divider = bclk_divider; _enc_word = 0; //_tx_carry = 0; //_tx_stage = 0; _slot_number = 0; // bit clock frequency = 1 * ADAT bit rate = 12.288 / 11.2896 MHz for( int j = 0; j < 256; ++j ) { xuint carry = 0; xuint data = 0b1000010000 | ((j & 0xF0) << 1) | (j & 0x0F); _encode_lut1[j] = 0; for( int i = 0; i < 10; ++i, data <<= 1 ) { if( data & 0b1000000000 ) carry = !carry; _encode_lut1[j] = (_encode_lut1[j] << 1) | carry; } } // bit clock frequency = 2 * ADAT bit rate = 24.576 / 22.5792 MHz if( bclk_divider == 1 ) { for( int j = 0; j < 256; ++j ) { xuint x = _encode_lut1[j]; _encode_lut1[j] = 0; for( int i = 9; i >= 0; --i ) { if( x & (1 << i) ) _encode_lut1[j] |= 3 << (2*i); } } } // bit clock frequency = 4 * ADAT bit rate = 49.152 / 45.1584 MHz if( bclk_divider == 2 ) { for( int j = 0; j < 256; ++j ) { xuint x = _encode_lut1[j]; _encode_lut1[j] = _encode_lut2[j] = 0; for( int i = 9; i >= 8; --i ) { if( x & (1 << i) ) _encode_lut2[j] |= 15 << (4*(i-8)); } for( int i = 7; i >= 0; --i ) { if( x & (1 << i) ) _encode_lut1[j] |= 15 << (4*i); } //printf( "%05x %02x%08x\n", x, _encode_lut2[j], _encode_lut1[j] ); } } } void xperipherals_adat_tx_2__configure( clock bit_clock ) { configure_out_port_no_ready( _xperipherals_adat_tx_2__port_txd, bit_clock, 0 ); clearbuf( _xperipherals_adat_tx_2__port_txd ); _enc_word = 0; //_tx_carry = 0; //_tx_stage = 0; _slot_number = 0; } #if XPERIPHERALS_ADAT_TX_2__BCLK_SPEED == 1 static void _encode_data( xuint sample, xuint byte_num ) { int shift = 8 * (3 - byte_num); if( _enc_word & 1 ) _enc_word = ~_encode_lut1[255 & (sample >> shift)] & 0x3FF; else _enc_word = _encode_lut1[255 & (sample >> shift)] & 0x3FF; } #elif XPERIPHERALS_ADAT_TX_2__BCLK_SPEED == 2 static void _encode_data( xuint sample, xuint byte_num ) { int shift = 8 * (3 - byte_num); if( _enc_word & 1 ) _enc_word = ~_encode_lut1[255 & (sample >> shift)] & 0xFFFFF; else _enc_word = _encode_lut1[255 & (sample >> shift)] & 0xFFFFF; } #elif XPERIPHERALS_ADAT_TX_2__BCLK_SPEED == 3 static void _encode_data( xuint sample, xuint byte_num ) { } #endif // 0.42 usec + 0.34 usec * 7 = 2.8 usec // 2.7 usec #if XPERIPHERALS_ADAT_TX_2__BCLK_SPEED == 1 void xperipherals_adat_tx_2__transfer( xsint wordA, xsint wordB ) { xuint data; switch( _slot_number ) { // | 1 |0:0|0:0|0:0|0:0| 1 |0:0|0:0|0:0|0:0| 1 |0:1|0:1|0:1|0:1| 1 | // |0:1|0:1|0:1|0:1| 1 |0:2|0:2|0:2|0:2| 1 |0:2|0:2|0:2|0:2| 1 |1:0| case 0: _encode_data( wordA, 0 ); data = _enc_word << 22; _encode_data( wordA, 1 ); data |= _enc_word << 12; _encode_data( wordA, 2 ); data |= _enc_word << 2; _encode_data( wordB, 0 ); data |= _enc_word >> 8; break; // |1:0|1:0|1:0| 1 |1:0|1:0|1:0|1:0| 1 |1:1|1:1|1:1|1:1| 1 |1:1|1:1| // |1:1|1:1| 1 |1:2|1:2|1:2|1:2| 1 |1:2|1:2|1:2|1:2| 1 |2:0|2:0|2:0| case 1: /* Word from prev step */ data = _enc_word << 24; _encode_data( wordA, 1 ); data |= _enc_word << 14; _encode_data( wordA, 2 ); data |= _enc_word << 4; _encode_data( wordB, 0 ); data |= _enc_word >> 6; break; // |2:0| 1 |2:0|2:0|2:0|2:0| 1 |2:1|2:1|2:1|2:1| 1 |2:1|2:1|2:1|2:1| // | 1 |2:2|2:2|2:2|2:2| 1 |2:2|2:2|2:2|2:2| 1 |3:0|3:0|3:0|3:0| 1 | case 2: /* Word from prev step */ data = _enc_word << 26; _encode_data( wordA, 1 ); data |= _enc_word << 16; _encode_data( wordA, 2 ); data |= _enc_word << 6; _encode_data( wordB, 0 ); data |= _enc_word >> 4; break; // |3:0|3:0|3:0|3:0| 1 |3:1|3:1|3:1|3:1| 1 |3:1|3:1|3:1|3:1| 1 |3:2| // |3:2|3:2|3:2| 1 |3:2|3:2|3:2|3:2| 1 |4:0|4:0|4:0|4:0| 1 |4:0|4:0| case 3: /* Word from prev step */ data = _enc_word << 28; _encode_data( wordA, 1 ); data |= _enc_word << 18; _encode_data( wordA, 2 ); data |= _enc_word << 8; _encode_data( wordB, 0 ); data |= _enc_word >> 2; break; // |4:0|4:0| 1 |4:1|4:1|4:1|4:1| 1 |4:1|4:1|4:1|4:1| 1 |4:2|4:2|4:2| // |4:2| 1 |4:2|4:2|4:2|4:2| 1 |5:0|5:0|5:0|5:0| 1 |5:0|5:0|5:0|5:0| case 4: /* Word from prev step */ data = _enc_word << 30; _encode_data( wordA, 1 ); data |= _enc_word << 20; _encode_data( wordA, 2 ); data |= _enc_word << 10; _encode_data( wordB, 0 ); data |= _enc_word >> 0; break; // | 1 |5:1|5:1|5:1|5:1| 1 |5:1|5:1|5:1|5:1| 1 |5:2|5:2|5:2|5:2| 1 | // |5:2|5:2|5:2|5:2| 1 |6:0|6:0|6:0|6:0| 1 |6:0|6:0|6:0|6:0| 1 |6:1| case 5: _encode_data( wordA, 1 ); data = _enc_word << 22; _encode_data( wordA, 2 ); data |= _enc_word << 12; _encode_data( wordB, 0 ); data |= _enc_word << 2; _encode_data( wordB, 1 ); data |= _enc_word >> 8; break; // |6:1|6:1|6:1| 1 |6:1|6:1|6:1|6:1| 1 |6:2|6:2|6:2|6:2| 1 |6:2|6:2| // |6:2|6:2| 1 |7:0|7:0|7:0|7:0| 1 |7:0|7:0|7:0|7:0| 1 |7:1|7:1|7:1| case 6: /* Word from prev step */ data = _enc_word << 24; _encode_data( wordA, 2 ); data |= _enc_word << 14; _encode_data( wordB, 0 ); data |= _enc_word << 4; _encode_data( wordB, 1 ); data |= _enc_word >> 6; break; // |7:1| 1 |7:1|7:1|7:1|7:1| 1 |7:2|7:2|7:2|7:2| 1 |7:2|7:2|7:2|7:2| // | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |ub0|ub1|ub2|ub3| case 7: /* Word from prev step */ data = _enc_word << 26; _encode_data( wordA, 2 ); data |= _enc_word << 16; // TODO - encode user data rather than hard-coding zeros //if( _enc_word & 1 ) _tx_carry = data |= 0b0000000000011111; if( _enc_word & 1 ) data |= 0b0000000000011111; else _enc_word = data |= 0b1111111111100000; _enc_word = data; break; } _xperipherals_adat_tx_2__port_txd <: bitrev( data ); if( ++_slot_number == 8 ) _slot_number = 0; } #elif XPERIPHERALS_ADAT_TX_2__BCLK_SPEED == 2 void xperipherals_adat_tx_2__transfer_slot( xsint wordA, xsint wordB ) { switch( _slot_number ) { case 0: switch( _step_number ) { // | 1 | 1 |0:0|0:0|0:0|0:0|0:0|0:0|0:0|0:0| 1 | 1 |0:0|0:0|0:0|0:0| // |0:0|0:0|0:0|0:0| 1 | 1 |0:1|0:1|0:1|0:1|0:1|0:1|0:1|0:1| 1 | 1 | case 0: _encode_data( wordA, 0 ); data = _enc_word << 12; _encode_data( wordA, 1 ); data |= _enc_word >> 8; break; // |0:1|0:1|0:1|0:1|0:1|0:1|0:1|0:1| 1 | 1 |0:2|0:2|0:2|0:2|0:2|0:2| // |0:2|0:2| 1 | 1 |0:2|0:2|0:2|0:2|0:2|0:2|0:2|0:2| 1 | 1 |1:0|1:0| case 1: /* Word from prev step */ data = _enc_word << 24; _encode_data( wordA, 2 ); data |= _enc_word << 4; _encode_data( wordB, 0 ); data |= _enc_word >> 8; break; } break; case 1: switch( _step_number ) { // |1:0|1:0|1:0|1:0|1:0|1:0| 1 | 1 |1:0|1:0|1:0|1:0|1:0|1:0|1:0|1:0| // | 1 | 1 |1:1|1:1|1:1|1:1|1:1|1:1|1:1|1:1| 1 | 1 |1:1|1:1|1:1|1:1| case 1: /* Word from prev step */ data = _enc_word << 16; _encode_data( wordA, 1 ); data |= _enc_word >> 4; break; // |1:1|1:1|1:1|1:1| 1 | 1 |1:2|1:2|1:2|1:2|1:2|1:2|1:2|1:2| 1 | 1 | // |1:2|1:2|1:2|1:2|1:2|1:2|1:2|1:2| 1 | 1 |2:0|2:0|2:0|2:0|2:0|2:0| case 1: _encode_data( wordA, 1 ); data |= _enc_word << 28; _encode_data( wordB, 24 ); data |= _enc_word >> 6; break; } break; // |2:0| 1 |2:0|2:0|2:0|2:0| 1 |2:1|2:1|2:1|2:1| 1 |2:1|2:1|2:1|2:1| // | 1 |2:2|2:2|2:2|2:2| 1 |2:2|2:2|2:2|2:2| 1 |3:0|3:0|3:0|3:0| 1 | case 2: /* Word from prev step */ data = _enc_word << 26; _encode_data( wordA, 16 ); data |= _enc_word << 16; _encode_data( wordA, 8 ); data |= _enc_word << 6; _encode_data( wordB, 24 ); data |= _enc_word >> 4; break; // |3:0|3:0|3:0|3:0| 1 |3:1|3:1|3:1|3:1| 1 |3:1|3:1|3:1|3:1| 1 |3:2| // |3:2|3:2|3:2| 1 |3:2|3:2|3:2|3:2| 1 |4:0|4:0|4:0|4:0| 1 |4:0|4:0| case 3: /* Word from prev step */ data = _enc_word << 28; _encode_data( wordA, 16 ); data |= _enc_word << 18; _encode_data( wordA, 8 ); data |= _enc_word << 8; _encode_data( wordB, 24 ); data |= _enc_word >> 2; break; // |4:0|4:0| 1 |4:1|4:1|4:1|4:1| 1 |4:1|4:1|4:1|4:1| 1 |4:2|4:2|4:2| // |4:2| 1 |4:2|4:2|4:2|4:2| 1 |5:0|5:0|5:0|5:0| 1 |5:0|5:0|5:0|5:0| case 4: /* Word from prev step */ data = _enc_word << 30; _encode_data( wordA, 16 ); data |= _enc_word << 20; _encode_data( wordA, 8 ); data |= _enc_word << 10; _encode_data( wordB, 24 ); data |= _enc_word >> 0; break; // | 1 |5:1|5:1|5:1|5:1| 1 |5:1|5:1|5:1|5:1| 1 |5:2|5:2|5:2|5:2| 1 | // |5:2|5:2|5:2|5:2| 1 |6:0|6:0|6:0|6:0| 1 |6:0|6:0|6:0|6:0| 1 |6:1| case 5: _encode_data( wordA, 16 ); data = _enc_word << 22; _encode_data( wordA, 8 ); data |= _enc_word << 12; _encode_data( wordB, 24 ); data |= _enc_word << 2; _encode_data( wordB, 16 ); data |= _enc_word >> 8; break; // |6:1|6:1|6:1| 1 |6:1|6:1|6:1|6:1| 1 |6:2|6:2|6:2|6:2| 1 |6:2|6:2| // |6:2|6:2| 1 |7:0|7:0|7:0|7:0| 1 |7:0|7:0|7:0|7:0| 1 |7:1|7:1|7:1| case 6: /* Word from prev step */ data = _enc_word << 24; _encode_data( wordA, 8 ); data |= _enc_word << 14; _encode_data( wordB, 24 ); data |= _enc_word << 4; _encode_data( wordB, 16 ); data |= _enc_word >> 6; break; // |7:1| 1 |7:1|7:1|7:1|7:1| 1 |7:2|7:2|7:2|7:2| 1 |7:2|7:2|7:2|7:2| // | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |ub0|ub1|ub2|ub3| case 7: /* Word from prev step */ data = _enc_word << 26; _encode_data( wordA, 8 ); data |= _enc_word << 16; // TODO - encode user data rather than hard-coding zeros //if( _enc_word & 1 ) _tx_carry = data |= 0b0000000000011111; if( _enc_word & 1 ) data |= 0b0000000000011111; else _enc_word = data |= 0b1111111111100000; _enc_word = data; break; } _xperipherals_adat_tx_2__port_txd <: bitrev( data ); } #elif XPERIPHERALS_ADAT_TX_2__BCLK_SPEED == 4 #endif #endif