Quisk version 4.2.28
This commit is contained in:
@@ -0,0 +1,3 @@
|
||||
The files in this afedrinet directory came from http://www.afedri-sdr.com. Only slight
|
||||
modifications were made by N2ADR. Thanks Alex!!!
|
||||
N2ADR: Changes made 26 January 2019.
|
||||
@@ -0,0 +1 @@
|
||||
#
|
||||
@@ -0,0 +1 @@
|
||||
gcc -o afedrinet_io.pyd --shared afedrinet_io.c ../is_key_down.c ../import_quisk_api.c -O3 -I"../" -I"C:\Programs\Python27\include" -L"C:\Programs\Python27\libs" -lws2_32 -lpython27
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
#replace include path and library name to right one for your system
|
||||
# for example for Python 2.7 it will look like -I"/usr/include/python2.7/" -lpython2.7
|
||||
gcc -o afedrinet_io.so --shared afedrinet_io.c ../is_key_down.c ../import_quisk_api.c -fPIC -O3 -I"../" -I"/usr/include/python2.7/" -lpython2.7
|
||||
@@ -0,0 +1,5 @@
|
||||
#!/bin/bash
|
||||
#replace include path and library name to right one for your system
|
||||
# for example for Python 2.7 it will look like -I"/usr/include/python2.7/" -lpython2.7
|
||||
#/usr/local/Cellar/python/2.7.10_2/Frameworks/Python.framework/Versions/2.7/lib/python2.7
|
||||
gcc -o afedrinet_io.so --shared afedrinet_io.c ../is_key_down.c ../import_quisk_api.c -I"../" -I"/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/" -L"/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/" -lpython2.7
|
||||
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
##################################################
|
||||
# AFEDRI Class module
|
||||
# Title: afedri.py
|
||||
# Author: k3it
|
||||
|
||||
# Adopted to work with Quisk
|
||||
# by 4Z5LV
|
||||
# Last Changes: Sat Feb 02 2013
|
||||
# Version: 2.2
|
||||
|
||||
# Adapted to work with Python3
|
||||
# by N2ADR
|
||||
# Last Changes: January 2020
|
||||
##################################################
|
||||
|
||||
from socket import *
|
||||
import wave
|
||||
import sys
|
||||
import struct
|
||||
import time
|
||||
import datetime
|
||||
import string
|
||||
import math
|
||||
|
||||
|
||||
class afedri(object):
|
||||
"""
|
||||
class definition for the Afedri SDR-NET
|
||||
"""
|
||||
def __init__(self,sdr_address="0.0.0.0", sdr_port=50000):
|
||||
if sdr_address == "0.0.0.0":
|
||||
__sdr_address,self.sdr_port = self.__discover_afedri()
|
||||
if __sdr_address is None:
|
||||
self.s = None
|
||||
return
|
||||
else:
|
||||
__sdr_address = sdr_address
|
||||
self.sdr_port = sdr_port
|
||||
|
||||
self.s = socket(AF_INET, SOCK_STREAM)
|
||||
self.s.settimeout(2)
|
||||
try:
|
||||
self.s.connect((__sdr_address,self.sdr_port))
|
||||
#print ("Established control connection with AFEDRI")
|
||||
except:
|
||||
print ("Error connecting to SDR")
|
||||
##sys.exit()
|
||||
self.s.close()
|
||||
self.s = None
|
||||
def close(self):
|
||||
if self.s:
|
||||
self.s.close()
|
||||
self.s = None
|
||||
def set_center_freq(self,target_freq):
|
||||
if not self.s: return 1
|
||||
__next_freq = target_freq
|
||||
__next_freq = struct.pack("<q",__next_freq)
|
||||
__set_freq_cmd = b"\x0a\x00\x20\x00\x00" + __next_freq[:5]
|
||||
self.s.send(__set_freq_cmd)
|
||||
__data = self.s.recv(10)
|
||||
__freq = __data[5:] + b"\x00\x00\x00"
|
||||
__freq = struct.unpack("<q",__freq)[0]
|
||||
return __freq
|
||||
|
||||
|
||||
def set_samp_rate(self,target_samprate):
|
||||
if not self.s: return 1
|
||||
#__samp_rate = target_samprate
|
||||
__samp_rate = struct.pack("<L",target_samprate)
|
||||
__set_rate_cmd = b"\x09\x00\xB8\x00\x00" + __samp_rate[:4]
|
||||
self.s.send(__set_rate_cmd)
|
||||
__data = self.s.recv(9)
|
||||
__samp = __data[5:] + b"\x00\x00\x00\x00"
|
||||
__samp = struct.unpack("<q",__samp)[0]
|
||||
return __samp
|
||||
|
||||
|
||||
def set_gain(self,target_gain):
|
||||
if not self.s: return 1
|
||||
__gain = target_gain
|
||||
# special afedri calculation for the gain byte
|
||||
__gain = ((__gain+10)/3 << 3) + 1
|
||||
__set_gain_cmd = b"\x06\x00\x38\x00\x00" + struct.pack("B",__gain)
|
||||
self.s.send(__set_gain_cmd)
|
||||
__data = self.s.recv(6)
|
||||
__rf_gain = -10 + 3 * (struct.unpack("B",__data[5:6])[0]>>3)
|
||||
return __rf_gain
|
||||
|
||||
def set_gain_indx(self,indx):
|
||||
if not self.s: return 1
|
||||
__gain = (indx << 3) + 1
|
||||
# special afedri calculation for the gain byte
|
||||
#__gain = ((__gain+10)/3 << 3) + 1
|
||||
__set_gain_cmd = b"\x06\x00\x38\x00\x00" + struct.pack("B",__gain)
|
||||
self.s.send(__set_gain_cmd)
|
||||
__data = self.s.recv(6)
|
||||
__rf_gain = -10 + 3 * (struct.unpack("B",__data[5:6])[0]>>3)
|
||||
return __rf_gain
|
||||
|
||||
def get_gain(self):
|
||||
"""
|
||||
NOT IMPLEMENTED IN AFEDRI?. DON'T USE
|
||||
"""
|
||||
if not self.s: return 1
|
||||
__get_gain_cmd = b"\x05\x20\x38\x00\x00"
|
||||
self.s.send(__get_gain_cmd)
|
||||
__data = self.s.recv(6)
|
||||
__rf_gain = -10 + 3 * (struct.unpack("B",__data[5:])[0]>>3)
|
||||
return __rf_gain
|
||||
|
||||
def get_fe_clock(self):
|
||||
if not self.s: return 1
|
||||
__get_lword_cmd = b"\x09\xE0\x02\x55\x00\x00\x00\x00\x00"
|
||||
__get_hword_cmd = b"\x09\xE0\x02\x55\x01\x00\x00\x00\x00"
|
||||
self.s.send(__get_lword_cmd)
|
||||
__data_l = self.s.recv(9)
|
||||
self.s.send(__get_hword_cmd)
|
||||
__data_h = self.s.recv(9)
|
||||
__fe_clock = struct.unpack("<H",__data_l[4:6])[0] + (struct.unpack("<H",__data_h[4:6])[0]<<16)
|
||||
return __fe_clock
|
||||
|
||||
def start_capture(self):
|
||||
#start 16-bit contiguous capture, complex numbers
|
||||
if not self.s: return 1
|
||||
__start_cmd=b"\x08\x00\x18\x00\x80\x02\x00\x00"
|
||||
self.s.send(__start_cmd)
|
||||
__data = self.s.recv(8)
|
||||
return __data
|
||||
|
||||
def get_sdr_name(self):
|
||||
#Request SDR's Name string command = array.array('B',[0x4, 0x20,1,0])
|
||||
if not self.s: return 1
|
||||
__start_cmd=b"\x04\x20\x01\x00"
|
||||
self.s.send(__start_cmd)
|
||||
__data = self.s.recv(16)
|
||||
__data = __data.decode('utf-8')
|
||||
return __data
|
||||
|
||||
def stop_capture(self):
|
||||
if not self.s: return 1
|
||||
__stop_cmd=b"\x08\x00\x18\x00\x00\x01\x00\x00"
|
||||
self.s.send(__stop_cmd)
|
||||
__data = self.s.recv(8)
|
||||
return __data
|
||||
|
||||
def __discover_afedri(self):
|
||||
# attempt to find AFEDRI SDR on the network
|
||||
# using AE4JY Simple Network Discovery Protocol
|
||||
|
||||
__DISCOVER_SERVER_PORT=48321 # PC client Tx port, SDR Server Rx Port
|
||||
__DISCOVER_CLIENT_PORT=48322 # PC client Rx port, SDR Server Tx Port
|
||||
|
||||
__data=b"\x38\x00\x5a\xa5" # magic discovery packet
|
||||
__data=__data.ljust(56,b"\x00") # pad with zeroes
|
||||
|
||||
self.s = socket(AF_INET, SOCK_DGRAM)
|
||||
self.s.bind(('', 0))
|
||||
self.s.setsockopt(SOL_SOCKET, SO_BROADCAST, 1)
|
||||
|
||||
self.sin = socket(AF_INET, SOCK_DGRAM)
|
||||
self.sin.bind(('', __DISCOVER_CLIENT_PORT))
|
||||
|
||||
#exception if no response to broadcast
|
||||
self.sin.settimeout(1)
|
||||
|
||||
|
||||
self.s.sendto(__data, ('<broadcast>',__DISCOVER_SERVER_PORT))
|
||||
try:
|
||||
__msg=self.sin.recv(256,0)
|
||||
__devname=__msg[5:20]
|
||||
__devname=__devname.decode('utf-8')
|
||||
__sn=__msg[21:36]
|
||||
__sn=__sn.decode('utf-8')
|
||||
__ip=inet_ntoa(__msg[40:36:-1])
|
||||
__port=struct.unpack("<H",__msg[53:55])[0]
|
||||
self.s.close()
|
||||
self.sin.close()
|
||||
print ("found ", __devname, __sn, __ip, __port)
|
||||
return (__ip,__port)
|
||||
except timeout:
|
||||
print ("No response from AFEDRI on the LAN")
|
||||
##sys.exit()
|
||||
return None, None
|
||||
|
||||
|
||||
def __del__(self):
|
||||
self.stop_capture()
|
||||
if self.s: self.s.close()
|
||||
|
||||
"""
|
||||
# verify and correct sampling rate according to the main clock speed
|
||||
# Alex Trushkin code 4z5lv:
|
||||
fe_main_clock_freq = a.get_fe_clock()
|
||||
tmp_div = fe_main_clock_freq / (4 * samp_rate)
|
||||
floor_div = math.floor(tmp_div)
|
||||
if (tmp_div - floor_div >= 0.5):
|
||||
floor_div += 1
|
||||
if floor_div < 15:
|
||||
floor_div = 15
|
||||
#print ("Warning: Max supported sampling rate is", math.floor(fe_main_clock_freq / (4 * floor_div)))
|
||||
elif floor_div > 625:
|
||||
floor_div = 625
|
||||
#print ("Warning: Min supported sampling rate is", math.floor(fe_main_clock_freq / (4 * floor_div)))
|
||||
|
||||
dSR = fe_main_clock_freq / (4 * floor_div)
|
||||
floor_SR = math.floor(dSR)
|
||||
if (dSR - floor_SR >= 0.5):
|
||||
floor_SR += 1
|
||||
if floor_SR != samp_rate:
|
||||
print ("Warning: invalid sample rate selected for the AFEDRI main clock (", fe_main_clock_freq, "Hz )")
|
||||
print (" setting to the next valid value", samp_rate, " => ", floor_SR)
|
||||
samp_rate = floor_SR
|
||||
"""
|
||||
@@ -0,0 +1,399 @@
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
#include <Winsock2.h>
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
#define QUISK_SHUT_RD SD_RECEIVE
|
||||
#define QUISK_SHUT_BOTH SD_BOTH
|
||||
#else
|
||||
#include <sys/socket.h>
|
||||
#include <arpa/inet.h>
|
||||
#define SOCKET int
|
||||
#define INVALID_SOCKET -1
|
||||
#define QUISK_SHUT_RD SHUT_RD
|
||||
#define QUISK_SHUT_BOTH SHUT_RDWR
|
||||
#endif
|
||||
|
||||
#include <complex.h>
|
||||
|
||||
#define IMPORT_QUISK_API
|
||||
#include "quisk.h"
|
||||
//#include "sdriq.h"
|
||||
|
||||
static SOCKET rx_udp_socket = INVALID_SOCKET; // Socket for receiving ADC samples from UDP
|
||||
static int rx_udp_started = 0; // Have we received any data yet?
|
||||
static int rx_udp_read_blocks = 0; // Number of blocks to read for each read call
|
||||
static double rx_udp_gain_correct = 1; // For decimation by 5, correct by 4096 / 5**5
|
||||
static int use_remove_dc=0; // Remove DC from samples
|
||||
//static int quisk_using_udp = 0;
|
||||
// This module provides access to the SDR-IQ by RfSpace. It is the source
|
||||
// for the Python extension module sdriq. It can be used as a model for an
|
||||
// extension module for other hardware. Read the end of this file for more
|
||||
// information. This module was written by James Ahlstrom, N2ADR.
|
||||
|
||||
// This module uses the Python interface to import symbols from the parent _quisk
|
||||
// extension module. It must be linked with import_quisk_api.c. See the documentation
|
||||
// at the start of import_quisk_api.c.
|
||||
|
||||
// Start of SDR-IQ specific code:
|
||||
//
|
||||
#define DEBUG 0
|
||||
|
||||
// Type field for the message block header; upper 3 bits of byte
|
||||
#define TYPE_HOST_SET 0
|
||||
#define TYPE_HOST_GET (1 << 5)
|
||||
#define NAME_SIZE 16
|
||||
|
||||
//#define UDP_BROADCAST
|
||||
#ifdef UDP_BROADCAST
|
||||
#define FIRST_IQ_DATA_IDX 20
|
||||
#define RX_UDP_SIZE 1044 // Expected size of UDP samples packet
|
||||
#else
|
||||
#define RX_UDP_SIZE 1028 // Expected size of UDP samples packet
|
||||
#define FIRST_IQ_DATA_IDX 4
|
||||
#endif
|
||||
#define BROADCAST_HEADER_SIZE 16
|
||||
#define UDP_PROTCOL_ID1 0x04
|
||||
#define UDP_PROTCOL_ID2 0x18
|
||||
|
||||
#ifdef DEBUG_IO
|
||||
#undef DEBUG_IO
|
||||
#define DEBUG_IO 1
|
||||
#endif
|
||||
|
||||
static PyObject * open_rx_udp(const char * ip, int port)
|
||||
{
|
||||
// const char * ip;
|
||||
// int port;
|
||||
char buf[128];
|
||||
struct sockaddr_in Addr;
|
||||
int recvsize;
|
||||
char optval;
|
||||
#if DEBUG_IO
|
||||
int intbuf;
|
||||
#ifdef MS_WINDOWS
|
||||
int bufsize = sizeof(int);
|
||||
#else
|
||||
socklen_t bufsize = sizeof(int);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
WORD wVersionRequested;
|
||||
WSADATA wsaData;
|
||||
#endif
|
||||
|
||||
// if (!PyArg_ParseTuple (args, "si", &ip, &port))
|
||||
// return NULL;
|
||||
// port = 50000;
|
||||
#ifdef MS_WINDOWS
|
||||
wVersionRequested = MAKEWORD(2, 2);
|
||||
if (WSAStartup(wVersionRequested, &wsaData) != 0) {
|
||||
sprintf(buf, "Failed to initialize Winsock (WSAStartup)");
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
#endif
|
||||
// quisk_using_udp = 1;
|
||||
rx_udp_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (rx_udp_socket != INVALID_SOCKET)
|
||||
{
|
||||
optval=1;
|
||||
setsockopt( rx_udp_socket, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval) );
|
||||
recvsize = 256000;
|
||||
setsockopt(rx_udp_socket, SOL_SOCKET, SO_RCVBUF, (char *)&recvsize, sizeof(recvsize));
|
||||
memset(&Addr, 0, sizeof(Addr));
|
||||
Addr.sin_family = AF_INET;
|
||||
Addr.sin_port = htons(port);
|
||||
Addr.sin_addr.s_addr = htonl(INADDR_ANY);//inet_addr("192.168.0.8");
|
||||
// Addr.sin_addr.S_un.S_addr = inet_addr(ip);
|
||||
// if (connect(rx_udp_socket, (const struct sockaddr *)&Addr, sizeof(Addr)) != 0)
|
||||
if (bind(rx_udp_socket, (const struct sockaddr *)&Addr, sizeof(Addr)) != 0)
|
||||
{
|
||||
shutdown(rx_udp_socket, QUISK_SHUT_BOTH);
|
||||
close(rx_udp_socket);
|
||||
rx_udp_socket = INVALID_SOCKET;
|
||||
sprintf(buf, "Failed to connect to UDP %s port %u", ip, port);
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "Capture from UDP %s port %u", ip, port);
|
||||
#if DEBUG_IO
|
||||
if (getsockopt(rx_udp_socket, SOL_SOCKET, SO_RCVBUF, (char *)&intbuf, &bufsize) == 0)
|
||||
{
|
||||
printf("UDP socket receive buffer size %d\n", intbuf);
|
||||
printf("address %s port %u\n", ip, port);
|
||||
}
|
||||
else
|
||||
printf ("Failure SO_RCVBUF\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
sprintf(buf, "Failed to open socket");
|
||||
}
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
|
||||
static PyObject * close_rx_udp(PyObject * self, PyObject * args)
|
||||
{
|
||||
short msg = 0x7373; // shutdown
|
||||
|
||||
if (!PyArg_ParseTuple (args, ""))
|
||||
return NULL;
|
||||
|
||||
if (rx_udp_socket != INVALID_SOCKET) {
|
||||
shutdown(rx_udp_socket, QUISK_SHUT_RD);
|
||||
send(rx_udp_socket, (char *)&msg, 2, 0);
|
||||
send(rx_udp_socket, (char *)&msg, 2, 0);
|
||||
QuiskSleepMicrosec(3000000);
|
||||
close(rx_udp_socket);
|
||||
rx_udp_socket = INVALID_SOCKET;
|
||||
}
|
||||
rx_udp_started = 0;
|
||||
|
||||
// if (quisk_using_udp) {
|
||||
// quisk_using_udp = 0;
|
||||
|
||||
#ifdef MS_WINDOWS
|
||||
WSACleanup();
|
||||
#endif
|
||||
// }
|
||||
Py_INCREF (Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
int afedri_read_rx_udp(complex * samp) // Read samples from UDP
|
||||
{ // Size of complex sample array is SAMP_BUFFER_SIZE
|
||||
ssize_t bytes;
|
||||
//int SR = 0;
|
||||
static int sample_rate = 0; // Sample rate such as 48000, 96000, 192000
|
||||
unsigned char buf[1500]; // Maximum Ethernet is 1500 bytes.
|
||||
static unsigned short seq0; // must be 8 bits
|
||||
unsigned short seq_curr = 0;
|
||||
#ifdef MS_WINDOWS
|
||||
__int32 i, count, nSamples, xr, xi, index;
|
||||
#else
|
||||
int32_t i, count, nSamples, xr, xi, index;
|
||||
#endif
|
||||
unsigned char * ptxr, * ptxi;
|
||||
static complex dc_average = 0; // Average DC component in samples
|
||||
static complex dc_sum = 0;
|
||||
static int dc_count = 0;
|
||||
static int dc_key_delay = 0;
|
||||
|
||||
// Data from the receiver is little-endian
|
||||
// if ( !rx_udp_read_blocks)
|
||||
if(sample_rate != pt_quisk_sound_state->sample_rate)
|
||||
{
|
||||
sample_rate = pt_quisk_sound_state->sample_rate;
|
||||
// "rx_udp_read_blocks" is the number of UDP blocks to read at once
|
||||
rx_udp_read_blocks = (int)(pt_quisk_sound_state->data_poll_usec * 1e-6 * sample_rate + 0.5);
|
||||
rx_udp_read_blocks = (rx_udp_read_blocks + (RX_UDP_SIZE / 12)) / (RX_UDP_SIZE / 6); // 6 bytes per sample
|
||||
if (rx_udp_read_blocks < 1)
|
||||
rx_udp_read_blocks = 1;
|
||||
#if DEBUG_IO
|
||||
printf("read_rx_udp: rx_udp_read_blocks %d\n", rx_udp_read_blocks);
|
||||
#endif
|
||||
}
|
||||
/* if ( ! rx_udp_gain_correct) {
|
||||
int dec;
|
||||
dec = (int)(rx_udp_clock / sample_rate + 0.5);
|
||||
if ((dec / 5) * 5 == dec) // Decimation by a factor of 5
|
||||
rx_udp_gain_correct = 1.31072;
|
||||
else // Decimation by factors of two
|
||||
rx_udp_gain_correct = 1.0;
|
||||
}
|
||||
*/
|
||||
nSamples = 0;
|
||||
for (count = 0; count < rx_udp_read_blocks; count++)
|
||||
{ // read several UDP blocks
|
||||
#if DEBUG_IO
|
||||
// printf("Data RX Process Begin %u\n",count);
|
||||
#endif
|
||||
bytes = recv(rx_udp_socket, (char *)buf, RX_UDP_SIZE, 0); // blocking read
|
||||
if (bytes != RX_UDP_SIZE) { // Known size of sample block
|
||||
pt_quisk_sound_state->read_error++;
|
||||
#if DEBUG_IO
|
||||
printf("read_rx_udp: Bad block size %i\n", (int)bytes);
|
||||
#endif
|
||||
continue;
|
||||
}
|
||||
// buf[0] is the sequence number
|
||||
// buf[1] is the status:
|
||||
// bit 0: key up/down state
|
||||
// bit 1: set for ADC overrange (clip)
|
||||
seq_curr = buf[2] | (buf[3] << 8);
|
||||
if (seq_curr != seq0) {
|
||||
#if DEBUG_IO
|
||||
printf("read_rx_udp: Bad sequence want %3d got %3d at block %d of %d\n",
|
||||
(unsigned int)seq0, (unsigned int)buf[0], count, rx_udp_read_blocks);
|
||||
#endif
|
||||
pt_quisk_sound_state->read_error++;
|
||||
}
|
||||
seq0 = seq_curr + 1; // Next expected sequence number
|
||||
// quisk_set_key_down(buf[1] & 0x01); // bit zero is key state
|
||||
// if (buf[1] & 0x02) // bit one is ADC overrange
|
||||
// quisk_sound_state.overrange++;
|
||||
index = FIRST_IQ_DATA_IDX;
|
||||
ptxr = (unsigned char *)&xr;
|
||||
ptxi = (unsigned char *)ξ
|
||||
// convert 24-bit samples to 32-bit samples; int must be 32 bits.
|
||||
while (index < bytes)
|
||||
{
|
||||
xr = xi = 0;
|
||||
memcpy (ptxr + 2, buf + index, 2);
|
||||
index += 2;
|
||||
memcpy (ptxi + 2, buf + index, 2);
|
||||
index += 2;
|
||||
samp[nSamples++] = (xr + xi * I) * rx_udp_gain_correct;
|
||||
xr = xi = 0;
|
||||
memcpy (ptxr + 2, buf + index, 2);
|
||||
index += 2;
|
||||
memcpy (ptxi + 2, buf + index, 2);
|
||||
index += 2;
|
||||
samp[nSamples++] = (xr + xi * I) * rx_udp_gain_correct;;
|
||||
//if (nSamples == 2) printf("%12d %12d\n", xr, xi);
|
||||
}
|
||||
}
|
||||
if (quisk_is_key_down()) {
|
||||
dc_key_delay = 0;
|
||||
dc_sum = 0;
|
||||
dc_count = 0;
|
||||
}
|
||||
else if (dc_key_delay < pt_quisk_sound_state->sample_rate) {
|
||||
dc_key_delay += nSamples;
|
||||
}
|
||||
else {
|
||||
dc_count += nSamples;
|
||||
for (i = 0; i < nSamples; i++) // Correction for DC offset in samples
|
||||
dc_sum += samp[i];
|
||||
if (dc_count > pt_quisk_sound_state->sample_rate * 2) {
|
||||
dc_average = dc_sum / dc_count;
|
||||
dc_sum = 0;
|
||||
dc_count = 0;
|
||||
//printf("dc average %lf %lf %d\n", creal(dc_average), cimag(dc_average), dc_count);
|
||||
//printf("dc polar %.0lf %d\n", cabs(dc_average),
|
||||
// (int)(360.0 / 2 / M_PI * atan2(cimag(dc_average), creal(dc_average))));
|
||||
}
|
||||
}
|
||||
if (use_remove_dc)
|
||||
for (i = 0; i < nSamples; i++) // Correction for DC offset in samples
|
||||
samp[i] -= dc_average;
|
||||
|
||||
// printf("%u\n", pt_quisk_sound_state->sample_rate);
|
||||
return nSamples;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// End of most AFEDRI specific code.
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// The API requires at least two Python functions for Open and Close, plus
|
||||
// additional Python functions as needed. And it requires exactly three
|
||||
// C funcions for Start, Stop and Read samples. Quisk runs in two threads,
|
||||
// a GUI thread and a sound thread. You must not call the GUI or any Python
|
||||
// code from the sound thread. You must return promptly from functions called
|
||||
// by the sound thread.
|
||||
//
|
||||
// The calling sequence is Open, Start, then repeated calls to Read, then
|
||||
// Stop, then Close.
|
||||
|
||||
// Start of Application Programming Interface (API) code:
|
||||
|
||||
// Called to close the sample source; called from the GUI thread.
|
||||
static PyObject * close_samples(PyObject * self, PyObject * args)
|
||||
{
|
||||
if (!PyArg_ParseTuple (args, ""))
|
||||
return NULL;
|
||||
close_rx_udp(self, args);
|
||||
Py_INCREF (Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// Called to open the sample source; called from the GUI thread.
|
||||
static PyObject * open_samples(PyObject * self, PyObject * args)
|
||||
{
|
||||
const char * ip;
|
||||
int port;
|
||||
// const char * name;
|
||||
// char buf[128];
|
||||
|
||||
if (!PyArg_ParseTuple (args, "si", &ip, &port))
|
||||
return NULL;
|
||||
|
||||
// name = QuiskGetConfigString("sdriq_name", "NoName");
|
||||
// sdriq_clock = QuiskGetConfigDouble("sdriq_clock", 66666667.0);
|
||||
|
||||
// Record our C-language Start/Stop/Read functions for use by sound.c.
|
||||
quisk_sample_source(NULL, NULL, &afedri_read_rx_udp);
|
||||
//////////////
|
||||
return open_rx_udp(ip, port); // AFEDRI specific
|
||||
// return PyString_FromString(buf); // return a string message
|
||||
}
|
||||
|
||||
// Miscellaneous functions needed by the SDR-IQ; called from the GUI thread as
|
||||
// a result of button presses.
|
||||
|
||||
|
||||
// Functions callable from Python are listed here:
|
||||
static PyMethodDef QuiskMethods[] = {
|
||||
{"open_samples", open_samples, METH_VARARGS, "Open the AFEDRI SDR-Net."},
|
||||
{"close_samples", close_samples, METH_VARARGS, "Close the AFEDRI SDR-Net."},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
// Python 2.7:
|
||||
PyMODINIT_FUNC initafedrinet_io (void)
|
||||
{
|
||||
if (Py_InitModule ("afedrinet_io", QuiskMethods) == NULL) {
|
||||
printf("Py_InitModule failed!\n");
|
||||
return;
|
||||
}
|
||||
// Import pointers to functions and variables from module _quisk
|
||||
if (import_quisk_api()) {
|
||||
printf("Failure to import pointers from _quisk\n");
|
||||
return; //Error
|
||||
}
|
||||
}
|
||||
|
||||
// Python 3:
|
||||
#else
|
||||
static struct PyModuleDef afedrinet_iomodule = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"afedrinet_io",
|
||||
NULL,
|
||||
-1,
|
||||
QuiskMethods
|
||||
} ;
|
||||
|
||||
PyMODINIT_FUNC PyInit_afedrinet_io(void)
|
||||
{
|
||||
PyObject * m;
|
||||
|
||||
m = PyModule_Create(&afedrinet_iomodule);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
// Import pointers to functions and variables from module _quisk
|
||||
if (import_quisk_api()) {
|
||||
printf("Failure to import pointers from _quisk\n");
|
||||
return m; //Error
|
||||
}
|
||||
return m;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
afedrinet2:
|
||||
python2 setup.py build_ext --force --inplace
|
||||
|
||||
afedrinet3:
|
||||
python3 setup.py build_ext --force --inplace
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
# This is a sample quisk_conf.py configuration file for Microsoft Windows.
|
||||
|
||||
# For Windows, your default config file name is "My Documents/quisk_conf.py",
|
||||
# but you can use a different config file by using -c or --config. Quisk creates
|
||||
# an initial default config file if there is none. To control Quisk, edit
|
||||
# "My Documents/quisk_conf.py" using any text editor; for example WordPad (not Notepad).
|
||||
|
||||
# In Windows you can see what sound devices you have, and you can set the Primary
|
||||
# Device for capture and playback by using Control Panel/Sounds and Audio Devices.
|
||||
# If you have only one sound device, it should be set as "Primary". If you have
|
||||
# several, find the names by using Control Panel/Sounds and Audio Devices; for
|
||||
# example, you may have "SoundMAX HD Audio" in the list for "Sound playback" and
|
||||
# "Sound recording". To specify this device for capture (recording) or playback,
|
||||
# enter a unique part of its name using exact upper/lower case. For example:
|
||||
# name_of_sound_capture = "SoundMAX"
|
||||
# name_of_sound_play = "SoundMAX"
|
||||
|
||||
# There are many possible options for your config file. Copy the ones you want
|
||||
# from the master file quisk_conf_defaults.py (but don't change the master file).
|
||||
# The master config file is located in the site-packages/quisk folder for Python 2.7.
|
||||
|
||||
# This file is Python code and the comment character is "#". To ignore a line,
|
||||
# start it with "#". To un-ignore a line, remove the "#". Generally you must start
|
||||
# lines in column one (the left edge) except for logic blocks.
|
||||
from afedrinet import quisk_hardware # Use different hardware file
|
||||
|
||||
use_rx_udp = 1 # Get ADC samples from UDP
|
||||
rx_udp_ip = "192.168.0.8" # Sample source IP address
|
||||
rx_udp_port = 50000 # Sample source UDP port
|
||||
rx_udp_clock = 79998382 # ADC sample rate in Hertz
|
||||
#rx_udp_decimation = 8 * 8 * 8 # Decimation from clock to UDP sample rate
|
||||
#sample_rate = int(float(rx_udp_clock) / rx_udp_decimation + 0.5) # Don't change this
|
||||
data_poll_usec = 10000
|
||||
#sample_rate = 192000 # ADC hardware sample rate in Hertz
|
||||
sample_rate = 740740 # ADC hardware sample rate in Hertz
|
||||
playback_rate = 48000 # Radio sound play rate
|
||||
name_of_sound_capt = ""#AFEDRI-SDR-Net Audio" # Name of soundcard capture hardware device.
|
||||
name_of_sound_play = "Buil-in Output" # Use the same device for play back.
|
||||
#name_of_sound_play = "Line 1"#Virtual Audio Cable" # Use the same device for play back.
|
||||
latency_millisecs = 50 # latency time in milliseconds
|
||||
display_fraction = 0.92 # The edges of the full bandwidth are not valid
|
||||
default_rf_gain = 11
|
||||
# Select the default screen when Quisk starts:
|
||||
#default_screen = 'Graph'
|
||||
default_screen = 'WFall'
|
||||
|
||||
# If you use hardware with a fixed VFO (crystal controlled SoftRock) un-comment the following:
|
||||
# import quisk_hardware_fixed as quisk_hardware
|
||||
# fixed_vfo_freq = 7056000
|
||||
|
||||
# If you use an SDR-IQ for capture, first install the SpectraView software
|
||||
# that came with the SDR-IQ. This will install the USB driver. Then set these parameters:
|
||||
# import quisk_hardware_sdriq as quisk_hardware # Use different hardware file
|
||||
# use_sdriq = 1 # Capture device is the SDR-IQ
|
||||
# sdriq_name = "SDR-IQ" # Name of the SDR-IQ device to open
|
||||
# sdriq_clock = 66666667.0 # actual sample rate (66666667 nominal)
|
||||
# sdriq_decimation = 500 # Must be 360, 500, 600, or 1250
|
||||
# sample_rate = int(float(sdriq_clock) / sdriq_decimation + 0.5) # Don't change this
|
||||
# name_of_sound_capt = "" # We do not capture from the soundcard
|
||||
# playback_rate = 48000 # Radio sound play rate, default 48000
|
||||
# display_fraction = 0.85 # The edges of the full bandwidth are not valid
|
||||
@@ -0,0 +1,54 @@
|
||||
# This is a sample quisk_conf.py configuration file for Linux
|
||||
# For Windows, your default config file name is "/home/user/quisk_conf.py"
|
||||
# but you can use a different config file by using -c or --config. Quisk creates
|
||||
# an initial default config file if there is none. To control Quisk, edit
|
||||
# "/home/user/quisk_conf.py" using any text editor; for example WordPad (not Notepad).
|
||||
# In Windows you can see what sound devices you have, and you can set the Primary
|
||||
# Device for capture and playback by using Control Panel/Sounds and Audio Devices.
|
||||
# If you have only one sound device, it should be set as "Primary". If you have
|
||||
# several, find the names by using Control Panel/Sounds and Audio Devices; for
|
||||
# example, you may have "SoundMAX HD Audio" in the list for "Sound playback" and
|
||||
# "Sound recording". To specify this device for capture (recording) or playback,
|
||||
# enter a unique part of its name using exact upper/lower case. For example:
|
||||
# name_of_sound_capture = "SoundMAX"
|
||||
# name_of_sound_play = "SoundMAX"
|
||||
# There are many possible options for your config file. Copy the ones you want
|
||||
# from the master file quisk_conf_defaults.py (but don't change the master file).
|
||||
# The master config file is located in the site-packages/quisk folder for Python 2.7.
|
||||
# This file is Python code and the comment character is "#". To ignore a line,
|
||||
# start it with "#". To un-ignore a line, remove the "#". Generally you must start
|
||||
# lines in column one (the left edge) except for logic blocks.
|
||||
from afedrinet import quisk_hardware # Use different hardware file
|
||||
use_rx_udp = 1 # Get ADC samples from UDP
|
||||
rx_udp_ip = "192.168.0.8" # Sample source IP address
|
||||
rx_udp_port = 50000 # Sample source UDP port
|
||||
rx_udp_clock = 80000000 # ADC sample rate in Hertz
|
||||
#rx_udp_decimation = 8 * 8 * 8 # Decimation from clock to UDP sample rate
|
||||
#sample_rate = int(float(rx_udp_clock) / rx_udp_decimation + 0.5) # Don't change this
|
||||
data_poll_usec = 10000
|
||||
#sample_rate = 192000 # ADC hardware sample rate in Hertz
|
||||
sample_rate = 740740 # ADC hardware sample rate in Hertz
|
||||
playback_rate = 48000 # Radio sound play rate
|
||||
name_of_sound_capt = ""#AFEDRI-SDR-Net Audio" # Name of soundcard capture hardware device.
|
||||
name_of_sound_play = "portaudiodefault"#hw:0,0" # Use the same device for play back.
|
||||
#name_of_sound_play = "Line 1"#Virtual Audio Cable" # Use the same device for play back.
|
||||
latency_millisecs = 50 # latency time in milliseconds
|
||||
display_fraction = 0.92 # The edges of the full bandwidth are not valid
|
||||
default_rf_gain = 14
|
||||
# Select the default screen when Quisk starts:
|
||||
#default_screen = 'Graph'
|
||||
default_screen = 'WFall'
|
||||
# If you use hardware with a fixed VFO (crystal controlled SoftRock) un-comment the following:
|
||||
# import quisk_hardware_fixed as quisk_hardware
|
||||
# fixed_vfo_freq = 7056000
|
||||
# If you use an SDR-IQ for capture, first install the SpectraView software
|
||||
# that came with the SDR-IQ. This will install the USB driver. Then set these parameters:
|
||||
# import quisk_hardware_sdriq as quisk_hardware # Use different hardware file
|
||||
# use_sdriq = 1 # Capture device is the SDR-IQ
|
||||
# sdriq_name = "SDR-IQ" # Name of the SDR-IQ device to open
|
||||
# sdriq_clock = 66666667.0 # actual sample rate (66666667 nominal)
|
||||
# sdriq_decimation = 500 # Must be 360, 500, 600, or 1250
|
||||
# sample_rate = int(float(sdriq_clock) / sdriq_decimation + 0.5) # Don't change this
|
||||
# name_of_sound_capt = "" # We do not capture from the soundcard
|
||||
# playback_rate = 48000 # Radio sound play rate, default 48000
|
||||
# display_fraction = 0.85 # The edges of the full bandwidth are not valid
|
||||
@@ -0,0 +1,54 @@
|
||||
# This is a sample quisk_conf.py configuration file for Linux
|
||||
# For Windows, your default config file name is "/home/user/quisk_conf.py"
|
||||
# but you can use a different config file by using -c or --config. Quisk creates
|
||||
# an initial default config file if there is none. To control Quisk, edit
|
||||
# "/home/user/quisk_conf.py" using any text editor; for example WordPad (not Notepad).
|
||||
# In Windows you can see what sound devices you have, and you can set the Primary
|
||||
# Device for capture and playback by using Control Panel/Sounds and Audio Devices.
|
||||
# If you have only one sound device, it should be set as "Primary". If you have
|
||||
# several, find the names by using Control Panel/Sounds and Audio Devices; for
|
||||
# example, you may have "SoundMAX HD Audio" in the list for "Sound playback" and
|
||||
# "Sound recording". To specify this device for capture (recording) or playback,
|
||||
# enter a unique part of its name using exact upper/lower case. For example:
|
||||
# name_of_sound_capture = "SoundMAX"
|
||||
# name_of_sound_play = "SoundMAX"
|
||||
# There are many possible options for your config file. Copy the ones you want
|
||||
# from the master file quisk_conf_defaults.py (but don't change the master file).
|
||||
# The master config file is located in the site-packages/quisk folder for Python 2.7.
|
||||
# This file is Python code and the comment character is "#". To ignore a line,
|
||||
# start it with "#". To un-ignore a line, remove the "#". Generally you must start
|
||||
# lines in column one (the left edge) except for logic blocks.
|
||||
from afedrinet import quisk_hardware # Use different hardware file
|
||||
use_rx_udp = 1 # Get ADC samples from UDP
|
||||
rx_udp_ip = "192.168.0.8" # Sample source IP address
|
||||
rx_udp_port = 50000 # Sample source UDP port
|
||||
rx_udp_clock = 80000000 # ADC sample rate in Hertz
|
||||
#rx_udp_decimation = 8 * 8 * 8 # Decimation from clock to UDP sample rate
|
||||
#sample_rate = int(float(rx_udp_clock) / rx_udp_decimation + 0.5) # Don't change this
|
||||
data_poll_usec = 10000
|
||||
#sample_rate = 192000 # ADC hardware sample rate in Hertz
|
||||
sample_rate = 740740 # ADC hardware sample rate in Hertz
|
||||
playback_rate = 48000 # Radio sound play rate
|
||||
name_of_sound_capt = ""#AFEDRI-SDR-Net Audio" # Name of soundcard capture hardware device.
|
||||
name_of_sound_play = "portaudiodefault"#hw:0,0" # Use the same device for play back.
|
||||
#name_of_sound_play = "Line 1"#Virtual Audio Cable" # Use the same device for play back.
|
||||
latency_millisecs = 50 # latency time in milliseconds
|
||||
display_fraction = 0.92 # The edges of the full bandwidth are not valid
|
||||
default_rf_gain = 14
|
||||
# Select the default screen when Quisk starts:
|
||||
#default_screen = 'Graph'
|
||||
default_screen = 'WFall'
|
||||
# If you use hardware with a fixed VFO (crystal controlled SoftRock) un-comment the following:
|
||||
# import quisk_hardware_fixed as quisk_hardware
|
||||
# fixed_vfo_freq = 7056000
|
||||
# If you use an SDR-IQ for capture, first install the SpectraView software
|
||||
# that came with the SDR-IQ. This will install the USB driver. Then set these parameters:
|
||||
# import quisk_hardware_sdriq as quisk_hardware # Use different hardware file
|
||||
# use_sdriq = 1 # Capture device is the SDR-IQ
|
||||
# sdriq_name = "SDR-IQ" # Name of the SDR-IQ device to open
|
||||
# sdriq_clock = 66666667.0 # actual sample rate (66666667 nominal)
|
||||
# sdriq_decimation = 500 # Must be 360, 500, 600, or 1250
|
||||
# sample_rate = int(float(sdriq_clock) / sdriq_decimation + 0.5) # Don't change this
|
||||
# name_of_sound_capt = "" # We do not capture from the soundcard
|
||||
# playback_rate = 48000 # Radio sound play rate, default 48000
|
||||
# display_fraction = 0.85 # The edges of the full bandwidth are not valid
|
||||
@@ -0,0 +1,94 @@
|
||||
# Please do not change this hardware control module.
|
||||
# It provides support for the SDR-IQ by RfSpace.
|
||||
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
#import _quisk as QS
|
||||
import os,sys
|
||||
#sys.path.append('./afedri')
|
||||
try:
|
||||
import afedrinet_io as AF
|
||||
from sdr_control import *
|
||||
except:
|
||||
from afedrinet import afedrinet_io as AF
|
||||
from afedrinet.sdr_control import *
|
||||
from ctypes import *
|
||||
os.environ['PATH'] = os.path.dirname(__file__) + ';' + os.environ['PATH']
|
||||
#from quisk import App as parent
|
||||
from quisk_hardware_model import Hardware as BaseHardware
|
||||
#from quisk import *
|
||||
|
||||
class Hardware(BaseHardware):
|
||||
def __init__(self, app, conf):
|
||||
BaseHardware.__init__(self, app, conf)
|
||||
self.local_tune = 2
|
||||
self.index = 0
|
||||
self.clock = 80000000
|
||||
self.old_LO_freq = 0
|
||||
self.rf_gain_labels = ('RF -10','RF -7','RF -4','RF -1','+2','+5','+8','+11','+14','+17','+20','+23','+26','+29','+32','+35')
|
||||
self.conf = conf
|
||||
self.plugin = Control(self.conf.rx_udp_ip, self.conf.rx_udp_port)
|
||||
self.app = app
|
||||
self.decimations = [] # supported decimation rates
|
||||
for dec in (53333, 96000, 133333, 185185, 192000, 370370, 740740, 1333333):
|
||||
self.decimations.append(dec)
|
||||
def open(self):
|
||||
self.plugin.OpenHW() # Return a config message
|
||||
RF_Gain_idx = int((10 + self.conf.default_rf_gain) / 3)
|
||||
if not 0 <= RF_Gain_idx < len(self.rf_gain_labels):
|
||||
RF_Gain_idx = 0
|
||||
self.plugin.SetAttenuator(RF_Gain_idx)
|
||||
self.app.BtnRfGain.SetIndex(RF_Gain_idx)
|
||||
#print ("RF Gain %i" % self.conf.default_rf_gain)
|
||||
return AF.open_samples(self.conf.rx_udp_ip, self.conf.rx_udp_port)
|
||||
def close(self):
|
||||
self.plugin.CloseHW()
|
||||
def OnButtonRfGain(self, event):
|
||||
btn = event.GetEventObject()
|
||||
n = btn.index
|
||||
if n > -1 or n < 16 :
|
||||
self.plugin.SetAttenuator(n)
|
||||
else:
|
||||
print ('Unknown RfGain')
|
||||
def ChangeFrequency(self, tune, vfo, source='', band='', event=None):
|
||||
self.local_tune = tune
|
||||
if vfo:
|
||||
self.plugin.SetHWLO(vfo)
|
||||
return tune, vfo
|
||||
def ReturnFrequency(self): # Return the current tuning and VFO frequency
|
||||
return (None, None) # Return LO frequency
|
||||
def GetFirmwareVersion(self):
|
||||
return 226
|
||||
def HeartBeat(self):
|
||||
# self.PrintStatus('Start', 'AFEDRI')
|
||||
return
|
||||
def VarDecimGetChoices(self): # Return a list/tuple of strings for the decimation control.
|
||||
l = [] # a list of sample rates
|
||||
for dec in self.decimations:
|
||||
l.append(str( dec ))
|
||||
return l
|
||||
def VarDecimGetLabel(self): # return a text label for the control
|
||||
return "Sample rate sps"
|
||||
def VarDecimGetIndex(self): # return the current index
|
||||
return self.index
|
||||
def VarDecimSet(self, index=None): # set decimation, return sample rate
|
||||
if index is None: # initial call to set decimation before the call to open()
|
||||
rate = self.application.vardecim_set # May be None or from different hardware
|
||||
try:
|
||||
dec = rate #int(float(self.conf.rx_udp_clock / rate + 0.5))
|
||||
self.index = self.decimations.index(dec)
|
||||
except:
|
||||
try:
|
||||
self.index = self.decimations.index(self.conf.sample_rate)
|
||||
except:
|
||||
self.index = 0
|
||||
else:
|
||||
self.index = index
|
||||
dec = self.decimations[self.index]
|
||||
self.plugin.SetHWSR(dec) # Return a config message
|
||||
return dec
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
Hello All!
|
||||
I want to publish here some information about possibility to use Quisk application on MAC computers running MAC OSX.
|
||||
It is for experienced MAC OS users that know what is Terminal and command shell tools and how to compile executable from source code:
|
||||
|
||||
1. You should download Quisk package from author's web page
|
||||
2. Xcode SDK and command tools
|
||||
3. Install macports to manage ports that required to be used with Quisk
|
||||
4. You should install the next packages:
|
||||
python27, py27-wxpython-2.8, fftw-3.0 , portaudio, pulseaudio and probably some additional
|
||||
5. Be ready that packages installation will take long time. Select macports python as default python executable:
|
||||
>> sudo port select --set python python27
|
||||
6. After you will extract Quisk files from archive to separate directory you must enter Quisk directory and compile Quisk for your system running next command:
|
||||
>> make macports
|
||||
7. After installation to use Quisk with AFEDRi SDR, you have to download additional packages: afedriusb , afedrinet extract contains of archive to separated folders afedriusb and afedrinet in main Quisk directory.
|
||||
8. For network connected AFEDRI you must enter afedrinet folder and compile SDR support library running afe_library script, before you can run this script you must modify path to python library and include folders in this script, for example on my MAC it looks like:
|
||||
###############################################################
|
||||
gcc -o afedrinet_io.so --shared afedrinet_io.c ../is_key_down.c ../import_quisk_api.c -I"../" -I"/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/" -L"/opt/local/Library/Frameworks/Python.framework/Versions/2.7/lib/" -lpython2.7
|
||||
###################################################################
|
||||
9. For USB connection you must download the sdr_commander v1.22
|
||||
Extract archive to separate folder and compile source code.
|
||||
After successful compilation you will get executable sdr_commander, you must
|
||||
copy it to quick/afedriusb folder
|
||||
10.
|
||||
10. Edit qusik_conf.py file to define correct sound device (card) name, copy this file as .quisk_conf.py to user's home directory.
|
||||
For example for portaudio devices it will look like this one:
|
||||
|
||||
#################################################################
|
||||
from afedriusb import quisk_hardware
|
||||
sample_rate = 185185
|
||||
name_of_sound_capt = "portaudio#2"
|
||||
name_of_sound_play = "portaudiodefault"
|
||||
latency_millisecs = 150
|
||||
default_rf_gain = 14
|
||||
default_screen = 'WFall'
|
||||
playback_rate = 48000
|
||||
default 48000
|
||||
##########################################################
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
#!/usr/bin/python # This is client.py file
|
||||
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
import os,sys
|
||||
os.environ['PATH'] = os.path.dirname(__file__) + ';' + os.environ['PATH']
|
||||
|
||||
import afedrinet
|
||||
import afedrinet.afedri
|
||||
|
||||
class Control:
|
||||
def __init__(self, sdr_address="192.168.0.8", sdr_port=50000):
|
||||
self.hw = afedrinet.afedri.afedri(sdr_address, sdr_port)
|
||||
if self.hw.s is None: # Failure to find the hardware
|
||||
self.hw = None
|
||||
def OpenHW(self):
|
||||
if not self.hw: return
|
||||
data = self.hw.get_sdr_name()
|
||||
print (data[4:])
|
||||
self.hw.start_capture()
|
||||
def CloseHW(self):
|
||||
if not self.hw: return
|
||||
self.hw.stop_capture()
|
||||
self.hw.close # Close the socket when done
|
||||
def SetHWLO(self, vfo):
|
||||
if not self.hw: return
|
||||
self.hw.set_center_freq(vfo)
|
||||
def SetHWSR(self, sample_rate):
|
||||
if not self.hw: return
|
||||
self.hw.set_samp_rate(sample_rate)
|
||||
print ("Sample Rate %i" % sample_rate)
|
||||
def SetAttenuator(self, indx):
|
||||
if not self.hw: return
|
||||
self.hw.set_gain_indx(indx)
|
||||
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
from distutils.core import setup, Extension
|
||||
import sys
|
||||
|
||||
# Afedri hardware support added by Alex, Alex@gmail.com
|
||||
|
||||
if sys.platform == "win32":
|
||||
Modules = [
|
||||
Extension ('afedrinet.afedrinet_io',
|
||||
libraries = ['WS2_32'],
|
||||
sources = ['../import_quisk_api.c', '../is_key_down.c', 'afedrinet_io.c'],
|
||||
include_dirs = ['.', '..'],
|
||||
)
|
||||
]
|
||||
else:
|
||||
Modules = [
|
||||
Extension ('afedrinet.afedrinet_io',
|
||||
libraries = ['m'],
|
||||
sources = ['../import_quisk_api.c', '../is_key_down.c', 'afedrinet_io.c'],
|
||||
include_dirs = ['.', '..'],
|
||||
)
|
||||
]
|
||||
|
||||
setup (name = 'afedrinet_io',
|
||||
version = '0.1',
|
||||
description = 'Afedri',
|
||||
long_description = "Afedri.",
|
||||
author = 'Alex',
|
||||
author_email = 'Alex@gmail.com',
|
||||
#url = 'http://',
|
||||
download_url = 'http://james.ahlstrom.name/quisk/',
|
||||
packages = ['afedrinet.afedrinet_io'],
|
||||
package_dir = {'afedrinet' : '.'},
|
||||
ext_modules = Modules,
|
||||
classifiers = [
|
||||
'Development Status :: 6 - Mature',
|
||||
'Environment :: X11 Applications',
|
||||
'Environment :: Win32 (MS Windows)',
|
||||
'Intended Audience :: End Users/Desktop',
|
||||
'License :: OSI Approved :: GNU General Public License (GPL)',
|
||||
'Natural Language :: English',
|
||||
'Operating System :: POSIX :: Linux',
|
||||
'Operating System :: Microsoft :: Windows',
|
||||
'Programming Language :: Python',
|
||||
'Programming Language :: C',
|
||||
'Topic :: Communications :: Ham Radio',
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
from __future__ import print_function
|
||||
from __future__ import absolute_import
|
||||
from __future__ import division
|
||||
|
||||
import os,sys
|
||||
from ctypes import *
|
||||
os.environ['PATH'] = os.path.dirname(__file__) + ';' + os.environ['PATH']
|
||||
from sdr_control import *
|
||||
#import sdr_control
|
||||
|
||||
#class self(control)
|
||||
cnt = Control()
|
||||
cnt.OpenHW()
|
||||
cnt.SetHWLO(28050000)
|
||||
cnt.SetHWSR(740740)
|
||||
cnt.CloseHW()
|
||||
Reference in New Issue
Block a user