fosphor/gl: Add a proper "smart" frequency axis

Signed-off-by: Sylvain Munaut <tnt@246tNt.com>
This commit is contained in:
Sylvain Munaut 2013-11-09 21:49:35 +01:00
parent 8e89f9cd8b
commit 010face67b
4 changed files with 239 additions and 5 deletions

View File

@ -20,7 +20,7 @@ all: main
resource_data.c: $(RESOURCE_FILES) mkresources.py
./mkresources.py $(RESOURCE_FILES) > resource_data.c
main: resource.o resource_data.o cl.o fosphor.o gl.o gl_cmap.o gl_cmap_gen.o gl_font.o main.o
main: resource.o resource_data.o axis.o cl.o fosphor.o gl.o gl_cmap.o gl_cmap_gen.o gl_font.o main.o
clean:
rm main *.o resource_data.c -f

170
lib/fosphor/axis.c Normal file
View File

@ -0,0 +1,170 @@
/*
* axis.c
*
* Logic to deal with various axises
*
* Copyright (C) 2013 Sylvain Munaut
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*! \addtogroup axis
* @{
*/
/*! \file axis.c
* \brief Logic to deal with various axises
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "axis.h"
#define FX_MODE_COUNT 0
#define FX_MODE_RELATIVE 1
#define FX_MODE_ABSOLUTE 2
static double
_si_scaling(double val, int max_num, char *prefix, int *exp)
{
const char prefixes[5] = { ' ', 'k', 'M', 'G', 'T' };
int exponent = log10f(fabs(val));
int d = exponent >= max_num ? ((exponent - max_num + 3) / 3) : 0;
if (prefix)
*prefix = prefixes[d];
if (exp)
*exp = d * 3;
return val / powf(10.0, d * 3);
}
static int
_num_decimals(double val)
{
int c;
double v;
for (c=0; c<22; c++) {
v = val * pow(10, c);
if ( fabs(v - round(v)) == 0.0 )
return c;
}
return -1;
}
void
freq_axis_build(struct freq_axis *fx, double center, double span)
{
/* Basic info */
fx->center = center;
fx->span = span;
fx->step = span / 10.0;
/* Select mode of operation */
if (span == 0.0) {
fx->mode = FX_MODE_COUNT;
} else if (center == 0.0) {
fx->mode = FX_MODE_RELATIVE;
} else if (floor(log10f(fx->step)) < (floor(log10f(fx->center)) - 4)) {
fx->mode = FX_MODE_RELATIVE;
} else {
fx->mode = FX_MODE_ABSOLUTE;
}
/* Select display format for abolute frequencies */
if (center != 0.0)
{
double max_freq = fx->center + (span / 2.0);
char prefix[2] = {0, 0};
int exp, x, y, z;
_si_scaling(max_freq, 4, prefix, &exp);
if (prefix[0] == ' ')
prefix[0] = '\0';
fx->abs_scale = 1.0 / powf(10.0, exp);
x = (int)floor(log10f(max_freq)) - exp + 1;
y = _num_decimals(fx->center * fx->abs_scale);
z = _num_decimals(fx->step * fx->abs_scale);
if (z > y)
y = z;
if (x + y > 6)
y = 6 - x;
sprintf(fx->abs_fmt, "%%.%dlf%s", y, prefix);
}
/* Select display format for relative mode */
if (fx->mode == FX_MODE_RELATIVE)
{
double max_dev = fx->step * 5;
char prefix[2] = {0, 0};
int exp, x, y;
_si_scaling(max_dev, 3, prefix, &exp);
if (prefix[0] == ' ')
prefix[0] = '\0';
fx->rel_step = fx->step / powf(10.0, exp);
x = (int)floor(log10f(max_dev)) - exp + 1;
y = _num_decimals(fx->rel_step);
if (x + y > 4)
y = 4 - x;
sprintf(fx->rel_fmt, "%%+.%dlf%s", y, prefix);
}
}
void
freq_axis_render(struct freq_axis *fx, char *str, int step)
{
/* Special case: count mode */
if (step && (fx->mode == FX_MODE_COUNT)) {
sprintf(str, "%+d", step);
return;
}
/* Special case: no center frequency */
if (!step && (fx->center == 0.0)) {
sprintf(str, "0");
return;
}
/* Relative case */
if (step && (fx->mode == FX_MODE_RELATIVE)) {
sprintf(str, fx->rel_fmt, step * fx->rel_step);
return;
}
/* Normal full absolute frequency */
sprintf(str, fx->abs_fmt, (fx->center + step * fx->step) * fx->abs_scale);
}
/*! @} */

50
lib/fosphor/axis.h Normal file
View File

@ -0,0 +1,50 @@
/*
* axis.h
*
* Logic to deal with various axises
*
* Copyright (C) 2013 Sylvain Munaut
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __FOSPHOR_AXIS_H__
#define __FOSPHOR_AXIS_H__
/*! \defgroup axis
* @{
*/
/*! \file axis.h
* \brief Logic to deal with various axises
*/
struct freq_axis
{
double center;
double span;
double step;
int mode;
char abs_fmt[16];
double abs_scale;
char rel_fmt[16];
double rel_step;
};
void freq_axis_build(struct freq_axis *fx, double center, double span);
void freq_axis_render(struct freq_axis *fx, char *str, int step);
/*! @} */
#endif /* __FOSPHOR_AXIS_H__ */

View File

@ -28,12 +28,14 @@
*/
#include <errno.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "gl_platform.h"
#include "axis.h"
#include "gl.h"
#include "gl_cmap.h"
#include "gl_cmap_gen.h"
@ -284,6 +286,7 @@ void
fosphor_gl_draw(struct fosphor *self, int w, int h, int wf_pos)
{
struct fosphor_gl_state *gl = self->gl;
struct freq_axis freq_axis;
float x_div_width, y_div_width;
float x[2], y[4];
int i;
@ -365,11 +368,18 @@ fosphor_gl_draw(struct fosphor *self, int w, int h, int wf_pos)
glPopMatrix();
/* Setup frequency axis */
freq_axis_build(&freq_axis,
self->frequency.center,
self->frequency.span
);
/* Draw grid */
for (i=0; i<11; i++)
{
float fg_color[3] = { 1.00f, 1.00f, 0.33f };
float xv, yv;
float xv, yv, xv_ofs;
char buf[32];
xv = x[0] + x_div_width * i;
yv = y[2] + y_div_width * i;
@ -398,10 +408,14 @@ fosphor_gl_draw(struct fosphor *self, int w, int h, int wf_pos)
"%d", self->power.db_ref - (10-i) * self->power.db_per_div
);
freq_axis_render(&freq_axis, buf, i-5);
xv_ofs = (i == 0) ? 5.0f : (i == 10 ? -5.0f : 0.0f);
glf_printf(gl->font,
xv - 5.0f, GLF_CENTER,
y[2] - 10.0f, GLF_CENTER,
"%3d", (i - 5)
xv + xv_ofs, GLF_CENTER,
y[2] - 10.0f, GLF_CENTER,
"%s", buf
);
glf_end();