Copy /*******************************************************************************
* Create Scope Panel - Green theme, waveform display
******************************************************************************/
static void hw_create_scope_panel(lv_obj_t *panel)
{
int32_t chart_w = hw_chart_width;
int32_t chart_h = hw_chart_height;
/* Chart with oscilloscope style */
hw_scope_chart = lv_chart_create(panel);
lv_obj_set_size(hw_scope_chart, chart_w, chart_h);
lv_obj_align(hw_scope_chart, LV_ALIGN_TOP_LEFT, 0, 0);
lv_chart_set_type(hw_scope_chart, LV_CHART_TYPE_LINE);
lv_chart_set_point_count(hw_scope_chart, HW_SCOPE_CHART_POINTS);
lv_chart_set_range(hw_scope_chart,
LV_CHART_AXIS_PRIMARY_Y, 0, 100);
/* Green-on-dark oscilloscope theme */
lv_obj_set_style_bg_color(hw_scope_chart,
lv_color_hex(0x001100), 0);
lv_obj_set_style_line_color(hw_scope_chart,
lv_color_hex(0x003300), LV_PART_MAIN);
lv_obj_set_style_size(hw_scope_chart, 0, 0, LV_PART_INDICATOR);
lv_obj_set_style_line_width(hw_scope_chart, 2, LV_PART_ITEMS);
lv_chart_set_div_line_count(hw_scope_chart, 4, 5);
lv_obj_set_style_border_width(hw_scope_chart, 1, 0);
lv_obj_set_style_border_color(hw_scope_chart,
lv_color_hex(0x004400), 0);
hw_scope_series = lv_chart_add_series(hw_scope_chart,
lv_color_hex(0x00ff00), LV_CHART_AXIS_PRIMARY_Y);
/* ROW 1: Dropdown | Freq Slider (read-only) | POT label | Run */
hw_scope_dropdown = lv_dropdown_create(panel);
lv_dropdown_set_options(hw_scope_dropdown,
"Square\nSine\nTriangle\nSawtooth\nNoise\nPulse");
lv_dropdown_set_selected(hw_scope_dropdown, 1);
lv_obj_set_size(hw_scope_dropdown,
HW_DROPDOWN_WIDTH, HW_DROPDOWN_HEIGHT);
lv_obj_align(hw_scope_dropdown, LV_ALIGN_BOTTOM_LEFT, 5, -50);
lv_obj_add_event_cb(hw_scope_dropdown, hw_wave_type_cb,
LV_EVENT_VALUE_CHANGED, NULL);
/* Frequency slider: READ-ONLY (syncs with POTEN) */
hw_scope_freq_slider = lv_slider_create(panel);
lv_obj_set_size(hw_scope_freq_slider,
HW_SLIDER_WIDTH - 20, HW_SLIDER_HEIGHT);
lv_slider_set_range(hw_scope_freq_slider, 0, 100);
lv_slider_set_value(hw_scope_freq_slider, 30, LV_ANIM_OFF);
lv_obj_align(hw_scope_freq_slider,
LV_ALIGN_BOTTOM_MID, -40, -55);
lv_obj_remove_flag(hw_scope_freq_slider,
LV_OBJ_FLAG_CLICKABLE); /* Read-only! */
hw_scope_freq_label = lv_label_create(panel);
lv_label_set_text(hw_scope_freq_label, "1.0kHz");
lv_obj_set_style_text_color(hw_scope_freq_label,
lv_color_hex(0x00ff00), 0);
lv_obj_align_to(hw_scope_freq_label, hw_scope_freq_slider,
LV_ALIGN_OUT_RIGHT_MID, 5, 0);
/* POTEN indicator (yellow) */
hw_scope_pot_label = lv_label_create(panel);
lv_label_set_text(hw_scope_pot_label, "POT: --%");
lv_obj_set_style_text_color(hw_scope_pot_label,
lv_color_hex(0xFFFF00), 0);
lv_obj_align(hw_scope_pot_label,
LV_ALIGN_BOTTOM_RIGHT, -80, -55);
/* Run LED + Button */
hw_scope_run_led = lv_led_create(panel);
lv_obj_set_size(hw_scope_run_led, HW_LED_SIZE, HW_LED_SIZE);
lv_led_set_color(hw_scope_run_led,
lv_palette_main(LV_PALETTE_GREEN));
lv_obj_align(hw_scope_run_led,
LV_ALIGN_BOTTOM_RIGHT, -70, -55);
lv_led_on(hw_scope_run_led);
hw_scope_run_btn = lv_button_create(panel);
lv_obj_set_size(hw_scope_run_btn,
HW_BUTTON_WIDTH, HW_BUTTON_HEIGHT);
lv_obj_align(hw_scope_run_btn,
LV_ALIGN_BOTTOM_RIGHT, -5, -50);
lv_obj_t *run_label = lv_label_create(hw_scope_run_btn);
lv_label_set_text(run_label, "Stop");
lv_obj_center(run_label);
lv_obj_add_event_cb(hw_scope_run_btn, hw_run_btn_cb,
LV_EVENT_CLICKED, NULL);
/* ROW 2: Measurements */
hw_scope_vpp_label = lv_label_create(panel);
lv_label_set_text(hw_scope_vpp_label, "Vpp: --");
lv_obj_set_style_text_color(hw_scope_vpp_label,
lv_color_hex(0x00ff00), 0);
lv_obj_align(hw_scope_vpp_label,
LV_ALIGN_BOTTOM_LEFT, 5, -10);
hw_scope_freq_meas_label = lv_label_create(panel);
lv_label_set_text(hw_scope_freq_meas_label, "Freq: --");
lv_obj_set_style_text_color(hw_scope_freq_meas_label,
lv_color_hex(0xffff00), 0);
lv_obj_align(hw_scope_freq_meas_label,
LV_ALIGN_BOTTOM_MID, 0, -10);
hw_scope_rms_label = lv_label_create(panel);
lv_label_set_text(hw_scope_rms_label, "RMS: --");
lv_obj_set_style_text_color(hw_scope_rms_label,
lv_color_hex(0x00ffff), 0);
lv_obj_align(hw_scope_rms_label,
LV_ALIGN_BOTTOM_RIGHT, -5, -10);
}
/*******************************************************************************
* Create Generator Panel - Orange theme (key differences from Scope)
******************************************************************************/
static void hw_create_gen_panel(lv_obj_t *panel)
{
/* Chart: Orange theme (0x110800 bg, 0xff8800 series) */
/* Layout เหมือน Scope แต่เปลี่ยนสีเป็น Orange */
/* KEY DIFFERENCE 1: Frequency slider is USER-CONTROLLED */
hw_gen_freq_slider = lv_slider_create(panel);
lv_slider_set_range(hw_gen_freq_slider, 10, 500);
/* ไม่มี lv_obj_remove_flag(LV_OBJ_FLAG_CLICKABLE) */
/* ผู้ใช้ drag ได้ (10-500 Hz สำหรับ visible LED effect) */
/* KEY DIFFERENCE 2: Duty slider is READ-ONLY (POTEN) */
hw_gen_duty_slider = lv_slider_create(panel);
lv_slider_set_range(hw_gen_duty_slider, 10, 90);
lv_obj_remove_flag(hw_gen_duty_slider,
LV_OBJ_FLAG_CLICKABLE); /* Read-only! */
/* KEY DIFFERENCE 3: OUTPUT switch controls LED3 */
hw_gen_switch = lv_switch_create(panel);
lv_obj_add_event_cb(hw_gen_switch, hw_gen_switch_cb,
LV_EVENT_VALUE_CHANGED, NULL);
/* KEY DIFFERENCE 4: POTEN->Duty + LED status labels */
hw_gen_pot_label = lv_label_create(panel);
lv_label_set_text(hw_gen_pot_label, "POT: --% -> Duty: --%");
hw_gen_led_status = lv_label_create(panel);
lv_label_set_text(hw_gen_led_status, "LED3: OFF");
/* (ดู source code เต็มสำหรับ layout coordinates) */
}
/*******************************************************************************
* Create FFT Panel - Cyan theme, bar chart
******************************************************************************/
static void hw_create_fft_panel(lv_obj_t *panel)
{
/* Bar chart: Cyan theme (0x001a1a bg, 0x00ffff series) */
hw_fft_chart = lv_chart_create(panel);
lv_chart_set_type(hw_fft_chart, LV_CHART_TYPE_BAR);
lv_chart_set_point_count(hw_fft_chart, HW_FFT_CHART_BINS);
/* CRITICAL: Bar spacing */
lv_obj_set_style_pad_column(hw_fft_chart, 2, 0);
/* Gain slider + Peak frequency label */
hw_fft_gain_slider = lv_slider_create(panel);
lv_slider_set_range(hw_fft_gain_slider, 10, 100);
lv_obj_add_event_cb(hw_fft_gain_slider,
hw_fft_gain_slider_cb, LV_EVENT_VALUE_CHANGED, NULL);
hw_fft_dominant_label = lv_label_create(panel);
lv_label_set_text(hw_fft_dominant_label, "Peak: -- Hz");
/* (ดู source code เต็มสำหรับ layout coordinates) */
}