root/ossiedev/branches/drdepoy/USRP_UHD_0.8.2/src/USRP_UHD.cpp @ 10608

Revision 10608, 9.1 KB (checked in by drdepoy, 4 years ago)

UHD device for 0.8.2

Line 
1/****************************************************************************
2
3Copyright 2005,2006 Virginia Polytechnic Institute and State University
4
5This file is part of the OSSIE USRP_UHD Device.
6
7OSSIE USRP_UHD Device is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 2 of the License, or
10(at your option) any later version.
11
12OSSIE USRP_UHD Device is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with OSSIE USRP_UHD Device; if not, write to the Free Software
19Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
21
22****************************************************************************/
23
24#include <byteswap.h>
25#include <iostream>
26#include <vector>
27#include <complex>
28
29#include "ossie/cf.h"
30#include "ossie/PortTypes.h"
31
32#include "ossie/ossieSupport.h"
33#include "ossie/debug.h"
34
35#include "USRP_UHD.h"
36
37USRP_UHD_i::USRP_UHD_i(char *id, char *label, char *profile) :
38        Device_impl(id, label, profile),
39        set_rx_packet_count(-1),
40        rx_packet_count(1024),
41        rx_packet_size(256),
42        rx_data_size(2),
43        number_of_channels(1),
44        complex(true),
45        rx_overruns(0),
46        rx_active(false),
47        tx_active(false),
48        full_duplex(false),
49        did_rx(false)
50{
51// Create USRP_UHD Control ports for TX and RX
52    rx_control_port = new USRP_UHD_RX_Control_i(this, "U2_RX_Control", "DomainName1");
53    tx_control_port = new USRP_UHD_TX_Control_i(this, "U2_TX_Control", "DomainName1");
54
55// Create the ports for TX data
56    tx_data_port = new standardInterfaces_i::complexShort_p("U2_TX_Data", "DomainName1");
57
58// Create the ports for RX Data
59    rx_data_1_port = new standardInterfaces_i::complexShort_u("U2_RX_Data_1", "DomainName1");
60    rx_data_2_port = new standardInterfaces_i::complexShort_u("U2_RX_Data_2", "DomainName1");
61}
62
63void USRP_UHD_i::start() throw (CF::Resource::StartError, CORBA::SystemException)
64{
65    DEBUG(3, USRP_UHD, "Start USRP_UHD called")
66}
67
68void USRP_UHD_i::stop() throw (CF::Resource::StopError, CORBA::SystemException)
69{
70    DEBUG(3, USRP_UHD, "Stop USRP_UHD called")
71    (rx_active)?std::cout<<"Active": std::cout<<"NOT Active";
72}
73
74CORBA::Object_ptr USRP_UHD_i::getPort(const char* portName)
75throw(CF::PortSupplier::UnknownPort, CORBA::SystemException)
76{
77    DEBUG(3, USRP_UHD, "USRP_UHD getPort called with : " << portName)
78
79    CORBA::Object_var p;
80
81    if (!CORBA::is_nil(p = rx_control_port->getPort(portName)))
82        return p._retn();
83    else if (!CORBA::is_nil(p = rx_data_1_port->getPort(portName)))
84        return p._retn();
85    else if (!CORBA::is_nil(p = rx_data_1_port->getPort(portName))) {
86        return p._retn();
87    } else if (!CORBA::is_nil(p = tx_control_port->getPort(portName))) {
88        return p._retn();
89    } else if (!CORBA::is_nil(p = tx_data_port->getPort(portName))) {
90        return p._retn();
91    }
92    std::cerr << "Couldn't find port " << portName << "Throwing exception" << std::endl;
93    throw CF::PortSupplier::UnknownPort();
94}
95
96void USRP_UHD_i::initialize() throw (CF::LifeCycle::InitializeError, CORBA::SystemException)
97{
98    DEBUG(3, USRP_UHD, "USRP_UHD Initialize called")
99    std::string args("addr=192.168.10.2");
100    DEBUG(1, USRP_UHD, "Creating the usrp device with: "<< args)
101    sdev = uhd::usrp::single_usrp::make(args);
102    dev = sdev->get_device();
103    sdev->set_rx_antenna("RX2");
104    sdev->set_rx_antenna("TX/RX");
105    DEBUG(1, USRP_UHD, "Using Device: "<< sdev->get_pp_string())
106}
107
108void USRP_UHD_i::configure(const CF::Properties &configProperties)
109throw (CORBA::SystemException, CF::PropertySet::InvalidConfiguration,
110       CF::PropertySet::PartialConfiguration)
111{
112
113}
114
115void USRP_UHD_i::query(CF::Properties &configProperties)
116throw (CORBA::SystemException, CF::UnknownProperties)
117{
118
119}
120
121
122void USRP_UHD_i::releaseObject()
123throw (CF::LifeCycle::ReleaseError, CORBA::SystemException)
124{
125
126    DEBUG(3, USRP_UHD, "USRP_UHD releaseObject called")
127}
128
129
130void USRP_UHD_i::rx_data_process()
131{
132
133///\TODO assumes one channel operation.  Set full_deplex to false to prevent Rx buffering during Tx
134///Full duplex mode is still broken. we still cannot transmit and receive simultaneously using WBX board
135
136    //tells the device to stream samples indefinitely
137    uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
138
139    //Use with STREAM_MODE_NUM_SAMPS_AND_DONE/_MORE     
140    //stream_cmd.num_samps = 65536;
141    //stream_cmd.time_spec = uhd::time_spec_t((time_t)0);
142   
143    //When true, the device will begin streaming ASAP
144    stream_cmd.stream_now = true;
145
146    sdev->issue_stream_cmd(stream_cmd);
147
148    PortTypes::ShortSequence I;
149    PortTypes::ShortSequence Q;
150   
151///\TODO Make sure rx_packet_size is >= than USRP_UHD_MIN_RX_SAMPLES!!!!!
152    rx_buff.resize(rx_packet_size);
153    I.length(rx_packet_size);
154    Q.length(rx_packet_size);
155
156    DEBUG(3, USRP_UHD, "RX packet count " << rx_packet_count)
157
158    while (rx_active && ((rx_packet_count == -1) || (rx_packet_count > 0))) {
159        uhd::rx_metadata_t md;
160//if we are running half duplex mode we will need to tell start streaming at the beginning of the loop
161        if (full_duplex == false && did_rx == false)  {
162                uhd::stream_cmd_t stream_cmd(uhd::stream_cmd_t::STREAM_MODE_START_CONTINUOUS);
163                sdev->issue_stream_cmd(stream_cmd);
164                did_rx = true;
165        }
166
167       
168//TODO get rid of num_rx_samps variable
169        size_t num_rx_samps = dev->recv( &rx_buff.front(), rx_packet_size, md,
170                                        uhd::io_type_t::COMPLEX_INT16,
171                                        uhd::device::RECV_MODE_FULL_BUFF);
172       
173        //Handle UHD error codes
174        switch(md.error_code){
175            case uhd::rx_metadata_t::ERROR_CODE_NONE:
176                break;
177            case uhd::rx_metadata_t::ERROR_CODE_TIMEOUT:
178                DEBUG(3, USRP_UHD, "Got timeout before all samples received, possible packet loss")
179                break;
180            default:
181                DEBUG(3, USRP_UHD, "Got error code 0x"<<md.error_code)
182        }
183
184        for (unsigned int i = 0; i < num_rx_samps; i++) {
185            I[i] = (CORBA::Short) rx_buff[i].real();
186            Q[i] = (CORBA::Short) rx_buff[i].imag();
187        }
188        rx_data_1_port->pushPacket(I, Q);
189       
190        if (rx_packet_count != -1)
191            --rx_packet_count;
192    }
193
194    DEBUG(3, USRP_UHD, "Exiting rx_data_process thread")
195    //tells the device to stop streaming samples
196    stream_cmd = uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS;
197    sdev->issue_stream_cmd(stream_cmd);
198    rx_active = false;
199    rx_thread->exit();
200}
201
202
203
204// USRP_UHD Expects data in little endian format
205static inline short convertToLE(short s)
206{
207#ifdef __powerpc__
208    s = bswap_16(s);
209#endif
210
211    return s;
212}
213
214void USRP_UHD_i::tx_data_process()
215{
216    PortTypes::ShortSequence *I_in, *Q_in;
217
218    const unsigned int tx_buf_len(USRP_UHD_MAX_TX_SAMPLES);
219
220    uhd::tx_metadata_t md3;
221
222    //Set start and end of burst flags to help with packet fragmentation if needed
223    //Host will send ACK packets when an EOB flag is received
224    //SOB true -> first packet in sequence gets SOB flag
225    //EOB true -> last packet in sequence gets EOB flag
226    md3.start_of_burst = false; 
227    md3.end_of_burst   = false;     
228
229    //We can send packets in the future if needed
230    //md.has_time_spec  = 0;     //no time
231    //md.time_spec = uhd::time_spec_t((time_t)0 );
232
233    std::vector< std::complex<short int> > tx_buff(tx_buf_len);
234
235    DEBUG(3, USRP_UHD, "Starting tx_data_process thread.")
236   
237    tx_active = true; // Cleared to stop TX in USRP_UHD_TX_Control->stop()
238
239    while (tx_active) {
240        //if running half duplex mode we want to stop Rx streaming while transmitting
241        if (full_duplex == false && did_rx == true)  {
242                did_rx = false;         
243                uhd::rx_metadata_t md;
244                size_t num_rx_samps = dev->recv( &rx_buff.front(), rx_packet_size, md,
245                                                uhd::io_type_t::COMPLEX_INT16,
246                                                uhd::device::RECV_MODE_FULL_BUFF);             
247                sdev->issue_stream_cmd(uhd::stream_cmd_t::STREAM_MODE_STOP_CONTINUOUS);
248               
249        }
250
251
252        tx_data_port->getData(I_in, Q_in);
253        size_t samps_to_send = I_in->length();
254       
255        if(samps_to_send > tx_buf_len){
256            std::cerr << "USRP_UHD Tx Buffer Overflow. Throwing Exception"<<std::endl;
257            throw std::runtime_error("USRP_UHD buffer overflow");
258        }
259
260        for (unsigned int i = 0; i < samps_to_send; ++i) {
261            tx_buff[i] = std::complex<short int> (convertToLE((*I_in)[i]),
262                                                 convertToLE((*Q_in)[i]));
263        }
264
265        //send the entire packet (driver fragments internally)
266        size_t num_tx_samps = dev->send( &tx_buff.front(), samps_to_send, md3,
267                                        uhd::io_type_t::COMPLEX_INT16,
268                                        uhd::device::SEND_MODE_FULL_BUFF);
269        tx_data_port->bufferEmptied();
270               
271    }
272   
273    DEBUG(3, USRP_UHD, "Exiting tx_data_process thread.")
274    tx_thread->exit();
275}
Note: See TracBrowser for help on using the browser.