kopia lustrzana https://github.com/cariboulabs/cariboulite
Merge branch 'main' of https://github.com/cariboulabs/cariboulite
commit
e9fd5e36cf
|
@ -0,0 +1,69 @@
|
|||
from PySimpleGUI.PySimpleGUI import Canvas, Column
|
||||
import time
|
||||
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_TX, SOAPY_SDR_CS16
|
||||
from PySimpleGUI import Window, WIN_CLOSED, Slider, Button, theme, Text, Radio, Image, InputText, Canvas
|
||||
from numpy.lib.arraypad import pad
|
||||
|
||||
|
||||
def setup_receiver(sdr, channel, freq_hz):
|
||||
use_agc = False # Use or don't use the AGC
|
||||
# The wide channel parameters
|
||||
sdr.setGainMode(SOAPY_SDR_RX, channel, use_agc) # Set the gain mode
|
||||
sdr.setGain(SOAPY_SDR_RX, channel, 50) # Set the gain
|
||||
sdr.setFrequency(SOAPY_SDR_RX, channel, freq_hz) # Tune the LO
|
||||
sdr.setBandwidth(SOAPY_SDR_RX, channel, 2.5e6)
|
||||
rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [channel]) # Setup data stream
|
||||
return rx_stream
|
||||
|
||||
def update_receiver_freq(sdr, stream, channel, freq_hz):
|
||||
sdr.setFrequency(SOAPY_SDR_RX, channel, freq_hz)
|
||||
|
||||
|
||||
# Data and Source Configuration
|
||||
rx_chan = 1 # 6G = 1
|
||||
N = 16384 # Number of complex samples per transfer
|
||||
rx_buff = np.empty(2 * N, np.int16) # Create memory buffer for data stream
|
||||
freq = 915.6e6
|
||||
|
||||
# Initialize CaribouLite Soapy
|
||||
sdr = SoapySDR.Device(dict(driver="Cariboulite")) # Create Cariboulite
|
||||
rx_stream = setup_receiver(sdr, rx_chan, freq)
|
||||
sdr.activateStream(rx_stream)
|
||||
|
||||
sr = sdr.readStream(rx_stream, [rx_buff], N, timeoutUs=int(5e6))
|
||||
# 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)
|
||||
exit
|
||||
|
||||
s_real = rx_buff[::2].astype(np.float32)
|
||||
s_imag = -rx_buff[1::2].astype(np.float32)
|
||||
x = s_real + 1j*s_imag
|
||||
|
||||
## PSD
|
||||
Fs = 4e6
|
||||
#N = 2048
|
||||
#x = x[0:N] # we will only take the FFT of the first 1024 samples, see text below
|
||||
x = x * np.hamming(len(x)) # apply a Hamming window
|
||||
|
||||
PSD = (np.abs(np.fft.fft(x))/N)**2
|
||||
PSD_log = 10.0*np.log10(PSD)
|
||||
PSD_shifted = np.fft.fftshift(PSD_log)
|
||||
|
||||
center_freq = freq
|
||||
f = np.arange(Fs/-2.0, Fs/2.0, Fs/N) # start, stop, step. centered around 0 Hz
|
||||
f += center_freq # now add center frequency
|
||||
|
||||
fig = plt.figure()
|
||||
plt.plot(f, PSD_shifted)
|
||||
plt.show()
|
||||
|
||||
fig = plt.figure()
|
||||
plt.plot(s_real)
|
||||
plt.plot(s_imag)
|
||||
plt.show()
|
|
@ -1,12 +1,15 @@
|
|||
from PySimpleGUI.PySimpleGUI import Canvas, Column
|
||||
import time
|
||||
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_TX, SOAPY_SDR_CS16
|
||||
from PySimpleGUI import Window, WIN_CLOSED, Slider, Button, theme, Text, Radio, Image
|
||||
from PySimpleGUI import Window, WIN_CLOSED, Slider, Button, theme, Text, Radio, Image, InputText, Canvas
|
||||
from numpy.lib.arraypad import pad
|
||||
|
||||
##
|
||||
## WINDOW FUNCTIONS
|
||||
def draw_figure_with_toolbar(canvas, fig, canvas_toolbar):
|
||||
if canvas.children:
|
||||
for child in canvas.winfo_children():
|
||||
|
@ -33,124 +36,268 @@ def create_window():
|
|||
layout = [
|
||||
[Column(
|
||||
layout=[
|
||||
[Text('Receiver LO')],
|
||||
[Text('Transmitter Fc')]
|
||||
[Text('Receiver LO [Hz]:'), InputText('868000000', key='RxFreq'), Text('RX Bandwidth: 2.5 MHz')],
|
||||
[Text('Transmitter Fc [Hz]:'), Text(key='TxCWFreq')],
|
||||
]
|
||||
)]
|
||||
)],
|
||||
[Canvas(key='controls_cv')],
|
||||
[Column(
|
||||
layout=[
|
||||
[Canvas(key='fig_cv', size=(400*2, 400))]
|
||||
[Canvas(key='fig_cv', size=(300*3, 300))]
|
||||
],
|
||||
background_color='#DAE0E6',
|
||||
pad=(0,0)
|
||||
)],
|
||||
[Button("Correct", size=(10,1)), Button("Exit", size=(10,1))],
|
||||
[Text('RSSI:', key='rssi'), Text('Alpha:', key='alpha'), Text('Cos(Phi):', key='cos_phi')],
|
||||
[Canvas(key='controls_params_cv')],
|
||||
[Column(
|
||||
layout=[
|
||||
[Canvas(key='params_cv', size=(200*4, 200))]
|
||||
],
|
||||
background_color='#DAE0E6',
|
||||
pad=(0,0)
|
||||
)],
|
||||
[Button("Correct", size=(10,1)), Button("Exit", size=(10,1)), Button("Run", size=(10,1))],
|
||||
]
|
||||
window = Window("CaribouLite PlayGround", layout, location=(800,400))
|
||||
return window
|
||||
|
||||
def calculate_psd(I,Q, fs):
|
||||
x = I + 1j*Q
|
||||
N = 16384 # len(I)
|
||||
x = x * np.hamming(len(x)) # apply a Hamming window
|
||||
PSD = (np.abs(np.fft.fft(x))/N)**2
|
||||
PSD_log = 10.0*np.log10(PSD)
|
||||
PSD_shifted = np.fft.fftshift(PSD_log)
|
||||
f = np.arange(fs/-2.0, fs/2.0, fs/N) # start, stop, step. centered around 0 Hz
|
||||
return f,PSD_shifted
|
||||
|
||||
def estimate_correct(rx_buff):
|
||||
s_real = rx_buff[::2].astype(np.float32)
|
||||
s_imag = rx_buff[1::2].astype(np.float32)
|
||||
def update_iq_graphs(window, I,Q,I_new, Q_new):
|
||||
plt.figure(1).clf()
|
||||
fig = plt.gcf()
|
||||
DPI = fig.get_dpi()
|
||||
fig.set_size_inches(304*4/float(DPI), 304/float(DPI))
|
||||
axs = fig.add_subplot(131)
|
||||
plt.scatter(I, Q)
|
||||
axs.set_aspect('equal', adjustable='box')
|
||||
plt.title('I/Q original')
|
||||
|
||||
c = s_real + 1j * s_imag
|
||||
c_no_bias = c - c.mean()
|
||||
axs = fig.add_subplot(132)
|
||||
plt.scatter(I_new, Q_new)
|
||||
axs.set_aspect('equal', adjustable='box')
|
||||
plt.title('I/Q corrected')
|
||||
|
||||
# scale Q to have unit amplitude
|
||||
Q_amp = np.sqrt(2*np.mean(s_imag**2))
|
||||
c /= Q_amp
|
||||
I, Q = c.real, c.imag
|
||||
f, psd = calculate_psd(I,Q, 4e6)
|
||||
f_corrected, psd_corrected = calculate_psd(I_new,Q_new, 4e6)
|
||||
|
||||
plt.subplot(133)
|
||||
plt.plot(f, psd)
|
||||
plt.plot(f_corrected, psd_corrected)
|
||||
|
||||
plt.grid()
|
||||
draw_figure_with_toolbar(window['fig_cv'].TKCanvas, fig, window['controls_cv'].TKCanvas)
|
||||
|
||||
def update_est_graphs(window, freq_diff, g_vec, phi_vec, rssi_vec):
|
||||
plt.figure(2).clf()
|
||||
fig = plt.gcf()
|
||||
DPI = fig.get_dpi()
|
||||
fig.set_size_inches(204*3/float(DPI), 204/float(DPI))
|
||||
plt.subplot(131)
|
||||
plt.plot(freq_diff, g_vec)
|
||||
plt.title('G')
|
||||
plt.subplot(132)
|
||||
plt.plot(freq_diff, phi_vec)
|
||||
plt.title('phi')
|
||||
plt.subplot(133)
|
||||
plt.plot(freq_diff, rssi_vec)
|
||||
plt.title('Relative Power')
|
||||
plt.grid()
|
||||
draw_figure_with_toolbar(window['params_cv'].TKCanvas, fig, window['controls_params_cv'].TKCanvas)
|
||||
|
||||
##
|
||||
## I/Q Correction Functions
|
||||
def fix_iq_blind(x):
|
||||
z = x - np.mean(x)
|
||||
p_in = np.var(z)
|
||||
|
||||
theta1 = (-1) * np.mean(np.sign(z.real) * z.imag)
|
||||
theta2 = np.mean(np.abs(z.real))
|
||||
theta3 = np.mean(np.abs(z.imag))
|
||||
c1 = theta1/theta2
|
||||
c2 = np.sqrt( ( (theta3**2 - theta1**2) / theta2**2 ) )
|
||||
|
||||
g = theta3/theta2
|
||||
phi = np.arcsin(theta1/theta3)
|
||||
wI = c2 * z.real
|
||||
wQ = c1 * z.real + z.imag
|
||||
z_out = wI + 1j * wQ
|
||||
|
||||
return (z_out, g, phi, p_in, c1, c2)
|
||||
|
||||
|
||||
def fix_iq_imbalance(x):
|
||||
# remove DC and save input power
|
||||
z = x - np.mean(x)
|
||||
p_in = np.var(z)
|
||||
|
||||
# scale Q to have unit amplitude (remember we're assuming a single input tone)
|
||||
Q_amp = np.sqrt(2*np.mean(z.imag**2)) # <== should be z.imag**2????
|
||||
z /= Q_amp
|
||||
|
||||
I, Q = z.real, z.imag
|
||||
|
||||
alpha_est = np.sqrt(2*np.mean(I**2))
|
||||
sin_phi_est = (2/alpha_est)*np.mean(I*Q)
|
||||
cos_phi_est = np.sqrt(1-sin_phi_est**2)
|
||||
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
|
||||
|
||||
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
|
||||
y = (I_new_p + 1j*Q_new_p)/cos_phi_est
|
||||
|
||||
return (s_real, s_imag, alpha_est, sin_phi_est, cos_phi_est, I_new_p, Q_new_p)
|
||||
print ('phase error:', np.arccos(cos_phi_est)*180/np.pi, 'degrees')
|
||||
print ('amplitude error:', 20*np.log10(alpha_est), 'dB')
|
||||
z_out = y*np.sqrt(p_in/np.var(y))
|
||||
return (z_out, alpha_est, np.arccos(cos_phi_est), p_in, sin_phi_est, cos_phi_est)
|
||||
|
||||
|
||||
##
|
||||
## Soapy Control functions
|
||||
|
||||
def setup_receiver(sdr, channel, freq_hz):
|
||||
use_agc = False # Use or don't use the AGC
|
||||
# The wide channel parameters
|
||||
sdr.setGainMode(SOAPY_SDR_RX, channel, use_agc) # Set the gain mode
|
||||
sdr.setGain(SOAPY_SDR_RX, channel, 70) # Set the gain
|
||||
sdr.setFrequency(SOAPY_SDR_RX, channel, freq_hz) # Tune the LO
|
||||
sdr.setBandwidth(SOAPY_SDR_RX, channel, 1.6e6)
|
||||
rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [channel]) # Setup data stream
|
||||
return rx_stream
|
||||
|
||||
def update_receiver_freq(sdr, stream, channel, freq_hz):
|
||||
sdr.setFrequency(SOAPY_SDR_RX, channel, freq_hz)
|
||||
|
||||
def setup_transmitter(sdr, channel, freq_hz):
|
||||
sdr.setFrequency(SOAPY_SDR_TX, channel, 867.5e6)
|
||||
sdr.setGain(SOAPY_SDR_TX, channel, 60)
|
||||
tx_stream = sdr.setupStream(SOAPY_SDR_TX, SOAPY_SDR_CS16, [channel], dict(CW="1"))
|
||||
return tx_stream
|
||||
|
||||
def update_transmitter_freq(sdr, stream, channel, freq_hz):
|
||||
sdr.deactivateStream(stream)
|
||||
sdr.setFrequency(SOAPY_SDR_TX, channel, freq_hz)
|
||||
sdr.activateStream(stream)
|
||||
|
||||
|
||||
##
|
||||
## MAIN
|
||||
|
||||
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
|
||||
|
||||
tx_chan = 0 # S1G = 0
|
||||
rx_chan = 1 # 6G = 1
|
||||
N = 16384 # Number of complex samples per transfer
|
||||
rx_buff = np.empty(2 * N, np.int16) # Create memory buffer for data stream
|
||||
timeout_us = int(5e6)
|
||||
|
||||
# Initialize CaribouLite
|
||||
# Initialize CaribouLite Soapy
|
||||
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
|
||||
rx_stream = setup_receiver(sdr, rx_chan, 868e6)
|
||||
tx_stream = setup_transmitter(sdr, tx_chan, 868.5e6)
|
||||
sdr.activateStream(tx_stream)
|
||||
sdr.activateStream(rx_stream)
|
||||
|
||||
# create the window
|
||||
window = create_window()
|
||||
|
||||
while True:
|
||||
event, values = window.read(timeout = 20)
|
||||
|
||||
if (event == "Exit" or event == WIN_CLOSED):
|
||||
break;
|
||||
elif event == "Correct":
|
||||
print("clicked correct")
|
||||
|
||||
if (event == "Correct"):
|
||||
n_reads += 1
|
||||
sr = sdr.readStream(rx_stream, [rx_buff], N, timeoutUs=timeout_us)
|
||||
freq = float(values['RxFreq'])
|
||||
tx_freq = freq + 0.5e6
|
||||
print("setting frequency ", freq)
|
||||
window['TxCWFreq'].update(tx_freq)
|
||||
|
||||
update_transmitter_freq(sdr, tx_stream, tx_chan, tx_freq)
|
||||
update_receiver_freq(sdr, rx_stream, rx_chan, freq)
|
||||
time.sleep(0.5)
|
||||
|
||||
sr = sdr.readStream(rx_stream, [rx_buff], N, timeoutUs=int(5e6))
|
||||
# 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)
|
||||
s_real = rx_buff[::2].astype(np.float32)
|
||||
s_imag = rx_buff[1::2].astype(np.float32)
|
||||
z = s_real + 1j*s_imag
|
||||
(z_out, g, phi, p_in,a,b) = fix_iq_imbalance(z)
|
||||
#(z_out, g, phi, p_in,a,b) = fix_iq_blind(z)
|
||||
rssi = 20*np.log10(p_in)
|
||||
phi *= 180/np.pi
|
||||
|
||||
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)
|
||||
window['rssi'].update('RSSI: %f dBm' % rssi)
|
||||
window['alpha'].update('Alpha: %f' % g)
|
||||
window['cos_phi'].update('Phi: %f' % phi)
|
||||
|
||||
update_iq_graphs(window, s_real, s_imag, z_out.real, z_out.imag)
|
||||
|
||||
elif event == "Run":
|
||||
print("clicked run")
|
||||
bw = 2.5e6
|
||||
rx_freq = float(values['RxFreq'])
|
||||
update_receiver_freq(sdr, rx_stream, rx_chan, rx_freq)
|
||||
|
||||
freq_num = 60
|
||||
tx_freq_vec = rx_freq + np.linspace(-bw/2, bw/2, freq_num)
|
||||
g_est_vec = np.empty(tx_freq_vec.size, np.float32)
|
||||
phi_vec = np.empty(tx_freq_vec.size, np.float32)
|
||||
rssi_vec = np.empty(tx_freq_vec.size, np.float32)
|
||||
|
||||
index = 0
|
||||
for tx_freq in tx_freq_vec:
|
||||
window['TxCWFreq'].update(tx_freq)
|
||||
update_transmitter_freq(sdr, tx_stream, tx_chan, tx_freq)
|
||||
time.sleep(1)
|
||||
|
||||
sr = sdr.readStream(rx_stream, [rx_buff], N, timeoutUs=int(5e6))
|
||||
# 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;
|
||||
|
||||
s_real = rx_buff[::2].astype(np.float32)
|
||||
s_imag = rx_buff[1::2].astype(np.float32)
|
||||
z = s_real + 1j*s_imag
|
||||
(z_out, g, phi, p_in, a,b) = fix_iq_imbalance(z)
|
||||
#(z_out, g, phi, p_in, a,b) = fix_iq_blind(z)
|
||||
|
||||
g_est_vec[index] = 20*np.log10(g)
|
||||
phi_vec[index] = phi*180/np.pi
|
||||
rssi_vec[index] = 20*np.log10(p_in)
|
||||
|
||||
window['rssi'].update('RSSI: %f dBm' % rssi_vec[index])
|
||||
window['alpha'].update('Alpha: %f' % g_est_vec[index])
|
||||
window['cos_phi'].update('Phi: %f' % phi_vec[index])
|
||||
|
||||
update_iq_graphs(window, s_real, s_imag, z_out.real, z_out.imag)
|
||||
index += 1
|
||||
time.sleep(0.1)
|
||||
|
||||
update_est_graphs(window, tx_freq_vec-rx_freq, g_est_vec, phi_vec, rssi_vec - np.max(rssi_vec))
|
||||
|
||||
|
||||
# Stop streaming and close the connection to the radio
|
||||
window.close()
|
||||
sdr.deactivateStream(rx_stream)
|
||||
sdr.deactivateStream(cw_tx_stream)
|
||||
sdr.deactivateStream(tx_stream)
|
||||
sdr.closeStream(rx_stream)
|
||||
sdr.closeStream(tx_stream)
|
||||
|
||||
|
||||
|
||||
|
@ -158,7 +305,9 @@ def main():
|
|||
## Global Area
|
||||
|
||||
# Enumerate the Soapy devices
|
||||
#res = SoapySDR.Device.enumerate()
|
||||
#for result in res:
|
||||
# print(result)
|
||||
res = SoapySDR.Device.enumerate()
|
||||
for result in res:
|
||||
print(result)
|
||||
|
||||
# run the program
|
||||
main()
|
||||
|
|
Plik diff jest za duży
Load Diff
Plik diff jest za duży
Load Diff
|
@ -301,8 +301,7 @@ module top(
|
|||
|
||||
// test reversed LSB / MSB
|
||||
// -----------------------
|
||||
.i_ddr_data ({w_lvds_rx_24_d1, w_lvds_rx_24_d0}), // tested and shown that this is the right way
|
||||
//.i_ddr_data ({w_lvds_rx_24_d0, w_lvds_rx_24_d1}),
|
||||
.i_ddr_data ({w_lvds_rx_24_d1, w_lvds_rx_24_d0}),
|
||||
|
||||
.i_fifo_full (w_rx_24_fifo_full),
|
||||
.o_fifo_write_clk (w_rx_24_fifo_write_clk),
|
||||
|
|
|
@ -76,6 +76,61 @@ int at86rf215_read_byte(at86rf215_st* dev, uint16_t addr)
|
|||
return chunk_rx[2];
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
#define NUM_CAL_STEPS 7
|
||||
void swap(int *p,int *q)
|
||||
{
|
||||
int t;
|
||||
t=*p;
|
||||
*p=*q;
|
||||
*q=t;
|
||||
}
|
||||
|
||||
void sort(int a[],int n)
|
||||
{
|
||||
int i,j,temp;
|
||||
|
||||
for(i = 0;i < n-1;i++) {
|
||||
for(j = 0;j < n-i-1;j++) {
|
||||
if(a[j] > a[j+1])
|
||||
swap(&a[j],&a[j+1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int median(int a[], int n)
|
||||
{
|
||||
if (n==0) return 0;
|
||||
sort(a,n);
|
||||
return a[(n+1)/2-1];
|
||||
}
|
||||
|
||||
int at86rf215_calibrate_device(at86rf215_st* dev, at86rf215_rf_channel_en ch, int* i, int* q)
|
||||
{
|
||||
int cal_i[NUM_CAL_STEPS] = {0};
|
||||
int cal_q[NUM_CAL_STEPS] = {0};
|
||||
bool override_flag = dev->override_cal;
|
||||
dev->override_cal = false;
|
||||
|
||||
for (int i = 0; i < NUM_CAL_STEPS; i ++)
|
||||
{
|
||||
at86rf215_radio_set_state(dev, ch, at86rf215_radio_state_cmd_trx_off);
|
||||
at86rf215_radio_set_state(dev, ch, at86rf215_radio_state_cmd_tx_prep);
|
||||
|
||||
io_utils_usleep(10000);
|
||||
|
||||
at86rf215_radio_get_tx_iq_calibration(dev, ch, &cal_i[i], &cal_q[i]);
|
||||
ZF_LOGD("Calibration of modem: I=%d, Q=%d", cal_i[i], cal_q[i]);
|
||||
}
|
||||
|
||||
// medians
|
||||
int cal_i_med = median(cal_i, NUM_CAL_STEPS);
|
||||
int cal_q_med = median(cal_q, NUM_CAL_STEPS);
|
||||
ZF_LOGI("Calibration Results of the modem: I=%d, Q=%d", cal_i_med, cal_q_med);
|
||||
dev->override_cal = override_flag;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
int at86rf215_init(at86rf215_st* dev,
|
||||
io_utils_spi_st* io_spi)
|
||||
|
@ -115,6 +170,15 @@ int at86rf215_init(at86rf215_st* dev,
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Initialize events
|
||||
event_node_init(&dev->events.lo_trx_ready_event);
|
||||
event_node_init(&dev->events.lo_energy_measure_event);
|
||||
event_node_init(&dev->events.hi_trx_ready_event);
|
||||
event_node_init(&dev->events.hi_energy_measure_event);
|
||||
|
||||
// calibrate TXPREP
|
||||
at86rf215_calibrate_device(dev, at86rf215_rf_channel_900mhz, &dev->cal.low_ch_i, &dev->cal.low_ch_q);
|
||||
at86rf215_calibrate_device(dev, at86rf215_rf_channel_2400mhz, &dev->cal.hi_ch_i, &dev->cal.hi_ch_q);
|
||||
dev->initialized = 1;
|
||||
|
||||
return 0;
|
||||
|
@ -138,6 +202,11 @@ int at86rf215_close(at86rf215_st* dev)
|
|||
|
||||
dev->initialized = 0;
|
||||
|
||||
event_node_close(&dev->events.lo_trx_ready_event);
|
||||
event_node_close(&dev->events.lo_energy_measure_event);
|
||||
event_node_close(&dev->events.hi_trx_ready_event);
|
||||
event_node_close(&dev->events.hi_energy_measure_event);
|
||||
|
||||
//io_utils_setup_gpio(dev->reset_pin, io_utils_dir_input, io_utils_pull_up);
|
||||
io_utils_setup_gpio(dev->irq_pin, io_utils_dir_input, io_utils_pull_up);
|
||||
|
||||
|
@ -351,6 +420,23 @@ void at86rf215_setup_iq_if(at86rf215_st* dev, at86rf215_iq_interface_config_st*
|
|||
at86rf215_write_buffer(dev, REG_RF_IQIFC0, data, 2);
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
double at86rf215_check_freq (at86rf215_st* dev, at86rf215_rf_channel_en ch, uint64_t freq_hz )
|
||||
{
|
||||
at86rf215_radio_channel_mode_en mode = 0;
|
||||
at86rf215_rf_channel_en req_ch = 0;
|
||||
|
||||
if (at86rf215_radio_get_good_channel(freq_hz, &mode, &req_ch) < 0 || req_ch != ch)
|
||||
{
|
||||
ZF_LOGE("the requested channel or frequency not supported");
|
||||
return -1;
|
||||
}
|
||||
int center_freq_25khz_res = 0;
|
||||
int channel_number = 0;
|
||||
double actual_freq = at86rf215_radio_get_frequency(mode, 1, freq_hz, ¢er_freq_25khz_res, &channel_number);
|
||||
return actual_freq;
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
int64_t at86rf215_setup_channel ( at86rf215_st* dev, at86rf215_rf_channel_en ch, uint64_t freq_hz )
|
||||
{
|
||||
|
@ -370,7 +456,7 @@ int64_t at86rf215_setup_channel ( at86rf215_st* dev, at86rf215_rf_channel_en ch,
|
|||
}
|
||||
int center_freq_25khz_res = 0;
|
||||
int channel_number = 0;
|
||||
float actual_freq = at86rf215_radio_get_frequency(mode, 1, freq_hz, ¢er_freq_25khz_res, &channel_number);
|
||||
double actual_freq = at86rf215_radio_get_frequency(mode, 1, freq_hz, ¢er_freq_25khz_res, &channel_number);
|
||||
at86rf215_radio_setup_channel(dev, ch, 1, center_freq_25khz_res, channel_number, mode);
|
||||
return (int64_t)actual_freq;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ extern "C" {
|
|||
#include "at86rf215_common.h"
|
||||
#include "at86rf215_radio.h"
|
||||
|
||||
|
||||
int at86rf215_init(at86rf215_st* dev,
|
||||
io_utils_spi_st* io_spi);
|
||||
int at86rf215_close(at86rf215_st* dev);
|
||||
|
@ -35,6 +36,14 @@ void at86rf215_setup_iq_radio_dac_value_override_no_freq (at86rf215_st* dev,
|
|||
at86rf215_rf_channel_en ch,
|
||||
uint8_t tx_power);
|
||||
int64_t at86rf215_setup_channel ( at86rf215_st* dev, at86rf215_rf_channel_en ch, uint64_t freq_hz );
|
||||
double at86rf215_check_freq (at86rf215_st* dev, at86rf215_rf_channel_en ch, uint64_t freq_hz );
|
||||
|
||||
// EVENTS
|
||||
|
||||
void event_node_init(event_st* ev);
|
||||
void event_node_close(event_st* ev);
|
||||
void event_node_wait_ready(event_st* ev);
|
||||
void event_node_signal_ready(event_st* ev, int ready);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -103,6 +103,32 @@ typedef struct
|
|||
uint8_t synchronized_incoming_iq;
|
||||
} at86rf215_iq_interface_config_st;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int low_ch_i;
|
||||
int low_ch_q;
|
||||
int hi_ch_i;
|
||||
int hi_ch_q;
|
||||
} at86rf215_cal_results_st;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
pthread_mutex_t ready_mutex;
|
||||
pthread_cond_t ready_cond;
|
||||
int ready;
|
||||
} event_st;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
event_st lo_trx_ready_event;
|
||||
event_st lo_energy_measure_event;
|
||||
event_st hi_trx_ready_event;
|
||||
event_st hi_energy_measure_event;
|
||||
} at86rf215_events_st;
|
||||
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
// pinout
|
||||
|
@ -118,10 +144,9 @@ typedef struct
|
|||
io_utils_spi_st* io_spi;
|
||||
int io_spi_handle;
|
||||
int initialized;
|
||||
|
||||
//at86rf215_radio_st RF_Settings;
|
||||
//BBC_Settings_t BBC_Settings;
|
||||
//bool Continuous;
|
||||
at86rf215_cal_results_st cal;
|
||||
bool override_cal;
|
||||
at86rf215_events_st events;
|
||||
} at86rf215_st;
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,39 @@
|
|||
#include <stdio.h>
|
||||
#include "zf_log/zf_log.h"
|
||||
#include "at86rf215_common.h"
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
void event_node_init(event_st* ev)
|
||||
{
|
||||
pthread_cond_init(&ev->ready_cond, NULL);
|
||||
pthread_mutex_init(&ev->ready_mutex, NULL);
|
||||
}
|
||||
|
||||
void event_node_close(event_st* ev)
|
||||
{
|
||||
pthread_cond_destroy(&ev->ready_cond);
|
||||
pthread_mutex_destroy(&ev->ready_mutex);
|
||||
}
|
||||
|
||||
void event_node_wait_ready(event_st* ev)
|
||||
{
|
||||
pthread_mutex_lock(&ev->ready_mutex);
|
||||
while (!ev->ready)
|
||||
{
|
||||
pthread_cond_wait(&ev->ready_cond, &ev->ready_mutex);
|
||||
}
|
||||
ev->ready = 0;
|
||||
pthread_mutex_unlock(&ev->ready_mutex);
|
||||
}
|
||||
|
||||
void event_node_signal_ready(event_st* ev, int ready)
|
||||
{
|
||||
pthread_mutex_lock(&ev->ready_mutex);
|
||||
ev->ready = ready;
|
||||
pthread_cond_signal(&ev->ready_cond);
|
||||
pthread_mutex_unlock(&ev->ready_mutex);
|
||||
}
|
||||
|
||||
//===================================================================
|
||||
static void at86rf215_radio_event_handler (at86rf215_st* dev,
|
||||
|
@ -26,11 +59,15 @@ static void at86rf215_radio_event_handler (at86rf215_st* dev,
|
|||
if (events->trx_ready)
|
||||
{
|
||||
ZF_LOGD("INT @ RADIO%s: Transceiver ready", channel_st);
|
||||
if (ch == at86rf215_rf_channel_900mhz) event_node_signal_ready(&dev->events.lo_trx_ready_event, 1);
|
||||
else if (ch == at86rf215_rf_channel_2400mhz) event_node_signal_ready(&dev->events.hi_trx_ready_event, 1);
|
||||
}
|
||||
|
||||
if (events->energy_detection_complete)
|
||||
{
|
||||
ZF_LOGD("INT @ RADIO%s: Energy detection complete", channel_st);
|
||||
if (ch == at86rf215_rf_channel_900mhz) event_node_signal_ready(&dev->events.lo_energy_measure_event, 1);
|
||||
else if (ch == at86rf215_rf_channel_2400mhz) event_node_signal_ready(&dev->events.hi_energy_measure_event, 1);
|
||||
}
|
||||
|
||||
if (events->battery_low)
|
||||
|
|
|
@ -163,9 +163,22 @@ void at86rf215_radio_set_state(at86rf215_st* dev, at86rf215_rf_channel_en ch, at
|
|||
at86rf215_write_byte(dev, reg_address, cmd & 0x7);
|
||||
}
|
||||
}
|
||||
if (cmd == at86rf215_radio_state_cmd_tx_prep)
|
||||
{
|
||||
//if (ch == at86rf215_rf_channel_900mhz) event_node_wait_ready(&dev->events.lo_trx_ready_event);
|
||||
//else if (ch == at86rf215_rf_channel_2400mhz) event_node_wait_ready(&dev->events.hi_trx_ready_event);
|
||||
|
||||
io_utils_usleep(1000);
|
||||
if (dev->override_cal)
|
||||
{
|
||||
int i = ch == at86rf215_rf_channel_900mhz ? dev->cal.low_ch_i : dev->cal.hi_ch_i;
|
||||
int q = ch == at86rf215_rf_channel_900mhz ? dev->cal.low_ch_q : dev->cal.hi_ch_q;
|
||||
at86rf215_radio_set_tx_iq_calibration(dev, ch, i, q);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static double _fine_freq_starts[] = {0, 377e6, 754e6, 2366e6, 2550e6};
|
||||
static double _fine_freq_starts[] = {0, 350e6, 754e6, 2366e6, 2550e6};
|
||||
static double _fine_freq_pll_src[] = {0, 6.5e6, 13e6, 26e6};
|
||||
//static int _fine_freq_ccf_min[] = {0, 126030, 126030, 85700};
|
||||
//static int _fine_freq_ccf_max[] = {0, 1340967, 1340967, 296172};
|
||||
|
|
|
@ -34,6 +34,40 @@ at86rf215_st dev =
|
|||
.spi_channel = CARIBOULITE_MODEM_SPI_CHANNEL,
|
||||
};
|
||||
|
||||
|
||||
|
||||
uint16_t unknown_regs[] = { 0x0015,
|
||||
0x0115, 0x0117, 0x0118, 0x0119, 0x011A, 0x011B, 0x011C, 0x011D, 0x011E, 0x011F, 0x0120, 0x0123, 0x0124, 0x0129,
|
||||
0x0215, 0x0217, 0x0218, 0x0219, 0x021A, 0x021B, 0x021C, 0x021D, 0x021E, 0x021F, 0x0220, 0x0223, 0x0224, 0x0229};
|
||||
|
||||
uint8_t defaults[] = { 0x0E,
|
||||
0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0f, 0x0f, 0x08,
|
||||
0x40, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0f, 0x0f, 0x08};
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// This test checks the version number and part numbers of the device
|
||||
int test_at86rf215_read_all_regs(at86rf215_st* dev)
|
||||
{
|
||||
for (uint16_t reg = 0; reg < 0x300; reg ++)
|
||||
{
|
||||
uint8_t val = at86rf215_read_byte(dev, reg);
|
||||
printf("REG #0x%04X : 0x%02X\n", reg, val);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_at86rf215_read_all_regs_check(at86rf215_st* dev)
|
||||
{
|
||||
int num_regs = sizeof(unknown_regs) / sizeof(uint16_t);
|
||||
|
||||
for (int i = 0; i < num_regs; i ++)
|
||||
{
|
||||
uint8_t val = at86rf215_read_byte(dev, unknown_regs[i]);
|
||||
if (val != defaults[i]) printf("REG #0x%04X : 0x%02X (instead of 0x%02X)\n", unknown_regs[i], val, defaults[i]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// This test checks the version number and part numbers of the device
|
||||
int test_at86rf215_read_chip_vn_pn(at86rf215_st* dev)
|
||||
|
@ -101,6 +135,8 @@ void test_at86rf215_sweep_frequencies(at86rf215_st* dev,
|
|||
printf("Press enter to step...\n");
|
||||
getchar();
|
||||
}
|
||||
|
||||
//test_at86rf215_read_all_regs_check(dev);
|
||||
f += step_freq;
|
||||
}
|
||||
|
||||
|
@ -119,9 +155,12 @@ int test_at86rf215_continues_iq_rx (at86rf215_st* dev, at86rf215_rf_channel_en r
|
|||
at86rf215_iq_clock_data_skew_4_906ns;
|
||||
|
||||
at86rf215_setup_iq_radio_receive (dev, radio, freq_hz, 0, skew);
|
||||
printf("Started I/Q RX session for Radio %d, Freq: %llu Hz, timeout: %d usec (0=infinity)\n",
|
||||
printf("Started I/Q RX session for Radio %d, Freq: %lu Hz, timeout: %d usec (0=infinity)\n",
|
||||
radio, freq_hz, usec_timeout);
|
||||
|
||||
|
||||
test_at86rf215_read_all_regs_check(dev);
|
||||
|
||||
if (usec_timeout>0)
|
||||
{
|
||||
io_utils_usleep(usec_timeout);
|
||||
|
@ -132,6 +171,8 @@ int test_at86rf215_continues_iq_rx (at86rf215_st* dev, at86rf215_rf_channel_en r
|
|||
getchar();
|
||||
}
|
||||
at86rf215_stop_iq_radio_receive (dev, radio);
|
||||
|
||||
test_at86rf215_read_all_regs_check(dev);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -166,9 +207,10 @@ int test_at86rf215_continues_iq_loopback (at86rf215_st* dev, at86rf215_rf_channe
|
|||
#define NO_FPGA_MODE 0
|
||||
#define TEST_VERSIONS 1
|
||||
#define TEST_FREQ_SWEEP 0
|
||||
#define TEST_IQ_RX_WIND 1
|
||||
#define TEST_IQ_RX_WIND_RAD 1
|
||||
#define TEST_IQ_RX_WIND 0
|
||||
#define TEST_IQ_RX_WIND_RAD 0
|
||||
#define TEST_IQ_LB_WIND 0
|
||||
#define TEST_READ_ALL_REGS 0
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// MAIN
|
||||
|
@ -200,6 +242,8 @@ int main ()
|
|||
at86rf215_reset(&dev);
|
||||
at86rf215_init(&dev, &io_spi_dev);
|
||||
|
||||
test_at86rf215_read_all_regs_check(&dev);
|
||||
|
||||
// TEST: read the p/n and v/n from the IC
|
||||
#if TEST_VERSIONS
|
||||
test_at86rf215_read_chip_vn_pn(&dev);
|
||||
|
@ -207,7 +251,7 @@ int main ()
|
|||
|
||||
// TEST: Frequency sweep
|
||||
#if TEST_FREQ_SWEEP
|
||||
test_at86rf215_sweep_frequencies(&dev, at86rf215_rf_channel_900mhz, 900e6, 1, 0, 10000);
|
||||
test_at86rf215_sweep_frequencies(&dev, at86rf215_rf_channel_900mhz, 900e6, 3, 10, 10000);
|
||||
#endif // TEST_FREQ_SWEEP
|
||||
|
||||
#if TEST_IQ_RX_WIND
|
||||
|
@ -222,6 +266,10 @@ int main ()
|
|||
test_at86rf215_continues_iq_loopback (&dev, at86rf215_rf_channel_900mhz, 900e6, -1);
|
||||
#endif
|
||||
|
||||
#if TEST_READ_ALL_REGS
|
||||
test_at86rf215_read_all_regs_check(&dev);
|
||||
#endif
|
||||
|
||||
at86rf215_close(&dev);
|
||||
io_utils_spi_close(&io_spi_dev);
|
||||
io_utils_cleanup();
|
||||
|
|
|
@ -293,6 +293,36 @@ static void set_realtime_priority()
|
|||
ZF_LOGI("Thread priority is %d", params.sched_priority);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void* caribou_smi_analyze_thread(void* arg)
|
||||
{
|
||||
pthread_t tid = pthread_self();
|
||||
caribou_smi_stream_st* st = (caribou_smi_stream_st*)arg;
|
||||
caribou_smi_st* dev = (caribou_smi_st*)st->parent_dev;
|
||||
caribou_smi_stream_type_en type = (caribou_smi_stream_type_en)(st->stream_id>>1 & 0x1);
|
||||
caribou_smi_channel_en ch = (caribou_smi_channel_en)(st->stream_id & 0x1);
|
||||
|
||||
ZF_LOGD("Entered SMI analysis thread id %lu, running = %d", tid, st->read_analysis_thread_running);
|
||||
set_realtime_priority();
|
||||
|
||||
while (st->read_analysis_thread_running)
|
||||
{
|
||||
pthread_mutex_lock(&st->read_analysis_lock);
|
||||
if (!st->read_analysis_thread_running) break;
|
||||
|
||||
if (st->data_cb) st->data_cb(dev->cb_context,
|
||||
st->service_context,
|
||||
type,
|
||||
ch,
|
||||
st->read_ret_value,
|
||||
st->current_app_buffer,
|
||||
st->batch_length);
|
||||
}
|
||||
|
||||
ZF_LOGD("Exitting SMI analysis thread id %lu, running = %d", tid, st->read_analysis_thread_running);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void* caribou_smi_thread(void *arg)
|
||||
{
|
||||
|
@ -303,9 +333,27 @@ void* caribou_smi_thread(void *arg)
|
|||
caribou_smi_channel_en ch = (caribou_smi_channel_en)(st->stream_id & 0x1);
|
||||
|
||||
ZF_LOGD("Entered thread id %lu, running = %d", tid, st->running);
|
||||
|
||||
set_realtime_priority();
|
||||
|
||||
// create the analysis thread and mutexes
|
||||
if (pthread_mutex_init(&st->read_analysis_lock, NULL) != 0)
|
||||
{
|
||||
ZF_LOGE("read_analysis_lock mutex creation failed");
|
||||
st->active = 0;
|
||||
st->running = 0;
|
||||
return NULL;
|
||||
}
|
||||
pthread_mutex_lock(&st->read_analysis_lock);
|
||||
st->read_analysis_thread_running = 1;
|
||||
|
||||
int ret = pthread_create(&st->read_analysis_thread, NULL, &caribou_smi_analyze_thread, st);
|
||||
if (ret != 0)
|
||||
{
|
||||
ZF_LOGE("read analysis stream thread creation failed");
|
||||
st->active = 0;
|
||||
st->running = 0;
|
||||
return NULL;
|
||||
}
|
||||
st->active = 1;
|
||||
|
||||
// start thread notification
|
||||
|
@ -321,9 +369,7 @@ void* caribou_smi_thread(void *arg)
|
|||
{
|
||||
if (!st->running)
|
||||
{
|
||||
//ZF_LOGD("1");
|
||||
usleep(100000);
|
||||
//ZF_LOGD("2");
|
||||
usleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -339,22 +385,21 @@ void* caribou_smi_thread(void *arg)
|
|||
{
|
||||
continue;
|
||||
}
|
||||
//ZF_LOGD("4");
|
||||
|
||||
st->read_ret_value = ret;
|
||||
st->current_app_buffer = st->current_smi_buffer;
|
||||
if (st->data_cb) st->data_cb(dev->cb_context,
|
||||
st->service_context,
|
||||
type,
|
||||
ch,
|
||||
ret,
|
||||
st->current_app_buffer,
|
||||
st->batch_length);
|
||||
pthread_mutex_unlock(&st->read_analysis_lock);
|
||||
|
||||
st->current_smi_buffer_index ++;
|
||||
if (st->current_smi_buffer_index >= (int)(st->num_of_buffers)) st->current_smi_buffer_index = 0;
|
||||
st->current_smi_buffer = st->buffers[st->current_smi_buffer_index];
|
||||
}
|
||||
|
||||
st->read_analysis_thread_running = 0;
|
||||
pthread_mutex_unlock(&st->read_analysis_lock);
|
||||
pthread_join(st->read_analysis_thread, NULL); // check if cancel is needed
|
||||
pthread_mutex_destroy(&st->read_analysis_lock);
|
||||
|
||||
// exit thread notification
|
||||
if (st->data_cb != NULL) st->data_cb(dev->cb_context,
|
||||
st->service_context,
|
||||
|
@ -510,6 +555,7 @@ static void caribou_smi_init_stream(caribou_smi_st* dev, caribou_smi_stream_type
|
|||
|
||||
st->active = 0;
|
||||
st->running = 0;
|
||||
st->read_analysis_thread_running = 0;
|
||||
st->parent_dev = dev;
|
||||
}
|
||||
|
||||
|
|
|
@ -77,6 +77,10 @@ typedef struct
|
|||
int running; // the stream state - is it running and fetching / pushing information
|
||||
int stream_id; // the stream id for the application - may be deleted later
|
||||
pthread_t stream_thread; // thread id
|
||||
pthread_t read_analysis_thread; // read analysis thread
|
||||
pthread_mutex_t read_analysis_lock; // read analysis thread locker mutex
|
||||
int read_analysis_thread_running;
|
||||
int read_ret_value;
|
||||
void* parent_dev; // the pointer to the owning SMI device
|
||||
void* service_context; // the serviced session contect (SoapySDR...)
|
||||
} caribou_smi_stream_st;
|
||||
|
|
|
@ -113,6 +113,8 @@ int cariboulite_config_detect_board(cariboulite_board_info_st *info)
|
|||
else
|
||||
sscanf(info->product_id, "%08x", &info->numeric_product_id);
|
||||
|
||||
info->sys_type = (cariboulite_system_type_en)info->numeric_product_id;
|
||||
|
||||
// seiral number
|
||||
if (cariboulite_config_serial_from_uuid(info->product_uuid, &info->numeric_serial_number) != 0)
|
||||
{
|
||||
|
@ -132,4 +134,5 @@ void cariboulite_config_print_board_info(cariboulite_board_info_st *info)
|
|||
ZF_LOGI("# Board Info - Product Version: %s, Numeric: %d", info->product_version, info->numeric_version);
|
||||
ZF_LOGI("# Board Info - Product UUID: %s, Numeric serial: 0x%08X", info->product_uuid, info->numeric_serial_number);
|
||||
ZF_LOGI("# Board Info - Vendor: %s", info->product_vendor);
|
||||
ZF_LOGI("# Board Info - Product Type: %s", info->sys_type == cariboulite_system_type_full? "CaribouLite FULL" : "CaribouLite ISM");
|
||||
}
|
|
@ -21,6 +21,13 @@ extern "C" {
|
|||
#define MAX_PATH_LEN 512
|
||||
#define INFO_MAX_LEN 64
|
||||
|
||||
typedef enum
|
||||
{
|
||||
cariboulite_system_type_unknown = 0,
|
||||
cariboulite_system_type_full = 1,
|
||||
cariboulite_system_type_ism = 2,
|
||||
} cariboulite_system_type_en;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char category_name[INFO_MAX_LEN];
|
||||
|
@ -33,8 +40,25 @@ typedef struct
|
|||
uint32_t numeric_serial_number;
|
||||
uint32_t numeric_version;
|
||||
uint32_t numeric_product_id;
|
||||
|
||||
cariboulite_system_type_en sys_type;
|
||||
} cariboulite_board_info_st;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
cariboulite_ext_ref_src_modem = 0,
|
||||
cariboulite_ext_ref_src_connector = 1,
|
||||
cariboulite_ext_ref_src_txco = 2,
|
||||
cariboulite_ext_ref_src_na = 3, // not applicable
|
||||
} cariboulite_ext_ref_src_en;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cariboulite_ext_ref_src_en src;
|
||||
double freq_hz;
|
||||
} cariboulite_ext_ref_settings_st;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cariboulite_board_info_st board_info;
|
||||
|
@ -57,6 +81,7 @@ typedef struct
|
|||
|
||||
// Management
|
||||
caribou_fpga_versions_st fpga_versions;
|
||||
cariboulite_ext_ref_settings_st ext_ref_settings;
|
||||
uint8_t fpga_error_status;
|
||||
} cariboulite_st;
|
||||
|
||||
|
|
|
@ -75,6 +75,7 @@ extern "C" {
|
|||
.spi_dev = CARIBOULITE_SPI_DEV, \
|
||||
.spi_channel = CARIBOULITE_MODEM_SPI_CHANNEL, \
|
||||
.initialized = 0, \
|
||||
.override_cal = true, \
|
||||
}, \
|
||||
.mixer = \
|
||||
{ \
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "cariboulite_radios.h"
|
||||
#include "cariboulite_events.h"
|
||||
#include "cariboulite_setup.h"
|
||||
|
||||
|
||||
#define GET_RADIO_PTR(radio,chan) ((chan)==cariboulite_channel_s1g?&((radio)->radio_sub1g):&((radio)->radio_6g))
|
||||
|
@ -258,7 +259,7 @@ int cariboulite_set_rx_bandwidth(cariboulite_radios_st* radios,
|
|||
at86rf215_radio_f_cut_en fcut = at86rf215_radio_rx_f_cut_half_fs;
|
||||
|
||||
// Automatically calculate the digital f_cut
|
||||
if (rx_bw >= at86rf215_radio_rx_bw_BW160KHZ_IF250KHZ && rx_bw <= at86rf215_radio_rx_bw_BW500KHZ_IF500KHZ)
|
||||
/*if (rx_bw >= at86rf215_radio_rx_bw_BW160KHZ_IF250KHZ && rx_bw <= at86rf215_radio_rx_bw_BW500KHZ_IF500KHZ)
|
||||
fcut = at86rf215_radio_rx_f_cut_0_25_half_fs;
|
||||
else if (rx_bw >= at86rf215_radio_rx_bw_BW630KHZ_IF1000KHZ && rx_bw <= at86rf215_radio_rx_bw_BW630KHZ_IF1000KHZ)
|
||||
fcut = at86rf215_radio_rx_f_cut_0_375_half_fs;
|
||||
|
@ -267,7 +268,7 @@ int cariboulite_set_rx_bandwidth(cariboulite_radios_st* radios,
|
|||
else if (rx_bw >= at86rf215_radio_rx_bw_BW1250KHZ_IF2000KHZ && rx_bw <= at86rf215_radio_rx_bw_BW1250KHZ_IF2000KHZ)
|
||||
fcut = at86rf215_radio_rx_f_cut_0_75_half_fs;
|
||||
else
|
||||
fcut = at86rf215_radio_rx_f_cut_half_fs;
|
||||
fcut = at86rf215_radio_rx_f_cut_half_fs;*/
|
||||
|
||||
rad->rx_fcut = fcut;
|
||||
|
||||
|
@ -511,7 +512,8 @@ int cariboulite_get_rand_val(cariboulite_radios_st* radios, cariboulite_channel_
|
|||
#define CARIBOULITE_MAX_LO (4200.0e6)
|
||||
#define CARIBOULITE_2G4_MIN (2395.0e6) // 2400
|
||||
#define CARIBOULITE_2G4_MAX (2485.0e6) // 2483.5
|
||||
#define CARIBOULITE_S1G_MIN1 (389.5e6)
|
||||
//#define CARIBOULITE_S1G_MIN1 (389.5e6)
|
||||
#define CARIBOULITE_S1G_MIN1 (350.0e6)
|
||||
#define CARIBOULITE_S1G_MAX1 (510.0e6)
|
||||
#define CARIBOULITE_S1G_MIN2 (779.0e6)
|
||||
#define CARIBOULITE_S1G_MAX2 (1020.0e6)
|
||||
|
@ -573,6 +575,7 @@ int cariboulite_set_frequency( cariboulite_radios_st* radios,
|
|||
double lo_act_freq = 0.0;
|
||||
double act_freq = 0.0;
|
||||
int error = 0;
|
||||
cariboulite_ext_ref_freq_en ext_ref_choice = cariboulite_ext_ref_off;
|
||||
conversion_dir_en conversion_direction = conversion_dir_none;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
|
@ -635,20 +638,31 @@ int cariboulite_set_frequency( cariboulite_radios_st* radios,
|
|||
caribou_fpga_set_io_ctrl_mode (&rad->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_low_power);
|
||||
}
|
||||
|
||||
// Calculate the best ext_ref
|
||||
double f_rf_mod_32 = (f_rf / 32e6);
|
||||
double f_rf_mod_26 = (f_rf / 26e6);
|
||||
f_rf_mod_32 -= (uint64_t)(f_rf_mod_32);
|
||||
f_rf_mod_26 -= (uint64_t)(f_rf_mod_26);
|
||||
if (f_rf_mod_32 > 16e6) f_rf_mod_32 = 32e6 - f_rf_mod_32;
|
||||
if (f_rf_mod_26 > 13e6) f_rf_mod_26 = 13e6 - f_rf_mod_26;
|
||||
ext_ref_choice = f_rf_mod_32 > f_rf_mod_26 ? cariboulite_ext_ref_32mhz : cariboulite_ext_ref_26mhz;
|
||||
cariboulite_setup_ext_ref (rad->cariboulite_sys, ext_ref_choice);
|
||||
|
||||
// Decide the conversion direction and IF/RF/LO
|
||||
//-------------------------------------
|
||||
if (f_rf >= CARIBOULITE_MIN_MIX &&
|
||||
f_rf <= (CARIBOULITE_2G4_MIN) )
|
||||
{
|
||||
// region #1 - UP CONVERSION
|
||||
// setup modem frequency <= CARIBOULITE_2G4_MAX
|
||||
uint32_t modem_freq = CARIBOULITE_2G4_MAX;
|
||||
if (f_rf > (CARIBOULITE_2G4_MAX/2 - 15e6) && f_rf < (CARIBOULITE_2G4_MAX/2 + 15e6)) modem_freq = CARIBOULITE_2G4_MIN;
|
||||
modem_act_freq = (double)at86rf215_setup_channel (&rad->cariboulite_sys->modem,
|
||||
at86rf215_rf_channel_2400mhz,
|
||||
(uint32_t)(CARIBOULITE_2G4_MAX));
|
||||
modem_freq);
|
||||
|
||||
// setup mixer LO according to the actual modem frequency
|
||||
lo_act_freq = rffc507x_set_frequency(&rad->cariboulite_sys->mixer, modem_act_freq + f_rf);
|
||||
act_freq = lo_act_freq - modem_act_freq;
|
||||
act_freq = modem_act_freq + lo_act_freq;
|
||||
|
||||
// setup fpga RFFE <= upconvert (tx / rx)
|
||||
conversion_direction = conversion_dir_up;
|
||||
|
@ -676,9 +690,12 @@ int cariboulite_set_frequency( cariboulite_radios_st* radios,
|
|||
at86rf215_rf_channel_2400mhz,
|
||||
(uint32_t)(CARIBOULITE_2G4_MIN));
|
||||
|
||||
uint32_t lo = f_rf + modem_act_freq;
|
||||
if (f_rf > (CARIBOULITE_2G4_MIN*2 + CARIBOULITE_MIN_LO)) lo = f_rf - modem_act_freq;
|
||||
// setup mixer LO to according to actual modem frequency
|
||||
lo_act_freq = rffc507x_set_frequency(&rad->cariboulite_sys->mixer, f_rf + modem_act_freq);
|
||||
act_freq = modem_act_freq + lo_act_freq;
|
||||
lo_act_freq = rffc507x_set_frequency(&rad->cariboulite_sys->mixer, f_rf - modem_act_freq);
|
||||
act_freq = lo_act_freq - modem_act_freq;
|
||||
if (f_rf > (CARIBOULITE_2G4_MIN*2 + CARIBOULITE_MIN_LO)) act_freq = modem_act_freq + lo_act_freq;
|
||||
|
||||
// setup fpga RFFE <= downconvert (tx / rx)
|
||||
conversion_direction = conversion_dir_down;
|
||||
|
@ -728,7 +745,9 @@ int cariboulite_set_frequency( cariboulite_radios_st* radios,
|
|||
at86rf215_radio_state_cmd_tx_prep);
|
||||
rad->state = at86rf215_radio_state_cmd_tx_prep;
|
||||
|
||||
if (!cariboulite_wait_for_lock(rad, &rad->modem_pll_locked, &rad->lo_pll_locked, 100))
|
||||
if (!cariboulite_wait_for_lock(rad, &rad->modem_pll_locked,
|
||||
lo_act_freq > CARIBOULITE_MIN_LO ? &rad->lo_pll_locked : NULL,
|
||||
100))
|
||||
{
|
||||
if (!rad->lo_pll_locked) ZF_LOGE("PLL MIXER failed to lock LO frequency (%.2f Hz)", lo_act_freq);
|
||||
if (!rad->modem_pll_locked) ZF_LOGE("PLL MODEM failed to lock IF frequency (%.2f Hz)", modem_act_freq);
|
||||
|
@ -894,7 +913,7 @@ int cariboulite_create_smi_stream(cariboulite_radios_st* radios,
|
|||
|
||||
int stream_id = caribou_smi_setup_stream(&rad->cariboulite_sys->smi,
|
||||
type, ch,
|
||||
buffer_length, 2,
|
||||
buffer_length, 3,
|
||||
caribou_smi_data_event,
|
||||
context);
|
||||
|
||||
|
|
|
@ -21,6 +21,24 @@ typedef enum
|
|||
cariboulite_channel_6g = 1,
|
||||
} cariboulite_channel_en;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cariboulite_channel_en type;
|
||||
bool cw_out;
|
||||
bool lo_out;
|
||||
cariboulite_ext_ref_src_en ext_ref_src;
|
||||
uint32_t ext_ref_freq_hz;
|
||||
|
||||
double requested_freq;
|
||||
double modem_actual_freq;
|
||||
double mixer_actual_freq;
|
||||
double actual_freq;
|
||||
double actual_freq_error;
|
||||
|
||||
bool modem_lock;
|
||||
bool mixer_lock;
|
||||
} cariboulite_freq_construction_st;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
cariboulite_st* cariboulite_sys;
|
||||
|
@ -53,11 +71,12 @@ typedef struct
|
|||
// FREQUENCY
|
||||
bool modem_pll_locked;
|
||||
bool lo_pll_locked;
|
||||
float lo_frequency;
|
||||
float if_frequency;
|
||||
float actual_rf_frequency;
|
||||
float requested_rf_frequency;
|
||||
float rf_frequency_error;
|
||||
double lo_frequency;
|
||||
double if_frequency;
|
||||
double actual_rf_frequency;
|
||||
double requested_rf_frequency;
|
||||
double rf_frequency_error;
|
||||
//cariboulite_freq_construction_st freq;
|
||||
|
||||
// SMI STREAMS
|
||||
int rx_stream_id;
|
||||
|
|
|
@ -121,6 +121,30 @@ int cariboulite_configure_fpga (cariboulite_st* sys, cariboulite_firmware_source
|
|||
return -error;
|
||||
}
|
||||
|
||||
//=======================================================================================
|
||||
int cariboulite_setup_ext_ref ( cariboulite_st *sys, cariboulite_ext_ref_freq_en ref)
|
||||
{
|
||||
switch(ref)
|
||||
{
|
||||
case cariboulite_ext_ref_26mhz:
|
||||
ZF_LOGD("Setting ext_ref = 26MHz");
|
||||
at86rf215_set_clock_output(&sys->modem, at86rf215_drive_current_4ma, at86rf215_clock_out_freq_26mhz);
|
||||
rffc507x_setup_reference_freq(&sys->mixer, 26e6);
|
||||
break;
|
||||
case cariboulite_ext_ref_32mhz:
|
||||
ZF_LOGD("Setting ext_ref = 32MHz");
|
||||
at86rf215_set_clock_output(&sys->modem, at86rf215_drive_current_4ma, at86rf215_clock_out_freq_32mhz);
|
||||
rffc507x_setup_reference_freq(&sys->mixer, 32e6);
|
||||
break;
|
||||
case cariboulite_ext_ref_off:
|
||||
ZF_LOGD("Setting ext_ref = OFF");
|
||||
at86rf215_set_clock_output(&sys->modem, at86rf215_drive_current_4ma, at86rf215_clock_out_freq_off);
|
||||
default:
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================================
|
||||
int cariboulite_init_submodules (cariboulite_st* sys)
|
||||
{
|
||||
|
@ -160,7 +184,7 @@ int cariboulite_init_submodules (cariboulite_st* sys)
|
|||
// Configure modem
|
||||
//------------------------------------------------------
|
||||
ZF_LOGD("Configuring modem initial state");
|
||||
at86rf215_set_clock_output(&sys->modem, at86rf215_drive_current_2ma, at86rf215_clock_out_freq_32mhz);
|
||||
//at86rf215_set_clock_output(&sys->modem, at86rf215_drive_current_4ma, at86rf215_clock_out_freq_26mhz);
|
||||
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);
|
||||
|
@ -192,7 +216,7 @@ int cariboulite_init_submodules (cariboulite_st* sys)
|
|||
.ext_lna_bypass_available = 0,
|
||||
.agc_backoff = 0,
|
||||
.analog_voltage_external = 0,
|
||||
.analog_voltage_enable_in_off = 0,
|
||||
.analog_voltage_enable_in_off = 1,
|
||||
.int_power_amplifier_voltage = 2,
|
||||
.fe_pad_configuration = 1,
|
||||
};
|
||||
|
@ -211,7 +235,7 @@ int cariboulite_init_submodules (cariboulite_st* sys)
|
|||
|
||||
// Configure mixer
|
||||
//------------------------------------------------------
|
||||
rffc507x_setup_reference_freq(&sys->mixer, 32e6);
|
||||
//rffc507x_setup_reference_freq(&sys->mixer, 26e6);
|
||||
rffc507x_calibrate(&sys->mixer);
|
||||
|
||||
ZF_LOGI("Cariboulite submodules successfully initialized");
|
||||
|
@ -323,11 +347,41 @@ int cariboulite_release_submodules(cariboulite_st* sys)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//=================================================
|
||||
int cariboulite_version_dependent_config (cariboulite_st* sys)
|
||||
{
|
||||
ZF_LOGI("Performing version dependent configurations");
|
||||
switch (sys->board_info.sys_type)
|
||||
{
|
||||
case cariboulite_system_type_full:
|
||||
ZF_LOGD("This board is a Full version CaribouLite - setting ext_ref: modem, 32MHz");
|
||||
// by default the ext_ref for the mixer - from the modem, 32MHz
|
||||
sys->ext_ref_settings.src = cariboulite_ext_ref_src_modem;
|
||||
sys->ext_ref_settings.freq_hz = 32000000;
|
||||
cariboulite_setup_ext_ref (sys, cariboulite_ext_ref_32mhz);
|
||||
break;
|
||||
case cariboulite_system_type_ism:
|
||||
ZF_LOGD("This board is a ISM version CaribouLite - setting ext_ref: OFF");
|
||||
sys->ext_ref_settings.src = cariboulite_ext_ref_src_na;
|
||||
sys->ext_ref_settings.freq_hz = 0;
|
||||
cariboulite_setup_ext_ref (sys, cariboulite_ext_ref_off);
|
||||
|
||||
break;
|
||||
case cariboulite_system_type_unknown:
|
||||
default:
|
||||
ZF_LOGE("This board doesn't have a valid product ID.");
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=================================================
|
||||
int cariboulite_init_driver(cariboulite_st *sys, void* signal_handler_cb, cariboulite_board_info_st *info)
|
||||
{
|
||||
zf_log_set_output_level(ZF_LOG_ERROR);
|
||||
//zf_log_set_output_level(ZF_LOG_VERBOSE);
|
||||
//zf_log_set_output_level(ZF_LOG_ERROR);
|
||||
zf_log_set_output_level(ZF_LOG_VERBOSE);
|
||||
|
||||
ZF_LOGI("driver initializing");
|
||||
if (info == NULL)
|
||||
|
@ -363,6 +417,12 @@ int cariboulite_init_driver(cariboulite_st *sys, void* signal_handler_cb, caribo
|
|||
return -cariboulite_submodules_init_failed;
|
||||
}
|
||||
|
||||
if (cariboulite_version_dependent_config(sys))
|
||||
{
|
||||
cariboulite_release_io (sys);
|
||||
return -cariboulite_board_dependent_config_failed;
|
||||
}
|
||||
|
||||
cariboulite_self_test_result_st self_tes_res = {0};
|
||||
if (cariboulite_self_test(sys, &self_tes_res) != 0)
|
||||
{
|
||||
|
|
|
@ -51,8 +51,16 @@ typedef enum
|
|||
cariboulite_fpga_configuration_failed = -3,
|
||||
cariboulite_submodules_init_failed = -4,
|
||||
cariboulite_self_test_failed = -5,
|
||||
cariboulite_board_dependent_config_failed = -6,
|
||||
} cariboulite_errors_en;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
cariboulite_ext_ref_off = 0,
|
||||
cariboulite_ext_ref_26mhz = 26,
|
||||
cariboulite_ext_ref_32mhz = 32,
|
||||
} cariboulite_ext_ref_freq_en;
|
||||
|
||||
int cariboulite_init_driver(cariboulite_st *sys, void* signal_handler_cb, cariboulite_board_info_st *info);
|
||||
void cariboulite_release_driver(cariboulite_st *sys);
|
||||
void cariboulite_lib_version(cariboulite_lib_version_st* v);
|
||||
|
@ -61,8 +69,11 @@ int cariboulite_setup_io (cariboulite_st* sys, void* sighandler);
|
|||
int cariboulite_release_io (cariboulite_st* sys);
|
||||
int cariboulite_configure_fpga (cariboulite_st* sys, cariboulite_firmware_source_en src, char* fpga_bin_path);
|
||||
int cariboulite_init_submodules (cariboulite_st* sys);
|
||||
int cariboulite_version_dependent_config (cariboulite_st* sys);
|
||||
int cariboulite_release_submodules(cariboulite_st* sys);
|
||||
int cariboulite_self_test(cariboulite_st* sys, cariboulite_self_test_result_st* res);
|
||||
int cariboulite_setup_ext_ref ( cariboulite_st *sys, cariboulite_ext_ref_freq_en ref);
|
||||
|
||||
int cariboulite_setup_frequency( cariboulite_st *sys,
|
||||
cariboulite_channel_en ch,
|
||||
cariboulite_channel_dir_en dir,
|
||||
|
|
|
@ -149,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, 5);
|
||||
set_RFFC507X_P1MIXIDD(dev, 5);
|
||||
set_RFFC507X_P2MIXIDD(dev, 2);
|
||||
set_RFFC507X_P1MIXIDD(dev, 2);
|
||||
|
||||
// Others
|
||||
set_RFFC507X_LDEN(dev, 1);
|
||||
|
|
|
@ -290,10 +290,12 @@ std::vector<double> Cariboulite::listSampleRates( const int direction, const siz
|
|||
return(options);
|
||||
}
|
||||
|
||||
#define BW_SHIFT_FACT (1.25)
|
||||
|
||||
//========================================================
|
||||
static at86rf215_radio_rx_bw_en convertRxBandwidth(double bw_numeric)
|
||||
{
|
||||
float fact = 1.25;
|
||||
float fact = BW_SHIFT_FACT;
|
||||
if (fabs(bw_numeric - (160000*fact)) < 1) return at86rf215_radio_rx_bw_BW160KHZ_IF250KHZ;
|
||||
if (fabs(bw_numeric - (200000*fact)) < 1) return at86rf215_radio_rx_bw_BW200KHZ_IF250KHZ;
|
||||
if (fabs(bw_numeric - (250000*fact)) < 1) return at86rf215_radio_rx_bw_BW250KHZ_IF250KHZ;
|
||||
|
@ -318,7 +320,7 @@ static at86rf215_radio_rx_bw_en convertRxBandwidth(double bw_numeric)
|
|||
//========================================================
|
||||
static double convertRxBandwidth(at86rf215_radio_rx_bw_en bw_en)
|
||||
{
|
||||
float fact = 1.25;
|
||||
float fact = BW_SHIFT_FACT;
|
||||
if (at86rf215_radio_rx_bw_BW160KHZ_IF250KHZ == bw_en) return 160000 * fact;
|
||||
if (at86rf215_radio_rx_bw_BW200KHZ_IF250KHZ == bw_en) return 200000 * fact;
|
||||
if (at86rf215_radio_rx_bw_BW250KHZ_IF250KHZ == bw_en) return 250000 * fact;
|
||||
|
@ -421,7 +423,7 @@ std::vector<double> Cariboulite::listBandwidths( const int direction, const size
|
|||
std::vector<double> options;
|
||||
if (direction == SOAPY_SDR_RX)
|
||||
{
|
||||
float fact = 1.25;
|
||||
float fact = BW_SHIFT_FACT;
|
||||
options.push_back( 160000*fact );
|
||||
options.push_back( 200000*fact );
|
||||
options.push_back( 250000*fact );
|
||||
|
|
|
@ -60,22 +60,22 @@ typedef struct
|
|||
// associated with CS32 - total 8 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int32_t q; // LSB
|
||||
int32_t i; // MSB
|
||||
int32_t i; // LSB
|
||||
int32_t q; // MSB
|
||||
} sample_complex_int32;
|
||||
|
||||
// associated with CF32 - total 8 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
float q; // LSB
|
||||
float i; // MSB
|
||||
float i; // LSB
|
||||
float q; // MSB
|
||||
} sample_complex_float;
|
||||
|
||||
// associated with CF64 - total 16 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
double q; // LSB
|
||||
double i; // MSB
|
||||
double i; // LSB
|
||||
double q; // MSB
|
||||
} sample_complex_double;
|
||||
#pragma pack()
|
||||
|
||||
|
|
|
@ -179,6 +179,7 @@ int SampleQueue::Read(uint8_t *buffer, size_t length, uint32_t *meta, long timeo
|
|||
int SampleQueue::ReadSamples(sample_complex_int16* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
static int once = 100;
|
||||
static uint16_t last_q = 0;
|
||||
// this is the native method
|
||||
int tot_length = num_elements * sizeof(sample_complex_int16);
|
||||
int res = Read((uint8_t *)buffer, tot_length, NULL, timeout_us);
|
||||
|
@ -193,6 +194,19 @@ int SampleQueue::ReadSamples(sample_complex_int16* buffer, size_t num_elements,
|
|||
once--;
|
||||
}*/
|
||||
int tot_read_elements = res / sizeof(sample_complex_int16);
|
||||
|
||||
// shift q
|
||||
//buffer[0].q = last_q;
|
||||
for (int i = 1; i < tot_read_elements; i++)
|
||||
{
|
||||
buffer[i-1].q = buffer[i].q;
|
||||
}
|
||||
|
||||
/*for (int i = tot_read_elements-1; i >= 0; i--)
|
||||
{
|
||||
buffer[i].q = buffer[i-1].q;
|
||||
}*/
|
||||
|
||||
for (int i = 0; i < tot_read_elements; i++)
|
||||
{
|
||||
buffer[i].i >>= 1;
|
||||
|
@ -203,7 +217,6 @@ int SampleQueue::ReadSamples(sample_complex_int16* buffer, size_t num_elements,
|
|||
|
||||
if (buffer[i].i >= (int16_t)0x1000) buffer[i].i -= (int16_t)0x2000;
|
||||
if (buffer[i].q >= (int16_t)0x1000) buffer[i].q -= (int16_t)0x2000;
|
||||
|
||||
/*if (i<5)
|
||||
{
|
||||
printf("i: %d, q: %d\n", buffer[i].i, buffer[i].q);
|
||||
|
@ -240,6 +253,48 @@ int SampleQueue::ReadSamples(sample_complex_float* buffer, size_t num_elements,
|
|||
buffer[i].q = (float)interm_native_buffer[i].q / max_val;
|
||||
}
|
||||
|
||||
double sumI = 0.0;
|
||||
double sumQ = 0.0;
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
sumI += buffer[i].i;
|
||||
sumQ += buffer[i].q;
|
||||
}
|
||||
sumI /= (double)res;
|
||||
sumQ /= (double)res;
|
||||
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
buffer[i].i -= sumI;
|
||||
buffer[i].q -= sumQ;
|
||||
}
|
||||
|
||||
double theta1 = 0.0;
|
||||
double theta2 = 0.0;
|
||||
double theta3 = 0.0;
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
int sign_I = (buffer[i].i > 0 ? 1 : -1);
|
||||
int sign_Q = (buffer[i].q > 0 ? 1 : -1);
|
||||
theta1 += sign_I * buffer[i].q;
|
||||
theta2 += sign_I * buffer[i].i;
|
||||
theta3 += sign_Q * buffer[i].q;
|
||||
}
|
||||
theta1 = - theta1 / (double)res;
|
||||
theta2 /= (double)res;
|
||||
theta3 /= (double)res;
|
||||
|
||||
double c1 = theta1 / theta2;
|
||||
double c2 = sqrt( (theta3*theta3 - theta1*theta1) / (theta2*theta2) );
|
||||
|
||||
for (int i = 0; i < res; i++)
|
||||
{
|
||||
float ii = buffer[i].i;
|
||||
float qq = buffer[i].q;
|
||||
buffer[i].i = c2 * ii;
|
||||
buffer[i].q = c1 * ii + qq;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
|
@ -238,7 +238,7 @@ SoapySDR::Stream *Cariboulite::setupStream(const int direction,
|
|||
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,
|
||||
GET_MTU_MS_BYTES(BUFFER_SIZE_MS), 4,
|
||||
caribou_stream_data_event,
|
||||
this);
|
||||
if (stream_id < 0)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# This is the CMakeCache file.
|
||||
# For build in directory: /home/pi/projects/cariboulite/software/utils
|
||||
# It was generated by CMake: /usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake
|
||||
# It was generated by CMake: /usr/bin/cmake
|
||||
# You can edit this file to change values found and used by cmake.
|
||||
# If you do not want to change any of the values, simply exit the editor.
|
||||
# If you do want to change a value, simply edit, save, and exit the editor.
|
||||
|
@ -235,11 +235,11 @@ CMAKE_CACHE_PATCH_VERSION:INTERNAL=4
|
|||
//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE
|
||||
CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1
|
||||
//Path to CMake executable.
|
||||
CMAKE_COMMAND:INTERNAL=/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake
|
||||
CMAKE_COMMAND:INTERNAL=/usr/bin/cmake
|
||||
//Path to cpack program executable.
|
||||
CMAKE_CPACK_COMMAND:INTERNAL=/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cpack
|
||||
CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack
|
||||
//Path to ctest program executable.
|
||||
CMAKE_CTEST_COMMAND:INTERNAL=/usr/local/lib/python3.7/dist-packages/cmake/data/bin/ctest
|
||||
CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest
|
||||
//ADVANCED property for variable: CMAKE_CXX_COMPILER
|
||||
CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1
|
||||
//ADVANCED property for variable: CMAKE_CXX_COMPILER_AR
|
||||
|
@ -332,7 +332,7 @@ CMAKE_RANLIB-ADVANCED:INTERNAL=1
|
|||
//ADVANCED property for variable: CMAKE_READELF
|
||||
CMAKE_READELF-ADVANCED:INTERNAL=1
|
||||
//Path to CMake installation.
|
||||
CMAKE_ROOT:INTERNAL=/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18
|
||||
CMAKE_ROOT:INTERNAL=/usr/share/cmake-3.18
|
||||
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS
|
||||
CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1
|
||||
//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG
|
||||
|
|
|
@ -11,25 +11,25 @@ set(CMAKE_MAKEFILE_DEPENDS
|
|||
"CMakeFiles/3.18.4/CMakeCXXCompiler.cmake"
|
||||
"CMakeFiles/3.18.4/CMakeSystem.cmake"
|
||||
"CMakeLists.txt"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeCInformation.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeCXXInformation.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeCommonLanguageInclude.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeGenericSystem.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeInitializeConfigs.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeLanguageInformation.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeSystemSpecificInformation.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/CMakeSystemSpecificInitialize.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Compiler/GNU-C.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Compiler/GNU-CXX.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Compiler/GNU.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Internal/CMakeCheckCompilerFlag.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Platform/Linux-GNU-C.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Platform/Linux-GNU-CXX.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Platform/Linux-GNU.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Platform/Linux.cmake"
|
||||
"/usr/local/lib/python3.7/dist-packages/cmake/data/share/cmake-3.18/Modules/Platform/UnixPaths.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeCInformation.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeCXXInformation.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeCheckCompilerFlagCommonPatterns.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeCommonLanguageInclude.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeGenericSystem.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeInitializeConfigs.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeLanguageInformation.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeSystemSpecificInformation.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/CMakeSystemSpecificInitialize.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Compiler/CMakeCommonCompilerMacros.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Compiler/GNU-C.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Compiler/GNU-CXX.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Compiler/GNU.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Internal/CMakeCheckCompilerFlag.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Platform/Linux-GNU-C.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Platform/Linux-GNU-CXX.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Platform/Linux-GNU.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Platform/Linux.cmake"
|
||||
"/usr/share/cmake-3.18/Modules/Platform/UnixPaths.cmake"
|
||||
)
|
||||
|
||||
# The corresponding makefile is:
|
||||
|
|
|
@ -54,10 +54,10 @@ cmake_force:
|
|||
SHELL = /bin/sh
|
||||
|
||||
# The CMake executable.
|
||||
CMAKE_COMMAND = /usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake
|
||||
CMAKE_COMMAND = /usr/bin/cmake
|
||||
|
||||
# The command to remove a file.
|
||||
RM = /usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -E rm -f
|
||||
RM = /usr/bin/cmake -E rm -f
|
||||
|
||||
# Escaping for special characters.
|
||||
EQUALS = =
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/install/strip.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/edit_cache.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/rebuild_cache.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/list_install_components.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/install.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/generate_bin_blob.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/install/local.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/edit_cache.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/install.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/list_install_components.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/rebuild_cache.dir
|
||||
/home/pi/projects/cariboulite/software/utils/CMakeFiles/generate_bin_blob.dir
|
||||
|
|
|
@ -53,10 +53,10 @@ cmake_force:
|
|||
SHELL = /bin/sh
|
||||
|
||||
# The CMake executable.
|
||||
CMAKE_COMMAND = /usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake
|
||||
CMAKE_COMMAND = /usr/bin/cmake
|
||||
|
||||
# The command to remove a file.
|
||||
RM = /usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -E rm -f
|
||||
RM = /usr/bin/cmake -E rm -f
|
||||
|
||||
# Escaping for special characters.
|
||||
EQUALS = =
|
||||
|
|
|
@ -58,10 +58,10 @@ cmake_force:
|
|||
SHELL = /bin/sh
|
||||
|
||||
# The CMake executable.
|
||||
CMAKE_COMMAND = /usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake
|
||||
CMAKE_COMMAND = /usr/bin/cmake
|
||||
|
||||
# The command to remove a file.
|
||||
RM = /usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -E rm -f
|
||||
RM = /usr/bin/cmake -E rm -f
|
||||
|
||||
# Escaping for special characters.
|
||||
EQUALS = =
|
||||
|
@ -78,19 +78,31 @@ CMAKE_BINARY_DIR = /home/pi/projects/cariboulite/software/utils
|
|||
# Special rule for the target install/strip
|
||||
install/strip: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
|
||||
/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
|
||||
/usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
|
||||
.PHONY : install/strip
|
||||
|
||||
# Special rule for the target install/strip
|
||||
install/strip/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
|
||||
/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
|
||||
/usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
|
||||
.PHONY : install/strip/fast
|
||||
|
||||
# Special rule for the target install/local
|
||||
install/local: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
|
||||
/usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
|
||||
.PHONY : install/local
|
||||
|
||||
# Special rule for the target install/local
|
||||
install/local/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
|
||||
/usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
|
||||
.PHONY : install/local/fast
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
edit_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..."
|
||||
/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
|
||||
/usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
|
||||
.PHONY : edit_cache
|
||||
|
||||
# Special rule for the target edit_cache
|
||||
|
@ -98,16 +110,17 @@ edit_cache/fast: edit_cache
|
|||
|
||||
.PHONY : edit_cache/fast
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
|
||||
/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : rebuild_cache
|
||||
# Special rule for the target install
|
||||
install: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
|
||||
/usr/bin/cmake -P cmake_install.cmake
|
||||
.PHONY : install
|
||||
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache/fast: rebuild_cache
|
||||
|
||||
.PHONY : rebuild_cache/fast
|
||||
# Special rule for the target install
|
||||
install/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
|
||||
/usr/bin/cmake -P cmake_install.cmake
|
||||
.PHONY : install/fast
|
||||
|
||||
# Special rule for the target list_install_components
|
||||
list_install_components:
|
||||
|
@ -119,29 +132,16 @@ list_install_components/fast: list_install_components
|
|||
|
||||
.PHONY : list_install_components/fast
|
||||
|
||||
# Special rule for the target install
|
||||
install: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
|
||||
/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -P cmake_install.cmake
|
||||
.PHONY : install
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache:
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
|
||||
/usr/bin/cmake --regenerate-during-build -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
|
||||
.PHONY : rebuild_cache
|
||||
|
||||
# Special rule for the target install
|
||||
install/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
|
||||
/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -P cmake_install.cmake
|
||||
.PHONY : install/fast
|
||||
# Special rule for the target rebuild_cache
|
||||
rebuild_cache/fast: rebuild_cache
|
||||
|
||||
# Special rule for the target install/local
|
||||
install/local: preinstall
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
|
||||
/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
|
||||
.PHONY : install/local
|
||||
|
||||
# Special rule for the target install/local
|
||||
install/local/fast: preinstall/fast
|
||||
@$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
|
||||
/usr/local/lib/python3.7/dist-packages/cmake/data/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
|
||||
.PHONY : install/local/fast
|
||||
.PHONY : rebuild_cache/fast
|
||||
|
||||
# The main all target
|
||||
all: cmake_check_build_system
|
||||
|
|
Plik binarny nie jest wyświetlany.
Ładowanie…
Reference in New Issue