From fa49fe6780b575345eeb5487fe60e39a26c74340 Mon Sep 17 00:00:00 2001 From: Cedric Roux <cedric.roux@eurecom.fr> Date: Fri, 18 Mar 2016 12:11:42 +0100 Subject: [PATCH] - 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 --- T_messages.txt | 8 +++ tracer/defs.h | 8 ++- tracer/main.c | 47 ++++++++++++- tracer/plot.c | 176 ++++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 204 insertions(+), 35 deletions(-) diff --git a/T_messages.txt b/T_messages.txt index ba6197b569..f954dd46ec 100644 --- a/T_messages.txt +++ b/T_messages.txt @@ -7,6 +7,14 @@ ID = ENB_UL_CHANNEL_ESTIMATE DESC = eNodeB channel estimation in the time domain GROUP = PHY:GRAPHIC:HEAVY 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 ID = LEGACY_MAC_INFO diff --git a/tracer/defs.h b/tracer/defs.h index 71b9dd0cfb..873292a70c 100644 --- a/tracer/defs.h +++ b/tracer/defs.h @@ -1,9 +1,15 @@ #ifndef _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 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 */ void *parse_database(char *filename); diff --git a/tracer/main.c b/tracer/main.c index 37774be4e5..853ed46fed 100644 --- a/tracer/main.c +++ b/tracer/main.c @@ -16,6 +16,8 @@ void *ul_plot; void *chest_plot; +void *pusch_iq_plot; +void *pucch_iq_plot; #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); 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: { unsigned char buf[T_BUFFER_MAX]; int size; @@ -345,8 +385,11 @@ int main(int n, char **v) if (do_dump_database) { dump_database(database); return 0; } if (do_xforms) { - ul_plot = make_plot(512, 100, 7680*2*10, "UL Input Signal"); - chest_plot = make_plot(512, 100, 512*2, "UL Channel Estimate UE 0"); + ul_plot = make_plot(512, 100, 7680*10, "UL Input Signal", PLOT_VS_TIME); + 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++) diff --git a/tracer/plot.c b/tracer/plot.c index 3cc0ad069f..e13398ab5e 100644 --- a/tracer/plot.c +++ b/tracer/plot.c @@ -6,6 +6,8 @@ #include <pthread.h> #include <math.h> #include <unistd.h> +#include <pthread.h> +#include <sys/select.h> typedef struct { Display *d; @@ -15,50 +17,117 @@ typedef struct { int height; float *buf; 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; +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) { float v; float *s; int i, j; 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 (XPending(p->d)) { XEvent 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 */ - GC gc; - XGCValues v; - gc = DefaultGC(p->d, DefaultScreen(p->d)); - v.foreground = WhitePixel(p->d, DefaultScreen(p->d)); - XChangeGC(p->d, gc, GCForeground, &v); - XFillRectangle(p->d, p->p, gc, 0, 0, p->width, p->height); - v.foreground = BlackPixel(p->d, DefaultScreen(p->d)); - XChangeGC(p->d, gc, GCForeground, &v); + { + GC gc; + XGCValues v; + gc = DefaultGC(p->d, DefaultScreen(p->d)); + v.foreground = WhitePixel(p->d, DefaultScreen(p->d)); + XChangeGC(p->d, gc, GCForeground, &v); + XFillRectangle(p->d, p->p, gc, 0, 0, p->width, p->height); + 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(); } - { - int i; - for (i = 0; i < p->bufsize/2; 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->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); + if (redraw) { + redraw = 0; + XCopyArea(p->d, p->p, p->w, DefaultGC(p->d, DefaultScreen(p->d)), + 0, 0, p->width, p->height, 0, 0); } - XCopyArea(p->d, p->p, p->w, DefaultGC(p->d, DefaultScreen(p->d)), - 0, 0, p->width, p->height, 0, 0); - usleep(100*1000); + FD_ZERO(&rset); + FD_SET(p->timer_pipe[0], &rset); + 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; @@ -73,13 +142,15 @@ static void new_thread(void *(*f)(void *), void *data) { fprintf(stderr, "pthread_attr_init err\n"); exit(1); } if (pthread_attr_setdetachstate(&att, PTHREAD_CREATE_DETACHED)) { 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)) { fprintf(stderr, "pthread_create err\n"); exit(1); } if (pthread_attr_destroy(&att)) { 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; Display *d; @@ -89,7 +160,7 @@ void *make_plot(int width, int height, int bufsize, char *title) d = XOpenDisplay(0); if (d == NULL) abort(); w = XCreateSimpleWindow(d, DefaultRootWindow(d), 0, 0, width, height, 0, WhitePixel(d, DefaultScreen(d)), WhitePixel(d, DefaultScreen(d))); - XSelectInput(d, w, ExposureMask); + XSelectInput(d, w, ExposureMask | ButtonPressMask); XMapWindow(d, w); 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->width = width; p->height = height; - p->buf = malloc(sizeof(float) * bufsize); if (p->buf == NULL) abort(); - p->iqbuf = malloc(sizeof(short) * 2 * bufsize); if (p->buf == NULL) abort(); - p->bufsize = bufsize; + if (type == PLOT_VS_TIME) { + p->buf = malloc(sizeof(float) * count); if (p->buf == NULL) abort(); + 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->w = w; 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(timer_thread, 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) { plot *p = _plot; + if (pthread_mutex_lock(&p->lock)) abort(); memcpy(p->buf + pos, data, len * sizeof(float)); + if (pthread_mutex_unlock(&p->lock)) abort(); +} + +void iq_plot_set(void *_plot, short *data, int count, int pos) +{ + plot *p = _plot; + 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_set(void *_plot, short *data, int len, int pos) +void iq_plot_add_point_loop(void *_plot, short i, short q) { plot *p = _plot; - memcpy(p->iqbuf + pos * 2, data, len * 2 * sizeof(short)); + 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(); } -- GitLab