/* -*- c++ -*- */ /* * Copyright 2008 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3, or (at your option) * any later version. * * GNU Radio is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #ifdef HAVE_ARPA_INET_H #include #endif #ifdef HAVE_NETINET_IN_H #include #endif #ifdef HAVE_SYS_SOCKET_H #include #endif #define DEBUG(A) printf("=debug=> %s\n", A) static void optimize_socket(int socket); /* * Holds types that need autoconf help. They're here and not in the .h file because * here we've got access to config.h */ class MSDD6000_RS::detail { public: struct sockaddr_in d_sockaddr; }; MSDD6000_RS::MSDD6000_RS(char* addr) : d_detail(new MSDD6000_RS::detail()) { d_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); optimize_socket(d_sock); // set up remote sockaddr // int s = inet_aton(addr, &d_adx); d_detail->d_sockaddr.sin_family = AF_INET; d_detail->d_sockaddr.sin_port = htons(10000); int s = inet_aton(addr, &d_detail->d_sockaddr.sin_addr); // set up local sockaddr struct in_addr d_myadx; struct sockaddr_in d_mysockaddr; short int port = 10010; d_myadx.s_addr = INADDR_ANY; d_mysockaddr.sin_family = AF_INET; d_mysockaddr.sin_port = htons(port); memcpy(&d_mysockaddr.sin_addr.s_addr, &d_myadx.s_addr, sizeof(in_addr)); //d_sockaddr.sin_addr = INADDR_ANY; s = bind(d_sock, (const sockaddr*) &d_mysockaddr, sizeof(d_mysockaddr)); // set default values //d_decim = 2; d_ddc_gain = 2; d_rf_attn = 0; d_fc_mhz = 3500; d_offset_hz = 0; d_ddc_gain = 0; d_ddc_sample_rate_khz = 25600; d_ddc_bw_khz = 25600; d_start = 0; d_state = STATE_STOPPED; } MSDD6000_RS::~MSDD6000_RS() { //printf("MSDD6000_RS::Destructing\n"); close(d_sock); } static void optimize_socket(int socket){ #define BANDWIDTH 1000000000/8 #define DELAY 0.5 int ret; int sock_buf_size = static_cast(2*BANDWIDTH*DELAY); char textbuf[512]; snprintf(textbuf, sizeof(textbuf), "%d", sock_buf_size); printf("sock_buf_size = %d\n", sock_buf_size); ret = setsockopt(socket, SOL_SOCKET, SO_SNDBUF, &sock_buf_size, sizeof(sock_buf_size)); ret = setsockopt(socket, SOL_SOCKET, SO_RCVBUF, &sock_buf_size, sizeof(sock_buf_size)); int uid = getuid(); if(uid!=0){ printf(" ****** COULD NOT OPTIMIZE SYSTEM NETWORK PARAMETERS BECAUSE YOU ARE NOT RUNNING AS ROOT *******\n ****** YOUR MSDD6000_RS RECIEVER PERFORMANCE IS GOING TO BE TERRIBLE *******\n"); return; } // SET UP SOME SYSTEM WIDE TCP SOCKET PARAMETERS // FIXME seems like kind of a big hammer. Are you sure you need this? FILE* fd = fopen("/proc/sys/net/core/netdev_max_backlog", "w"); if (fd){ fwrite("10000", 1, strlen("10000"), fd); fclose(fd); } fd = fopen("/proc/sys/net/core/rmem_max", "w"); if (fd){ fwrite(textbuf, 1, strlen(textbuf), fd); fclose(fd); } fd = fopen("/proc/sys/net/core/wmem_max", "w"); if (fd){ fwrite(textbuf, 1, strlen(textbuf), fd); fclose(fd); } // just incase these were rejected before because of max sizes... ret = setsockopt( socket, SOL_SOCKET, SO_SNDBUF, (char *)&sock_buf_size, sizeof(sock_buf_size) ); ret = setsockopt( socket, SOL_SOCKET, SO_RCVBUF, (char *)&sock_buf_size, sizeof(sock_buf_size) ); } //void MSDD6000_RS::set_decim(int decim_pow2){ // DEBUG("SETTING NEW DECIM"); // d_decim = decim_pow2; // // if(d_state==STATE_STARTED) // send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz); //} void MSDD6000_RS::set_rf_attn(int attn){ DEBUG("SETTING NEW RF ATTN"); d_rf_attn = attn; if(d_state==STATE_STARTED) send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_offset_hz, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); } void MSDD6000_RS::set_ddc_gain(int gain){ DEBUG("SETTING NEW DDC GAIN"); d_ddc_gain = gain; if(d_state==STATE_STARTED) send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_offset_hz, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); } void MSDD6000_RS::set_fc(int center_mhz, int offset_hz){ DEBUG("SETTING NEW FC"); d_fc_mhz = center_mhz; d_offset_hz = offset_hz; send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_offset_hz, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); // if(d_state==STATE_STARTED) // send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz); // send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); // } void MSDD6000_RS::set_ddc_samp_rate(float sample_rate_khz){ DEBUG("SETTING NEW SAMPLE RATE"); d_ddc_sample_rate_khz = sample_rate_khz; send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_offset_hz, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); } void MSDD6000_RS::set_ddc_bw(float bw_khz){ DEBUG("SETTING NEW DDC BW"); d_ddc_bw_khz = bw_khz; send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_offset_hz, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); } void MSDD6000_RS::start(){ send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_offset_hz, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); return; } void MSDD6000_RS::stop(){ // new request with 0 decim tells it to halt stop_data(); } int MSDD6000_RS::start_data(){ d_start = 1; send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_offset_hz, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); d_state = STATE_STARTED; return 0; } int MSDD6000_RS::stop_data(){ // new request with 0 decim tells it to halt d_start = 0; send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_offset_hz, d_ddc_sample_rate_khz, d_ddc_bw_khz, d_start); d_state = STATE_STOPPED; return 0; } /* Query functions */ float MSDD6000_RS::pull_ddc_samp_rate(){ return d_ddc_sample_rate_khz; } float MSDD6000_RS::pull_ddc_bw(){ return d_ddc_bw_khz; } float MSDD6000_RS::pull_rx_freq(){ return d_fc_mhz; } int MSDD6000_RS::pull_ddc_gain(){ return d_ddc_gain; } int MSDD6000_RS::pull_rf_atten(){ return d_rf_attn; } void MSDD6000_RS::send_request(float freq_mhz, float rf_attn, float ddc_gain, float ddc_offset_hz, float ddc_samp_rate_khz, float ddc_input_bw_khz, float ddc_start){ static char buff[512]; // Send MSDD6000_RS control frame. sprintf(buff, "%f %f %f %f %f %f %f\n",freq_mhz, rf_attn, ddc_gain, ddc_offset_hz, ddc_samp_rate_khz, ddc_input_bw_khz, ddc_start); //ddc_dec, ddc_offset_hz); printf("sending: %s\n", buff); int flags = 0; sendto( d_sock, buff, strlen(buff)+1, flags, (const sockaddr*)&(d_detail->d_sockaddr), sizeof(d_detail->d_sockaddr)); } int MSDD6000_RS::read(char* buf, int size){ int flags = 0; return recv(d_sock, buf, size, flags); } int MSDD6000_RS::parse_control(char* buf, int size){ //packet_len = sprintf(&txbuff[6], "%f %f %f %f %f %f %f",downsamp,ddc_dec_rate,ddc_step_int,ddc_step_frac,ddc_samp_rate_khz,ddc_input_bw_khz,ddc_start); float downsamp; float ddc_dec_rate; float ddc_step_int; float ddc_step_frac; float ddc_samp_rate_khz; float ddc_input_bw_khz; float ddc_start; sscanf(&buf[6],"%f %f %f %f %f %f %f",&downsamp,&ddc_dec_rate,&ddc_step_int,&ddc_step_frac,&ddc_samp_rate_khz,&ddc_input_bw_khz,&ddc_start); // pull off sample rate d_ddc_sample_rate_khz = ddc_samp_rate_khz; printf("Sample Rate %f\n",d_ddc_sample_rate_khz); // pull off bw d_ddc_bw_khz = ddc_input_bw_khz; printf("BW %f\n", d_ddc_bw_khz); return 0; }