///*! \file vita_output.c // * \brief transmit vita packets to the Ethernet // * // * \copyright Copyright 2012-2013 FlexRadio Systems. All Rights Reserved. // * Unauthorized use, duplication or distribution of this software is // * strictly prohibited by law. // * // * \date 2-APR-2012 // * \author Stephen Hicks, N5AC // * // */ /* ***************************************************************************** * * Copyright (C) 2012-2014 FlexRadio Systems. * * This program 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 of the License, or * (at your option) any later version. * This program 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, see . * * Contact Information: * email: gplflexradiosystems.com * Mail: FlexRadio Systems, Suite 1-150, 4616 W. Howard LN, Austin, TX 78728 * * ************************************************************************** */ #include #include #include #include #include #include #include #include #include // for write, usleep #include #include "vita_output.h" #include "common.h" #include "hal_listener.h" extern int errno; #define FORMAT_DBFS 0 #define FORMAT_DBM 1 #define VITA_CLASS_ID_1 (uint32)VITA_OUI #define VITA_CLASS_ID_2 SL_VITA_INFO_CLASS << 16 | SL_VITA_IF_DATA_CLASS #define MAX_SAMPLES_PER_PACKET (MAX_IF_DATA_PAYLOAD_SIZE/8) #define MAX_BINS_PER_PACKET 700 // local variable declarations static vita_if_data waveform_packet; static int vita_sock; static struct sockaddr_in vita_sLocalAddr; static uint32 _local_ip_addr; static uint16 _dest_port; void vita_output_Init(const char * ip ) { output("\033[32mInitializing VITA-49 output engine...\n\033[m"); vita_sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (vita_sock < 0) { output(ANSI_RED " Failed to initialize VITA socket\n"); return; } errno = 0; bind(vita_sock, (struct sockaddr *)&vita_sLocalAddr, sizeof(vita_sLocalAddr)); if (errno) { output(ANSI_RED "error binding socket: errno=%d\n",errno); } struct in_addr addr; if ( ip == NULL ) { output(ANSI_RED "NULL IP Supplied!!\n"); tc_abort(); } if ( inet_aton(ip, &addr) == 0) { output(ANSI_RED "Could not convert local addr to binary\n"); } else { _local_ip_addr = ntohl(addr.s_addr); } _dest_port = 4991; // output("host = %d.%d.%d.%d : %d", ip>>24, (ip>>16)&0xFF, (ip>>8)&0xFF, ip&0xFF, _dest_port); output("Vita Output Init - ip = '%s' port = %d\n", ip,_dest_port); } void UDPSendByIPandPort(void* packet, uint32 num_bytes, uint32 ip_address, uint16 udp_port) { struct sockaddr_in sock; sock.sin_family = AF_INET; sock.sin_addr.s_addr = htonl(ip_address); sock.sin_port = htons(udp_port); errno = 0; int32 ret_val = sendto(vita_sock, packet, num_bytes, 0, (struct sockaddr*)&sock, sizeof(sock)); if ( errno || ret_val < 0) { output( "Error sending packet: errno%d \n", errno); } } static void _vita_formatWaveformPacket(Complex* buffer, uint32 samples, uint32 stream_id, uint32 packet_count, uint32 class_id_h, uint32 class_id_l, uint32 ip_addr, uint16 port) { waveform_packet.header = htonl( VITA_PACKET_TYPE_IF_DATA_WITH_STREAM_ID | VITA_HEADER_CLASS_ID_PRESENT | VITA_TSI_OTHER | VITA_TSF_SAMPLE_COUNT | (packet_count << 16) | (7+samples*2)); waveform_packet.stream_id = htonl(stream_id); waveform_packet.class_id_h = htonl(class_id_h); waveform_packet.class_id_l = htonl(class_id_l); waveform_packet.timestamp_int = 0; waveform_packet.timestamp_frac_h = 0; waveform_packet.timestamp_frac_l = 0; memcpy(waveform_packet.payload, buffer, samples * sizeof(Complex)); //HAL_update_count(stream_id, class_id_h, class_id_l, samples * 8 + 28, HAL_STATUS_OUTPUT_OK, OUTPUT, WFM, ip_addr, port); } static uint32 _waveform_packet_count = 0; void emit_waveform_output(BufferDescriptor buf_desc_out) { int samples_sent, samples_to_send; Complex * buf_pointer; if (buf_desc_out == NULL) { output(ANSI_RED "buf_desc_out is NULL\n"); return; } if (buf_desc_out->buf_ptr == NULL) { output(ANSI_RED "buf_desc_out->buf_ptr is NULL\n"); return; } Complex* out_buffer = (Complex*)buf_desc_out->buf_ptr; uint32 buf_size = buf_desc_out->num_samples; // convert to big endian for network int i; for(i=0; i preferred_samples_per_packet) { samples_to_send = preferred_samples_per_packet; } else { samples_to_send = buf_size - samples_sent; } //output("samples_to_send: %d\n", samples_to_send); _vita_formatWaveformPacket( buf_pointer, samples_to_send, buf_desc_out->stream_id, _waveform_packet_count++ & 0xF, (uint32) FLEXRADIO_OUI, SL_VITA_SLICE_AUDIO_CLASS, _local_ip_addr, 4991); buf_pointer += samples_to_send; samples_sent += samples_to_send; vita_sLocalAddr.sin_port = htons(VITA_49_SOURCE_PORT); UDPSendByIPandPort(&waveform_packet, samples_to_send * 8 + 28, _local_ip_addr, _dest_port); } }