Forum Rule: Always post complete source code & details to reproduce any issue!
Page 1 of 4 1 2 3 ... LastLast
Results 1 to 25 of 89

Thread: S/pdif

  1. #1
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070

    S/pdif



    EDIT:

    Working version: https://github.com/FrankBoesing/Teensy3-SPDIF
    Only PIN22 is needed.




    Today I read me a bit in S / PDIF.
    I think we could make it happen on a Teensy using SPI.
    The protocol is not too complicated, actually we could even use the 2 SPI device of T3.1, because there is no need for SCK.
    Unfortunately there is a problem: The baud rate.

    We need exactly 64 * 44100 Hz (= 2.8224 MHz)

    I do not believe that the SPI device this baud rate can generate, but maybe there is a trick?

    What comes to mind:
    - An external clock with the SPI device in slave mode (perhaps with a tiny avr which generates the clk?)
    - Somehow use the built-in timer to generate (2x ?) 2.8224 MHz

    Unfortunately, we can then no longer use SPI for other things, such as rading from SD.

    Another idea: a Teensy LC as a "slave" for the T3.1. The LC would do S / PDIF output (again we have to think about the clock), the T3.1 provide the audio data to the LC.

    What do you think?
    Do you have any other ideas?
    Last edited by Frank B; 06-06-2015 at 07:14 PM.

  2. #2
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    You might (ab)use the I2S FIFO to generate the SPDIF signal. The I2S clock has somewhat more flexibility and allows you to generate the exact clockrate.

    Edit: This suggestion above will not work in combination with the audio shield.
    Also the audio library works at 44118 Hz. I do not know how if this falls within the timing requirements of SPDIF (Did not check, but I suspect it is outside of specification). The internal ADC cannot be set closer to 44.1 kHz. The audio shield can be set at an exact 44.1 kHz.

    Edit2: SPDIF clock requirement:
    high accuracy mode: 50 ppm, so 44100 +/- 2 Hz
    normal accuracy mode: 1000 ppm, so 44100 +/- 44 Hz
    Conclusion: The default clock used in the audio library is within spec for SPDIF.
    Last edited by kpc; 05-18-2015 at 06:27 PM.

  3. #3
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    Quote Originally Posted by kpc View Post
    You might (ab)use the I2S FIFO to generate the SPDIF signal. The I2S clock has somewhat more flexibility and allows you to generate the exact clockrate.

    Edit: This suggestion above will not work in combination with the audio shield.
    Also the audio library works at 44118 Hz. I do not know how if this falls within the timing requirements of SPDIF (Did not check, but I suspect it is outside of specification). The internal ADC cannot be set closer to 44.1 kHz. The audio shield can be set at an exact 44.1 kHz.

    Edit2: SPDIF clock requirement:
    high accuracy mode: 50 ppm, so 44100 +/- 2 Hz
    normal accuracy mode: 1000 ppm, so 44100 +/- 44 Hz
    Conclusion: The default clock used in the audio library is within spec for SPDIF.
    I2S is a good idea. We don't loose the SPI then, which is more important than i2s in this case, i think. And you can use cheap spdif/analog converters (worst case).
    Currently i have not much time, but I did s/pdif on my list. I will definately try this, perhaps in the second half of the year.

  4. #4
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    The archiveable clocks (bitrate) are very close to 2822400 Hz:
    Code:
    144MHz FRACT: 48 DIV: 2499 FREQ: 2822400 ERR:0
    120MHz FRACT: 88 DIV: 3783 FREQ: 2822410.15 ERR:10.15
    96MHz FRACT: 73 DIV: 2516 FREQ: 2822407.63 ERR:7.63
    72MHz FRACT: 48 DIV: 1249 FREQ: 2822400 ERR:0
    48MHz FRACT: 146 DIV: 2499 FREQ: 2822400 ERR:0
    24MHz FRACT: 146 DIV: 1249 FREQ: 2822400 ERR:0
    That looks good.
    We need a translation-table for Bi-phase mark encoding and a bit of additional conversion and we are done.

    http://whitefiles.org/b1_s/1_free_gu...t/pgs/h13f.htm
    Last edited by Frank B; 05-19-2015 at 07:19 AM.

  5. #5
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    Correction, i think we need a clock of 2 * 64 * 44100 Hz to archive the bitrate of 2822400 because of the encoding
    (Am i wrong?)
    Code:
    144MHz FRACT: 48 DIV: 1249 FREQ: 5644800 ERR:0
    120MHz FRACT: 146 DIV: 3124 FREQ: 5644800 ERR:0
    96MHz FRACT: 146 DIV: 2499 FREQ: 5644800 ERR:0
    72MHz FRACT: 48 DIV: 624 FREQ: 5644800 ERR:0
    48MHz FRACT: 146 DIV: 1249 FREQ: 5644800 ERR:0
    24MHz FRACT: 146 DIV: 624 FREQ: 5644800 ERR:0
    12MHz FRACT: 293 DIV: 624 FREQ: 5644800 ERR:0

  6. #6
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,135
    Do any of the SPDIF chips have options to generate the high accuracy clock? Or maybe a shield could be made with the right crystal?

    I've been looking for a good reason to work on (read: actually fix & test) the I2S slave mode objects.....

  7. #7
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    A 28.224MHZ Crystal can be used to create the common audio-frequencies.

  8. #8
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    I did not verify your FRACT/DIV values, but you might want to check this thread. This code will perform the calculations based on the pll clock frequency setting. It might seem a pretty big function, but it actually only compiles to a surprisingly few instructions. Also no floating point involved in setting the frequency.
    Code:
    setI2SmasterClock(44100, 2 * 64);
    getI2SmasterClock(2 * 64)
    The code does not (yet) set the bitclock counter.

    And yes, you need the double clock frequency, because of the Manchester coding. I would generate a lookup table of 256 with the manchester coded versions (16 bit) of each byte. One lookup table for the preamble byte and one for all other bytes.

  9. #9
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    If i only had more time...

    KPC, i wrote a short PHP script:
    Code:
     function calcDiv($F_CPU) {
     
     $x = 0;
     $y = 0;
     
     $mx = 0;
     $my = 0;
     $mz = 100000000;
     $t = 44100 * 64 * 2;
     
     for ($x = 0; $x<=511; $x++){ 
    	for ($y=0; $y<=4095; $y++) { 
    		$z = abs($F_CPU * (($x+1) / ($y+1)) - $t);
    	    if ($z < $mz) { $mx = $x; $my = $y; $mz = $z; }		
    	}
     }	
     echo "\r\n<br>",	
    	$F_CPU/1000000,
    	"MHz FRACT: $mx \tDIV: $my \t FREQ: ",round($F_CPU * (($mx+1) / ($my+1)),2),"\tERR:",round( $F_CPU * (($mx+1) / ($my+1)) - $t,2 );
     }
    
     calcDiv(144 * 1000000);
     calcDiv(120 * 1000000);
     calcDiv(96 * 1000000);
     calcDiv(72 * 1000000); 
     calcDiv(48 * 1000000);  
     calcDiv(24 * 1000000);   
     calcDiv(12 * 1000000);
    But thanks for the link, seems to be interesting.

  10. #10
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    I see you used F_CPU, I think you should use F_PLL.
    Furthermore, beware that the actual register values are the calulated values minus one.

    Edit: In Audio/output_i2s.cpp Paul lists the values he is using, to achieve 256 * 44118.
    Edit2:
    And you can use cheap spdif/analog converters (worst case).
    For testing, just use an LED.
    Last edited by kpc; 05-19-2015 at 11:11 AM.

  11. #11
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    Great Toslink :-)

    Ok, my script spits out the same values for 256 * 44118 as Paul uses (-1), so it seems to be ok.
    Why 11MHz clock ? I don#t understand..
    Last edited by Frank B; 05-19-2015 at 01:16 PM.

  12. #12
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    The master clock is used for the delta/sigma modulator and the digital filters. The actual multiplication factor is determined by the I2S device, 256 is a commonly used factor. The SGTL5000 on the audio shield can also accept 384 and 512, bit this will only raise the clock frequency, as well as being out of spec for the Teensy.

  13. #13
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,135
    Does anyone know of any good I2S to SPDIF chips? I've seen the Cirrus CS8406, but it's kinda spendy.

  14. #14
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    WM8805 ? But i don't know the price.

  15. #15
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    Quote Originally Posted by Frank B View Post
    We need a translation-table for Bi-phase mark encoding and a bit of additional conversion and we are done.
    Lookuptable: Done.

    Code:
    {const ? perhaps ram is faster..todo: test speed}
    uint16_t bmclookup = { //biphase mark econded values for 0x00..0xff
    	0xcccc, 0x4ccc, 0x2ccc, 0xaccc, 0x34cc, 0xb4cc, 0xd4cc, 0x54cc,
            0x32cc, 0xb2cc, 0xd2cc, 0x52cc, 0xcacc, 0x4acc, 0x2acc, 0xaacc,
    	0x334c, 0xb34c, 0xd34c, 0x534c, 0xcb4c, 0x4b4c, 0x2b4c, 0xab4c,
    	0xcd4c, 0x4d4c, 0x2d4c, 0xad4c, 0x354c, 0xb54c, 0xd54c, 0x554c,
    	0x332c, 0xb32c, 0xd32c, 0x532c, 0xcb2c, 0x4b2c, 0x2b2c, 0xab2c,
    	0xcd2c, 0x4d2c, 0x2d2c, 0xad2c, 0x352c, 0xb52c, 0xd52c, 0x552c,
    	0xccac, 0x4cac, 0x2cac, 0xacac, 0x34ac, 0xb4ac, 0xd4ac, 0x54ac,
    	0x32ac, 0xb2ac, 0xd2ac, 0x52ac, 0xcaac, 0x4aac, 0x2aac, 0xaaac,
    	0x3334, 0xb334, 0xd334, 0x5334, 0xcb34, 0x4b34, 0x2b34, 0xab34,
    	0xcd34, 0x4d34, 0x2d34, 0xad34, 0x3534, 0xb534, 0xd534, 0x5534,
    	0xccb4, 0x4cb4, 0x2cb4, 0xacb4, 0x34b4, 0xb4b4, 0xd4b4, 0x54b4,
    	0x32b4, 0xb2b4, 0xd2b4, 0x52b4, 0xcab4, 0x4ab4, 0x2ab4, 0xaab4,
    	0xccd4, 0x4cd4, 0x2cd4, 0xacd4, 0x34d4, 0xb4d4, 0xd4d4, 0x54d4,
    	0x32d4, 0xb2d4, 0xd2d4, 0x52d4, 0xcad4, 0x4ad4, 0x2ad4, 0xaad4,
    	0x3354, 0xb354, 0xd354, 0x5354, 0xcb54, 0x4b54, 0x2b54, 0xab54,
    	0xcd54, 0x4d54, 0x2d54, 0xad54, 0x3554, 0xb554, 0xd554, 0x5554,
    	0x3332, 0xb332, 0xd332, 0x5332, 0xcb32, 0x4b32, 0x2b32, 0xab32,
    	0xcd32, 0x4d32, 0x2d32, 0xad32, 0x3532, 0xb532, 0xd532, 0x5532,
    	0xccb2, 0x4cb2, 0x2cb2, 0xacb2, 0x34b2, 0xb4b2, 0xd4b2, 0x54b2,
    	0x32b2, 0xb2b2, 0xd2b2, 0x52b2, 0xcab2, 0x4ab2, 0x2ab2, 0xaab2,
    	0xccd2, 0x4cd2, 0x2cd2, 0xacd2, 0x34d2, 0xb4d2, 0xd4d2, 0x54d2,
    	0x32d2, 0xb2d2, 0xd2d2, 0x52d2, 0xcad2, 0x4ad2, 0x2ad2, 0xaad2,
    	0x3352, 0xb352, 0xd352, 0x5352, 0xcb52, 0x4b52, 0x2b52, 0xab52,
    	0xcd52, 0x4d52, 0x2d52, 0xad52, 0x3552, 0xb552, 0xd552, 0x5552,
    	0xccca, 0x4cca, 0x2cca, 0xacca, 0x34ca, 0xb4ca, 0xd4ca, 0x54ca,
    	0x32ca, 0xb2ca, 0xd2ca, 0x52ca, 0xcaca, 0x4aca, 0x2aca, 0xaaca,
    	0x334a, 0xb34a, 0xd34a, 0x534a, 0xcb4a, 0x4b4a, 0x2b4a, 0xab4a,
    	0xcd4a, 0x4d4a, 0x2d4a, 0xad4a, 0x354a, 0xb54a, 0xd54a, 0x554a,
    	0x332a, 0xb32a, 0xd32a, 0x532a, 0xcb2a, 0x4b2a, 0x2b2a, 0xab2a,
    	0xcd2a, 0x4d2a, 0x2d2a, 0xad2a, 0x352a, 0xb52a, 0xd52a, 0x552a,
    	0xccaa, 0x4caa, 0x2caa, 0xacaa, 0x34aa, 0xb4aa, 0xd4aa, 0x54aa,
    	0x32aa, 0xb2aa, 0xd2aa, 0x52aa, 0xcaaa, 0x4aaa, 0x2aaa, 0xaaaa,
    };
    Sorry, i'm using this thread a bit like a a notepad for later.. but perhaps others might be interested too.
    Question: How (and when: before or after encoding?) is the paritybit calculated.

  16. #16
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    You can find some versions of IEC60958 on law.resource.org.
    According to the spec:
    Time slot 31 (parity bit) carries a parity bit such that time slots 4 to 31 inclusive carry an even number of ones and an even number of zeros (even parity).
    NOTE 3: The preambles have even parity as an expllclt property
    This is before encoding, since after encoding, the number of ones is fixed. For each unencoded bit due to the manchester coding, after encoding, it will always have 1 high bit.
    Last edited by kpc; 05-19-2015 at 06:32 PM.

  17. #17
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    Quote Originally Posted by kpc View Post
    You can find some versions of IEC60958 on law.resource.org.
    According to the spec:

    This is before encoding, since after encoding, the number of ones is fixed. For each unencoded bit due to the manchester coding, after encoding, it will always have 1 high bit.
    Hm, there is a GCC built-in function int __builtin_parity... maybe it is useful..i try this..

  18. #18
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    It may suprise, but the parity is the same for bmc !
    So. technically, it does not matter wether the parity-calculation is done before or after encoding.
    (But i think before is faster (less bits) )

    I did not test what is faster (__builtin or lookup) (i'll do that later) but I was playing with __builtin_parity anyway, so I created a table that I can use it later if I decide to...
    Code:
    //for (int i = 0; i <= 255; i++) Serial.printf("%d, %s",__builtin_parity(i),((i+1) % 16==0) ? "\r\n": "");
    const 
    uint16_t paritylookup[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, 
            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, 
            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, 
            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, 
            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, 
            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
    };
    Nice pattern :-)

    The next for me to do is to read the manual again and figure out how to setup i2s for LSB first, 64bit, 1 channel (i hope this is possible), dma..

  19. #19
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    15,135
    I don't see how I2S can be single channel. One channel is sent with LRCLK is low and the other while LRCLK is high.

  20. #20
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    Ok..then 2 * 32 bit
    Thanks for the info, so i don't waste time time for a single channel :-)

  21. #21
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    I am also playing a little with spdif. Nothing working yet, but it seems that only very few modifications to output_i2s are needed.
    Also my interpretation of the spec might be wrong, but I get a different lookup table. Only the first value is the same. My first line is:
    Code:
    0xcccc, 0xb333, 0xd333, 0xaccc, 0xcb33, 0xb4cc, 0xd4cc, 0xab33,
    And the encoding:
    Code:
    static void inline bmc_encode(uint32_t *dest, int16_t sample, uint16_t preamble)  __attribute__((always_inline));
    static void inline bmc_encode(uint32_t *dest, int16_t sample, uint16_t preamble)
    {
            uint32_t bmc1, bmc2, bmc3, val;
            val = sample << 4;
            val |= __builtin_parity(val) << 23;
            bmc1 = bmc_lookup[val & 0xff];
            dest[0] = (preamble << 16) | (bmc1 & 0xffff);
            bmc2 = bmc_lookup[(val >> 8) & 0xff] ^ -(bmc1 & 1);
            bmc3 = bmc_lookup[(val >> 16) & 0xff] ^ -(bmc2 & 1);
            dest[1] = (bmc2 << 16) | (bmc3 & 0xffff);
    }
    The preamble is depending on the status bit counter: 0xe8cc, 0xe2cc or 0xe4cc
    As said, nothing tested yet on the hardware, so this code might be wrong.


    Edit: The cortex m4 does not seem to have a builtin parity instruction, it gets translated to library call. I have not checked the library code.
    The following code I used before on other microcontrollers. On the cortex m4 it is only 6 assembly instructions (also only 6 cycles)
    Code:
    inline uint32_t parity(uint32_t v)  __attribute__((always_inline));
    inline uint32_t parity(uint32_t v)
    {
            v ^= v >> 1;
            v ^= v >> 2;
            v = (v & 0x11111111ul) * 0x11111111ul;
            return = (v >> 28) & 1;
    }
    Edit2: The library code is actually 7 assembly instructions (also 7 cycles) + 4 cycles for the branch instructions. So in total, takes 83% more time than the code above.
    Last edited by kpc; 05-20-2015 at 07:11 PM.

  22. #22
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    Quote Originally Posted by kpc View Post
    I am also playing a little with spdif. Nothing working yet, but it seems that only very few modifications to output_i2s are needed.
    Also my interpretation of the spec might be wrong, but I get a different lookup table. Only the first value is the same. My first line is:
    Code:
    0xcccc, 0xb333, 0xd333, 0xaccc, 0xcb33, 0xb4cc, 0xd4cc, 0xab33,
    And the encoding:
    Code:
    static void inline bmc_encode(uint32_t *dest, int16_t sample, uint16_t preamble)  __attribute__((always_inline,unused));
    static void inline bmc_encode(uint32_t *dest, int16_t sample, uint16_t preamble)
    {
            uint32_t bmc1, bmc2, bmc3, val;
            val = sample << 4;
            val |= __builtin_parity(val) << 23;
            bmc1 = bmc_lookup[val & 0xff];
            dest[0] = (preamble << 16) | (bmc1 & 0xffff);
            bmc2 = bmc_lookup[(val >> 8) & 0xff] ^ -(bmc1 & 1);
            bmc3 = bmc_lookup[(val >> 16) & 0xff] ^ -(bmc2 & 1);
            dest[1] = (bmc2 << 16) | (bmc3 & 0xffff);
    }
    The preamble is depending on the status bit counter: 0xe8cc, 0xe2cc or 0xe4cc
    As said, nothing tested yet on the hardware, so this code might be wrong.


    Edit: The cortex m4 does not seem to have a builtin parity instruction, it gets translated to library call. I have not checked the library code.
    The following code I used before on other microcontrollers. On the cortex m4 it is only 6 assembly instructions
    Code:
            v ^= v >> 1;
            v ^= v >> 2;
            v = (v & 0x11111111ul) * 0x11111111ul;
            parity = (v >> 28) & 1;
    kpc, as i understood the descriptions, the parity bit is calculated for a whole subframe except the the preamble.
    __builtin_parity can do 32 Bit at once, so it might be more efficient to first create the the subrame without preamble, calculate and add then the parity, then encode. then as last step add the preamble.

    this code for raspberry might help:
    https://github.com/humppe/spdif-encoder

    Maye we can use it to test our encodings, (whole blocks of 192 frames) and compare the output.

    The code is pretty straight forward , but slowly .Each bit is processed individually .
    Last edited by Frank B; 05-20-2015 at 07:15 PM.

  23. #23
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    bmc lookup:
    Code:
    your value for 1 is : 0xb333 = 1011001100110011
    mine is :                      0100110011001100
    so we are near, it's almost the same but one is inversed, or backward

  24. #24
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    In my encoding, I only calculate the parity on the final three bytes, the preamble is even by definition, as are the following 4 LSB bits, since for 16 bit data these will be zeros.
    Since the header ends with a 0, I would expect every following bit to be a 1, so the MSB of the encoded values is by definition 1.
    Anyway, I will check the code you linked.

  25. #25
    Senior Member Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany
    Posts
    4,070
    It's a complete SPDIF encoder.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •