Working hard on ddcd.
This commit is contained in:
parent
4380bec6fa
commit
71e80ea809
3 changed files with 142 additions and 24 deletions
1
Makefile
1
Makefile
|
@ -67,6 +67,7 @@ install: all
|
||||||
install -m 0755 libcsdr.so /usr/lib
|
install -m 0755 libcsdr.so /usr/lib
|
||||||
install -m 0755 csdr /usr/bin
|
install -m 0755 csdr /usr/bin
|
||||||
install -m 0755 csdr-fm /usr/bin
|
install -m 0755 csdr-fm /usr/bin
|
||||||
|
install -m 0755 ddcd /usr/bin
|
||||||
ldconfig
|
ldconfig
|
||||||
uninstall:
|
uninstall:
|
||||||
rm /usr/lib/libcsdr.so /usr/bin/csdr /usr/bin/csdr-fm
|
rm /usr/lib/libcsdr.so /usr/bin/csdr /usr/bin/csdr-fm
|
||||||
|
|
144
ddcd.cpp
144
ddcd.cpp
|
@ -37,9 +37,16 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
int host_port = 0;
|
int host_port = 0;
|
||||||
char host_address[100] = "127.0.0.1";
|
char host_address[100] = "127.0.0.1";
|
||||||
int decimation = 0;
|
int decimation = 0;
|
||||||
|
float transition_bw = 0.05;
|
||||||
int bufsize = 1024;
|
int bufsize = 1024;
|
||||||
int bufsizeall;
|
int bufsizeall;
|
||||||
int pipe_max_size;
|
int pipe_max_size;
|
||||||
|
char ddc_method_str[100] = "td";
|
||||||
|
ddc_method_t ddc_method;
|
||||||
|
pid_t main_dsp_proc;
|
||||||
|
pid_t pgrp;
|
||||||
|
int input_pipe = STDIN_FILENO; //can be stdin, or the stdout of main_subprocess
|
||||||
|
|
||||||
char* buf;
|
char* buf;
|
||||||
|
|
||||||
int set_nonblocking(int fd)
|
int set_nonblocking(int fd)
|
||||||
|
@ -71,7 +78,9 @@ int main(int argc, char* argv[])
|
||||||
{"port", required_argument, 0, 'p' },
|
{"port", required_argument, 0, 'p' },
|
||||||
{"address", required_argument, 0, 'a' },
|
{"address", required_argument, 0, 'a' },
|
||||||
{"decimation", required_argument, 0, 'd' },
|
{"decimation", required_argument, 0, 'd' },
|
||||||
{"bufsize", required_argument, 0, 'b' }
|
{"bufsize", required_argument, 0, 'b' },
|
||||||
|
{"method", required_argument, 0, 'm' }
|
||||||
|
{"transition", required_argument, 0, 't' }
|
||||||
};
|
};
|
||||||
c = getopt_long(argc, argv, "p:a:d:b:", long_options, &option_index);
|
c = getopt_long(argc, argv, "p:a:d:b:", long_options, &option_index);
|
||||||
if(c==-1) break;
|
if(c==-1) break;
|
||||||
|
@ -90,17 +99,38 @@ int main(int argc, char* argv[])
|
||||||
case 'b':
|
case 'b':
|
||||||
bufsize=atoi(optarg);
|
bufsize=atoi(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
host_address[100-1]=0;
|
||||||
|
strncpy(ddc_method_str,optarg,100-1);
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
sscanf(optarg,"%g",&transition_bw);
|
||||||
|
break;
|
||||||
case 0:
|
case 0:
|
||||||
case '?':
|
case '?':
|
||||||
case ':':
|
case ':':
|
||||||
default:
|
default:;
|
||||||
printf(" 0%o ??\n", c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!decimation) error_exit(MSG_START "missing required command line argument, --decimation.\n");
|
if(!decimation) print_exit(MSG_START "missing required command line argument, --decimation.\n");
|
||||||
if(!host_port) error_exit(MSG_START "missing required command line argument, --port.\n");
|
if(!host_port) print_exit(MSG_START "missing required command line argument, --port.\n");
|
||||||
|
if(decimation<0) print_exit(MSG_START "invalid value for --decimation (should be >0).\n");
|
||||||
|
if(decimation==1) fprintf(stderr, MSG_START "decimation = 1, just copying raw samples.\n");
|
||||||
|
if(transition_bw<0||transition_bw>0.5) print_exit(MSG_START "invalid value for --transition (should be between 0 and 0.5).\n");
|
||||||
|
|
||||||
|
if(!strcmp(ddc_method_str,"td"))
|
||||||
|
{
|
||||||
|
ddc_method = M_TD;
|
||||||
|
fprintf(stderr, MSG_START "method is M_TD (default).\n");
|
||||||
|
}
|
||||||
|
else if (!strcmp(ddc_method_str,"fastddc"))
|
||||||
|
{
|
||||||
|
ddc_method = M_FASTDDC;
|
||||||
|
fprintf(stderr, MSG_START "method is M_FASTDDC.\n");
|
||||||
|
}
|
||||||
|
else print_exit(MSG_START "invalid parameter given to --method.\n");
|
||||||
|
|
||||||
struct sockaddr_in addr_host;
|
struct sockaddr_in addr_host;
|
||||||
int listen_socket;
|
int listen_socket;
|
||||||
std::vector<client_t*> clients;
|
std::vector<client_t*> clients;
|
||||||
|
@ -109,7 +139,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
int sockopt = 1;
|
int sockopt = 1;
|
||||||
if( setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt)) == -1 )
|
if( setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&sockopt, sizeof(sockopt)) == -1 )
|
||||||
error_exit(MSG_START "cannot set SO_REUSEADDR.\n"); //the best description on SO_REUSEADDR ever: http://stackoverflow.com/a/14388707/3182453
|
error_exit(MSG_START "cannot set SO_REUSEADDR"); //the best description on SO_REUSEADDR ever: http://stackoverflow.com/a/14388707/3182453
|
||||||
|
|
||||||
memset(&addr_host,'0',sizeof(addr_host));
|
memset(&addr_host,'0',sizeof(addr_host));
|
||||||
addr_host.sin_family=AF_INET;
|
addr_host.sin_family=AF_INET;
|
||||||
|
@ -117,13 +147,13 @@ int main(int argc, char* argv[])
|
||||||
addr_host.sin_addr.s_addr = INADDR_ANY;
|
addr_host.sin_addr.s_addr = INADDR_ANY;
|
||||||
|
|
||||||
if( (addr_host.sin_addr.s_addr=inet_addr(host_address)) == INADDR_NONE )
|
if( (addr_host.sin_addr.s_addr=inet_addr(host_address)) == INADDR_NONE )
|
||||||
error_exit(MSG_START "invalid host address.\n");
|
error_exit(MSG_START "invalid host address");
|
||||||
|
|
||||||
if( bind(listen_socket, (struct sockaddr*) &addr_host, sizeof(addr_host)) < 0 )
|
if( bind(listen_socket, (struct sockaddr*) &addr_host, sizeof(addr_host)) < 0 )
|
||||||
error_exit(MSG_START "cannot bind() address to the socket.\n");
|
error_exit(MSG_START "cannot bind() address to the socket");
|
||||||
|
|
||||||
if( listen(listen_socket, 10) == -1 )
|
if( listen(listen_socket, 10) == -1 )
|
||||||
error_exit(MSG_START "cannot listen() on socket.\n");
|
error_exit(MSG_START "cannot listen() on socket");
|
||||||
|
|
||||||
fprintf(stderr,MSG_START "listening on %s:%d\n", inet_ntoa(addr_host.sin_addr), host_port);
|
fprintf(stderr,MSG_START "listening on %s:%d\n", inet_ntoa(addr_host.sin_addr), host_port);
|
||||||
|
|
||||||
|
@ -131,18 +161,9 @@ int main(int argc, char* argv[])
|
||||||
socklen_t addr_cli_len = sizeof(addr_cli);
|
socklen_t addr_cli_len = sizeof(addr_cli);
|
||||||
int new_socket;
|
int new_socket;
|
||||||
|
|
||||||
//Set stdin and listen_socket to non-blocking
|
|
||||||
if(set_nonblocking(STDIN_FILENO) || set_nonblocking(listen_socket))
|
|
||||||
error_exit(MSG_START "cannot set_nonblocking().\n");
|
|
||||||
|
|
||||||
bufsizeall = bufsize*sizeof(char);
|
bufsizeall = bufsize*sizeof(char);
|
||||||
buf = (char*)malloc(bufsizeall);
|
buf = (char*)malloc(bufsizeall);
|
||||||
|
|
||||||
FD_ZERO(&select_fds);
|
|
||||||
FD_SET(listen_socket, &select_fds);
|
|
||||||
FD_SET(STDIN_FILENO, &select_fds);
|
|
||||||
int highfd = ((listen_socket>STDIN_FILENO)?listen_socket:STDIN_FILENO) + 1;
|
|
||||||
|
|
||||||
FILE* tempfile = fopen("/proc/sys/fs/pipe-max-size","r");
|
FILE* tempfile = fopen("/proc/sys/fs/pipe-max-size","r");
|
||||||
if(!tempfile)
|
if(!tempfile)
|
||||||
{
|
{
|
||||||
|
@ -159,6 +180,46 @@ int main(int argc, char* argv[])
|
||||||
// perror("failed to fcntl(STDIN_FILENO, F_SETPIPE_SZ, ...)");
|
// perror("failed to fcntl(STDIN_FILENO, F_SETPIPE_SZ, ...)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//We'll see if it is a good idea:
|
||||||
|
setpgrp();
|
||||||
|
pgrp = getpgrp();
|
||||||
|
|
||||||
|
//Start DSP subprocess from the main process if required
|
||||||
|
char main_subprocess_cmd_buf[500];
|
||||||
|
pid_t main_subprocess_pid = 0;
|
||||||
|
|
||||||
|
int pipe_m2s_ctl[2]; //main to subprocess :: control channel
|
||||||
|
int pipe_s2m[2]; //subprocess to main
|
||||||
|
|
||||||
|
if(pipe(pipe_m2s_ctl)) error_exit(MSG_START "couldn't create pipe_m2s_ctl");
|
||||||
|
if(pipe(pipe_s2m)) error_exit(MSG_START "couldn't create pipe_s2m");
|
||||||
|
|
||||||
|
if(decimation!=1)
|
||||||
|
{
|
||||||
|
switch(ddc_method)
|
||||||
|
{
|
||||||
|
case M_TD:
|
||||||
|
break;
|
||||||
|
case M_FASTDDC:
|
||||||
|
sprintf(main_subprocess_cmd_buf, subprocess_args_fastddc_1, decimation, tansition_bw);
|
||||||
|
close(STDIN_FILENO); // redirect stdin to the stdin of the subprocess
|
||||||
|
main_subprocess_pid = run_subprocess( main_subprocess_cmd_buf, 0, pipe_s2m );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int highfd = 0;
|
||||||
|
FD_ZERO(&select_fds);
|
||||||
|
FD_SET(listen_socket, &select_fds);
|
||||||
|
maxfd(&highfd, listen_socket);
|
||||||
|
if(main_subprocess_pid) input_pipe = pipe_s2m[1]; //else STDIN_FILENO
|
||||||
|
FD_SET(input_pipe, &select_fds);
|
||||||
|
maxfd(&highfd, input_pipe);
|
||||||
|
|
||||||
|
//Set stdin and listen_socket to non-blocking
|
||||||
|
if(set_nonblocking(input_pipe) || set_nonblocking(listen_socket)) //don't do it before subprocess fork!
|
||||||
|
error_exit(MSG_START "cannot set_nonblocking()");
|
||||||
|
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
//Let's wait until there is any new data to read, or any new connection!
|
//Let's wait until there is any new data to read, or any new connection!
|
||||||
|
@ -173,17 +234,17 @@ int main(int argc, char* argv[])
|
||||||
this_client->socket = new_socket;
|
this_client->socket = new_socket;
|
||||||
if(pipe(this_client->pipefd) == -1)
|
if(pipe(this_client->pipefd) == -1)
|
||||||
{
|
{
|
||||||
perror(MSG_START "cannot open new pipe() for the client.\n");
|
perror(MSG_START "cannot open new pipe() for the client");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(fcntl(this_client->pipefd[1], F_SETPIPE_SZ, pipe_max_size) == -1)
|
if(fcntl(this_client->pipefd[1], F_SETPIPE_SZ, pipe_max_size) == -1)
|
||||||
perror("failed to F_SETPIPE_SZ for the client pipe!");
|
perror("failed to F_SETPIPE_SZ for the client pipe");
|
||||||
if(this_client->pid = fork())
|
if(this_client->pid = fork())
|
||||||
{
|
{
|
||||||
//We're the parent
|
//We're the parent
|
||||||
set_nonblocking(this_client->pipefd[1]);
|
set_nonblocking(this_client->pipefd[1]);
|
||||||
clients.push_back(this_client);
|
clients.push_back(this_client);
|
||||||
printf("client pid: %d\n", this_client->pid);
|
fprintf(stderr, MSG_START "client pid: %d\n", this_client->pid);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -193,7 +254,7 @@ int main(int argc, char* argv[])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int retval = read(STDIN_FILENO, buf, bufsizeall);
|
int retval = read(input_pipe, buf, bufsizeall);
|
||||||
if(retval==0)
|
if(retval==0)
|
||||||
{
|
{
|
||||||
//end of input stream, close clients and exit
|
//end of input stream, close clients and exit
|
||||||
|
@ -236,7 +297,31 @@ int main(int argc, char* argv[])
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid_t run_subprocess(char* cmd, int* pipe_in, int* pipe_out)
|
||||||
|
{
|
||||||
|
pid_t pid = fork();
|
||||||
|
if(p < 0) return 0; //fork failed
|
||||||
|
if(p==0)
|
||||||
|
{
|
||||||
|
//We're the subprocess
|
||||||
|
if(fcntl(pipe_in[1], F_SETPIPE_SZ, pipe_max_size) == -1) perror("Failed to F_SETPIPE_SZ in run_subprocess()");
|
||||||
|
if(pipe_in)
|
||||||
|
{
|
||||||
|
close(pipe_in[1]);
|
||||||
|
dup2(pipe_in[0], STDIN_FILENO);
|
||||||
|
}
|
||||||
|
if(pipe_out)
|
||||||
|
{
|
||||||
|
close(pipe_out[0]);
|
||||||
|
dup2(pipe_out[1], STDOUT_FILENO);
|
||||||
|
}
|
||||||
|
execl("/bin/bash","bash","-c",cmd, 0);
|
||||||
|
error_exit(MSG_START "run_subprocess failed to execute command")
|
||||||
|
}
|
||||||
|
else return pid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_client(client_t* client, const char* what)
|
void print_client(client_t* client, const char* what)
|
||||||
|
@ -251,7 +336,7 @@ void client_cleanup()
|
||||||
|
|
||||||
void client()
|
void client()
|
||||||
{
|
{
|
||||||
fprintf(stderr, "I'm the client\n");
|
print_client(this_client, "client process forked.");
|
||||||
for(;;)
|
for(;;)
|
||||||
{
|
{
|
||||||
read(this_client->pipefd[0],buf,bufsizeall);
|
read(this_client->pipefd[0],buf,bufsizeall);
|
||||||
|
@ -268,3 +353,14 @@ void error_exit(const char* why)
|
||||||
perror(why);
|
perror(why);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void print_exit(const char* why)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s", why);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void maxfd(int* maxfd, int fd)
|
||||||
|
{
|
||||||
|
if(fd>*maxfd) *maxfd=fd+1;
|
||||||
|
}
|
||||||
|
|
21
ddcd.h
21
ddcd.h
|
@ -23,10 +23,31 @@ typedef struct client_s
|
||||||
pid_t pid;
|
pid_t pid;
|
||||||
int pipefd[2];
|
int pipefd[2];
|
||||||
int error;
|
int error;
|
||||||
|
pid_t dsp_proc;
|
||||||
} client_t;
|
} client_t;
|
||||||
|
|
||||||
|
|
||||||
void client();
|
void client();
|
||||||
void error_exit(const char* why);
|
void error_exit(const char* why);
|
||||||
|
void print_exit(const char* why);
|
||||||
void print_client(client_t* client, const char* what);
|
void print_client(client_t* client, const char* what);
|
||||||
int proc_exists(pid_t pid);
|
int proc_exists(pid_t pid);
|
||||||
|
void run_subprocess(char* cmd, int* pipe_in, int* pipe_out);
|
||||||
|
void maxfd(int* maxfd, int fd);
|
||||||
|
|
||||||
|
typedef enum ddc_method_e
|
||||||
|
{
|
||||||
|
M_TD,
|
||||||
|
M_FASTDDC
|
||||||
|
} ddc_method_t;
|
||||||
|
|
||||||
|
const char subprocess_cmd_td[] = "csdr "
|
||||||
|
#ifdef NEON_OPTS
|
||||||
|
"shift_addfast_cc"
|
||||||
|
#else
|
||||||
|
"shift_unroll_cc"
|
||||||
|
#endif
|
||||||
|
" --pipe %d,%d | csdr fir_decimate_cc %d %g" };
|
||||||
|
|
||||||
|
const char subprocess_args_fastddc_1[] = "csdr fastddc_fwd_cc %d %g";
|
||||||
|
const char subprocess_args_fastddc_2[] = "csdr fastddc_inv_cc %d --pipe %d,%d %g";
|
||||||
|
|
Loading…
Reference in a new issue