display.c 5.45 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"
11
12
13
14
15
#include "FreeRTOS.h"
#include "timers.h"

#define MAX_BRIGHTNESS 300
#define FREQ 100
Gerd's avatar
Gerd committed
16
17

static TaskHandle_t lock = NULL;
fleur's avatar
fleur committed
18
19
static TimerHandle_t display_timer;
static StaticTimer_t display_timer_buffer;
20
21
22
23
24
25

static bool display_on;
static bool wake_event;
static uint16_t timeout_cycles = 1000;
static uint8_t lpf_speed = 10; //ca. 1Hz f_g
static uint8_t brightness_table[MAX_BRIGHTNESS];
Gerd's avatar
Gerd committed
26
27
28
29
30
31
32
33
34
35
36

static int check_lock()
{
	TaskHandle_t task = xTaskGetCurrentTaskHandle();
	if (task != lock) {
		return -EBUSY;
	} else {
		return 0;
	}
}

37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
void epic_disp_set_brightness_table(uint8_t table[MAX_BRIGHTNESS])
{
	for (int i = 0; i < MAX_BRIGHTNESS; i++){
		brightness_table[i]=table[i];
	}
}

static uint16_t limit(uint16_t input, uint16_t max, uint16_t min){
	uint16_t output = input > max ? max : input;
	return output < 0 ? 0 : output;
}

static uint16_t lpf(uint16_t input, uint8_t speed){
	static uint16_t output;
	output = speed*input+(~speed)*output;
	output = output >> 8;
	return output;
}

static void auto_backlight(){
	uint16_t light = 0;
	if(display_on){
		epic_light_sensor_get(&light);
		light = brightness_table[limit(light,MAX_BRIGHTNESS-1,0)];
	}

	uint16_t lpf_light = lpf(light, lpf_speed);
	lpf_light = limit(lpf_light,100,display_on);
	epic_disp_backlight(lpf_light);
}

fleur's avatar
fleur committed
68
69
70
71
void epic_disp_set_timeout_cycles(int cycles){
	timeout_cycles=cycles;
}

72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
void epic_disp_wake(){
	wake_event = true;
}

static void CALLBACK_power_mgmt(){ //u gotta loop dis
	uint16_t buttonTimeout = 0;
	if(!timeout_cycles){
		display_on = true;
	} else if(wake_event){
		buttonTimeout = timeout_cycles;
		display_on = true;
		wake_event = false;
	} else if(buttonTimeout){
		buttonTimeout--;
	} else {
		display_on = false;
	}
	auto_backlight();
}

void epic_disp_backlight_auto_stop()
{
fleur's avatar
fleur committed
94
95
	if (!display_timer || xTimerIsTimerActive(display_timer) == pdFALSE) { return; }
	xTimerStop(display_timer, 0);
96
97
}

fleur's avatar
fleur committed
98
void epic_disp_backlight_auto_start(){
fleur's avatar
fleur committed
99
100
	if(!display_timer) {
		display_timer = xTimerCreateStatic(
101
102
103
104
105
				"auto_backlight",
				FREQ,
				pdTRUE,
				NULL,
				CALLBACK_power_mgmt,
fleur's avatar
fleur committed
106
				&display_timer_buffer
107
		);
fleur's avatar
fleur committed
108
		xTimerStart(display_timer, 0);
109
110
111
	}
}

Gerd's avatar
Gerd committed
112
113
114
115
116
117
int epic_disp_print(
	uint16_t posx,
	uint16_t posy,
	const char *pString,
	uint16_t fg,
	uint16_t bg
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
) {
	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,
	uint16_t posx,
	uint16_t posy,
	const char *pString,
	uint16_t fg,
	uint16_t bg
Gerd's avatar
Gerd committed
135
136
) {
	int cl = check_lock();
137
138
139
	if (font >= (sizeof(font_map) / sizeof(sFONT *))) {
		return -EINVAL;
	}
Gerd's avatar
Gerd committed
140
141
142
	if (cl < 0) {
		return cl;
	} else {
143
144
145
146
147
148
149
150
151
		gfx_puts(
			font_map[font],
			&display_screen,
			posx,
			posy,
			pString,
			fg,
			bg
		);
Gerd's avatar
Gerd committed
152
153
154
155
156
157
158
159
160
161
		return 0;
	}
}

int epic_disp_clear(uint16_t color)
{
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	} else {
162
		gfx_clear_to_color(&display_screen, color);
Gerd's avatar
Gerd committed
163
164
165
166
		return 0;
	}
}

167
168
169
170
171
172
int epic_disp_pixel(uint16_t x, uint16_t y, uint16_t color)
{
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	} else {
173
		gfx_setpixel(&display_screen, x, y, color);
174
175
176
177
		return 0;
	}
}

Gerd's avatar
Gerd committed
178
179
180
181
182
183
int epic_disp_line(
	uint16_t xstart,
	uint16_t ystart,
	uint16_t xend,
	uint16_t yend,
	uint16_t color,
Rahix's avatar
Rahix committed
184
	enum disp_linestyle linestyle,
Gerd's avatar
Gerd committed
185
186
187
188
189
190
	uint16_t pixelsize
) {
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	} else {
191
		/* TODO add linestyle support to gfx code */
192
		gfx_line(
193
194
195
196
197
198
199
			&display_screen,
			xstart,
			ystart,
			xend,
			yend,
			pixelsize,
			color
Gerd's avatar
Gerd committed
200
201
202
203
204
205
206
207
208
209
210
		);
		return 0;
	}
}

int epic_disp_rect(
	uint16_t xstart,
	uint16_t ystart,
	uint16_t xend,
	uint16_t yend,
	uint16_t color,
Rahix's avatar
Rahix committed
211
	enum disp_fillstyle fillstyle,
Gerd's avatar
Gerd committed
212
213
214
	uint16_t pixelsize
) {
	int cl = check_lock();
215
	if (cl < 0)
Gerd's avatar
Gerd committed
216
		return cl;
217
218
219
220
221
222
223
224
225
226
227

	switch (fillstyle) {
	case FILLSTYLE_EMPTY:
		gfx_rectangle(
			&display_screen,
			xstart,
			ystart,
			xend - xstart,
			yend - ystart,
			pixelsize,
			color
Gerd's avatar
Gerd committed
228
		);
229
230
231
232
233
234
235
236
237
238
239
		break;
	case FILLSTYLE_FILLED:
		gfx_rectangle_fill(
			&display_screen,
			xstart,
			ystart,
			xend - xstart,
			yend - ystart,
			color
		);
		break;
Gerd's avatar
Gerd committed
240
	}
241
	return 0;
Gerd's avatar
Gerd committed
242
243
244
245
246
247
248
}

int epic_disp_circ(
	uint16_t x,
	uint16_t y,
	uint16_t rad,
	uint16_t color,
Rahix's avatar
Rahix committed
249
	enum disp_fillstyle fillstyle,
Gerd's avatar
Gerd committed
250
251
252
	uint16_t pixelsize
) {
	int cl = check_lock();
253
	if (cl < 0)
Gerd's avatar
Gerd committed
254
		return cl;
255
256
257
258
259
260
261
262

	switch (fillstyle) {
	case FILLSTYLE_EMPTY:
		gfx_circle(&display_screen, x, y, rad, pixelsize, color);
		break;
	case FILLSTYLE_FILLED:
		gfx_circle_fill(&display_screen, x, y, rad, color);
		break;
Gerd's avatar
Gerd committed
263
	}
264
265

	return 0;
Gerd's avatar
Gerd committed
266
267
268
269
270
271
272
273
}

int epic_disp_update()
{
	int cl = check_lock();
	if (cl < 0) {
		return cl;
	}
274

275
	gfx_update(&display_screen);
276
277
278
279
280
281
282
283
284
285
286
287
	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
288
289
}

290
291
int epic_disp_backlight(uint16_t brightness)
{
292
	/* TODO: lock? */
293
294
295
296
	LCD_SetBacklight(brightness);
	return 0;
}

Gerd's avatar
Gerd committed
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
int epic_disp_open()
{
	TaskHandle_t task = xTaskGetCurrentTaskHandle();
	if (lock == task) {
		return 0;
	} else if (lock == NULL) {
		lock = task;
		return 0;
	} else {
		return -EBUSY;
	}
}

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