|
@@ -61,14 +61,20 @@ struct visu_packet {
|
|
|
u8_t which;
|
|
|
u8_t count;
|
|
|
union {
|
|
|
- u32_t width;
|
|
|
- u32_t full_bars;
|
|
|
+ struct {
|
|
|
+ u32_t bars;
|
|
|
+ u32_t spectrum_scale;
|
|
|
+ } full;
|
|
|
+ struct {
|
|
|
+ u32_t width;
|
|
|
+ u32_t height;
|
|
|
+ s32_t col;
|
|
|
+ s32_t row;
|
|
|
+ u32_t border;
|
|
|
+ u32_t bars;
|
|
|
+ u32_t spectrum_scale;
|
|
|
+ };
|
|
|
};
|
|
|
- u32_t height;
|
|
|
- s32_t col;
|
|
|
- s32_t row;
|
|
|
- u32_t border;
|
|
|
- u32_t small_bars;
|
|
|
};
|
|
|
|
|
|
struct ANIC_header {
|
|
@@ -98,8 +104,7 @@ static struct {
|
|
|
#define RMS_LEN_BIT 6
|
|
|
#define RMS_LEN (1 << RMS_LEN_BIT)
|
|
|
|
|
|
-// actually this is 2x the displayed BW
|
|
|
-#define DISPLAY_BW 32000
|
|
|
+#define DISPLAY_BW 20000
|
|
|
|
|
|
static struct scroller_s {
|
|
|
// copy of grfs content
|
|
@@ -128,9 +133,10 @@ static struct scroller_s {
|
|
|
static EXT_RAM_ATTR struct {
|
|
|
int bar_gap, bar_width, bar_border;
|
|
|
struct {
|
|
|
- int current;
|
|
|
- int max;
|
|
|
+ int current, max;
|
|
|
+ int limit;
|
|
|
} bars[MAX_BARS];
|
|
|
+ float spectrum_scale;
|
|
|
int n, col, row, height, width, border;
|
|
|
enum { VISU_BLANK, VISU_VUMETER, VISU_SPECTRUM, VISU_WAVEFORM } mode;
|
|
|
int speed, wake;
|
|
@@ -659,13 +665,14 @@ static void visu_update(void) {
|
|
|
// actual FFT that might be less cycle than all the crap below
|
|
|
dsps_fft2r_fc32_ae32(visu.samples, FFT_LEN);
|
|
|
dsps_bit_rev_fc32_ansi(visu.samples, FFT_LEN);
|
|
|
+ float rate = visu_export.rate;
|
|
|
|
|
|
// now arrange the result with the number of bar and sampling rate (don't want DC)
|
|
|
- for (int i = 1, j = 1; i <= visu.n && j < (FFT_LEN / 2); i++) {
|
|
|
+ for (int i = 0, j = 1; i < visu.n && j < (FFT_LEN / 2); i++) {
|
|
|
float power, count;
|
|
|
|
|
|
// find the next point in FFT (this is real signal, so only half matters)
|
|
|
- for (count = 0, power = 0; j * visu.n * visu_export.rate < i * (FFT_LEN / 2) * DISPLAY_BW && j < (FFT_LEN / 2); j++, count += 1) {
|
|
|
+ for (count = 0, power = 0; j * visu_export.rate < visu.bars[i].limit * FFT_LEN && j < FFT_LEN / 2; j++, count += 1) {
|
|
|
power += visu.samples[2*j] * visu.samples[2*j] + visu.samples[2*j+1] * visu.samples[2*j+1];
|
|
|
}
|
|
|
// due to sample rate, we have reached the end of the available spectrum
|
|
@@ -674,7 +681,7 @@ static void visu_update(void) {
|
|
|
if (count) power /= count * 2.;
|
|
|
} else if (count) {
|
|
|
// how much of what remains do we need to add
|
|
|
- float ratio = j - (float) (i * DISPLAY_BW * (FFT_LEN / 2)) / (float) (visu.n * visu_export.rate);
|
|
|
+ float ratio = j - (visu.bars[i].limit * FFT_LEN) / rate;
|
|
|
power += (visu.samples[2*j] * visu.samples[2*j] + visu.samples[2*j+1] * visu.samples[2*j+1]) * ratio;
|
|
|
|
|
|
// normalize accumulated data
|
|
@@ -685,9 +692,9 @@ static void visu_update(void) {
|
|
|
}
|
|
|
|
|
|
// convert to dB and bars, same back-off
|
|
|
- if (power) visu.bars[i-1].current = 32 * (0.01667f*10*(log10f(power) - log10f(FFT_LEN/2*2)) - 0.2543f);
|
|
|
- if (visu.bars[i-1].current > 31) visu.bars[i-1].current = 31;
|
|
|
- else if (visu.bars[i-1].current < 0) visu.bars[i-1].current = 0;
|
|
|
+ if (power) visu.bars[i].current = 32 * (0.01667f*10*(log10f(power) - log10f(FFT_LEN/2*2)) - 0.2543f);
|
|
|
+ if (visu.bars[i].current > 31) visu.bars[i].current = 31;
|
|
|
+ else if (visu.bars[i].current < 0) visu.bars[i].current = 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -715,6 +722,22 @@ static void visu_update(void) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+/****************************************************************************************
|
|
|
+ * Visu packet handler
|
|
|
+ */
|
|
|
+void spectrum_limits(int min, int n, int pos) {
|
|
|
+ if (n / 2) {
|
|
|
+ int i;
|
|
|
+ float step = (DISPLAY_BW - min) * visu.spectrum_scale / (n/2);
|
|
|
+ visu.bars[pos].limit = min + step;
|
|
|
+ for (i = 1; i < n/2; i++) visu.bars[pos+i].limit = visu.bars[pos+i-1].limit + step;
|
|
|
+ spectrum_limits(visu.bars[pos + n/2 - 1].limit, n/2, pos + n/2);
|
|
|
+ } else {
|
|
|
+ visu.bars[pos].limit = DISPLAY_BW;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/****************************************************************************************
|
|
|
* Visu packet handler
|
|
|
*/
|
|
@@ -737,31 +760,38 @@ static void visu_handler( u8_t *data, int len) {
|
|
|
if (visu.row >= SB_HEIGHT) display->clear(false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row - visu.height - 1);
|
|
|
|
|
|
if (visu.mode) {
|
|
|
- pkt->width = htonl(pkt->width);
|
|
|
- pkt->height = htonl(pkt->height);
|
|
|
- pkt->row = htonl(pkt->row);
|
|
|
- pkt->col = htonl(pkt->col);
|
|
|
-
|
|
|
- if (pkt->width > 0 && pkt->count >= 4) {
|
|
|
+ if (pkt->count >= 4) {
|
|
|
// small visu, then go were we are told to
|
|
|
- visu.width = pkt->width;
|
|
|
+ pkt->height = htonl(pkt->height);
|
|
|
+ pkt->row = htonl(pkt->row);
|
|
|
+ pkt->col = htonl(pkt->col);
|
|
|
+
|
|
|
+ visu.width = htonl(pkt->width);
|
|
|
visu.height = pkt->height ? pkt->height : SB_HEIGHT;
|
|
|
visu.col = pkt->col < 0 ? display->width + pkt->col : pkt->col;
|
|
|
visu.row = pkt->row < 0 ? display->height + pkt->row : pkt->row;
|
|
|
visu.border = htonl(pkt->border);
|
|
|
- bars = htonl(pkt->small_bars);
|
|
|
+ bars = htonl(pkt->bars);
|
|
|
+ visu.spectrum_scale = htonl(pkt->spectrum_scale) / 100.;
|
|
|
} else {
|
|
|
// full screen visu, try to use bottom screen if available
|
|
|
visu.width = display->width;
|
|
|
visu.height = display->height > SB_HEIGHT ? display->height - SB_HEIGHT : display->height;
|
|
|
visu.col = visu.border = 0;
|
|
|
visu.row = display->height - visu.height;
|
|
|
- // already in CPU order
|
|
|
- bars = pkt->full_bars;
|
|
|
+ bars = htonl(pkt->full.bars);
|
|
|
+ visu.spectrum_scale = htonl(pkt->full.spectrum_scale) / 100.;
|
|
|
}
|
|
|
|
|
|
// try to adapt to what we have
|
|
|
- visu.n = visu.mode == VISU_VUMETER ? 2 : (bars ? bars : MAX_BARS);
|
|
|
+ if (visu.mode == VISU_SPECTRUM) {
|
|
|
+ visu.n = bars ? bars : MAX_BARS;
|
|
|
+ if (visu.spectrum_scale <= 0 || visu.spectrum_scale > 0.5) visu.spectrum_scale = 0.5;
|
|
|
+ spectrum_limits(0, visu.n, 0);
|
|
|
+ } else {
|
|
|
+ visu.n = 2;
|
|
|
+ }
|
|
|
+
|
|
|
do {
|
|
|
visu.bar_width = (visu.width - visu.border - visu.bar_gap * (visu.n - 1)) / visu.n;
|
|
|
if (visu.bar_width > 0) break;
|
|
@@ -784,7 +814,7 @@ static void visu_handler( u8_t *data, int len) {
|
|
|
|
|
|
display->clear(false, true, visu.col, visu.row, visu.col + visu.width - 1, visu.row - visu.height - 1);
|
|
|
|
|
|
- LOG_INFO("Visualizer with %u bars of width %d:%d:%d:%d (%w:%u,h:%u,c:%u,r:%u)", visu.n, visu.bar_border, visu.bar_width, visu.bar_gap, visu.border, visu.width, visu.height, visu.col, visu.row);
|
|
|
+ LOG_INFO("Visualizer with %u bars of width %d:%d:%d:%d (%w:%u,h:%u,c:%u,r:%u,s:%.02f)", visu.n, visu.bar_border, visu.bar_width, visu.bar_gap, visu.border, visu.width, visu.height, visu.col, visu.row, visu.spectrum_scale);
|
|
|
} else {
|
|
|
LOG_INFO("Stopping visualizer");
|
|
|
}
|