- add PUSCH/PUCCH plots
- update X events management - lock to protect data while plotting (may become a problem in the future) - better naming of dimensions this commit should be cut in small pieces bah
This commit is contained in:
@@ -7,6 +7,14 @@ ID = ENB_UL_CHANNEL_ESTIMATE
|
|||||||
DESC = eNodeB channel estimation in the time domain
|
DESC = eNodeB channel estimation in the time domain
|
||||||
GROUP = PHY:GRAPHIC:HEAVY
|
GROUP = PHY:GRAPHIC:HEAVY
|
||||||
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
|
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,antenna : buffer,chest_t
|
||||||
|
ID = PUSCH_IQ
|
||||||
|
DESC = eNodeB PUSCH received IQ data
|
||||||
|
GROUP = PHY:GRAPHIC:HEAVY
|
||||||
|
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,nb_rb : buffer,pusch_comp
|
||||||
|
ID = PUCCH_1AB_IQ
|
||||||
|
DESC = eNodeB PUCCH received IQ data
|
||||||
|
GROUP = PHY:GRAPHIC:HEAVY
|
||||||
|
FORMAT = int,eNB_ID : int,UE_ID : int,frame : int,subframe : int,I : int,Q
|
||||||
|
|
||||||
#legacy logs
|
#legacy logs
|
||||||
ID = LEGACY_MAC_INFO
|
ID = LEGACY_MAC_INFO
|
||||||
|
|||||||
+7
-1
@@ -1,9 +1,15 @@
|
|||||||
#ifndef _TRACER_DEFS_H_
|
#ifndef _TRACER_DEFS_H_
|
||||||
#define _TRACER_DEFS_H_
|
#define _TRACER_DEFS_H_
|
||||||
|
|
||||||
void *make_plot(int width, int height, int bufsize, char *title);
|
/* types of plots */
|
||||||
|
#define PLOT_VS_TIME 0
|
||||||
|
#define PLOT_IQ_POINTS 1
|
||||||
|
|
||||||
|
void *make_plot(int width, int height, int bufsize, char *title, int type);
|
||||||
void plot_set(void *plot, float *data, int len, int pos);
|
void plot_set(void *plot, float *data, int len, int pos);
|
||||||
void iq_plot_set(void *plot, short *data, int len, int pos);
|
void iq_plot_set(void *plot, short *data, int len, int pos);
|
||||||
|
void iq_plot_set_sized(void *_plot, short *data, int len);
|
||||||
|
void iq_plot_add_point_loop(void *_plot, short i, short q);
|
||||||
|
|
||||||
/* returns an opaque pointer - truly a 'database *', see t_data.c */
|
/* returns an opaque pointer - truly a 'database *', see t_data.c */
|
||||||
void *parse_database(char *filename);
|
void *parse_database(char *filename);
|
||||||
|
|||||||
+45
-2
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
void *ul_plot;
|
void *ul_plot;
|
||||||
void *chest_plot;
|
void *chest_plot;
|
||||||
|
void *pusch_iq_plot;
|
||||||
|
void *pucch_iq_plot;
|
||||||
|
|
||||||
#ifdef T_USE_SHARED_MEMORY
|
#ifdef T_USE_SHARED_MEMORY
|
||||||
|
|
||||||
@@ -236,6 +238,44 @@ void get_message(int s)
|
|||||||
if (chest_plot) iq_plot_set(chest_plot, (short*)buf, 512, 0);
|
if (chest_plot) iq_plot_set(chest_plot, (short*)buf, 512, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case T_PUSCH_IQ: {
|
||||||
|
unsigned char buf[T_BUFFER_MAX];
|
||||||
|
int size;
|
||||||
|
int eNB, UE, frame, subframe, nb_rb;
|
||||||
|
GET(s, &eNB, sizeof(int));
|
||||||
|
GET(s, &UE, sizeof(int));
|
||||||
|
GET(s, &frame, sizeof(int));
|
||||||
|
GET(s, &subframe, sizeof(int));
|
||||||
|
GET(s, &nb_rb, sizeof(int));
|
||||||
|
GET(s, &size, sizeof(int));
|
||||||
|
GET(s, buf, size);
|
||||||
|
if (size != 12*25*14*4)
|
||||||
|
{printf("bad T_PUSCH_IQ, we want 25 RBs and 14 symbols/TTI\n");
|
||||||
|
abort();}
|
||||||
|
if (pusch_iq_plot) {
|
||||||
|
uint32_t *src, *dst;
|
||||||
|
int i, l;
|
||||||
|
dst = (uint32_t*)buf;
|
||||||
|
for (l = 0; l < 14; l++) {
|
||||||
|
src = (uint32_t*)buf + l * 12 * 25;
|
||||||
|
for (i = 0; i < nb_rb*12; i++) *dst++ = *src++;
|
||||||
|
}
|
||||||
|
iq_plot_set_sized(pusch_iq_plot, (short*)buf, nb_rb*12*14);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case T_PUCCH_1AB_IQ: {
|
||||||
|
int eNB, UE, frame, subframe, I, Q;
|
||||||
|
GET(s, &eNB, sizeof(int));
|
||||||
|
GET(s, &UE, sizeof(int));
|
||||||
|
GET(s, &frame, sizeof(int));
|
||||||
|
GET(s, &subframe, sizeof(int));
|
||||||
|
GET(s, &I, sizeof(int));
|
||||||
|
GET(s, &Q, sizeof(int));
|
||||||
|
printf("receiving %d %d\n", I, Q);
|
||||||
|
if (pucch_iq_plot) iq_plot_add_point_loop(pucch_iq_plot, I*10, Q*10);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case T_buf_test: {
|
case T_buf_test: {
|
||||||
unsigned char buf[T_BUFFER_MAX];
|
unsigned char buf[T_BUFFER_MAX];
|
||||||
int size;
|
int size;
|
||||||
@@ -345,8 +385,11 @@ int main(int n, char **v)
|
|||||||
if (do_dump_database) { dump_database(database); return 0; }
|
if (do_dump_database) { dump_database(database); return 0; }
|
||||||
|
|
||||||
if (do_xforms) {
|
if (do_xforms) {
|
||||||
ul_plot = make_plot(512, 100, 7680*2*10, "UL Input Signal");
|
ul_plot = make_plot(512, 100, 7680*10, "UL Input Signal", PLOT_VS_TIME);
|
||||||
chest_plot = make_plot(512, 100, 512*2, "UL Channel Estimate UE 0");
|
chest_plot = make_plot(512, 100, 512, "UL Channel Estimate UE 0",
|
||||||
|
PLOT_VS_TIME);
|
||||||
|
pusch_iq_plot = make_plot(100, 100, 12*25*14, "PUSCH IQ",PLOT_IQ_POINTS);
|
||||||
|
pucch_iq_plot = make_plot(100, 100, 1000, "PUCCH IQ", PLOT_IQ_POINTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < on_off_n; i++)
|
for (i = 0; i < on_off_n; i++)
|
||||||
|
|||||||
+144
-32
@@ -6,6 +6,8 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
Display *d;
|
Display *d;
|
||||||
@@ -15,50 +17,117 @@ typedef struct {
|
|||||||
int height;
|
int height;
|
||||||
float *buf;
|
float *buf;
|
||||||
short *iqbuf;
|
short *iqbuf;
|
||||||
int bufsize;
|
int count;
|
||||||
|
int type;
|
||||||
|
volatile int iq_count; /* for ULSCH IQ data */
|
||||||
|
int iq_insert_pos;
|
||||||
|
pthread_mutex_t lock;
|
||||||
|
float zoom;
|
||||||
|
int timer_pipe[2];
|
||||||
} plot;
|
} plot;
|
||||||
|
|
||||||
|
static void *timer_thread(void *_p)
|
||||||
|
{
|
||||||
|
plot *p = _p;
|
||||||
|
char c;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
/* more or less 10Hz */
|
||||||
|
usleep(100*1000);
|
||||||
|
c = 1;
|
||||||
|
if (write(p->timer_pipe[1], &c, 1) != 1) abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static void *plot_thread(void *_p)
|
static void *plot_thread(void *_p)
|
||||||
{
|
{
|
||||||
float v;
|
float v;
|
||||||
float *s;
|
float *s;
|
||||||
int i, j;
|
int i, j;
|
||||||
plot *p = _p;
|
plot *p = _p;
|
||||||
|
int redraw = 0;
|
||||||
|
int replot = 0;
|
||||||
|
fd_set rset;
|
||||||
|
int xfd = ConnectionNumber(p->d);
|
||||||
|
int maxfd = xfd > p->timer_pipe[0] ? xfd : p->timer_pipe[0];
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
while (XPending(p->d)) {
|
while (XPending(p->d)) {
|
||||||
XEvent e;
|
XEvent e;
|
||||||
XNextEvent(p->d, &e);
|
XNextEvent(p->d, &e);
|
||||||
|
switch (e.type) {
|
||||||
|
case ButtonPress:
|
||||||
|
/* button 4: zoom out */
|
||||||
|
if (e.xbutton.button == 4) { p->zoom = p->zoom * 1.25; replot = 1; }
|
||||||
|
/* button 5: zoom in */
|
||||||
|
if (e.xbutton.button == 5) { p->zoom = p->zoom * 0.8; replot = 1; }
|
||||||
|
printf("zoom: %f\n", p->zoom);
|
||||||
|
break;
|
||||||
|
case Expose: redraw = 1; break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (replot == 1) {
|
||||||
|
replot = 0;
|
||||||
|
redraw = 1;
|
||||||
|
|
||||||
/* TODO: get white & black GCs at startup */
|
/* TODO: get white & black GCs at startup */
|
||||||
GC gc;
|
{
|
||||||
XGCValues v;
|
GC gc;
|
||||||
gc = DefaultGC(p->d, DefaultScreen(p->d));
|
XGCValues v;
|
||||||
v.foreground = WhitePixel(p->d, DefaultScreen(p->d));
|
gc = DefaultGC(p->d, DefaultScreen(p->d));
|
||||||
XChangeGC(p->d, gc, GCForeground, &v);
|
v.foreground = WhitePixel(p->d, DefaultScreen(p->d));
|
||||||
XFillRectangle(p->d, p->p, gc, 0, 0, p->width, p->height);
|
XChangeGC(p->d, gc, GCForeground, &v);
|
||||||
v.foreground = BlackPixel(p->d, DefaultScreen(p->d));
|
XFillRectangle(p->d, p->p, gc, 0, 0, p->width, p->height);
|
||||||
XChangeGC(p->d, gc, GCForeground, &v);
|
v.foreground = BlackPixel(p->d, DefaultScreen(p->d));
|
||||||
|
XChangeGC(p->d, gc, GCForeground, &v);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_mutex_lock(&p->lock)) abort();
|
||||||
|
|
||||||
|
if (p->type == PLOT_VS_TIME) {
|
||||||
|
for (i = 0; i < p->count; i++)
|
||||||
|
p->buf[i] = 10*log10(1.0+(float)(p->iqbuf[2*i]*p->iqbuf[2*i]+
|
||||||
|
p->iqbuf[2*i+1]*p->iqbuf[2*i+1]));
|
||||||
|
s = p->buf;
|
||||||
|
for (i = 0; i < 512; i++) {
|
||||||
|
v = 0;
|
||||||
|
for (j = 0; j < p->count/512; j++, s++) v += *s;
|
||||||
|
v /= p->count/512;
|
||||||
|
XDrawLine(p->d, p->p, DefaultGC(p->d, DefaultScreen(p->d)),
|
||||||
|
i, 100, i, 100-v);
|
||||||
|
}
|
||||||
|
} else if (p->type == PLOT_IQ_POINTS) {
|
||||||
|
XPoint pts[p->iq_count];
|
||||||
|
int count = p->iq_count;
|
||||||
|
for (i = 0; i < count; i++) {
|
||||||
|
pts[i].x = p->iqbuf[2*i]*p->zoom/20+50;
|
||||||
|
pts[i].y = -p->iqbuf[2*i+1]*p->zoom/20+50;
|
||||||
|
}
|
||||||
|
XDrawPoints(p->d, p->p, DefaultGC(p->d, DefaultScreen(p->d)),
|
||||||
|
pts, count, CoordModeOrigin);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
if (redraw) {
|
||||||
int i;
|
redraw = 0;
|
||||||
for (i = 0; i < p->bufsize/2; i++)
|
XCopyArea(p->d, p->p, p->w, DefaultGC(p->d, DefaultScreen(p->d)),
|
||||||
p->buf[i] = 10*log10(1.0+(float)(p->iqbuf[2*i]*p->iqbuf[2*i]+
|
0, 0, p->width, p->height, 0, 0);
|
||||||
p->iqbuf[2*i+1]*p->iqbuf[2*i+1]));
|
|
||||||
}
|
|
||||||
s = p->buf;
|
|
||||||
for (i = 0; i < 512; i++) {
|
|
||||||
v = 0;
|
|
||||||
for (j = 0; j < p->bufsize/2/512; j++, s++) v += *s;
|
|
||||||
v /= p->bufsize/2/512;
|
|
||||||
XDrawLine(p->d, p->p, DefaultGC(p->d, DefaultScreen(p->d)), i, 100, i, 100-v);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
XCopyArea(p->d, p->p, p->w, DefaultGC(p->d, DefaultScreen(p->d)),
|
FD_ZERO(&rset);
|
||||||
0, 0, p->width, p->height, 0, 0);
|
FD_SET(p->timer_pipe[0], &rset);
|
||||||
usleep(100*1000);
|
FD_SET(xfd, &rset);
|
||||||
|
if (select(maxfd+1, &rset, NULL, NULL, NULL) == -1) abort();
|
||||||
|
if (FD_ISSET(p->timer_pipe[0], &rset)) {
|
||||||
|
char b[512];
|
||||||
|
read(p->timer_pipe[0], b, 512);
|
||||||
|
replot = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -73,13 +142,15 @@ static void new_thread(void *(*f)(void *), void *data)
|
|||||||
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
{ fprintf(stderr, "pthread_attr_init err\n"); exit(1); }
|
||||||
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED))
|
||||||
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
{ fprintf(stderr, "pthread_attr_setdetachstate err\n"); exit(1); }
|
||||||
|
if (pthread_attr_setstacksize(&att, 10000000))
|
||||||
|
{ fprintf(stderr, "pthread_attr_setstacksize err\n"); exit(1); }
|
||||||
if (pthread_create(&t, &att, f, data))
|
if (pthread_create(&t, &att, f, data))
|
||||||
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
{ fprintf(stderr, "pthread_create err\n"); exit(1); }
|
||||||
if (pthread_attr_destroy(&att))
|
if (pthread_attr_destroy(&att))
|
||||||
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
{ fprintf(stderr, "pthread_attr_destroy err\n"); exit(1); }
|
||||||
}
|
}
|
||||||
|
|
||||||
void *make_plot(int width, int height, int bufsize, char *title)
|
void *make_plot(int width, int height, int count, char *title, int type)
|
||||||
{
|
{
|
||||||
plot *p;
|
plot *p;
|
||||||
Display *d;
|
Display *d;
|
||||||
@@ -89,7 +160,7 @@ void *make_plot(int width, int height, int bufsize, char *title)
|
|||||||
d = XOpenDisplay(0); if (d == NULL) abort();
|
d = XOpenDisplay(0); if (d == NULL) abort();
|
||||||
w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, width, height,
|
w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, width, height,
|
||||||
0, WhitePixel(d, DefaultScreen(d)), WhitePixel(d, DefaultScreen(d)));
|
0, WhitePixel(d, DefaultScreen(d)), WhitePixel(d, DefaultScreen(d)));
|
||||||
XSelectInput(d, w, ExposureMask);
|
XSelectInput(d, w, ExposureMask | ButtonPressMask);
|
||||||
XMapWindow(d, w);
|
XMapWindow(d, w);
|
||||||
|
|
||||||
XStoreName(d, w, title);
|
XStoreName(d, w, title);
|
||||||
@@ -99,15 +170,31 @@ void *make_plot(int width, int height, int bufsize, char *title)
|
|||||||
p = malloc(sizeof(*p)); if (p == NULL) abort();
|
p = malloc(sizeof(*p)); if (p == NULL) abort();
|
||||||
p->width = width;
|
p->width = width;
|
||||||
p->height = height;
|
p->height = height;
|
||||||
p->buf = malloc(sizeof(float) * bufsize); if (p->buf == NULL) abort();
|
if (type == PLOT_VS_TIME) {
|
||||||
p->iqbuf = malloc(sizeof(short) * 2 * bufsize); if (p->buf == NULL) abort();
|
p->buf = malloc(sizeof(float) * count); if (p->buf == NULL) abort();
|
||||||
p->bufsize = bufsize;
|
p->iqbuf = malloc(sizeof(short) * count * 2); if(p->iqbuf==NULL)abort();
|
||||||
|
} else {
|
||||||
|
p->buf = NULL;
|
||||||
|
p->iqbuf = malloc(sizeof(short) * count * 2); if(p->iqbuf==NULL)abort();
|
||||||
|
}
|
||||||
|
p->count = count;
|
||||||
|
|
||||||
p->d = d;
|
p->d = d;
|
||||||
p->w = w;
|
p->w = w;
|
||||||
p->p = pm;
|
p->p = pm;
|
||||||
|
p->type = type;
|
||||||
|
|
||||||
|
p->iq_count = 0;
|
||||||
|
p->iq_insert_pos = 0;
|
||||||
|
|
||||||
|
p->zoom = 1;
|
||||||
|
|
||||||
|
pthread_mutex_init(&p->lock, NULL);
|
||||||
|
|
||||||
|
if (pipe(p->timer_pipe)) abort();
|
||||||
|
|
||||||
new_thread(plot_thread, p);
|
new_thread(plot_thread, p);
|
||||||
|
new_thread(timer_thread, p);
|
||||||
|
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
@@ -115,11 +202,36 @@ void *make_plot(int width, int height, int bufsize, char *title)
|
|||||||
void plot_set(void *_plot, float *data, int len, int pos)
|
void plot_set(void *_plot, float *data, int len, int pos)
|
||||||
{
|
{
|
||||||
plot *p = _plot;
|
plot *p = _plot;
|
||||||
|
if (pthread_mutex_lock(&p->lock)) abort();
|
||||||
memcpy(p->buf + pos, data, len * sizeof(float));
|
memcpy(p->buf + pos, data, len * sizeof(float));
|
||||||
|
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
void iq_plot_set(void *_plot, short *data, int len, int pos)
|
void iq_plot_set(void *_plot, short *data, int count, int pos)
|
||||||
{
|
{
|
||||||
plot *p = _plot;
|
plot *p = _plot;
|
||||||
memcpy(p->iqbuf + pos * 2, data, len * 2 * sizeof(short));
|
if (pthread_mutex_lock(&p->lock)) abort();
|
||||||
|
memcpy(p->iqbuf + pos * 2, data, count * 2 * sizeof(short));
|
||||||
|
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void iq_plot_set_sized(void *_plot, short *data, int count)
|
||||||
|
{
|
||||||
|
plot *p = _plot;
|
||||||
|
if (pthread_mutex_lock(&p->lock)) abort();
|
||||||
|
memcpy(p->iqbuf, data, count * 2 * sizeof(short));
|
||||||
|
p->iq_count = count;
|
||||||
|
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
void iq_plot_add_point_loop(void *_plot, short i, short q)
|
||||||
|
{
|
||||||
|
plot *p = _plot;
|
||||||
|
if (pthread_mutex_lock(&p->lock)) abort();
|
||||||
|
p->iqbuf[p->iq_insert_pos*2] = i;
|
||||||
|
p->iqbuf[p->iq_insert_pos*2+1] = q;
|
||||||
|
if (p->iq_count != p->count) p->iq_count++;
|
||||||
|
p->iq_insert_pos++;
|
||||||
|
if (p->iq_insert_pos == p->count) p->iq_insert_pos = 0;
|
||||||
|
if (pthread_mutex_unlock(&p->lock)) abort();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user