ALDL Dashboard for RPi systems
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

227 lines
6.1 KiB

/*
* 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;
}