Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 4 FirstFirst 1 2 3 4 LastLast
Results 26 to 50 of 96

Thread: S/pdif

  1. #26
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    This is another good article about spdif:
    http://www.nutsvolts.com/uploads/mag...s/873/HDTV.pdf (fast forward to page 3)
    The next (minor) challenge is the channelstatus-bit. But that's only a bit shift over 24 constant bytes (192 bit) . We can do AES/EBU too, i think..

  2. #27
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    I checked the status bits, and keeping everything 0 is what we need.
    This boils down to: 44.1 kHz, no copyright, 1000ppm clock.
    I do not have luck with the raspi code. When testing with all zeros as the input, I see
    Code:
    ./spdif-encoder < /dev/zero | hexdump
    0000000 cccc 00cc cccc cccc cccc 00cc cccc cccc
    I cannot recognize the preamble in there.

  3. #28
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    perhaps some raspberry trickyness..
    /* BCM2835-ARM-Peripherals.pdf:
    * "Note that data is always serialised MS-bit first. This is well-established
    * behaviour in both PCM and I2S."
    *
    * pcm_iec958.c says that preamble is at LSB ... Because of this, the bit ordering
    * is reversed here while performing bmc encoding..
    */
    There are 8 bits zero... hm.

  4. #29
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    I think I got it, only tested on PC.
    Code:
    /* This code is free to use */
    /* Kire Pudsje, May 2015 */
    #include <stdio.h>
    #include <stdint.h>
    #include <arpa/inet.h> // htonl
    
    // table assumes previous state is 0, use bitwise invert of values otherwise
    const uint16_t bmc_lookup[] = {
            0xcccc, 0xcccd, 0xcccb, 0xccca, 0xccd3, 0xccd2, 0xccd4, 0xccd5,
            0xccb3, 0xccb2, 0xccb4, 0xccb5, 0xccac, 0xccad, 0xccab, 0xccaa,
            0xcd33, 0xcd32, 0xcd34, 0xcd35, 0xcd2c, 0xcd2d, 0xcd2b, 0xcd2a,
            0xcd4c, 0xcd4d, 0xcd4b, 0xcd4a, 0xcd53, 0xcd52, 0xcd54, 0xcd55,
            0xcb33, 0xcb32, 0xcb34, 0xcb35, 0xcb2c, 0xcb2d, 0xcb2b, 0xcb2a,
            0xcb4c, 0xcb4d, 0xcb4b, 0xcb4a, 0xcb53, 0xcb52, 0xcb54, 0xcb55,
            0xcacc, 0xcacd, 0xcacb, 0xcaca, 0xcad3, 0xcad2, 0xcad4, 0xcad5,
            0xcab3, 0xcab2, 0xcab4, 0xcab5, 0xcaac, 0xcaad, 0xcaab, 0xcaaa,
            0xd333, 0xd332, 0xd334, 0xd335, 0xd32c, 0xd32d, 0xd32b, 0xd32a,
            0xd34c, 0xd34d, 0xd34b, 0xd34a, 0xd353, 0xd352, 0xd354, 0xd355,
            0xd2cc, 0xd2cd, 0xd2cb, 0xd2ca, 0xd2d3, 0xd2d2, 0xd2d4, 0xd2d5,
            0xd2b3, 0xd2b2, 0xd2b4, 0xd2b5, 0xd2ac, 0xd2ad, 0xd2ab, 0xd2aa,
            0xd4cc, 0xd4cd, 0xd4cb, 0xd4ca, 0xd4d3, 0xd4d2, 0xd4d4, 0xd4d5,
            0xd4b3, 0xd4b2, 0xd4b4, 0xd4b5, 0xd4ac, 0xd4ad, 0xd4ab, 0xd4aa,
            0xd533, 0xd532, 0xd534, 0xd535, 0xd52c, 0xd52d, 0xd52b, 0xd52a,
            0xd54c, 0xd54d, 0xd54b, 0xd54a, 0xd553, 0xd552, 0xd554, 0xd555,
            0xb333, 0xb332, 0xb334, 0xb335, 0xb32c, 0xb32d, 0xb32b, 0xb32a,
            0xb34c, 0xb34d, 0xb34b, 0xb34a, 0xb353, 0xb352, 0xb354, 0xb355,
            0xb2cc, 0xb2cd, 0xb2cb, 0xb2ca, 0xb2d3, 0xb2d2, 0xb2d4, 0xb2d5,
            0xb2b3, 0xb2b2, 0xb2b4, 0xb2b5, 0xb2ac, 0xb2ad, 0xb2ab, 0xb2aa,
            0xb4cc, 0xb4cd, 0xb4cb, 0xb4ca, 0xb4d3, 0xb4d2, 0xb4d4, 0xb4d5,
            0xb4b3, 0xb4b2, 0xb4b4, 0xb4b5, 0xb4ac, 0xb4ad, 0xb4ab, 0xb4aa,
            0xb533, 0xb532, 0xb534, 0xb535, 0xb52c, 0xb52d, 0xb52b, 0xb52a,
            0xb54c, 0xb54d, 0xb54b, 0xb54a, 0xb553, 0xb552, 0xb554, 0xb555,
            0xaccc, 0xaccd, 0xaccb, 0xacca, 0xacd3, 0xacd2, 0xacd4, 0xacd5,
            0xacb3, 0xacb2, 0xacb4, 0xacb5, 0xacac, 0xacad, 0xacab, 0xacaa,
            0xad33, 0xad32, 0xad34, 0xad35, 0xad2c, 0xad2d, 0xad2b, 0xad2a,
            0xad4c, 0xad4d, 0xad4b, 0xad4a, 0xad53, 0xad52, 0xad54, 0xad55,
            0xab33, 0xab32, 0xab34, 0xab35, 0xab2c, 0xab2d, 0xab2b, 0xab2a,
            0xab4c, 0xab4d, 0xab4b, 0xab4a, 0xab53, 0xab52, 0xab54, 0xab55,
            0xaacc, 0xaacd, 0xaacb, 0xaaca, 0xaad3, 0xaad2, 0xaad4, 0xaad5,
            0xaab3, 0xaab2, 0xaab4, 0xaab5, 0xaaac, 0xaaad, 0xaaab, 0xaaaa
    };
    
    // On the teensy, this is just a single assembly function
    uint32_t rbit(uint32_t v)
    {
            uint32_t r = 0;
            for (int i = 0; i < 32; i++) {
                    r = (r << 1) | (v & 1);
                    v >>= 1;
            }
            return r;
    }
    
    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;
    }
    
    static void inline bmc_encode(uint32_t *dest, uint16_t sample, uint16_t preamble) __attribute__((always_inline));
    static void inline bmc_encode(uint32_t *dest, uint16_t sample, uint16_t preamble)
    {
            uint32_t bmc1, bmc2, bmc3, val;
            val = rbit((sample << 4) | (parity(sample) << 23));
            bmc1 = bmc_lookup[(val >> 24) & 0xff];
            dest[0] = (preamble << 16) | (bmc1 & 0xffff);
            bmc2 = bmc_lookup[(val >> 16) & 0xff] ^ -(bmc1 & 1);
            bmc3 = bmc_lookup[(val >> 8) & 0xff] ^ -(bmc2 & 1);
            dest[1] = (bmc2 << 16) | (bmc3 & 0xffff);
    }
    
    int main(void) {
        int cnt = 1;
        bool left = true;
        uint16_t sample, preamble;
        uint32_t dest[2];
        while (fread(&sample, 2, 1, stdin))
        {
            cnt--;
            if (left) {
                if (cnt == 0) {
                    cnt = 192;
                    preamble = 0xe8cc;
                }
                else
                    preamble = 0xe2cc;
            }
            else
                    preamble = 0xe4cc;
            bmc_encode(dest, sample, preamble);
            left = !left;
    
            // flip because of byte order when writing to disk
            dest[0] = htonl(dest[0]);
            dest[1] = htonl(dest[1]);
            fwrite(dest, 8, 1, stdout);
        }
        return 0;
    }
    Code:
    ./spdif < /dev/urandom | hexdump -C
    Last edited by kpc; 05-20-2015 at 10:58 PM.

  5. #30
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    Looks great !
    But are you sure that the copyprotectionbit is 0 ? I read "1" means unprotected.

  6. #31
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    Sorry, you are right. There was a small mistake, I had 192 L+R frames, seems 192 is the total number of frames, code was adjusted.

  7. #32
    Senior Member
    Join Date
    Jul 2014
    Posts
    138
    Just as an interesting idea, there is another TOSLink optical audio protocol out there called ADAT.

    It is 12.288 Mbit/s which is a challenge but would allow 8 channel audio output with a teensy if you use an ADA8200 but perhaps the most interesting thing is that the ADA8200 supports an external word clock from either the ADAT signal or a BNC input, so if you weren't able to do exactly 12.288Mbit/s it may not matter.

    When SPDIF is working, I may take a look at whether I can use the same code to generate ADAT (it has a different clock and signalling scheme but I'd imagine the teensy peripheral usage would be similar).

  8. #33
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    A thought in between:
    We need to adjust the Audio Library at 44100 Hz instead of 44118.

  9. #34
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    @Frank B, Unless you are using pure synthetic waveforms, you cannot use 44100. With the audio shield it was possible, but the Teensy ADC clock needs to be an integer division of the system clock. 44118 is the closest. An escape would be to use 48000, which is a pure integer division of the system clock.
    As said earlier, the 44118 is within specifications of the S/PDIF standard (1000 ppm)

  10. #35
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    Ok, you're right, the ADC I have not considered.

    Too bad. We are now 45 Hz below the exact frequency.
    144MHz FRACT: 1 DIV: 50 FREQ: 5647058.82 ERR:-45.18
    120MHz FRACT: 3 DIV: 84 FREQ: 5647058.82 ERR:-45.18
    96MHz FRACT: 0 DIV: 16 FREQ: 5647058.82 ERR:-45.18
    72MHz FRACT: 3 DIV: 50 FREQ: 5647058.82 ERR:-45.18
    48MHz FRACT: 1 DIV: 16 FREQ: 5647058.82 ERR:-45.18
    16MHz FRACT: 5 DIV: 16 FREQ: 5647058.82 ERR:-45.189
    (dont subtract 1)

    But if this is within the spec, it'll be ok.

  11. #36
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    Actually, I now left my clock at 11.29 MHz, since apparently the minimum bit clock divider is 2 (reg value 0).

  12. #37
    Quote Originally Posted by kpc View Post
    As said earlier, the 44118 is within specifications of the S/PDIF standard (1000 ppm)
    from what I remember, however, this does not guarantee the sync between two devices, after a bit of time with excessive jitter they are no longer in sync.

  13. #38
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    I do not know what Frank's intentions are, but I just want to hook it up to my amplifier, so syncing between multiple inputs is not an issue for me.
    I assume here that my amplifier has a PLL to recover the clock, and it is not a hardwired clock rate with sample skip synchronization.
    Last edited by kpc; 05-21-2015 at 11:54 AM.

  14. #39
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    16,298
    Looks like all that's needed now is a I2S configuration for 32 bit frames!

    I ordered some of these:
    http://www.digikey.com/product-detai...A/1080-1434-ND

    and a quick PCB to wire them up:
    https://www.oshpark.com/projects/KcDBKHta

  15. #40
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    16,298
    Oh, I see... 64 encoded bits per sample. Hmmm... should be possible somehow. Will play with the audio lib side when those PCBs and connectors arrive.

  16. #41
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    This is how I got this far.
    Still trying to convince the I2S module to output the correct number of bits without gaps, so not fully functional yet.
    It is already integrated in the audio lib. Like I said in one of my first posts, only slight modifications needed to output_i2s.

    Edit: Now starting to think the DMA copying only does 16 bits.

    Indeed, but that is not all.
    Code:
            dma.TCD->SOFF = 4;
            dma.TCD->NBYTES_MLNO = 4;
    Edit2: I think I have the stream working. Now I need to check if audio is actually coming out.
    Also I think it can now still be used together with the audio shield, where the audio shield can only be used as input.
    This also allows for exact 44100 kHz sampling. But first: get it working.
    Attached Files Attached Files
    Last edited by kpc; 05-21-2015 at 02:56 PM.

  17. #42
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    I need a cinch output. But optional toslink is great. I saw some some example circuits somewhere, but they were TTL, not 3.2V.

    Regarding IS2, the best format would be 32 Bits per channel, LSB first. This is very close to the spdif format.

  18. #43
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    OK now the file with the right bitstream (I think).
    I now use 16 bit DMA copying and also 16 bit output from the I2S module. I know it is very ugly but it seems to do the trick for now.
    I had to add ugly __REV(__REV16(...)).
    The __REV16() is I think needed due to the 16 bit copying of DMA.
    But also the byte order seems reversed, hence the __REV(). Bit order however is OK.

    I cannot get any sound out of my amplifier yet. Either the bitstream is still wrong, or I cannot get enough light in the TOSLINK cable. (I only have a 15 meter version, which is on the long side). I tested with the LED on the teensy itself and also a TOSLINK LED module rescued from an old CD-player. But this was made for 5 volt and I cannot access the internal resistor.

    Can anybody with a logic analyzer provide me with an example of a S/P-DIF stream, so that I can verify my data? I do have a bus-pirate, but the signals are too fast for it.
    Attached Files Attached Files

  19. #44
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    Quote Originally Posted by kpc View Post
    OK now the file with the right bitstream (I think).
    I now use 16 bit DMA copying and also 16 bit output from the I2S module. I know it is very ugly but it seems to do the trick for now.
    I had to add ugly __REV(__REV16(...)).
    The __REV16() is I think needed due to the 16 bit copying of DMA.
    But also the byte order seems reversed, hence the __REV(). Bit order however is OK.

    I cannot get any sound out of my amplifier yet. Either the bitstream is still wrong, or I cannot get enough light in the TOSLINK cable. (I only have a 15 meter version, which is on the long side). I tested with the LED on the teensy itself and also a TOSLINK LED module rescued from an old CD-player. But this was made for 5 volt and I cannot access the internal resistor.

    Can anybody with a logic analyzer provide me with an example of a S/P-DIF stream, so that I can verify my data? I do have a bus-pirate, but the signals are too fast for it.
    Perhaps we can get rid of some of the _REV later, with reversing the table and the rest.
    I have a cheap 20MHz LA (should be ok for 5.6 MHz) , but unfortunately I will be the next few days on the road, so i can't do any measuring before friday.
    Are you sure, that your 11MHz clock is ok ? How do you transfer the data, with doubling every bit or gaps between them ? As i understood it, we need 5.6 MHZ, not more, and a continous datastream, least significant bit first.
    Regarding the light, I read that best works a 660 nm LED. It depends on the receiving-side how sensitive it is for other colors.
    Last edited by Frank B; 05-21-2015 at 06:08 PM.

  20. #45
    Senior Member
    Join Date
    Jan 2015
    Location
    frisia
    Posts
    285
    When watching on an oscilloscope, the stream seems like I want it to be, no gaps and the proper frequency. You are right, the __REV's are temporary. Also the 16 bit copying and outputting should be changed to proper 32 bit versions. But I first would like to hear some output.
    This weekend I will grep a proper 5V buffer with sufficient speed, to properly steer my TOSLINK LED.

  21. #46
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    Not measured, but a "Screenshot" from sigrok. I think this helps a bit.


    http://sigrok.org/wiki/Protocol_decoder:Spdif

    I hope that I find time for this on sunday....


    Edit:
    Screenshot of the preambles only, looks ok so far.
    Click image for larger version. 

Name:	spdif1.jpg 
Views:	139 
Size:	84.0 KB 
ID:	4399
    Currently, i've configured I2S & DMA for 8-Bit, this makes the whole thing a easier.
    The LR-Clock is synced to the preambles.
    Last edited by Frank B; 05-31-2015 at 10:21 AM.

  22. #47
    Junior Member
    Join Date
    Mar 2014
    Posts
    1
    Hi All,

    Interesting subject. I've been doing some cursory research in this area of late and stumbled upon this link;

    http://www.minidsp.com/products/usb-...e/ministreamer

    Hopefully it is useful to this topic. It might be interesting to integrate into the Teensy 3 audio eco system. Any thoughts if it is not off topic by to much is welcome.

    Thank you,

    Jon

  23. #48
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347

    Smile Success!!

    Success !!
    Yeah :-)

    I have a stereo 1-khz "beep". Not from the audiolib, but it is the proof that the teensy is able to output SPDIF :-)
    I took a bright white LED (had no red LED in stock that was bright enough) and a TOSLINk cable.

    This is the best 1000Hz beep I have ever heard ;-)

    The rest is.. a "todo", but the main problems are solved now. The "connection" to the Audio-Library is missing, but that's not too complicated.
    I think, that i can upload (GITHUB) a first working version in the next days.

    Click image for larger version. 

Name:	spdif_beep.jpg 
Views:	117 
Size:	68.0 KB 
ID:	4400
    Last edited by Frank B; 05-31-2015 at 07:35 PM.

  24. #49
    Senior Member+ Frank B's Avatar
    Join Date
    Apr 2014
    Location
    Germany NRW
    Posts
    4,347
    @Paul,
    i never used DMA and I2S at this Level; and have only little knowlage about it (what is a "minor loop"?)

    Currently I use the 16-Bit configuration from the I2S-output (Audiolib)
    Better would be the following (i tried, but had no success):

    There is a buffer:
    DMAMEM static uint8_t SPDIF_tx_buffer[192 * 2 * 2 * 4];

    I want to output it as 32 Bit values (currently 16)
    We don't need any clock-signals, but for debugging it is good to configure the LRCLK as a sync-signal every 64 bit (this is a spdif-channel ) - i managed to do this for the current 16 bit output.
    (2 * 64 Bit (=2 channels) are a "Frame", 192 "Frames" a "Block" - the tx_buffer from above is a whole block)

    The DMA & I2S config needs to be changed to output the raw 32 Bit data from the buffer continously, with "I2S_TCR4_MF" not set (->LSB first)
    Can you help ?
    Last edited by Frank B; 05-31-2015 at 09:14 PM.

  25. #50
    Senior Member PaulStoffregen's Avatar
    Join Date
    Nov 2012
    Posts
    16,298
    Quote Originally Posted by Frank B View Post
    Can you help ?
    Yes, but probably can't do very much until next week when I have all the hardware.

    My purple PCB arrived this weekend. I have not soldered it yet, but I will soon. The connectors arrived from Digikey quite some time ago.

    I ordered a TOSLINK to RCA audio adaptor and an optical cable on Amazon. Their shipping info says it will arrive on June 6 (yeah, I used the free but slow shipping, and Amazon took several days before shipping it... I think they intentionally delay if you don't pay for their "prime" service). It's a UPS tracking number. I do not believe UPS will really deliver on Saturday. Usually only postal mail arrives on the weekend. It's likely I will get it on Monday, June 8.

    I could look at the waveform on my oscilloscope, but that would be very difficult to know if it's really working.
    Last edited by PaulStoffregen; 06-01-2015 at 08:58 AM.

Posting Permissions

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