Copy void part3_ex6_spectrum_analyzer(void)
{
lv_obj_t *scr = lv_screen_active();
lv_obj_set_style_bg_color(scr, lv_color_hex(0x0a0a1e), 0);
/* ===== Title Row ===== */
lv_obj_t *title = lv_label_create(scr);
lv_label_set_text(title, "Part 3 Ex6: Spectrum Analyzer");
lv_obj_set_style_text_color(title, lv_color_hex(0xff6600), 0);
lv_obj_align(title, LV_ALIGN_TOP_LEFT, 10, 3);
/* Peak frequency label */
peak_freq_label = lv_label_create(scr);
lv_label_set_text(peak_freq_label, "Peak: -- Hz");
lv_obj_set_style_text_color(peak_freq_label,
lv_color_hex(0xffff00), 0);
lv_obj_align(peak_freq_label, LV_ALIGN_TOP_RIGHT, -10, 3);
/* ===== Wave Type Dropdown ===== */
lv_obj_t *wave_dd = lv_dropdown_create(scr);
lv_dropdown_set_options(wave_dd,
"Sine\nSquare\nTriangle\nSawtooth\nDual Sine");
lv_dropdown_set_selected(wave_dd, 0);
lv_obj_set_width(wave_dd, 110);
lv_obj_align(wave_dd, LV_ALIGN_TOP_LEFT, 10, 22);
lv_obj_add_event_cb(wave_dd, fft_wave_cb,
LV_EVENT_VALUE_CHANGED, NULL);
/* Gain slider */
lv_obj_t *gain_lbl = lv_label_create(scr);
lv_label_set_text(gain_lbl, "Gain:");
lv_obj_set_style_text_color(gain_lbl, lv_color_hex(0x00ffff), 0);
lv_obj_align(gain_lbl, LV_ALIGN_TOP_LEFT, 140, 28);
lv_obj_t *gain_slider = lv_slider_create(scr);
lv_slider_set_range(gain_slider, 10, 100);
lv_slider_set_value(gain_slider, 50, LV_ANIM_OFF);
lv_obj_set_width(gain_slider, 120);
lv_obj_align(gain_slider, LV_ALIGN_TOP_LEFT, 185, 28);
lv_obj_add_event_cb(gain_slider, fft_gain_cb,
LV_EVENT_VALUE_CHANGED, NULL);
/* ===== Time Domain Chart (ด้านบน) ===== */
time_chart = lv_chart_create(scr);
lv_obj_set_size(time_chart, 440, 90);
lv_obj_align(time_chart, LV_ALIGN_TOP_MID, 0, 50);
lv_chart_set_type(time_chart, LV_CHART_TYPE_LINE);
lv_chart_set_point_count(time_chart, TIME_DISPLAY_PTS);
lv_chart_set_range(time_chart, LV_CHART_AXIS_PRIMARY_Y, 0, 100);
lv_chart_set_div_line_count(time_chart, 2, 5);
lv_obj_set_style_bg_color(time_chart, lv_color_hex(0x001a00), 0);
lv_obj_set_style_line_color(time_chart, lv_color_hex(0x002200),
LV_PART_MAIN);
lv_obj_set_style_border_color(time_chart, lv_color_hex(0x004400), 0);
lv_obj_set_style_border_width(time_chart, 1, 0);
lv_obj_set_style_size(time_chart, 0, 0, LV_PART_INDICATOR);
time_series = lv_chart_add_series(time_chart,
lv_color_hex(0x00ff00), LV_CHART_AXIS_PRIMARY_Y);
/* ===== FFT Bar Chart (ด้านล่าง) ===== */
fft_chart = lv_chart_create(scr);
lv_obj_set_size(fft_chart, 440, 110);
lv_obj_align(fft_chart, LV_ALIGN_BOTTOM_MID, 0, -22);
lv_chart_set_type(fft_chart, LV_CHART_TYPE_BAR);
lv_chart_set_point_count(fft_chart, FFT_DISPLAY_BINS);
lv_chart_set_range(fft_chart, LV_CHART_AXIS_PRIMARY_Y, 0, 100);
lv_chart_set_div_line_count(fft_chart, 4, 5);
/* CRITICAL: Bar spacing */
lv_obj_set_style_pad_column(fft_chart, 2, 0);
/* Cyan theme */
lv_obj_set_style_bg_color(fft_chart, lv_color_hex(0x001a1a), 0);
lv_obj_set_style_line_color(fft_chart, lv_color_hex(0x003333),
LV_PART_MAIN);
lv_obj_set_style_border_color(fft_chart, lv_color_hex(0x006666), 0);
lv_obj_set_style_border_width(fft_chart, 1, 0);
fft_series = lv_chart_add_series(fft_chart,
lv_color_hex(0x00ffff), LV_CHART_AXIS_PRIMARY_Y);
/* Initialize bars to 0 */
for (int i = 0; i < FFT_DISPLAY_BINS; i++) {
lv_chart_set_value_by_id(fft_chart, fft_series, i, 0);
}
/* Frequency scale labels */
lv_obj_t *f0 = lv_label_create(scr);
lv_label_set_text(f0, "0 Hz");
lv_obj_set_style_text_color(f0, lv_color_hex(0x666666), 0);
lv_obj_align(f0, LV_ALIGN_BOTTOM_LEFT, 15, -5);
lv_obj_t *fmax = lv_label_create(scr);
lv_label_set_text_fmt(fmax, "%u Hz",
(unsigned int)(FFT_SAMPLE_RATE / 2));
lv_obj_set_style_text_color(fmax, lv_color_hex(0x666666), 0);
lv_obj_align(fmax, LV_ALIGN_BOTTOM_RIGHT, -15, -5);
/* ===== Timer ===== */
fft_timer = lv_timer_create(fft_timer_cb, 200, NULL);
/* แสดงผลครั้งแรก */
update_fft_display();
}