kopia lustrzana https://github.com/cariboulabs/cariboulite
Merge branches 'main' and 'main' of https://github.com/cariboulabs/cariboulite
commit
a3b7e6b377
|
@ -22,7 +22,7 @@ def setup_receiver(sdr, channel, freq_hz):
|
|||
sdr.setGainMode(SOAPY_SDR_RX, channel, use_agc) # Set the gain mode
|
||||
sdr.setGain(SOAPY_SDR_RX, channel, 0) # Set the gain
|
||||
sdr.setFrequency(SOAPY_SDR_RX, channel, freq_hz) # Tune the LO
|
||||
sdr.setBandwidth(SOAPY_SDR_RX, channel, 2.5e6)
|
||||
sdr.setBandwidth(SOAPY_SDR_RX, channel, 2500e5)
|
||||
rx_stream = sdr.setupStream(SOAPY_SDR_RX, SOAPY_SDR_CS16, [channel]) # Setup data stream
|
||||
return rx_stream
|
||||
|
||||
|
@ -77,4 +77,4 @@ plt.show()
|
|||
fig = plt.figure()
|
||||
plt.plot(s_real)
|
||||
plt.plot(s_imag)
|
||||
plt.show()
|
||||
plt.show()
|
Plik diff jest za duży
Load Diff
|
@ -20,15 +20,13 @@ module lvds_rx
|
|||
localparam
|
||||
modem_i_sync = 3'b10,
|
||||
modem_q_sync = 3'b01;
|
||||
// modem_i_sync = 3'b01,
|
||||
// modem_q_sync = 3'b10;
|
||||
|
||||
// Internal Registers
|
||||
reg [1:0] r_state_if;
|
||||
reg [2:0] r_phase_count;
|
||||
reg [31:0] r_data;
|
||||
reg r_push;
|
||||
reg [1:0] r_cnt;
|
||||
reg r_cnt;
|
||||
|
||||
assign o_debug_state = r_state_if;
|
||||
|
||||
|
@ -64,39 +62,35 @@ module lvds_rx
|
|||
end
|
||||
|
||||
r_phase_count <= 3'b111;
|
||||
r_data <= 0;
|
||||
r_push <= 1'b0;
|
||||
r_data[3:2] <= 2'b11;
|
||||
r_data[1:0] <= r_cnt;
|
||||
end
|
||||
|
||||
state_i_phase: begin
|
||||
if (r_phase_count == 3'b000) begin
|
||||
if (i_ddr_data == modem_q_sync ) begin
|
||||
r_phase_count <= 3'b111;
|
||||
r_phase_count <= 3'b110;
|
||||
r_state_if <= state_q_phase;
|
||||
end else begin
|
||||
r_state_if <= state_idle;
|
||||
end
|
||||
|
||||
end else begin
|
||||
r_phase_count <= r_phase_count - 1;
|
||||
r_data <= {r_data[29:0], i_ddr_data};
|
||||
end
|
||||
|
||||
//r_data <= {r_data[29:0], i_ddr_data};
|
||||
r_data <= {r_data[29:0], i_ddr_data};
|
||||
end
|
||||
|
||||
state_q_phase: begin
|
||||
if (r_phase_count == 3'b000) begin
|
||||
r_push <= ~i_fifo_full;
|
||||
r_state_if <= state_idle;
|
||||
//o_fifo_data <= {r_data[29:0], i_ddr_data};
|
||||
o_fifo_data <= r_data;
|
||||
r_cnt <= r_cnt + 1;
|
||||
o_fifo_data <= {r_data[29:0], i_ddr_data};
|
||||
end else begin
|
||||
r_phase_count <= r_phase_count - 1;
|
||||
r_data <= {r_data[29:0], i_ddr_data};
|
||||
end
|
||||
//r_data <= {r_data[29:0], i_ddr_data};
|
||||
r_data <= {r_data[29:0], i_ddr_data};
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
|
18265
firmware/top.asc
18265
firmware/top.asc
Plik diff jest za duży
Load Diff
BIN
firmware/top.bin
BIN
firmware/top.bin
Plik binarny nie jest wyświetlany.
20911
firmware/top.json
20911
firmware/top.json
Plik diff jest za duży
Load Diff
|
@ -45,6 +45,87 @@ static void caribou_smi_print_smi_settings(caribou_smi_st* dev, struct smi_setti
|
|||
static void caribou_smi_setup_settings (caribou_smi_st* dev, struct smi_settings *settings);
|
||||
static void caribou_smi_init_stream(caribou_smi_st* dev, caribou_smi_stream_type_en type, caribou_smi_channel_en ch);
|
||||
|
||||
|
||||
#define TIMING_PERF_SYNC (0)
|
||||
|
||||
#if (TIMING_PERF_SYNC)
|
||||
#define TIMING_PERF_SYNC_VARS \
|
||||
struct timeval tv_pre = {0}; \
|
||||
struct timeval tv_post = {0}; \
|
||||
long long total_samples = 0,last_total_samples = 0; \
|
||||
double time_pre = 0, batch_time = 0, sample_rate = 0; \
|
||||
double time_post = 0, process_time = 0; \
|
||||
double temp_pre; \
|
||||
double num_samples = 0, num_samples_avg = 0;
|
||||
|
||||
#define TIMING_PERF_SYNC_TICK \
|
||||
gettimeofday(&tv_pre, NULL);
|
||||
|
||||
#define TIMING_PERF_SYNC_TOCK \
|
||||
gettimeofday(&tv_post, NULL); \
|
||||
num_samples = (double)(st->read_ret_value) / 4.0; \
|
||||
num_samples_avg = num_samples_avg*0.1 + num_samples*0.9; \
|
||||
temp_pre = tv_pre.tv_sec + ((double)(tv_pre.tv_usec)) / 1e6; \
|
||||
time_post = tv_post.tv_sec + ((double)(tv_post.tv_usec)) / 1e6; \
|
||||
batch_time = temp_pre - time_pre; \
|
||||
sample_rate = sample_rate*0.1 + (num_samples / batch_time) * 0.9; \
|
||||
process_time = process_time*0.1 + (time_post - temp_pre)*0.9; \
|
||||
time_pre = temp_pre; \
|
||||
total_samples += st->read_ret_value; \
|
||||
if ((total_samples - last_total_samples) > 4000000*4) \
|
||||
{ \
|
||||
last_total_samples = total_samples; \
|
||||
ZF_LOGD("sample_rate = %.2f SPS, process_time = %.2f usec" \
|
||||
", num_samples_avg = %.1f", \
|
||||
sample_rate, process_time * 1e6, num_samples_avg); \
|
||||
}
|
||||
#else
|
||||
#define TIMING_PERF_SYNC_VARS
|
||||
#define TIMING_PERF_SYNC_TICK
|
||||
#define TIMING_PERF_SYNC_TOCK
|
||||
#endif
|
||||
|
||||
//=========================================================================
|
||||
void dump_hex(const void* data, size_t size)
|
||||
{
|
||||
char ascii[17];
|
||||
size_t i, j;
|
||||
ascii[16] = '\0';
|
||||
|
||||
for (i = 0; i < size; ++i) {
|
||||
printf("%02X ", ((unsigned char*)data)[i]);
|
||||
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~')
|
||||
{
|
||||
ascii[i % 16] = ((unsigned char*)data)[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
ascii[i % 16] = '.';
|
||||
}
|
||||
if ((i+1) % 8 == 0 || i+1 == size)
|
||||
{
|
||||
printf(" ");
|
||||
if ((i+1) % 16 == 0)
|
||||
{
|
||||
printf("| %s \n", ascii);
|
||||
}
|
||||
else if (i+1 == size)
|
||||
{
|
||||
ascii[(i+1) % 16] = '\0';
|
||||
if ((i+1) % 16 <= 8)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
for (j = (i+1) % 16; j < 16; ++j)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
printf("| %s \n", ascii);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
char* caribou_smi_get_error_string(caribou_smi_error_en err)
|
||||
{
|
||||
|
@ -131,49 +212,6 @@ int caribou_smi_close (caribou_smi_st* dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
int caribou_smi_read_async(
|
||||
caribou_smi_st* dev,
|
||||
caribou_smi_address_en source,
|
||||
char* buffer,
|
||||
int size_of_buf,
|
||||
struct aiocb *read_aiocb)
|
||||
{
|
||||
// set the address
|
||||
if (source > 0 && CARIBOU_SMI_READ_ADDR(source))
|
||||
{
|
||||
if (source != dev->current_address)
|
||||
{
|
||||
int ret = ioctl(dev->filedesc, BCM2835_SMI_IOC_ADDRESS, source);
|
||||
if (ret != 0)
|
||||
{
|
||||
ZF_LOGE("failed setting smi address (idle / %d) to device", source);
|
||||
return -1;
|
||||
}
|
||||
printf("Set address to %d\n", source);
|
||||
dev->current_address = source;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ZF_LOGE("the specified address is not a read address (%d)", source);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero((char *)read_aiocb, sizeof(struct aiocb));
|
||||
read_aiocb->aio_buf = buffer;
|
||||
read_aiocb->aio_fildes = dev->filedesc;
|
||||
read_aiocb->aio_nbytes = size_of_buf;
|
||||
read_aiocb->aio_offset = 0;
|
||||
int ret = aio_read(read_aiocb);
|
||||
if (ret < 0)
|
||||
{
|
||||
printf("aio_read failed!!\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
int caribou_smi_timeout_read(caribou_smi_st* dev,
|
||||
caribou_smi_address_en source,
|
||||
|
@ -348,6 +386,7 @@ static void set_realtime_priority(int priority_deter)
|
|||
ZF_LOGI("Thread priority is %d", params.sched_priority);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
int caribou_smi_search_offset(uint8_t *buff, int len)
|
||||
{
|
||||
bool succ = false;
|
||||
|
@ -365,24 +404,131 @@ int caribou_smi_search_offset(uint8_t *buff, int len)
|
|||
}
|
||||
|
||||
//=========================================================================
|
||||
#define TIMING_PERF_SYNC (0)
|
||||
/*void caribou_smi_convert_data(uint8_t *buffer,
|
||||
size_t length_bytes,
|
||||
caribou_smi_sample_complex_int16* cmplx_vec,
|
||||
caribou_smi_sample_meta* meta_vec)
|
||||
{
|
||||
static bool ptr = true;
|
||||
|
||||
// the verilog struct looks as follows:
|
||||
// [ 31:30 ] [ 29:28 ] [ 27:15 ] [ 14 ] [ 13:1 ] [ 0 ]
|
||||
// [always "11"] [ CNT 2Bits ] [ I sample ] [ SYNC1 ] [ Q sample ] [ SYNC2 ]
|
||||
|
||||
uint32_t *samples = (uint32_t*)buffer;
|
||||
//uint32_t cnt_gaps = 0;
|
||||
int num_sync_errors = 0;
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
dump_hex(buffer, 64);
|
||||
for (int k = 0; k < 8; k ++)
|
||||
{
|
||||
|
||||
printf("0x%08X, \n", __builtin_bswap32(samples[k]));
|
||||
}
|
||||
//ptr = false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < length_bytes/4; i++)
|
||||
{
|
||||
uint32_t s = __builtin_bswap32(samples[i]);
|
||||
|
||||
meta_vec[i].sync2 = s & 0x00000001; s >>= 1;
|
||||
cmplx_vec[i].q = s & 0x00001FFF; s >>= 13;
|
||||
meta_vec[i].sync1 = s & 0x00000001; s >>= 1;
|
||||
cmplx_vec[i].i = s & 0x00001FFF; s >>= 13;
|
||||
meta_vec[i].cnt = s & 0x00000003; s >>= 2;
|
||||
if (s != 0x3)
|
||||
{
|
||||
num_sync_errors++;
|
||||
}
|
||||
|
||||
if (cmplx_vec[i].i >= (int16_t)0x1000) cmplx_vec[i].i -= (int16_t)0x2000;
|
||||
if (cmplx_vec[i].q >= (int16_t)0x1000) cmplx_vec[i].q -= (int16_t)0x2000;
|
||||
|
||||
// TODO: calculate the cnt gaps
|
||||
}
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
for (int k = 0; k < 64; k ++)
|
||||
{
|
||||
printf("(%d, %d), sync = [%d,%d]\n", cmplx_vec[k].i, cmplx_vec[k].q, meta_vec[k].sync1, meta_vec[k].sync2);
|
||||
}
|
||||
ptr = false;
|
||||
}
|
||||
|
||||
//if (num_sync_errors) printf("caribou_smi_convert_data: sync errors @ %d samples\n", num_sync_errors);
|
||||
}*/
|
||||
|
||||
void caribou_smi_convert_data(uint8_t *buffer,
|
||||
size_t length_bytes,
|
||||
caribou_smi_sample_complex_int16* cmplx_vec,
|
||||
caribou_smi_sample_meta* meta_vec)
|
||||
{
|
||||
static bool ptr = true;
|
||||
|
||||
// the verilog struct looks as follows:
|
||||
// [31:30] [ 29:17 ] [ 16 ] [ 15:14 ] [ 13:1 ] [ 0 ]
|
||||
// [ '00'] [ I sample ] [ '0' ] [ '01' ] [ Q sample ] [ '0' ]
|
||||
|
||||
uint32_t *samples = (uint32_t*)buffer;
|
||||
//uint32_t cnt_gaps = 0;
|
||||
int num_sync_errors = 0;
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
printf("got byte array with %d bytes\n", length_bytes);
|
||||
dump_hex(buffer, 64);
|
||||
for (int k = 0; k < 8; k ++)
|
||||
{
|
||||
|
||||
printf("0x%08X, \n", (samples[k]));
|
||||
}
|
||||
//ptr = false;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < length_bytes/4; i++)
|
||||
{
|
||||
uint32_t s = (samples[i]);
|
||||
|
||||
/*meta_vec[i].sync2 = s & 0x00000001; */s >>= 1;
|
||||
cmplx_vec[i].q = s & 0x00001FFF; s >>= 13;
|
||||
s >>= 2;
|
||||
/*meta_vec[i].sync1 = s & 0x00000001; */s >>= 1;
|
||||
cmplx_vec[i].i = s & 0x00001FFF; s >>= 13;
|
||||
//meta_vec[i].cnt = s & 0x00000003; s >>= 2;
|
||||
if (s != 0x0)
|
||||
{
|
||||
num_sync_errors++;
|
||||
}
|
||||
|
||||
if (cmplx_vec[i].i >= (int16_t)0x1000) cmplx_vec[i].i -= (int16_t)0x2000;
|
||||
if (cmplx_vec[i].q >= (int16_t)0x1000) cmplx_vec[i].q -= (int16_t)0x2000;
|
||||
|
||||
// TODO: calculate the cnt gaps
|
||||
}
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
for (int k = 0; k < 64; k ++)
|
||||
{
|
||||
printf("(%d, %d), sync = [%d,%d]\n", cmplx_vec[k].i, cmplx_vec[k].q, meta_vec[k].sync1, meta_vec[k].sync2);
|
||||
}
|
||||
ptr = false;
|
||||
}
|
||||
|
||||
//if (num_sync_errors) printf("caribou_smi_convert_data: sync errors @ %d samples\n", num_sync_errors);
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void* caribou_smi_analyze_thread(void* arg)
|
||||
{
|
||||
//static int a = 0;
|
||||
int current_data_size = 0;
|
||||
pthread_t tid = pthread_self();
|
||||
|
||||
// --------------------------------------------
|
||||
// TIMING PERF VARIABLES
|
||||
#if (TIMING_PERF_SYNC)
|
||||
struct timeval tv_pre = {0};
|
||||
struct timeval tv_post = {0};
|
||||
long long total_samples = 0;
|
||||
double time_pre = 0, batch_time = 0, sample_rate = 0;
|
||||
double time_post = 0, process_time = 0;
|
||||
double temp_pre;
|
||||
double num_samples = 0, num_samples_avg = 0;
|
||||
#endif // TIMING_PERF_SYNC
|
||||
TIMING_PERF_SYNC_VARS;
|
||||
|
||||
caribou_smi_stream_st* st = (caribou_smi_stream_st*)arg;
|
||||
caribou_smi_st* dev = (caribou_smi_st*)st->parent_dev;
|
||||
|
@ -393,56 +539,36 @@ void* caribou_smi_analyze_thread(void* arg)
|
|||
set_realtime_priority(2);
|
||||
|
||||
int offset = 0;
|
||||
// ****************************************
|
||||
// MAIN LOOP
|
||||
// ****************************************
|
||||
while (st->read_analysis_thread_running)
|
||||
{
|
||||
pthread_mutex_lock(&st->read_analysis_lock);
|
||||
|
||||
#if (TIMING_PERF_SYNC)
|
||||
gettimeofday(&tv_pre, NULL);
|
||||
#endif
|
||||
|
||||
TIMING_PERF_SYNC_TICK;
|
||||
if (!st->read_analysis_thread_running) break;
|
||||
|
||||
offset = caribou_smi_search_offset(st->current_app_buffer, 16);
|
||||
/*offset = caribou_smi_search_offset(st->current_app_buffer, 16);
|
||||
if (offset == -1)
|
||||
{
|
||||
ZF_LOGE("Offset error!");
|
||||
for (int i = 0; i < 60; i+=4)
|
||||
{
|
||||
printf("%08X\n", *((uint32_t*)(st->current_app_buffer + i)));
|
||||
}
|
||||
}
|
||||
dump_hex(st->current_app_buffer, 60);
|
||||
}*/
|
||||
current_data_size = st->read_ret_value;
|
||||
if (offset != 0) current_data_size -= 4;
|
||||
//if (offset != 0) current_data_size -= 4;
|
||||
|
||||
if (st->data_cb) st->data_cb(dev->cb_context,
|
||||
st->service_context,
|
||||
type,
|
||||
ch,
|
||||
current_data_size,
|
||||
st->current_app_buffer + offset,
|
||||
st->batch_length);
|
||||
caribou_smi_convert_data(st->current_app_buffer + offset,
|
||||
current_data_size,
|
||||
st->app_cmplx_vec,
|
||||
st->app_meta_vec);
|
||||
|
||||
if (st->data_cb) st->data_cb(dev->cb_context, st->service_context, type, ch,
|
||||
current_data_size / 4,
|
||||
st->app_cmplx_vec,
|
||||
st->app_meta_vec,
|
||||
st->batch_length / 4);
|
||||
|
||||
#if (TIMING_PERF_SYNC)
|
||||
gettimeofday(&tv_post, NULL);
|
||||
|
||||
// benchmarking
|
||||
num_samples = (double)(st->read_ret_value) / 4.0;
|
||||
num_samples_avg = num_samples_avg*0.1 + num_samples*0.9;
|
||||
temp_pre = tv_pre.tv_sec + ((double)(tv_pre.tv_usec)) / 1e6;
|
||||
time_post = tv_post.tv_sec + ((double)(tv_post.tv_usec)) / 1e6;
|
||||
|
||||
batch_time = temp_pre - time_pre;
|
||||
sample_rate = sample_rate*0.1 + (num_samples / batch_time) * 0.9;
|
||||
process_time = process_time*0.1 + (time_post - temp_pre)*0.9;
|
||||
|
||||
time_pre = temp_pre;
|
||||
total_samples += st->read_ret_value;
|
||||
if (total_samples % (4*4000000) == 0)
|
||||
{
|
||||
printf("sample_rate = %.2f SPS, process_time = %.2f usec, num_samples_avg = %.1f\n", sample_rate, process_time * 1e6, num_samples_avg);
|
||||
}
|
||||
#endif
|
||||
TIMING_PERF_SYNC_TOCK;
|
||||
}
|
||||
|
||||
ZF_LOGD("Leaving SMI analysis thread id %lu, running = %d", tid, st->read_analysis_thread_running);
|
||||
|
@ -452,24 +578,11 @@ void* caribou_smi_analyze_thread(void* arg)
|
|||
//=========================================================================
|
||||
void* caribou_smi_thread(void *arg)
|
||||
{
|
||||
// --------------------------------------------
|
||||
// TIMING PERF VARIABLES
|
||||
#if (TIMING_PERF_SYNC)
|
||||
struct timeval tv_pre = {0};
|
||||
struct timeval tv_post = {0};
|
||||
long long total_samples = 0;
|
||||
long long last_total_samples = 0;
|
||||
double time_pre = 0, batch_time = 0, sample_rate = 0;
|
||||
double time_post = 0, process_time = 0;
|
||||
double temp_pre;
|
||||
double num_samples = 0, num_samples_avg = 0;
|
||||
#endif // TIMING_PERF_SYNC
|
||||
// --------------------------------------------
|
||||
TIMING_PERF_SYNC_VARS;
|
||||
|
||||
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 thread id %lu, running = %d, Perf-Verbosity = %d", tid, st->running, TIMING_PERF_SYNC);
|
||||
|
@ -498,13 +611,11 @@ void* caribou_smi_thread(void *arg)
|
|||
|
||||
// start thread notification
|
||||
if (st->data_cb != NULL) st->data_cb(dev->cb_context, st->service_context,
|
||||
caribou_smi_stream_start,
|
||||
ch,
|
||||
0,
|
||||
st->current_app_buffer,
|
||||
st->batch_length);
|
||||
caribou_smi_stream_start, ch, 0, NULL, NULL, 0);
|
||||
|
||||
// thread main loop
|
||||
// ****************************************
|
||||
// MAIN LOOP
|
||||
// ****************************************
|
||||
while (st->active)
|
||||
{
|
||||
if (!st->running)
|
||||
|
@ -513,12 +624,7 @@ void* caribou_smi_thread(void *arg)
|
|||
continue;
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
// TIMING PERF
|
||||
#if (TIMING_PERF_SYNC)
|
||||
gettimeofday(&tv_pre, NULL);
|
||||
#endif // TIMING_PERF_SYNC
|
||||
// --------------------------------------------
|
||||
TIMING_PERF_SYNC_TICK;
|
||||
|
||||
int ret = caribou_smi_timeout_read(dev, st->addr, (char*)st->current_smi_buffer, st->batch_length, 200);
|
||||
if (ret < 0)
|
||||
|
@ -546,30 +652,7 @@ void* caribou_smi_thread(void *arg)
|
|||
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];
|
||||
|
||||
// --------------------------------------------
|
||||
// TIMING PERF
|
||||
#if (TIMING_PERF_SYNC)
|
||||
gettimeofday(&tv_post, NULL);
|
||||
num_samples = (double)(st->read_ret_value) / 4.0;
|
||||
num_samples_avg = num_samples_avg*0.1 + num_samples*0.9;
|
||||
temp_pre = tv_pre.tv_sec + ((double)(tv_pre.tv_usec)) / 1e6;
|
||||
time_post = tv_post.tv_sec + ((double)(tv_post.tv_usec)) / 1e6;
|
||||
|
||||
batch_time = temp_pre - time_pre;
|
||||
sample_rate = sample_rate*0.1 + (num_samples / batch_time) * 0.9;
|
||||
process_time = process_time*0.1 + (time_post - temp_pre)*0.9;
|
||||
|
||||
time_pre = temp_pre;
|
||||
total_samples += st->read_ret_value;
|
||||
if ((total_samples - last_total_samples) > 4000000*4)
|
||||
{
|
||||
last_total_samples = total_samples;
|
||||
ZF_LOGD("sample_rate = %.2f SPS, process_time = %.2f usec"
|
||||
", num_samples_avg = %.1f",
|
||||
sample_rate, process_time * 1e6, num_samples_avg);
|
||||
}
|
||||
#endif // TIMING_PERF_SYNC
|
||||
// --------------------------------------------
|
||||
TIMING_PERF_SYNC_TOCK;
|
||||
}
|
||||
|
||||
st->read_analysis_thread_running = 0;
|
||||
|
@ -578,153 +661,14 @@ void* caribou_smi_thread(void *arg)
|
|||
pthread_mutex_destroy(&st->read_analysis_lock);
|
||||
|
||||
// exit thread notification
|
||||
if (st->data_cb != NULL) st->data_cb(dev->cb_context,
|
||||
st->service_context,
|
||||
caribou_smi_stream_end,
|
||||
(caribou_smi_channel_en)(st->stream_id>>1),
|
||||
0,
|
||||
st->current_app_buffer,
|
||||
st->batch_length);
|
||||
if (st->data_cb != NULL) st->data_cb(dev->cb_context, st->service_context,
|
||||
caribou_smi_stream_end, (caribou_smi_channel_en)(st->stream_id>>1),
|
||||
0, NULL, NULL, 0);
|
||||
|
||||
ZF_LOGD("Leaving thread id %lu", tid);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*#define TIMING_PERF_ASYNC (1)
|
||||
//=========================================================================
|
||||
void* caribou_smi_thread_async(void *arg)
|
||||
{
|
||||
// --------------------------------------------
|
||||
// TIMING PERF VARIABLES
|
||||
#if (TIMING_PERF_ASYNC)
|
||||
struct timeval tv_pre = {0};
|
||||
struct timeval tv_post = {0};
|
||||
long long total_samples = 0;
|
||||
double time_pre = 0, batch_time = 0, sample_rate = 0;
|
||||
double time_post = 0, process_time = 0;
|
||||
double temp_pre;
|
||||
double num_samples = 0, num_samples_avg = 0;
|
||||
#endif // TIMING_PERF_ASYNC
|
||||
// --------------------------------------------
|
||||
|
||||
pthread_t tid = pthread_self();
|
||||
struct aiocb read_aiocb = {0};
|
||||
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 thread id %lu, running = %d", tid, st->running);
|
||||
set_realtime_priority(0);
|
||||
|
||||
st->active = 1;
|
||||
|
||||
// start thread notification
|
||||
if (st->data_cb != NULL) st->data_cb(dev->cb_context, st->service_context,
|
||||
caribou_smi_stream_start,
|
||||
ch,
|
||||
0,
|
||||
st->current_app_buffer,
|
||||
st->batch_length);
|
||||
|
||||
// -------------------------------
|
||||
// THREAD MAIN LOOP
|
||||
// -------------------------------
|
||||
while (st->active)
|
||||
{
|
||||
if (!st->running)
|
||||
{
|
||||
usleep(1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
// TIMING PERF
|
||||
#if (TIMING_PERF_ASYNC)
|
||||
gettimeofday(&tv_pre, NULL);
|
||||
#endif // TIMING_PERF_ASYNC
|
||||
// --------------------------------------------
|
||||
|
||||
// Run the async read
|
||||
// This operation doesn't block and returns immediatelly
|
||||
// in the meantime we do other stuff and some back
|
||||
// to get the results later.
|
||||
int ret = caribou_smi_read_async(dev, st->addr,
|
||||
(char*)st->current_smi_buffer,
|
||||
st->batch_length,
|
||||
&read_aiocb);
|
||||
|
||||
if (ret < 0)
|
||||
{
|
||||
ZF_LOGE("async read failed");
|
||||
if (dev->error_cb) dev->error_cb(dev->cb_context, st->stream_id & 0x1, caribou_smi_error_read_failed);
|
||||
break;
|
||||
}
|
||||
|
||||
// analyze the last buffer that was accepted
|
||||
if (st->current_app_buffer)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// --------------------------------------------
|
||||
// TIMING PERF
|
||||
#if (TIMING_PERF_ASYNC)
|
||||
gettimeofday(&tv_post, NULL);
|
||||
num_samples = (double)(st->read_ret_value) / 4.0;
|
||||
num_samples_avg = num_samples_avg*0.1 + num_samples*0.9;
|
||||
temp_pre = tv_pre.tv_sec + ((double)(tv_pre.tv_usec)) / 1e6;
|
||||
time_post = tv_post.tv_sec + ((double)(tv_post.tv_usec)) / 1e6;
|
||||
|
||||
batch_time = temp_pre - time_pre;
|
||||
sample_rate = sample_rate*0.1 + (num_samples / batch_time) * 0.9;
|
||||
process_time = process_time*0.1 + (time_post - temp_pre)*0.9;
|
||||
|
||||
time_pre = temp_pre;
|
||||
total_samples += st->read_ret_value;
|
||||
if (total_samples % (4*4000000) == 0)
|
||||
{
|
||||
printf("sample_rate = %.2f SPS, process_time = %.2f usec"
|
||||
", num_samples_avg = %.1f\n",
|
||||
sample_rate, process_time * 1e6, num_samples_avg);
|
||||
}
|
||||
#endif // TIMING_PERF_ASYNC
|
||||
// --------------------------------------------
|
||||
|
||||
// wait for the async to complete
|
||||
struct aiocb* read_aiocb_vec[1];
|
||||
read_aiocb_vec[0] = &read_aiocb;
|
||||
ret = aio_suspend(read_aiocb_vec, 1, NULL);
|
||||
if (ret >= 0)
|
||||
{
|
||||
st->read_ret_value = st->batch_length;
|
||||
st->current_app_buffer = st->current_smi_buffer;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
// exit thread notification
|
||||
if (st->data_cb != NULL) st->data_cb(dev->cb_context,
|
||||
st->service_context,
|
||||
caribou_smi_stream_end,
|
||||
(caribou_smi_channel_en)(st->stream_id>>1),
|
||||
0,
|
||||
st->current_app_buffer,
|
||||
st->batch_length);
|
||||
|
||||
ZF_LOGD("Leaving thread id %lu", tid);
|
||||
return NULL;
|
||||
}*/
|
||||
|
||||
//=========================================================================
|
||||
static int caribou_smi_set_driver_streaming_state(caribou_smi_st* dev, int state)
|
||||
{
|
||||
|
@ -753,8 +697,10 @@ int caribou_smi_setup_stream(caribou_smi_st* dev,
|
|||
return 1;
|
||||
}
|
||||
|
||||
st->app_meta_vec = NULL;
|
||||
st->app_cmplx_vec = NULL;
|
||||
st->batch_length = dev->native_batch_length_bytes;
|
||||
st->num_of_buffers = 3;
|
||||
st->num_of_buffers = 2;
|
||||
st->data_cb = cb;
|
||||
|
||||
caribou_smi_set_driver_streaming_state(dev, 0);
|
||||
|
@ -766,6 +712,26 @@ int caribou_smi_setup_stream(caribou_smi_st* dev,
|
|||
return -1;
|
||||
}
|
||||
|
||||
// Allocate the complex vector and metadata vector
|
||||
st->app_cmplx_vec =
|
||||
(caribou_smi_sample_complex_int16*)malloc(sizeof(caribou_smi_sample_complex_int16) * st->batch_length / 4);
|
||||
if (st->app_cmplx_vec == NULL)
|
||||
{
|
||||
ZF_LOGE("application complex buffer allocation failed");
|
||||
release_buffer_vec(st->buffers, st->num_of_buffers, st->batch_length);
|
||||
return -1;
|
||||
}
|
||||
|
||||
st->app_meta_vec =
|
||||
(caribou_smi_sample_meta*)malloc(sizeof(caribou_smi_sample_meta) * st->batch_length / 4);
|
||||
if (st->app_meta_vec == NULL)
|
||||
{
|
||||
ZF_LOGE("application meta-data buffer allocation failed");
|
||||
release_buffer_vec(st->buffers, st->num_of_buffers, st->batch_length);
|
||||
free(st->app_cmplx_vec);
|
||||
return -1;
|
||||
}
|
||||
|
||||
st->current_smi_buffer_index = 0;
|
||||
st->current_smi_buffer = st->buffers[0];
|
||||
st->current_app_buffer = st->buffers[st->num_of_buffers-1];
|
||||
|
@ -779,6 +745,8 @@ int caribou_smi_setup_stream(caribou_smi_st* dev,
|
|||
{
|
||||
ZF_LOGE("read stream thread creation failed");
|
||||
release_buffer_vec(st->buffers, st->num_of_buffers, st->batch_length);
|
||||
free(st->app_cmplx_vec);
|
||||
free(st->app_meta_vec);
|
||||
st->buffers = NULL;
|
||||
st->active = 0;
|
||||
st->running = 0;
|
||||
|
@ -869,7 +837,11 @@ int caribou_smi_destroy_stream(caribou_smi_st* dev, int id)
|
|||
}
|
||||
|
||||
release_buffer_vec(dev->streams[id].buffers, dev->streams[id].num_of_buffers, dev->streams[id].batch_length);
|
||||
|
||||
free(dev->streams[id].app_cmplx_vec);
|
||||
free(dev->streams[id].app_meta_vec);
|
||||
|
||||
dev->streams[id].app_cmplx_vec = NULL;
|
||||
dev->streams[id].app_meta_vec = NULL;
|
||||
dev->streams[id].buffers = NULL;
|
||||
dev->streams[id].current_smi_buffer = NULL;
|
||||
dev->streams[id].current_app_buffer = NULL;
|
||||
|
@ -934,50 +906,7 @@ static void caribou_smi_setup_settings (caribou_smi_st* dev, struct smi_settings
|
|||
settings->dma_enable = 1;
|
||||
settings->pack_data = 1;
|
||||
settings->dma_passthrough_enable = 1;
|
||||
|
||||
//settings->dma_read_thresh = 1;
|
||||
//settings->dma_write_thresh = 1;
|
||||
//settings->dma_panic_read_thresh = 1;
|
||||
//settings->dma_panic_write_thresh = 1;
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
void dump_hex(const void* data, size_t size)
|
||||
{
|
||||
char ascii[17];
|
||||
size_t i, j;
|
||||
ascii[16] = '\0';
|
||||
for (i = 0; i < size; ++i) {
|
||||
printf("%02X ", ((unsigned char*)data)[i]);
|
||||
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~')
|
||||
{
|
||||
ascii[i % 16] = ((unsigned char*)data)[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
ascii[i % 16] = '.';
|
||||
}
|
||||
if ((i+1) % 8 == 0 || i+1 == size)
|
||||
{
|
||||
printf(" ");
|
||||
if ((i+1) % 16 == 0)
|
||||
{
|
||||
printf("| %s \n", ascii);
|
||||
}
|
||||
else if (i+1 == size)
|
||||
{
|
||||
ascii[(i+1) % 16] = '\0';
|
||||
if ((i+1) % 16 <= 8)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
for (j = (i+1) % 16; j < 16; ++j)
|
||||
{
|
||||
printf(" ");
|
||||
}
|
||||
printf("| %s \n", ascii);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,18 +41,37 @@ typedef enum
|
|||
caribou_smi_error_read_failed = 0,
|
||||
} caribou_smi_error_en;
|
||||
|
||||
#pragma pack(1)
|
||||
// associated with CS16 - total 4 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int16_t i; // LSB
|
||||
int16_t q; // MSB
|
||||
} caribou_smi_sample_complex_int16;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint8_t cnt : 2;
|
||||
uint8_t sync1 : 1;
|
||||
uint8_t sync2 : 1;
|
||||
uint8_t res : 4;
|
||||
} caribou_smi_sample_meta;
|
||||
#pragma pack()
|
||||
|
||||
#define CARIBOU_SMI_ERROR_STRS { \
|
||||
"reading from SMI source failed", \
|
||||
}
|
||||
|
||||
typedef void (*caribou_smi_data_callback)( void *ctx, // The context of the requesting application
|
||||
void *serviced_context, // the context of the session within the app
|
||||
caribou_smi_stream_type_en type, // which type of stream is it? read / write?
|
||||
caribou_smi_channel_en ch, // which channel (900 / 2400)
|
||||
uint32_t byte_count, // for "read stream only" - number of read data bytes in buffer
|
||||
uint8_t *buffer, // for "read" - data buffer to be analyzed
|
||||
// for "write" - the data buffer to be filled with information
|
||||
uint32_t buffer_len_bytes); // the total size of the buffer
|
||||
typedef void (*caribou_smi_data_callback)( void *ctx, // The context of the requesting application
|
||||
void *serviced_context, // the context of the session within the app
|
||||
caribou_smi_stream_type_en type, // which type of stream is it? read / write?
|
||||
caribou_smi_channel_en ch, // which channel (900 / 2400)
|
||||
size_t num_samples, // for "read stream only" - number of read data bytes in buffer
|
||||
caribou_smi_sample_complex_int16 *cplx_vec, // for "read" - complex vector of samples to be analyzed
|
||||
// for "write" - complex vector of samples to be written into
|
||||
caribou_smi_sample_meta *metadat_vec, // for "read" - the metadata send by the receiver for each sample
|
||||
// for "write" - the metadata to be written by app for each sample
|
||||
size_t total_length_samples); // The capacity (in terms of samples) in the above vectors
|
||||
|
||||
typedef void (*caribou_smi_error_callback)( void *ctx,
|
||||
caribou_smi_channel_en ch,
|
||||
|
@ -73,6 +92,9 @@ typedef struct
|
|||
uint8_t *current_smi_buffer; // the buffer that is currently in the SMI DMA
|
||||
uint8_t *current_app_buffer; // the buffer that is currently analyzed / written by the application callback
|
||||
|
||||
caribou_smi_sample_complex_int16* app_cmplx_vec;
|
||||
caribou_smi_sample_meta* app_meta_vec;
|
||||
|
||||
int active; // the thread is active
|
||||
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
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -348,7 +348,7 @@ int cariboulite_init_submodules (cariboulite_st* sys)
|
|||
|
||||
at86rf215_iq_interface_config_st modem_iq_config = {
|
||||
.loopback_enable = 0,
|
||||
.drv_strength = at86rf215_iq_drive_current_2ma,
|
||||
.drv_strength = at86rf215_iq_drive_current_4ma,
|
||||
.common_mode_voltage = at86rf215_iq_common_mode_v_ieee1596_1v2,
|
||||
.tx_control_with_iq_if = false,
|
||||
.radio09_mode = at86rf215_iq_if_mode,
|
||||
|
|
|
@ -10,15 +10,6 @@
|
|||
#define IS_POWER_OF_2(x) (!((x) == 0) && !((x) & ((x) - 1)))
|
||||
#define MIN(x,y) ((x)>(y)?(y):(x))
|
||||
|
||||
uint32_t next_power_of_2 (uint32_t x)
|
||||
{
|
||||
uint32_t power = 1;
|
||||
while(power < x)
|
||||
{
|
||||
power <<= 1;
|
||||
}
|
||||
return power;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
class circular_buffer {
|
||||
|
@ -142,6 +133,17 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
private:
|
||||
uint32_t next_power_of_2 (uint32_t x)
|
||||
{
|
||||
uint32_t power = 1;
|
||||
while(power < x)
|
||||
{
|
||||
power <<= 1;
|
||||
}
|
||||
return power;
|
||||
}
|
||||
|
||||
private:
|
||||
std::mutex mutex_;
|
||||
std::condition_variable cond_var_;
|
||||
|
|
|
@ -30,11 +30,8 @@ enum Cariboulite_Format
|
|||
CARIBOULITE_FORMAT_FLOAT64 = 3,
|
||||
};
|
||||
|
||||
//#define BUFFER_SIZE_MS ( 10 )
|
||||
#define NUM_SAMPLEQUEUE_BUFS ( 3 )
|
||||
#define NUM_BYTES_PER_CPLX_ELEM ( 4 )
|
||||
//#define GET_MTU_MS(ms) ( 4000*(ms) )
|
||||
//#define GET_MTU_MS_BYTES(ms) ( GET_MTU_MS(ms) * NUM_BYTES_PER_CPLX_ELEM )
|
||||
|
||||
#pragma pack(1)
|
||||
// associated with CS8 - total 2 bytes / element
|
||||
|
@ -51,13 +48,6 @@ typedef struct
|
|||
int16_t q :12; // MSB
|
||||
} sample_complex_int12;
|
||||
|
||||
// associated with CS16 - total 4 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
int16_t i; // LSB
|
||||
int16_t q; // MSB
|
||||
} sample_complex_int16;
|
||||
|
||||
// associated with CS32 - total 8 bytes / element
|
||||
typedef struct
|
||||
{
|
||||
|
@ -99,10 +89,10 @@ public:
|
|||
SampleQueue(int mtu_bytes, int num_buffers);
|
||||
~SampleQueue();
|
||||
int AttachStreamId(int id, int dir, int channel);
|
||||
int Write(uint8_t *buffer, size_t length, uint32_t meta, long timeout_us);
|
||||
int Read(uint8_t *buffer, size_t length, uint32_t *meta, long timeout_us);
|
||||
int Write(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t* meta, long timeout_us);
|
||||
int Read(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t *meta, long timeout_us);
|
||||
|
||||
int ReadSamples(sample_complex_int16* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(caribou_smi_sample_complex_int16* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_float* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_double* buffer, size_t num_elements, long timeout_us);
|
||||
int ReadSamples(sample_complex_int8* buffer, size_t num_elements, long timeout_us);
|
||||
|
@ -114,13 +104,13 @@ public:
|
|||
Cariboulite_Format chosen_format;
|
||||
int dig_filt;
|
||||
private:
|
||||
circular_buffer<sample_complex_int16> *queue;
|
||||
circular_buffer<caribou_smi_sample_complex_int16> *queue;
|
||||
size_t mtu_size_bytes;
|
||||
uint8_t *partial_buffer;
|
||||
int partial_buffer_start;
|
||||
int partial_buffer_length;
|
||||
|
||||
sample_complex_int16 *interm_native_buffer;
|
||||
caribou_smi_sample_complex_int16 *interm_native_buffer;
|
||||
#define FILT_ORDER 6
|
||||
#define FILT_ORDER1 8
|
||||
Iir::Butterworth::LowPass<FILT_ORDER> filt20_i;
|
||||
|
|
|
@ -2,34 +2,11 @@
|
|||
#include <Iir.h>
|
||||
#include <byteswap.h>
|
||||
|
||||
|
||||
|
||||
//==============================================
|
||||
void print_iq(uint32_t* array, int len)
|
||||
{
|
||||
//printf("Values I/Q:\n");
|
||||
for (int i=0; i<len; i++)
|
||||
{
|
||||
unsigned int v = array[i];
|
||||
//swap_little_big (&v);
|
||||
|
||||
int16_t q_val = (v>> 1) & (0x1FFF);
|
||||
int16_t i_val = (v>>17) & (0x1FFF);
|
||||
if (q_val >= 0x1000) q_val-=0x2000;
|
||||
if (i_val >= 0x1000) i_val-=0x2000;
|
||||
float fi = i_val, fq = q_val;
|
||||
float mod = sqrt(fi*fi + fq*fq);
|
||||
float arg = atan2(fq, fi);
|
||||
printf("(%d, %d), ", i_val, q_val);
|
||||
if ((i % 32) == 0) printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
SampleQueue::SampleQueue(int mtu_bytes, int num_buffers)
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_INFO, "Creating SampleQueue MTU: %d bytes, NumBuffers: %d", mtu_bytes, num_buffers);
|
||||
queue = new circular_buffer(mtu_bytes / 4 * num_buffers)
|
||||
queue = new circular_buffer<caribou_smi_sample_complex_int16>(mtu_bytes / 4 * num_buffers*10);
|
||||
mtu_size_bytes = mtu_bytes;
|
||||
stream_id = -1;
|
||||
stream_dir = -1;
|
||||
|
@ -42,7 +19,7 @@ SampleQueue::SampleQueue(int mtu_bytes, int num_buffers)
|
|||
|
||||
// a buffer for conversion betwen native and emulated formats
|
||||
// the maximal size is the 2*(mtu_size in bytes)
|
||||
interm_native_buffer = new sample_complex_int16[2*mtu_size_bytes];
|
||||
interm_native_buffer = new caribou_smi_sample_complex_int16[2*mtu_size_bytes];
|
||||
is_cw = 0;
|
||||
|
||||
filt20_i.setup(4e6, 20e3/2);
|
||||
|
@ -61,9 +38,6 @@ SampleQueue::SampleQueue(int mtu_bytes, int num_buffers)
|
|||
//=================================================================
|
||||
SampleQueue::~SampleQueue()
|
||||
{
|
||||
//printf("~SampleQueue streamID: %d, dir: %d, channel: %d\n", stream_id, stream_dir, stream_channel);
|
||||
//SoapySDR_logf(SOAPY_SDR_INFO, "~SampleQueue streamID: %d, dir: %d, channel: %d", stream_id, stream_dir, stream_channel);
|
||||
|
||||
stream_id = -1;
|
||||
stream_dir = -1;
|
||||
stream_channel = -1;
|
||||
|
@ -88,131 +62,35 @@ int SampleQueue::AttachStreamId(int id, int dir, int channel)
|
|||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::Write(sample_complex_int16 *buffer, size_t num_samples, uint8_t* meta, long timeout_us)
|
||||
int SampleQueue::Write(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t* meta, long timeout_us)
|
||||
{
|
||||
return queue->put(buffer, elements)
|
||||
return queue->put(buffer, num_samples);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::Read(uint8_t *buffer, size_t length, uint32_t *meta, long timeout_us)
|
||||
int SampleQueue::Read(caribou_smi_sample_complex_int16 *buffer, size_t num_samples, uint8_t *meta, long timeout_us)
|
||||
{
|
||||
tsqueue_item_st* item_ptr = NULL;
|
||||
int left_to_read = length;
|
||||
int read_so_far = 0;
|
||||
int chunk = 0;
|
||||
|
||||
// first read out from partial buffer
|
||||
int amount_to_read_from_partial = (left_to_read <= partial_buffer_length) ?
|
||||
left_to_read : partial_buffer_length;
|
||||
memcpy (buffer, partial_buffer + partial_buffer_start, amount_to_read_from_partial);
|
||||
left_to_read -= amount_to_read_from_partial;
|
||||
partial_buffer_length -= amount_to_read_from_partial;
|
||||
partial_buffer_start += amount_to_read_from_partial;
|
||||
read_so_far += amount_to_read_from_partial;
|
||||
|
||||
// read from the queue
|
||||
while (left_to_read)
|
||||
{
|
||||
int res = tsqueue_pop_item(&queue, &item_ptr, timeout_us);
|
||||
switch (res)
|
||||
{
|
||||
case TSQUEUE_NOT_INITIALIZED:
|
||||
case TSQUEUE_SEM_FAILED:
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_ERROR, "popping buffer %d failed", chunk);
|
||||
return -1;
|
||||
} break;
|
||||
case TSQUEUE_TIMEOUT:
|
||||
case TSQUEUE_FAILED_EMPTY: return read_so_far; break;
|
||||
default: break;
|
||||
}
|
||||
if (meta) *meta = item_ptr->metadata;
|
||||
|
||||
// if we need more or exactly the mtu size
|
||||
if (left_to_read >= item_ptr->length)
|
||||
{
|
||||
memcpy(&buffer[read_so_far], item_ptr->data, item_ptr->length);
|
||||
left_to_read -= item_ptr->length;
|
||||
read_so_far += item_ptr->length;
|
||||
}
|
||||
// if we need less than the mtu size - store the residue for next time
|
||||
else
|
||||
{
|
||||
// copy out only the amount that is needed
|
||||
memcpy(&buffer[read_so_far], item_ptr->data, left_to_read);
|
||||
|
||||
// we are left with "item_ptr->length - left_to_read" bytes
|
||||
// which will be stored for future requests
|
||||
|
||||
// store the residue in the partial buffer - for the next time
|
||||
partial_buffer_length = item_ptr->length - left_to_read;
|
||||
partial_buffer_start = (int)mtu_size_bytes - partial_buffer_length;
|
||||
memcpy (partial_buffer + partial_buffer_start,
|
||||
item_ptr->data + left_to_read,
|
||||
partial_buffer_length);
|
||||
|
||||
read_so_far += left_to_read;
|
||||
left_to_read = 0;
|
||||
}
|
||||
chunk ++;
|
||||
}
|
||||
|
||||
return read_so_far;
|
||||
return queue->get(buffer, num_samples);
|
||||
}
|
||||
|
||||
//=================================================================
|
||||
int SampleQueue::ReadSamples(sample_complex_int16* buffer, size_t num_elements, long timeout_us)
|
||||
int SampleQueue::ReadSamples(caribou_smi_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);
|
||||
|
||||
int res = Read(buffer, num_elements, NULL, timeout_us);
|
||||
if (res < 0)
|
||||
{
|
||||
// todo!!
|
||||
return res;
|
||||
}
|
||||
|
||||
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 = 1; i < tot_read_elements; i+=2)
|
||||
{
|
||||
short t = buffer[i].i;
|
||||
buffer[i].i = buffer[i+1].i;
|
||||
buffer[i+1].i = t;
|
||||
t = buffer[i].q;
|
||||
buffer[i].q = buffer[i+1].q;
|
||||
buffer[i+1].q = t;
|
||||
}*/
|
||||
|
||||
/*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;
|
||||
buffer[i].q >>= 1;
|
||||
|
||||
buffer[i].i = buffer[i].i & 0x1FFF;
|
||||
buffer[i].q = buffer[i].q & 0x1FFF;
|
||||
|
||||
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;
|
||||
}
|
||||
int tot_read_elements = res;
|
||||
|
||||
return tot_read_elements;
|
||||
|
||||
// digital filters - TBD
|
||||
if (dig_filt == 0)
|
||||
{
|
||||
for (int i = 0; i < res; i++)
|
||||
|
@ -260,7 +138,7 @@ int SampleQueue::ReadSamples(sample_complex_int16* buffer, size_t num_elements,
|
|||
//=================================================================
|
||||
int SampleQueue::ReadSamples(sample_complex_float* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(sample_complex_int16));
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(caribou_smi_sample_complex_int16));
|
||||
|
||||
// do not allow to store more than is possible in the intermediate buffer
|
||||
if (num_elements > max_native_samples)
|
||||
|
@ -332,7 +210,7 @@ int SampleQueue::ReadSamples(sample_complex_float* buffer, size_t num_elements,
|
|||
//=================================================================
|
||||
int SampleQueue::ReadSamples(sample_complex_double* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(sample_complex_int16));
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(caribou_smi_sample_complex_int16));
|
||||
|
||||
// do not allow to store more than is possible in the intermediate buffer
|
||||
if (num_elements > max_native_samples)
|
||||
|
@ -362,7 +240,7 @@ int SampleQueue::ReadSamples(sample_complex_double* buffer, size_t num_elements,
|
|||
//=================================================================
|
||||
int SampleQueue::ReadSamples(sample_complex_int8* buffer, size_t num_elements, long timeout_us)
|
||||
{
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(sample_complex_int16));
|
||||
uint32_t max_native_samples = 2*(mtu_size_bytes / sizeof(caribou_smi_sample_complex_int16));
|
||||
|
||||
// do not allow to store more than is possible in the intermediate buffer
|
||||
if (num_elements > max_native_samples)
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
#include "Cariboulite.hpp"
|
||||
#include "cariboulite_config/cariboulite_config_default.h"
|
||||
|
||||
|
||||
//=================================================================
|
||||
static void caribou_stream_data_event( void *ctx,
|
||||
void *service_context,
|
||||
caribou_smi_stream_type_en type,
|
||||
caribou_smi_channel_en ch,
|
||||
uint32_t byte_count,
|
||||
uint8_t *buffer,
|
||||
uint32_t buffer_len_bytes)
|
||||
size_t sample_count,
|
||||
caribou_smi_sample_complex_int16 *cmplx_vec,
|
||||
caribou_smi_sample_meta *meta_vec,
|
||||
size_t buffers_capacity_samples)
|
||||
{
|
||||
cariboulite_st* sys = (cariboulite_st*)ctx;
|
||||
Cariboulite *obj = (Cariboulite*)service_context;
|
||||
|
@ -23,7 +23,7 @@ static void caribou_stream_data_event( void *ctx,
|
|||
case caribou_smi_stream_type_read:
|
||||
{
|
||||
int sample_queue_index = CARIBOU_SMI_GET_STREAM_ID(type, ch);
|
||||
obj->sample_queues[sample_queue_index]->Write(buffer, buffer_len_bytes, 0, 10000L);
|
||||
obj->sample_queues[sample_queue_index]->Write(cmplx_vec, sample_count, 0, 10000L);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -38,16 +38,16 @@ static void caribou_stream_data_event( void *ctx,
|
|||
//-------------------------------------------------------
|
||||
case caribou_smi_stream_start:
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_DEBUG, "start event: stream channel %d, batch length: %d bytes",
|
||||
ch, buffer_len_bytes);
|
||||
SoapySDR_logf(SOAPY_SDR_DEBUG, "start event: stream channel %d, batch length: %d samples",
|
||||
ch, buffers_capacity_samples);
|
||||
}
|
||||
break;
|
||||
|
||||
//-------------------------------------------------------
|
||||
case caribou_smi_stream_end:
|
||||
{
|
||||
SoapySDR_logf(SOAPY_SDR_DEBUG, "end event: stream channel %d, batch length: %d bytes",
|
||||
ch, buffer_len_bytes);
|
||||
SoapySDR_logf(SOAPY_SDR_DEBUG, "end event: stream channel %d, batch length: %d sample",
|
||||
ch, buffers_capacity_samples);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -278,7 +278,7 @@ void Cariboulite::closeStream(SoapySDR::Stream *stream)
|
|||
size_t Cariboulite::getStreamMTU(SoapySDR::Stream *stream) const
|
||||
{
|
||||
//printf("getStreamMTU\n");
|
||||
return 1024 * 1024 / 2 / 4; // # milliseconds of buffer
|
||||
return 1024 * 1024 / 2 / 4;
|
||||
}
|
||||
|
||||
//========================================================
|
||||
|
@ -399,7 +399,7 @@ int Cariboulite::readStream(
|
|||
}
|
||||
break;
|
||||
case CARIBOULITE_FORMAT_INT16:
|
||||
res = sample_queues[stream_id]->ReadSamples((sample_complex_int16*)buffs[0], numElems, timeoutUs);
|
||||
res = sample_queues[stream_id]->ReadSamples((caribou_smi_sample_complex_int16*)buffs[0], numElems, timeoutUs);
|
||||
break;
|
||||
case CARIBOULITE_FORMAT_INT8:
|
||||
res = sample_queues[stream_id]->ReadSamples((sample_complex_int8*)buffs[0], numElems, timeoutUs);
|
||||
|
|
Ładowanie…
Reference in New Issue