Commit aee6c83a authored by Projects's avatar Projects

Merged Tom's UI library.

parent 36979342
/*
* Copyright (C) 2014 Julian Lewis
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gfx.h"
#define GFX_POOL_SIZE 4096
static uint32_t gfx_pool_mem[GFX_POOL_SIZE/4];
static int gfx_pool_pos = 0;
void *gfx_alloc(int count)
{
count += 3;
count *= 4;
count /= 4; // align to 32 bits
if(count + gfx_pool_pos >= GFX_POOL_SIZE)
return NULL;
void *p = gfx_pool_mem + gfx_pool_pos;
gfx_pool_pos += count;
return p;
}
void gfx_init_surface( struct surface *surf, struct surface *parent, int x0, int y0, int w, int h )
{
if(!parent)
{
surf->width = w;
surf->height = h;
surf->clip.x0 = 0;
surf->clip.y0 = 0;
surf->clip.x1 = w - 1;
surf->clip.y1 = h - 1;
surf->stride = (w + 7) / 8;
surf->data = gfx_alloc(surf->stride * h);
memset( surf->data, 0, surf->stride * h);
} else {
surf->width = parent->width;
surf->height= parent->height;
surf->stride = parent->stride;
surf->clip.x0 = 0;
surf->clip.y0 = 0;
surf->clip.x1 = w - 1;
surf->clip.y1 = h - 1;
surf->client_x = x0;
surf->client_y = y0;
surf->data = parent->data;
}
}
void gfx_set_clip (struct surface *surf, int x0, int y0, int x1, int y1 )
{
surf->clip.x0 = x0;
surf->clip.y0 = y0;
surf->clip.x1 = x1;
surf->clip.y1 = y1;
}
void gfx_reset_clip (struct surface *surf)
{
surf->clip.x0 = 0;
surf->clip.y0 = 0;
surf->clip.x1 = surf->width - 1;
surf->clip.y1 = surf->height - 1;
}
void gfx_box( struct surface *surf, int x0, int y0, int x1, int y1, int value)
{
uint8_t x, y;
x0 = MAX(x0, surf->clip.x0);
x1 = MIN(x1, surf->clip.x1);
y0 = MAX(y0, surf->clip.y0);
y1 = MIN(y1, surf->clip.y1);
for(x = x0; x <= x1; x++)
{
for(y = y0; y <= y1; y++)
{
gfx_set_pixel(surf, x, y, value);
}
}
}
void gfx_clear(struct surface *surf, int value)
{
gfx_box( surf, 0, 0, surf->width-1, surf->height-1, value);
}
void gfx_line( struct surface *surf, int x0, int y0, int x1, int y1, int value )
{
int dx = abs(x1 - x0);
int sx = x0 < x1 ? 1 : -1;
int dy = abs(y1 - y0);
int sy = y0 < y1 ? 1 : -1;
int err = (dx > dy ? dx : -dy) / 2;
int e2;
for(;;)
{
gfx_set_pixel(surf, x0, y0, value);
if(x0 == x1 && y0 == y1)
break;
e2 = err;
if(e2 > -dx) { err -= dy; x0 += sx; }
if(e2 < dy) { err += dx; y0 += sy; }
}
}
static uint8_t draw_glyph(const struct font *font, struct surface *surf, uint8_t x0, uint8_t y0, char c)
{
if(c < font->min_char || c > font->max_char)
return 0;
const uint8_t *buf = font->glyph_data + font->offset_table[c - font->min_char];
uint8_t w = font->width_table[c - font->min_char];
uint8_t x, y;
//printf("DrawGlyph: %d %d '%c'\n", x0, y0, c);
for(y = 0; y < font->height; y++)
{
for(x = 0; x < w; x++)
{
if(buf[((w + 7) >> 3) * y + (x >> 3)] & (1 << (7 - (x & 7))))
gfx_set_pixel(surf, x + x0, y + y0, c);
}
}
return w;
}
void gfx_text(struct surface *surf, const struct font *font, uint8_t x, uint8_t y, const char *str)
{
char c;
while((c = *str++))
x += draw_glyph(font, surf, x, y, c);
}
void gfx_centered_text(struct surface *surf, const struct font *font, uint8_t y, const char *str)
{
int w = gfx_text_width(font, str);
gfx_text(surf, font, surf->width / 2 - w / 2, y, str);
}
int gfx_text_width( const struct font *font, const char *str)
{
int c;
int w = 0;
while((c = *str++))
{
if(c < font->min_char || c > font->max_char)
continue;
w += font->width_table[c - font->min_char];
}
return w;
}
void gfx_fill_circle(struct surface *surf, int x0, int y0, int radius, int value)
{
int x = radius;
int y = 0;
int xChange = 1 - (radius << 1);
int yChange = 0;
int radiusError = 0;
while (x >= y)
{
int i;
for (i = x0 - x; i <= x0 + x; i++)
{
gfx_set_pixel(surf, i, y0 + y, value);
gfx_set_pixel(surf, i, y0 - y, value);
}
for (i = x0 - y; i <= x0 + y; i++)
{
gfx_set_pixel(surf, i, y0 + x, value);
gfx_set_pixel(surf, i, y0 - x, value);
}
y++;
radiusError += yChange;
yChange += 2;
if (((radiusError << 1) + xChange) > 0)
{
x--;
radiusError += xChange;
xChange += 2;
}
}
}
void gfx_round_box(struct surface *surf, int x0, int y0, int x1, int y1, int radius, int value)
{
gfx_box(surf, x0, y0 + radius, x1, y1 - radius, value);
gfx_box(surf, x0 +radius , y0, x1 - radius, y1, value);
gfx_fill_circle(surf, x0+radius, y0+radius, radius, value);
gfx_fill_circle(surf, x1-radius, y0+radius, radius, value);
gfx_fill_circle(surf, x1-radius, y1-radius, radius, value);
gfx_fill_circle(surf, x0+radius, y1-radius, radius, value);
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __GFX_H
#define __GFX_H
#include "font.h"
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
#define COLOR_WHITE 0
#define COLOR_BLACK 1
#define COLOR_TOGGLE 2
struct rect {
uint8_t x0, y0, x1, y1;
};
struct surface
{
uint8_t width, height, stride;
struct rect clip;
int client_x, client_y;
void *data;
};
static inline void gfx_set_pixel(struct surface *surf, int x, int y, int value)
{
if(x < surf->clip.x0 || x > surf->clip.x1 ||
y < surf->clip.y0 || y > surf->clip.y1)
return;
x += surf->client_x;
y += surf->client_y;
uint8_t mask = 1 << (x & 0x07);
uint8_t *p = surf->data + (y * surf->stride) + (x >> 3);
if(value == COLOR_BLACK)
*p |= mask;
else if(value == COLOR_WHITE)
*p &= ~mask;
else
*p ^= mask;
}
void gfx_init_surface(struct surface *surf, struct surface *parent, int x0, int y0, int w, int h);
void gfx_box(struct surface *surf, int x0, int y0, int x1, int y1, int value);
void gfx_line(struct surface *surf, int x0, int y0, int x1, int y1, int value);
void gfx_text(struct surface *surf, const struct font *font, uint8_t x, uint8_t y, const char *str);
void gfx_centered_text(struct surface *surf, const struct font *font, uint8_t y, const char *str);
int gfx_text_width(const struct font *font, const char *str);
void gfx_clear(struct surface *surf, int value);
void gfx_set_clip (struct surface *surf, int x0, int y0, int x1, int y1);
void gfx_reset_clip (struct surface *surf);
void gfx_fill_circle(struct surface *surf, int x0, int y0, int radius, int value);
void gfx_round_box(struct surface *surf, int x0, int y0, int x1, int y1, int radius, int value);
#endif
/*
* Copyright (C) 2014 Julian Lewis
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "gfx.h"
#include "ui.h"
#include <drivers/lcd.h>
#include <stdlib.h>
#define DBG
struct surface screen;
static struct ui_widget *widget_list = NULL;
void ui_init() {
gfx_init_surface(&screen, NULL, 0, 0, LCD_WIDTH, LCD_HEIGHT);
}
void ui_add_widget(struct ui_widget *w) {
w->next = NULL;
if(!widget_list) {
widget_list = w;
} else {
struct ui_widget *wl;
// find the last widget (the ending semicolon in the for loop is ok)
for(wl = widget_list; wl->next; wl = wl->next);
wl->next = w;
}
if(!(w->flags & WF_DOUBLE_BUFFER)) {
gfx_init_surface(&w->dc, &screen, w->pos.x0, w->pos.y0,
w->pos.x1 - w->pos.x0 + 1, w->pos.y1 - w->pos.y0 + 1);
}
else {
DBG("NonImpl\n");
}
w->flags |= WF_DIRTY;
}
static int update_widget(struct ui_widget *w, struct event evt) {
if((w->flags & WF_ACTIVE) && (w->event)) {
w->event(w, evt);
}
if((w->flags & WF_VISIBLE) && (w->flags & WF_DIRTY))
{
if(w->redraw) {
w->redraw(w);
w->flags &= ~WF_DIRTY;
}
return 1;
}
return 0;
}
void draw_surface(struct surface *surf)
{
int y, x;
lcd_clear();
// TODO that sucks a little bit..
for(y = 0; y < surf->height; y++) {
for(x = 0; x < surf->width; x++) {
uint8_t mask = 1 << (x & 0x07);
uint8_t *p = surf->data + (y * surf->stride) + (x >> 3);
lcd_set_pixel(x, y, (*p & mask));
}
}
lcd_update();
}
void ui_update(struct event evt) {
int screen_dirty = 0;
struct ui_widget *w;
for(w = widget_list; w; w = w->next)
{
screen_dirty |= update_widget(w, evt);
}
if(screen_dirty)
draw_surface(&screen);
}
/*void ui_activate(struct ui_widget *w, int activate) {
}
void ui_show(struct ui_widget *w, int show) {
}
void ui_set_modal(struct ui_widget *w, int modal) {
}*/
void ui_init_widget(struct ui_widget *w) {
w->n_children = 0;
}
void ui_add_child(struct ui_widget *w, struct ui_widget *child) {
w->children[ w->n_children ] = child;
w->flags |= WF_DIRTY;
w->n_children++;
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* 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 2
* 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, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef __UI_H
#define __UI_H
#include "gfx.h"
#include <event.h>
#define WF_DIRTY (1<<0)
#define WF_VISIBLE (1<<1)
#define WF_TRANSPARENT (1<<2)
#define WF_ACTIVE (1<<3)
#define WF_DOUBLE_BUFFER (1<<4)
#define MAX_CHILD_WIDGETS 8
struct ui_widget {
void (*redraw)(struct ui_widget *w);
void (*event)(struct ui_widget *w, struct event evt);
struct rect pos;
uint8_t order;
int flags;
struct surface dc;
struct ui_widget *next;
struct ui_widget *children[MAX_CHILD_WIDGETS];
int n_children;
};
extern struct surface screen;
void ui_init();
void ui_add_widget(struct ui_widget *w);
void ui_update(struct event evt);
//void ui_activate(struct ui_widget *w, int activate);
//void ui_show(struct ui_widget *w, int show);
//void ui_set_modal(struct ui_widget *w, int modal);
void ui_init_widget(struct ui_widget *w);
void ui_add_child(struct ui_widget *w, struct ui_widget *child);
#endif
......@@ -149,6 +149,8 @@ C_SRC += \
../common/gfx/font_xm4x6.c \
../common/gfx/font_xm5x8.c \
../common/gfx/graphics.c \
../common/gfx/gfx.c \
../common/gfx/ui.c \
../common/udelay.c \
FreeRTOS/Source/timers.c \
FreeRTOS/Source/tasks.c \
......
......@@ -32,6 +32,7 @@
#include <apps/menu.h>
#include <drivers/buttons.h>
#include <drivers/lcd.h>
#include <gfx/ui.h>
int main(void)
{
......@@ -44,6 +45,7 @@ int main(void)
buttons_init();
lcd_init();
ui_init();
GPIO_PinModeSet(gpioPortE, 11, gpioModePushPull, 0);
GPIO_PinModeSet(gpioPortE, 12, gpioModePushPull, 0);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment