bug_fixes_integration_tx
David Michaeli 2022-04-19 19:26:21 +03:00
rodzic 5173581cf3
commit 0935f22b47
10 zmienionych plików z 1218 dodań i 943 usunięć

Wyświetl plik

@ -10,7 +10,7 @@ include_directories(${PROJECT_SOURCE_DIR}/src)
# ------------------------------------
# MAIN - Source files for main library
# ------------------------------------
set(SOURCES_LIB src/cariboulite_setup.c src/cariboulite_events.c src/cariboulite_radios.c)
set(SOURCES_LIB src/cariboulite_setup.c src/cariboulite_events.c src/cariboulite_radios.c src/cariboulite_radio.c)
# Add internal project dependencies
add_subdirectory(src/datatypes EXCLUDE_FROM_ALL)

Wyświetl plik

@ -0,0 +1,878 @@
#ifndef ZF_LOG_LEVEL
#define ZF_LOG_LEVEL ZF_LOG_VERBOSE
#endif
#define ZF_LOG_DEF_SRCLOC ZF_LOG_SRCLOC_LONG
#define ZF_LOG_TAG "CARIBOULITE Radio"
#include "zf_log/zf_log.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <linux/random.h>
#include <sys/ioctl.h>
#include "cariboulite_radio.h"
#include "cariboulite_events.h"
#include "cariboulite_setup.h"
#define GET_CH(rad_ch) ((rad_ch)==cariboulite_channel_s1g ?at86rf215_rf_channel_900mhz : at86rf215_rf_channel_2400mhz)
#define GET_SMI_CH(rad_ch) ((rad_ch)==cariboulite_channel_s1g ?caribou_smi_channel_900 : caribou_smi_channel_2400)
#define GET_SMI_DIR(ch_dir) ((dir) == cariboulite_channel_dir_rx ? caribou_smi_stream_type_read : caribou_smi_stream_type_write)
//=========================================================================
void cariboulite_radio_init(cariboulite_radio_state_st* radio, cariboulite_st *sys, cariboulite_channel_en type)
{
memset (radio, 0, sizeof(cariboulite_radio_state_st));
radio->cariboulite_sys = sys;
radio->active = true;
radio->channel_direction = cariboulite_channel_dir_rx;
radio->type = type;
radio->cw_output = false;
radio->lo_output = false;
radio->rx_stream_id = -1;
radio->tx_stream_id = -1;
}
//=========================================================================
int cariboulite_radio_dispose(cariboulite_radio_state_st* radio)
{
radio->active = false;
// If streams are active - destroy them
if (radio->rx_stream_id != -1)
{
caribou_smi_destroy_stream(&radio->cariboulite_sys->smi, radio->rx_stream_id);
radio->rx_stream_id = -1;
}
if (radio->tx_stream_id != -1)
{
caribou_smi_destroy_stream(&radio->cariboulite_sys->smi, radio->tx_stream_id);
radio->tx_stream_id = -1;
}
usleep(100000);
at86rf215_radio_set_state( &radio->cariboulite_sys->modem,
GET_CH(radio->type),
at86rf215_radio_state_cmd_trx_off);
radio->state = at86rf215_radio_state_cmd_trx_off;
// Type specific
if (radio->type == cariboulite_channel_6g)
{
caribou_fpga_set_io_ctrl_mode (&radio->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_low_power);
}
}
//=========================================================================
int cariboulite_radio_sync_information(cariboulite_radio_state_st* radio)
{
cariboulite_radio_get_mod_state (radio, NULL);
cariboulite_radio_get_rx_gain_control(radio, NULL, NULL);
cariboulite_radio_get_rx_bandwidth(radio, NULL);
cariboulite_radio_get_tx_power(radio, NULL);
cariboulite_radio_get_rssi(radio, NULL);
cariboulite_radio_get_energy_det(radio, NULL);
}
//=========================================================================
int cariboulite_radio_get_mod_state (cariboulite_radio_state_st* radio, at86rf215_radio_state_cmd_en *state)
{
radio->state = at86rf215_radio_get_state(&radio->cariboulite_sys->modem, GET_CH(radio->type));
if (state) *state = radio->state;
return 0;
}
//=========================================================================
int cariboulite_radio_get_mod_intertupts (cariboulite_radio_state_st* radio, at86rf215_radio_irq_st **irq_table)
{
at86rf215_irq_st irq = {0};
at86rf215_get_irqs(&radio->cariboulite_sys->modem, &irq, 0);
memcpy (&radio->interrupts,
(radio->type == cariboulite_channel_s1g) ? (&irq.radio09) : (&irq.radio24),
sizeof(at86rf215_radio_irq_st));
if (irq_table) *irq_table = &radio->interrupts;
return 0;
}
//=========================================================================
int cariboulite_radio_set_rx_gain_control(cariboulite_radio_state_st* radio,
bool rx_agc_on,
int rx_gain_value_db)
{
int control_gain_val = (int)roundf((float)(rx_gain_value_db) / 3.0f);
if (control_gain_val < 0) control_gain_val = 0;
if (control_gain_val > 23) control_gain_val = 23;
at86rf215_radio_agc_ctrl_st rx_gain_control =
{
.agc_measure_source_not_filtered = 1,
.avg = at86rf215_radio_agc_averaging_32,
.reset_cmd = 0,
.freeze_cmd = 0,
.enable_cmd = rx_agc_on,
.att = at86rf215_radio_agc_relative_atten_21_db,
.gain_control_word = control_gain_val,
};
at86rf215_radio_setup_agc(&radio->cariboulite_sys->modem, GET_CH(radio->type), &rx_gain_control);
radio->rx_agc_on = rx_agc_on;
radio->rx_gain_value_db = rx_gain_value_db;
return 0;
}
//=========================================================================
int cariboulite_radio_get_rx_gain_control(cariboulite_radio_state_st* radio,
bool *rx_agc_on,
int *rx_gain_value_db)
{
at86rf215_radio_agc_ctrl_st agc_ctrl = {0};
at86rf215_radio_get_agc(&radio->cariboulite_sys->modem, GET_CH(radio->type), &agc_ctrl);
radio->rx_agc_on = agc_ctrl.enable_cmd;
radio->rx_gain_value_db = agc_ctrl.gain_control_word * 3;
if (rx_agc_on) *rx_agc_on = radio->rx_agc_on;
if (rx_gain_value_db) *rx_gain_value_db = radio->rx_gain_value_db;
return 0;
}
//=========================================================================
int cariboulite_radio_get_rx_gain_limits(cariboulite_radio_state_st* radio,
int *rx_min_gain_value_db,
int *rx_max_gain_value_db,
int *rx_gain_value_resolution_db)
{
if (rx_min_gain_value_db) *rx_min_gain_value_db = 0;
if (rx_max_gain_value_db) *rx_max_gain_value_db = 23*3;
if (rx_gain_value_resolution_db) *rx_gain_value_resolution_db = 3;
return 0;
}
//=========================================================================
int cariboulite_radio_set_rx_bandwidth(cariboulite_radio_state_st* radio,
at86rf215_radio_rx_bw_en rx_bw)
{
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)
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;
else if (rx_bw >= at86rf215_radio_rx_bw_BW800KHZ_IF1000KHZ && rx_bw <= at86rf215_radio_rx_bw_BW1000KHZ_IF1000KHZ)
fcut = at86rf215_radio_rx_f_cut_0_5_half_fs;
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;
radio->rx_fcut = fcut;
at86rf215_radio_set_rx_bw_samp_st cfg =
{
.inverter_sign_if = 0,
.shift_if_freq = 1, // A value of one configures the receiver to shift the IF frequency
// by factor of 1.25. This is useful to place the image frequency according
// to channel scheme. This increases the IF frequency to max 2.5MHz
// thus places the internal LO fasr away from the signal => lower noise
.bw = rx_bw,
.fcut = radio->rx_fcut, // keep the same
.fs = radio->rx_fs, // keep the same
};
at86rf215_radio_set_rx_bandwidth_sampling(&radio->cariboulite_sys->modem, GET_CH(radio->type), &cfg);
radio->rx_bw = rx_bw;
return 0;
}
//=========================================================================
int cariboulite_radio_get_rx_bandwidth(cariboulite_radio_state_st* radio,
at86rf215_radio_rx_bw_en *rx_bw)
{
at86rf215_radio_set_rx_bw_samp_st cfg = {0};
at86rf215_radio_get_rx_bandwidth_sampling(&radio->cariboulite_sys->modem, GET_CH(radio->type), &cfg);
radio->rx_bw = cfg.bw;
radio->rx_fcut = cfg.fcut;
radio->rx_fs = cfg.fs;
if (rx_bw) *rx_bw = radio->rx_bw;
return 0;
}
//=========================================================================
int cariboulite_radio_set_rx_samp_cutoff(cariboulite_radio_state_st* radio,
at86rf215_radio_sample_rate_en rx_sample_rate,
at86rf215_radio_f_cut_en rx_cutoff)
{
at86rf215_radio_set_rx_bw_samp_st cfg =
{
.inverter_sign_if = 0, // A value of one configures the receiver to implement the inverted-sign
// IF frequency. Use default setting for normal operation
.shift_if_freq = 1, // A value of one configures the receiver to shift the IF frequency
// by factor of 1.25. This is useful to place the image frequency according
// to channel scheme.
.bw = radio->rx_bw, // keep the same
.fcut = rx_cutoff,
.fs = rx_sample_rate,
};
at86rf215_radio_set_rx_bandwidth_sampling(&radio->cariboulite_sys->modem, GET_CH(radio->type), &cfg);
radio->rx_fs = rx_sample_rate;
radio->rx_fcut = rx_cutoff;
return 0;
}
//=========================================================================
int cariboulite_radio_get_rx_samp_cutoff(cariboulite_radio_state_st* radio,
at86rf215_radio_sample_rate_en *rx_sample_rate,
at86rf215_radio_f_cut_en *rx_cutoff)
{
cariboulite_radio_get_rx_bandwidth(radio, NULL);
if (rx_sample_rate) *rx_sample_rate = radio->rx_fs;
if (rx_cutoff) *rx_cutoff = radio->rx_fcut;
return 0;
}
//=========================================================================
int cariboulite_radio_set_tx_power(cariboulite_radio_state_st* radio,
int tx_power_dbm)
{
if (tx_power_dbm < -18) tx_power_dbm = -18;
if (tx_power_dbm > 13) tx_power_dbm = 13;
int tx_power_ctrl = 18 + tx_power_dbm;
at86rf215_radio_tx_ctrl_st cfg =
{
.pa_ramping_time = at86rf215_radio_tx_pa_ramp_16usec,
.current_reduction = at86rf215_radio_pa_current_reduction_0ma, // we can use this to gain some more
// granularity with the tx gain control
.tx_power = tx_power_ctrl,
.analog_bw = radio->tx_bw, // same as before
.digital_bw = radio->tx_fcut, // same as before
.fs = radio->tx_fs, // same as before
.direct_modulation = 0,
};
at86rf215_radio_setup_tx_ctrl(&radio->cariboulite_sys->modem, GET_CH(radio->type), &cfg);
radio->tx_power = tx_power_dbm;
return 0;
}
//=========================================================================
int cariboulite_radio_get_tx_power(cariboulite_radio_state_st* radio,
int *tx_power_dbm)
{
at86rf215_radio_tx_ctrl_st cfg = {0};
at86rf215_radio_get_tx_ctrl(&radio->cariboulite_sys->modem, GET_CH(radio->type), &cfg);
radio->tx_power = cfg.tx_power - 18;
radio->tx_bw = cfg.analog_bw;
radio->tx_fcut = cfg.digital_bw;
radio->tx_fs = cfg.fs;
if (tx_power_dbm) *tx_power_dbm = radio->tx_power;
return 0;
}
//=========================================================================
int cariboulite_radio_set_tx_bandwidth(cariboulite_radio_state_st* radio,
at86rf215_radio_tx_cut_off_en tx_bw)
{
at86rf215_radio_tx_ctrl_st cfg =
{
.pa_ramping_time = at86rf215_radio_tx_pa_ramp_16usec,
.current_reduction = at86rf215_radio_pa_current_reduction_0ma, // we can use this to gain some more
// granularity with the tx gain control
.tx_power = 18 + radio->tx_power, // same as before
.analog_bw = tx_bw,
.digital_bw = radio->tx_fcut, // same as before
.fs = radio->tx_fs, // same as before
.direct_modulation = 0,
};
at86rf215_radio_setup_tx_ctrl(&radio->cariboulite_sys->modem, GET_CH(radio->type), &cfg);
radio->tx_bw = tx_bw;
return 0;
}
//=========================================================================
int cariboulite_radio_get_tx_bandwidth(cariboulite_radio_state_st* radio,
at86rf215_radio_tx_cut_off_en *tx_bw)
{
cariboulite_radio_get_tx_power(radio, NULL);
if (tx_bw) *tx_bw = radio->tx_bw;
return 0;
}
//=========================================================================
int cariboulite_radio_set_tx_samp_cutoff(cariboulite_radio_state_st* radio,
at86rf215_radio_sample_rate_en tx_sample_rate,
at86rf215_radio_f_cut_en tx_cutoff)
{
at86rf215_radio_tx_ctrl_st cfg =
{
.pa_ramping_time = at86rf215_radio_tx_pa_ramp_16usec,
.current_reduction = at86rf215_radio_pa_current_reduction_0ma, // we can use this to gain some more
// granularity with the tx gain control
.tx_power = 18 + radio->tx_power, // same as before
.analog_bw = radio->tx_bw, // same as before
.digital_bw = tx_cutoff,
.fs = tx_sample_rate,
.direct_modulation = 0,
};
at86rf215_radio_setup_tx_ctrl(&radio->cariboulite_sys->modem, GET_CH(radio->type), &cfg);
radio->tx_fcut = tx_cutoff;
radio->tx_fs = tx_sample_rate;
return 0;
}
//=========================================================================
int cariboulite_radio_get_tx_samp_cutoff(cariboulite_radio_state_st* radio,
at86rf215_radio_sample_rate_en *tx_sample_rate,
at86rf215_radio_f_cut_en *tx_cutoff)
{
cariboulite_radio_get_tx_power(radio, NULL);
if (tx_sample_rate) *tx_sample_rate = radio->tx_fs;
if (tx_cutoff) *tx_cutoff = radio->tx_fcut;
return 0;
}
//=========================================================================
int cariboulite_radio_get_rssi(cariboulite_radio_state_st* radio, float *rssi_dbm)
{
float rssi = at86rf215_radio_get_rssi_dbm(&radio->cariboulite_sys->modem, GET_CH(radio->type));
if (rssi >= -127.0 && rssi <= 4) // register only valid values
{
radio->rx_rssi = rssi;
if (rssi_dbm) *rssi_dbm = rssi;
return 0;
}
// if error maintain the older number and return error
if (rssi_dbm) *rssi_dbm = radio->rx_rssi;
return -1;
}
//=========================================================================
int cariboulite_radio_get_energy_det(cariboulite_radio_state_st* radio, float *energy_det_val)
{
at86rf215_radio_energy_detection_st det = {0};
at86rf215_radio_get_energy_detection(&radio->cariboulite_sys->modem, GET_CH(radio->type), &det);
if (det.energy_detection_value >= -127.0 && det.energy_detection_value <= 4) // register only valid values
{
radio->rx_energy_detection_value = det.energy_detection_value;
if (energy_det_val) *energy_det_val = radio->rx_energy_detection_value;
return 0;
}
if (energy_det_val) *energy_det_val = radio->rx_energy_detection_value;
return -1;
}
//======================================================================
typedef struct {
int bit_count; /* number of bits of entropy in data */
int byte_count; /* number of bytes of data in array */
unsigned char buf[1];
} entropy_t;
static int add_entropy(uint8_t byte)
{
int rand_fid = open("/dev/urandom", O_RDWR);
if (rand_fid != 0)
{
// error opening device
ZF_LOGE("Opening /dev/urandom device file failed");
return -1;
}
entropy_t ent = {
.bit_count = 8,
.byte_count = 1,
.buf = {byte},
};
if (ioctl(rand_fid, RNDADDENTROPY, &ent) != 0)
{
ZF_LOGE("IOCTL to /dev/urandom device file failed");
}
if (close(rand_fid) !=0 )
{
ZF_LOGE("Closing /dev/urandom device file failed");
return -1;
}
return 0;
}
//=========================================================================
int cariboulite_radio_get_rand_val(cariboulite_radio_state_st* radio, uint8_t *rnd)
{
radio->random_value = at86rf215_radio_get_random_value(&radio->cariboulite_sys->modem, GET_CH(radio->type));
if (rnd) *rnd = radio->random_value;
// add the random number to the system entropy. why not :)
add_entropy(radio->random_value);
return 0;
}
//=================================================
// FREQUENCY CONVERSION LOGIC
//=================================================
#define CARIBOULITE_MIN_MIX (1.0e6) // 30
#define CARIBOULITE_MAX_MIX (6000.0e6) // 6000
#define CARIBOULITE_MIN_LO (85.0e6)
#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 (350.0e6) // 389.5e6
#define CARIBOULITE_S1G_MAX1 (510.0e6)
#define CARIBOULITE_S1G_MIN2 (779.0e6)
#define CARIBOULITE_S1G_MAX2 (1020.0e6)
typedef enum
{
conversion_dir_none = 0,
conversion_dir_up = 1,
conversion_dir_down = 2,
} conversion_dir_en;
//=================================================
bool cariboulite_radio_wait_mixer_lock(cariboulite_radio_state_st* radio, int retries)
{
rffc507x_device_status_st stat = {0};
// applicable only to the 6G channel
if (radio->type != cariboulite_channel_6g)
{
return false;
}
int relock_retries = retries;
do
{
rffc507x_readback_status(&radio->cariboulite_sys->mixer, NULL, &stat);
rffc507x_print_stat(&stat);
if (!stat.pll_lock) rffc507x_relock(&radio->cariboulite_sys->mixer);
} while (!stat.pll_lock && relock_retries--);
return stat.pll_lock;
}
//=================================================
bool cariboulite_radio_wait_modem_lock(cariboulite_radio_state_st* radio, int retries)
{
at86rf215_radio_pll_ctrl_st cfg = {0};
int relock_retries = retries;
do
{
at86rf215_radio_get_pll_ctrl(&radio->cariboulite_sys->modem, GET_CH(radio->type), &cfg);
} while (!cfg.pll_locked && relock_retries--);
return cfg.pll_locked;
}
//=================================================
bool cariboulite_radio_wait_for_lock( cariboulite_radio_state_st* radio, bool *mod, bool *mix, int retries)
{
bool mix_lock = true, mod_lock = true;
if (radio->type == cariboulite_channel_6g)
{
mix_lock = cariboulite_radio_wait_mixer_lock(radio, retries);
if (mix) *mix = mix_lock;
}
mod_lock = cariboulite_radio_wait_modem_lock(radio, retries);
if (mod) *mod = mod_lock;
return mix_lock && mod_lock;
}
//=========================================================================
int cariboulite_radio_set_frequency(cariboulite_radio_state_st* radio,
bool break_before_make,
double *freq)
{
double f_rf = *freq;
double modem_act_freq = 0.0;
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;
//--------------------------------------------------------------------------------
// SUB 1GHZ CONFIGURATION
//--------------------------------------------------------------------------------
if (radio->type == cariboulite_channel_s1g)
{
if ( (f_rf >= CARIBOULITE_S1G_MIN1 && f_rf <= CARIBOULITE_S1G_MAX1) ||
(f_rf >= CARIBOULITE_S1G_MIN2 && f_rf <= CARIBOULITE_S1G_MAX2) )
{
// setup modem frequency <= f_rf
if (break_before_make)
{
at86rf215_radio_set_state(&radio->cariboulite_sys->modem,
at86rf215_rf_channel_900mhz,
at86rf215_radio_state_cmd_trx_off);
radio->state = at86rf215_radio_state_cmd_trx_off;
}
modem_act_freq = at86rf215_setup_channel (&radio->cariboulite_sys->modem,
at86rf215_rf_channel_900mhz,
(uint32_t)f_rf);
radio->if_frequency = 0;
radio->lo_pll_locked = 1;
radio->modem_pll_locked = cariboulite_radio_wait_modem_lock(radio, 3);
radio->if_frequency = modem_act_freq;
radio->actual_rf_frequency = radio->if_frequency;
radio->requested_rf_frequency = f_rf;
radio->rf_frequency_error = radio->actual_rf_frequency - radio->requested_rf_frequency;
// return actual frequency
*freq = radio->actual_rf_frequency;
}
else
{
ZF_LOGE("unsupported frequency for S1G channel - %.2f Hz", f_rf);
error = -1;
}
}
//--------------------------------------------------------------------------------
// 30-6GHz CONFIGURATION
//--------------------------------------------------------------------------------
else if (radio->type == cariboulite_channel_6g)
{
// Changing the frequency may sometimes need to break RX / TX
if (break_before_make)
{
// make sure that during the transition the modem is not transmitting and then
// verify that the FE is in low power mode
at86rf215_radio_set_state( &radio->cariboulite_sys->modem,
at86rf215_rf_channel_2400mhz,
at86rf215_radio_state_cmd_trx_off);
radio->state = at86rf215_radio_state_cmd_trx_off;
caribou_fpga_set_io_ctrl_mode (&radio->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);
f_rf_mod_32 *= 32e6;
f_rf_mod_26 *= 26e6;
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 = 26e6 - 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 (radio->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
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 (&radio->cariboulite_sys->modem,
at86rf215_rf_channel_2400mhz,
modem_freq);
// setup mixer LO according to the actual modem frequency
lo_act_freq = rffc507x_set_frequency(&radio->cariboulite_sys->mixer, modem_act_freq - f_rf);
act_freq = modem_act_freq - lo_act_freq;
// setup fpga RFFE <= upconvert (tx / rx)
conversion_direction = conversion_dir_up;
}
//-------------------------------------
else if ( f_rf > CARIBOULITE_2G4_MIN &&
f_rf <= CARIBOULITE_2G4_MAX )
{
cariboulite_setup_ext_ref (radio->cariboulite_sys, cariboulite_ext_ref_off);
// region #2 - bypass mode
// setup modem frequency <= f_rf
modem_act_freq = (double)at86rf215_setup_channel (&radio->cariboulite_sys->modem,
at86rf215_rf_channel_2400mhz,
(uint32_t)f_rf);
lo_act_freq = 0;
act_freq = modem_act_freq;
conversion_direction = conversion_dir_none;
}
//-------------------------------------
else if ( f_rf > (CARIBOULITE_2G4_MAX) &&
f_rf <= CARIBOULITE_MAX_MIX )
{
// region #3 - DOWN-CONVERSION
// setup modem frequency <= CARIBOULITE_2G4_MIN
modem_act_freq = (double)at86rf215_setup_channel (&radio->cariboulite_sys->modem,
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(&radio->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;
}
//-------------------------------------
else
{
ZF_LOGE("unsupported frequency for 6GHz channel - %.2f Hz", f_rf);
error = -1;
}
// Setup the frontend
// This step takes the current radio direction of communication
// and the down/up conversion decision made before to setup the RF front-end
switch (conversion_direction)
{
case conversion_dir_up:
if (radio->channel_direction == cariboulite_channel_dir_rx)
{
caribou_fpga_set_io_ctrl_mode (&radio->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_rx_lowpass);
}
else if (radio->channel_direction == cariboulite_channel_dir_tx)
{
caribou_fpga_set_io_ctrl_mode (&radio->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_tx_lowpass);
}
break;
case conversion_dir_none:
caribou_fpga_set_io_ctrl_mode (&radio->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_bypass);
break;
case conversion_dir_down:
if (radio->channel_direction == cariboulite_channel_dir_rx)
{
caribou_fpga_set_io_ctrl_mode (&radio->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_rx_hipass);
}
else if (radio->channel_direction == cariboulite_channel_dir_tx)
{
caribou_fpga_set_io_ctrl_mode (&radio->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_tx_hipass);
}
break;
default: break;
}
// Make sure the LO and the IF PLLs are locked
at86rf215_radio_set_state( &radio->cariboulite_sys->modem,
GET_CH(radio->type),
at86rf215_radio_state_cmd_tx_prep);
radio->state = at86rf215_radio_state_cmd_tx_prep;
if (!cariboulite_radio_wait_for_lock(radio, &radio->modem_pll_locked,
lo_act_freq > CARIBOULITE_MIN_LO ? &radio->lo_pll_locked : NULL,
100))
{
if (!radio->lo_pll_locked) ZF_LOGE("PLL MIXER failed to lock LO frequency (%.2f Hz)", lo_act_freq);
if (!radio->modem_pll_locked) ZF_LOGE("PLL MODEM failed to lock IF frequency (%.2f Hz)", modem_act_freq);
error = 1;
}
// Update the actual frequencies
radio->lo_frequency = lo_act_freq;
radio->if_frequency = modem_act_freq;
radio->actual_rf_frequency = act_freq;
radio->requested_rf_frequency = f_rf;
radio->rf_frequency_error = radio->actual_rf_frequency - radio->requested_rf_frequency;
if (freq) *freq = act_freq;
// activate the channel according to the new configuration
cariboulite_radio_activate_channel(radio, 1);
}
if (error >= 0)
{
ZF_LOGD("Frequency setting CH: %d, Wanted: %.2f Hz, Set: %.2f Hz (MOD: %.2f, MIX: %.2f)",
radio->type, f_rf, act_freq, modem_act_freq, lo_act_freq);
}
return -error;
}
//=========================================================================
int cariboulite_radio_get_frequency(cariboulite_radio_state_st* radio,
double *freq, double *lo, double* i_f)
{
if (freq) *freq = radio->actual_rf_frequency;
if (lo) *lo = radio->lo_frequency;
if (i_f) *i_f = radio->if_frequency;
}
//=========================================================================
int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
bool active)
{
ZF_LOGD("Activating channel %d, dir = %s, active = %d", radio->type, radio->channel_direction==cariboulite_channel_dir_rx?"RX":"TX", active);
// if the channel state is active, turn it off before reactivating
if (radio->state != at86rf215_radio_state_cmd_tx_prep)
{
at86rf215_radio_set_state( &radio->cariboulite_sys->modem,
GET_CH(radio->type),
at86rf215_radio_state_cmd_tx_prep);
radio->state = at86rf215_radio_state_cmd_tx_prep;
ZF_LOGD("Setup Modem state tx_prep");
}
if (!active)
{
at86rf215_radio_set_state( &radio->cariboulite_sys->modem,
GET_CH(radio->type),
at86rf215_radio_state_cmd_trx_off);
radio->state = at86rf215_radio_state_cmd_trx_off;
ZF_LOGD("Setup Modem state trx_off");
return 0;
}
// Activate the channel according to the configurations
// RX on both channels looks the same
if (radio->channel_direction == cariboulite_channel_dir_rx)
{
at86rf215_radio_set_state( &radio->cariboulite_sys->modem,
GET_CH(radio->type),
at86rf215_radio_state_cmd_rx);
ZF_LOGD("Setup Modem state cmd_rx");
}
else if (radio->channel_direction == cariboulite_channel_dir_tx)
{
// if its an LO frequency output from the mixer - no need for modem output
// LO applicable only to the channel with the mixer
if (radio->lo_output && radio->type == cariboulite_channel_6g)
{
// here we need to configure lo bypass on the mixer
rffc507x_output_lo(&radio->cariboulite_sys->mixer, 1);
}
// otherwise we need the modem
else
{
// make sure the mixer doesn't bypass the lo
rffc507x_output_lo(&radio->cariboulite_sys->mixer, 0);
cariboulite_radio_set_tx_bandwidth(radio, radio->cw_output?at86rf215_radio_tx_cut_off_80khz:radio->tx_bw);
// CW output - constant I/Q values override
at86rf215_radio_set_tx_dac_input_iq(&radio->cariboulite_sys->modem,
GET_CH(radio->type),
radio->cw_output, 0x7E,
radio->cw_output, 0x3F);
// transition to state TX
at86rf215_radio_set_state(&radio->cariboulite_sys->modem,
GET_CH(radio->type),
at86rf215_radio_state_cmd_tx);
}
}
return 0;
}
//=========================================================================
int cariboulite_radio_set_cw_outputs(cariboulite_radio_state_st* radio,
bool lo_out, bool cw_out)
{
if (radio->lo_output && radio->type == cariboulite_channel_6g)
{
radio->lo_output = lo_out;
}
else
{
radio->lo_output = false;
}
radio->cw_output = cw_out;
if (cw_out)
{
radio->channel_direction = cariboulite_channel_dir_tx;
}
else
{
radio->channel_direction = cariboulite_channel_dir_rx;
}
return 0;
}
//=========================================================================
int cariboulite_radio_get_cw_outputs(cariboulite_radio_state_st* radio,
bool *lo_out, bool *cw_out)
{
if (lo_out) *lo_out = radio->lo_output;
if (cw_out) *cw_out = radio->cw_output;
return 0;
}
//=========================================================================
int cariboulite_radio_create_smi_stream(cariboulite_radio_state_st* radio,
cariboulite_channel_dir_en dir,
void* context)
{
caribou_smi_channel_en ch = GET_SMI_CH(radio->type);
caribou_smi_stream_type_en type = GET_SMI_DIR(dir);
int stream_id = caribou_smi_setup_stream(&radio->cariboulite_sys->smi,
type,
ch,
caribou_smi_data_event,
context);
// store the stream id's
if (type == caribou_smi_stream_type_read)
{
radio->rx_stream_id = stream_id;
}
else if (type == caribou_smi_stream_type_write)
{
radio->tx_stream_id = stream_id;
}
return stream_id;
}
//=========================================================================
int cariboulite_radio_destroy_smi_stream(cariboulite_radio_state_st* radio,
cariboulite_channel_dir_en dir)
{
int stream_id = (dir == cariboulite_channel_dir_rx) ? radio->rx_stream_id : radio->tx_stream_id;
if (stream_id == -1)
{
ZF_LOGE("The specified channel (%d) doesn't have open stream of type %d", radio->type, dir);
return -1;
}
return caribou_smi_destroy_stream(&radio->cariboulite_sys->smi, stream_id);
}
//=========================================================================
int cariboulite_radio_run_pause_stream(cariboulite_radio_state_st* radio,
cariboulite_channel_dir_en dir,
bool run)
{
int stream_id = (dir == cariboulite_channel_dir_rx) ? radio->rx_stream_id : radio->tx_stream_id;
if (stream_id == -1)
{
ZF_LOGE("The specified channel (%d) doesn't have open stream of type %d", radio->type, dir);
return -1;
}
return caribou_smi_run_pause_stream (&radio->cariboulite_sys->smi, stream_id, run);
}

Wyświetl plik

@ -0,0 +1,191 @@
#ifndef __CARIBOULABS_RADIO_H__
#define __CARIBOULABS_RADIO_H__
#ifdef __cplusplus
extern "C" {
#endif
#include "cariboulite_config/cariboulite_config.h"
#include "at86rf215/at86rf215.h"
typedef enum
{
cariboulite_channel_dir_rx = 0,
cariboulite_channel_dir_tx = 1,
} cariboulite_channel_dir_en;
typedef enum
{
cariboulite_channel_s1g = 0,
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;
cariboulite_channel_dir_en channel_direction;
cariboulite_channel_en type;
bool active;
bool cw_output;
bool lo_output;
// MODEM STATES
at86rf215_radio_state_cmd_en state;
at86rf215_radio_irq_st interrupts;
bool rx_agc_on;
int rx_gain_value_db;
at86rf215_radio_rx_bw_en rx_bw;
at86rf215_radio_f_cut_en rx_fcut;
at86rf215_radio_sample_rate_en rx_fs;
int tx_power;
at86rf215_radio_tx_cut_off_en tx_bw;
at86rf215_radio_f_cut_en tx_fcut;
at86rf215_radio_sample_rate_en tx_fs;
// at86rf215_radio_energy_detection_st rx_energy_detection;
float rx_energy_detection_value;
float rx_rssi;
// FREQUENCY
bool modem_pll_locked;
bool lo_pll_locked;
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;
int tx_stream_id;
// OTHERS
uint8_t random_value;
float rx_thermal_noise_floor;
// CALIBRATION
int num_of_rx_cal_points;
int num_of_tx_cal_points;
float rx_power_gain_calibration[6001];
float tx_power_gain_calibration[6001];
} cariboulite_radio_state_st;
void cariboulite_radio_init(cariboulite_radio_state_st* radio, cariboulite_st *sys, cariboulite_channel_en type);
int cariboulite_radio_dispose(cariboulite_radio_state_st* radio);
int cariboulite_radio_sync_information(cariboulite_radio_state_st* radio);
int cariboulite_radio_get_mod_state (cariboulite_radio_state_st* radio, at86rf215_radio_state_cmd_en *state);
int cariboulite_radio_get_mod_intertupts (cariboulite_radio_state_st* radio, at86rf215_radio_irq_st **irq_table);
int cariboulite_radio_set_rx_gain_control(cariboulite_radio_state_st* radio,
bool rx_agc_on,
int rx_gain_value_db);
int cariboulite_radio_get_rx_gain_control(cariboulite_radio_state_st* radio,
bool *rx_agc_on,
int *rx_gain_value_db);
int cariboulite_radio_get_rx_gain_limits(cariboulite_radio_state_st* radio,
int *rx_min_gain_value_db,
int *rx_max_gain_value_db,
int *rx_gain_value_resolution_db);
int cariboulite_radio_set_rx_bandwidth(cariboulite_radio_state_st* radio,
at86rf215_radio_rx_bw_en rx_bw);
int cariboulite_radio_get_rx_bandwidth(cariboulite_radio_state_st* radio,
at86rf215_radio_rx_bw_en *rx_bw);
int cariboulite_radio_set_rx_samp_cutoff(cariboulite_radio_state_st* radio,
at86rf215_radio_sample_rate_en rx_sample_rate,
at86rf215_radio_f_cut_en rx_cutoff);
int cariboulite_radio_get_rx_samp_cutoff(cariboulite_radio_state_st* radio,
at86rf215_radio_sample_rate_en *rx_sample_rate,
at86rf215_radio_f_cut_en *rx_cutoff);
int cariboulite_radio_set_tx_power(cariboulite_radio_state_st* radio,
int tx_power_dbm);
int cariboulite_radio_get_tx_power(cariboulite_radio_state_st* radio,
int *tx_power_dbm);
int cariboulite_radio_set_tx_bandwidth(cariboulite_radio_state_st* radio,
at86rf215_radio_tx_cut_off_en tx_bw);
int cariboulite_radio_get_tx_bandwidth(cariboulite_radio_state_st* radio,
at86rf215_radio_tx_cut_off_en *tx_bw);
int cariboulite_radio_set_tx_samp_cutoff(cariboulite_radio_state_st* radio,
at86rf215_radio_sample_rate_en tx_sample_rate,
at86rf215_radio_f_cut_en tx_cutoff);
int cariboulite_radio_get_tx_samp_cutoff(cariboulite_radio_state_st* radio,
at86rf215_radio_sample_rate_en *tx_sample_rate,
at86rf215_radio_f_cut_en *tx_cutoff);
int cariboulite_radio_get_rssi(cariboulite_radio_state_st* radio, float *rssi_dbm);
int cariboulite_radio_get_energy_det(cariboulite_radio_state_st* radio, float *energy_det_val);
int cariboulite_radio_get_rand_val(cariboulite_radio_state_st* radio, uint8_t *rnd);
bool cariboulite_radio_wait_mixer_lock(cariboulite_radio_state_st* radio, int retries);
bool cariboulite_radio_wait_modem_lock(cariboulite_radio_state_st* radio, int retries);
int cariboulite_radio_set_frequency(cariboulite_radio_state_st* radio,
bool break_before_make,
double *freq);
int cariboulite_radio_get_frequency(cariboulite_radio_state_st* radio,
double *freq, double *lo, double* i_f);
int cariboulite_radio_activate_channel(cariboulite_radio_state_st* radio,
bool active);
int cariboulite_radio_set_cw_outputs(cariboulite_radio_state_st* radio,
bool lo_out, bool cw_out);
int cariboulite_radio_get_cw_outputs(cariboulite_radio_state_st* radio,
bool *lo_out, bool *cw_out);
int cariboulite_radio_create_smi_stream(cariboulite_radio_state_st* radio,
cariboulite_channel_dir_en dir,
void* context);
int cariboulite_radio_destroy_smi_stream(cariboulite_radio_state_st* radio,
cariboulite_channel_dir_en dir);
int cariboulite_radio_run_pause_stream(cariboulite_radio_state_st* radio,
cariboulite_channel_dir_en dir,
bool run);
#ifdef __cplusplus
}
#endif
#endif // __CARIBOULABS_RADIO_H__

Wyświetl plik

@ -19,43 +19,6 @@
#define GET_RADIO_PTR(radio,chan) ((chan)==cariboulite_channel_s1g?&((radio)->radio_sub1g):&((radio)->radio_6g))
#define GET_CH(rad_ch) ((rad_ch)==cariboulite_channel_s1g?at86rf215_rf_channel_900mhz:at86rf215_rf_channel_2400mhz)
//======================================================================
typedef struct {
int bit_count; /* number of bits of entropy in data */
int byte_count; /* number of bytes of data in array */
unsigned char buf[1];
} entropy_t;
static int add_entropy(uint8_t byte)
{
int rand_fid = open("/dev/urandom", O_RDWR);
if (rand_fid != 0)
{
// error opening device
ZF_LOGE("Opening /dev/urandom device file failed");
return -1;
}
entropy_t ent = {
.bit_count = 8,
.byte_count = 1,
.buf = {byte},
};
if (ioctl(rand_fid, RNDADDENTROPY, &ent) != 0)
{
ZF_LOGE("IOCTL to /dev/urandom device file failed");
}
if (close(rand_fid) !=0 )
{
ZF_LOGE("Closing /dev/urandom device file failed");
return -1;
}
return 0;
}
//======================================================================
int cariboulite_init_radios(cariboulite_radios_st* radios, cariboulite_st *sys)
@ -63,96 +26,27 @@ int cariboulite_init_radios(cariboulite_radios_st* radios, cariboulite_st *sys)
memset (radios, 0, sizeof(cariboulite_radios_st));
// Sub-1GHz
radios->radio_sub1g.cariboulite_sys = sys;
radios->radio_sub1g.active = true;
radios->radio_sub1g.channel_direction = cariboulite_channel_dir_rx;
radios->radio_sub1g.type = cariboulite_channel_s1g;
radios->radio_sub1g.cw_output = false;
radios->radio_sub1g.lo_output = false;
radios->radio_sub1g.rx_stream_id = -1;
radios->radio_sub1g.tx_stream_id = -1;
cariboulite_radio_init(&radios->radio_sub1g, sys, cariboulite_channel_s1g);
// Wide band channel
radios->radio_6g.cariboulite_sys = sys;
radios->radio_6g.active = true;
radios->radio_6g.channel_direction = cariboulite_channel_dir_rx;
radios->radio_6g.type = cariboulite_channel_6g;
radios->radio_6g.cw_output = false;
radios->radio_6g.lo_output = false;
radios->radio_6g.rx_stream_id = -1;
radios->radio_6g.tx_stream_id = -1;
cariboulite_radio_init(&radios->radio_6g, sys, cariboulite_channel_6g);
cariboulite_sync_radio_information(radios);
cariboulite_radio_sync_information(&radios->radio_sub1g);
cariboulite_radio_sync_information(&radios->radio_6g);
}
//======================================================================
int cariboulite_dispose_radios(cariboulite_radios_st* radios)
{
radios->radio_sub1g.active = false;
radios->radio_6g.active = false;
// If streams are active - destroy them
if (radios->radio_sub1g.rx_stream_id != -1)
{
caribou_smi_destroy_stream(&radios->radio_sub1g.cariboulite_sys->smi, radios->radio_sub1g.rx_stream_id);
radios->radio_sub1g.rx_stream_id = -1;
}
if (radios->radio_sub1g.tx_stream_id != -1)
{
caribou_smi_destroy_stream(&radios->radio_sub1g.cariboulite_sys->smi, radios->radio_sub1g.tx_stream_id);
radios->radio_sub1g.tx_stream_id = -1;
}
if (radios->radio_6g.rx_stream_id != -1)
{
caribou_smi_destroy_stream(&radios->radio_6g.cariboulite_sys->smi, radios->radio_sub1g.rx_stream_id);
radios->radio_6g.rx_stream_id = -1;
}
if (radios->radio_6g.tx_stream_id != -1)
{
caribou_smi_destroy_stream(&radios->radio_6g.cariboulite_sys->smi, radios->radio_sub1g.tx_stream_id);
radios->radio_6g.tx_stream_id = -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);
at86rf215_radio_set_state( &rad_s1g->cariboulite_sys->modem,
GET_CH(cariboulite_channel_s1g),
at86rf215_radio_state_cmd_trx_off);
rad_s1g->state = at86rf215_radio_state_cmd_trx_off;
at86rf215_radio_set_state( &rad_6g->cariboulite_sys->modem,
GET_CH(cariboulite_channel_6g),
at86rf215_radio_state_cmd_trx_off);
rad_6g->state = at86rf215_radio_state_cmd_trx_off;
caribou_fpga_set_io_ctrl_mode (&rad_6g->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_low_power);
cariboulite_radio_dispose(&radios->radio_sub1g);
cariboulite_radio_dispose(&radios->radio_6g);
}
//======================================================================
int cariboulite_sync_radio_information(cariboulite_radios_st* radios)
{
cariboulite_get_mod_state (radios, cariboulite_channel_s1g, NULL);
cariboulite_get_mod_state (radios, cariboulite_channel_6g, NULL);
cariboulite_get_rx_gain_control(radios, cariboulite_channel_s1g, NULL, NULL);
cariboulite_get_rx_gain_control(radios, cariboulite_channel_6g, NULL, NULL);
cariboulite_get_rx_bandwidth(radios, cariboulite_channel_s1g, NULL);
cariboulite_get_rx_bandwidth(radios, cariboulite_channel_6g, NULL);
cariboulite_get_tx_power(radios, cariboulite_channel_s1g, NULL);
cariboulite_get_tx_power(radios, cariboulite_channel_6g, NULL);
cariboulite_get_rssi(radios, cariboulite_channel_s1g, NULL);
cariboulite_get_rssi(radios, cariboulite_channel_6g, NULL);
cariboulite_get_energy_det(radios, cariboulite_channel_s1g, NULL);
cariboulite_get_energy_det(radios, cariboulite_channel_6g, NULL);
cariboulite_radio_sync_information(&radios->radio_sub1g);
cariboulite_radio_sync_information(&radios->radio_6g);
}
//======================================================================
@ -160,35 +54,15 @@ int cariboulite_get_mod_state ( cariboulite_radios_st* radios,
cariboulite_channel_en channel,
at86rf215_radio_state_cmd_en *state)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
rad->state = at86rf215_radio_get_state(&rad->cariboulite_sys->modem, GET_CH(channel));
if (state) *state = rad->state;
return 0;
return cariboulite_radio_get_mod_state (GET_RADIO_PTR(radios,channel), state);
}
//======================================================================
int cariboulite_get_mod_intertupts (cariboulite_radios_st* radios,
cariboulite_channel_en channel,
at86rf215_radio_irq_st **irq_table)
{
at86rf215_irq_st irq = {0};
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_get_irqs(&rad->cariboulite_sys->modem, &irq, 0);
if (channel == cariboulite_channel_s1g)
{
memcpy (&rad->interrupts, &irq.radio09, sizeof(at86rf215_radio_irq_st));
if (irq_table) *irq_table = &irq.radio09;
}
else
{
memcpy (&rad->interrupts, &irq.radio24, sizeof(at86rf215_radio_irq_st));
if (irq_table) *irq_table = &irq.radio24;
}
return 0;
return cariboulite_radio_get_mod_intertupts (GET_RADIO_PTR(radios,channel), irq_table);
}
//======================================================================
@ -197,27 +71,9 @@ int cariboulite_set_rx_gain_control(cariboulite_radios_st* radios,
bool rx_agc_on,
int rx_gain_value_db)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
int control_gain_val = (int)roundf((float)(rx_gain_value_db) / 3.0f);
if (control_gain_val < 0) control_gain_val = 0;
if (control_gain_val > 23) control_gain_val = 23;
at86rf215_radio_agc_ctrl_st rx_gain_control =
{
.agc_measure_source_not_filtered = 1,
.avg = at86rf215_radio_agc_averaging_32,
.reset_cmd = 0,
.freeze_cmd = 0,
.enable_cmd = rx_agc_on,
.att = at86rf215_radio_agc_relative_atten_21_db,
.gain_control_word = control_gain_val,
};
at86rf215_radio_setup_agc(&rad->cariboulite_sys->modem, GET_CH(channel), &rx_gain_control);
rad->rx_agc_on = rx_agc_on;
rad->rx_gain_value_db = rx_gain_value_db;
return 0;
return cariboulite_radio_set_rx_gain_control(GET_RADIO_PTR(radios,channel),
rx_agc_on,
rx_gain_value_db);
}
//======================================================================
@ -226,15 +82,9 @@ int cariboulite_get_rx_gain_control(cariboulite_radios_st* radios,
bool *rx_agc_on,
int *rx_gain_value_db)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_radio_agc_ctrl_st agc_ctrl = {0};
at86rf215_radio_get_agc(&rad->cariboulite_sys->modem, GET_CH(channel), &agc_ctrl);
rad->rx_agc_on = agc_ctrl.enable_cmd;
rad->rx_gain_value_db = agc_ctrl.gain_control_word * 3;
if (rx_agc_on) *rx_agc_on = rad->rx_agc_on;
if (rx_gain_value_db) *rx_gain_value_db = rad->rx_gain_value_db;
return 0;
return cariboulite_radio_get_rx_gain_control(GET_RADIO_PTR(radios,channel),
rx_agc_on,
rx_gain_value_db);
}
//======================================================================
@ -244,10 +94,10 @@ int cariboulite_get_rx_gain_limits(cariboulite_radios_st* radios,
int *rx_max_gain_value_db,
int *rx_gain_value_resolution_db)
{
if (rx_min_gain_value_db) *rx_min_gain_value_db = 0;
if (rx_max_gain_value_db) *rx_max_gain_value_db = 23*3;
if (rx_gain_value_resolution_db) *rx_gain_value_resolution_db = 3;
return 0;
return cariboulite_radio_get_rx_gain_limits(NULL,
rx_min_gain_value_db,
rx_max_gain_value_db,
rx_gain_value_resolution_db);
}
//======================================================================
@ -255,37 +105,8 @@ int cariboulite_set_rx_bandwidth(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
at86rf215_radio_rx_bw_en rx_bw)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_radio_f_cut_en fcut = at86rf215_radio_rx_f_cut_half_fs;
return cariboulite_radio_set_rx_bandwidth(GET_RADIO_PTR(radios,channel), rx_bw);
// Automatically calculate the digital f_cut
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;
else if (rx_bw >= at86rf215_radio_rx_bw_BW800KHZ_IF1000KHZ && rx_bw <= at86rf215_radio_rx_bw_BW1000KHZ_IF1000KHZ)
fcut = at86rf215_radio_rx_f_cut_0_5_half_fs;
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;
rad->rx_fcut = fcut;
at86rf215_radio_set_rx_bw_samp_st cfg =
{
.inverter_sign_if = 0,
.shift_if_freq = 1, // A value of one configures the receiver to shift the IF frequency
// by factor of 1.25. This is useful to place the image frequency according
// to channel scheme. This increases the IF frequency to max 2.5MHz
// thus places the internal LO fasr away from the signal => lower noise
.bw = rx_bw,
.fcut = rad->rx_fcut, // keep the same
.fs = rad->rx_fs, // keep the same
};
at86rf215_radio_set_rx_bandwidth_sampling(&rad->cariboulite_sys->modem, GET_CH(channel), &cfg);
rad->rx_bw = rx_bw;
return 0;
}
//======================================================================
@ -293,14 +114,7 @@ int cariboulite_get_rx_bandwidth(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
at86rf215_radio_rx_bw_en *rx_bw)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_radio_set_rx_bw_samp_st cfg = {0};
at86rf215_radio_get_rx_bandwidth_sampling(&rad->cariboulite_sys->modem, GET_CH(channel), &cfg);
rad->rx_bw = cfg.bw;
rad->rx_fcut = cfg.fcut;
rad->rx_fs = cfg.fs;
if (rx_bw) *rx_bw = rad->rx_bw;
return 0;
cariboulite_radio_get_rx_bandwidth(GET_RADIO_PTR(radios,channel), rx_bw);
}
//======================================================================
@ -309,23 +123,9 @@ int cariboulite_set_rx_samp_cutoff(cariboulite_radios_st* radios,
at86rf215_radio_sample_rate_en rx_sample_rate,
at86rf215_radio_f_cut_en rx_cutoff)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_radio_set_rx_bw_samp_st cfg =
{
.inverter_sign_if = 0, // A value of one configures the receiver to implement the inverted-sign
// IF frequency. Use default setting for normal operation
.shift_if_freq = 1, // A value of one configures the receiver to shift the IF frequency
// by factor of 1.25. This is useful to place the image frequency according
// to channel scheme.
.bw = rad->rx_bw, // keep the same
.fcut = rx_cutoff,
.fs = rx_sample_rate,
};
at86rf215_radio_set_rx_bandwidth_sampling(&rad->cariboulite_sys->modem, GET_CH(channel), &cfg);
rad->rx_fs = rx_sample_rate;
rad->rx_fcut = rx_cutoff;
return 0;
return cariboulite_radio_set_rx_samp_cutoff(GET_RADIO_PTR(radios,channel),
rx_sample_rate,
rx_cutoff);
}
//======================================================================
@ -334,11 +134,9 @@ int cariboulite_get_rx_samp_cutoff(cariboulite_radios_st* radios,
at86rf215_radio_sample_rate_en *rx_sample_rate,
at86rf215_radio_f_cut_en *rx_cutoff)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
cariboulite_get_rx_bandwidth(radios, channel, NULL);
if (rx_sample_rate) *rx_sample_rate = rad->rx_fs;
if (rx_cutoff) *rx_cutoff = rad->rx_fcut;
return 0;
return cariboulite_radio_get_rx_samp_cutoff(GET_RADIO_PTR(radios,channel),
rx_sample_rate,
rx_cutoff);
}
//======================================================================
@ -346,27 +144,7 @@ int cariboulite_set_tx_power(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
int tx_power_dbm)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
if (tx_power_dbm < -18) tx_power_dbm = -18;
if (tx_power_dbm > 13) tx_power_dbm = 13;
int tx_power_ctrl = 18 + tx_power_dbm;
at86rf215_radio_tx_ctrl_st cfg =
{
.pa_ramping_time = at86rf215_radio_tx_pa_ramp_16usec,
.current_reduction = at86rf215_radio_pa_current_reduction_0ma, // we can use this to gain some more
// granularity with the tx gain control
.tx_power = tx_power_ctrl,
.analog_bw = rad->tx_bw, // same as before
.digital_bw = rad->tx_fcut, // same as before
.fs = rad->tx_fs, // same as before
.direct_modulation = 0,
};
at86rf215_radio_setup_tx_ctrl(&rad->cariboulite_sys->modem, GET_CH(channel), &cfg);
rad->tx_power = tx_power_dbm;
return 0;
return cariboulite_radio_set_tx_power(GET_RADIO_PTR(radios,channel), tx_power_dbm);
}
//======================================================================
@ -374,16 +152,7 @@ int cariboulite_get_tx_power(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
int *tx_power_dbm)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_radio_tx_ctrl_st cfg = {0};
at86rf215_radio_get_tx_ctrl(&rad->cariboulite_sys->modem, GET_CH(channel), &cfg);
rad->tx_power = cfg.tx_power - 18;
rad->tx_bw = cfg.analog_bw;
rad->tx_fcut = cfg.digital_bw;
rad->tx_fs = cfg.fs;
if (tx_power_dbm) *tx_power_dbm = rad->tx_power;
return 0;
return cariboulite_radio_get_tx_power(GET_RADIO_PTR(radios,channel), tx_power_dbm);
}
//======================================================================
@ -391,23 +160,7 @@ int cariboulite_set_tx_bandwidth(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
at86rf215_radio_tx_cut_off_en tx_bw)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_radio_tx_ctrl_st cfg =
{
.pa_ramping_time = at86rf215_radio_tx_pa_ramp_16usec,
.current_reduction = at86rf215_radio_pa_current_reduction_0ma, // we can use this to gain some more
// granularity with the tx gain control
.tx_power = 18 + rad->tx_power, // same as before
.analog_bw = tx_bw,
.digital_bw = rad->tx_fcut, // same as before
.fs = rad->tx_fs, // same as before
.direct_modulation = 0,
};
at86rf215_radio_setup_tx_ctrl(&rad->cariboulite_sys->modem, GET_CH(channel), &cfg);
rad->tx_bw = tx_bw;
return 0;
return cariboulite_radio_set_tx_bandwidth(GET_RADIO_PTR(radios,channel), tx_bw);
}
//======================================================================
@ -415,10 +168,7 @@ int cariboulite_get_tx_bandwidth(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
at86rf215_radio_tx_cut_off_en *tx_bw)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
cariboulite_get_tx_power(radios, channel, NULL);
if (tx_bw) *tx_bw = rad->tx_bw;
return 0;
return cariboulite_radio_get_tx_bandwidth(GET_RADIO_PTR(radios,channel), tx_bw);
}
//======================================================================
@ -427,139 +177,38 @@ int cariboulite_set_tx_samp_cutoff(cariboulite_radios_st* radios,
at86rf215_radio_sample_rate_en tx_sample_rate,
at86rf215_radio_f_cut_en tx_cutoff)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_radio_tx_ctrl_st cfg =
{
.pa_ramping_time = at86rf215_radio_tx_pa_ramp_16usec,
.current_reduction = at86rf215_radio_pa_current_reduction_0ma, // we can use this to gain some more
// granularity with the tx gain control
.tx_power = 18 + rad->tx_power, // same as before
.analog_bw = rad->tx_bw, // same as before
.digital_bw = tx_cutoff,
.fs = tx_sample_rate,
.direct_modulation = 0,
};
at86rf215_radio_setup_tx_ctrl(&rad->cariboulite_sys->modem, GET_CH(channel), &cfg);
rad->tx_fcut = tx_cutoff;
rad->tx_fs = tx_sample_rate;
return 0;
return cariboulite_radio_set_tx_samp_cutoff(GET_RADIO_PTR(radios,channel),
tx_sample_rate,
tx_cutoff);
}
//======================================================================
int cariboulite_get_tx_samp_cutoff(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
at86rf215_radio_sample_rate_en *tx_sample_rate,
at86rf215_radio_f_cut_en *rx_cutoff)
at86rf215_radio_f_cut_en *tx_cutoff)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
cariboulite_get_tx_power(radios, channel, NULL);
if (tx_sample_rate) *tx_sample_rate = rad->tx_fs;
if (rx_cutoff) *rx_cutoff = rad->tx_fcut;
return 0;
return cariboulite_radio_get_tx_samp_cutoff(GET_RADIO_PTR(radios,channel),
tx_sample_rate,
tx_cutoff);
}
//======================================================================
int cariboulite_get_rssi(cariboulite_radios_st* radios, cariboulite_channel_en channel, float *rssi_dbm)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
float rssi = at86rf215_radio_get_rssi_dbm(&rad->cariboulite_sys->modem, GET_CH(channel));
if (rssi >= -127.0 && rssi <= 4) // register only valid values
{
rad->rx_rssi = rssi;
if (rssi_dbm) *rssi_dbm = rssi;
return 0;
}
if (rssi_dbm) *rssi_dbm = rad->rx_rssi;
return -1;
return cariboulite_radio_get_rssi(GET_RADIO_PTR(radios,channel), rssi_dbm);
}
//======================================================================
int cariboulite_get_energy_det(cariboulite_radios_st* radios, cariboulite_channel_en channel, float *energy_det_val)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
at86rf215_radio_energy_detection_st det = {0};
at86rf215_radio_get_energy_detection(&rad->cariboulite_sys->modem, GET_CH(channel), &det);
if (det.energy_detection_value >= -127.0 && det.energy_detection_value <= 4) // register only valid values
{
rad->rx_energy_detection_value = det.energy_detection_value;
if (energy_det_val) *energy_det_val = rad->rx_energy_detection_value;
return 0;
}
if (energy_det_val) *energy_det_val = rad->rx_energy_detection_value;
return -1;
return cariboulite_radio_get_energy_det(GET_RADIO_PTR(radios,channel), energy_det_val);
}
//======================================================================
int cariboulite_get_rand_val(cariboulite_radios_st* radios, cariboulite_channel_en channel, uint8_t *rnd)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
rad->random_value = at86rf215_radio_get_random_value(&rad->cariboulite_sys->modem, GET_CH(channel));
if (rnd) *rnd = rad->random_value;
add_entropy(rad->random_value);
return 0;
}
//=================================================
#define CARIBOULITE_MIN_MIX (1.0e6) // 30
#define CARIBOULITE_MAX_MIX (6000.0e6) // 6000
#define CARIBOULITE_MIN_LO (85.0e6)
#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 (350.0e6)
#define CARIBOULITE_S1G_MAX1 (510.0e6)
#define CARIBOULITE_S1G_MIN2 (779.0e6)
#define CARIBOULITE_S1G_MAX2 (1020.0e6)
typedef enum
{
conversion_dir_none = 0,
conversion_dir_up = 1,
conversion_dir_down = 2,
} conversion_dir_en;
//=================================================
bool cariboulite_wait_for_lock( cariboulite_radio_state_st* rad, bool *mod, bool *mix, int retries)
{
bool mix_lock = true, mod_lock = true;
if (mix)
{
rffc507x_device_status_st stat = {0};
int relock_retries = retries;
do
{
rffc507x_readback_status(&rad->cariboulite_sys->mixer, NULL, &stat);
rffc507x_print_stat(&stat);
if (!stat.pll_lock) rffc507x_relock(&rad->cariboulite_sys->mixer);
} while (!stat.pll_lock && relock_retries--);
*mix = stat.pll_lock;
mix_lock = (bool)stat.pll_lock;
}
if (mod)
{
at86rf215_radio_pll_ctrl_st cfg = {0};
int relock_retries = retries;
do
{
at86rf215_rf_channel_en ch = rad->type == cariboulite_channel_s1g ?
at86rf215_rf_channel_900mhz : at86rf215_rf_channel_2400mhz;
at86rf215_radio_get_pll_ctrl(&rad->cariboulite_sys->modem, ch, &cfg);
} while (!cfg.pll_locked && relock_retries--);
*mod = cfg.pll_locked;
mod_lock = (bool)cfg.pll_locked;
}
return mix_lock && mod_lock;
return cariboulite_radio_get_rand_val(GET_RADIO_PTR(radios,channel), rnd);
}
//=================================================
@ -568,214 +217,9 @@ int cariboulite_set_frequency( cariboulite_radios_st* radios,
bool break_before_make,
double *freq)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
double f_rf = *freq;
double modem_act_freq = 0.0;
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;
//--------------------------------------------------------------------------------
// SUB 1GHZ CONFIGURATION
//--------------------------------------------------------------------------------
if (channel == cariboulite_channel_s1g)
{
if ( (f_rf >= CARIBOULITE_S1G_MIN1 && f_rf <= CARIBOULITE_S1G_MAX1) ||
(f_rf >= CARIBOULITE_S1G_MIN2 && f_rf <= CARIBOULITE_S1G_MAX2) )
{
// setup modem frequency <= f_rf
if (break_before_make)
{
at86rf215_radio_set_state( &rad->cariboulite_sys->modem,
at86rf215_rf_channel_900mhz,
at86rf215_radio_state_cmd_trx_off);
rad->state = at86rf215_radio_state_cmd_trx_off;
}
modem_act_freq = at86rf215_setup_channel (&rad->cariboulite_sys->modem,
at86rf215_rf_channel_900mhz,
(uint32_t)f_rf);
at86rf215_radio_pll_ctrl_st cfg = {0};
at86rf215_radio_get_pll_ctrl(&rad->cariboulite_sys->modem, at86rf215_rf_channel_900mhz, &cfg);
rad->if_frequency = 0;
rad->lo_pll_locked = 1;
rad->modem_pll_locked = cfg.pll_locked;
rad->if_frequency = modem_act_freq;
rad->actual_rf_frequency = rad->if_frequency;
rad->requested_rf_frequency = f_rf;
rad->rf_frequency_error = rad->actual_rf_frequency - rad->requested_rf_frequency;
// return actual frequency
*freq = rad->actual_rf_frequency;
}
else
{
// error - unsupported frequency for S1G channel
ZF_LOGE("unsupported frequency for S1G channel - %.2f Hz", f_rf);
error = -1;
}
}
//--------------------------------------------------------------------------------
// 30-6GHz CONFIGURATION
//--------------------------------------------------------------------------------
else if (channel == cariboulite_channel_6g)
{
// Changing the frequency may sometimes need to break RX / TX
if (break_before_make)
{
// make sure that during the transition the modem is not transmitting and then
// verify that the FE is in low power mode
at86rf215_radio_set_state( &rad->cariboulite_sys->modem,
at86rf215_rf_channel_2400mhz,
at86rf215_radio_state_cmd_trx_off);
rad->state = at86rf215_radio_state_cmd_trx_off;
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);
f_rf_mod_32 *= 32e6;
f_rf_mod_26 *= 26e6;
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 = 26e6 - 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
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,
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 = modem_act_freq - lo_act_freq;
// setup fpga RFFE <= upconvert (tx / rx)
conversion_direction = conversion_dir_up;
}
//-------------------------------------
else if ( f_rf > CARIBOULITE_2G4_MIN &&
f_rf <= CARIBOULITE_2G4_MAX )
{
cariboulite_setup_ext_ref (rad->cariboulite_sys, cariboulite_ext_ref_off);
// region #2 - bypass mode
// setup modem frequency <= f_rf
modem_act_freq = (double)at86rf215_setup_channel (&rad->cariboulite_sys->modem,
at86rf215_rf_channel_2400mhz,
(uint32_t)f_rf);
lo_act_freq = 0;
act_freq = modem_act_freq;
conversion_direction = conversion_dir_none;
}
//-------------------------------------
else if ( f_rf > (CARIBOULITE_2G4_MAX) &&
f_rf <= CARIBOULITE_MAX_MIX )
{
// region #3 - DOWN-CONVERSION
// setup modem frequency <= CARIBOULITE_2G4_MIN
modem_act_freq = (double)at86rf215_setup_channel (&rad->cariboulite_sys->modem,
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 = 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;
}
//-------------------------------------
else
{
// error - unsupported frequency for 6G channel
ZF_LOGE("unsupported frequency for 6GHz channel - %.2f Hz", f_rf);
error = -1;
}
// Setup the frontend
// This step takes the current radio direction of communication
// and the down/up conversion decision made before to setup the RF front-end
switch (conversion_direction)
{
case conversion_dir_up:
if (rad->channel_direction == cariboulite_channel_dir_rx)
{
caribou_fpga_set_io_ctrl_mode (&rad->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_rx_lowpass);
}
else if (rad->channel_direction == cariboulite_channel_dir_tx)
{
caribou_fpga_set_io_ctrl_mode (&rad->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_tx_lowpass);
}
break;
case conversion_dir_none:
caribou_fpga_set_io_ctrl_mode (&rad->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_bypass);
break;
case conversion_dir_down:
if (rad->channel_direction == cariboulite_channel_dir_rx)
{
caribou_fpga_set_io_ctrl_mode (&rad->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_rx_hipass);
}
else if (rad->channel_direction == cariboulite_channel_dir_tx)
{
caribou_fpga_set_io_ctrl_mode (&rad->cariboulite_sys->fpga, 0, caribou_fpga_io_ctrl_rfm_tx_hipass);
}
break;
default: break;
}
// Make sure the LO and the IF PLLs are locked
at86rf215_radio_set_state( &rad->cariboulite_sys->modem,
GET_CH(channel),
at86rf215_radio_state_cmd_tx_prep);
rad->state = at86rf215_radio_state_cmd_tx_prep;
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);
error = 1;
}
// Update the actual frequencies
rad->lo_frequency = lo_act_freq;
rad->if_frequency = modem_act_freq;
rad->actual_rf_frequency = act_freq;
rad->requested_rf_frequency = f_rf;
rad->rf_frequency_error = rad->actual_rf_frequency - rad->requested_rf_frequency;
if (freq) *freq = act_freq;
// activate the channel according to the new configuration
cariboulite_activate_channel(radios, channel, 1);
}
if (error >= 0)
{
ZF_LOGD("Frequency setting CH: %d, Wanted: %.2f Hz, Set: %.2f Hz (MOD: %.2f, MIX: %.2f)",
channel, f_rf, act_freq, modem_act_freq, lo_act_freq);
}
return -error;
return cariboulite_radio_set_frequency(GET_RADIO_PTR(radios,channel),
break_before_make,
freq);
}
//======================================================================
@ -783,10 +227,8 @@ int cariboulite_get_frequency( cariboulite_radios_st* radios,
cariboulite_channel_en channel,
double *freq, double *lo, double* i_f)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
if (freq) *freq = rad->actual_rf_frequency;
if (lo) *lo = rad->lo_frequency;
if (i_f) *i_f = rad->if_frequency;
return cariboulite_radio_get_frequency(GET_RADIO_PTR(radios,channel),
freq, lo, i_f);
}
//======================================================================
@ -794,142 +236,34 @@ int cariboulite_activate_channel(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
bool active)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,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)
{
at86rf215_radio_set_state( &rad->cariboulite_sys->modem,
GET_CH(channel),
at86rf215_radio_state_cmd_tx_prep);
rad->state = at86rf215_radio_state_cmd_tx_prep;
ZF_LOGD("Setup Modem state tx_prep");
}
if (!active)
{
at86rf215_radio_set_state( &rad->cariboulite_sys->modem,
GET_CH(channel),
at86rf215_radio_state_cmd_trx_off);
rad->state = at86rf215_radio_state_cmd_trx_off;
ZF_LOGD("Setup Modem state trx_off");
return 0;
}
// Activate the channel according to the configurations
// RX on both channels looks the same
if (rad->channel_direction == cariboulite_channel_dir_rx)
{
at86rf215_radio_set_state( &rad->cariboulite_sys->modem,
GET_CH(channel),
at86rf215_radio_state_cmd_rx);
ZF_LOGD("Setup Modem state cmd_rx");
}
else if (rad->channel_direction == cariboulite_channel_dir_tx)
{
// if its an LO frequency output from the mixer - no need for modem output
// LO applicable only to the channel with the mixer
if (rad->lo_output && channel == cariboulite_channel_6g)
{
// here we need to configure lo bypass on the mixer
rffc507x_output_lo(&rad->cariboulite_sys->mixer, 1);
}
// otherwise we need the modem
else
{
// make sure the mixer doesn't bypass the lo
rffc507x_output_lo(&rad->cariboulite_sys->mixer, 0);
cariboulite_set_tx_bandwidth(radios, channel,
rad->cw_output?at86rf215_radio_tx_cut_off_80khz:rad->tx_bw);
// CW output - constant I/Q values override
at86rf215_radio_set_tx_dac_input_iq(&rad->cariboulite_sys->modem,
GET_CH(channel),
rad->cw_output, 0x7E,
rad->cw_output, 0x3F);
// transition to state TX
at86rf215_radio_set_state(&rad->cariboulite_sys->modem,
GET_CH(channel),
at86rf215_radio_state_cmd_tx);
}
}
return 0;
return cariboulite_radio_activate_channel(GET_RADIO_PTR(radios,channel), active);
}
//======================================================================
int cariboulite_set_cw_outputs(cariboulite_radios_st* radios,
cariboulite_channel_en channel, bool lo_out, bool cw_out)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
if (rad->lo_output && channel == cariboulite_channel_6g)
{
rad->lo_output = lo_out;
}
else
{
rad->lo_output = false;
}
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;
return cariboulite_radio_set_cw_outputs(GET_RADIO_PTR(radios,channel),
lo_out, cw_out);
}
//======================================================================
int cariboulite_get_cw_outputs(cariboulite_radios_st* radios,
cariboulite_channel_en channel, bool *lo_out, bool *cw_out)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
if (lo_out) *lo_out = rad->lo_output;
if (cw_out) *cw_out = rad->cw_output;
return 0;
return cariboulite_radio_get_cw_outputs(GET_RADIO_PTR(radios,channel),
lo_out, cw_out);
}
//=================================================
int cariboulite_create_smi_stream(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
cariboulite_channel_dir_en dir,
int buffer_length,
void* context)
{
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
caribou_smi_channel_en ch = (channel == cariboulite_channel_s1g) ?
caribou_smi_channel_900 : caribou_smi_channel_2400;
caribou_smi_stream_type_en type = (dir == cariboulite_channel_dir_rx) ?
caribou_smi_stream_type_read : caribou_smi_stream_type_write;
int stream_id = caribou_smi_setup_stream(&rad->cariboulite_sys->smi,
type,
ch,
caribou_smi_data_event,
context);
// keep the stream ids
if (type == caribou_smi_stream_type_read)
{
rad->rx_stream_id = stream_id;
}
else if (type == caribou_smi_stream_type_write)
{
rad->tx_stream_id = stream_id;
}
return stream_id;
return cariboulite_radio_create_smi_stream(GET_RADIO_PTR(radios,channel),
dir,
context);
}
//=================================================
@ -937,15 +271,14 @@ int cariboulite_destroy_smi_stream(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
cariboulite_channel_dir_en dir)
{
// fetch the stream id
cariboulite_radio_state_st* rad = GET_RADIO_PTR(radios,channel);
int stream_id = (dir == cariboulite_channel_dir_rx) ? rad->rx_stream_id : rad->tx_stream_id;
if (stream_id == -1)
{
ZF_LOGE("The specified channel (%d) doesn't have open stream of type %d", channel, dir);
return -1;
}
caribou_smi_destroy_stream(&rad->cariboulite_sys->smi, stream_id);
return cariboulite_radio_destroy_smi_stream(GET_RADIO_PTR(radios,channel), dir);
}
//=================================================
int cariboulite_run_pause_stream(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
cariboulite_channel_dir_en dir,
bool run)
{
return cariboulite_radio_run_pause_stream(GET_RADIO_PTR(radios,channel), dir, run);
}

Wyświetl plik

@ -6,93 +6,10 @@ extern "C" {
#endif
#include "cariboulite_config/cariboulite_config.h"
#include "cariboulite_radio.h"
#include "at86rf215/at86rf215.h"
typedef enum
{
cariboulite_channel_dir_rx = 0,
cariboulite_channel_dir_tx = 1,
} cariboulite_channel_dir_en;
typedef enum
{
cariboulite_channel_s1g = 0,
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;
cariboulite_channel_dir_en channel_direction;
cariboulite_channel_en type;
bool active;
bool cw_output;
bool lo_output;
// MODEM STATES
at86rf215_radio_state_cmd_en state;
at86rf215_radio_irq_st interrupts;
bool rx_agc_on;
int rx_gain_value_db;
at86rf215_radio_rx_bw_en rx_bw;
at86rf215_radio_f_cut_en rx_fcut;
at86rf215_radio_sample_rate_en rx_fs;
int tx_power;
at86rf215_radio_tx_cut_off_en tx_bw;
at86rf215_radio_f_cut_en tx_fcut;
at86rf215_radio_sample_rate_en tx_fs;
// at86rf215_radio_energy_detection_st rx_energy_detection;
float rx_energy_detection_value;
float rx_rssi;
// FREQUENCY
bool modem_pll_locked;
bool lo_pll_locked;
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;
int tx_stream_id;
// OTHERS
uint8_t random_value;
float rx_thermal_noise_floor;
// CALIBRATION
int num_of_rx_cal_points;
int num_of_tx_cal_points;
float rx_power_gain_calibration[6001];
float tx_power_gain_calibration[6001];
} cariboulite_radio_state_st;
typedef struct
{
cariboulite_radio_state_st radio_sub1g;
@ -200,7 +117,6 @@ int cariboulite_get_cw_outputs(cariboulite_radios_st* radios,
int cariboulite_create_smi_stream(cariboulite_radios_st* radios,
cariboulite_channel_en channel,
cariboulite_channel_dir_en dir,
int buffer_length,
void* context);
int cariboulite_destroy_smi_stream(cariboulite_radios_st* radios,

Wyświetl plik

@ -10,44 +10,40 @@ SoapyCaribouliteSession Cariboulite::sess;
Cariboulite::Cariboulite(const SoapySDR::Kwargs &args)
{
int stream_id = 0;
CARIBOULITE_CONFIG_DEFAULT(temp);
caribou_smi_stream_type_en types[] = {caribou_smi_stream_type_write,
caribou_smi_stream_type_write,
caribou_smi_stream_type_read,
caribou_smi_stream_type_read};
caribou_smi_channel_en channels[] = {caribou_smi_channel_900,
caribou_smi_channel_2400,
caribou_smi_channel_900,
caribou_smi_channel_2400};
SoapySDR_logf(SOAPY_SDR_INFO, "Initializing DeviceID: %s, Label: %s, ChannelType: %s",
args.at("device_id").c_str(),
args.at("label").c_str(),
args.at("channel").c_str());
for (int i = 0; i < 4; i++)
{
int stream_id = CARIBOU_SMI_GET_STREAM_ID(types[i], channels[i]);
sample_queues[i] = new SampleQueue(getStreamMTU(NULL)*NUM_BYTES_PER_CPLX_ELEM, NUM_SAMPLEQUEUE_BUFS);
int dir = (types[i] == caribou_smi_stream_type_write)? SOAPY_SDR_TX : SOAPY_SDR_RX;
int ch = (channels[i] == caribou_smi_channel_900)? cariboulite_channel_s1g : cariboulite_channel_6g;
sample_queues[i]->AttachStreamId(stream_id, dir, ch);
}
// Initialize the stream Sample Queues
sample_queue_tx = new SampleQueue(getStreamMTU(NULL)*NUM_BYTES_PER_CPLX_ELEM, NUM_SAMPLEQUEUE_BUFS);
sample_queue_rx = new SampleQueue(getStreamMTU(NULL)*NUM_BYTES_PER_CPLX_ELEM, NUM_SAMPLEQUEUE_BUFS);
cariboulite_init_radios(&radios, &sess.cariboulite_sys);
//SoapySDR_logf(SOAPY_SDR_INFO, "Cariboulite c'tor");
// TODO: Exception when error
if (!args.at("channel").compare ("HiF"))
{
sample_queue_tx->AttachStreamId(0, caribou_smi_stream_type_write, caribou_smi_channel_2400);
sample_queue_rx->AttachStreamId(1, caribou_smi_stream_type_read, caribou_smi_channel_2400);
cariboulite_radio_init(&radio, &sess.cariboulite_sys, cariboulite_channel_6g);
}
else if (!args.at("channel").compare ("S1G"))
{
sample_queue_tx->AttachStreamId(0, caribou_smi_stream_type_write, caribou_smi_channel_900);
sample_queue_rx->AttachStreamId(1, caribou_smi_stream_type_read, caribou_smi_channel_900);
cariboulite_radio_init(&radio, &sess.cariboulite_sys, cariboulite_channel_s1g);
}
else
{
throw std::string("Channel type is not specified correctly");
}
}
//========================================================
Cariboulite::~Cariboulite()
{
cariboulite_dispose_radios(&radios);
for (int i = 0; i < 4; i++)
{
delete sample_queues[i];
}
//SoapySDR_logf(SOAPY_SDR_INFO, "Cariboulite d'tor");
cariboulite_radio_dispose(&radio);
delete sample_queue_tx;
delete sample_queue_rx;
}
/*******************************************************************
@ -81,8 +77,8 @@ std::vector<std::string> Cariboulite::listAntennas( const int direction, const s
{
//printf("listAntennas dir: %d, channel: %ld\n", direction, channel);
std::vector<std::string> options;
if (channel == cariboulite_channel_s1g) options.push_back( "TX/RX Sub1GHz" );
else if (channel == cariboulite_channel_6g) options.push_back( "TX/RX 6GHz" );
if (radio.type == cariboulite_channel_s1g) options.push_back( "TX/RX Sub1GHz" );
else if (radio.type == cariboulite_channel_6g) options.push_back( "TX/RX 6GHz" );
return(options);
}
@ -91,8 +87,8 @@ std::vector<std::string> Cariboulite::listAntennas( const int direction, const s
std::string Cariboulite::getAntenna( const int direction, const size_t channel ) const
{
//printf("getAntenna dir: %d, channel: %ld\n", direction, channel);
if (channel == cariboulite_channel_s1g) return "TX/RX Sub1GHz";
else if (channel == cariboulite_channel_6g) return "TX/RX 6GHz";
if (radio.type == cariboulite_channel_s1g) return "TX/RX Sub1GHz";
else if (radio.type == cariboulite_channel_6g) return "TX/RX 6GHz";
return "";
}
@ -126,17 +122,16 @@ std::vector<std::string> Cariboulite::listGains(const int direction, const size_
void Cariboulite::setGain(const int direction, const size_t channel, const double value)
{
//printf("setGain dir: %d, channel: %ld, value: %.2f\n", direction, channel, value);
cariboulite_radio_state_st* rad = channel == cariboulite_channel_s1g? &radios.radio_sub1g : &radios.radio_6g;
bool cur_agc_mode = rad->rx_agc_on;
bool cur_agc_mode = radio.rx_agc_on;
if (direction == SOAPY_SDR_RX)
{
cariboulite_set_rx_gain_control(&radios, (cariboulite_channel_en)channel, cur_agc_mode, value);
cariboulite_radio_set_rx_gain_control(&radio, cur_agc_mode, value);
}
else if (direction == SOAPY_SDR_TX)
{
// base if -18dBm output so, given a gain of 0dB we should have -18 dBm
cariboulite_set_tx_power(&radios, (cariboulite_channel_en)channel, value - 18.0);
cariboulite_radio_set_tx_power(&radio, value - 18.0);
}
}
@ -154,12 +149,12 @@ double Cariboulite::getGain(const int direction, const size_t channel) const
if (direction == SOAPY_SDR_RX)
{
cariboulite_get_rx_gain_control((cariboulite_radios_st*)&radios, (cariboulite_channel_en)channel, NULL, &value);
cariboulite_radio_get_rx_gain_control((cariboulite_radio_state_st*)&radio, NULL, &value);
}
else if (direction == SOAPY_SDR_TX)
{
int temp = 0;
cariboulite_get_tx_power((cariboulite_radios_st*)&radios, (cariboulite_channel_en)channel, &temp);
cariboulite_radio_get_tx_power((cariboulite_radio_state_st*)&radio, &temp);
value = temp + 18.0;
}
SoapySDR_logf(SOAPY_SDR_INFO, "getGain dir: %d, channel: %ld, value: %d", direction, channel, value);
@ -209,12 +204,11 @@ bool Cariboulite::hasGainMode(const int direction, const size_t channel) const
void Cariboulite::setGainMode( const int direction, const size_t channel, const bool automatic )
{
//printf("setGainMode dir: %d, channel: %ld, auto: %d\n", direction, channel, automatic);
cariboulite_radio_state_st* rad = channel == cariboulite_channel_s1g? &radios.radio_sub1g : &radios.radio_6g;
bool rx_gain = rad->rx_gain_value_db;
bool rx_gain = radio.rx_gain_value_db;
if (direction == SOAPY_SDR_RX)
{
cariboulite_set_rx_gain_control(&radios, (cariboulite_channel_en)channel, automatic, rx_gain);
cariboulite_radio_set_rx_gain_control(&radio, automatic, rx_gain);
}
}
@ -231,8 +225,7 @@ bool Cariboulite::getGainMode( const int direction, const size_t channel ) const
if (direction == SOAPY_SDR_RX)
{
cariboulite_get_rx_gain_control((cariboulite_radios_st*)&radios, (cariboulite_channel_en)channel,
&mode, NULL);
cariboulite_radio_get_rx_gain_control((cariboulite_radio_state_st*)&radio, &mode, NULL);
SoapySDR_logf(SOAPY_SDR_INFO, "getGainMode dir: %d, channel: %ld, auto: %d", direction, channel, mode);
return mode;
}
@ -245,24 +238,17 @@ bool Cariboulite::getGainMode( const int direction, const size_t channel ) const
******************************************************************/
void Cariboulite::setSampleRate( const int direction, const size_t channel, const double rate )
{
cariboulite_radio_state_st* rad = channel == cariboulite_channel_s1g? &radios.radio_sub1g : &radios.radio_6g;
at86rf215_radio_f_cut_en rx_cuttof = rad->rx_fcut;
at86rf215_radio_f_cut_en tx_cuttof = rad->tx_fcut;
at86rf215_radio_f_cut_en rx_cuttof = radio.rx_fcut;
at86rf215_radio_f_cut_en tx_cuttof = radio.tx_fcut;
//printf("setSampleRate dir: %d, channel: %ld, rate: %.2f\n", direction, channel, rate);
if (direction == SOAPY_SDR_RX)
{
cariboulite_set_rx_samp_cutoff(&radios,
(cariboulite_channel_en)channel,
at86rf215_radio_rx_sample_rate_4000khz,
rx_cuttof);
cariboulite_radio_set_rx_samp_cutoff(&radio, at86rf215_radio_rx_sample_rate_4000khz, rx_cuttof);
}
else if (direction == SOAPY_SDR_TX)
{
cariboulite_set_tx_samp_cutoff(&radios,
(cariboulite_channel_en)channel,
at86rf215_radio_rx_sample_rate_4000khz,
tx_cuttof);
cariboulite_radio_set_tx_samp_cutoff(&radio, at86rf215_radio_rx_sample_rate_4000khz, tx_cuttof);
}
}
@ -393,14 +379,12 @@ void Cariboulite::setBandwidth( const int direction, const size_t channel, const
if (direction == SOAPY_SDR_RX)
{
cariboulite_set_rx_bandwidth(&radios,(cariboulite_channel_en)channel, convertRxBandwidth(setbw));
if (channel == 0) sample_queues[2]->dig_filt = filt;
else if (channel == 1) sample_queues[3]->dig_filt = filt;
cariboulite_radio_set_rx_bandwidth(&radio, convertRxBandwidth(setbw));
sample_queue_rx->dig_filt = filt;
}
else if (direction == SOAPY_SDR_TX)
{
cariboulite_set_tx_bandwidth(&radios,(cariboulite_channel_en)channel,
convertTxBandwidth(setbw));
cariboulite_radio_set_tx_bandwidth(&radio, convertTxBandwidth(setbw));
}
}
@ -412,13 +396,13 @@ double Cariboulite::getBandwidth( const int direction, const size_t channel ) co
if (direction == SOAPY_SDR_RX)
{
at86rf215_radio_rx_bw_en bw;
cariboulite_get_rx_bandwidth((cariboulite_radios_st*)&radios,(cariboulite_channel_en)channel, &bw);
cariboulite_radio_get_rx_bandwidth((cariboulite_radio_state_st*)&radio, &bw);
return convertRxBandwidth(bw);
}
else if (direction == SOAPY_SDR_TX)
{
at86rf215_radio_tx_cut_off_en bw;
cariboulite_get_tx_bandwidth((cariboulite_radios_st*)&radios,(cariboulite_channel_en)channel, &bw);
cariboulite_radio_get_tx_bandwidth((cariboulite_radio_state_st*)&radio, &bw);
return convertTxBandwidth(bw);
}
return 0.0;
@ -483,7 +467,7 @@ void Cariboulite::setFrequency( const int direction, const size_t channel, const
return;
}
err = cariboulite_set_frequency(&radios, (cariboulite_channel_en)channel, true, (double *)&frequency);
err = cariboulite_radio_set_frequency(&radio, true, (double *)&frequency);
if (err == 0) SoapySDR_logf(SOAPY_SDR_INFO, "setFrequency dir: %d, channel: %ld, freq: %.2f", direction, channel, frequency);
else SoapySDR_logf(SOAPY_SDR_ERROR, "setFrequency dir: %d, channel: %ld, freq: %.2f FAILED", direction, channel, frequency);
}
@ -498,7 +482,7 @@ double Cariboulite::getFrequency( const int direction, const size_t channel, con
return 0.0;
}
cariboulite_get_frequency((cariboulite_radios_st*)&radios,(cariboulite_channel_en)channel, &freq, NULL, NULL);
cariboulite_radio_get_frequency((cariboulite_radio_state_st*)&radio, &freq, NULL, NULL);
return freq;
}
@ -530,14 +514,14 @@ SoapySDR::RangeList Cariboulite::getFrequencyRange( const int direction, const s
throw std::runtime_error( "getFrequencyRange(" + name + ") unknown name" );
}
if (channel == cariboulite_channel_s1g)
if (radio.type == cariboulite_channel_s1g)
{
SoapySDR::RangeList list;
list.push_back(SoapySDR::Range( 389.5e6, 510e6 ));
list.push_back(SoapySDR::Range( 779e6, 1020e6 ));
return list;
}
else if (channel == cariboulite_channel_6g)
else if (radio.type == cariboulite_channel_6g)
{
return (SoapySDR::RangeList( 1, SoapySDR::Range( 1e6, 6000e6 ) ) );
}

Wyświetl plik

@ -21,6 +21,7 @@
#include "datatypes/circular_buffer.h"
#include "cariboulite_setup.h"
#include "cariboulite_radios.h"
#include "cariboulite_radio.h"
enum Cariboulite_Format
{
@ -175,8 +176,8 @@ public:
long long &timeNs,
const long timeoutUs = 100000);
int findSampleQueue(const int direction, const size_t channel);
int findSampleQueueById(int stream_id);
//int findSampleQueue(const int direction, const size_t channel);
//int findSampleQueueById(int stream_id);
/*******************************************************************
* Antenna API
@ -232,8 +233,9 @@ public:
Type readSensor(const int direction, const size_t channel, const std::string &key) const;
public:
cariboulite_radios_st radios;
SampleQueue* sample_queues[4];
cariboulite_radio_state_st radio;
SampleQueue* sample_queue_tx;
SampleQueue* sample_queue_rx;
// Static load time initializations
static SoapyCaribouliteSession sess;

Wyświetl plik

@ -38,7 +38,6 @@ void soapy_sighandler( struct cariboulite_st_t *sys,
SoapyCaribouliteSession::SoapyCaribouliteSession(void)
{
std::lock_guard<std::mutex> lock(sessionMutex);
//printf("SoapyCaribouliteSession, sessionCount: %ld\n", sessionCount);
SoapySDR_logf(SOAPY_SDR_INFO, "SoapyCaribouliteSession, sessionCount: %ld", sessionCount);
if (sessionCount == 0)
{
@ -63,7 +62,6 @@ SoapyCaribouliteSession::SoapyCaribouliteSession(void)
SoapyCaribouliteSession::~SoapyCaribouliteSession(void)
{
std::lock_guard<std::mutex> lock(sessionMutex);
//printf("~SoapyCaribouliteSession, sessionCount: %ld\n", sessionCount);
//SoapySDR_logf(SOAPY_SDR_INFO, "~SoapyCaribouliteSession, sessionCount: %ld", sessionCount);
sessionCount--;
if (sessionCount == 0)

Wyświetl plik

@ -106,29 +106,6 @@ SoapySDR::ArgInfoList Cariboulite::getStreamArgsInfo(const int direction, const
return streamArgs;
}
//========================================================
int Cariboulite::findSampleQueue(const int direction, const size_t channel)
{
for (uint32_t i = 0; i < 4; i++)
{
if (sample_queues[i]->stream_dir == direction &&
sample_queues[i]->stream_channel == (int)channel)
return i;
}
return -1;
}
//========================================================
int Cariboulite::findSampleQueueById(int stream_id)
{
for (uint32_t i = 0; i < 4; i++)
{
if (sample_queues[i]->stream_id == stream_id)
return i;
}
return -1;
}
//========================================================
/*!
* Initialize a stream given a list of channels and stream arguments.
@ -190,6 +167,7 @@ SoapySDR::Stream *Cariboulite::setupStream(const int direction,
channels.size()?channels[0]:0);
std::vector<size_t> channels_internal = channels;
// default channel - sub1GHz
if ( channels_internal.size() == 0 )
{
@ -258,7 +236,6 @@ SoapySDR::Stream *Cariboulite::setupStream(const int direction,
*/
void Cariboulite::closeStream(SoapySDR::Stream *stream)
{
//SoapySDR_logf(SOAPY_SDR_INFO, "closeStream");
if (stream == NULL) return;
int stream_id = (intptr_t)stream;
@ -277,7 +254,6 @@ void Cariboulite::closeStream(SoapySDR::Stream *stream)
*/
size_t Cariboulite::getStreamMTU(SoapySDR::Stream *stream) const
{
//printf("getStreamMTU\n");
return 1024 * 1024 / 2 / 4;
}

Wyświetl plik

@ -1,5 +1,6 @@
#include <SoapySDR/Device.hpp>
#include <SoapySDR/Registry.hpp>
#include <sstream>
#include "Cariboulite.hpp"
@ -18,45 +19,41 @@ SoapySDR::KwargsList findCariboulite(const SoapySDR::Kwargs &args)
SoapySDR_logf(SOAPY_SDR_DEBUG, "CaribouLite Lib v%d.%d rev %d",
lib_version.major_version, lib_version.minor_version, lib_version.revision);
// When multiboard will be supported, change this to enumertion with count >1
if ( ( count = cariboulite_config_detect_board(&board_info) ) <= 0)
{
SoapySDR_logf(SOAPY_SDR_DEBUG, "No Cariboulite boards found");
return results;
}
// to support for two channels, each CaribouLite detected will be identified as
// two boards for the SoapyAPI
int devId = 0;
for (int i = 0; i < count; i++)
{
std::stringstream serialstr;
serialstr.str("");
serialstr << std::hex << board_info.numeric_serial_number;
SoapySDR_logf(SOAPY_SDR_DEBUG, "Serial %s", serialstr.str().c_str());
for (int ch = 0; ch < 2; ch ++)
{
std::stringstream serialstr;
std::stringstream label;
SoapySDR::Kwargs soapyInfo;
serialstr.str("");
serialstr << std::hex << ((board_info.numeric_serial_number << 1) | ch);
label.str("");
label << (ch?std::string("CaribouLite HiF"):std::string("CaribouLite S1G")) << "[" << serialstr.str() << "]";
SoapySDR::Kwargs soapyInfo;
SoapySDR_logf(SOAPY_SDR_DEBUG, "Serial %s", serialstr.str().c_str());
soapyInfo["device_id"] = std::to_string(devId);
soapyInfo["label"] = "Cariboulite [" + serialstr.str() + "]";
soapyInfo["serial"] = serialstr.str();
soapyInfo["name"] = board_info.product_name;
soapyInfo["vendor"] = board_info.product_vendor;
soapyInfo["uuid"] = board_info.product_uuid;
soapyInfo["version"] = board_info.product_version;
devId++;
soapyInfo["device_id"] = std::to_string(devId);
soapyInfo["label"] = label.str();
soapyInfo["serial"] = serialstr.str();
soapyInfo["name"] = board_info.product_name;
soapyInfo["vendor"] = board_info.product_vendor;
soapyInfo["uuid"] = board_info.product_uuid;
soapyInfo["version"] = board_info.product_version;
soapyInfo["channel"] = ch?"HiF":"S1G";
devId++;
if (args.count("device_id") != 0)
{
if (args.at("device_id") != soapyInfo.at("device_id"))
{
continue;
}
SoapySDR_logf(SOAPY_SDR_DEBUG, "Found device by device_id %s", soapyInfo.at("device_id").c_str());
}
results.push_back(soapyInfo);
results.push_back(soapyInfo);
}
}
return results;