228 lines
6.1 KiB
C
228 lines
6.1 KiB
C
/*
|
|
* ALDL Dashboard, Dashboard rendering code
|
|
*
|
|
* (c) 2019 Solomon Peachy <pizza@shaftnet.org>
|
|
*
|
|
* The latest version of this program can be found at:
|
|
*
|
|
* http://git.shaftnet.org/cgit/selphy_print.git
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the Free
|
|
* Software Foundation; either version 3 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
* for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* [http://www.gnu.org/licenses/gpl-3.0.html]
|
|
*
|
|
* SPDX-License-Identifier: GPL-3.0+
|
|
*
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
|
|
#include "aldl.h"
|
|
|
|
#include <SDL2/SDL.h>
|
|
#include <SDL2/SDL_ttf.h>
|
|
|
|
/* Dimensions and basic stuff */
|
|
|
|
#define SCREEN_W 320
|
|
#define SCREEN_H 240
|
|
#define FONT "/usr/share/fonts/levien-inconsolata/Inconsolata-Regular.ttf"
|
|
#define FONT_SZ 14
|
|
#define VIDEODRIVER NULL
|
|
#define WINDOW_NAME "ALDL Dashboard"
|
|
static const SDL_Color textcolor = {255,255,255};
|
|
static const SDL_Color errorcolor = {255,255,255};
|
|
|
|
/* State */
|
|
static SDL_bool videoinit = SDL_FALSE;
|
|
static SDL_Window *window = NULL;
|
|
static TTF_Font *font = NULL;
|
|
static SDL_Renderer *renderer = NULL;
|
|
|
|
/* Cleanup */
|
|
void OnQuit(void) {
|
|
if (videoinit) {
|
|
SDL_VideoQuit();
|
|
}
|
|
SDL_Quit();
|
|
}
|
|
|
|
/* Initialize */
|
|
int init_dash(void) {
|
|
if (SDL_Init(0)) {
|
|
printf("fail to init SDL\n");
|
|
return 1;
|
|
}
|
|
|
|
/* Clean up on exit */
|
|
atexit(OnQuit);
|
|
|
|
if (SDL_VideoInit(VIDEODRIVER)) {
|
|
printf("fail to init SDL_Video\n");
|
|
return 2;
|
|
}
|
|
videoinit = SDL_TRUE;
|
|
|
|
/* Init font subsystem */
|
|
if (TTF_Init()) {
|
|
printf("fail to init TTF\n");
|
|
return 3;
|
|
}
|
|
|
|
/* Load up a font */
|
|
font = TTF_OpenFont(FONT, FONT_SZ);
|
|
if (!font) {
|
|
printf("Can't open font '%s'\n", FONT);
|
|
return 4;
|
|
}
|
|
|
|
/* Set up display */
|
|
window = SDL_CreateWindow(WINDOW_NAME,
|
|
SDL_WINDOWPOS_UNDEFINED,
|
|
SDL_WINDOWPOS_UNDEFINED,
|
|
SCREEN_W, SCREEN_H, 0);
|
|
if (!window) {
|
|
printf("fail to create window\n");
|
|
return 5;
|
|
}
|
|
|
|
/* Set up renderer */
|
|
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_SOFTWARE);
|
|
if (!renderer) {
|
|
printf("Fail to create renderer");
|
|
return 7;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
#define RENDER_TEXT_NOARG(__i, __x, __y, __color, __format) \
|
|
do { \
|
|
surf = TTF_RenderText_Solid(font, __format, __color); \
|
|
if (surf) { \
|
|
drawn_tex[__i] = SDL_CreateTextureFromSurface(renderer, surf); \
|
|
SDL_FreeSurface(surf); \
|
|
} \
|
|
DestR.x = __x; \
|
|
DestR.y = __y; \
|
|
SDL_QueryTexture(drawn_tex[__i], NULL, NULL, &DestR.w, &DestR.h); \
|
|
SDL_RenderCopy(renderer, drawn_tex[__i], NULL, &DestR); \
|
|
__i++; \
|
|
} while (0)
|
|
#define RENDER_TEXT_1ARG(__i, __x, __y, __color, __format, __arg) \
|
|
do { \
|
|
snprintf(txtbuf, sizeof(txtbuf), __format, __arg); \
|
|
surf = TTF_RenderText_Solid(font, txtbuf, __color); \
|
|
if (surf) { \
|
|
drawn_tex[__i] = SDL_CreateTextureFromSurface(renderer, surf); \
|
|
SDL_FreeSurface(surf); \
|
|
} \
|
|
DestR.x = __x; \
|
|
DestR.y = __y; \
|
|
SDL_QueryTexture(drawn_tex[__i], NULL, NULL, &DestR.w, &DestR.h); \
|
|
SDL_RenderCopy(renderer, drawn_tex[__i], NULL, &DestR); \
|
|
__i++; \
|
|
} while (0)
|
|
|
|
#define NUM_TEXTS_MAX 64
|
|
int render_dash(void) {
|
|
int i = 0;
|
|
SDL_Surface *surf;
|
|
SDL_Texture *drawn_tex[NUM_TEXTS_MAX] = { NULL };
|
|
SDL_Rect DestR;
|
|
char txtbuf[64];
|
|
|
|
if (SDL_QuitRequested())
|
|
return 0;
|
|
|
|
/* Clear with black */
|
|
SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE);
|
|
SDL_RenderClear(renderer);
|
|
|
|
/* Set draw color */
|
|
if (decoded.mil)
|
|
SDL_SetRenderDrawColor(renderer, 255, 0, 0, SDL_ALPHA_OPAQUE);
|
|
else
|
|
SDL_SetRenderDrawColor(renderer, 255, 255, 255, SDL_ALPHA_OPAQUE);
|
|
|
|
/* Draw Border, 1px */
|
|
SDL_RenderDrawLine(renderer, 0, 0, SCREEN_W -1, 0);
|
|
SDL_RenderDrawLine(renderer, 0, 0, 0, SCREEN_H -1);
|
|
SDL_RenderDrawLine(renderer, SCREEN_W -1, 0, SCREEN_W -1, SCREEN_H);
|
|
SDL_RenderDrawLine(renderer, 0, SCREEN_H -1, SCREEN_W -1, SCREEN_H -1);
|
|
|
|
/* Draw fixed text */
|
|
RENDER_TEXT_NOARG(i, 100, 10, textcolor, "ALDL Dashboard");
|
|
|
|
if (!gotsync) {
|
|
/* No sync yet.. */
|
|
RENDER_TEXT_NOARG(i, 100, 100, errorcolor, "NO SYNC\n");
|
|
goto done;
|
|
}
|
|
|
|
RENDER_TEXT_1ARG(i, 10, 30, textcolor, "PROM %04x", decoded.prom_id);
|
|
/* Draw variable text */
|
|
RENDER_TEXT_1ARG(i, 10, 50, textcolor, "%03u MPH", decoded.mph);
|
|
RENDER_TEXT_1ARG(i, 10, 70, textcolor, "%04d RPM", decoded.rpm);
|
|
RENDER_TEXT_1ARG(i, 10, 90, textcolor, "%03.1f C", decoded.coolant_temp_c);
|
|
RENDER_TEXT_1ARG(i, 10, 110, textcolor, "%03u%% TP", decoded.tp);
|
|
|
|
if (decoded.idling) {
|
|
RENDER_TEXT_1ARG(i, 200, 30, textcolor, "IDLE @ %04d", decoded.idle_tgt);
|
|
if (decoded.closed_loop_idle)
|
|
RENDER_TEXT_NOARG(i, 200, 50, textcolor, "CLOSED LOOP");
|
|
else
|
|
RENDER_TEXT_NOARG(i, 200, 50, textcolor, "OPEN LOOP");
|
|
} else {
|
|
if (decoded.closed_loop)
|
|
RENDER_TEXT_NOARG(i, 200, 50, textcolor, "CLOSED LOOP");
|
|
else
|
|
RENDER_TEXT_NOARG(i, 200, 50, textcolor, "OPEN LOOP");
|
|
}
|
|
if (decoded.ac_request)
|
|
RENDER_TEXT_NOARG(i, 200, 70, textcolor, "AC REQ");
|
|
|
|
if (decoded.shift_req)
|
|
RENDER_TEXT_NOARG(i, 200, 90, textcolor, "SHIFT REQ");
|
|
else if (decoded.top_gear)
|
|
RENDER_TEXT_NOARG(i, 200, 90, textcolor, "TOP GEAR");
|
|
else if (decoded.neutral)
|
|
RENDER_TEXT_NOARG(i, 200, 90, textcolor, "NEUTRAL");
|
|
|
|
RENDER_TEXT_1ARG(i, 200, 110, textcolor, "BAT %02.01f v", decoded.battery_v);
|
|
|
|
RENDER_TEXT_1ARG(i, 310, 225, textcolor, "%c", decoded.heartbeat ? '^' : '*');
|
|
|
|
if (decoded.mil) {
|
|
/* Something wrong! */
|
|
RENDER_TEXT_1ARG(i, 10, 200, errorcolor, "CHECK ENGINE %06x\n", decoded.mil);
|
|
}
|
|
|
|
done:
|
|
|
|
/* Commit! */
|
|
SDL_RenderPresent(renderer);
|
|
|
|
/* Clean up afterwards */
|
|
for (i = 0; i < NUM_TEXTS_MAX ; i++) {
|
|
if (drawn_tex[i])
|
|
SDL_DestroyTexture(drawn_tex[i]);
|
|
}
|
|
|
|
return 1;
|
|
}
|