discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] Simples case of message passing


From: Marcus Müller
Subject: Re: [Discuss-gnuradio] Simples case of message passing
Date: Sun, 08 Feb 2015 18:03:46 +0100
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0

Hello Daniel, hi Rich,

if you actually want to pass a string as PMT, the pmt::intern("..") is ok (although it has a performance penalty[0]).
If you want to simply sent byte buffers, the uniform vectors approach would be the best (have a look at make_uvector8).

As for a simple example of message passing: I didn't try very thoroughly to understand your code, but it seems a bit complicated for what it tries to achieve (which is simply sending a message when there's stream items available). For one, there's message_sink / _source which already converts from stream to message port for you; secondly, I don't understand your meta object at all, sorry.

I think there's a simpler example for message sending in our guided tutorials [1], specifically in part 5, with the chat application's source code here [2], but that's python; however, C++ and python implementations would closely resemble each other here.

Now, that example is far more general purpose -- but there's a whole framework dedicated to processing digital signals in gr-digital. I do recommend looking at the OFDM examples [3], but for your classical preamble method, the test_corr_and_sync.grc[4] example is likely close to what you want. It's centered around digital::correlate_and_sync_cc [5]. You'll notice that it just passes through all samples, and whenever it detects a preamble, adds stream tags [important concept here, 6] denoting that estimate. The downstream PFB time sync and the costas loop then use the time_est and the phase_est tag to synchronize to the transmitter. Of course, you'd still have to "throw away" everything that's not part of a packet yourself.

With that functionality in mind, I'd like to direct your attention to the tx_ofdm.grc example:
1. It uses tagged streams; these are just sample streams (not message ports), but for blocks that do care, the GNU Radio scheduler makes sure that there's always exactly one "packet" worth of items available (as marked by a specified tag). That's the preferred way of dealing with packeted data -- it lets you use all the standard blocks on items (eg. multiply etc), whilst still keeping the packeted structure.
2. It uses the packet header generator [7], which takes in bytes of data, and generates a header for these -- which will enable the header_payload_demux[8] to function. You'd still need a preamble and a correlation -- but correlate_and_sync emits tags, any one of which's keys you can use as trigger key for header_payload_demux.

Now, I must admit that I'm not absolutely sure where correlate_and_sync adds its tags (ie. at the center of the detected preamble or somewhere else), so it's possible you'd have to account for a fixed distance.

I hope that this gives you a few useful hints.
Best regards & happy hacking,

Marcus M

PS: By the way, simple_{framer,correlator} are in the deprecated group[10], which I guess is the reason writing documentation had had a low priority.

[0] Strings are internalized in PMT, ie. they are hashed upon creation and a new PMT is only
[1] https://gnuradio.org/redmine/projects/gnuradio/wiki/Guided_Tutorials
[2] https://github.com/gnuradio/gr-tutorial/blob/master/python/chat_blocks.py
[3] https://github.com/gnuradio/gnuradio/tree/master/gr-digital/examples/ofdm ; These files are usually installed somewhere like /usr/share/gnuradio/examples/digital
[4] https://github.com/gnuradio/gnuradio/blob/master/gr-digital/examples/demod/test_corr_and_sync.grc
[5] http://gnuradio.org/doc/doxygen/classgr_1_1digital_1_1correlate__and__sync__cc.html
[6] https://gnuradio.org/redmine/projects/gnuradio/wiki/Guided_Tutorial_Programming_Topics#52-Stream-Tags
[7] http://gnuradio.org/doc/doxygen/classgr_1_1digital_1_1packet__headergenerator__bb.html
[8] http://gnuradio.org/doc/doxygen/classgr_1_1digital_1_1header__payload__demux.html
[10] http://gnuradio.org/doc/doxygen/group__deprecated__blk.html
On 02/08/2015 02:48 AM, Daniel Franch wrote:
Earlier today, I've posted a question on how to do frame detection and extraction in GNU Radio (http://gnuradio.4.n7.nabble.com/Simple-Frame-Detection-td52233.html). I have a feeling that the best way to accomplish what I need is using the message passing system. 

But I simply can't find an easy enough example to understand how message passing works. So I tried to create two simple blocks in order to better understand this system. I simply wanted a block that would receive a stream (not neccesarily tagged) of bytes and then post them as a message. The other one would receive this message and then output the same stream of bytes. I know there are message source/sink blocks that do this, but as I understand, they work on a previous message passing system. 

My blocks were written this way: 

Message writing: 
message_write_b_impl::message_write_b_impl() 
      : gr::sync_block("message_write_b", 
              gr::io_signature::make(1, 1, sizeof(char)), 
              gr::io_signature::make(0, 0, 0)) 
    { 
        message_port_register_out(pmt::mp("out")); 
        buffer = new char[128]; 
        counter = 0; 
    } 

    /* 
     * Our virtual destructor. 
     */ 
    message_write_b_impl::~message_write_b_impl() 
    { 
        delete[] buffer; 
    } 
    
    void 
    message_write_b_impl::send_message() 
    { 
        pmt::pmt_t meta = pmt::make_dict(); 
        pmt::pmt_t payload = pmt::from_long(long(buffer[counter++])); 
        message_port_pub(pmt::mp("out"), pmt::cons(meta, payload)); 
        std::memset(buffer, 0, sizeof(buffer)); 
    } 

    int 
    message_write_b_impl::work(int noutput_items, 
                          gr_vector_const_void_star &input_items, 
                          gr_vector_void_star &output_items) 
    { 
        const char *in = (const char *) input_items[0]; 

        for(int i = 0; i < noutput_items; i++) 
        { 
            buffer[counter] = in[i]; 
            this->send_message(); 
            
            if(counter >= 128) 
            { 
                counter = 0; 
            }             
        } 
        consume_each(noutput_items); 
        
        return 0; 
    } 

Message read: 
message_read_b_impl::message_read_b_impl() 
      : gr::sync_block("message_read_b", 
              gr::io_signature::make(0, 0, 0), 
              gr::io_signature::make(1, 1, sizeof(char))) 
    { 
        message_port_register_in(pmt::mp("in")); 
        set_msg_handler(pmt::mp("in"), 
        boost::bind(&message_read_b_impl::in_handling, this, _1)); 
        
        buffer = new char[128]; 
        counter = 0; 
        rx_check = false; 
    } 

    /* 
     * Our virtual destructor. 
     */ 
    message_read_b_impl::~message_read_b_impl() 
    { 
        delete[] buffer; 
    } 
    
    void 
    message_read_b_impl::in_handling(pmt::pmt_t msg) 
    { 
        if(pmt::is_integer(msg)) 
        { 
            buffer[counter++] = char(pmt::from_long(msg)); 
            rx_check = true; 
        } 
        if(counter == 128) 
        { 
            counter = 0; 
            rx_check = false; 
        } 
    } 

    int 
    message_read_b_impl::work(int noutput_items, 
                          gr_vector_const_void_star &input_items, 
                          gr_vector_void_star &output_items) 
    { 
        char *out = (char *) output_items[0]; 

        for(int i = 0; i < noutput_items; i++) 
        {       
            while(!rx_check); 
            out[i] = buffer[i]; 
        } 
        return noutput_items; 
    } 

As far as I understand, this could be the simplest case to send bytes through messages. But I feel there is something wrong, as the pmt doesn't seem to have a method to deal with chars, so I have to do lots of conversions. Still, this didn't seem to be a reason of bigger concerns. 

My python QA block simply does a message connect between their message ports. But when I try to run the test, the tb simply freezes and I have to finish with ctrl+C. 

Is there any easier way to implement message passing? 

Thanks in advance, 
Dan Franch


_______________________________________________
Discuss-gnuradio mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio


reply via email to

[Prev in Thread] Current Thread [Next in Thread]