Switch RX SPDIF input port on the fly Topic is solved

Sub forums for various specialist XMOS applications. e.g. USB audio, motor control and robotics.
Post Reply
ffomich
Experienced Member
Posts: 119
Joined: Mon Sep 15, 2014 1:32 pm

Switch RX SPDIF input port on the fly

Post by ffomich »

Hi,

I have self-made board with Analog, AES/EBU XLR3 & S/PDIF TOSLINK inputs.

I have UAC1 firmware based on USB Audio 2.0 project with input selector. I can switch input using Windows Volume Control. At one time only one input is active.

Software module SpdifReceive() decodes input digital stream.

It works correctly if I change input port statically.

on tile[SPDIF_RX_TILE] : buffered in port:4 p_spdif_rx = PORT_SPDIF_IN;
or
on tile[SPDIF_RX_TILE] : buffered in port:4 p_spdif_rx = PORT_AES_IN;

Code: Select all

main()
{
   par
   {
    ...
    SpdifReceive(p_spdif_rx, c_spdif_rx, 1, clk_spd_rx);
   }
}
My question is:
Is it possible to change input port on the fly while firmware is running?

May be like this:
on tile[SPDIF_RX_TILE] : buffered in port:4 p_digital_rx[2] = {PORT_AES_IN,PORT_SPDIF_IN};

Code: Select all

main()
{
   par
   {
    ...
    SpdifReceive(p_digital_rx[index], c_spdif_rx, 1, clk_spd_rx);
   }
}
"index" is changed in AudioClassRequests_1()


View Solution
User avatar
Ross
XCore Expert
Posts: 962
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

(I added code tags to your post to make it a bit more readable..)

Ignoring any horrible workarounds such as changing the port resource ID under the SPDIF codes nose or a external physical mux, it seems to me that you need an Kill command to the SPDIF core. (You would save a 1-bit port with something external of course..)

SpdifReceive() would then exits and you can call it with another port. This isn't something it supports at the moment by the looks of it and would need adding.

Another option its to run 2 x SpdifReceive() cores and select which ones output to use.. This required no extra work on the SPDIF code, but would burn some more MIPs/Power. I suppose this would give the neat switch.
ffomich
Experienced Member
Posts: 119
Joined: Mon Sep 15, 2014 1:32 pm

Post by ffomich »

Thank you Ross,
I'll try to run 2xSpdifReceive()
ffomich
Experienced Member
Posts: 119
Joined: Mon Sep 15, 2014 1:32 pm

Post by ffomich »

I have challenge while trying to use 2xSpdifReceive().

Original project architecture is:

Code: Select all

XMOS input port -> spdifReceive(channel) -> clockGen(channel) -> ... -> mixer() -> USB recording
My idea is:

Code: Select all

XMOS input port1 -> spdifReceive(ch1) -\ 
                                          -> clockGen(ch1, ch2) -> ... -> mixer() -> USB rec
XMOS input port2 -> spdifReceive(ch2) -/
spdifReceive() is written in asm, so I try to add input switching into clockGen().

Code: Select all

void clockGen(channel) - original
{
  ...
  while(1)
  {
     select
     {
            case ...:
            case ...:

            /* Receive sample from S/PDIF RX thread (steaming chan) */
            case channel:> tmp:

                ...
                break;

     } // eo select
  }// eo while

}
Index of current input I send from AudioClassRequests_1() to clockGen() via already existing c_clk_ctl channel.

The challenge is how to add if(index == INPUT_1) into select statement.
I want to realize something like this:

Code: Select all

void clockGen(ch1, ch2, c_clk_ctl)
{
  unsigned char index;
  while(1)
  {
     select
     {
            ...
            case c_clk_clk event:
              get index from c_clk_ctl channel
              break;

if (index == INPUT_1)
{
            /* Receive sample from S/PDIF rx port */
            case ch1 :> tmp:
}
else
{
            /* Receive sample from AES/EBU rx port */
            case ch2 :> tmp:
}
                ...
                break;

     } // eo select
  }// eo while

}
The only way I can realize it is:

Code: Select all

void clockGen(ch1, ch2, c_clk_ctl)
{
  unsigned char index;
  while(1)
  {
  if (index == INPUT_1)
  {
     select
     {
            ...
            case c_clk_clk event:
              get index from c_clk_ctl channel
              break;

            /* Receive sample from S/PDIF rx port */
            case ch1 :> tmp:
     } // eo select

  }
  else
  {
     select
     {
            ...
            case c_clk_clk event:
              get index from c_clk_ctl channel
              break;

            /* Receive sample from AES/EBU rx port */
            case ch2 :> tmp:
                ...
                break;
     } // eo select
  }// eo if

  }// eo while

}
But it doesn't work.:( No sound from both digital inputs.

Can anybody recommend me code contruction to switch inputs in clockGen()?

P.S. There is workaround to pass audio samples from both digital inputs to mixer() and switch inputs there, but this is an extreme case.
ffomich
Experienced Member
Posts: 119
Joined: Mon Sep 15, 2014 1:32 pm

Post by ffomich »

I have found error in this part of my code:

Code: Select all

case c_clk_clk event:
              /* Get index from c_clk_ctl channel */
              break;
Now my realization with doubling select works correctly.

Code: Select all

while(1)
{
  if (index == INPUT_1)
  {
     select
     {
            ...
            case c_clk_clk event:
              /* Get index from c_clk_ctl channel */
              break;

            case ch1 :> tmp:
              /* Receive sample from S/PDIF rx port */
              break;
     } // eo select

  }
  else
  {
     select
     {
            ...
            case c_clk_clk event:
              /* Get index from c_clk_ctl channel */
              break;

            case ch2 :> tmp:
              /* Receive sample from AES/EBU rx port */
                break;
     } // eo select
  }// eo if

}// eo while
User avatar
Ross
XCore Expert
Posts: 962
Joined: Thu Dec 10, 2009 9:20 pm
Location: Bristol, UK

Post by Ross »

Congrats, glad you have that working!
Post Reply