#include #include #include #include #include #include "xperipherals_spdif.h" #ifdef XPERIPHERALS_SPDIF_1 extern in port master_audio_clock_port; extern clock master_audio_clock_block; #if XPERIPHERALS_SPDIF_1__SUPPORT_TX on tile[XPERIPHERALS_SPDIF_1__TILE_NUMBER] : out buffered port:32 _xperipherals_spdif_1__tx_port = XPERIPHERALS_SPDIF_1__TXD_PORT; #endif #if XPERIPHERALS_SPDIF_1__SUPPORT_RX on tile[XPERIPHERALS_SPDIF_1__TILE_NUMBER] : in buffered port:32 _xperipherals_spdif_1__rx_port = XPERIPHERALS_SPDIF_1__RXD_PORT; #endif static xuint _xperipherals_spdif_1__frame = 0; static xuint _xperipherals_spdif_1__tx_flags = 0; static xuint _xperipherals_spdif_1__rx_flags = 0; #if XPERIPHERALS_SPDIF_1__SUPPORT_TX static xuint _xperipherals_spdif_1__tx_data = 0; #endif #if XPERIPHERALS_SPDIF_1__SUPPORT_RX static xuint _xperipherals_spdif_1__rx_data = 0; #endif static xuint _xperipherals_spdif_1__syncstate = 0; static xuint _xperipherals_spdif_1__synctime; #if XPERIPHERALS_SPDIF_1__SUPPORT_TX xuint _xperipherals_spdif_1__encode[2][16] = {{ 0b11001100, 0b11001101, 0b11001011, 0b11001010, 0b11010011, 0b11010010, 0b11010100, 0b11010101, 0b10110011, 0b10110010, 0b10110100, 0b10110101, 0b10101100, 0b10101101, 0b10101011, 0b10101010, },{ 0b00110011, 0b00110010, 0b00110100, 0b00110101, 0b00101100, 0b00101101, 0b00101011, 0b00101010, 0b01001100, 0b01001101, 0b01001011, 0b01001010, 0b01010011, 0b01010010, 0b01010100, 0b01010101, }}; #endif xuint _xperipherals_spdif_1__header_1 [2] = {0b11101000, 0b00010111}; xuint _xperipherals_spdif_1__header_N[2][2] = {{0b11100010, 0b00011101},{0b11100100,0b00011011}}; #if XPERIPHERALS_SPDIF_1__SUPPORT_RX xuint _xperipherals_spdif_1__decode[256] = { 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0111, 0b0110, 0b0100, 0b0101, 0b0000, 0b0000, 0b0000, 0b0000, 0b0001, 0b0000, 0b0010, 0b0011, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b1011, 0b1010, 0b1000, 0b1001, 0b0000, 0b0000, 0b0000, 0b0000, 0b1101, 0b1100, 0b1110, 0b1111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b1111, 0b1110, 0b1100, 0b1101, 0b0000, 0b0000, 0b0000, 0b0000, 0b1001, 0b1000, 0b1010, 0b1011, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0011, 0b0010, 0b0000, 0b0001, 0b0000, 0b0000, 0b0000, 0b0000, 0b0101, 0b0100, 0b0110, 0b0111, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, 0b0000, }; #endif xbyte _xperipherals_spdif_1__parity[256] = { 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1, 0,1,1,0,1,0,0,1, 1,0,0,1,0,1,1,0, 1,0,0,1,0,1,1,0, 0,1,1,0,1,0,0,1, }; xbool _xperipherals_spdif_1__calc_parity( xuint data ) { return _xperipherals_spdif_1__parity[ (xbyte)(data >> 24) ] ^ _xperipherals_spdif_1__parity[ (xbyte)(data >> 16) ] ^ _xperipherals_spdif_1__parity[ (xbyte)(data >> 8) ] ^ _xperipherals_spdif_1__parity[ (xbyte)(data >> 0) ]; } void XPERIPHERALS_spdif_1__initialize( void ) { _xperipherals_spdif_1__frame = 0; _xperipherals_spdif_1__syncstate = 1; } void XPERIPHERALS_spdif_1__configure( clock bit_clock ) { #if XPERIPHERALS_SPDIF_1__SUPPORT_TX configure_out_port_no_ready( _xperipherals_spdif_1__tx_port, bit_clock, 0 ); clearbuf( _xperipherals_spdif_1__tx_port ); #endif #if XPERIPHERALS_SPDIF_1__SUPPORT_RX configure_in_port_no_ready( _xperipherals_spdif_1__rx_port, bit_clock ); clearbuf( _xperipherals_spdif_1__rx_port ); #endif } #if XPERIPHERALS_SPDIF_1__SUPPORT_RX void XPERIPHERALS_spdif_1__synchronize( xuint phase ) { _xperipherals_spdif_1__syncstate = 0; return; if( _xperipherals_spdif_1__syncstate == 1 ) { _xperipherals_spdif_1__rx_port :> _xperipherals_spdif_1__rx_data @ _xperipherals_spdif_1__synctime; _xperipherals_spdif_1__synctime += 32; _xperipherals_spdif_1__syncstate++; } // Find a subframe - look for subrame header and skip one clock cycle per sub-frame // to account for headers on non 32-bit boundaries. else if( _xperipherals_spdif_1__syncstate == 2 ) { _xperipherals_spdif_1__rx_port :> _xperipherals_spdif_1__rx_data @ _xperipherals_spdif_1__synctime; _xperipherals_spdif_1__rx_data = bitrev( _xperipherals_spdif_1__rx_data ) >> 24; if( _xperipherals_spdif_1__rx_data == 0xE8 || _xperipherals_spdif_1__rx_data == 0xE2 || _xperipherals_spdif_1__rx_data == 0x17 || _xperipherals_spdif_1__rx_data == 0x1D ) { _xperipherals_spdif_1__synctime += 32; if( phase != 0 ) _xperipherals_spdif_1__synctime += 32; _xperipherals_spdif_1__syncstate = 3; } else if( _xperipherals_spdif_1__rx_data == 0xE4 || _xperipherals_spdif_1__rx_data == 0x1B ) { _xperipherals_spdif_1__synctime += 32; if( phase != 1 ) _xperipherals_spdif_1__synctime += 32; _xperipherals_spdif_1__syncstate = 3; } else _xperipherals_spdif_1__synctime += 33; } // Traverse sub-frames and synchronize to the first sub-frame (find sub-frame #1) else if( _xperipherals_spdif_1__syncstate == 3 ) { _xperipherals_spdif_1__rx_port :> _xperipherals_spdif_1__rx_data @ _xperipherals_spdif_1__synctime; _xperipherals_spdif_1__rx_data = bitrev( _xperipherals_spdif_1__rx_data ) >> 24; if( phase == 0 && (_xperipherals_spdif_1__rx_data == 0xE8 || _xperipherals_spdif_1__rx_data == 0x17) ) { asm("setpt res[%0], %1"::"r"(_xperipherals_spdif_1__rx_port),"r"(_xperipherals_spdif_1__synctime+32)); _xperipherals_spdif_1__syncstate = 0; } _xperipherals_spdif_1__synctime += 32; } } #endif // last=0, pre=B, word=000000000000 --> 11101000 11001100 11001100 11001100 = E8CCCCCC // pre=B, word=000000000000, f=0001 --> 11100100 11001100 11001100 11001101 = CCCCCCCD // last=1, pre=W, word=000000000000 --> 00011011 00110011 00110011 00110011 = 1B333333 // pre=W, word=000000000000, f=0001 --> 00110011 00110011 00110011 00110010 = 33333332 // last=0, pre=M, word=000000000000 --> 11100010 11001100 11001100 11001100 = E2CCCCCC // pre=M, word=000000000000, f=0001 --> 11100100 11001100 11001100 11001101 = CCCCCCCD // last=1, pre=W, word=000000000000 --> 00011011 00110011 00110011 00110011 = 1B333333 // pre=W, word=000000000000, f=0001 --> 00110011 00110011 00110011 00110010 = 33333332 // last=1, pre=B, word=000000000000 --> 00010111 00110011 00110011 00110011 = 17333333 // pre=B, word=000000000000, f=0001 --> 00110011 00110011 00110011 00110010 = 33333332 // last=0, pre=W, word=000000000000 --> 11100100 11001100 11001100 11001100 = E4CCCCCC // pre=W, word=000000000000, f=0001 --> 11001100 11001100 11001100 11001101 = CCCCCCCD // last=1, pre=M, word=000000000000 --> 00011101 00110011 00110011 00110011 = 1D333333 // pre=M, word=000000000000, f=0001 --> 00110011 00110011 00110011 00110010 = 33333332 // last=0, pre=W, word=000000000000 --> 11100100 11001100 11001100 11001100 = E4CCCCCC // pre=W, word=000000000000, f=0001 --> 11001100 11001100 11001100 11001101 = CCCCCCCD void _xperipherals_spdif_1__phase1_write( xuint tx_value ) { // Encode and transmit first 32-bit portion of BMC encoded 32-bit word #if XPERIPHERALS_SPDIF_1__SUPPORT_TX if( _xperipherals_spdif_1__frame == 0 ) _xperipherals_spdif_1__tx_data = _xperipherals_spdif_1__header_1[_xperipherals_spdif_1__tx_data & 1]; else _xperipherals_spdif_1__tx_data = _xperipherals_spdif_1__header_N[_xperipherals_spdif_1__frame & 1][_xperipherals_spdif_1__tx_data & 1]; _xperipherals_spdif_1__tx_data = (_xperipherals_spdif_1__tx_data << 24) + (_xperipherals_spdif_1__encode[_xperipherals_spdif_1__tx_data & 1][(tx_value >> 28) & 15] << 16) + (_xperipherals_spdif_1__encode[_xperipherals_spdif_1__tx_data & 1][(tx_value >> 24) & 15] << 8) + (_xperipherals_spdif_1__encode[_xperipherals_spdif_1__tx_data & 1][(tx_value >> 20) & 15] << 0); _xperipherals_spdif_1__tx_port <: bitrev( _xperipherals_spdif_1__tx_data ); printf( "%05i 1 %08X\n", _xperipherals_spdif_1__frame, _xperipherals_spdif_1__tx_data ); #endif } void _xperipherals_spdif_1__phase2_write( xuint tx_value ) { // Encode and transmit second 32-bit portion of BMC encoded 32-bit word #if XPERIPHERALS_SPDIF_1__SUPPORT_TX _xperipherals_spdif_1__tx_data = (_xperipherals_spdif_1__encode[_xperipherals_spdif_1__tx_data & 1][(tx_value >> 16) & 15] << 24) + (_xperipherals_spdif_1__encode[_xperipherals_spdif_1__tx_data & 1][(tx_value >> 12) & 15] << 16) + (_xperipherals_spdif_1__encode[_xperipherals_spdif_1__tx_data & 1][(tx_value >> 8) & 15] << 8) + (_xperipherals_spdif_1__encode[_xperipherals_spdif_1__tx_data & 1][(tx_value >> 0) & 15] << 0); _xperipherals_spdif_1__tx_port <: bitrev( _xperipherals_spdif_1__tx_data ); printf( "%05i 2 %08X\n", _xperipherals_spdif_1__frame, _xperipherals_spdif_1__tx_data ); #endif } void _xperipherals_spdif_1__phase1_read( xuint& rx_sample ) { // Receive and decode first 32-bit portion of BMC encoded 32-bit word #if XPERIPHERALS_SPDIF_1__SUPPORT_RX if( _xperipherals_spdif_1__syncstate < 3 ) XPERIPHERALS_spdif_1__synchronize( 0 ); else { _xperipherals_spdif_1__rx_port :> _xperipherals_spdif_1__rx_data; _xperipherals_spdif_1__rx_data = bitrev( _xperipherals_spdif_1__rx_data ); //if( (_xperipherals_spdif_1__rx_data >> 28) != 0xE && (_xperipherals_spdif_1__rx_data >> 28) != 0x1 ) { // _xperipherals_spdif_1__syncstate = 1; // return; //} rx_sample = (_xperipherals_spdif_1__decode[(_xperipherals_spdif_1__rx_data >> 16) & 255] << 28) + (_xperipherals_spdif_1__decode[(_xperipherals_spdif_1__rx_data >> 8) & 255] << 24) + (_xperipherals_spdif_1__decode[(_xperipherals_spdif_1__rx_data >> 0) & 255] << 20); } #endif } void _xperipherals_spdif_1__phase2_read( xuint& rx_sample ) { // Receive and decode second 32-bit portion of BMC encoded 32-bit word #if XPERIPHERALS_SPDIF_1__SUPPORT_RX if( _xperipherals_spdif_1__syncstate < 3 ) XPERIPHERALS_spdif_1__synchronize( 1 ); else { _xperipherals_spdif_1__rx_port :> _xperipherals_spdif_1__rx_data; _xperipherals_spdif_1__rx_data = bitrev( _xperipherals_spdif_1__rx_data ); rx_sample += (_xperipherals_spdif_1__decode[(_xperipherals_spdif_1__rx_data >> 24) & 255] << 16) + (_xperipherals_spdif_1__decode[(_xperipherals_spdif_1__rx_data >> 16) & 255] << 12) + (_xperipherals_spdif_1__decode[(_xperipherals_spdif_1__rx_data >> 8) & 255] << 8); } #endif } xuint _xperipherals_spdif_1__tx_value; xuint _xperipherals_spdif_1__rx_value; void XPERIPHERALS_spdif_1__transfer_beg( xsint tx_sample, xuint tx_data, xuint& rx_data ) { _xperipherals_spdif_1__tx_value = (tx_sample & ~15) | (tx_data & 15); _xperipherals_spdif_1__tx_flags = 1; _xperipherals_spdif_1__phase1_write( _xperipherals_spdif_1__tx_value ); _xperipherals_spdif_1__phase1_read( _xperipherals_spdif_1__rx_value ); } void XPERIPHERALS_spdif_1__transfer_end( xsint& rx_sample, xuint tx_data, xuint& rx_data ) { _xperipherals_spdif_1__phase2_write( _xperipherals_spdif_1__tx_value ); _xperipherals_spdif_1__phase2_read( _xperipherals_spdif_1__rx_value ); if( ++_xperipherals_spdif_1__frame == 384 ) _xperipherals_spdif_1__frame = 0; rx_sample = _xperipherals_spdif_1__rx_value & ~15; rx_data = _xperipherals_spdif_1__rx_value & 15; } #endif