From 7a2860f8693174cc5d9f5772dacb9aaff729a3c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Thu, 22 Sep 2016 22:41:09 +0200 Subject: [PATCH] added text labels & lin mode --- User/dotmatrix.h | 4 -- User/font.h | 108 ++++++++++++++++++++++++++++++++++++++++++++++ User/screendef.h | 11 +++++ User/scrolltext.c | 73 +++++++++++++++++++++++++++++++ User/scrolltext.h | 13 ++++++ User/user_main.c | 80 ++++++++++++++++++++++++++-------- 6 files changed, 268 insertions(+), 21 deletions(-) create mode 100644 User/font.h create mode 100644 User/screendef.h create mode 100644 User/scrolltext.c create mode 100644 User/scrolltext.h diff --git a/User/dotmatrix.h b/User/dotmatrix.h index b61c7eb..555488e 100644 --- a/User/dotmatrix.h +++ b/User/dotmatrix.h @@ -21,10 +21,6 @@ typedef struct { uint32_t rows; /*!< Number of drivers vertically */ } DotMatrix_Init; -// global inst -extern DotMatrix_Cfg *dmtx; - - DotMatrix_Cfg* dmtx_init(DotMatrix_Init *init); /** diff --git a/User/font.h b/User/font.h new file mode 100644 index 0000000..ebe223a --- /dev/null +++ b/User/font.h @@ -0,0 +1,108 @@ +#ifndef FONT_H +#define FONT_H + +#define FONT_MIN ' ' +#define FONT_MAX '~' + +#define FONT_WIDTH 6 + +const unsigned char font[96][6] = { + {0x00,0x00,0x00,0x00,0x00,0x00}, // + {0x5c,0x00,0x00,0x00,0x00,0x00}, // ! + {0x06,0x00,0x06,0x00,0x00,0x00}, // " + {0x28,0x7c,0x28,0x7c,0x28,0x00}, // # + {0x5c,0x54,0xfe,0x54,0x74,0x00}, // $ + {0x44,0x20,0x10,0x08,0x44,0x00}, // % + {0x28,0x54,0x54,0x20,0x50,0x00}, // & + {0x06,0x00,0x00,0x00,0x00,0x00}, // ' + {0x38,0x44,0x00,0x00,0x00,0x00}, // ( + {0x44,0x38,0x00,0x00,0x00,0x00}, // ) + {0x02,0x07,0x02,0x00,0x00,0x00}, // * + {0x10,0x10,0x7c,0x10,0x10,0x00}, // + + {0xc0,0x00,0x00,0x00,0x00,0x00}, // , + {0x10,0x10,0x10,0x10,0x10,0x00}, // - + {0x40,0x00,0x00,0x00,0x00,0x00}, // . + {0x60,0x10,0x0c,0x00,0x00,0x00}, // / + {0x7c,0x64,0x54,0x4c,0x7c,0x00}, // 0 + {0x48,0x7c,0x40,0x00,0x00,0x00}, // 1 + {0x64,0x54,0x54,0x54,0x48,0x00}, // 2 + {0x44,0x54,0x54,0x54,0x6c,0x00}, // 3 + {0x3c,0x20,0x70,0x20,0x20,0x00}, // 4 + {0x5c,0x54,0x54,0x54,0x24,0x00}, // 5 + {0x7c,0x54,0x54,0x54,0x74,0x00}, // 6 + {0x04,0x04,0x64,0x14,0x0c,0x00}, // 7 + {0x7c,0x54,0x54,0x54,0x7c,0x00}, // 8 + {0x5c,0x54,0x54,0x54,0x7c,0x00}, // 9 + {0x44,0x00,0x00,0x00,0x00,0x00}, // : + {0xc4,0x00,0x00,0x00,0x00,0x00}, // ; + {0x10,0x28,0x44,0x00,0x00,0x00}, // < + {0x28,0x28,0x28,0x28,0x28,0x00}, // = + {0x44,0x28,0x10,0x00,0x00,0x00}, // > + {0x08,0x04,0x54,0x08,0x00,0x00}, // ? + {0x7c,0x44,0x54,0x54,0x5c,0x00}, // @ + {0x7c,0x24,0x24,0x24,0x7c,0x00}, // A + {0x7c,0x54,0x54,0x54,0x6c,0x00}, // B + {0x7c,0x44,0x44,0x44,0x44,0x00}, // C + {0x7c,0x44,0x44,0x44,0x38,0x00}, // D + {0x7c,0x54,0x54,0x54,0x44,0x00}, // E + {0x7c,0x14,0x14,0x14,0x04,0x00}, // F + {0x7c,0x44,0x44,0x54,0x74,0x00}, // G + {0x7c,0x10,0x10,0x10,0x7c,0x00}, // H + {0x44,0x44,0x7c,0x44,0x44,0x00}, // I + {0x60,0x40,0x40,0x44,0x7c,0x00}, // J + {0x7c,0x10,0x10,0x28,0x44,0x00}, // K + {0x7c,0x40,0x40,0x40,0x40,0x00}, // L + {0x7c,0x08,0x10,0x08,0x7c,0x00}, // M + {0x7c,0x08,0x10,0x20,0x7c,0x00}, // N + {0x38,0x44,0x44,0x44,0x38,0x00}, // O + {0x7c,0x14,0x14,0x14,0x08,0x00}, // P + {0x3c,0x24,0x64,0x24,0x3c,0x00}, // Q + {0x7c,0x14,0x14,0x14,0x68,0x00}, // R + {0x5c,0x54,0x54,0x54,0x74,0x00}, // S + {0x04,0x04,0x7c,0x04,0x04,0x00}, // T + {0x7c,0x40,0x40,0x40,0x7c,0x00}, // U + {0x0c,0x30,0x40,0x30,0x0c,0x00}, // V + {0x3c,0x40,0x30,0x40,0x3c,0x00}, // W + {0x44,0x28,0x10,0x28,0x44,0x00}, // X + {0x0c,0x10,0x60,0x10,0x0c,0x00}, // Y + {0x44,0x64,0x54,0x4c,0x44,0x00}, // Z + {0x7c,0x44,0x00,0x00,0x00,0x00}, // [ + {0x0c,0x10,0x60,0x00,0x00,0x00}, // "\" + {0x44,0x7c,0x00,0x00,0x00,0x00}, // ] + {0x00,0x01,0x00,0x01,0x00,0x00}, // ^ + {0x40,0x40,0x40,0x40,0x40,0x40}, // _ + {0x00,0x01,0x00,0x00,0x00,0x00}, // ` + {0x7c,0x24,0x24,0x24,0x7c,0x00}, // a + {0x7c,0x54,0x54,0x54,0x6c,0x00}, // b + {0x7c,0x44,0x44,0x44,0x44,0x00}, // c + {0x7c,0x44,0x44,0x44,0x38,0x00}, // d + {0x7c,0x54,0x54,0x54,0x44,0x00}, // e + {0x7c,0x14,0x14,0x14,0x04,0x00}, // f + {0x7c,0x44,0x44,0x54,0x74,0x00}, // g + {0x7c,0x10,0x10,0x10,0x7c,0x00}, // h + {0x44,0x44,0x7c,0x44,0x44,0x00}, // i + {0x60,0x40,0x40,0x44,0x7c,0x00}, // j + {0x7c,0x10,0x10,0x28,0x44,0x00}, // k + {0x7c,0x40,0x40,0x40,0x40,0x00}, // l + {0x7c,0x08,0x10,0x08,0x7c,0x00}, // m + {0x7c,0x08,0x10,0x20,0x7c,0x00}, // n + {0x38,0x44,0x44,0x44,0x38,0x00}, // o + {0x7c,0x14,0x14,0x14,0x08,0x00}, // p + {0x3c,0x24,0x64,0x24,0x3c,0x00}, // q + {0x7c,0x14,0x14,0x14,0x68,0x00}, // r + {0x5c,0x54,0x54,0x54,0x74,0x00}, // s + {0x04,0x04,0x7c,0x04,0x04,0x00}, // t + {0x7c,0x40,0x40,0x40,0x7c,0x00}, // u + {0x0c,0x30,0x40,0x30,0x0c,0x00}, // v + {0x3c,0x40,0x30,0x40,0x3c,0x00}, // w + {0x44,0x28,0x10,0x28,0x44,0x00}, // x + {0x0c,0x10,0x60,0x10,0x0c,0x00}, // y + {0x44,0x64,0x54,0x4c,0x44,0x00}, // z + {0x10,0x7c,0x44,0x00,0x00,0x00}, // { + {0x6c,0x00,0x00,0x00,0x00,0x00}, // | + {0x44,0x7c,0x10,0x00,0x00,0x00}, // } + {0x02,0x01,0x02,0x01,0x00,0x00}, // ~ + {0x00,0x00,0x00,0x00,0x00,0x00} +}; + +#endif // FONT_H diff --git a/User/screendef.h b/User/screendef.h new file mode 100644 index 0000000..6ac416c --- /dev/null +++ b/User/screendef.h @@ -0,0 +1,11 @@ +// +// Created by MightyPork on 2016/09/22. +// + +#ifndef F107_FFT_SCREENDEF_H +#define F107_FFT_SCREENDEF_H + +#define SCREEN_W 32 +#define SCREEN_H 16 + +#endif //F107_FFT_SCREENDEF_H diff --git a/User/scrolltext.c b/User/scrolltext.c new file mode 100644 index 0000000..6e849fc --- /dev/null +++ b/User/scrolltext.c @@ -0,0 +1,73 @@ +#include +#include "scrolltext.h" + +#include "font.h" +#include "screendef.h" + +volatile bool text_moving; + +/** + * Print text at coordinates + * @param text + * @param x + * @param y + */ +void printtext(DotMatrix_Cfg *disp, const char *text, int x, int y) +{ + int totalX = 0; + + for (int textX = 0; textX < (int)strlen(text); textX++) { + uint8_t ch = (uint8_t)text[textX]; + if (ch < FONT_MIN) ch = '?'; + if (ch > FONT_MAX) ch = '?'; + ch -= ' '; // normalize for font table + + if (ch == 0) { // space + totalX += 4; + continue; + } + + // one letter + uint8_t blanks = 0; + + // skip empty space on right + for (int charX = FONT_WIDTH-1; charX >= 0; charX--) { + uint8_t col = font[ch][charX]; + if (col == 0x00) { + blanks++; + } else { + break; + } + } + + for (int charX = 0; charX < FONT_WIDTH - blanks; charX++) { + uint8_t col = font[ch][charX]; + for (int charY = 0; charY < 8; charY++) { + dmtx_set(disp, x + totalX, y + 8 - charY, (col >> charY) & 1); + } + totalX++; + } + + totalX+= 2; // gap + } +} + +/** + * Scroll text across the screen + * @param text + * @param step delay per step (ms) + */ +void scrolltext(DotMatrix_Cfg *disp, const char *text, ms_time_t step) +{ + (void)step; + + text_moving = true; + for (int i = 0; i < (int)strlen(text)*(FONT_WIDTH+1) + SCREEN_W-1; i++) { + if (i > 0) delay_ms(step); + + dmtx_clear(disp); + printtext(disp, text, (SCREEN_W-1)-i, SCREEN_H/2-4); + dmtx_show(disp); + } + text_moving = false; +} diff --git a/User/scrolltext.h b/User/scrolltext.h new file mode 100644 index 0000000..c0b5ad4 --- /dev/null +++ b/User/scrolltext.h @@ -0,0 +1,13 @@ +#ifndef SCROLLTEXT_H +#define SCROLLTEXT_H + +#include "dotmatrix.h" +#include "timebase.h" + +volatile extern bool text_moving; + +void printtext(DotMatrix_Cfg *disp, const char *text, int x, int y); + +void scrolltext(DotMatrix_Cfg *disp, const char *text, ms_time_t step); + +#endif // SCROLLTEXT_H diff --git a/User/user_main.c b/User/user_main.c index 9466ff0..f55de99 100644 --- a/User/user_main.c +++ b/User/user_main.c @@ -13,6 +13,8 @@ #include "debounce.h" #include "debug.h" #include "fft_windows.h" +#include "screendef.h" +#include "scrolltext.h" // 512 = show 0-5 kHz // 256 = show 0-10 kHz @@ -21,9 +23,7 @@ #define BIN_COUNT (SAMPLE_COUNT/2) #define CFFT_INST arm_cfft_sR_f32_len256 -#define SCREEN_W 32 -#define SCREEN_H 16 -#define DEFAULT_BRIGHTNESS 2 +#define DEFAULT_BRIGHTNESS 3 // Pins #define BTN_CENTER 0 @@ -44,6 +44,8 @@ #define VOL_STEP_THRESH 0.01 #define VOL_STEP_SPEEDUP_TIME 750 +#define SCROLL_STEP_MS 15 + uint32_t audio_samples[SAMPLE_COUNT * 2]; // 2x size needed for complex FFT float *audio_samples_f = (float *) audio_samples; @@ -62,10 +64,14 @@ volatile bool capture_pending = false; float y_scale = 1; uint8_t brightness = DEFAULT_BRIGHTNESS; +/** var used to signalize to MAIN that a banner should scroll */ +static bool request_banner_text = false; + /** active rendering mode (visualisation preset) */ enum { MODE_SPECTRUM, MODE_SPECTRUM2, + MODE_LINEAR, MODE_WAVEFORM, MAX_MODE } render_mode; @@ -77,7 +83,7 @@ bool right_pressed = false; static void display_wave(); -static void calculate_fft(); +static void calculate_fft(bool logmode); static void display_fft(); @@ -102,18 +108,28 @@ void capture_start() /** This callback is called by HAL after the transfer is complete */ void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { + if (text_moving || request_banner_text) { + capture_pending = false; + return; + } + switch (render_mode) { case MODE_WAVEFORM: display_wave(); break; + case MODE_LINEAR: + calculate_fft(false); + display_fft(); + break; + case MODE_SPECTRUM: - calculate_fft(); + calculate_fft(true); display_fft(); break; case MODE_SPECTRUM2: - calculate_fft(); + calculate_fft(true); display_fft_spindle(); break; } @@ -181,7 +197,7 @@ void display_wave() } /** Calculate FFT */ -static void calculate_fft() +static void calculate_fft(bool logmode) { float *bins = audio_samples_f; @@ -203,7 +219,11 @@ static void calculate_fft() for (int i = 0; i < BIN_COUNT; i++) { // +1 because bin 0 is always 0 float bin = bins[i] * (1.0f / BIN_COUNT) * FFT_PRELOG_SCALE; - bin = log2f(bin); + if (logmode) { + bin = log2f(bin); + } else { + // + } bins[i] = bin * FFT_FINAL_SCALE; } } @@ -216,7 +236,9 @@ static void display_fft() float *bins = audio_samples_f; for (int x = 0; x < SCREEN_W; x++) { - for (int j = 0; j < 1 + floorf(bins[x]); j++) { + float bin = floorf(bins[x]); + if (bin<0) bin=0; + for (int j = 0; j < 1 + bin; j++) { dmtx_set(disp, x, j, 1); } } @@ -232,7 +254,9 @@ static void display_fft_spindle() float *bins = audio_samples_f; for (int x = 0; x < SCREEN_W; x++) { - for (int j = 0; j < 1 + floorf(bins[x] * 0.5f); j++) { + float bin = floorf(bins[x] * 0.5f); + if (bin<0) bin=0; + for (int j = 0; j < 1 + bin; j++) { dmtx_set(disp, x, 7 + j, 1); dmtx_set(disp, x, 7 - j, 1); } @@ -305,9 +329,11 @@ static void gamepad_button_cb(uint32_t btn, bool press) if (++render_mode == MAX_MODE) { render_mode = 0; } + + info("Switched to render mode %d", render_mode); + request_banner_text = true; } - info("Switched to render mode %d", render_mode); break; } } @@ -385,8 +411,9 @@ void user_main() user_init(); + request_banner_text = true; + ms_time_t counter1 = 0; - ms_time_t counter2 = 0; while (1) { if (ms_loop_elapsed(&counter1, 500)) { // Blink @@ -441,12 +468,31 @@ void user_main() } } - // capture a sample to update display - //if (ms_loop_elapsed(&counter2, 10)) { - if (!capture_pending) { - capture_start(); + if (request_banner_text) { + switch (render_mode) { + case MODE_SPECTRUM: + scrolltext(disp, "FFT LOG-Y", SCROLL_STEP_MS); + break; + + case MODE_SPECTRUM2: + scrolltext(disp, "FFT LOG-Y MIRROR", SCROLL_STEP_MS); + break; + + case MODE_LINEAR: + scrolltext(disp, "FFT LIN-Y", SCROLL_STEP_MS); + break; + + case MODE_WAVEFORM: + scrolltext(disp, "WAVEFORM", SCROLL_STEP_MS); + break; } - //} + request_banner_text = false; + } + + // capture a sample to update display + if (!capture_pending) { + capture_start(); + } } }