⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 display.c

📁 Linmodem is soft modem source code for embedded system
💻 C
字号:
/*  * X11 interface for linmodem *  * Copyright (c) 2000 Fabrice Bellard. * * This code is released under the GNU General Public License version * 2. Please read the file COPYING to know the exact terms of the * license. */#include <stdarg.h>#include <stdlib.h>#include <string.h>#include <X11/Xlib.h>#include <X11/Xutil.h>#include <X11/extensions/XShm.h>#include <X11/keysym.h>#include "lm.h"#define NB_MODES 5enum {    DISP_MODE_SAMPLE, /* display the brut samples */    DISP_MODE_ECHOCANCEL, /* display the echo cancellor info */    DISP_MODE_SAMPLESYNC, /* display the samples after freq normalize                             & symbol recovery */    DISP_MODE_EQUALIZER, /* display the equalizer filter */    DISP_MODE_QAM, /* display the qam */} disp_state;char *mode_str[NB_MODES] = {    "Sample",    "Echo Cancel",    "Sample Sync",    "Equalizer",    "QAM",};#define QAM_SIZE 460static void set_state(int state);/**************************/#define RGB(r, g, b) ((((r) >> 3) << 11) | (((g) >> 2) << 5) | ((b) >> 3))Display *display;Window window;GC gc;XFontStruct *xfont;unsigned int fg, bg;int minx, miny;int font_xsize, font_ysize;int lm_display_init(void){    XSizeHints hint;    int screen;    XVisualInfo vinfo;    int size_x = 640;    int size_y = 480;    XSetWindowAttributes xwa;    char *fontname = "fixed";    display = XOpenDisplay("");    if (display == NULL) {	return -1;    }    screen = DefaultScreen(display);    bg = RGB(0, 0, 0);    fg = RGB(255, 255, 255);    /* Fill in hint structure */    hint.x = 0;    hint.y = 0;    hint.width = size_x;    hint.height = size_y;    hint.flags = PPosition | PSize;    /* Make the window */    if (!XMatchVisualInfo(display, screen, 16, TrueColor, &vinfo)) {        printf("A 16 bit visual is need by this program\n");        return -1;    }    window = XCreateSimpleWindow(display,                                 DefaultRootWindow(display),                                 hint.x, hint.y,                                 hint.width, hint.height,                                 4, fg, bg);    /* Enable backing store */    xwa.backing_store = Always;    XChangeWindowAttributes(display, window, CWBackingStore, &xwa);    XSelectInput(display, window, StructureNotifyMask);    /* Tell other applications about this window */    XSetStandardProperties(display, window,			   "linmodem", "linmodem",			   None, NULL, 0, &hint);    /* Map window. */    XMapWindow(display, window);    /* Wait for map. */    while (1) {	XEvent xev;	XNextEvent(display, &xev);	if (xev.type == MapNotify && xev.xmap.event == window)	    break;    }    XSelectInput(display, window, KeyPressMask		 | ButtonPressMask);    gc = XCreateGC(display, window, 0, 0);    xfont = XLoadQueryFont (display, fontname);    if (!xfont) {        fprintf(stderr, "Could not load font '%s'\n", fontname);        return -1;    }    font_xsize = xfont->max_bounds.rbearing - xfont->min_bounds.lbearing;    font_ysize = xfont->max_bounds.ascent + xfont->max_bounds.descent;    set_state(DISP_MODE_SAMPLE);    return 0;}void lm_display_close(void){    XCloseDisplay(display);}void printf_at(int x, int y, char *fmt, ...){    va_list ap;    char buf[1024];        va_start(ap, fmt);    vsnprintf(buf, sizeof(buf), fmt, ap);        XSetFont(display, gc, xfont->fid);    XSetForeground(display, gc, bg);    XFillRectangle(display, window, gc,                    x * font_xsize, y * font_ysize,                    font_xsize * strlen(buf), font_ysize);                       XSetForeground(display, gc, fg);    XDrawString(display, window, gc, x * font_xsize, (y + 1) * font_ysize - 1,                 buf, strlen(buf));        va_end(ap);}/* draw a graph at (x1, y1, x1 + w, y1 + h). The points are computed   by calc_func */#define DG_AUTOSCALE_YMIN 0x0001#define DG_AUTOSCALE_YMAX 0x0002void draw_graph(char *title,                int x1, int y1, int w, int h,                float xmin, float xmax, float ymin, float ymax,                int flags, float (*calc_func)(float)) {    int i, yy, xx;    float x, y;    int ly;    float tab[1024];        /* auto scale */    for(i=0;i<w;i++) {        x = ((float)i / (float)(w-1)) * (xmax - xmin) + xmin;        y = calc_func(x);        tab[i] = y;        if (i == 0) {            if (flags & DG_AUTOSCALE_YMIN)                ymin = y;            if (flags & DG_AUTOSCALE_YMAX)                ymax = y;        } else {            if (flags & DG_AUTOSCALE_YMIN && y < ymin)                ymin = y;            if (flags & DG_AUTOSCALE_YMAX && y > ymax)                ymax = y;        }    }    /* draw ! */    XSetForeground(display, gc, bg);    XFillRectangle(display, window, gc, x1, y1, w, h);        XSetForeground(display, gc, RGB(255, 0, 0));    XDrawRectangle(display, window, gc, x1, y1, w, h);        /* axis */    XSetForeground(display, gc, RGB(0, 255, 0));    if (xmin <= 0.0 && 0.0 <= xmax) {        xx = (int)rint(((0.0 - xmin) / (xmax - xmin)) * (w-1)) + x1;        XDrawLine(display, window, gc,                           xx, y1, xx, y1 + h - 1);    }        if (ymin <= 0.0 && 0.0 <= ymax) {        yy = y1 + h - 1 - (int)rint(((0.0 - ymin) / (ymax - ymin)) * (h-1));        XDrawLine(display, window, gc,                           x1, yy, x1 + w - 1, yy);    }    XSetForeground(display, gc, RGB(255, 255, 255));    ly = -1;    for(i=0;i<w;i++) {        y = tab[i];        if (y >= ymin && y <= ymax) {            yy = y1 + h - 1 - (int)rint(((y - ymin) / (ymax - ymin)) * (h-1));            if (ly >= 0) {                XDrawLine(display, window, gc,                           i - 1, ly, i, yy);            } else {                XDrawPoint(display, window, gc,                            i, yy);            }            ly = yy;        } else {            ly = -1;        }    }    /* title */    XSetForeground(display, gc, RGB(0, 255, 0));        printf_at((x1+font_xsize-1) / font_xsize,              (y1+font_ysize-1) / font_ysize,              "%s - ymin=%6.3e ymax=%6.3e", title, ymin, ymax);             }/***************************************************//* utilities *//***************************************************//* si and sq must be betwen -1.0 and 1.0 */int nb_samples = 0;void lm_dump_qam(float si, float sq){    int x, y;    if (disp_state != DISP_MODE_QAM)        return;    x = (int)(si * (QAM_SIZE/2)) + (QAM_SIZE/2);    y = (int)(sq * (QAM_SIZE/2)) + (QAM_SIZE/2);    if (x < 0 || x >= QAM_SIZE ||        y < 0 || y >= QAM_SIZE)        return;    XSetForeground(display, gc, RGB(255, 255, 255));    XDrawPoint(display, window, gc, x, y);    nb_samples++;    printf_at(minx, 1, "# samples: %d", nb_samples);}/* print samples */#define NB_SAMPLES 512float sample_mem[NB_CHANNELS][NB_SAMPLES];int sample_pos[NB_CHANNELS];float sample_hamming[NB_SAMPLES];int sample_hamming_init = 0;complex sample_fft[NB_SAMPLES];int sample_channel;float calc_sample(float x){    return sample_mem[sample_channel][(int)x];}float calc_sample_pow(float x){    complex *p = &sample_fft[(int)x];    return p->re * p->re + p->im * p->im;}void draw_samples(int channel){    int i;    sample_channel = channel;    draw_graph("Sample",               0, 0, QAM_SIZE, QAM_SIZE/2,                 0.0, NB_SAMPLES - 1, 0.0, 0.0,                DG_AUTOSCALE_YMAX | DG_AUTOSCALE_YMIN,               calc_sample);        if (!sample_hamming_init) {        calc_hamming(sample_hamming, NB_SAMPLES);        sample_hamming_init = 1;    }        for(i=0;i<NB_SAMPLES;i++) {        sample_fft[i].re = sample_mem[channel][i] * sample_hamming[i];        sample_fft[i].im = 0;    }        fft_calc(sample_fft, NB_SAMPLES, 0);        draw_graph("Spectral power",               0, QAM_SIZE/2, QAM_SIZE, QAM_SIZE/2,                 0.0, NB_SAMPLES/2 - 1, 0.0, 0.0,                DG_AUTOSCALE_YMAX, calc_sample_pow);}void lm_dump_sample(int channel, float val){    sample_mem[channel][sample_pos[channel]] = val;    if (++sample_pos[channel] == NB_SAMPLES) {        sample_pos[channel] = 0;                if ((disp_state == DISP_MODE_SAMPLE &&             channel == CHANNEL_SAMPLE) ||            (disp_state == DISP_MODE_SAMPLESYNC &&             channel == CHANNEL_SAMPLESYNC)) {                        draw_samples(channel);        }    }}#if 0int last_eye_y[2];int last_eye_x[2];/* print an eye diagram (each symbol is sampled at integer time   values). We print 1 centered period */void lm_dump_eye(int channel, float time, float val){    int x, y;    if (disp_state != DISP_MODE_EYE)        return;    if (val < -1)        val = -1;    else if (val > 1)        val = 1;    y = (int)(val * (QAM_SIZE/2)) + (QAM_SIZE/2);    time += 0.5;    if (time >= 1.0)        time -= 1.0;    x = (int)(time * QAM_SIZE);        XSetForeground(display, gc, RGB(255, 255, 255));    if (x > last_eye_x[channel] && 0) {        XDrawLine(display, window, gc,                   last_eye_x[channel], last_eye_y[channel], x, y);    } else {        XDrawPoint(display, window, gc, x, y);    }    last_eye_x[channel] = x;    last_eye_y[channel] = y;}#endif/* print equalizer */#define EQ_FFT_SIZE 144static int eq_count = 0;static s32 (*eq_filter)[2];static int eq_norm;static complex eq_fft[EQ_FFT_SIZE];float calc_eq_re(float x){    return (float)eq_filter[(int)rint(x)][0] / (float)eq_norm;}float calc_eq_im(float x){    return (float)eq_filter[(int)rint(x)][1] / (float)eq_norm;}float calc_eq_pow(float x){    complex *p = &eq_fft[(int)x];    return p->re * p->re + p->im * p->im;}float calc_eq_phase(float x){    complex *p = &eq_fft[(int)x];    return atan2(p->im, p->re);}void lm_dump_equalizer(s32 eq_filter1[][2], int norm, int size){    int i;        if (disp_state != DISP_MODE_EQUALIZER)        return;        if (++eq_count == 1) {        eq_count = 0;        eq_filter = eq_filter1;        eq_norm = norm;        draw_graph("Eqz real",                   0, 0, QAM_SIZE, QAM_SIZE/4,                     0.0, size - 1, -1.5, 1.5,                    0,                   calc_eq_re);        draw_graph("Eqz imag",                   0, QAM_SIZE/4, QAM_SIZE, QAM_SIZE/4,                     0.0, size - 1, -1.5, 1.5,                    0,                   calc_eq_im);        for(i=0;i<EQ_FFT_SIZE;i++) {            if (i < size) {                eq_fft[i].re = eq_filter[i][0] / (float)norm;                eq_fft[i].im = eq_filter[i][1] / (float)norm;            } else {                eq_fft[i].re = eq_fft[i].im = 0;            }        }                if (EQ_FFT_SIZE == 144) {            complex eq_fft1[144];            slow_fft(eq_fft1, eq_fft, EQ_FFT_SIZE, 0);            for(i=0;i<EQ_FFT_SIZE;i++)                eq_fft[i] = eq_fft1[i];                    } else {            fft_calc(eq_fft, EQ_FFT_SIZE, 0);        }        draw_graph("Eqz spec pow",                   0, 2*QAM_SIZE/4, QAM_SIZE, QAM_SIZE/4,                     0.0, EQ_FFT_SIZE - 1, 0.0, 0.0,                   DG_AUTOSCALE_YMAX, calc_eq_pow);        draw_graph("Eqz spec phase",                   0, 3*QAM_SIZE/4, QAM_SIZE, QAM_SIZE/4,                     0.0, EQ_FFT_SIZE - 1, -M_PI, M_PI,                   0, calc_eq_phase);    }}/* agc */void lm_dump_agc(float gain){    printf_at(minx, 2, "AGC: %10.5f", gain);}void lm_dump_linesim_power(float tx_db, float rx_db, float noise_db){    printf_at(minx, 3, "TX: %6.2f dB SNR: %6.2f dB", tx_db, rx_db - noise_db);    printf_at(minx, 4, "RX: %6.2f dB  N0: %6.2f dB", rx_db, noise_db);}static void set_state(int state){    int i;    minx = ((QAM_SIZE + font_xsize) / font_xsize) + 1;    miny = ((QAM_SIZE + font_ysize) / font_ysize);        disp_state = state;    XSetForeground(display, gc, bg);    XFillRectangle(display, window, gc, 0, 0, 640, 480);    XSetForeground(display, gc, RGB(255, 0, 0));    XDrawRectangle(display, window, gc, 0, 0, QAM_SIZE, QAM_SIZE);    switch(disp_state) {    case DISP_MODE_QAM:        XDrawLine(display, window, gc, 0, QAM_SIZE/2, QAM_SIZE-1, QAM_SIZE/2);        XDrawLine(display, window, gc, QAM_SIZE/2, 0, QAM_SIZE/2, QAM_SIZE-1);        break;    default:        break;    }    printf_at(minx, 0, "Mode: %s", mode_str[disp_state]);        for(i=0;i<NB_MODES;i++) {        printf_at(1 + 15 * i, miny, "F%d:%s", i + 1, mode_str[i]);    }}int lm_display_poll_event(void){    char buf[80];    XEvent xev;    KeySym keysym;    XComposeStatus status;    if (XPending(display) <= 0)        return 0;    XNextEvent(display, &xev);    switch(xev.type) {    case KeyPress:	XLookupString((XKeyEvent *) & xev, buf, 80, &keysym, &status);        switch(keysym) {        case XK_q:            return 1;        case XK_F1:        case XK_F2:        case XK_F3:        case XK_F4:        case XK_F5:        case XK_F6:        case XK_F7:        case XK_F8:            {                int mode;                mode = keysym - XK_F1;                if (mode < NB_MODES) {                    set_state(mode);                }            }            break;        }        break;    }    return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -