174 lines
5.4 KiB
C++
174 lines
5.4 KiB
C++
/* -*- c++ -*- */
|
|
/*
|
|
* Copyright 2004 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 2, 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 GNU Radio; see the file COPYING. If not, write to
|
|
* the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
* Boston, MA 02111-1307, USA.
|
|
*
|
|
* This file is part of OP25
|
|
* repeater_chan_usrp_rx Copyright 2010-2013 KA1RBI
|
|
*
|
|
*/
|
|
|
|
/*
|
|
* config.h is generated by configure. It contains the results
|
|
* of probing for features, options etc. It should be the first
|
|
* file included in your .cc file.
|
|
*/
|
|
#ifdef HAVE_CONFIG_H
|
|
#include "config.h"
|
|
#endif
|
|
|
|
#include <gr_io_signature.h>
|
|
#include <gr_prefs.h>
|
|
#include <gr_math.h>
|
|
#include <gr_expj.h>
|
|
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <time.h>
|
|
#include <repeater_chan_usrp_rx.h>
|
|
#include <sys/time.h>
|
|
#include <sys/types.h>
|
|
#include <sys/select.h>
|
|
|
|
#ifndef min
|
|
#define min(a,b) ((a<b)?a:b)
|
|
#endif
|
|
|
|
static const int phase_table[4] = {+1, +3, -1, -3};
|
|
static const int COMPLEX_FRAME_SIZE = 96 * sizeof(gr_complex); // 4800 * 0.02
|
|
|
|
/*
|
|
* Create a new instance of repeater_chan_usrp_rx and return
|
|
* a boost shared_ptr. This is effectively the public constructor.
|
|
*/
|
|
repeater_chan_usrp_rx_sptr
|
|
repeater_make_chan_usrp_rx (const char* udp_host, int port, int debug, int input_size)
|
|
{
|
|
return repeater_chan_usrp_rx_sptr (new repeater_chan_usrp_rx(udp_host, port, debug, input_size));
|
|
}
|
|
|
|
/*
|
|
* The private constructor
|
|
*/
|
|
repeater_chan_usrp_rx::repeater_chan_usrp_rx (const char* udp_host, int port, int debug, int input_size)
|
|
: gr_block ("chan_usrp_rx",
|
|
gr_make_io_signature (1, 1, input_size),
|
|
gr_make_io_signature (0, 0, 0)),
|
|
d_udp_host(udp_host),
|
|
d_port(port),
|
|
d_debug(debug),
|
|
d_sampbuf_ct(0),
|
|
d_sendseq(0),
|
|
d_input_size(input_size),
|
|
d_buf_data_size ((input_size == sizeof(gr_complex)) ? COMPLEX_FRAME_SIZE : USRP_VOICE_FRAME_SIZE),
|
|
d_max_sampbuf_ct(d_buf_data_size / d_input_size)
|
|
{
|
|
assert(input_size == sizeof(int16_t) || input_size == sizeof(gr_complex));
|
|
|
|
write_buf = new char[sizeof(struct _chan_usrp_bufhdr) + d_buf_data_size];
|
|
|
|
init_sock(udp_host, port);
|
|
}
|
|
|
|
repeater_chan_usrp_rx::~repeater_chan_usrp_rx ()
|
|
{
|
|
if (write_sock > 0)
|
|
close(write_sock);
|
|
|
|
delete [] write_buf;
|
|
}
|
|
|
|
// static int sends, samps;
|
|
|
|
int
|
|
repeater_chan_usrp_rx::general_work (int noutput_items,
|
|
gr_vector_int &ninput_items,
|
|
gr_vector_const_void_star &input_items,
|
|
gr_vector_void_star &output_items)
|
|
{
|
|
struct timeval tv;
|
|
|
|
const int16_t *in = (const int16_t *) input_items[0];
|
|
int16_t *sampbuf = (int16_t *) &write_buf[sizeof(struct _chan_usrp_bufhdr)];
|
|
|
|
const gr_complex *in_c = (const gr_complex *) input_items[0];
|
|
gr_complex *sampbuf_c = (gr_complex *) &write_buf[sizeof(struct _chan_usrp_bufhdr)];
|
|
|
|
struct _chan_usrp_bufhdr *bufhdrp = (struct _chan_usrp_bufhdr*) write_buf;
|
|
gettimeofday(&tv, NULL);
|
|
// fprintf(stderr, "sec %lu usec %lu output %d\n", tv.tv_sec, tv.tv_usec, noutput_items);
|
|
|
|
int consumed = 0;
|
|
|
|
for (int i = 0; i < noutput_items; i++) {
|
|
if (d_input_size == sizeof(gr_complex)) {
|
|
sampbuf_c[d_sampbuf_ct++] = in_c[i];
|
|
} else {
|
|
sampbuf[d_sampbuf_ct++] = in[i];
|
|
}
|
|
consumed++;
|
|
if (d_sampbuf_ct >= d_max_sampbuf_ct) {
|
|
d_sampbuf_ct = 0;
|
|
memset(bufhdrp, 0, sizeof(struct _chan_usrp_bufhdr));
|
|
memcpy(bufhdrp->eye, "USRP", 4);
|
|
bufhdrp->seq = htonl(d_sendseq++);
|
|
bufhdrp->keyup = htonl(1);
|
|
/* int rc = */ (void) sendto(write_sock, write_buf, sizeof(struct _chan_usrp_bufhdr) + d_buf_data_size, 0, (struct sockaddr *)&write_sock_addr, sizeof(write_sock_addr)); // fixme: check rc
|
|
// gettimeofday(&tv, NULL);
|
|
// fprintf(stderr, "rc %d sends %d samps %u sec %lu usec %lu\n", rc, sends++, samps, tv.tv_sec, tv.tv_usec);
|
|
break;
|
|
}
|
|
}
|
|
consume_each(consumed);
|
|
return 0;
|
|
}
|
|
|
|
void repeater_chan_usrp_rx::unkey(void)
|
|
{
|
|
struct _chan_usrp_bufhdr bufhdr;
|
|
memset(&bufhdr, 0, sizeof(struct _chan_usrp_bufhdr));
|
|
memcpy(bufhdr.eye, "USRP", 4);
|
|
bufhdr.seq = htonl(d_sendseq++); // FIXME: need to lock this?
|
|
sendto(write_sock, &bufhdr, sizeof(struct _chan_usrp_bufhdr), 0, (struct sockaddr *)&write_sock_addr, sizeof(write_sock_addr));
|
|
}
|
|
|
|
void repeater_chan_usrp_rx::init_sock(const char* udp_host, int udp_port)
|
|
{
|
|
memset (&write_sock_addr, 0, sizeof(write_sock_addr));
|
|
write_sock = socket(PF_INET, SOCK_DGRAM, 17); // UDP socket
|
|
if (write_sock < 0) {
|
|
fprintf(stderr, "op25_imbe_vocoder: socket: %d\n", errno);
|
|
write_sock = 0;
|
|
return;
|
|
}
|
|
if (!inet_aton(udp_host, &write_sock_addr.sin_addr)) {
|
|
fprintf(stderr, "op25_imbe_vocoder: inet_aton: bad IP address\n");
|
|
close(write_sock);
|
|
write_sock = 0;
|
|
return;
|
|
}
|
|
write_sock_addr.sin_family = AF_INET;
|
|
write_sock_addr.sin_port = htons(udp_port);
|
|
}
|