From 6fa2737027914bce7b409460b973bd7636ab094d Mon Sep 17 00:00:00 2001
From: Cedric Roux <cedric.roux@eurecom.fr>
Date: Tue, 15 Mar 2016 17:01:05 +0100
Subject: [PATCH] add a plotter for raw IQ samples from eNB uplink received
 data

only works for 5MHz (7680 samples per TTI), one transport block
(basic FDD thing)
---
 Makefile        |   2 +-
 T.h             |  36 +++++++++-----
 T_defs.h        |   4 +-
 T_messages.txt  |  27 ++++++++++-
 generate_Txx.c  |   4 +-
 tracer/Makefile |   6 ++-
 tracer/defs.h   |   8 ++++
 tracer/main.c   |  24 ++++++++++
 tracer/plot.c   | 123 ++++++++++++++++++++++++++++++++++++++++++++++++
 9 files changed, 214 insertions(+), 20 deletions(-)
 create mode 100644 tracer/defs.h
 create mode 100644 tracer/plot.c

diff --git a/Makefile b/Makefile
index 06315e4585..c65ed27b8e 100644
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,7 @@ $(PROG): $(OBJS)
 T_IDs.h: $(GENIDS) T_messages.txt
 	./$(GENIDS) T_messages.txt T_IDs.h
 
-main.o: T.h T_IDs.h
+main.o: T.h T_IDs.h T_defs.h
 
 clean:
 	rm -f *.o $(PROG) $(GENIDS) core T_IDs.h
diff --git a/T.h b/T.h
index ec7b1d2a0c..46c5bdc180 100644
--- a/T.h
+++ b/T.h
@@ -236,7 +236,7 @@ extern T_cache_t *T_cache;
     } \
   } while (0)
 
-#define T11(t,t0,x0,t1,x1,t2,x2,t3,x3) \
+#define T11(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -245,11 +245,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t1(3, x1); \
       T_PUT_##t2(4, x2); \
       T_PUT_##t3(5, x3); \
+      T_PUT_##t4(6, x4); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T13(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4) \
+#define T13(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -259,11 +260,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t2(4, x2); \
       T_PUT_##t3(5, x3); \
       T_PUT_##t4(6, x4); \
+      T_PUT_##t5(7, x5); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T15(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5) \
+#define T15(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -274,11 +276,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t3(5, x3); \
       T_PUT_##t4(6, x4); \
       T_PUT_##t5(7, x5); \
+      T_PUT_##t6(8, x6); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T17(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6) \
+#define T17(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -290,11 +293,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t4(6, x4); \
       T_PUT_##t5(7, x5); \
       T_PUT_##t6(8, x6); \
+      T_PUT_##t7(9, x7); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T19(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7) \
+#define T19(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -307,11 +311,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t5(7, x5); \
       T_PUT_##t6(8, x6); \
       T_PUT_##t7(9, x7); \
+      T_PUT_##t8(10, x8); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T21(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8) \
+#define T21(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -325,11 +330,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t6(8, x6); \
       T_PUT_##t7(9, x7); \
       T_PUT_##t8(10, x8); \
+      T_PUT_##t9(11, x9); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T23(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9) \
+#define T23(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -344,11 +350,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t7(9, x7); \
       T_PUT_##t8(10, x8); \
       T_PUT_##t9(11, x9); \
+      T_PUT_##t10(12, x10); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T25(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10) \
+#define T25(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -364,11 +371,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t8(10, x8); \
       T_PUT_##t9(11, x9); \
       T_PUT_##t10(12, x10); \
+      T_PUT_##t11(13, x11); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T27(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11) \
+#define T27(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -385,11 +393,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t9(11, x9); \
       T_PUT_##t10(12, x10); \
       T_PUT_##t11(13, x11); \
+      T_PUT_##t12(14, x12); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T29(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12) \
+#define T29(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -407,11 +416,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t10(12, x10); \
       T_PUT_##t11(13, x11); \
       T_PUT_##t12(14, x12); \
+      T_PUT_##t13(15, x13); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T31(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13) \
+#define T31(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13,t14,x14) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -430,11 +440,12 @@ extern T_cache_t *T_cache;
       T_PUT_##t11(13, x11); \
       T_PUT_##t12(14, x12); \
       T_PUT_##t13(15, x13); \
+      T_PUT_##t14(16, x14); \
       T_SEND(); \
     } \
   } while (0)
 
-#define T33(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13,t14,x14) \
+#define T33(t,t0,x0,t1,x1,t2,x2,t3,x3,t4,x4,t5,x5,t6,x6,t7,x7,t8,x8,t9,x9,t10,x10,t11,x11,t12,x12,t13,x13,t14,x14,t15,x15) \
   do { \
     if (T_ACTIVE(t)) { \
       T_LOCAL_DATA \
@@ -454,6 +465,7 @@ extern T_cache_t *T_cache;
       T_PUT_##t12(14, x12); \
       T_PUT_##t13(15, x13); \
       T_PUT_##t14(16, x14); \
+      T_PUT_##t15(17, x15); \
       T_SEND(); \
     } \
   } while (0)
diff --git a/T_defs.h b/T_defs.h
index 1d01ea7415..5aca54e8d6 100644
--- a/T_defs.h
+++ b/T_defs.h
@@ -2,10 +2,10 @@
 #define _T_defs_H_
 
 /* maximum size of a message - increase if needed */
-#define T_BUFFER_MAX 1024
+#define T_BUFFER_MAX (1024*64)
 
 /* size of the local cache for messages (must be pow(2,something)) */
-#define T_CACHE_SIZE (65536 * 2)
+#define T_CACHE_SIZE (8192 * 2)
 
 typedef struct {
   volatile int busy;
diff --git a/T_messages.txt b/T_messages.txt
index 8cca071ae8..e5f0c916a3 100644
--- a/T_messages.txt
+++ b/T_messages.txt
@@ -1,17 +1,41 @@
+#PHY logs
+ID = ENB_INPUT_SIGNAL
+    DESC = eNodeB received signal in the time domain for a duration of 1ms
+    GROUP = PHY:GRAPHIC:HEAVY
+    FORMAT = int,eNB_ID : int,frame : int,subframe : int,antenna : buffer,rxdata
+
 #legacy logs
 ID = LEGACY_MAC_INFO
-    DESC = MAC legacy logs
+    DESC = MAC legacy logs - info level
     GROUP = MAC:INFO:LEGACY
 ID = LEGACY_MAC_ERROR
+    DESC = MAC legacy logs - error level
+    GROUP = MAC:ERROR:LEGACY
 ID = LEGACY_MAC_WARNING
+    DESC = MAC legacy logs - warning level
+    GROUP = MAC:WARNING:LEGACY
 ID = LEGACY_MAC_DEBUG
+    DESC = MAC legacy logs - debug level
+    GROUP = MAC:DEBUG:LEGACY
 ID = LEGACY_MAC_TRACE
+    DESC = MAC legacy logs - trace level
+    GROUP = MAC:TRACE:LEGACY
 
 ID = LEGACY_PHY_INFO
+    DESC = PHY legacy logs - info level
+    GROUP = PHY:INFO:LEGACY
 ID = LEGACY_PHY_ERROR
+    DESC = PHY legacy logs - error level
+    GROUP = PHY:ERROR:LEGACY
 ID = LEGACY_PHY_WARNING
+    DESC = PHY legacy logs - warning level
+    GROUP = PHY:WARNING:LEGACY
 ID = LEGACY_PHY_DEBUG
+    DESC = PHY legacy logs - debug level
+    GROUP = PHY:DEBUG:LEGACY
 ID = LEGACY_PHY_TRACE
+    DESC = PHY legacy logs - trace level
+    GROUP = PHY:TRACE:LEGACY
 
 ID = LEGACY_S1AP_INFO
 ID = LEGACY_S1AP_ERROR
@@ -137,5 +161,6 @@ ID = LEGACY_CLI_WARNING
 ID = LEGACY_CLI_DEBUG
 ID = LEGACY_CLI_TRACE
 
+#for debug/test - not used
 ID = first
 ID = buf_test
diff --git a/generate_Txx.c b/generate_Txx.c
index 6e803aac50..da6282adc1 100644
--- a/generate_Txx.c
+++ b/generate_Txx.c
@@ -4,13 +4,13 @@ void print(int n)
 {
   int i;
   printf("#define T%d(t", n);
-  for(i=0; i<(n-3)/2; i++) printf(",t%d,x%d", i, i);
+  for(i=0; i<(n-1)/2; i++) printf(",t%d,x%d", i, i);
   printf(") \\\n");
   printf("  do { \\\n");
   printf("    if (T_ACTIVE(t)) { \\\n");
   printf("      T_LOCAL_DATA \\\n");
   printf("      T_HEADER(t); \\\n");
-  for(i=0; i<(n-3)/2; i++) printf("      T_PUT_##t%d(%d, x%d); \\\n", i, i+2, i);
+  for(i=0; i<(n-1)/2; i++) printf("      T_PUT_##t%d(%d, x%d); \\\n", i, i+2, i);
   printf("      T_SEND(); \\\n");
   printf("    } \\\n");
   printf("  } while (0)\n");
diff --git a/tracer/Makefile b/tracer/Makefile
index 156700812e..047e1a5c38 100644
--- a/tracer/Makefile
+++ b/tracer/Makefile
@@ -1,12 +1,14 @@
 CC=gcc
-CFLAGS=-Wall -g -O3
+CFLAGS=-Wall -g -pthread
+
+LIBS=-lX11 -lm
 
 #comment those two lines to NOT use shared memory
 CFLAGS += -DT_USE_SHARED_MEMORY
 LIBS += -lrt
 
 PROG=tracer
-OBJS=main.o
+OBJS=main.o plot.o
 
 $(PROG): $(OBJS)
 	$(CC) $(CFLAGS) -o $(PROG) $(OBJS) $(LIBS)
diff --git a/tracer/defs.h b/tracer/defs.h
new file mode 100644
index 0000000000..73e11a0c7d
--- /dev/null
+++ b/tracer/defs.h
@@ -0,0 +1,8 @@
+#ifndef _TRACER_DEFS_H_
+#define _TRACER_DEFS_H_
+
+void *make_plot(int width, int height, int bufsize);
+void plot_set(void *plot, float *data, int len, int pos);
+void iq_plot_set(void *plot, short *data, int len, int pos);
+
+#endif /* _TRACER_DEFS_H_ */
diff --git a/tracer/main.c b/tracer/main.c
index f9da2085bf..e80c5691a1 100644
--- a/tracer/main.c
+++ b/tracer/main.c
@@ -8,10 +8,14 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#include "defs.h"
+
 #define T_ID(x) x
 #include "../T_IDs.h"
 #include "../T_defs.h"
 
+void *ul_plot;
+
 #ifdef T_USE_SHARED_MEMORY
 
 T_cache_t *T_cache;
@@ -195,6 +199,23 @@ void get_message(int s)
   case T_LEGACY_CLI_WARNING: S("CLI", "WARNING"); break;
   case T_LEGACY_CLI_DEBUG: S("CLI", "DEBUG"); break;
   case T_LEGACY_CLI_TRACE: S("CLI", "TRACE"); break;
+  case T_ENB_INPUT_SIGNAL: {
+    unsigned char buf[T_BUFFER_MAX];
+    int size;
+    int eNB, frame, subframe, antenna;
+    GET(s, &eNB, sizeof(int));
+    GET(s, &frame, sizeof(int));
+    GET(s, &subframe, sizeof(int));
+    GET(s, &antenna, sizeof(int));
+    GET(s, &size, sizeof(int));
+    GET(s, buf, size);
+    printf("got T_ENB_INPUT_SIGNAL eNB %d frame %d subframe %d antenna %d size %d %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n",
+           eNB, frame, subframe, antenna, size, buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],buf[8],buf[9],buf[10],buf[11],buf[12],buf[13],buf[14],buf[15]);
+    if (size != 4 * 7680)
+      {printf("bad T_ENB_INPUT_SIGNAL, only 7680 samples allowed\n");abort();}
+    iq_plot_set(ul_plot, (short*)buf, 7680, subframe*7680);
+    break;
+  }
   case T_buf_test: {
     unsigned char buf[T_BUFFER_MAX];
     int size;
@@ -252,6 +273,9 @@ int main(void)
   if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
   for (l = 0; l < T_NUMBER_OF_IDS; l++)
     if (write(s, &l, sizeof(int)) != sizeof(int)) abort();
+
+  ul_plot = make_plot(512, 100, 7680*2*10);
+
   /* read messages */
   while (1) {
 #ifdef T_USE_SHARED_MEMORY
diff --git a/tracer/plot.c b/tracer/plot.c
new file mode 100644
index 0000000000..ba203b0886
--- /dev/null
+++ b/tracer/plot.c
@@ -0,0 +1,123 @@
+#include "defs.h"
+#include <X11/Xlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <math.h>
+#include <unistd.h>
+
+typedef struct {
+  Display *d;
+  Window w;
+  Pixmap p;
+  int width;
+  int height;
+  float *buf;
+  short *iqbuf;
+  int bufsize;
+} plot;
+
+static void *plot_thread(void *_p)
+{
+  float v;
+  float *s;
+  int i, j;
+  plot *p = _p;
+  while (1) {
+    while (XPending(p->d)) {
+      XEvent e;
+      XNextEvent(p->d, &e);
+    }
+
+    {
+      /* 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);
+    }
+
+  {
+    int i;
+    for (i = 0; i < 512*150; 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 < 150; j++, s++) v += *s;
+      v /= 150;
+      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)),
+              0, 0, p->width, p->height, 0, 0);
+    usleep(100*1000);
+  }
+
+  return NULL;
+}
+
+static void new_thread(void *(*f)(void *), void *data)
+{
+  pthread_t t;
+  pthread_attr_t att;
+
+  if (pthread_attr_init(&att))
+    { 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_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)
+{
+  plot *p;
+  Display *d;
+  Window w;
+  Pixmap pm;
+
+  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);
+  XMapWindow(d, w);
+
+  pm = XCreatePixmap(d, w, width, height, DefaultDepth(d, DefaultScreen(d)));
+
+  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;
+
+  p->d = d;
+  p->w = w;
+  p->p = pm;
+
+  new_thread(plot_thread, p);
+
+  return p;
+}
+
+void plot_set(void *_plot, float *data, int len, int pos)
+{
+  plot *p = _plot;
+  memcpy(p->buf + pos, data, len * sizeof(float));
+}
+
+void iq_plot_set(void *_plot, short *data, int len, int pos)
+{
+  plot *p = _plot;
+  memcpy(p->iqbuf + pos * 2, data, len * 2 * sizeof(short));
+}
-- 
GitLab