d37afcc11e6f228c1000eaf5ce06b415b5cdb48b
[debian/gnuradio] / gr-msdd6000 / src / msdd6000.cc
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2008,2009 Free Software Foundation, Inc.
4  * 
5  * This file is part of GNU Radio
6  * 
7  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  * 
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License along
18  * with this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24 #include <msdd6000.h>
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29
30 #ifdef HAVE_ARPA_INET_H
31 #include <arpa/inet.h>
32 #endif
33 #ifdef HAVE_NETINET_IN_H
34 #include <netinet/in.h>
35 #endif
36 #ifdef HAVE_SYS_SOCKET_H
37 #include <sys/socket.h>
38 #endif
39
40 #define DEBUG(A)        printf("=debug=> %s\n", A)
41
42 static void 
43 optimize_socket(int socket);
44
45 /*
46  * Holds types that need autoconf help.  They're here and not in the .h file because
47  * here we've got access to config.h
48  */
49 class MSDD6000::detail {
50 public:
51   struct sockaddr_in d_sockaddr;
52 };
53
54
55 MSDD6000::MSDD6000(char* addr)
56   : d_detail(new MSDD6000::detail())
57 {
58         d_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP);
59         
60         optimize_socket(d_sock);
61         
62         
63         // set up remote sockaddr
64 //      int s = inet_aton(addr, &d_adx); 
65         d_detail->d_sockaddr.sin_family = AF_INET;
66         d_detail->d_sockaddr.sin_port = htons(10000);
67         int s = inet_aton(addr, &d_detail->d_sockaddr.sin_addr);
68         
69         // set up local sockaddr
70         struct in_addr d_myadx;
71         struct sockaddr_in d_mysockaddr;
72         short int port = 10010;
73         d_myadx.s_addr = INADDR_ANY;
74         d_mysockaddr.sin_family = AF_INET;
75         d_mysockaddr.sin_port = htons(port);
76         memcpy(&d_mysockaddr.sin_addr.s_addr, &d_myadx.s_addr, sizeof(in_addr));
77         //d_sockaddr.sin_addr = INADDR_ANY;
78         s = bind(d_sock, (const sockaddr*) &d_mysockaddr, sizeof(d_mysockaddr));
79         
80         // set default values
81         d_decim = 2;
82         d_ddc_gain = 2;
83         d_rf_attn = 0;
84         d_state = STATE_STOPPED;
85 }
86
87 MSDD6000::~MSDD6000()
88 {
89   // NOP
90 }
91
92
93 static void
94 optimize_socket(int socket){
95 #define BANDWIDTH       1000000000/8
96 #define DELAY           0.5
97         int ret;
98
99         int sock_buf_size = static_cast<int>(2*BANDWIDTH*DELAY);
100         char textbuf[512];
101         snprintf(textbuf, sizeof(textbuf), "%d", sock_buf_size);
102         printf("sock_buf_size = %d\n", sock_buf_size);
103         
104         ret = setsockopt(socket, SOL_SOCKET, SO_SNDBUF,
105                          &sock_buf_size, sizeof(sock_buf_size));
106
107         ret = setsockopt(socket, SOL_SOCKET, SO_RCVBUF,
108                          &sock_buf_size, sizeof(sock_buf_size));
109         
110         int uid = getuid();
111         if(uid!=0){
112                 printf(" ****** COULD NOT OPTIMIZE SYSTEM NETWORK PARAMETERS BECAUSE YOU ARE NOT RUNNING AS ROOT *******\n ****** YOUR MSDD6000 RECIEVER PERFORMANCE IS GOING TO BE TERRIBLE *******\n");
113                 return;
114         }
115
116
117         // SET UP SOME SYSTEM WIDE TCP SOCKET PARAMETERS
118         // FIXME seems like kind of a big hammer.  Are you sure you need this?
119         FILE* fd = fopen("/proc/sys/net/core/netdev_max_backlog", "w");
120         if (fd){
121           fwrite("10000", 1, strlen("10000"), fd);
122           fclose(fd);
123         }
124
125         fd = fopen("/proc/sys/net/core/rmem_max", "w");
126         if (fd){
127           fwrite(textbuf, 1, strlen(textbuf), fd);
128           fclose(fd);
129         }
130
131         fd = fopen("/proc/sys/net/core/wmem_max", "w");
132         if (fd){
133           fwrite(textbuf, 1, strlen(textbuf), fd);
134           fclose(fd);
135         }
136
137         // just incase these were rejected before because of max sizes...
138
139         ret = setsockopt( socket, SOL_SOCKET, SO_SNDBUF,
140                    (char *)&sock_buf_size, sizeof(sock_buf_size) );
141
142         ret = setsockopt( socket, SOL_SOCKET, SO_RCVBUF,
143                    (char *)&sock_buf_size, sizeof(sock_buf_size) );
144         
145 }
146
147
148 void MSDD6000::set_decim(int decim_pow2){
149         DEBUG("SETTING NEW DECIM");
150         d_decim = decim_pow2;
151
152         if(d_state==STATE_STARTED)
153                 send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
154 }
155
156 void MSDD6000::set_rf_attn(int attn){
157         DEBUG("SETTING NEW RF ATTN");
158         d_rf_attn = attn;
159         if(d_state==STATE_STARTED)
160                 send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
161 }
162
163 void MSDD6000::set_ddc_gain(int gain){
164         DEBUG("SETTING NEW DDC GAIN");
165         d_ddc_gain = gain;
166         if(d_state==STATE_STARTED)
167                 send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
168 }
169
170 void MSDD6000::set_fc(int center_mhz, int offset_hz){
171         DEBUG("SETTING NEW FC");
172         d_fc_mhz = center_mhz;
173         d_offset_hz = offset_hz;
174         
175         if(d_state==STATE_STARTED)
176                 send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
177 }
178
179
180 void MSDD6000::start(){
181         send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, d_decim, d_offset_hz);
182         d_state = STATE_STARTED;
183         }
184
185
186 void MSDD6000::stop(){
187         // new request with 0 decim tells it to halt
188         send_request(d_fc_mhz, d_rf_attn, d_ddc_gain, 0, d_offset_hz);
189         d_state = STATE_STOPPED;
190         }
191
192
193 void MSDD6000::send_request(float freq_mhz, float rf_attn, float ddc_gain, float ddc_dec, float ddc_offset_hz){
194         static char buff[512];
195         sprintf(buff, "%f %f %f %f %f\n",freq_mhz, rf_attn, ddc_gain, ddc_dec, ddc_offset_hz);
196         printf("sending: %s\n", buff);
197         int flags = 0;
198         sendto( d_sock, buff, strlen(buff)+1, flags,
199                 (const sockaddr*)&(d_detail->d_sockaddr), sizeof(d_detail->d_sockaddr));
200         }
201
202
203 int  MSDD6000::read(char* buf, int size){
204         int flags = 0;
205         return recv(d_sock, buf, size, flags);
206         }
207
208