bug_fixes_integration_tx
David Michaeli 2022-01-03 21:38:43 +02:00
commit a3b7e6b377
14 zmienionych plików z 28697 dodań i 16866 usunięć

Wyświetl plik

@ -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()

Wyświetl plik

@ -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

Plik diff jest za duży Load Diff

Plik binarny nie jest wyświetlany.

Plik diff jest za duży Load Diff

Wyświetl plik

@ -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);
}
}
}
}

Wyświetl plik

@ -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

Wyświetl plik

@ -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,

Wyświetl plik

@ -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_;

Wyświetl plik

@ -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;

Wyświetl plik

@ -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)

Wyświetl plik

@ -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);