diff --git a/app_example_rx/src/main.xc b/app_example_rx/src/main.xc index 3379f1d..9f75bb9 100644 --- a/app_example_rx/src/main.xc +++ b/app_example_rx/src/main.xc @@ -8,6 +8,7 @@ #include "SpdifReceive.h" buffered in port:4 oneBitPort = XS1_PORT_1F; +buffered in port:32 fourBitsPort = XS1_PORT_4D; clock clockblock = XS1_CLKBLK_1; //:: @@ -30,7 +31,10 @@ void handleSamples(streaming chanend c) { int main(void) { streaming chan c; par { - SpdifReceive(oneBitPort, c, 1, clockblock); + //------ Use one of these functions ------- + SpdifReceive(oneBitPort, c, 1, clockblock); + //SpdifReceive_port4_buf32(fourBitsPort, c, 1, clockblock); + //----------------------------------------- handleSamples(c); } return 0; diff --git a/app_example_tx/src/main.xc b/app_example_tx/src/main.xc index fee9fa5..0d44fa4 100644 --- a/app_example_tx/src/main.xc +++ b/app_example_tx/src/main.xc @@ -8,11 +8,13 @@ #include #include #include "SpdifTransmit.h" +#include "SpdifTransmit_4bitPort.h" #define SAMPLE_FREQUENCY_HZ 96000 #define MASTER_CLOCK_FREQUENCY_HZ 12288000 on stdcore[1] : buffered out port:32 oneBitPort = XS1_PORT_1K; +on stdcore[1] : buffered out port:32 fourBitsPort = XS1_PORT_4D; on stdcore[1] : in port masterClockPort = XS1_PORT_1L; on stdcore[1] : clock clockblock = XS1_CLKBLK_1; //:: @@ -106,6 +108,13 @@ void transmitSpdif(chanend c) { } //:: +//::spdif thread 2 +void transmitSpdif_4bitPort(chanend c) { + SpdifTransmitPortConfig_4bitPort(fourBitsPort, clockblock, masterClockPort); + SpdifTransmit_4bitPort(fourBitsPort, c); +} +//:: + //::data generation #define WAVE_LEN 512 void generate(chanend c) { @@ -139,7 +148,10 @@ void example(void) { chan c; setupPll(); par { - transmitSpdif(c); + //------- Use one of these functions ------- + transmitSpdif(c); + //transmitSpdif_4bitPort(c); + //------------------------------------------ generate(c); clockGen(); } diff --git a/module_spdif_rx/README.rst b/module_spdif_rx/README.rst index 93fa9b4..3e2135e 100644 --- a/module_spdif_rx/README.rst +++ b/module_spdif_rx/README.rst @@ -1,5 +1,5 @@ -module_spdif_tx +module_spdif_rx ================ :scope: General Use -:description: S/PDIF transmit module +:description: S/PDIF receive module diff --git a/module_spdif_rx/src/SpdifReceive.h b/module_spdif_rx/src/SpdifReceive.h index c9bf203..a55ff06 100644 --- a/module_spdif_rx/src/SpdifReceive.h +++ b/module_spdif_rx/src/SpdifReceive.h @@ -59,4 +59,20 @@ **/ void SpdifReceive(in buffered port:4 p, streaming chanend c, int initial_divider, clock clk); + +/** + * \param p S/PDIF input 4-bit port. This port must be 32-bit buffered, + * declared as ``in buffered port:32`` + * + * \param c channel to output samples to + * + * \param initial_divider initial divide for initial estimate of sample rate + * For a 100Mhz reference clock, use an initial divider + * of 1 for 192000, 2 for 96000/88200, and 4 for 48000/44100. + * + * \param clk clock block sourced from the 100 MHz reference clock. + * + **/ +void SpdifReceive_port4_buf32(in buffered port:32 p, streaming chanend c, int initial_divider, clock clk); + #endif // _SpdifReceive_h_ diff --git a/module_spdif_rx/src/SpdifReceive_port4_buf32.S b/module_spdif_rx/src/SpdifReceive_port4_buf32.S new file mode 100644 index 0000000..3d3e921 --- /dev/null +++ b/module_spdif_rx/src/SpdifReceive_port4_buf32.S @@ -0,0 +1,2236 @@ +// +// SpdifReceive_port4_buf32() receives S/PDIF stream from 4-bit port. +// Tested with 44100 and 48000 input sample freq. + +// Code limitations: +// 1. Code is suitable only for XCORE-200 processor because of using UNZIP assembler commands +// 2. Code assumes S/PDIF signal wire is connected to P4x0 port pin. +// For other wire connection edit READ function. + +#include + +.syntax architectural + +#define STACK 10 +.globl SpdifReceive_port4_buf32 +.type SpdifReceive_port4_buf32, @function +.linkset SpdifReceive_port4_buf32.nstackwords,STACK +.globl SpdifReceive_port4_buf32.nstackwords +.linkset SpdifReceive_port4_buf32.maxthreads,0 +.globl SpdifReceive_port4_buf32.maxthreads +.linkset SpdifReceive_port4_buf32.maxtimers,0 +.globl SpdifReceive_port4_buf32.maxtimers +.linkset SpdifReceive_port4_buf32.maxchanends,0 +.globl SpdifReceive_port4_buf32.maxchanends +.globl parseSpDifc_port4_buf32 +.linkset parseSpDifc_port4_buf32.nstackwords,0 +.globl parseSpDifc_port4_buf32.nstackwords + +.cc_top SpdifReceive_port4_buf32.func, SpdifReceive_port4_buf32 +SpdifReceive_port4_buf32_start: // Used for .size directive +BERROR: + STWSP lr, 8 + BLRF parseSpDifE + +parseSpDifTerminate: + INCT r11, r1 +#ifdef TEST +parseSpDifE: +#endif + CLRSR XS1_SR_EEBLE_MASK + CLRSR XS1_SR_FAST_MASK + EDU r1 + OR r0, r4, r4 + OR r1, r5, r5 + LDWSP r2, 8 + LDWSP r4, 1 + LDWSP r5, 2 + LDWSP r6, 3 + LDWSP r7, 4 + LDWSP r8, 5 + LDWSP r9, 6 + LDWSP r10, 7 + RETSP STACK + + + + // Parse SPDIF entry point + + // arguments: + // void SpdifReceive_port4_buf32( + // in buffered port:32 p r0 + // streaming chanend c r1 + // int initial_divider r2 + // clock clk r3 + // ); +.align 4 +SpdifReceive_port4_buf32: +#if defined(__XS2A__) +.issue_mode single + ENTSP_lu6 STACK +#else + ENTSP STACK +#endif + + //LDC r4, 0xf + //AND r4, r3, r4 + //BRFT r4, parseSpDifc_port4_buf32 + SETCI r3, 7 // XS1_SETC_RUNR_STOP + SETD r3, r2 + SETCLK r0, r3 + SETCI r3, 15 // XS1_SETC_RUNR_START +#ifdef INV + SETCI r0, 0x600F // invert +#endif + SETSR XS1_SR_FAST_MASK +parseSpDifc_port4_buf32: + + STWSP r4, 1 + STWSP r5, 2 + STWSP r6, 3 + STWSP r7, 4 + STWSP r8, 5 + STWSP r9, 6 + STWSP r10, 7 + CLRSR XS1_SR_EEBLE_MASK + EDU r1 +.syntax default + ldap r11, parseSpDifTerminate + setv res[r1], r11 +.syntax architectural + EEU r1 + SETSR XS1_SR_EEBLE_MASK + + BLRF startParsing + + // READ function + // 1) check flag, if flag is set go to 7) + // 3) pack bits -> get 8 data bits + // 4) save 4 high bits, set flag + // 5) prepare 4 lower bits for next processing + // 6) exit + // 7) load saved 4 high bits + // 8) prepare 4 high bits for next processing + // 9) clear flag + // 10) exit + +READ: + + LDC r4, 0x80 // r4 = 0x80 // load bitmask + AND r4, r2, r4 // r4 = r2 & r4 = r2 & 0x80 // check high/low bits flag + BRFT_ru6 r4, getHIGH //if (r4 != 0) jump getHIGH // if we have 4 high bits already - jump to getHIGH, else read new 32-bit data from port + + IN r2, r0 // r2 = data from port = 0b xxxH xxxG xxxF xxxE xxxD xxxC xxxB xxxA // read port + LDC r4, 0x1111 //r4 = 0x1111 = 0b 0000 0000 0000 0000 0001 0001 0001 0001 // prepare r4 + UNZIP r4, r2, 0 //r2 = 0b 0000 0000 0101 0101 xHxG xFxE xDxC xBxA // pack bits with step = 2^0 = 1 + UNZIP r4, r2, 0 //r2 = 0b xxxx xxxx xxxx xxxx 0000 1111 HGFE DCBA // pack bits with step = 2^0 = 1 again + LDC r4, 0xF //r4 = 0xF = 0b1111 // load bit mask for lower 4 bits + AND r4, r2, r4 //r4 = r2 & r4 = r2 & 0xF = 0bDCBA // save lower 4 bits in r4 + SHLI r4, r4, 1 //r4 = r4 << 1 = r4*2 = 0b 000D CBA0 // prepare jump address for next BLR*_lu10 command + SHRI r2, r2, 3 //r2 = r2 >> 3 = (r2 >> 4)*2 = 0b 000x xxxx xxxx xxxx xxx0 0001 111H GFED // save high 4 bits and high/low data part flag in r2 for processing in the next step + RETSP 0 // return + +getHIGH: + + LDC r4, 0x1E // r4 = 0x1E = 0b 0001 1110 // load bitmask + AND r4, r2, r4 // r4 = r2 & r4 = r2 & 0x1E = 0b 000H GFE0 (= 0b HGFE << 1) // prepare jump address for next BLR*_lu10 command + LDC r2, 0 // r2 = 0 // clear high/low bits flag + RETSP 0 // return + + // Entry points for slowing down and speeding up + +BFASTER: +#ifndef TEST + GETD r4, r3 + SHRI r4, r4, 1 + BRFT r4, setClock + BLRF startParsing +#endif +BSLOWER: +#ifndef TEST + GETD r4, r3 + SHLI r4, r4, 1 + LDC r6, 8 + LSU r10, r4, r6 + BRFT r10, setClock + LDC r4, 1 +setClock: + SETCI r3, 7 + SETD r3, r4 + SETCI r3, 15 +#endif + BLRF startParsing + + + +startParsing: + LDC r5, 0x5555 + LDC r6, 0x0 + LDC r7, 0x1 + LDC r8, 0x1A + LDC r9, 0x2 + LDC r10, 0x4 + LDC r11, 0x0 + BRFU startIt +#ifndef TEST +parseSpDifE: + LDC r5, 0x68 +#endif +startIt: + IN r4, r0 // dummy read from port + LDC r2, 0 // r2 = 0 + BLRB_lu10 READ + + BRU r4 + BLRF_lu10 L0000 + BLRF_lu10 L000 + BLRF_lu10 L00 + BLRF_lu10 L00 + BLRF_lu10 L0 + BLRF_lu10 L0 + BLRF_lu10 L0 + BLRF_lu10 L0 + BLRF_lu10 L1 + BLRF_lu10 L1 + BLRF_lu10 L1 + BLRF_lu10 L1 + BLRF_lu10 L11 + BLRF_lu10 L11 + BLRF_lu10 L111 + BLRF_lu10 L1111 + + + + +L11111_U: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000 + BLRF_lu10 L000 + BLRB_lu10 BERROR + BLRF_lu10 L00 + BLRF_lu10 L0_1 + BLRB_lu10 BERROR + BLRF_lu10 L0_1 + BLRF_lu10 L0 + BLRF_lu10 L0001 + BLRF_lu10 L001 + BLRB_lu10 BERROR + BLRF_lu10 L01 + BLRF_lu10 L0011 + BLRF_lu10 L011 + BLRF_lu10 L0111 + BLRB_lu10 BERROR + +.align 4 +.syntax default +L0111_CHOICE: + bt r6, L111_TZ +.syntax architectural +L0111_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L0111 +.align 4 +L0111_1: + LMUL r6,r5,r5,r7,r5,r7 +L0111: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0001_1 + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRB_lu10 BERROR + BLRF_lu10 L0011_1 + BLRB_lu10 BERROR + BLRB_lu10 L0111_1 + BLRB_lu10 BERROR + + +L11100_S: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L111_UY + BLRF_lu10 L1111_UZ + + +L111111_S: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRF_lu10 L000_TX + BLRB_lu10 BERROR + BLRF_lu10 L0_X + BLRF_lu10 L0_X + BLRF_lu10 L0_X + BLRF_lu10 L0_X + BLRB_lu10 BERROR + BLRF_lu10 L1_UX + BLRF_lu10 L1_UX + BLRB_lu10 BERROR + BLRF_lu10 L1_UX + BLRF_lu10 L11_UX + BLRF_lu10 L11_UX + BLRF_lu10 L111_UY + BLRB_lu10 BERROR + + +L111111_U: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000 + BLRF_lu10 L000 + BLRB_lu10 BERROR + BLRF_lu10 L00 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0_1 + BLRB_lu10 BERROR + BLRF_lu10 L0001 + BLRF_lu10 L001 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0011 + BLRF_lu10 L011 + BLRB_lu10 L0111 + BLRB_lu10 BERROR + + +L1111111_U: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000 + BLRF_lu10 L000 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0_1 + BLRB_lu10 BERROR + BLRF_lu10 L0001 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0011 + BLRB_lu10 BERROR + BLRB_lu10 L0111 + BLRB_lu10 BERROR + + +L00111: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0001_1 + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRB_lu10 BERROR + BLRF_lu10 L0011_1 + BLRB_lu10 BERROR + BLRB_lu10 L0111_1 + BLRB_lu10 BERROR + + +.align 4 +L0011_1: + LMUL r6,r5,r5,r7,r5,r7 + BRFU L0011 +.align 4 +L0011_0: + LMUL r6, r5, r11, r11, r5, r5 +L0011: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_1 + BLRF_lu10 L000_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0001_1 + BLRF_lu10 L001_1 + BLRB_lu10 BFASTER + BLRB_lu10 BERROR + BLRB_lu10 L0011_1 + BLRF_lu10 L011_1 + BLRB_lu10 L0111_1 + BLRB_lu10 BERROR + + +.align 4 +L1111_UY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L1111_U +.align 4 +L1111_UZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 +L1111_U: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000 + BLRF_lu10 L000 + BLRB_lu10 BERROR + BLRF_lu10 L00 + BLRF_lu10 L0_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0 + BLRF_lu10 L0001 + BLRF_lu10 L001 + BLRB_lu10 BERROR + BLRF_lu10 L01 + BLRB_lu10 L0011 + BLRF_lu10 L011 + BLRB_lu10 L0111 + BLRB_lu10 L1111111_U + + +L1111100_S: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRF_lu10 L000_Y + BLRF_lu10 L00_X + BLRF_lu10 L00_Y + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0_X + BLRF_lu10 L0_Y + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L01_Y + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L111_UX + BLRB_lu10 L1111_UY + +.align 4 +L011_CHOICE: +.syntax default + bt r6, L11_TZ +.syntax architectural +L011_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L011 +.align 4 +L011_1: + LMUL r6,r5,r5,r7,r5,r7 +L011: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_1 + BLRF_lu10 L000_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0001_1 + BLRF_lu10 L001_1 + BLRB_lu10 BFASTER + BLRB_lu10 BERROR + BLRB_lu10 L0011_1 + BLRB_lu10 L011_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + +.align 4 +L0001_CHOICE: +.syntax default + bt r6, L1_TZ +.syntax architectural +L0001_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L0001 +.align 4 +L0001_1: + LMUL r6,r5,r5,r7,r5,r7 +L0001: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_1 + BLRF_lu10 L000_1 + BLRB_lu10 BERROR + BLRF_lu10 L11100_0 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0_00 + BLRB_lu10 L0001_1 + BLRF_lu10 L001_1 + BLRB_lu10 BFASTER + BLRF_lu10 L1_01 + BLRB_lu10 L0011_1 + BLRB_lu10 L011_1 + BLRB_lu10 BERROR + BLRF_lu10 L11111_0 + +.align 4 +L001_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L001 +.align 4 +L001_1: + LMUL r6,r5,r5,r7,r5,r7 +L001: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_1 + BLRF_lu10 L000_1 + BLRB_lu10 BERROR + BLRF_lu10 L00_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L0001_1 + BLRB_lu10 L001_1 + BLRB_lu10 BFASTER + BLRF_lu10 L01_1 + BLRB_lu10 BERROR + BLRB_lu10 L011_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + + +.align 4 +L00011_0: + LMUL r6, r5, r11, r11, r5, r5 +L00011: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0_00 + BLRB_lu10 L0001_1 + BLRF_lu10 L1_01 + BLRB_lu10 BFASTER + BLRB_lu10 BERROR + BLRB_lu10 L0011_1 + BLRF_lu10 L11_01 + BLRB_lu10 L0111_1 + BLRF_lu10 L111111_0 + + .align 4 +L11111_0: + LMUL r6, r5, r11, r11, r5, r5 +L11111: +.syntax default + bt r6, L11111a +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_0 + BLRF_lu10 L000_0 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0_01 + BLRB_lu10 BERROR + BLRF_lu10 L0_01 + BLRB_lu10 BERROR + BLRB_lu10 L0001_0 + BLRB_lu10 L001_0 + BLRB_lu10 BFASTER + BLRB_lu10 BERROR + BLRB_lu10 L0011_0 + BLRB_lu10 L011_0 + BLRB_lu10 L0111_0 + BLRB_lu10 BSLOWER + + +L11000: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRF_lu10 L1000_1 + BLRB_lu10 BERROR + BLRF_lu10 L1100_1 + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRB_lu10 BERROR + BLRF_lu10 L1110_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L1111_1 + + +.align 4 +L111_UX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L111_U +.align 4 +L111_UY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L111_U +.align 4 +L111_UZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 +L111_U: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000 + BLRF_lu10 L000 + BLRB_lu10 BERROR + BLRF_lu10 L00 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0 + BLRB_lu10 L0001 + BLRB_lu10 L001 + BLRB_lu10 BERROR + BLRF_lu10 L01 + BLRB_lu10 L0011 + BLRB_lu10 L011 + BLRB_lu10 L0111 + BLRB_lu10 L1111111_U + + .align 4 +L00000_0: + LMUL r6, r5, r11, r11, r5, r5 +L00000: +.syntax default + bt r6, L00000a +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BSLOWER + BLRF_lu10 L1000_0 + BLRF_lu10 L100_0 + BLRF_lu10 L1100_0 + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRF_lu10 L110_0 + BLRF_lu10 L1110_0 + BLRB_lu10 BERROR + BLRF_lu10 L1_01 + BLRB_lu10 BERROR + BLRF_lu10 L1_01 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L111_0 + BLRF_lu10 L1111_0 + +.align 4 +L0_Y: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L0 +.align 4 +L0_X: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L0 +.align 4 +L0_01: + LMUL r6,r5,r5,r10,r7,r11 + BRFU L0 +.align 4 +L0_1: + LMUL r6,r5,r5,r7,r5,r7 + BRFU L0 +.align 4 +L0_00: + LMUL r6, r5, r11, r11, r5, r5 +L0_0: + LMUL r6, r5, r11, r11, r5, r5 +L0: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L00000 + BLRB_lu10 BERROR + BLRF_lu10 L00_1 + BLRF_lu10 L00_1 + BLRB_lu10 L0_1 + BLRB_lu10 BFASTER + BLRB_lu10 L0_1 + BLRB_lu10 L0_1 + BLRF_lu10 L1_0 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L00011 + BLRB_lu10 BERROR + BLRB_lu10 L00111 + BLRB_lu10 BERROR + + +.align 4 +L0000_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L0000 +.align 4 +L0000_1: + LMUL r6,r5,r5,r7,r5,r7 +L0000: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000000 + BLRF_lu10 L1000_0 + BLRF_lu10 L100_0 + BLRF_lu10 L1100_0 + BLRF_lu10 L10_CHOICE + BLRB_lu10 BFASTER + BLRF_lu10 L110_0 + BLRF_lu10 L1110_0 + BLRF_lu10 L1_S + BLRF_lu10 L1_01 + BLRB_lu10 BERROR + BLRF_lu10 L1_01 + BLRF_lu10 L11_S + BLRB_lu10 BFASTER + BLRF_lu10 L111_S + BLRF_lu10 L1111_0 + +.align 4 +L100_CHOICE: +.syntax default + bt r6, L00_TZ +.syntax architectural +L100_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L100 +.align 4 +L100_1: + LMUL r6,r5,r5,r7,r5,r7 +L100: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L100_1 + BLRF_lu10 L1100_1 + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRF_lu10 L110_1 + BLRF_lu10 L1110_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L111_1 + BLRF_lu10 L1111_1 + +.align 4 +L000_Y: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L000 +.align 4 +L000_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L000 +.align 4 +L000_1: + LMUL r6,r5,r5,r7,r5,r7 +L000: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000000 + BLRB_lu10 L000_1 + BLRB_lu10 L100_0 + BLRF_lu10 L00_1 + BLRF_lu10 L10_0 + BLRB_lu10 BFASTER + BLRF_lu10 L110_0 + BLRF_lu10 L1110_0 + BLRF_lu10 L1_S + BLRB_lu10 L001_1 + BLRB_lu10 BERROR + BLRF_lu10 L01_1 + BLRF_lu10 L11_S + BLRB_lu10 BFASTER + BLRF_lu10 L111_0 + BLRF_lu10 L1111_0 + + +.align 4 +L1100_1: + LMUL r6,r5,r5,r7,r5,r7 + BRFU L1100 +.align 4 +L1100_0: + LMUL r6, r5, r11, r11, r5, r5 +L1100: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRF_lu10 L1000_1 + BLRB_lu10 L100_1 + BLRB_lu10 L1100_1 + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRF_lu10 L110_1 + BLRF_lu10 L1110_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L111_1 + BLRF_lu10 L1111_1 + +.align 4 +L01_Y: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L01 +.align 4 +L01_CHOICE: +.syntax default + bt r6, L1_TZ +.syntax architectural +L01_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L01 +.align 4 +L01_1: + LMUL r6,r5,r5,r7,r5,r7 +L01: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRB_lu10 L000_1 + BLRB_lu10 BERROR + BLRF_lu10 L00_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L001_1 + BLRB_lu10 BFASTER + BLRB_lu10 L01_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + + +.align 4 +L000_TY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L000_T +.align 4 +L000_TZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 + BRFU L000_T +.align 4 +L000_TX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 +L000_T: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRB_lu10 L000 + BLRB_lu10 BERROR + BLRF_lu10 L00 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L0 + BLRB_lu10 BERROR + BLRB_lu10 L001 + BLRB_lu10 BERROR + BLRB_lu10 L01 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L111_U + BLRB_lu10 L1111_U + + +.align 4 +L1111_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L1111 +.align 4 +L1111_1: + LMUL r6,r5,r5,r7,r5,r7 +L1111: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_0 + BLRF_lu10 L000_S + BLRB_lu10 BFASTER + BLRF_lu10 L00_S + BLRB_lu10 L0_01 + BLRB_lu10 BERROR + BLRB_lu10 L0_01 + BLRF_lu10 L0_S + BLRB_lu10 L0001_0 + BLRB_lu10 L001_0 + BLRB_lu10 BFASTER + BLRB_lu10 L01_CHOICE + BLRB_lu10 L0011_0 + BLRB_lu10 L011_0 + BLRB_lu10 L0111_0 + BLRF_lu10 L1111111 + + +.align 4 +L11100_0: + LMUL r6, r5, r11, r11, r5, r5 +L11100: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L000000_0 + BLRF_lu10 L1000_1 + BLRF_lu10 L00_01 + BLRB_lu10 L1100_1 + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRB_lu10 L0_01 + BLRF_lu10 L1110_1 + BLRF_lu10 L1_00 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L1111_1 + + .align 4 +L000000_0: + LMUL r6, r5, r11, r11, r5, r5 +L000000: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BSLOWER + BLRF_lu10 L1000_CHOICE + BLRF_lu10 L00_TZ + BLRF_lu10 L00_TZ + BLRF_lu10 L0_TZ + BLRB_lu10 BFASTER + BLRF_lu10 L0_TZ + BLRF_lu10 L1110_CHOICE + BLRB_lu10 BSLOWER + BLRF_lu10 L1_UZ + BLRB_lu10 BERROR + BLRF_lu10 L1_UZ + BLRF_lu10 L11_S + BLRB_lu10 BERROR + BLRF_lu10 L111_S + BLRF_lu10 L1111_S + +.align 4 +L1110_CHOICE: +.syntax default + bt r6, L0_TZ +.syntax architectural +L1110_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L1110 +.align 4 +L1110_1: + LMUL r6,r5,r5,r7,r5,r7 +L1110: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L00000_0 + BLRB_lu10 BERROR + BLRB_lu10 L100_1 + BLRB_lu10 L1100_1 + BLRB_lu10 L0_01 + BLRB_lu10 BFASTER + BLRF_lu10 L110_1 + BLRB_lu10 L1110_1 + BLRF_lu10 L1_00 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L00011_0 + BLRB_lu10 BERROR + BLRF_lu10 L111_1 + BLRB_lu10 L1111_1 + +.align 4 +.syntax default +L1000_CHOICE: + bt r6, L000_TZ +.syntax architectural +L1000_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L1000 +.align 4 +L1000_1: + LMUL r6,r5,r5,r7,r5,r7 +L1000: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRB_lu10 L1000_1 + BLRB_lu10 BERROR + BLRB_lu10 L1100_1 + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRB_lu10 BERROR + BLRB_lu10 L1110_1 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L1111_1 + +.align 4 +L1_UY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L1_U +.align 4 +L1_UX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L1_U +.align 4 +L1_UZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 +L1_U: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000 + BLRB_lu10 L000 + BLRB_lu10 BERROR + BLRF_lu10 L00 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L0 + BLRB_lu10 L0001 + BLRB_lu10 L001 + BLRB_lu10 BERROR + BLRB_lu10 L01 + BLRB_lu10 L0011 + BLRB_lu10 L011 + BLRB_lu10 L0111 + BLRB_lu10 L11111_U + +.align 4 +L00_Y: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L00 +.align 4 +L00_X: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L00 +.align 4 +L00_0: + LMUL r6,r5,r11,r11,r5,r5 + BRFU L00 +.align 4 +L00_01: + LMUL r6,r5,r5,r10,r7,r11 + BRFU L00 +.align 4 +L00_1: + LMUL r6,r5,r5,r7,r5,r7 +L00: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L000000 + BLRB_lu10 L000_1 + BLRB_lu10 L00_1 + BLRB_lu10 L00_1 + BLRF_lu10 L10_0 + BLRB_lu10 BFASTER + BLRB_lu10 L0_1 + BLRB_lu10 L0_1 + BLRF_lu10 L1_S + BLRB_lu10 BERROR + BLRB_lu10 BFASTER + BLRB_lu10 L01_1 + BLRF_lu10 L11_0 + BLRB_lu10 BERROR + BLRF_lu10 L111_0 + BLRB_lu10 BERROR + +.align 4 +L1_S: +.syntax default + bf r6, L1_0 +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRB_lu10 L000_TZ + BLRB_lu10 BERROR + BLRB_lu10 L11100_S + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRF_lu10 L0_TY + BLRB_lu10 L1_UZ + BLRB_lu10 L1_UZ + BLRB_lu10 BERROR + BLRB_lu10 L1_UZ + BLRF_lu10 L11_UZ + BLRF_lu10 L11_UZ + BLRB_lu10 BERROR + BLRF_lu10 L11111_S + + +.align 4 +L11_UX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L11_U +.align 4 +L11_UY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L11_U +.align 4 +L11_UZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 +L11_U: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000 + BLRB_lu10 L000 + BLRB_lu10 BERROR + BLRB_lu10 L00 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L0 + BLRB_lu10 L0001 + BLRB_lu10 L001 + BLRB_lu10 BERROR + BLRB_lu10 L01 + BLRB_lu10 L0011 + BLRB_lu10 L011 + BLRB_lu10 L0111 + BLRB_lu10 L111111_U + + +.align 4 +L0_TZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 + BRFU L0_T +.align 4 +L0_TX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L0_T +.align 4 +L0_TY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 +L0_T: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRB_lu10 L000 + BLRB_lu10 L00 + BLRB_lu10 L00 + BLRB_lu10 L0 + BLRB_lu10 BERROR + BLRB_lu10 L0 + BLRB_lu10 L0 + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L11_U + BLRB_lu10 BERROR + BLRB_lu10 L111_U + BLRB_lu10 L1111_U + + +L111110_S: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 BERROR + BLRB_lu10 L000_Y + BLRB_lu10 L00_Y + BLRB_lu10 L00_Y + BLRB_lu10 L0_X + BLRB_lu10 BERROR + BLRB_lu10 L0_Y + BLRB_lu10 L0_Y + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 BERROR + BLRB_lu10 L11_UX + BLRB_lu10 BERROR + BLRB_lu10 L111_UY + BLRB_lu10 L1111_UY + +.align 4 +L11_S: +.syntax default + bf r6, L11_0 +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000_TY + BLRF_lu10 FERROR + BLRF_lu10 L00_TY + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L111110_S + BLRB_lu10 L1_UZ + BLRB_lu10 L1_UZ + BLRF_lu10 FERROR + BLRB_lu10 L1_UY + BLRB_lu10 L11_UZ + BLRB_lu10 L11_UZ + BLRB_lu10 L111_UZ + BLRB_lu10 L111111_S + + .align 4 +L111111_0: + LMUL r6, r5, r11, r11, r5, r5 +L111111: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_S + BLRF_lu10 L000_S + BLRF_lu10 FERROR + BLRF_lu10 L00_S + BLRF_lu10 L0_UZ + BLRF_lu10 FERROR + BLRF_lu10 L0_UZ + BLRF_lu10 FSLOWER + BLRB_lu10 L0001_CHOICE + BLRF_lu10 L1_TZ + BLRF_lu10 FFASTER + BLRF_lu10 L1_TZ + BLRF_lu10 L11_TZ + BLRF_lu10 L11_TZ + BLRB_lu10 L0111_CHOICE + BLRF_lu10 FSLOWER + +.align 4 +L111_S: +.syntax default + bf r6, L111_0 +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000_TY + BLRF_lu10 FERROR + BLRB_lu10 L1111100_S + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0_TX + BLRB_lu10 L1_UY + BLRB_lu10 L1_UY + BLRF_lu10 FERROR + BLRB_lu10 L1_UY + BLRB_lu10 L11_UZ + BLRB_lu10 L11_UY + BLRB_lu10 L111_UZ + BLRF_lu10 L1111111_S + + +L000000_U: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L1000 + BLRB_lu10 L100 + BLRB_lu10 L1100 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 L110 + BLRB_lu10 L1110 + BLRF_lu10 FERROR + BLRF_lu10 L1_1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 L11 + BLRF_lu10 FERROR + BLRF_lu10 L111 + BLRB_lu10 L1111 + +.align 4 +L1111_S: +.syntax default + bf r6, L1111_0 +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L000_TY + BLRB_lu10 L000_TX + BLRF_lu10 FERROR + BLRF_lu10 L00_TX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0_TX + BLRB_lu10 L1_UY + BLRB_lu10 L1_UY + BLRF_lu10 FERROR + BLRB_lu10 L1_UY + BLRB_lu10 L11_UY + BLRB_lu10 L11_UY + BLRB_lu10 L111_UY + BLRF_lu10 L1111111_S + + +L00000_U: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L1000 + BLRB_lu10 L100 + BLRB_lu10 L1100 + BLRF_lu10 L10 + BLRF_lu10 FERROR + BLRF_lu10 L110 + BLRB_lu10 L1110 + BLRF_lu10 L1 + BLRF_lu10 L1_1 + BLRF_lu10 FERROR + BLRF_lu10 L1_1 + BLRF_lu10 L11 + BLRF_lu10 FERROR + BLRF_lu10 L111 + BLRB_lu10 L1111 + + +L11111_S: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000_TX + BLRF_lu10 FERROR + BLRF_lu10 L00_TX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0_TX + BLRB_lu10 L1_UX + BLRB_lu10 L1_UX + BLRF_lu10 FERROR + BLRB_lu10 L1_UX + BLRB_lu10 L11_UY + BLRB_lu10 L11_UY + BLRB_lu10 L111_UY + BLRF_lu10 FERROR + + +.align 4 +L00_TY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L00_T +.align 4 +L00_TZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 + BRFU L00_T +.align 4 +L00_TX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 +L00_T: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000 + BLRB_lu10 L00 + BLRB_lu10 L00 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0 + BLRB_lu10 L0 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L01 + BLRB_lu10 L11_U + BLRF_lu10 FERROR + BLRB_lu10 L111_U + BLRB_lu10 L1111_U + +.align 4 +L110_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L110 +.align 4 +L110_1: + LMUL r6,r5,r5,r7,r5,r7 +L110: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L100_1 + BLRF_lu10 FERROR + BLRF_lu10 L10_1 + BLRF_lu10 FFASTER + BLRB_lu10 L110_1 + BLRB_lu10 L1110_1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 L11_1 + BLRF_lu10 FERROR + BLRF_lu10 L111_1 + BLRB_lu10 L1111_1 + +.align 4 +L111_Y: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L111 +.align 4 +L111_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L111 +.align 4 +L111_1: + LMUL r6,r5,r5,r7,r5,r7 +L111: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_0 + BLRB_lu10 L000_0 + BLRF_lu10 FFASTER + BLRF_lu10 L00_S + BLRF_lu10 L10_1 + BLRF_lu10 FERROR + BLRB_lu10 L110_1 + BLRF_lu10 L0_S + BLRB_lu10 L0001_0 + BLRB_lu10 L001_0 + BLRF_lu10 FFASTER + BLRB_lu10 L01_0 + BLRF_lu10 L11_1 + BLRB_lu10 L011_0 + BLRB_lu10 L111_1 + BLRF_lu10 L1111111 + + +L1111111_S: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0_X + BLRF_lu10 FERROR + BLRB_lu10 L0_X + BLRF_lu10 FERROR + BLRB_lu10 L1_UX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11_UX + BLRB_lu10 L11_UX + BLRB_lu10 L111_UX + BLRF_lu10 FERROR + +.align 4 +L1_Y: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L1 +.align 4 +L1_X: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L1 +.align 4 +L1_01: + LMUL r6,r5,r5,r10,r7,r11 + BRFU L1 +.align 4 +L1_1: + LMUL r6,r5,r5,r7,r5,r7 + BRFU L1 +.align 4 +L1_00: + LMUL r6, r5, r11, r11, r5, r5 +L1_0: + LMUL r6, r5, r11, r11, r5, r5 +L1: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L11000 + BLRF_lu10 FERROR + BLRB_lu10 L11100 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0_0 + BLRB_lu10 L1_1 + BLRB_lu10 L1_1 + BLRF_lu10 FFASTER + BLRB_lu10 L1_1 + BLRF_lu10 L11_1 + BLRF_lu10 L11_1 + BLRF_lu10 FERROR + BLRB_lu10 L11111 + + +L0000000_U: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L1000 + BLRF_lu10 FERROR + BLRB_lu10 L1100 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L1110 + BLRF_lu10 FERROR + BLRB_lu10 L1_1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L111 + BLRB_lu10 L1111 + +.align 4 +L11_Y: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L11 +.align 4 +L11_X: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L11 +.align 4 +L11_0: + LMUL r6,r5,r11,r11,r5,r5 + BRFU L11 +.align 4 +L11_01: + LMUL r6,r5,r5,r10,r7,r11 + BRFU L11 +.align 4 +L11_1: + LMUL r6,r5,r5,r7,r5,r7 +L11: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000_0 + BLRF_lu10 FERROR + BLRB_lu10 L00_0 + BLRF_lu10 L10_1 + BLRF_lu10 FFASTER + BLRF_lu10 FERROR + BLRF_lu10 L0_S + BLRB_lu10 L1_1 + BLRB_lu10 L1_1 + BLRF_lu10 FFASTER + BLRB_lu10 L01_0 + BLRB_lu10 L11_1 + BLRB_lu10 L11_1 + BLRB_lu10 L111_1 + BLRB_lu10 L111111 + +.align 4 +L0_UY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L0_U +.align 4 +L0_UX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L0_U +.align 4 +L0_UZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 +L0_U: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L00000_U + BLRB_lu10 L1000 + BLRB_lu10 L100 + BLRB_lu10 L1100 + BLRF_lu10 L10 + BLRF_lu10 FERROR + BLRB_lu10 L110 + BLRB_lu10 L1110 + BLRB_lu10 L1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11 + BLRF_lu10 FERROR + BLRB_lu10 L111 + BLRB_lu10 L1111 + + +.align 4 +L00_UX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L00_U +.align 4 +L00_UY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L00_U +.align 4 +L00_UZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 +L00_U: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L000000_U + BLRB_lu10 L1000 + BLRB_lu10 L100 + BLRB_lu10 L1100 + BLRF_lu10 L10 + BLRF_lu10 FERROR + BLRB_lu10 L110 + BLRB_lu10 L1110 + BLRB_lu10 L1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11 + BLRF_lu10 FERROR + BLRB_lu10 L111 + BLRB_lu10 L1111 + +.align 4 +L10_Y: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L10 +.align 4 +L10_CHOICE: +.syntax default + bt r6, L0_TZ +.syntax architectural +L10_0: + LMUL r6, r5, r11, r11, r5, r5 + BRFU L10 +.align 4 +L10_1: + LMUL r6,r5,r5,r7,r5,r7 +L10: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L10_1 + BLRF_lu10 FFASTER + BLRB_lu10 L110_1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11_1 + BLRF_lu10 FERROR + BLRB_lu10 L111_1 + BLRF_lu10 FERROR + + +.align 4 +L000_UX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L000_U +.align 4 +L000_UY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L000_U +.align 4 +L000_UZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 +L000_U: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000000_U + BLRB_lu10 L1000 + BLRB_lu10 L100 + BLRB_lu10 L1100 + BLRB_lu10 L10 + BLRF_lu10 FERROR + BLRB_lu10 L110 + BLRB_lu10 L1110 + BLRB_lu10 L1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11 + BLRF_lu10 FERROR + BLRB_lu10 L111 + BLRB_lu10 L1111 + + +L0000000: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FSLOWER + BLRB_lu10 L000_TZ + BLRB_lu10 L00_TZ + BLRB_lu10 L00_TZ + BLRF_lu10 FERROR + BLRF_lu10 FFASTER + BLRF_lu10 FERROR + BLRB_lu10 L0_TY + BLRF_lu10 FSLOWER + BLRB_lu10 L1_UZ + BLRF_lu10 FERROR + BLRB_lu10 L1_UZ + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L111_S + BLRB_lu10 L1111_S + + +.align 4 +L0000_UY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L0000_U +.align 4 +L0000_UZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 +L0000_U: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000000_U + BLRB_lu10 L1000 + BLRB_lu10 L100 + BLRB_lu10 L1100 + BLRB_lu10 L10 + BLRF_lu10 FERROR + BLRB_lu10 L110 + BLRB_lu10 L1110 + BLRB_lu10 L1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L1_1 + BLRB_lu10 L11 + BLRF_lu10 FERROR + BLRB_lu10 L111 + BLRB_lu10 L1111 + +.align 4 +L0_S: +.syntax default + bf r6, L0_0 +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L00000_S + BLRF_lu10 FERROR + BLRB_lu10 L00_UZ + BLRB_lu10 L00_UZ + BLRB_lu10 L0_UZ + BLRF_lu10 FERROR + BLRB_lu10 L0_UZ + BLRB_lu10 L0_UZ + BLRF_lu10 L1_TY + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 L00011_S + BLRF_lu10 FERROR + BLRF_lu10 L111_TZ + BLRF_lu10 FERROR + +.align 4 +L000_S: +.syntax default + bf r6, L000_0 +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000000_S + BLRB_lu10 L000_UZ + BLRB_lu10 L00_UY + BLRB_lu10 L00_UZ + BLRB_lu10 L0_UY + BLRF_lu10 FERROR + BLRB_lu10 L0_UY + BLRB_lu10 L0_UY + BLRF_lu10 L1_TX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 L0000011_S + BLRF_lu10 FERROR + BLRF_lu10 L111_TY + BLRF_lu10 FERROR + +.align 4 +L00_S: +.syntax default + bf r6, L00_0 +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L000000_S + BLRB_lu10 L000_UZ + BLRB_lu10 L00_UZ + BLRB_lu10 L00_UZ + BLRB_lu10 L0_UY + BLRF_lu10 FERROR + BLRB_lu10 L0_UZ + BLRB_lu10 L0_UZ + BLRF_lu10 L000001_S + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 L11_TY + BLRF_lu10 FERROR + BLRF_lu10 L111_TY + BLRF_lu10 FERROR + + +.align 4 +L111_TY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L111_T +.align 4 +L111_TZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 + BRFU L111_T +.align 4 +L111_TX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 +L111_T: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_U + BLRB_lu10 L000_U + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L10 + BLRF_lu10 FERROR + BLRB_lu10 L110 + BLRF_lu10 FERROR + BLRB_lu10 L1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11 + BLRF_lu10 FERROR + BLRB_lu10 L111 + BLRF_lu10 FERROR + + +L00000a: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000_TZ + BLRB_lu10 L00_TZ + BLRB_lu10 L00_TZ + BLRB_lu10 L0_TZ + BLRF_lu10 FFASTER + BLRB_lu10 L0_TZ + BLRB_lu10 L0_TZ + BLRB_lu10 L1_S + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11_S + BLRF_lu10 FERROR + BLRB_lu10 L111_S + BLRB_lu10 L1111_S + + +L1111111: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000_S + BLRB_lu10 L000_S + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0_UZ + BLRF_lu10 FERROR + BLRB_lu10 L0_UZ + BLRF_lu10 FSLOWER + BLRF_lu10 L1_TY + BLRF_lu10 FERROR + BLRF_lu10 FFASTER + BLRF_lu10 FERROR + BLRF_lu10 L11_TZ + BLRF_lu10 L11_TZ + BLRB_lu10 L111_TZ + BLRF_lu10 FSLOWER + + +.align 4 +L1_TZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 + BRFU L1_T +.align 4 +L1_TX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 + BRFU L1_T +.align 4 +L1_TY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 +L1_T: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_U + BLRB_lu10 L000_U + BLRF_lu10 FERROR + BLRB_lu10 L00_U + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L1 + BLRB_lu10 L1 + BLRF_lu10 FERROR + BLRB_lu10 L1 + BLRB_lu10 L11 + BLRB_lu10 L11 + BLRB_lu10 L111 + BLRF_lu10 FERROR + + +L000000_S: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000_UY + BLRB_lu10 L00_UX + BLRB_lu10 L00_UX + BLRB_lu10 L0_UX + BLRF_lu10 FERROR + BLRB_lu10 L0_UX + BLRB_lu10 L0_UX + BLRF_lu10 FERROR + BLRB_lu10 L1_X + BLRB_lu10 L1_X + BLRB_lu10 L1_X + BLRB_lu10 L1_X + BLRF_lu10 FERROR + BLRB_lu10 L111_TX + BLRF_lu10 FERROR + + +.align 4 +L11_TY: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r11,r11 + BRFU L11_T +.align 4 +L11_TZ: + BITREV r5, r5 + OUT r1,r5 + LADD r5,r6,r8,r9,r11 + BRFU L11_T +.align 4 +L11_TX: + BITREV r5, r5 + OUT r1,r5 + LSUB r5,r6,r8,r7,r11 +L11_T: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_U + BLRB_lu10 L000_U + BLRF_lu10 FERROR + BLRB_lu10 L00_U + BLRB_lu10 L10 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L1 + BLRB_lu10 L1 + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11 + BLRB_lu10 L11 + BLRB_lu10 L111 + BLRF_lu10 FERROR + + +L00000_S: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000_UY + BLRB_lu10 L00_UY + BLRB_lu10 L00_UY + BLRB_lu10 L0_UX + BLRF_lu10 FERROR + BLRB_lu10 L0_UX + BLRB_lu10 L0_UX + BLRB_lu10 L1_TX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11_TX + BLRF_lu10 FERROR + BLRB_lu10 L111_TX + BLRF_lu10 FERROR + +.align 4 +L0000_S: +.syntax default + bf r6, L0000_0 +.syntax architectural + BLRB_lu10 READ + BRU r4 + BLRF_lu10 L0000000_S + BLRB_lu10 L000_UY + BLRB_lu10 L00_UY + BLRB_lu10 L00_UY + BLRB_lu10 L0_UY + BLRF_lu10 FERROR + BLRB_lu10 L0_UY + BLRB_lu10 L0_UY + BLRB_lu10 L1_TX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11_TX + BLRF_lu10 FERROR + BLRB_lu10 L111_TX + BLRB_lu10 L111_TY + + +L11111a: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_S + BLRB_lu10 L000_S + BLRF_lu10 FERROR + BLRB_lu10 L00_S + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0_S + BLRB_lu10 L1_TZ + BLRB_lu10 L1_TZ + BLRF_lu10 FFASTER + BLRB_lu10 L1_TZ + BLRB_lu10 L11_TZ + BLRB_lu10 L11_TZ + BLRB_lu10 L111_TZ + BLRF_lu10 FERROR + + +L0000000_S: + BLRB_lu10 READ + BRU r4 + BLRF_lu10 FERROR + BLRB_lu10 L000_UX + BLRB_lu10 L00_UX + BLRB_lu10 L00_UX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L0_UX + BLRF_lu10 FERROR + BLRB_lu10 L1_X + BLRF_lu10 FERROR + BLRB_lu10 L1_X + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + + +L0000011_S: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_UY + BLRB_lu10 L000_UX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L10_Y + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L1_Y + BLRB_lu10 L1_X + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L11_Y + BLRB_lu10 L11_X + BLRB_lu10 L111_Y + BLRF_lu10 FERROR + + +L00011_S: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_UZ + BLRB_lu10 L000_UY + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + + +L000001_S: + BLRB_lu10 READ + BRU r4 + BLRB_lu10 L0000_UY + BLRB_lu10 L000_UY + BLRF_lu10 FERROR + BLRB_lu10 L00_UX + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRF_lu10 FERROR + BLRB_lu10 L1_Y + BLRB_lu10 L1_Y + BLRF_lu10 FERROR + BLRB_lu10 L1_X + BLRB_lu10 L11_Y + BLRB_lu10 L11_Y + BLRB_lu10 L111_Y + BLRF_lu10 FERROR + +FFASTER: BRBU BFASTER +FSLOWER: BRBU BSLOWER +FERROR: BRBU BERROR +.size SpdifReceive_port4_buf32, .-SpdifReceive_port4_buf32_start +.cc_bottom SpdifReceive_port4_buf32.func diff --git a/module_spdif_tx/README.rst b/module_spdif_tx/README.rst index 3e2135e..93fa9b4 100644 --- a/module_spdif_tx/README.rst +++ b/module_spdif_tx/README.rst @@ -1,5 +1,5 @@ -module_spdif_rx +module_spdif_tx ================ :scope: General Use -:description: S/PDIF receive module +:description: S/PDIF transmit module diff --git a/module_spdif_tx/src/SpdifTransmit_4bitPort.h b/module_spdif_tx/src/SpdifTransmit_4bitPort.h new file mode 100644 index 0000000..4259f74 --- /dev/null +++ b/module_spdif_tx/src/SpdifTransmit_4bitPort.h @@ -0,0 +1,48 @@ +#ifndef _SPDIF_TRANSMIT_4BIT_PORT_ +#define _SPDIF_TRANSMIT_4BIT_PORT_ + +/** + * Code limitations: + * 1. Code is suitable only for XCORE-200 processor because of using UNZIP assembler commands + * 2. Code assumes S/PDIF signal wire is connected to P4x0 port pin. + * For other wire connection edit my_partout() function. + * + * Function expects a buffered single bit port clock from the master clock + * + * All channel communication is done via builtins (e.g. + * outuint, outct etc.) + * + * On startup expects two words over the channel: + * + * 1) Desired sample frequency (in Hz) + * + * 2) Master clock frequency (in Hz) + * + * Then sample pairs: + * + * 1) Left sample + * + * 2) Right sample + * + * The data format is 24-bit signed left aligned in a 32-bit word. + * + * If a XS1_CT_END token is received, the thread stops and waits for new sample/master freq pair + * + * @param p S/PDIF tx port + * @param c Channel-end for sample freq and samples + */ +void SpdifTransmit_4bitPort(buffered out port:32 p, chanend c); + +/** + * Configure out port to be clocked by clock block, driven from master clock input. + * + * Must be called before SpdifTransmit_4biPort() + * + * @param p S/PDIF tx port + * @param cl Clock block to be used + * @param p_mclk Master-clock input port + */ +void SpdifTransmitPortConfig_4bitPort(out buffered port:32 p, clock cl, in port p_mclk); + +#endif + diff --git a/module_spdif_tx/src/SpdifTransmit_4bitPort.xc b/module_spdif_tx/src/SpdifTransmit_4bitPort.xc new file mode 100644 index 0000000..421c4ba --- /dev/null +++ b/module_spdif_tx/src/SpdifTransmit_4bitPort.xc @@ -0,0 +1,568 @@ +#include +#include +#include + +#define VALIDITY 0x00000000 /* Validity bit (x<<28) */ + +void SpdifTransmitPortConfig_4bitPort(out buffered port:32 p, clock clk, in port p_mclk) +{ + /* Clock clock block from master-clock */ + configure_clock_src(clk, p_mclk); + + /* Clock S/PDIF tx port from MClk */ + configure_out_port_no_ready(p, clk, 0); + + /* Set delay to align SPDIF output to the clock at the external flop */ + set_clock_fall_delay(clk, 7); + + /* Start the clockblock ticking */ + start_clock(clk); +} + + + +/* Returns parity for a given word */ +static int inline parity32(unsigned x) +{ + crc32(x, 0, 1); + return (x & 1); +} + +extern unsigned dataWords_1_Nibble[16]; + +extern unsigned dataWords_1[256]; +extern unsigned preableWords_1[3]; + + +extern unsigned dataWords_2[16]; +extern unsigned preableWords_2[3]; + +extern unsigned dataWords_4[32]; +extern unsigned preambleWords_4[6]; + + +/* void my_partout(out buffered port:32 p, unsigned n, unsigned val) + * + * This function converts 8/16 data bits to 32-bit value and outputs it to the 32-bit port buffer. + * + * Parameters: + * port p : 4-bit XCORE port, must be declared as 'out buffered port:32' + * unsigned n: data length 8 or 16 + * unsigned val: value to send +*/ +void my_partout(out buffered port:32 p, unsigned n, unsigned val) +{ + if (n == 16) + // send 16 bits to port in 2 steps: insert zeroes in each 8-bit part and send 32 bit to port, repeat + { + unsigned long long res = 0; // 64-bit value + unsigned int data = val & 0xFF; // get low 8-bit = [x x x x ... b7 b6 ... b0] + res = zip(0, data, 0); // convert to [0 x 0 x ... b7 0 b6 0 ... 0 b0] + res &= 0xFFFFFFFF; // get low 32-bit part + + data = zip(0, res, 0); // convert again to [0 0 0 x 0 0 0 x ... b7 0 0 0 b6 ... 0 0 0 b0] + p <: data; // send low 32 bits to port [0 0 0 b7 0 0 0 b6 ... 0 0 0 b0] + + + data = (val >> 8) & 0xFF; //get bits from 15 to 8 = [x x x x ... b15 b14 ... b8] + res = zip(0, data, 0); // convert to [0 x 0 x ... b15 0 b14 0 ... 0 b8] + res &= 0xFFFFFFFF; // get low 32-bit part + + data = zip(0, res, 0); // convert again to [0 0 0 x 0 0 0 x ... b15 0 0 0 b14 ... 0 0 0 b8] + p <: data; // send low 32 bits to port [0 0 0 b15 0 0 0 b14 ... 0 0 0 b8] + + } + else if (n == 8) + // send 8 bits to port in 1 steps: insert zeroes and send 32 bit to port + { + unsigned long long res = 0; + unsigned int data = val & 0xFF; + res = zip(0, data, 0); // convert to [0 x 0 x ... b7 0 b6 0 ... 0 b0] + + res &= 0xFFFFFFFF; + + data = zip(0, res, 0); // convert again to [0 0 0 x 0 0 0 x ... b7 0 0 0 b6 ... 0 0 0 b0] + p <: data; // send low 32 bits to port [0 0 0 b7 0 0 0 b6 ... 0 0 0 b0] + } +} + + +/* E.g. 24MHz -> 192kHz */ +void SpdifTransmit_4bitPort_1(out buffered port:32 p, chanend c_tx0, const int ctrl_left[2], const int ctrl_right[2]) +{ + unsigned word; + unsigned xor = 0; + unsigned encoded_preamble, encoded_word; + + unsigned sample, sample2, control, preamble, parity; + + /* Check for new frequency */ + if (testct(c_tx0)) + { + chkct(c_tx0, XS1_CT_END); + return; + } + + /* Get L/R samples */ + sample = inuint(c_tx0) >> 4 & 0x0FFFFFF0 ; + sample2 = inuint(c_tx0); + +#pragma unsafe arrays + while (1) + { + int controlLeft = ctrl_left[0]; + int controlRight = ctrl_right[0]; + int newblock = 2; + + for (int i = 0 ; i < 192; i++) + { + + /* Left sample */ + control = (controlLeft & 1) << 30; + preamble = newblock ; + parity = parity32(sample | control | VALIDITY) << 31; + word = preamble | sample | control | parity | VALIDITY; + + /* Preamble */ + encoded_preamble = preableWords_1[word & 0xF]; + encoded_preamble ^= xor; + my_partout(p, 8, encoded_preamble); + xor = __builtin_sext(encoded_preamble, 8) >> 8; /* xor = 0xFFFFFFFF * ((encoded_preamble & 0x8000) == 0x8000); */ + /* Replace with sext(encoded_word,1) */ + word = word >> 4; + + /* Lookup remaining 28 bits, 8/4 bits at a time */ + encoded_word = dataWords_1[word & 0xFF]; + encoded_word ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_word); + xor = __builtin_sext(encoded_word, 16) >> 16; /* xor = 0xFFFFFFFF * (encoded_word < 0); */ + /* Replace with sext(encoded_word,1) */ + word = word >> 8; + + newblock = 0; + controlLeft >>=1; + + encoded_word = dataWords_1[word & 0xFF]; + encoded_word ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_word); + xor = __builtin_sext(encoded_word, 16) >> 16; /* xor = 0xFFFFFFFF * (encoded_word < 0); */ + /* Replace with sext(encoded_word,1) */ + word = word >> 8; + + encoded_word = dataWords_1_Nibble[word & 0xF]; + encoded_word ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 8, encoded_word); + xor = __builtin_sext(encoded_word, 8) >> 8; /* xor = 0xFFFFFFFF * ((encoded_word & 0x8000) != 0); */ + /* Replace with sext(encoded_word,1) */ + word = word >> 4; + + sample = sample2 >> 4 & 0x0FFFFFF0 ; + + encoded_word = dataWords_1[word & 0xFF]; + encoded_word ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_word); + xor = __builtin_sext(encoded_word, 16) >> 16; /* xor = 0xFFFFFFFF * (encoded_word < 0); */ + /* Replace with sext(encoded_word,1) */ + + /* Right sample */ + + control = (controlRight & 1)<<30; + preamble = (1); + parity = parity32(sample | control | VALIDITY) << 31; + word = preamble | sample | control | parity | VALIDITY; + + + /* Preamble */ + encoded_preamble = preableWords_1[word & 0xF]; + encoded_preamble ^= xor; + my_partout(p, 8, encoded_preamble); + xor = __builtin_sext(encoded_preamble, 8) >> 8; /* xor = 0xFFFFFFFF * ((encoded_preamble & 0x8000) == 0x8000); */ + /* Replace with sext(encoded_word,1) */ + word = word >> 4; + + /* Lookup remaining 28 bits, 8/4 bits at a time */ + encoded_word = dataWords_1[word & 0xFF]; + encoded_word ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_word); + xor = __builtin_sext(encoded_word, 16) >> 16; /* xor = 0xFFFFFFFF * (encoded_word < 0); */ + /* Replace with sext(encoded_word,1) */ + word = word >> 8; + + encoded_word = dataWords_1[word & 0xFF]; + encoded_word ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_word); + xor = __builtin_sext(encoded_word, 16) >> 16; /* xor = 0xFFFFFFFF * (encoded_word < 0); */ + /* Replace with sext(encoded_word,1) */ + word = word >> 8; + + controlRight >>=1; + + encoded_word = dataWords_1_Nibble[word & 0xF]; + encoded_word ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 8, encoded_word); + xor = __builtin_sext(encoded_word, 8) >> 8; /* xor = 0xFFFFFFFF * ((encoded_word & 0x8000) != 0); */ + /* Replace with sext(encoded_word,1) */ + word = word >> 4; + + /* Test for new frequency */ + if (testct(c_tx0)) + { + chkct(c_tx0, XS1_CT_END); + return; + } + + /* Get new samples... */ + sample = inuint(c_tx0) >> 4 & 0x0FFFFFF0 ; + sample2 = inuint(c_tx0); + + encoded_word = dataWords_1[word & 0xFF]; + encoded_word ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_word); + xor = __builtin_sext(encoded_word, 16) >> 16; /* xor = 0xFFFFFFFF * (encoded_word < 0); */ + /* Replace with sext(encoded_word,1) */ + if (i == 31) { + controlLeft = ctrl_left[1]; + controlRight = ctrl_right[1]; + } + } + } +} + +/* Divide by 2, e.g 24 -> 96khz */ +void SpdifTransmit_4bitPort_2(out buffered port:32 p, chanend c_tx0, const int ctrl_left[2], const int ctrl_right[2]) +{ + unsigned word; + unsigned xor = 0; + unsigned encoded_preamble, encoded_byte; + + unsigned sample, sample2, control, preamble, parity; + + clearbuf(p); + +#pragma unsafe arrays + while (1) + { + int controlLeft = ctrl_left[0]; + int controlRight = ctrl_right[0]; + int newblock = 2; + + for (int i = 0; i < 192; i++) + { + /* Check for new frequency */ + if (testct(c_tx0)) + { + chkct(c_tx0, XS1_CT_END); + return; + } + + /* Input samples */ + sample = inuint(c_tx0) >> 4 & 0x0FFFFFF0 ; + sample2 = inuint(c_tx0); + + control = (controlLeft & 1)<<30; + preamble = newblock ; + parity = parity32(sample | control | VALIDITY) << 31; + word = preamble | sample | control | parity | VALIDITY; + + /* Output left sample */ + + /* Preamble */ + encoded_preamble = preableWords_2[word & 0xF]; + encoded_preamble ^= xor; + my_partout(p, 16, encoded_preamble); + xor = __builtin_sext(encoded_preamble, 16) >> 16; + word = word >> 4; + + newblock = 0; + controlLeft >>=1; + + /* Lookup remaining 28 bits, 4 bits at a time */ +#pragma unsafe arrays +#pragma loop unroll(7) + for (int i = 0; i < 7; i++) + { + encoded_byte = dataWords_2[word & 0xF]; + encoded_byte ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_byte); + xor = __builtin_sext(encoded_byte, 16) >> 16; + word = word >> 4; + } + + sample = sample2 >> 4 & 0x0FFFFFF0 ; + + control = (controlRight & 1)<<30; + preamble = (1); + parity = parity32(sample | control | VALIDITY) << 31; + word = preamble | sample | control | parity | VALIDITY; + + /* Output right sample */ + + /* Preamble */ + encoded_preamble = preableWords_2[word & 0xF]; + encoded_preamble ^= xor; + my_partout(p, 16, encoded_preamble); + xor = __builtin_sext(encoded_preamble, 16) >> 16; + word = word >> 4; + + controlRight >>=1; + + /* Lookup remaining 28 bits, 4 bits at a time */ +#pragma unsafe arrays +#pragma loop unroll(7) + for (int i = 0; i < 7; i++) + { + encoded_byte = dataWords_2[word & 0xF]; + encoded_byte ^= xor; // Xor to invert data if lsab of last data was a 1 + my_partout(p, 16, encoded_byte); + xor = __builtin_sext(encoded_byte, 16) >> 16; + word = word >> 4; + } + + if (i == 31) { + controlLeft = ctrl_left[1]; + controlRight = ctrl_right[1]; + } + } + } +} + + + +/* Divide by 4, e.g 24 -> 48khz */ +void SpdifTransmit_4bitPort_4(buffered out port:32 p, chanend c_tx0, const int ctrl_left[2], const int ctrl_right[2]) +{ + unsigned word; + unsigned xor = 0; + unsigned encoded_preamble, encoded_byte; + + unsigned sample, control, preamble, parity, sample2; + + clearbuf(p); + +#pragma unsafe arrays + while (1) + { + int controlLeft = ctrl_left[0]; + int controlRight = ctrl_right[0]; + int newblock = 2; + + for (int i = 0 ; i<192; i++) + { + /* Check for new sample frequency */ + if (testct(c_tx0)) + { + /* Swallow control token and return */ + chkct(c_tx0, XS1_CT_END); + return; + } + + /* Input left and right samples */ + sample = inuint(c_tx0) >> 4 & 0x0FFFFFF0 ; + sample2 = inuint(c_tx0); + + /* Create status bit */ + control = (controlLeft & 1) << 30; + preamble = newblock ; + + /* Generate parity bit */ + parity = parity32(sample | control | VALIDITY) << 31; + + /* Generate complete 32bit word */ + word = preamble | sample | control | parity | VALIDITY; + + /* Output left sample */ + + /* Look up preamble and output */ + encoded_preamble = preambleWords_4[(word & 0xF)*2+1]; + encoded_preamble ^= xor; + my_partout(p, 16, encoded_preamble); + + encoded_preamble = preambleWords_4[(word & 0xF)*2]; + encoded_preamble ^= xor; + my_partout(p, 16, encoded_preamble); + xor = __builtin_sext(encoded_preamble, 16) >> 16; + word = word >> 4; + + newblock = 0; + controlLeft >>=1; + + /* Lookup remaining 28 bits, 4 bits at a time */ +#pragma unsafe arrays +#pragma loop unroll(7) + for (int i = 0; i < 7; i++) + { + encoded_byte = dataWords_4[(word & 0xF)*2+1]; + encoded_byte ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_byte); + encoded_byte = dataWords_4[(word & 0xF) * 2]; + encoded_byte ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_byte); + xor = __builtin_sext(encoded_byte, 16) >> 16; + word = word >> 4; + } + + sample = sample2 >> 4 & 0x0FFFFFF0 ; + + /* Output right sample */ + + control = (controlRight & 1)<<30; + preamble = (1); + parity = parity32(sample | control | VALIDITY) << 31; + word = preamble | sample | control | parity | VALIDITY; + + /* Look up and output pre-amble, 2 bytes at a time */ + encoded_preamble = preambleWords_4[(word & 0xF)*2+1]; + encoded_preamble ^= xor; + my_partout(p, 16, encoded_preamble); + + encoded_preamble = preambleWords_4[(word & 0xF)*2]; + encoded_preamble ^= xor; + my_partout(p, 16, encoded_preamble); + xor = __builtin_sext(encoded_preamble, 16) >> 16; + word = word >> 4; + + controlRight >>=1; + + + /* Lookup remaining 28 bits, 4 bits at a time */ +#pragma unsafe arrays +#pragma loop unroll(7) + for (int i = 0; i < 7; i++) + { + encoded_byte = dataWords_4[(word & 0xF)*2+1]; + encoded_byte ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + my_partout(p, 16, encoded_byte); + encoded_byte = dataWords_4[(word & 0xF) * 2]; + encoded_byte ^= xor; /* Xor to invert data if lsab of last data was a 1 */ + xor = __builtin_sext(encoded_byte, 16) >> 16; + word = word >> 4; + my_partout(p, 16, encoded_byte); + } + + if (i == 31) { + controlLeft = ctrl_left[1]; + controlRight = ctrl_right[1]; + } + } + } +} + + +void SpdifTransmitError_4bitPort(chanend c_in) +{ + +#if 0 + printstr("Sample Frequency and Master Clock Frequency combination not supported\n"); +#endif + + while(1) + { + /* Keep swallowing samples until we get a sample frequency change */ + if (testct(c_in)) + { + chkct(c_in, XS1_CT_END); + return; + } + + inuint(c_in); + inuint(c_in); + } +} + +/* Defines for building channel status words */ +#define CHAN_STAT_L 0x00107A04 +#define CHAN_STAT_R 0x00207A04 + +#define CHAN_STAT_44100 0x00000000 +#define CHAN_STAT_48000 0x02000000 +#define CHAN_STAT_88200 0x08000000 +#define CHAN_STAT_96000 0x0A000000 +#define CHAN_STAT_176400 0x0C000000 +#define CHAN_STAT_192000 0x0E000000 + +#define CHAN_STAT_WORD_2 0x0000000B + + +/* S/PDIF transmit thread */ +void SpdifTransmit_4bitPort(buffered out port:32 p, chanend c_in) +{ + int chanStat_L[2], chanStat_R[2]; + unsigned divide; + + /* Receive sample frequency over channel (in Hz) */ + unsigned samFreq = inuint(c_in); + + /* Receive master clock frequency over channel (in Hz) */ + unsigned mclkFreq = inuint(c_in); + + /* Create channel status words based on sample freq */ + switch(samFreq) + { + case 44100: + chanStat_L[0] = CHAN_STAT_L | CHAN_STAT_44100; + chanStat_R[0] = CHAN_STAT_R | CHAN_STAT_44100; + break; + + case 48000: + chanStat_L[0] = CHAN_STAT_L | CHAN_STAT_48000; + chanStat_R[0] = CHAN_STAT_R | CHAN_STAT_48000; + break; + + case 88200: + chanStat_L[0] = CHAN_STAT_L | CHAN_STAT_88200; + chanStat_R[0] = CHAN_STAT_R | CHAN_STAT_88200; + break; + + case 96000: + chanStat_L[0] = CHAN_STAT_L | CHAN_STAT_96000; + chanStat_R[0] = CHAN_STAT_R | CHAN_STAT_96000; + break; + + case 176400: + chanStat_L[0] = CHAN_STAT_L | CHAN_STAT_176400; + chanStat_R[0] = CHAN_STAT_R | CHAN_STAT_176400; + break; + + case 192000: + chanStat_L[0] = CHAN_STAT_L | CHAN_STAT_192000; + chanStat_R[0] = CHAN_STAT_R | CHAN_STAT_192000; + break; + + default: + /* Sample frequency not recognised.. carry on for now... */ + chanStat_L[0] = CHAN_STAT_L; + chanStat_R[0] = CHAN_STAT_R; + break; + + } + chanStat_L[1] = CHAN_STAT_WORD_2; + chanStat_R[1] = CHAN_STAT_WORD_2; + + /* Calculate required divide */ + divide = mclkFreq / (samFreq * 2 * 32 * 2); + + switch(divide) + { + case 1: + /* Highest sample freq supported by mclk freq, eg: 24 -> 192 */ + SpdifTransmit_4bitPort_1(p, c_in, chanStat_L, chanStat_R); + break; + + case 2: + /* E.g. 24 -> 96 */ + SpdifTransmit_4bitPort_2(p, c_in, chanStat_L, chanStat_R); + break; + + case 4: + /* E.g. 24MHz -> 48kHz */ + SpdifTransmit_4bitPort_4(p, c_in, chanStat_L, chanStat_R); + break; + + default: + /* Mclk does not support required sample freq */ + SpdifTransmitError_4bitPort(c_in); + break; + } +} + +