Added an audio FFT view in Wideband FM receive

Tried speeding up fill_rectangle for clearing the waveform widget
This commit is contained in:
furrtek
2018-05-21 18:46:48 +01:00
parent b11c3c94b6
commit b813b32593
19 changed files with 259 additions and 38 deletions

View File

@@ -100,25 +100,26 @@ void fft_swap_in_place(std::array<T, N>& data) {
/* http://www.drdobbs.com/cpp/a-simple-and-efficient-fft-implementatio/199500857?pgno=3 */
template<typename T, size_t N>
void fft_c_preswapped(std::array<T, N>& data) {
void fft_c_preswapped(std::array<T, N>& data, const size_t from, const size_t to) {
static_assert(power_of_two(N), "only defined for N == power of two");
constexpr auto K = log_2(N);
if ((to > K) || (from > K)) return;
constexpr size_t K_max = 8;
static_assert(K <= K_max, "No FFT twiddle factors for K > 8");
static constexpr std::array<std::complex<float>, K_max> wp_table { {
{ -2.0f, 0.0f },
{ -1.0f, -1.0f },
{ -0.2928932188134524756f, -0.7071067811865475244f },
{ -0.076120467488713243872f, -0.38268343236508977173f },
{ -0.019214719596769550874f, -0.19509032201612826785f },
{ -0.0048152733278031137552f, -0.098017140329560601994f },
{ -0.0012045437948276072852f, -0.049067674327418014255f },
{ -0.00030118130379577988423f, -0.024541228522912288032f },
{ -2.0f, 0.0f }, // 2
{ -1.0f, -1.0f }, // 4
{ -0.2928932188134524756f, -0.7071067811865475244f }, // 8
{ -0.076120467488713243872f, -0.38268343236508977173f }, // 16
{ -0.019214719596769550874f, -0.19509032201612826785f }, // 32
{ -0.0048152733278031137552f, -0.098017140329560601994f }, // 64
{ -0.0012045437948276072852f, -0.049067674327418014255f }, // 128
{ -0.00030118130379577988423f, -0.024541228522912288032f }, // 256
} };
/* Provide data to this function, pre-swapped. */
for(size_t k = 0; k < log_2(N); k++) {
for(size_t k = from; k < to; k++) {
const size_t mmax = 1 << k;
const auto wp = wp_table[k];
T w { 1.0f, 0.0f };

View File

@@ -297,6 +297,15 @@ void ILI9341::fill_rectangle(ui::Rect r, const ui::Color c) {
}
}
void ILI9341::fill_rectangle_unrolled8(ui::Rect r, const ui::Color c) {
const auto r_clipped = r.intersect(screen_rect());
if( !r_clipped.is_empty() ) {
lcd_start_ram_write(r_clipped);
size_t count = r_clipped.width() * r_clipped.height();
io.lcd_write_pixels_unrolled8(c, count);
}
}
void ILI9341::render_line(const ui::Point p, const uint8_t count, const ui::Color* line_buffer) {
lcd_start_ram_write(p, { count, 1 });
io.lcd_write_pixels(line_buffer, count);

View File

@@ -49,6 +49,7 @@ public:
void wake();
void fill_rectangle(ui::Rect r, const ui::Color c);
void fill_rectangle_unrolled8(ui::Rect r, const ui::Color c);
void draw_line(const ui::Point start, const ui::Point end, const ui::Color color);
void fill_circle(
const ui::Point center,

View File

@@ -106,6 +106,7 @@ public:
AudioLevelReport = 51,
CodedSquelch = 52,
AudioSpectrumConfig = 53,
MAX
};
@@ -273,6 +274,27 @@ public:
size_t trigger { 0 };
};
struct AudioSpectrum {
std::array<uint8_t, 128> db { { 0 } };
//uint32_t sampling_rate { 0 };
};
using AudioSpectrumFIFO = FIFO<AudioSpectrum>;
class AudioSpectrumConfigMessage : public Message {
public:
static constexpr size_t fifo_k = 2;
constexpr AudioSpectrumConfigMessage(
AudioSpectrumFIFO* fifo
) : Message { ID::AudioSpectrumConfig },
fifo { fifo }
{
}
AudioSpectrumFIFO* fifo { nullptr };
};
struct ChannelSpectrum {
std::array<uint8_t, 256> db { { 0 } };
uint32_t sampling_rate { 0 };

View File

@@ -158,6 +158,21 @@ public:
}
}
void lcd_write_pixels_unrolled8(const ui::Color pixel, size_t n) {
auto v = pixel.v;
n >>= 3;
while(n--) {
lcd_write_data(v);
lcd_write_data(v);
lcd_write_data(v);
lcd_write_data(v);
lcd_write_data(v);
lcd_write_data(v);
lcd_write_data(v);
lcd_write_data(v);
}
}
void lcd_write_pixels(const ui::Color* const pixels, size_t n) {
for(size_t i=0; i<n; i++) {
lcd_write_pixel(pixels[i]);

View File

@@ -98,6 +98,10 @@ void Painter::fill_rectangle(const Rect r, const Color c) {
display.fill_rectangle(r, c);
}
void Painter::fill_rectangle_unrolled8(const Rect r, const Color c) {
display.fill_rectangle_unrolled8(r, c);
}
void Painter::paint_widget_tree(Widget* const w) {
if( ui::is_dirty() ) {
paint_widget(w);

View File

@@ -56,6 +56,7 @@ public:
void draw_rectangle(const Rect r, const Color c);
void fill_rectangle(const Rect r, const Color c);
void fill_rectangle_unrolled8(const Rect r, const Color c);
void paint_widget_tree(Widget* const w);

View File

@@ -1493,6 +1493,7 @@ Waveform::Waveform(
color_ { color }
{
//set_focusable(false);
//previous_data.resize(length_, 0);
}
void Waveform::set_cursor(const uint32_t i, const int16_t position) {
@@ -1522,19 +1523,31 @@ void Waveform::set_length(const uint32_t new_length) {
void Waveform::paint(Painter& painter) {
size_t n;
Coord y, y_offset = screen_rect().location().y();
Coord prev_x = screen_rect().location().x(), prev_y;
Coord prev_x, prev_y;
float x, x_inc;
Dim h = screen_rect().size().height();
const float y_scale = (float)(h - 1) / 65536.0;
int16_t * data_start = data_ + offset_;
// Clear
painter.fill_rectangle(screen_rect(), Color::black());
if (!length_) return;
x_inc = (float)screen_rect().size().width() / length_;
// Clear
painter.fill_rectangle_unrolled8(screen_rect(), Color::black());
/*prev_x = screen_rect().location().x();
prev_y = previous_data[0];
x = prev_x + x_inc;
for (n = 1; n < length_; n++) {
y = previous_data[n];
display.draw_line( {prev_x, prev_y}, {(Coord)x, y}, Color::black());
prev_x = x;
prev_y = y;
x += x_inc;
}*/
prev_x = screen_rect().location().x();
if (digital_) {
// Digital waveform: each value is an horizontal line
x = 0;
@@ -1557,8 +1570,10 @@ void Waveform::paint(Painter& painter) {
x = prev_x + x_inc;
h /= 2;
prev_y = y_offset + h - (*(data_start++) * y_scale);
//previous_data[0] = prev_y;
for (n = 1; n < length_; n++) {
y = y_offset + h - (*(data_start++) * y_scale);
//previous_data[n] = y;
display.draw_line( {prev_x, prev_y}, {(Coord)x, y}, color_);
prev_x = x;

View File

@@ -617,6 +617,7 @@ private:
const Color cursor_colors[2] = { Color::cyan(), Color::magenta() };
int16_t * data_;
//std::vector<int16_t> previous_data { };
uint32_t length_;
uint32_t offset_;
bool digital_ { false };