Initial commit
IMU and bubble level working
This commit is contained in:
132
main/bubble.c
Normal file
132
main/bubble.c
Normal file
@@ -0,0 +1,132 @@
|
||||
#include "bubble.h"
|
||||
|
||||
typedef struct {
|
||||
float min_val;
|
||||
float max_val;
|
||||
float cur_val;
|
||||
} bubble_level_dsc_t;
|
||||
|
||||
|
||||
static void bubble_draw_cb(lv_event_t * e)
|
||||
{
|
||||
lvgl_port_lock(0);
|
||||
|
||||
lv_obj_t * obj = lv_event_get_target(e);
|
||||
bubble_level_dsc_t * d = lv_obj_get_user_data(obj);
|
||||
if(!d) return;
|
||||
|
||||
// 1) Get the LVGL draw layer (clipping is automatic)
|
||||
lv_layer_t * layer = lv_event_get_layer(e);
|
||||
|
||||
// 2) Figure out the object's inner rectangle
|
||||
lv_area_t coords;
|
||||
lv_obj_get_coords(obj, &coords);
|
||||
lv_area_t inner = {
|
||||
.x1 = coords.x1 + 2, .y1 = coords.y1 + 2,
|
||||
.x2 = coords.x2 - 2, .y2 = coords.y2 - 2
|
||||
};
|
||||
|
||||
// 3) Draw the border
|
||||
lv_draw_rect_dsc_t rect_dsc;
|
||||
lv_draw_rect_dsc_init(&rect_dsc);
|
||||
rect_dsc.border_color = lv_color_hex(0xAAAAAA);
|
||||
rect_dsc.border_width = 2;
|
||||
rect_dsc.bg_opa = LV_OPA_TRANSP;
|
||||
lv_draw_rect(layer, &rect_dsc, &inner);
|
||||
|
||||
// 4) Draw guide lines at the center
|
||||
lv_coord_t mid_x = (inner.x1 + inner.x2) / 2;
|
||||
lv_coord_t mid_y = (inner.y1 + inner.y2) / 2;
|
||||
|
||||
lv_draw_line_dsc_t line_dsc;
|
||||
lv_draw_line_dsc_init(&line_dsc);
|
||||
line_dsc.color = lv_color_hex(0x444444);
|
||||
line_dsc.width = 1;
|
||||
|
||||
// Set up points and convert to 'precise' type
|
||||
lv_point_t tl = { inner.x1 + 10, mid_y };
|
||||
lv_point_t tr = { inner.x2 - 10, mid_y };
|
||||
line_dsc.p1 = lv_point_to_precise(&tl);
|
||||
line_dsc.p2 = lv_point_to_precise(&tr);
|
||||
lv_draw_line(layer, &line_dsc);
|
||||
|
||||
lv_point_t tt = { mid_x, inner.y1 + 10 };
|
||||
lv_point_t tb = { mid_x, inner.y2 - 10 };
|
||||
line_dsc.p1 = lv_point_to_precise(&tt);
|
||||
line_dsc.p2 = lv_point_to_precise(&tb);
|
||||
lv_draw_line(layer, &line_dsc);
|
||||
|
||||
// 5) Compute bubble position (normalized between min_val → max_val)
|
||||
float norm = (d->cur_val - d->min_val) / (d->max_val - d->min_val);
|
||||
norm = norm < 0 ? 0 : (norm > 1 ? 1 : norm);
|
||||
|
||||
const lv_coord_t bubble_d = 16;
|
||||
lv_coord_t avail_w = (inner.x2 - inner.x1 + 1) - bubble_d;
|
||||
lv_coord_t bx = inner.x1 + (lv_coord_t)(norm * avail_w);
|
||||
lv_coord_t by = mid_y - (bubble_d / 2);
|
||||
|
||||
// 6) Draw the bubble as a filled circle (rounded rect)
|
||||
lv_draw_rect_dsc_t circ_dsc;
|
||||
lv_draw_rect_dsc_init(&circ_dsc);
|
||||
circ_dsc.bg_color = lv_color_hex(0x00CC00);
|
||||
circ_dsc.bg_opa = LV_OPA_COVER;
|
||||
circ_dsc.radius = bubble_d / 2;
|
||||
circ_dsc.border_opa = LV_OPA_TRANSP;
|
||||
|
||||
lv_area_t circ_area = {
|
||||
.x1 = bx,
|
||||
.y1 = by,
|
||||
.x2 = bx + bubble_d - 1,
|
||||
.y2 = by + bubble_d - 1
|
||||
};
|
||||
lv_draw_rect(layer, &circ_dsc, &circ_area);
|
||||
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
|
||||
lv_obj_t * bubble_create(lv_obj_t * parent,
|
||||
lv_coord_t width, lv_coord_t height,
|
||||
float min_val, float max_val, float initial)
|
||||
{
|
||||
// 1) Create a container object (no special style)
|
||||
lv_obj_t * obj = lv_obj_create(parent);
|
||||
lv_obj_set_size(obj, width, height);
|
||||
|
||||
// (Optional) center it or let the caller position it:
|
||||
// lv_obj_center(obj);
|
||||
|
||||
// 2) Allocate or attach our descriptor
|
||||
// In LVGL v9 you can use USER_DATA: need to enable LV_USE_USER_DATA = 1
|
||||
bubble_level_dsc_t * dsc = lv_malloc(sizeof(bubble_level_dsc_t));
|
||||
if(!dsc) return NULL; /* handle out-of-memory */
|
||||
dsc->min_val = min_val;
|
||||
dsc->max_val = max_val;
|
||||
dsc->cur_val = initial;
|
||||
lv_obj_set_user_data(obj, dsc);
|
||||
|
||||
// 3) Register our draw callback
|
||||
lv_obj_add_event_cb(obj, bubble_draw_cb, LV_EVENT_DRAW_MAIN, NULL);
|
||||
|
||||
// 4) Make sure the object does NOT get a default background fill
|
||||
lv_obj_set_style_bg_opa(obj, LV_OPA_TRANSP, 0);
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
void bubble_setValue(lv_obj_t * bubble, float v)
|
||||
{
|
||||
lvgl_port_lock(0);
|
||||
// 1) Retrieve the descriptor
|
||||
bubble_level_dsc_t * d = lv_obj_get_user_data(bubble);
|
||||
if(!d) return;
|
||||
|
||||
// 2) Update the stored value
|
||||
d->cur_val = v;
|
||||
|
||||
// 3) Tell LVGL that object must be re‐drawn
|
||||
lv_obj_invalidate(bubble);
|
||||
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
Reference in New Issue
Block a user