acid-drop

- Hacking the planet from a LilyGo T-Deck using custom firmware
git clone git://git.acid.vegas/acid-drop.git
Log | Files | Refs | Archive | README | LICENSE

lv_example_chart_8.c (5516B)

      1 #include "../../lv_examples.h"
      2 #if LV_USE_CHART && LV_DRAW_COMPLEX && LV_BUILD_EXAMPLES
      3 
      4 /*  A struct is used to keep track of the series list because later we need to draw to the series in the reverse order to which they were initialised. */
      5 typedef struct {
      6     lv_obj_t * obj;
      7     lv_chart_series_t * series_list[3];
      8 } stacked_area_chart_t;
      9 
     10 static stacked_area_chart_t stacked_area_chart;
     11 
     12 /**
     13  * Callback which draws the blocks of colour under the lines
     14  **/
     15 static void draw_event_cb(lv_event_t * e)
     16 {
     17     lv_obj_t * obj = lv_event_get_target(e);
     18 
     19     /*Add the faded area before the lines are drawn*/
     20     lv_obj_draw_part_dsc_t * dsc = lv_event_get_draw_part_dsc(e);
     21     if(dsc->part == LV_PART_ITEMS) {
     22         if(!dsc->p1 || !dsc->p2)
     23             return;
     24 
     25         /*Add a line mask that keeps the area below the line*/
     26         lv_draw_mask_line_param_t line_mask_param;
     27         lv_draw_mask_line_points_init(&line_mask_param, dsc->p1->x, dsc->p1->y, dsc->p2->x, dsc->p2->y,
     28                                       LV_DRAW_MASK_LINE_SIDE_BOTTOM);
     29         int16_t line_mask_id = lv_draw_mask_add(&line_mask_param, NULL);
     30 
     31         /*Draw a rectangle that will be affected by the mask*/
     32         lv_draw_rect_dsc_t draw_rect_dsc;
     33         lv_draw_rect_dsc_init(&draw_rect_dsc);
     34         draw_rect_dsc.bg_opa = LV_OPA_COVER;
     35         draw_rect_dsc.bg_color = dsc->line_dsc->color;
     36 
     37         lv_area_t a;
     38         a.x1 = dsc->p1->x;
     39         a.x2 = dsc->p2->x;
     40         a.y1 = LV_MIN(dsc->p1->y, dsc->p2->y);
     41         a.y2 = obj->coords.y2 -
     42                13; /* -13 cuts off where the rectangle draws over the chart margin. Without this an area of 0 doesn't look like 0 */
     43         lv_draw_rect(dsc->draw_ctx, &draw_rect_dsc, &a);
     44 
     45         /*Remove the mask*/
     46         lv_draw_mask_free_param(&line_mask_param);
     47         lv_draw_mask_remove_id(line_mask_id);
     48     }
     49 }
     50 
     51 /**
     52  * Helper function to round a fixed point number
     53  **/
     54 static int32_t round_fixed_point(int32_t n, int8_t shift)
     55 {
     56     /* Create a bitmask to isolates the decimal part of the fixed point number */
     57     int32_t mask = 1;
     58     for(int32_t bit_pos = 0; bit_pos < shift; bit_pos++) {
     59         mask = (mask << 1) + 1;
     60     }
     61 
     62     int32_t decimal_part = n & mask;
     63 
     64     /* Get 0.5 as fixed point */
     65     int32_t rounding_boundary = 1 << (shift - 1);
     66 
     67     /* Return either the integer part of n or the integer part + 1 */
     68     return (decimal_part < rounding_boundary) ? (n & ~mask) : ((n >> shift) + 1) << shift;
     69 }
     70 
     71 /**
     72  * Stacked area chart
     73  */
     74 void lv_example_chart_8(void)
     75 {
     76     /*Create a stacked_area_chart.obj*/
     77     stacked_area_chart.obj = lv_chart_create(lv_scr_act());
     78     lv_obj_set_size(stacked_area_chart.obj, 200, 150);
     79     lv_obj_center(stacked_area_chart.obj);
     80     lv_chart_set_type(stacked_area_chart.obj, LV_CHART_TYPE_LINE);
     81     lv_chart_set_div_line_count(stacked_area_chart.obj, 5, 7);
     82     lv_obj_add_event_cb(stacked_area_chart.obj, draw_event_cb, LV_EVENT_DRAW_PART_BEGIN, NULL);
     83 
     84     /* Set range to 0 to 100 for percentages. Draw ticks */
     85     lv_chart_set_range(stacked_area_chart.obj, LV_CHART_AXIS_PRIMARY_Y, 0, 100);
     86     lv_chart_set_axis_tick(stacked_area_chart.obj, LV_CHART_AXIS_PRIMARY_Y, 3, 0, 5, 1, true, 30);
     87 
     88     /*Set point size to 0 so the lines are smooth */
     89     lv_obj_set_style_size(stacked_area_chart.obj, 0, LV_PART_INDICATOR);
     90 
     91     /*Add some data series*/
     92     stacked_area_chart.series_list[0] = lv_chart_add_series(stacked_area_chart.obj, lv_palette_main(LV_PALETTE_RED),
     93                                                             LV_CHART_AXIS_PRIMARY_Y);
     94     stacked_area_chart.series_list[1] = lv_chart_add_series(stacked_area_chart.obj, lv_palette_main(LV_PALETTE_BLUE),
     95                                                             LV_CHART_AXIS_PRIMARY_Y);
     96     stacked_area_chart.series_list[2] = lv_chart_add_series(stacked_area_chart.obj, lv_palette_main(LV_PALETTE_GREEN),
     97                                                             LV_CHART_AXIS_PRIMARY_Y);
     98 
     99     for(int point = 0; point < 10; point++) {
    100         /* Make some random data */
    101         uint32_t vals[3] = {lv_rand(10, 20), lv_rand(20, 30), lv_rand(20, 30)};
    102 
    103         int8_t fixed_point_shift = 5;
    104         uint32_t total = vals[0] + vals[1] + vals[2];
    105         uint32_t draw_heights[3];
    106         uint32_t int_sum = 0;
    107         uint32_t decimal_sum = 0;
    108 
    109         /* Fixed point cascade rounding ensures percentages add to 100 */
    110         for(int32_t series_index = 0; series_index < 3; series_index++) {
    111             decimal_sum += (((vals[series_index] * 100) << fixed_point_shift) / total);
    112             int_sum += (vals[series_index] * 100) / total;
    113 
    114             int32_t modifier = (round_fixed_point(decimal_sum, fixed_point_shift) >> fixed_point_shift) - int_sum;
    115 
    116             /*  The draw heights are equal to the percentage of the total each value is + the cumulative sum of the previous percentages.
    117                 The accumulation is how the values get "stacked" */
    118             draw_heights[series_index] = int_sum + modifier;
    119 
    120             /*  Draw to the series in the reverse order to which they were initialised.
    121                 Without this the higher values will draw on top of the lower ones.
    122                 This is because the Z-height of a series matches the order it was initialised */
    123             lv_chart_set_next_value(stacked_area_chart.obj, stacked_area_chart.series_list[3 - series_index - 1],
    124                                     draw_heights[series_index]);
    125         }
    126     }
    127 
    128     lv_chart_refresh(stacked_area_chart.obj);
    129 }
    130 
    131 #endif