bug fixes, python

bug_fixes_integration_tx
David Michaeli 2021-12-05 22:22:22 +02:00
rodzic f704da6c93
commit d465c5b425
11 zmienionych plików z 204 dodań i 80 usunięć

Wyświetl plik

@ -1,49 +1,57 @@
from PySimpleGUI.PySimpleGUI import Canvas, Column
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
import SoapySDR
from SoapySDR import SOAPY_SDR_RX, SOAPY_SDR_CS16
from SoapySDR import SOAPY_SDR_RX, SOAPY_SDR_TX, SOAPY_SDR_CS16
from PySimpleGUI import Window, WIN_CLOSED, Slider, Button, theme, Text, Radio, Image
from numpy.lib.arraypad import pad
# Enumerate the Soapy devices
res = SoapySDR.Device.enumerate()
for result in res:
print(result)
def draw_figure_with_toolbar(canvas, fig, canvas_toolbar):
if canvas.children:
for child in canvas.winfo_children():
child.destroy()
if canvas_toolbar.children:
for child in canvas_toolbar.winfo_children():
child.destroy()
figure_canvas_agg = FigureCanvasTkAgg(fig, master=canvas)
figure_canvas_agg.draw()
# Data and Source Configuration
rx_chan = 1 # RX1 = 0, RX2 = 1
N = 16384 # Number of complex samples per transfer
fs = 4e6 # Radio sample Rate
freq = 868e6 # LO tuning frequency in Hz
use_agc = True # Use or don't use the AGC
timeout_us = int(5e6)
toolbar = Toolbar(figure_canvas_agg, canvas_toolbar)
toolbar.update()
figure_canvas_agg.get_tk_widget().pack(side='right', fill='both', expand=1)
# Initialize CaribouLite
sdr = SoapySDR.Device(dict(driver="Cariboulite")) # Create Cariboulite
sdr.setSampleRate(SOAPY_SDR_RX, rx_chan, fs) # Set sample rate
sdr.setGainMode(SOAPY_SDR_RX, rx_chan, use_agc) # Set the gain mode
sdr.setFrequency(SOAPY_SDR_RX, rx_chan, freq) # Tune the LO
sdr.setBandwidth(SOAPY_SDR_RX, rx_chan, 2.5e6)
# Create data buffer and start streaming samples to it
rx_buff = np.empty(2 * N, np.int16) # Create memory buffer for data stream
rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [
rx_chan]) # Setup data stream
sdr.activateStream(rx_stream) # this turns the radio on
class Toolbar(NavigationToolbar2Tk):
def __init__(self, *args, **kwargs):
super(Toolbar, self).__init__(*args,**kwargs)
# Save the file names for plotting later. Remove if not plotting.
file_names = []
file_ctr = 0
nfiles = 1
def create_window():
#theme("Default")
layout = [
[Column(
layout=[
[Text('Receiver LO')],
[Text('Transmitter Fc')]
]
)]
[Canvas(key='controls_cv')],
[Column(
layout=[
[Canvas(key='fig_cv', size=(400*2, 400))]
],
background_color='#DAE0E6',
pad=(0,0)
)],
[Button("Correct", size=(10,1)), Button("Exit", size=(10,1))],
]
window = Window("CaribouLite PlayGround", layout, location=(800,400))
return window
while file_ctr < nfiles:
print(file_ctr, '. READING ', N, ' samples from CaribouLite')
# Read the samples from the data buffer
sr = sdr.readStream(rx_stream, [rx_buff], N, timeoutUs=timeout_us)
# Make sure that the proper number of samples was read
rc = sr.ret
assert rc == N, 'Error Reading Samples from Device (error code = %d)!' % rc
def estimate_correct(rx_buff):
s_real = rx_buff[::2].astype(np.float32)
s_imag = rx_buff[1::2].astype(np.float32)
@ -59,22 +67,98 @@ while file_ctr < nfiles:
sin_phi_est = (2/alpha_est)*np.mean(I*Q)
cos_phi_est = np.sqrt(1-sin_phi_est**2)
print('phase error: ', np.arccos(cos_phi_est)*360/3.1415, ' degrees')
print('amplitude error: ', 20*np.log10(alpha_est), ' dB' )
I_new_p = (1/alpha_est) * I
Q_new_p = (-sin_phi_est/alpha_est) * I + Q
y = (I_new_p + 1j*Q_new_p) / cos_phi_est
print('phase error: ', np.arccos(cos_phi_est)*360/3.1415, ' degrees')
print('amplitude error: ', 20*np.log10(alpha_est), ' dB' )
return (s_real, s_imag, alpha_est, sin_phi_est, cos_phi_est, I_new_p, Q_new_p)
# plt.plot(s_real, s_imag, 'k', label='I')
plt.scatter(I_new_p, Q_new_p)
plt.ylabel('I / Q Balance')
plt.show()
def main():
# Data and Source Configuration
tx_chan = 0 # S1G = 0, 6G = 1
rx_chan = 1 # S1G = 0, 6G = 1
N = 16384 # Nu5mber of complex samples per transfer
fs = 4e6 # Radio sample Rate
freq = 868e6 # LO tuning frequency in Hz
use_agc = True # Use or don't use the AGC
gain = 60
n_reads = 0
file_ctr += 1
if file_ctr > nfiles:
break
rx_buff = np.empty(2 * N, np.int16) # Create memory buffer for data stream
timeout_us = int(5e6)
# Stop streaming and close the connection to the radio
sdr.deactivateStream(rx_stream)
sdr.closeStream(rx_stream)
# Initialize CaribouLite
sdr = SoapySDR.Device(dict(driver="Cariboulite")) # Create Cariboulite
# The wide channel parameters
sdr.setSampleRate(SOAPY_SDR_RX, rx_chan, fs) # Set sample rate
sdr.setGainMode(SOAPY_SDR_RX, rx_chan, use_agc) # Set the gain mode
sdr.setGain(SOAPY_SDR_RX, rx_chan, gain) # Set the gain
sdr.setFrequency(SOAPY_SDR_RX, rx_chan, freq) # Tune the LO
sdr.setBandwidth(SOAPY_SDR_RX, rx_chan, 2.5e6)
# The S1G channel parameter
sdr.setFrequency(SOAPY_SDR_TX, tx_chan, 868.5e6)
sdr.setGain(SOAPY_SDR_TX, tx_chan, 50)
cw_tx_stream = sdr.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CS16, [tx_chan], dict(CW="1"))
sdr.activateStream(cw_tx_stream)
# Create data buffer and start streaming samples to it
rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16,
[rx_chan]) # Setup data stream
sdr.activateStream(rx_stream) # this turns the radio on
# create the window
window = create_window()
while True:
event, values = window.read(timeout = 20)
if (event == "Exit" or event == WIN_CLOSED):
break;
if (event == "Correct"):
n_reads += 1
sr = sdr.readStream(rx_stream, [rx_buff], N, timeoutUs=timeout_us)
# Make sure that the proper number of samples was read
rc = sr.ret
if (rc != N):
print("Error Reading Samples from Device (error code = %d)!" % rc)
break;
I,Q, alpha_est, sin_phi_est, cos_phi_est, I_new, Q_new = estimate_correct(rx_buff)
plt.figure(1).clf()
fig = plt.gcf()
DPI = fig.get_dpi()
fig.set_size_inches(404*2/float(DPI), 404/float(DPI))
plt.subplot(121)
plt.scatter(I, Q)
plt.title('I/Q original')
plt.subplot(122)
plt.scatter(I_new, Q_new)
plt.title('I/Q corrected')
plt.grid()
draw_figure_with_toolbar(window['fig_cv'].TKCanvas, fig, window['controls_cv'].TKCanvas)
# Stop streaming and close the connection to the radio
window.close()
sdr.deactivateStream(rx_stream)
sdr.deactivateStream(cw_tx_stream)
sdr.closeStream(rx_stream)
###########################################################
## Global Area
# Enumerate the Soapy devices
#res = SoapySDR.Device.enumerate()
#for result in res:
# print(result)
main()

Wyświetl plik

@ -80,6 +80,7 @@ extern "C" {
{ \
.cs_pin = CARIBOULITE_MIXER_SS, \
.reset_pin = CARIBOULITE_MIXER_RESET, \
.ref_freq_hz = 32e6, \
.initialized = 0, \
}, \
.reset_fpga_on_startup = 1, \

Wyświetl plik

@ -114,7 +114,7 @@ int cariboulite_dispose_radios(cariboulite_radios_st* radios)
caribou_smi_destroy_stream(&radios->radio_6g.cariboulite_sys->smi, radios->radio_sub1g.tx_stream_id);
radios->radio_6g.tx_stream_id = -1;
}
sleep(1);
usleep(100000);
cariboulite_radio_state_st* rad_s1g = GET_RADIO_PTR(radios,cariboulite_channel_s1g);
cariboulite_radio_state_st* rad_6g = GET_RADIO_PTR(radios,cariboulite_channel_6g);
@ -774,7 +774,7 @@ int cariboulite_activate_channel(cariboulite_radios_st* radios,
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
ZF_LOGD("Activating channel %d", channel);
ZF_LOGD("Activating channel %d, dir = %s, active = %d", channel, rad->channel_direction==cariboulite_channel_dir_rx?"RX":"TX", active);
// if the channel state is active, turn it off before reactivating
if (rad->state != at86rf215_radio_state_cmd_tx_prep)
{
@ -855,6 +855,15 @@ int cariboulite_set_cw_outputs(cariboulite_radios_st* radios,
}
rad->cw_output = cw_out;
if (cw_out)
{
rad->channel_direction = cariboulite_channel_dir_tx;
}
else
{
rad->channel_direction = cariboulite_channel_dir_rx;
}
return 0;
}

Wyświetl plik

@ -160,8 +160,8 @@ int cariboulite_init_submodules (cariboulite_st* sys)
// Configure modem
//------------------------------------------------------
ZF_LOGD("Configuring modem initial state");
at86rf215_set_clock_output(&sys->modem, at86rf215_drive_current_8ma, at86rf215_clock_out_freq_32mhz);
at86rf215_setup_rf_irq(&sys->modem, 0, 1, at86rf215_drive_current_4ma);
at86rf215_set_clock_output(&sys->modem, at86rf215_drive_current_2ma, at86rf215_clock_out_freq_32mhz);
at86rf215_setup_rf_irq(&sys->modem, 0, 1, at86rf215_drive_current_2ma);
at86rf215_radio_set_state(&sys->modem, at86rf215_rf_channel_900mhz, at86rf215_radio_state_cmd_trx_off);
at86rf215_radio_set_state(&sys->modem, at86rf215_rf_channel_2400mhz, at86rf215_radio_state_cmd_trx_off);
@ -211,6 +211,7 @@ int cariboulite_init_submodules (cariboulite_st* sys)
// Configure mixer
//------------------------------------------------------
rffc507x_setup_reference_freq(&sys->mixer, 32e6);
rffc507x_calibrate(&sys->mixer);
ZF_LOGI("Cariboulite submodules successfully initialized");
@ -295,7 +296,7 @@ int cariboulite_release_submodules(cariboulite_st* sys)
//------------------------------------------------------
ZF_LOGD("CLOSE SMI");
caribou_smi_close(&sys->smi);
sleep(1);
usleep(10000);
// AT86RF215
//------------------------------------------------------

Wyświetl plik

@ -24,6 +24,7 @@ static char *io_utils_gpio_mode_strs[] = {"IN","OUT","ALT5","ALT4","ALT0","ALT1"
int io_utils_setup(pigpioSigHandler sigHandler)
{
ZF_LOGI("initializing pigpio");
gpioCfgInterfaces(PI_DISABLE_FIFO_IF|PI_DISABLE_SOCK_IF|PI_LOCALHOST_SOCK_IF);
int status = gpioInitialise();
if (status < 0)
{

Wyświetl plik

@ -43,8 +43,6 @@
#define LO_MAX 5400
#define LO_MAX_HZ (LO_MAX*1e6)
#define REF_FREQ 32
#define REF_FREQ_HZ (REF_FREQ*1e6)
#define FREQ_ONE_MHZ (1000*1000)
//===========================================================================
@ -151,8 +149,8 @@ int rffc507x_init( rffc507x_st* dev,
set_RFFC507X_P2CTV(dev, 12);
set_RFFC507X_P1CTV(dev, 12);
set_RFFC507X_RGBYP(dev, 1);
set_RFFC507X_P2MIXIDD(dev, 6);
set_RFFC507X_P1MIXIDD(dev, 6);
set_RFFC507X_P2MIXIDD(dev, 5);
set_RFFC507X_P1MIXIDD(dev, 5);
// Others
set_RFFC507X_LDEN(dev, 1);
@ -253,9 +251,10 @@ void rffc507x_enable(rffc507x_st* dev)
}
//===========================================================================
void rffc507x_calculate_freq_params(uint8_t lodiv, double fvco, uint8_t fbkdiv, uint16_t *n, uint16_t *p1nmsb, uint8_t *p1nlsb, double* act_freq_hz)
void rffc507x_calculate_freq_params(double ref_freq_hz, uint8_t lodiv, double fvco, uint8_t fbkdiv,
uint16_t *n, uint16_t *p1nmsb, uint8_t *p1nlsb, double* act_freq_hz)
{
double n_div = fvco / fbkdiv / REF_FREQ_HZ;
double n_div = fvco / fbkdiv / ref_freq_hz;
*n = (uint16_t)(n_div);
double temp_p1nmsb = ( (double)(1<<16) ) * ( n_div - (double)(*n) );
@ -266,7 +265,18 @@ void rffc507x_calculate_freq_params(uint8_t lodiv, double fvco, uint8_t fbkdiv,
uint32_t n_div24_bit = (uint32_t)(round(n_div * (1<<24))) & 0xFFFFFFFF;
//uint32_t n_div24_bit = (uint32_t)((n_div * (1<<24))) & 0xFFFFFFFF;
if (act_freq_hz) *act_freq_hz = (REF_FREQ_HZ * n_div24_bit * fbkdiv) / ((double)(lodiv) * (double)(1<<24));
if (act_freq_hz) *act_freq_hz = (ref_freq_hz * n_div24_bit * fbkdiv) / ((double)(lodiv) * (double)(1<<24));
}
//===========================================================================
int rffc507x_setup_reference_freq(rffc507x_st* dev, double ref_freq_hz)
{
if (ref_freq_hz < 10e6 || ref_freq_hz > 104e6)
{
return -1;
}
dev->ref_freq_hz = ref_freq_hz;
return 0;
}
//===========================================================================
@ -298,7 +308,7 @@ double rffc507x_set_frequency(rffc507x_st* dev, double lo_hz)
set_RFFC507X_PLLCPL(dev, 2);
}
rffc507x_calculate_freq_params(lodiv, fvco, fbkdiv, &n, &p1nmsb, &p1nlsb, &tune_freq_hz);
rffc507x_calculate_freq_params(dev->ref_freq_hz, lodiv, fvco, fbkdiv, &n, &p1nmsb, &p1nlsb, &tune_freq_hz);
//ZF_LOGD("----------------------------------------------------------");
//ZF_LOGD("LO_HZ=%.2f n_lo=%d lodiv=%d", lo_hz, n_lo, lodiv);
@ -323,7 +333,7 @@ double rffc507x_set_frequency(rffc507x_st* dev, double lo_hz)
// After the device is enabled, the divider values can be reprogrammed with the prescaler divider ratio of 2
// and the new n, nummsb, and numlsb values. Taking the previous example of an LO of 314.159265MHz:
fbkdiv = 2;
rffc507x_calculate_freq_params(lodiv, fvco, fbkdiv, &n, &p1nmsb, &p1nlsb, &tune_freq_hz);
rffc507x_calculate_freq_params(dev->ref_freq_hz, lodiv, fvco, fbkdiv, &n, &p1nmsb, &p1nlsb, &tune_freq_hz);
//ZF_LOGD("LO_HZ=%.2f n_lo=%d lodiv=%d", lo_hz, n_lo, lodiv);
//ZF_LOGD("fvco=%.2f fbkdiv=%d n=%d", fvco, fbkdiv, n);

Wyświetl plik

@ -61,6 +61,7 @@ typedef struct
{
int cs_pin;
int reset_pin;
double ref_freq_hz;
io_utils_spi_st* io_spi;
int io_spi_handle;
@ -104,6 +105,7 @@ void rffc507x_print_stat(rffc507x_device_status_st* stat);
void rffc507x_calibrate(rffc507x_st* dev);
void rffc507x_relock(rffc507x_st* dev);
void rffc507x_output_lo(rffc507x_st* dev, int state);
int rffc507x_setup_reference_freq(rffc507x_st* dev, double ref_freq_hz);
#ifdef __cplusplus
}

Wyświetl plik

@ -23,6 +23,7 @@ rffc507x_st dev =
{
.cs_pin = CARIBOULITE_MXR_SS,
.reset_pin = CARIBOULITE_MXR_RESET,
.ref_freq_hz = 32e6,
};
int main ()

Wyświetl plik

@ -109,6 +109,7 @@ public:
int stream_id;
int stream_dir;
int stream_channel;
int is_cw;
Cariboulite_Format chosen_format;
private:
tsqueue_st queue;

Wyświetl plik

@ -40,7 +40,7 @@ SampleQueue::SampleQueue(int mtu_bytes, int num_buffers)
// a buffer for conversion betwen native and emulated formats
// the maximal size is the 2*(mtu_size in bytes)
interm_native_buffer = new sample_complex_int16[2*mtu_size_bytes];
is_cw = 0;
}
//=================================================================

Wyświetl plik

@ -184,12 +184,11 @@ SoapySDR::Stream *Cariboulite::setupStream(const int direction,
const std::vector<size_t> &channels,
const SoapySDR::Kwargs &args)
{
SoapySDR_logf(SOAPY_SDR_INFO, "setupStream: dir: %d, format: %s, channels: ", direction, format.c_str());
for (int i = 0; i < (int)channels.size(); i++)
{
SoapySDR_logf(SOAPY_SDR_INFO, "setupStream: %d. %ld", i, channels[i]);
}
int cw = (args.count("CW") != 0) ? std::atoi(args.at("CW").c_str()) : 0;
SoapySDR_logf(SOAPY_SDR_INFO, "setupStream: dir= %s, format= %s, is_cw= %d, ch= %d",
direction == SOAPY_SDR_TX?"TX":"RX", format.c_str(), cw,
channels.size()?channels[0]:0);
std::vector<size_t> channels_internal = channels;
// default channel - sub1GHz
if ( channels_internal.size() == 0 )
@ -204,6 +203,7 @@ SoapySDR::Stream *Cariboulite::setupStream(const int direction,
caribou_smi_stream_type_en type = (direction == SOAPY_SDR_RX) ? caribou_smi_stream_type_read : caribou_smi_stream_type_write;
caribou_smi_channel_en channel = (ch == cariboulite_channel_s1g) ? caribou_smi_channel_900 : caribou_smi_channel_2400;
int stream_id = CARIBOU_SMI_GET_STREAM_ID(type, channel);
sample_queues[stream_id]->is_cw = cw;
// Setup the SampleQueue's format
if (format == SOAPY_SDR_CS16)
@ -228,18 +228,26 @@ SoapySDR::Stream *Cariboulite::setupStream(const int direction,
throw std::runtime_error( "setupStream invalid format " + format );
}
// create the stream
stream_id = caribou_smi_setup_stream(&sess.cariboulite_sys.smi,
type, channel,
GET_MTU_MS_BYTES(BUFFER_SIZE_MS), 1,
caribou_stream_data_event,
this);
if (stream_id < 0)
// create the stream (only for non CW streams)
if (sample_queues[stream_id]->is_cw)
{
throw std::runtime_error( "setupStream caribou_smi_setup_stream failed" );
cariboulite_set_cw_outputs(&radios, (cariboulite_channel_en)ch, false, true);
}
else
{
cariboulite_set_cw_outputs(&radios, (cariboulite_channel_en)ch, false, false);
stream_id = caribou_smi_setup_stream(&sess.cariboulite_sys.smi,
type, channel,
GET_MTU_MS_BYTES(BUFFER_SIZE_MS), 1,
caribou_stream_data_event,
this);
if (stream_id < 0)
{
throw std::runtime_error( "setupStream caribou_smi_setup_stream failed" );
}
}
SoapySDR_logf(SOAPY_SDR_INFO, "finished setup stream, stream_id = %d", stream_id);
SoapySDR_logf(SOAPY_SDR_INFO, "finished setup stream, stream_id = %d, CW=%d", stream_id, cw);
return (SoapySDR::Stream *)((void*)stream_id);
}
@ -305,7 +313,10 @@ int Cariboulite::activateStream(SoapySDR::Stream *stream,
(cariboulite_channel_en)sample_queues[stream_id]->stream_channel,
true);
caribou_smi_run_pause_stream (&sess.cariboulite_sys.smi, (intptr_t)stream, 1);
if ((cariboulite_channel_en)sample_queues[stream_id]->is_cw == 0)
{
caribou_smi_run_pause_stream (&sess.cariboulite_sys.smi, (intptr_t)stream, 1);
}
return 0;
}
@ -329,8 +340,11 @@ int Cariboulite::deactivateStream(SoapySDR::Stream *stream, const int flags, con
SoapySDR_logf(SOAPY_SDR_INFO, "deactivateStream");
int stream_id = (intptr_t)stream;
caribou_smi_run_pause_stream (&sess.cariboulite_sys.smi, (intptr_t)stream, 0);
sleep(1);
if ((cariboulite_channel_en)sample_queues[stream_id]->is_cw == 0)
{
caribou_smi_run_pause_stream (&sess.cariboulite_sys.smi, (intptr_t)stream, 0);
sleep(1);
}
cariboulite_activate_channel(&radios,
(cariboulite_channel_en)sample_queues[stream_id]->stream_channel,