hexagram/src/cluster.c

281 lines
8.7 KiB
C
Raw Normal View History

2019-06-09 15:46:41 -05:00
#include <stdlib.h>
#include <string.h>
2019-06-09 15:46:41 -05:00
#include <hexagram/cluster.h>
2024-01-11 17:39:52 -05:00
#define CLUSTER_WIDTH 1280
#define CLUSTER_HEIGHT 480
#define SHIFT_INDICATOR_X 392
#define SHIFT_INDICATOR_Y 24
#define SECTION_HEIGHT_TOP 64
#define SECTION_HEIGHT_BOTTOM 52
2024-01-17 17:40:23 -05:00
#define SPEEDO_MAX 322.0
2024-01-11 17:39:52 -05:00
#define PATTERN_WIDTH 100
#define PATTERN_HEIGHT 87
static const double hexagon_pattern_color[3] = { 0.3, 0.1, 0.3 };
static const double hexagon_pattern_matrix[6] = {
0.21213203, 0.21213203, 0.21213203, -0.21213203, 1, 1
};
static const double hexagon_pattern_scale[2] = { 3, 3 };
static const char *hexagon_pattern =
"M 23.246093 0,"
" 0 13.382812,"
"V 44.689453"
"L 0.0839844 44.640625,"
" 24.033203 58.505859,"
" 24.001953 86.332031,"
" 22.841796 87"
"h 4.478516"
"L 26.068359 86.275391,"
" 26.099609 58.449219,"
" 50.083984 44.640625,"
" 74.033203 58.505859,"
" 74.001953 86.332031,"
" 72.841796 87"
"h 4.478516"
"L 76.068359 86.275391,"
" 76.099609 58.449219,"
" 100 44.689453,"
"V 13.365234"
"L 76.919921 0"
"H 73.246093"
"L 50.015625 13.373047,"
" 26.919921 0"
"Z"
"M 25.083984 1.25,"
" 49.033203 15.115234,"
" 49.001953, 42.941406,"
" 25.017578 56.75,"
" 1.0019531 42.845703,"
"l 0.033203 -27.75"
"z"
"m 50 0,"
" 24.017576 13.904297,"
" -0.0352 27.75"
"L 75.017578 56.75,"
" 51.068359 42.884766,"
" 51.099609 15.058594"
"Z";
2019-06-09 15:46:41 -05:00
2019-06-28 18:12:29 -05:00
int hexagram_cluster_filter_can_if(hexagram_can_if *can_if) {
2024-01-09 22:15:59 -05:00
struct can_filter filters[4] = {
2019-06-28 18:12:29 -05:00
{ .can_id = 0x280, .can_mask = 0x3f0 },
{ .can_id = 0x320, .can_mask = 0x320 },
2024-01-09 22:15:59 -05:00
{ .can_id = 0x540, .can_mask = 0x540 },
2019-06-28 18:12:29 -05:00
{ .can_id = 0x5a0, .can_mask = 0x5a0 }
};
return setsockopt(hexagram_can_if_fd(can_if),
SOL_CAN_RAW,
CAN_RAW_FILTER,
&filters,
sizeof(filters));
}
2024-01-11 17:39:52 -05:00
int hexagram_cluster_init(hexagram_cluster *cluster,
double rpm_min,
double rpm_redline,
double rpm_max) {
cluster->width = CLUSTER_WIDTH;
cluster->height = CLUSTER_HEIGHT;
if (hexagram_pattern_init(&cluster->pattern,
PATTERN_WIDTH,
PATTERN_HEIGHT,
hexagon_pattern_color,
HEXAGRAM_PATTERN_STROKE,
hexagon_pattern,
strlen(hexagon_pattern)) < 0) {
goto error_pattern_init;
}
2024-01-11 17:39:52 -05:00
if (hexagram_speedo_init(&cluster->speedo,
CLUSTER_HEIGHT / 2,
CLUSTER_HEIGHT / 2,
CLUSTER_HEIGHT / 2,
2024-01-17 17:40:23 -05:00
SPEEDO_MAX) < 0) {
2024-01-11 17:39:52 -05:00
goto error_speedo_init;
}
2024-01-11 17:39:52 -05:00
if (hexagram_fuel_init(&cluster->fuel,
CLUSTER_HEIGHT / 2,
CLUSTER_HEIGHT / 2,
CLUSTER_HEIGHT / 2) < 0) {
goto error_fuel_init;
}
2024-01-11 17:39:52 -05:00
if (hexagram_tacho_init(&cluster->tacho,
CLUSTER_WIDTH - CLUSTER_HEIGHT / 2,
CLUSTER_HEIGHT / 2,
CLUSTER_HEIGHT / 2,
rpm_redline,
rpm_max) < 0) {
goto error_tacho_init;
}
2024-01-11 17:39:52 -05:00
if (hexagram_thermo_init(&cluster->thermo,
CLUSTER_WIDTH - CLUSTER_HEIGHT / 2,
CLUSTER_HEIGHT / 2,
CLUSTER_HEIGHT / 2) < 0) {
goto error_thermo_init;
}
2024-01-11 17:39:52 -05:00
if (hexagram_odo_init(&cluster->odo,
0.8 * CLUSTER_HEIGHT,
CLUSTER_HEIGHT - (SECTION_HEIGHT_BOTTOM - HEXAGRAM_TEXT_FONT_SIZE) / 2,
2024-01-11 17:39:52 -05:00
HEXAGRAM_TEXT_LEFT,
HEXAGRAM_ODO_MILES) < 0) {
goto error_odo_init;
}
2024-01-11 17:39:52 -05:00
if (hexagram_clock_init(&cluster->clock,
CLUSTER_WIDTH / 2,
CLUSTER_HEIGHT - (SECTION_HEIGHT_BOTTOM - HEXAGRAM_TEXT_FONT_SIZE) / 2,
2024-01-11 17:39:52 -05:00
HEXAGRAM_TEXT_MIDDLE,
HEXAGRAM_CLOCK_24H) < 0) {
goto error_clock_init;
}
2024-01-11 17:39:52 -05:00
if (hexagram_temp_init(&cluster->temp,
CLUSTER_WIDTH - 0.8 * CLUSTER_HEIGHT,
CLUSTER_HEIGHT - (SECTION_HEIGHT_BOTTOM - HEXAGRAM_TEXT_FONT_SIZE) / 2,
2024-01-11 17:39:52 -05:00
HEXAGRAM_TEXT_RIGHT,
HEXAGRAM_TEMP_CELSIUS) < 0) {
goto error_temp_init;
}
if (hexagram_tacho_shift_indicator_init(&cluster->shift_indicator,
SHIFT_INDICATOR_X,
SHIFT_INDICATOR_Y,
rpm_min,
rpm_redline) < 0) {
goto error_tacho_shift_indicator_init;
}
2024-01-11 17:39:52 -05:00
if (hexagram_status_icon_box_init(&cluster->status,
CLUSTER_WIDTH / 2 - HEXAGRAM_STATUS_ICON_WIDTH * 3.5,
CLUSTER_HEIGHT - SECTION_HEIGHT_BOTTOM - 16 - HEXAGRAM_STATUS_ICON_HEIGHT * 3,
HEXAGRAM_STATUS_ICON_WIDTH * 7,
HEXAGRAM_STATUS_ICON_HEIGHT * 3) < 0) {
goto error_status_icon_box_init;
}
cluster->gauges[0] = &cluster->speedo.dial.gauge;
cluster->gauges[1] = &cluster->fuel.dial.gauge;
cluster->gauges[2] = &cluster->tacho.dial.gauge;
cluster->gauges[3] = &cluster->thermo.dial.gauge;
cluster->gauges[4] = &cluster->odo.text.gauge;
cluster->gauges[5] = &cluster->temp.text.gauge;
cluster->gauges[6] = &cluster->clock.text.gauge;
cluster->gauges[7] = &cluster->status.gauge;
cluster->gauges[8] = &cluster->shift_indicator.gauge;
return 0;
2024-01-11 17:39:52 -05:00
error_status_icon_box_init:
error_tacho_shift_indicator_init:
hexagram_temp_cleanup(&cluster->temp);
error_temp_init:
error_clock_init:
error_odo_init:
error_thermo_init:
error_tacho_init:
error_fuel_init:
error_speedo_init:
hexagram_pattern_cleanup(&cluster->pattern);
error_pattern_init:
return -1;
}
2024-01-11 17:39:52 -05:00
void hexagram_cluster_cleanup(hexagram_cluster *cluster) {
hexagram_status_icon_box_cleanup(&cluster->status);
hexagram_temp_cleanup(&cluster->temp);
hexagram_pattern_cleanup(&cluster->pattern);
}
2024-01-11 17:39:52 -05:00
hexagram_cluster *hexagram_cluster_new(double rpm_min,
double rpm_redline,
double rpm_max) {
hexagram_cluster *cluster;
2019-06-09 15:46:41 -05:00
2024-01-11 17:39:52 -05:00
if ((cluster = malloc(sizeof(*cluster))) == NULL) {
goto error_malloc_cluster;
}
hexagram_cluster_init(cluster, rpm_min, rpm_redline, rpm_max);
2024-01-11 17:39:52 -05:00
return cluster;
2024-01-11 17:39:52 -05:00
error_malloc_cluster:
return NULL;
}
void hexagram_cluster_destroy(hexagram_cluster *cluster) {
hexagram_cluster_cleanup(cluster);
free(cluster);
}
void hexagram_cluster_draw_bg(hexagram_cluster *cluster, cairo_t *cr) {
int i;
cairo_set_source_rgb(cr, 0.1, 0.1, 0.1);
cairo_rectangle(cr, 0, 0, CLUSTER_WIDTH, CLUSTER_HEIGHT);
cairo_fill(cr);
cairo_rectangle(cr, 0, 0, CLUSTER_WIDTH, CLUSTER_HEIGHT);
hexagram_pattern_fill(&cluster->pattern,
cr,
hexagon_pattern_matrix,
hexagon_pattern_scale);
/* Top dark area */
cairo_set_source_rgba(cr, 0, 0, 0, 0.5);
cairo_rectangle(cr, 0, 0, CLUSTER_WIDTH, SECTION_HEIGHT_TOP);
cairo_fill(cr);
cairo_set_source_rgba(cr, 1, 1, 1, 0.25);
cairo_move_to(cr, 0, SECTION_HEIGHT_TOP);
cairo_line_to(cr, CLUSTER_WIDTH, SECTION_HEIGHT_TOP);
cairo_stroke(cr);
/* Bottom dark area */
cairo_set_source_rgba(cr, 0, 0, 0, 0.5);
cairo_rectangle(cr,
0,
CLUSTER_HEIGHT - SECTION_HEIGHT_BOTTOM,
CLUSTER_WIDTH,
SECTION_HEIGHT_BOTTOM);
cairo_fill(cr);
cairo_set_source_rgba(cr, 1, 1, 1, 0.25);
cairo_move_to(cr, 0, CLUSTER_HEIGHT - SECTION_HEIGHT_BOTTOM);
cairo_line_to(cr, CLUSTER_WIDTH, CLUSTER_HEIGHT - SECTION_HEIGHT_BOTTOM);
cairo_stroke(cr);
for (i=0; i<HEXAGRAM_CLUSTER_GAUGE_COUNT; i++) {
if (cluster->gauges[i]->draw_bg) {
cluster->gauges[i]->draw_bg(cluster->gauges[i], cr);
}
}
}
void hexagram_cluster_draw_fg(hexagram_cluster *cluster, cairo_t *cr) {
int i;
for (i=0; i<HEXAGRAM_CLUSTER_GAUGE_COUNT; i++) {
if (cluster->gauges[i]->draw_fg) {
cluster->gauges[i]->draw_fg(cluster->gauges[i], cr);
}
}
}