Read and write simultaneously from a port

If you have a simple question and just want an answer.
RValls
New User
Posts: 2
Joined: Fri Jun 05, 2015 8:21 am

Read and write simultaneously from a port

Post by RValls »

Hi all!

I am starting with XMOS, and I am a bit confused with ports, timed IO and so.

I have been able to link a clock with an external clock input to a port, and write and read to/from the data port, independently, but not simultaneously.

Can somebody explain how could it be done?

How the timed input works?

Why the processor is hanged waiting?

And finally, what is wrong in my code?

The data I am handling is a TDM data bus, with sync signal, bclk, data_in and data_out ports. The sync and bclk works fine, data_out works fine IF there is no read. When I read, my data write is delayed.

 

#include "tdm_master.h"

#include <xclib.h>
 
//Configures the ports
static void tdm_master_configure_ports(
        out buffered port:32 p_dout[num_out],
        static const size_t num_out,
        in buffered port:32 p_din[num_in],
        static const size_t num_in,
        out buffered port:32 p_tdm_sync,
        in port p_bclk,
        clock clk)
{
    int i;
 
    configure_clock_src(clk, p_bclk);
 
    configure_out_port(p_tdm_sync, clk, 0);
    for (i=0;i<num_out;++i)
        configure_out_port(p_dout, clk, 0);
    for (i=0;i<num_in;++i)
        configure_in_port(p_din, clk);
 
   start_clock(clk);
}
 
#define PORT_IN(p, x) asm("in %0, res[%1]" : "=r"(x)  : "r"(p))
#define PORT_SET_TIME(p, t) asm("setpt res[%0], %1" :: "r"(p), "r"(t));
 
//Write data to the output ports. This function processes all the outport ports, since there may be more than one
[[always_inline]]
 static void tdm_master_output_ch(client tdm_callback_if tdm_i,
         out buffered port:32 p_dout[num_out],
         static const size_t num_out,
         size_t frame_ch,
         size_t channels_per_frame
         )
{
    for (int i=0;i<num_out;++i) {
        //Ask the interface to send a new value.
        p_dout <: bitrev(tdm_i.send((channels_per_frame*i)+(frame_ch)));
    }
}
 
//Read data from the input ports. This function processes all the input ports, since there may be more than one
[[always_inline]]
 static void tdm_master_input_ch(client tdm_callback_if tdm_i,
         in buffered port:32 p_din[num_in],
         static const size_t num_in,
         size_t frame_ch,
         size_t channels_per_frame
         )
{
    int32_t value;
 
    for (int i=0;i<num_in;++i) {
        p_din :> value;
        //Notify the interface we have received a new value
        tdm_i.receive((channels_per_frame*i)+(frame_ch), bitrev(value));
    }
}
 
//Main function. 
//There is only 1 output port and 1 input port, but I want the code to be ready to support more than one I/O ports.
 void tdm_custom(client tdm_callback_if tdm_i,
         out buffered port:32 p_dout[num_out],
         static const size_t num_out,
         in buffered port:32 p_din[num_in],
         static const size_t num_in,
         out buffered port:32 p_tdm_sync,
         in port p_bclk,
         clock clk
         )
{
    int i;
    tdm_master_config_t config;
    tdm_i.init(config);
 
    uint32_t sync_mask=(1<<config.sync_len)-1;
    //sync_mask=0x1
    //config.channels_per_frame=8
 
    tdm_master_configure_ports(p_dout, num_out, p_din, num_in, p_tdm_sync, p_bclk, clk);
 
    //I configure the port time. I have seen this somewhere, but I don't know actually why I have chosen this values
    for (i=0;i<num_out;++i) {
        PORT_SET_TIME(p_dout, 0);
        p_dout @ 64 <: 0;
    }
 
    for (i=0;i<num_in;++i) {
        PORT_SET_TIME(p_din, 31);
    }
 
    PORT_SET_TIME(p_tdm_sync, 0);
    p_tdm_sync @ 64 <: 0;
 
    while (1) {
        int32_t value;
 
        //We send the first
        p_tdm_sync <: sync_mask;
        tdm_master_output_ch(tdm_i, p_dout, num_out, 0, config.channels_per_frame);
 
        //Now process the other channels in the frame
        for (int curr_channel=1;curr_channel<config.channels_per_frame;++curr_channel) {
            //First we read them
            tdm_master_input_ch(tdm_i, p_din, num_in, curr_channel-1, config.channels_per_frame);
 
            //And now we send them
            p_tdm_sync <: 0;
            tdm_master_output_ch(tdm_i, p_dout, num_out, curr_channel, config.channels_per_frame);
        }
 
        //Finally read the last one.
        tdm_master_input_ch(tdm_i, p_din, num_in, config.channels_per_frame-1, config.channels_per_frame);
    }
}
 
Any help is appreciated.
 
Best regards,
Ruben
Guest

Post by Guest »

You can configure te port as output port and send data out on the port. Simulteneously, you can use peek() function to peek the current value on the port. peek is available in xs1.h.