Skip to content

Commit a28cea8

Browse files
committed
Add simple-framebuffer device support (using SDL). Only supports RGB565 for now. Enabled if HAS_SCREEN=True is set whilst building.
1 parent 6d9d6a3 commit a28cea8

File tree

5 files changed

+230
-1
lines changed

5 files changed

+230
-1
lines changed

device-tree/device_tree.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ extern "C"
2727
#include "device_timer_clint.h"
2828
#include "device_irq_ctrl.h"
2929
#include "device_irq_plic.h"
30+
#ifdef INCLUDE_SCREEN
31+
#include "device_frame_buffer.h"
32+
#endif
3033
#include "device_dummy.h"
3134

3235
//-----------------------------------------------------------------
@@ -185,6 +188,22 @@ bool device_tree::load(cpu *cpu)
185188
printf("|- Create SPI: Addr %08x IRQ %d\n", reg_addr, irq_num);
186189
cpu->attach_device(new device_spi_lite(reg_addr, irq_ctrl, irq_num));
187190
}
191+
#ifdef INCLUDE_SCREEN
192+
else if (!strcmp(compat, "simple-framebuffer"))
193+
{
194+
uint32_t width = 640;
195+
uint32_t height = 480;
196+
const uint32_t *p_width = (const uint32_t*)fdt_getprop(m_fdt, offset, "width", &size);
197+
if (p_width)
198+
width = ntohl(*p_width);
199+
const uint32_t *p_height = (const uint32_t*)fdt_getprop(m_fdt, offset, "height", &size);
200+
if (p_height)
201+
height = ntohl(*p_height);
202+
203+
printf("|- Create frame buffer: Addr %08x IRQ %d\n", reg_addr, irq_num);
204+
cpu->attach_device(new device_frame_buffer(reg_addr, width, height));
205+
}
206+
#endif
188207
else
189208
{
190209
printf("|- Create dummy device (%s): Addr %08x - %08x\n", compat, reg_addr, reg_addr + reg_size-1);

display/display.cpp

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
//-----------------------------------------------------------------
2+
// ExactStep IAISS
3+
// V0.5
4+
// github.com/ultraembedded/exactstep
5+
// Copyright 2014-2019
6+
// License: BSD 3-Clause
7+
//-----------------------------------------------------------------
8+
#include "display.h"
9+
10+
#ifdef INCLUDE_SCREEN
11+
#include <SDL/SDL.h>
12+
#endif
13+
14+
//-----------------------------------------------------------------
15+
// Defines
16+
//-----------------------------------------------------------------
17+
// RGB565 pixel format -> components
18+
#define RGB16_R(value) ((((value) >> 11) & 0x1F) << 3)
19+
#define RGB16_G(value) ((((value) >> 5) & 0x3F) << 2)
20+
#define RGB16_B(value) ((((value) >> 0) & 0x1F) << 3)
21+
22+
//-----------------------------------------------------------------
23+
// init: Create SDL based screen buffer
24+
//-----------------------------------------------------------------
25+
bool display::init(int width, int height)
26+
{
27+
#ifdef INCLUDE_SCREEN
28+
m_width = width;
29+
m_height = height;
30+
31+
if (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE))
32+
return false;
33+
34+
int flags = SDL_HWSURFACE | SDL_ASYNCBLIT | SDL_HWACCEL;
35+
SDL_Surface *screen = SDL_SetVideoMode(m_width, m_height, 0, flags);
36+
if (!screen || !screen->pixels)
37+
return false;
38+
39+
m_screen = screen;
40+
SDL_WM_SetCaption("ExactStep", "ExactStep");
41+
42+
// Disable cursor
43+
uint8_t data = 0;
44+
SDL_Cursor *cursor = SDL_CreateCursor(&data, &data, 8, 1, 0, 0);
45+
SDL_ShowCursor(1);
46+
SDL_SetCursor(cursor);
47+
#endif
48+
49+
return true;
50+
}
51+
//-----------------------------------------------------------------
52+
// update: Redraw entire screen from frame buffer
53+
//-----------------------------------------------------------------
54+
bool display::update(uint8_t *memory)
55+
{
56+
#ifdef INCLUDE_SCREEN
57+
SDL_Surface *screen = (SDL_Surface *)m_screen;
58+
uint16_t *frame = (uint16_t *)memory;
59+
60+
SDL_LockSurface(screen);
61+
for (int y=0;y<m_height;y++)
62+
{
63+
for (int x=0;x<m_width;x++)
64+
{
65+
uint16_t v = frame[(y*m_width)+x];
66+
uint32_t r = RGB16_R(v);
67+
uint32_t g = RGB16_G(v);
68+
uint32_t b = RGB16_B(v);
69+
70+
((uint32_t*)screen->pixels)[(y * (screen->pitch / 4)) + x] =
71+
(
72+
r << screen->format->Rshift |
73+
g << screen->format->Gshift |
74+
b << screen->format->Bshift
75+
);
76+
}
77+
}
78+
SDL_UnlockSurface(screen);
79+
SDL_UpdateRect(screen, 0, 0, 0, 0);
80+
#endif
81+
82+
return true;
83+
}
84+
85+

display/display.h

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//-----------------------------------------------------------------
2+
// ExactStep IAISS
3+
// V0.5
4+
// github.com/ultraembedded/exactstep
5+
// Copyright 2014-2019
6+
// License: BSD 3-Clause
7+
//-----------------------------------------------------------------
8+
#ifndef __DISPLAY_H__
9+
#define __DISPLAY_H__
10+
11+
#include <stdint.h>
12+
#include <stdlib.h>
13+
14+
//-----------------------------------------------------------------
15+
// SDL based display widget
16+
//-----------------------------------------------------------------
17+
class display
18+
{
19+
public:
20+
display()
21+
{
22+
m_screen = NULL;
23+
m_width = 0;
24+
m_height = 0;
25+
}
26+
bool init(int width, int height);
27+
bool update(uint8_t *memory);
28+
29+
private:
30+
int m_width;
31+
int m_height;
32+
void *m_screen;
33+
};
34+
35+
#endif

makefile

+10-1
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,27 @@
55
# Target
66
TARGET ?= exactstep
77

8+
HAS_SCREEN ?= False
9+
810
# Source Files
9-
SRC_DIR = core peripherals cpu-rv32 cpu-rv64 cpu-armv6m cli platforms device-tree
11+
SRC_DIR = core peripherals cpu-rv32 cpu-rv64 cpu-armv6m cli platforms device-tree display
1012

1113
CFLAGS = -O2 -fPIC
1214
CFLAGS += -Wno-format
15+
ifneq ($(HAS_SCREEN),False)
16+
CFLAGS += -DINCLUDE_SCREEN
17+
endif
1318

1419
INCLUDE_PATH += $(SRC_DIR)
1520
CFLAGS += $(patsubst %,-I%,$(INCLUDE_PATH))
1621

1722
LDFLAGS =
1823
LIBS = -lelf -lbfd -lfdt
1924

25+
ifneq ($(HAS_SCREEN),False)
26+
LIBS += -lSDL
27+
endif
28+
2029
###############################################################################
2130
# Variables
2231
###############################################################################

peripherals/device_frame_buffer.h

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//-----------------------------------------------------------------
2+
// ExactStep IAISS
3+
// V0.5
4+
// github.com/ultraembedded/exactstep
5+
// Copyright 2014-2019
6+
// License: BSD 3-Clause
7+
//-----------------------------------------------------------------
8+
#ifndef __DEVICE_FRAME_BUFFER_H__
9+
#define __DEVICE_FRAME_BUFFER_H__
10+
11+
#include "device.h"
12+
#include "display.h"
13+
14+
//-----------------------------------------------------------------
15+
// device_frame_buffer: Simplified frame buffer device
16+
//-----------------------------------------------------------------
17+
class device_frame_buffer: public device
18+
{
19+
public:
20+
device_frame_buffer(uint32_t base_addr, int width, int height): device("fb", base_addr, height * width * 2, NULL, -1)
21+
{
22+
m_fb = new uint8_t[height * width * 2];
23+
m_ticks = 0;
24+
25+
m_display.init(width, height);
26+
}
27+
28+
void reset(void)
29+
{
30+
31+
}
32+
33+
int min_access_size(void) { return 1; }
34+
35+
bool write8(uint32_t address, uint8_t data)
36+
{
37+
address -= m_base;
38+
m_fb[address] = data;
39+
return true;
40+
}
41+
42+
bool write_block(uint32_t address, uint8_t *data, int length)
43+
{
44+
address -= m_base;
45+
for (int i=0;i<length;i++)
46+
m_fb[address+i] = data[i];
47+
return true;
48+
}
49+
50+
bool write32(uint32_t address, uint32_t data)
51+
{
52+
address -= m_base;
53+
m_fb[address+0] = data >> 0;
54+
m_fb[address+1] = data >> 8;
55+
m_fb[address+2] = data >> 16;
56+
m_fb[address+3] = data >> 24;
57+
return true;
58+
}
59+
60+
bool read32(uint32_t address, uint32_t &data)
61+
{
62+
return true;
63+
}
64+
65+
int clock(void)
66+
{
67+
if (++m_ticks == 100000)
68+
{
69+
m_display.update(m_fb);
70+
m_ticks = 0;
71+
}
72+
return 0;
73+
}
74+
75+
private:
76+
uint8_t *m_fb;
77+
int m_ticks;
78+
display m_display;
79+
};
80+
81+
#endif

0 commit comments

Comments
 (0)