301 lines
9.2 KiB
C
301 lines
9.2 KiB
C
/*
|
|
* home_screen.c
|
|
*
|
|
* Created on: Aug 7, 2023
|
|
* Author: leo
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "lvgl.h"
|
|
|
|
#include "PSE_unit.h"
|
|
#include "PSE_unit_edit_screen.h"
|
|
#include "pse_stepper_planer.h"
|
|
|
|
static pse_unit* units;
|
|
static int units_num;
|
|
|
|
static uint16_t workspace_index = 0;
|
|
static lv_obj_t* ws_label;
|
|
|
|
static lv_timer_t* volume_readout_update_timer = NULL;
|
|
|
|
static uint8_t run_status = 0;
|
|
|
|
static void delete_timer(lv_timer_t** timer){
|
|
if(*timer == NULL) return;
|
|
lv_timer_del(*timer);
|
|
*timer = NULL;
|
|
}
|
|
|
|
void volume_readout_update(lv_timer_t* timer){
|
|
for(int i = 0; i < units_num; i++){
|
|
if(units[i].enabled){
|
|
pse_home_display* disp = units[i].home_display;
|
|
pse_unit_compute_volume_delivered(&units[i]);
|
|
int32_t volume = units[i].volume;
|
|
lv_label_set_text_fmt(disp->volume, "%ld.%.3d\nmL", volume / 1000, abs(volume) % 1000);
|
|
}
|
|
}
|
|
}
|
|
|
|
// start stop button handler
|
|
static void run_handler(lv_event_t * e){
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
|
|
if(code == LV_EVENT_VALUE_CHANGED) {
|
|
lv_obj_t* button = lv_event_get_current_target(e);
|
|
lv_obj_t* label = lv_obj_get_child(button, 0);
|
|
lv_state_t state = lv_obj_get_state(button);
|
|
|
|
// start
|
|
if(state & LV_STATE_CHECKED){
|
|
lv_label_set_text(label, LV_SYMBOL_PAUSE);
|
|
pse_sp_set_dir_all(units, units_num, 1);
|
|
pse_sp_start_all(units, units_num);
|
|
|
|
// store the status in case we switch to the edit screen while running
|
|
run_status = 1;
|
|
|
|
// start the volume readout update timer
|
|
volume_readout_update_timer = lv_timer_create(volume_readout_update, 100, NULL);
|
|
}
|
|
else{ // stop
|
|
lv_label_set_text(label, LV_SYMBOL_PLAY);
|
|
pse_sp_stop_all(units, units_num);
|
|
delete_timer(&volume_readout_update_timer);
|
|
run_status = 0;
|
|
|
|
// save the unit (to keep track of the position)
|
|
save_units(units, units_num, workspace_index);
|
|
}
|
|
}
|
|
}
|
|
|
|
static lv_coord_t units_col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
|
static lv_coord_t units_row_dsc[] = {LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
|
|
|
static lv_obj_t* screen;
|
|
|
|
static void unit_widget_enabled_handler(lv_event_t * e){
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
|
|
if(code == LV_EVENT_VALUE_CHANGED) {
|
|
lv_obj_t* button = lv_event_get_current_target(e);
|
|
lv_obj_t* label = lv_obj_get_child(button, 0);
|
|
lv_state_t state = lv_obj_get_state(button);
|
|
|
|
|
|
pse_unit* unit = lv_event_get_user_data(e);
|
|
if(state & LV_STATE_CHECKED){
|
|
lv_label_set_text(label, LV_SYMBOL_CLOSE);
|
|
unit->enabled = 0;
|
|
}
|
|
else{
|
|
lv_label_set_text(label, LV_SYMBOL_OK);
|
|
unit->enabled = 1;
|
|
}
|
|
save_units(units, units_num, workspace_index);
|
|
}
|
|
}
|
|
|
|
static void unit_home_handler(lv_event_t * e){
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
|
|
if(code == LV_EVENT_CLICKED) {
|
|
pse_unit* unit = lv_event_get_user_data(e);
|
|
pse_stepper_conf* c = unit->stepper_conf;
|
|
pse_stepper_status* s = unit->stepper_status;
|
|
if(s->steps_counter == 0) return;
|
|
s->stop_at_limit = 1;
|
|
s->stop_steps = 0;
|
|
pse_sp_jog_speed(c, s, 1);
|
|
pse_sp_set_dir(unit, s->steps_counter < 0);
|
|
pse_sp_start_axis(c, s);
|
|
}
|
|
}
|
|
|
|
static void unit_widget_clicked_handler(lv_event_t* e){
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
|
|
if(code == LV_EVENT_CLICKED) {
|
|
if(volume_readout_update_timer != NULL) delete_timer(&volume_readout_update_timer);
|
|
pse_unit* unit = lv_event_get_user_data(e);
|
|
PSE_unit_edit_screen_Gen(units, unit, units_num, workspace_index);
|
|
}
|
|
}
|
|
|
|
static void update_readouts_widgets(){
|
|
for(int i = 0; i < units_num; i++){
|
|
pse_unit* pse_unit = &units[i];
|
|
lv_label_set_text_fmt(pse_unit->home_display->flow, "%lu.%03lu\nmL/mn", pse_unit->flow / 1000, pse_unit->flow % 1000);
|
|
volume_readout_update(NULL);
|
|
|
|
lv_obj_t* enabled = pse_unit->home_display->enabled;
|
|
lv_obj_t* enabled_label = lv_obj_get_child(enabled, 0);
|
|
if(pse_unit->enabled){
|
|
lv_obj_clear_state(enabled, LV_STATE_CHECKED);
|
|
lv_label_set_text(enabled_label, LV_SYMBOL_OK);
|
|
}
|
|
else{
|
|
lv_obj_add_state(enabled, LV_STATE_CHECKED);
|
|
lv_label_set_text(enabled_label, LV_SYMBOL_CLOSE);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void ws_left_handler(lv_event_t * e){
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
|
|
if(code != LV_EVENT_CLICKED) return;
|
|
|
|
if(workspace_index == 0) return;
|
|
workspace_index--;
|
|
|
|
lv_label_set_text_fmt(ws_label, "%d", workspace_index);
|
|
load_units_short(units, units_num, workspace_index);
|
|
update_readouts_widgets();
|
|
}
|
|
static void ws_right_handler(lv_event_t * e){
|
|
lv_event_code_t code = lv_event_get_code(e);
|
|
|
|
if(code != LV_EVENT_CLICKED) return;
|
|
|
|
workspace_index++;
|
|
|
|
lv_label_set_text_fmt(ws_label, "%d", workspace_index);
|
|
load_units_short(units, units_num, workspace_index);
|
|
update_readouts_widgets();
|
|
}
|
|
|
|
static lv_obj_t* PSE_unit_widget(lv_obj_t* parent, pse_unit* pse_unit){
|
|
// The main container
|
|
lv_obj_t* cont = lv_obj_create(parent);
|
|
lv_obj_set_size(cont, lv_pct(24), lv_pct(100));
|
|
lv_obj_set_flex_flow(cont, LV_FLEX_FLOW_COLUMN);
|
|
lv_obj_add_event_cb(cont, unit_widget_clicked_handler, LV_EVENT_ALL, pse_unit);
|
|
|
|
// flow setting
|
|
lv_obj_t* flow = lv_label_create(cont);
|
|
lv_obj_set_width(flow, lv_pct(100));
|
|
lv_obj_set_flex_grow(flow, 1);
|
|
lv_label_set_long_mode(flow, LV_LABEL_LONG_CLIP);
|
|
lv_label_set_text_fmt(flow, "%02lu.%03lu\nmL/mn", pse_unit->flow / 1000, pse_unit->flow % 1000);
|
|
pse_unit->home_display->flow = flow;
|
|
|
|
// volume delivered readout
|
|
lv_obj_t* vol = lv_label_create(cont);
|
|
lv_obj_set_width(vol, lv_pct(100));
|
|
lv_obj_set_flex_grow(vol, 1);
|
|
lv_label_set_long_mode(vol, LV_LABEL_LONG_CLIP);
|
|
lv_label_set_text_fmt(vol, "%ld.%03d\nmL", pse_unit->volume / 1000, abs(pse_unit->volume) % 1000);
|
|
pse_unit->home_display->volume = vol;
|
|
|
|
// home button
|
|
lv_obj_t* home = lv_btn_create(cont);
|
|
lv_obj_t* home_label = lv_label_create(home);
|
|
lv_obj_set_width(home, lv_pct(100));
|
|
lv_obj_add_event_cb(home, unit_home_handler, LV_EVENT_ALL, pse_unit);
|
|
lv_obj_set_flex_grow(home, 1);
|
|
lv_obj_center(home_label);
|
|
lv_label_set_text(home_label, LV_SYMBOL_HOME);
|
|
|
|
// enabled button
|
|
lv_obj_t* enabled = lv_btn_create(cont);
|
|
lv_obj_t* enabled_label = lv_label_create(enabled);
|
|
lv_obj_set_width(enabled, lv_pct(100));
|
|
lv_obj_add_flag(enabled, LV_OBJ_FLAG_CHECKABLE);
|
|
lv_obj_add_event_cb(enabled, unit_widget_enabled_handler, LV_EVENT_ALL, pse_unit);
|
|
lv_obj_set_flex_grow(enabled, 1);
|
|
lv_obj_center(enabled_label);
|
|
lv_label_set_text(enabled_label, LV_SYMBOL_OK);
|
|
if(!pse_unit->enabled){
|
|
lv_obj_add_state(enabled, LV_STATE_CHECKED);
|
|
lv_label_set_text(enabled_label, LV_SYMBOL_CLOSE);
|
|
}
|
|
pse_unit->home_display->enabled = enabled;
|
|
return cont;
|
|
}
|
|
|
|
void Home_Screen_Gen(pse_unit* pse_units, uint8_t pse_unit_num, uint8_t delete){
|
|
// Create a new screen
|
|
lv_obj_t* scr = lv_obj_create(NULL);
|
|
screen = scr;
|
|
|
|
// set global unit variable
|
|
units = pse_units;
|
|
units_num = pse_unit_num;
|
|
|
|
// create the top menu on the top 20%
|
|
lv_obj_t* top_menu = lv_obj_create(scr);
|
|
lv_obj_set_align(top_menu, LV_ALIGN_TOP_LEFT);
|
|
lv_obj_set_size(top_menu, lv_pct(100), lv_pct(20));
|
|
lv_obj_set_style_pad_all(top_menu, 5, 0);
|
|
lv_obj_set_flex_flow(top_menu, LV_FLEX_FLOW_ROW);
|
|
|
|
// add a run button
|
|
lv_obj_t* run_button = lv_btn_create(top_menu);
|
|
lv_obj_set_flex_grow(run_button, 3);
|
|
lv_obj_set_align(run_button, LV_ALIGN_TOP_LEFT);
|
|
lv_obj_add_flag(run_button, LV_OBJ_FLAG_CHECKABLE);
|
|
lv_obj_add_event_cb(run_button, run_handler, LV_EVENT_ALL, NULL);
|
|
|
|
// add the start label
|
|
lv_obj_t* run_label = lv_label_create(run_button);
|
|
lv_label_set_text(run_label, LV_SYMBOL_PLAY);
|
|
lv_obj_center(run_label);
|
|
if(run_status){
|
|
lv_obj_add_state(run_button, LV_STATE_CHECKED);
|
|
lv_label_set_text(run_label, LV_SYMBOL_PAUSE);
|
|
volume_readout_update_timer = lv_timer_create(volume_readout_update, 100, NULL);
|
|
}
|
|
|
|
// add workspace switcher
|
|
lv_obj_t* ws_left = lv_btn_create(top_menu);
|
|
lv_obj_set_flex_grow(ws_left, 1);
|
|
lv_obj_add_event_cb(ws_left, ws_left_handler, LV_EVENT_CLICKED, NULL);
|
|
|
|
lv_obj_t* ws_left_label = lv_label_create(ws_left);
|
|
lv_label_set_text(ws_left_label, LV_SYMBOL_LEFT);
|
|
lv_obj_center(ws_left_label);
|
|
|
|
lv_obj_t* ws_label_cont = lv_obj_create(top_menu);
|
|
lv_obj_set_flex_grow(ws_label_cont, 1);
|
|
lv_obj_set_height(ws_label_cont, lv_pct(100));
|
|
lv_obj_set_style_pad_all(ws_label_cont, 0, 0);
|
|
lv_obj_center(ws_label_cont);
|
|
|
|
ws_label = lv_label_create(ws_label_cont);
|
|
lv_label_set_text_fmt(ws_label, "%d", workspace_index);
|
|
lv_obj_set_style_text_align(ws_label, LV_TEXT_ALIGN_CENTER, 0);
|
|
lv_obj_center(ws_label);
|
|
|
|
lv_obj_t* ws_right = lv_btn_create(top_menu);
|
|
lv_obj_set_flex_grow(ws_right, 1);
|
|
lv_obj_add_event_cb(ws_right, ws_right_handler, LV_EVENT_CLICKED, NULL);
|
|
|
|
lv_obj_t* ws_right_label = lv_label_create(ws_right);
|
|
lv_label_set_text(ws_right_label, LV_SYMBOL_RIGHT);
|
|
lv_obj_center(ws_right_label);
|
|
|
|
// grid layout for the 4 differents units
|
|
lv_obj_t* units_grid = lv_obj_create(scr);
|
|
lv_obj_align_to(units_grid, top_menu, LV_ALIGN_OUT_BOTTOM_LEFT, 0, 0);
|
|
lv_obj_set_size(units_grid, lv_pct(100), lv_pct(80));
|
|
lv_obj_set_style_pad_all(units_grid, 5, 0);
|
|
lv_obj_set_layout(units_grid, LV_LAYOUT_GRID);
|
|
|
|
lv_obj_set_grid_dsc_array(units_grid, units_col_dsc, units_row_dsc);
|
|
|
|
for(int i = 0; i < pse_unit_num; i++){
|
|
lv_obj_t* obj = PSE_unit_widget(units_grid, &pse_units[i]);
|
|
lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_CENTER, i, 1, LV_GRID_ALIGN_CENTER, 0, 1);
|
|
}
|
|
|
|
// fade in the new screen
|
|
lv_scr_load_anim(scr, LV_SCR_LOAD_ANIM_FADE_ON, 0, 0, delete);
|
|
}
|