display.c 4.68 KB
Newer Older
1
#include "display.h"
Gerd's avatar
Gerd committed
2
3
#include "Fonts/fonts.h"
#include "FreeRTOS.h"
4
#include "LCD_Driver.h"
5
6
7
8
9
10
#include "epicardium.h"
#include "gfx.h"
#include "gpio.h"
#include "task.h"
#include "tmr.h"
#include "tmr_utils.h"
Gerd's avatar
Gerd committed
11
12
13

static TaskHandle_t lock = NULL;

14
static struct gfx_region *current_fb = &application_screen;
Stefan Haun's avatar
Stefan Haun committed
15
static bool fullscreen               = false;
16

Gerd's avatar
Gerd committed
17
18
19
20
21
22
23
24
25
26
27
static int check_lock()
{
	TaskHandle_t task = xTaskGetCurrentTaskHandle();
	if (task != lock) {
		return -EBUSY;
	} else {
		return 0;
	}
}

int epic_disp_print(
28
29
	int16_t posx,
	int16_t posy,
Gerd's avatar
Gerd committed
30
31
32
	const char *pString,
	uint16_t fg,
	uint16_t bg
33
34
35
36
37
38
39
40
41
42
43
44
) {
	return epic_disp_print_adv(DISP_FONT20, posx, posy, pString, fg, bg);
}

static const sFONT *font_map[] = {
	[DISP_FONT8] = &Font8,   [DISP_FONT12] = &Font12,
	[DISP_FONT16] = &Font16, [DISP_FONT20] = &Font20,
	[DISP_FONT24] = &Font24,
};

int epic_disp_print_adv(
	uint8_t font,
45
46
	int16_t posx,
	int16_t posy,
47
48
49
	const char *pString,
	uint16_t fg,
	uint16_t bg
Gerd's avatar
Gerd committed
50
51
) {
	int cl = check_lock();
52
53
54
	if (font >= (sizeof(font_map) / sizeof(sFONT *))) {
		return -EINVAL;
	}
Gerd's avatar
Gerd committed
55
56
57
	if (cl < 0) {
		return cl;
	} else {
58
59
60
61
62
63
64
65
66
		gfx_puts(
			font_map[font],
			&display_screen,
			posx,
			posy,
			pString,
			fg,
			bg
		);
Gerd's avatar
Gerd committed
67
68
69
70
71
72
73
74
75
76
		return 0;
	}
}

int epic_disp_clear(uint16_t color)
{
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	} else {
Stefan Haun's avatar
Stefan Haun committed
77
		gfx_clear_to_color(current_fb, color);
Gerd's avatar
Gerd committed
78
79
80
81
		return 0;
	}
}

82
int epic_disp_pixel(int16_t x, int16_t y, uint16_t color)
83
84
85
86
87
{
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	} else {
Stefan Haun's avatar
Stefan Haun committed
88
		gfx_setpixel(current_fb, x, y, color);
89
90
91
92
		return 0;
	}
}

Gerd's avatar
Gerd committed
93
int epic_disp_line(
94
95
96
97
	int16_t xstart,
	int16_t ystart,
	int16_t xend,
	int16_t yend,
Gerd's avatar
Gerd committed
98
	uint16_t color,
Rahix's avatar
Rahix committed
99
	enum disp_linestyle linestyle,
Gerd's avatar
Gerd committed
100
101
102
103
104
105
	uint16_t pixelsize
) {
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	} else {
106
		/* TODO add linestyle support to gfx code */
107
		gfx_line(
Stefan Haun's avatar
Stefan Haun committed
108
			current_fb,
109
110
111
112
113
114
			xstart,
			ystart,
			xend,
			yend,
			pixelsize,
			color
Gerd's avatar
Gerd committed
115
116
117
118
119
120
		);
		return 0;
	}
}

int epic_disp_rect(
121
122
123
124
	int16_t xstart,
	int16_t ystart,
	int16_t xend,
	int16_t yend,
Gerd's avatar
Gerd committed
125
	uint16_t color,
Rahix's avatar
Rahix committed
126
	enum disp_fillstyle fillstyle,
Gerd's avatar
Gerd committed
127
128
129
	uint16_t pixelsize
) {
	int cl = check_lock();
130
	if (cl < 0)
Gerd's avatar
Gerd committed
131
		return cl;
132
133
134
135

	switch (fillstyle) {
	case FILLSTYLE_EMPTY:
		gfx_rectangle(
Stefan Haun's avatar
Stefan Haun committed
136
			current_fb,
137
138
139
140
141
142
			xstart,
			ystart,
			xend - xstart,
			yend - ystart,
			pixelsize,
			color
Gerd's avatar
Gerd committed
143
		);
144
145
146
		break;
	case FILLSTYLE_FILLED:
		gfx_rectangle_fill(
Stefan Haun's avatar
Stefan Haun committed
147
			current_fb,
148
149
150
151
152
153
154
			xstart,
			ystart,
			xend - xstart,
			yend - ystart,
			color
		);
		break;
Gerd's avatar
Gerd committed
155
	}
156
	return 0;
Gerd's avatar
Gerd committed
157
158
159
}

int epic_disp_circ(
160
161
	int16_t x,
	int16_t y,
Gerd's avatar
Gerd committed
162
163
	uint16_t rad,
	uint16_t color,
Rahix's avatar
Rahix committed
164
	enum disp_fillstyle fillstyle,
Gerd's avatar
Gerd committed
165
166
167
	uint16_t pixelsize
) {
	int cl = check_lock();
168
	if (cl < 0)
Gerd's avatar
Gerd committed
169
		return cl;
170
171
172

	switch (fillstyle) {
	case FILLSTYLE_EMPTY:
Stefan Haun's avatar
Stefan Haun committed
173
		gfx_circle(current_fb, x, y, rad, pixelsize, color);
174
175
		break;
	case FILLSTYLE_FILLED:
Stefan Haun's avatar
Stefan Haun committed
176
		gfx_circle_fill(current_fb, x, y, rad, color);
177
		break;
Gerd's avatar
Gerd committed
178
	}
179
180

	return 0;
Gerd's avatar
Gerd committed
181
182
}

183
184
185
186
187
188
189
190
void compositor()
{
	for (int y = 0; y < display_screen.height; y++) {
		for (int x = 0; x < display_screen.width; x++) {
			uint8_t *overlay_pixel =
				fb_pixel(overlay_screen.fb, x, y);
			uint8_t *target = fb_pixel(display_screen.fb, x, y);

Stefan Haun's avatar
Stefan Haun committed
191
192
			if ((overlay_pixel[0] == 0) &&
			    (overlay_pixel[1] == 0)) {
193
194
				uint8_t *app_pixel =
					fb_pixel(application_screen.fb, x, y);
Stefan Haun's avatar
Stefan Haun committed
195
196
197
				target[0] = app_pixel[0];
				target[1] = app_pixel[1];
			} else {
198
199
200
201
202
203
204
				target[0] = overlay_pixel[0];
				target[1] = overlay_pixel[1];
			}
		}
	}
}

Gerd's avatar
Gerd committed
205
206
207
208
209
210
int epic_disp_update()
{
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	}
211

Stefan Haun's avatar
Stefan Haun committed
212
	if (!fullscreen) {
Stefan Haun's avatar
Stefan Haun committed
213
214
		compositor();
	}
Stefan Haun's avatar
Stefan Haun committed
215

216
	gfx_update(&display_screen);
217
218
219
220
221
222
223
224
225
226
227
228
	return 0;
}

int epic_disp_framebuffer(union disp_framebuffer *fb)
{
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	}

	LCD_Set(fb->raw, sizeof(fb->raw));
	return 0;
Gerd's avatar
Gerd committed
229
230
}

231
232
int epic_disp_backlight(uint16_t brightness)
{
233
	/* TODO: lock? */
234
235
236
237
	LCD_SetBacklight(brightness);
	return 0;
}

Gerd's avatar
Gerd committed
238
239
240
241
int epic_disp_open()
{
	TaskHandle_t task = xTaskGetCurrentTaskHandle();
	if (lock == task) {
Stefan Haun's avatar
Stefan Haun committed
242
		current_fb = fullscreen ? &display_screen : &application_screen;
Gerd's avatar
Gerd committed
243
244
		return 0;
	} else if (lock == NULL) {
Stefan Haun's avatar
Stefan Haun committed
245
246
247
		lock       = task;
		current_fb = fullscreen ? &display_screen : &application_screen;
		return 0;
Gerd's avatar
Gerd committed
248
249
250
251
252
	} else {
		return -EBUSY;
	}
}

Stefan Haun's avatar
Stefan Haun committed
253
254
int epic_disp_set_fullscreen(bool enable)
{
Stefan Haun's avatar
Stefan Haun committed
255
256
257
258
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	}
Stefan Haun's avatar
Stefan Haun committed
259

Stefan Haun's avatar
Stefan Haun committed
260
	fullscreen = enable;
Stefan Haun's avatar
Stefan Haun committed
261

Stefan Haun's avatar
Stefan Haun committed
262
	current_fb = fullscreen ? &display_screen : &application_screen;
Stefan Haun's avatar
Stefan Haun committed
263

Stefan Haun's avatar
Stefan Haun committed
264
	return 0;
Stefan Haun's avatar
Stefan Haun committed
265
266
267
268
}

bool epic_disp_is_fullscreen()
{
Stefan Haun's avatar
Stefan Haun committed
269
	return fullscreen;
Stefan Haun's avatar
Stefan Haun committed
270
271
}

272
273
int epic_disp_overlay()
{
Stefan Haun's avatar
Stefan Haun committed
274
275
276
277
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	}
278

Stefan Haun's avatar
Stefan Haun committed
279
	current_fb = &overlay_screen;
280

Stefan Haun's avatar
Stefan Haun committed
281
	return 0;
282
283
}

Gerd's avatar
Gerd committed
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
int epic_disp_close()
{
	if (check_lock() < 0 && lock != NULL) {
		return -EBUSY;
	} else {
		lock = NULL;
		return 0;
	}
}

void disp_forcelock()
{
	TaskHandle_t task = xTaskGetCurrentTaskHandle();
	lock              = task;
}