VxKernel 0.6.0-24 : Add SDL2 support (fake board)

@add
<> board/sdl2
  | [board] add DMA module support
  | [board] add RTC module support
<> src/driver/mpu/x86/sdl2
  | [dma] add fake DMA driver
  | [rtc] add fake RTC driver

@update
<> driver/mpu/x86/sdl2
  | [keyboard] add key more information
  | [keyboard] display keymap when the driver is installed
  | [keyboard] allow event pop even if the `event` argument is NULL
  | [timer] display driver installation logs
  | [window] display driver installation logs
  | [window] display VRAM in x2
<> driver/mpu/sh/sh7305/
  | [keysc] allow event pop even if the `event` argument is NULL

@fix
<> board/sdl2
  | [initialize] fix constructor priority
  | [initialize] fix constructor logs
<> driver/mpu/sh/sh7305/
  | [keysc] fix safety with event NULL
  | [rtc] fix file organization
This commit is contained in:
Yann MAGNIN 2022-08-26 10:30:46 +02:00
parent 176f4cb9d1
commit ca4e598d28
9 changed files with 359 additions and 123 deletions

View File

@ -7,7 +7,9 @@ modules = [
'display',
'hypervisor',
'timer',
'keyboard'
'keyboard',
'dma',
'rtc'
]
[drivers]

View File

@ -5,15 +5,10 @@
extern void kinit(void);
__attribute__((constructor))
__attribute__((constructor(101)))
int _initialize(void)
{
printf("early kernel initialisation...");
/* initialize drivers and modules */
printf("early kernel initialisation...\n");
kinit();
printf("OK\n");
return 0;
}

View File

@ -86,6 +86,9 @@ int sh7305_keycache_keydown(vkey_t key)
/* sh7305_keycache_event_push() : push event on the keycache */
int sh7305_keycache_event_push(vkey_event_t *event)
{
if (event == NULL)
return -1;
cpu_atomic_start();
keyinfo.queue.idx += 1;
@ -114,13 +117,17 @@ int sh7305_keycache_event_pop(vkey_event_t *event)
cpu_atomic_start();
if (keyinfo.queue.idx < 0) {
event->key = VKEY_NONE;
event->type = VKEYEV_NONE;
if (event != NULL) {
event->key = VKEY_NONE;
event->type = VKEYEV_NONE;
}
ret = 0;
} else {
event->time = keyinfo.queue.list[0].time;
event->type = keyinfo.queue.list[0].type;
event->key = keyinfo.queue.list[0].key;
if (event != NULL) {
event->time = keyinfo.queue.list[0].time;
event->type = keyinfo.queue.list[0].type;
event->key = keyinfo.queue.list[0].key;
}
memcpy(
&keyinfo.queue.list[0],
@ -137,14 +144,16 @@ int sh7305_keycache_event_pop(vkey_event_t *event)
}
/* sh7305_keycache_event_wait() : wait event or timeout != 0 */
int sh7305_keycache_event_wait(vkey_event_t *e, volatile int *timeout)
int sh7305_keycache_event_wait(vkey_event_t *event, volatile int *timeout)
{
do {
if (sh7305_keycache_event_pop(e))
if (sh7305_keycache_event_pop(event))
return 1;
if (timeout != NULL && timeout != 0) {
e->type = VKEYEV_NONE;
e->key = VKEY_NONE;
if (event != NULL) {
event->type = VKEYEV_NONE;
event->key = VKEY_NONE;
}
return 0;
}
__asm__("sleep");

View File

@ -56,6 +56,75 @@ void sh7305_rtc_periodic_disable(void)
SH7305_RTC.RCR2.PES = RTC_NONE;
}
//---
// User API
//---
/* int8(), int16(): Convert BCD to integer */
static int int8(uint8_t bcd)
{
return (bcd & 0x0f) + 10 * (bcd >> 4);
}
static int int16(uint16_t bcd)
{
return (bcd & 0xf) + 10 * ((bcd >> 4) & 0xf) + 100 * ((bcd >> 8) & 0xf)
+ 1000 * (bcd >> 12);
}
/* bcd8(), bcd16(): Convert integer to BCD */
static uint8_t bcd8(int integer)
{
integer %= 100;
return ((integer / 10) << 4) | (integer % 10);
}
static uint16_t bcd16(int integer)
{
integer %= 10000;
return (bcd8(integer / 100) << 8) | bcd8(integer % 100);
}
/* sh7305_rtc_get_time(): Read the current time from the RTC */
int sh7305_rtc_get_time(rtc_time_t *time)
{
do {
SH7305_RTC.RCR1.CF = 0;
time->ticks = SH7305_RTC.R64CNT;
time->seconds = int8(SH7305_RTC.RSECCNT.byte);
time->minutes = int8(SH7305_RTC.RMINCNT.byte);
time->hours = int8(SH7305_RTC.RHRCNT.byte);
time->month_day = int8(SH7305_RTC.RDAYCNT.byte);
time->month = int8(SH7305_RTC.RMONCNT.byte);
time->year = int16(SH7305_RTC.RYRCNT.word);
time->week_day = SH7305_RTC.RWKCNT;
} while(SH7305_RTC.RCR1.CF != 0);
return 0;
}
/* sh7305_rtc_set_time(): Set current time in the RTC */
int sh7305_rtc_set_time(rtc_time_t const *time)
{
int wday = time->week_day;
if(wday >= 7) wday = 0;
do {
SH7305_RTC.RCR1.CF = 0;
SH7305_RTC.RSECCNT.byte = bcd8(time->seconds);
SH7305_RTC.RMINCNT.byte = bcd8(time->minutes);
SH7305_RTC.RHRCNT.byte = bcd8(time->hours);
SH7305_RTC.RDAYCNT.byte = bcd8(time->month_day);
SH7305_RTC.RMONCNT.byte = bcd8(time->month);
SH7305_RTC.RYRCNT.word = bcd16(time->year);
SH7305_RTC.RWKCNT = wday;
} while(SH7305_RTC.RCR1.CF != 0);
return 0;
}
//---
// Define driver information
//---
@ -151,77 +220,6 @@ static void __rtc_hrestore(struct rtc_ctx *state)
SH7305_RTC.RCR2.START = state->rtc.RCR2.START;
}
//---
// User API
//---
/* int8(), int16(): Convert BCD to integer */
static int int8(uint8_t bcd)
{
return (bcd & 0x0f) + 10 * (bcd >> 4);
}
static int int16(uint16_t bcd)
{
return (bcd & 0xf) + 10 * ((bcd >> 4) & 0xf) + 100 * ((bcd >> 8) & 0xf)
+ 1000 * (bcd >> 12);
}
/* bcd8(), bcd16(): Convert integer to BCD */
static uint8_t bcd8(int integer)
{
integer %= 100;
return ((integer / 10) << 4) | (integer % 10);
}
static uint16_t bcd16(int integer)
{
integer %= 10000;
return (bcd8(integer / 100) << 8) | bcd8(integer % 100);
}
/* sh7305_rtc_get_time(): Read the current time from the RTC */
int sh7305_rtc_get_time(rtc_time_t *time)
{
do {
SH7305_RTC.RCR1.CF = 0;
time->ticks = SH7305_RTC.R64CNT;
time->seconds = int8(SH7305_RTC.RSECCNT.byte);
time->minutes = int8(SH7305_RTC.RMINCNT.byte);
time->hours = int8(SH7305_RTC.RHRCNT.byte);
time->month_day = int8(SH7305_RTC.RDAYCNT.byte);
time->month = int8(SH7305_RTC.RMONCNT.byte);
time->year = int16(SH7305_RTC.RYRCNT.word);
time->week_day = SH7305_RTC.RWKCNT;
} while(SH7305_RTC.RCR1.CF != 0);
return 0;
}
/* sh7305_rtc_set_time(): Set current time in the RTC */
int sh7305_rtc_set_time(rtc_time_t const *time)
{
int wday = time->week_day;
if(wday >= 7) wday = 0;
do {
SH7305_RTC.RCR1.CF = 0;
SH7305_RTC.RSECCNT.byte = bcd8(time->seconds);
SH7305_RTC.RMINCNT.byte = bcd8(time->minutes);
SH7305_RTC.RHRCNT.byte = bcd8(time->hours);
SH7305_RTC.RDAYCNT.byte = bcd8(time->month_day);
SH7305_RTC.RMONCNT.byte = bcd8(time->month);
SH7305_RTC.RYRCNT.word = bcd16(time->year);
SH7305_RTC.RWKCNT = wday;
} while(SH7305_RTC.RCR1.CF != 0);
return 0;
}
//---
// Declare driver
//---
struct vhex_driver drv_rtc = {
.name = "RTC",
.hpowered = (void*)&__rtc_hpowered,

View File

@ -0,0 +1,76 @@
#include <vhex/driver.h>
#include <vhex/dma/interface.h>
#include <vhex/dma.h>
#include <string.h>
#include <stdio.h>
/* dma_memcpy() : memcpy using DMA */
dma_id_t sdl_dma_memcpy(void * restrict dst, void * restrict src, size_t sz)
{
memcpy(dst, src, sz);
return 0;
}
/* dma_memset() : memset using the DMA */
dma_id_t sdl_dma_memset(void *dst, int c, size_t sz)
{
memset(dst, c, sz);
return 0;
}
/* dma_wait() : wait the end of the DMA channel transfer */
int sdl_dma_wait(dma_id_t id)
{
(void)id;
return 0;
}
/* dma_wait() : wait the end of the DMA channel transfer without interruption */
int sdl_dma_spinwait(dma_id_t id)
{
(void)id;
return 0;
}
//---
// Fake driver definition
//---
static void __dma_configure(void)
{
// Nothing to do, this is a fake driver
printf("[drv] DMA: fake driver initialized\n");
}
static void __dma_hsave(void)
{
// Nothing to do, this is a fake driver
;
}
static void __dma_hrestore(void)
{
// Nothing to do, this is a fake driver
;
}
struct vhex_driver drv_dma = {
.name = "SDL2 DMA",
.hsave = (void*)&__dma_hsave,
.hrestore = (void*)&__dma_hrestore,
.configure = (void*)&__dma_configure,
.state_size = 4,
.flags = {
.DMA = 1,
.SHARED = 0,
.UNUSED = 0,
},
.module_data = &(struct dma_drv_interface){
.dma_memcpy = &sdl_dma_memcpy,
.dma_memset = &sdl_dma_memset,
.dma_wait = &sdl_dma_wait,
.dma_spinwait = &sdl_dma_spinwait
}
};
VHEX_DECLARE_DRIVER(05, drv_dma);

View File

@ -20,24 +20,74 @@ static struct {
static struct {
int sdl2_id;
char const * const sdl2_name;
int vhex_id;
char const * const vhex_name;
} key_translation[16] = {
{ .sdl2_id = 49, .vhex_id = VKEY_F1 }, // 1
{ .sdl2_id = 50, .vhex_id = VKEY_F2 }, // 2
{ .sdl2_id = 51, .vhex_id = VKEY_F3 }, // 3
{ .sdl2_id = 52, .vhex_id = VKEY_F4 }, // 4
{ .sdl2_id = 53, .vhex_id = VKEY_F5 }, // 5
{ .sdl2_id = 54, .vhex_id = VKEY_F6 }, // 6
{ .sdl2_id = 0x4000004f, .vhex_id = VKEY_RIGHT }, // right arrow
{ .sdl2_id = 0x40000050, .vhex_id = VKEY_LEFT }, // left arrow
{ .sdl2_id = 0x40000051, .vhex_id = VKEY_DOWN }, // down arrow
{ .sdl2_id = 0x40000052, .vhex_id = VKEY_UP }, // up arrow
{ .sdl2_id = 13, .vhex_id = VKEY_EXE }, // enter
{ .sdl2_id = 0x400000e0, .vhex_id = VKEY_ALPHA }, // shift
{ .sdl2_id = 0x400000e1, .vhex_id = VKEY_SHIFT }, // ctrl
{ .sdl2_id = 27, .vhex_id = VKEY_EXIT }, // echap
{ .sdl2_id = 8, .vhex_id = VKEY_DEL }, // backspace
{ .sdl2_id = 9, .vhex_id = VKEY_MENU }, // tab
{
.sdl2_id = 49, .sdl2_name = "1",
.vhex_id = VKEY_F1, .vhex_name = "F1"
},
{
.sdl2_id = 50, .sdl2_name = "2",
.vhex_id = VKEY_F2, .vhex_name = "F2"
},
{
.sdl2_id = 51, .sdl2_name = "3",
.vhex_id = VKEY_F3, .vhex_name = "F3"
},
{
.sdl2_id = 52, .sdl2_name = "4",
.vhex_id = VKEY_F4, .vhex_name = "F4"
},
{
.sdl2_id = 53, .sdl2_name = "5",
.vhex_id = VKEY_F5, .vhex_name = "F5"
},
{
.sdl2_id = 54, .sdl2_name = "6",
.vhex_id = VKEY_F6, .vhex_name = "F6"
},
{
.sdl2_id = 0x4000004f, .sdl2_name = "right arrow",
.vhex_id = VKEY_RIGHT, .vhex_name = "right arrow"
},
{
.sdl2_id = 0x40000050, .sdl2_name = "left arrow",
.vhex_id = VKEY_LEFT, .vhex_name = "left arrow"
},
{
.sdl2_id = 0x40000051, .sdl2_name = "down arrow",
.vhex_id = VKEY_DOWN, .vhex_name = "down arrow"
},
{
.sdl2_id = 0x40000052, .sdl2_name = "up arrow",
.vhex_id = VKEY_UP, .vhex_name = "up arrow"
},
{
.sdl2_id = 13, .sdl2_name = "enter",
.vhex_id = VKEY_EXE, .vhex_name = "EXE"
},
{
.sdl2_id = 0x400000e0, .sdl2_name = "shift",
.vhex_id = VKEY_ALPHA, .vhex_name = "ALPHA"
},
{
.sdl2_id = 0x400000e1, .sdl2_name = "ctrl",
.vhex_id = VKEY_SHIFT, .vhex_name = "SHIFT"
},
{
.sdl2_id = 27, .sdl2_name = "echap",
.vhex_id = VKEY_EXIT, .vhex_name = "EXIT"
},
{
.sdl2_id = 8, .sdl2_name = "backspace",
.vhex_id = VKEY_DEL, .vhex_name = "DEL"
},
{
.sdl2_id = 9, .sdl2_name = "tab",
.vhex_id = VKEY_MENU, .vhex_name = "MENU"
},
};
@ -52,14 +102,14 @@ static int sdl_keycache_event_pop(vkey_event_t *event)
SDL_Event evt;
int ret;
if (event == NULL)
return -1;
while (1)
{
ret = SDL_PollEvent(&evt);
if (ret == 0) {
event->key = VKEY_NONE;
if (event != NULL) {
event->key = VKEY_NONE;
event->type = VKEYEV_NONE;
}
return 0;
}
@ -72,9 +122,13 @@ static int sdl_keycache_event_pop(vkey_event_t *event)
if (evt.key.keysym.sym != key_translation[i].sdl2_id)
continue;
event->time = 0;
event->type = (evt.type == SDL_KEYDOWN) ? VKEYEV_DOWN : VKEYEV_UP;
event->key = key_translation[i].vhex_id;
if (event != NULL) {
event->time = 0;
event->key = key_translation[i].vhex_id;
event->type = VKEYEV_DOWN;
if (evt.type == SDL_KEYDOWN)
event->type = VKEYEV_UP;
}
return 1;
}
}
@ -88,8 +142,18 @@ static int sdl_keycache_event_pop(vkey_event_t *event)
/* __keysc_configure() : configure the keyboard module */
static void __keysc_configure(void)
{
// Nothing to do, this is a fake driver
;
printf("[drv] keyboard: keymap notes:\n");
printf(" +-------------+-------------+\n");
printf(" | OS | Vhex |\n");
printf(" +-------------+-------------+\n");
for (int i = 0; i < __SDL2_KEYCODE_SUPPORTED; ++i) {
printf(
" | %-11s | %-11s |\n",
key_translation[i].sdl2_name,
key_translation[i].vhex_name
);
}
printf(" +-------------+-------------+\n");
}
/* __keysc_hsave() : save hardware information */

View File

@ -0,0 +1,72 @@
#include <vhex/rtc.h>
#include <vhex/rtc/interface.h>
#include <vhex/driver.h>
#include <time.h>
#include <stdio.h>
/* sdl_rtc_get_time(): Read the current time from the RTC */
int sdl_rtc_get_time(rtc_time_t *rtc)
{
time_t rtime;
struct tm *tinfo;
if (rtc == NULL)
return -1;
time(&rtime);
tinfo = localtime(&rtime);
rtc->ticks = 0;
rtc->seconds = tinfo->tm_sec;
rtc->minutes = tinfo->tm_min;
rtc->hours = tinfo->tm_hour;
rtc->month_day = tinfo->tm_mday;
rtc->month = tinfo->tm_mon;
rtc->year = tinfo->tm_year + 1900;
rtc->week_day = tinfo->tm_wday;
return 0;
}
//---
// Fake driver definition
//---
/* __rtc_configure() : configure the RTC */
static void __rtc_configure(void)
{
// Nothing to do, this is a fake driver
printf("[drv] RTC: fake driver initialized\n");
}
/* __rtc_hsave() : save hardware information */
static void __rtc_hsave(void)
{
// Nothing to do, this is a fake driver
;
}
/* __rtc_hrestore() : restore hardware information */
static void __rtc_hrestore(void)
{
// Nothing to do, this is a fake driver
;
}
struct vhex_driver drv_rtc = {
.name = "SDL2 RTC",
.hsave = (void*)&__rtc_hsave,
.hrestore = (void*)&__rtc_hrestore,
.configure = (void*)&__rtc_configure,
.state_size = 4,
.flags = {
.RTC = 1,
.SHARED = 0,
.UNUSED = 0,
},
.module_data = &(struct rtc_drv_interface){
.rtc_get_time = &sdl_rtc_get_time,
.rtc_set_time = NULL,
}
};
VHEX_DECLARE_DRIVER(06, drv_rtc);

View File

@ -222,6 +222,7 @@ void sdl_tmu_fps_quit(fps_t *fps)
static void __tmu_configure(void)
{
printf("[drv] TMU: fake driver initialized\n");
for (int i = 0; i < 9; ++i) {
timer_cache[i].used = false;
timer_cache[i].id = 0;

View File

@ -37,18 +37,37 @@ int sdl_frame_frag_next(dsurface_t *surface)
int sdl_frame_frag_send(dsurface_t *surface)
{
SDL_SetWindowSize(__sdl_window, 396, 224);
SDL_SetWindowSize(__sdl_window, 396 * 2, 224 * 2);
SDL_Surface *src = SDL_CreateRGBSurface(
0, 396, 224, 24,
0, 396 * 2, 224 * 2, 24,
0x000000ff, 0x0000ff00, 0x0000ff00, 0
);
uint16_t *vram = surface->vram;
uint8_t *display = src->pixels;
for (int i = 0; i < 396 * 224; ++i){
display[(i * 3) + 0] = (((vram[i] & 0xf800) >> 11) * 255) / 31;
display[(i * 3) + 1] = (((vram[i] & 0x07e0) >> 5) * 255) / 63;
display[(i * 3) + 2] = (((vram[i] & 0x001f) >> 0) * 255) / 31;
uint8_t *disp = src->pixels;
int r;
int g;
int b;
off_t yoff = 0;
for (int y = 0 ; y < 224; ++y) {
for (int x = 0; x < 396 ; ++x) {
r = (((vram[(y * 396) + x] & 0xf800) >> 11) * 255) / 31;
g = (((vram[(y * 396) + x] & 0x07e0) >> 5) * 255) / 63;
b = (((vram[(y * 396) + x] & 0x001f) >> 0) * 255) / 31;
disp[yoff + (x * 6) + 0] = r;
disp[yoff + (x * 6) + 1] = g;
disp[yoff + (x * 6) + 2] = b;
disp[yoff + (x * 6) + 3] = r;
disp[yoff + (x * 6) + 4] = g;
disp[yoff + (x * 6) + 5] = b;
}
memcpy(&disp[yoff + (396 * 6)], &disp[yoff], 396 * 6);
yoff += 396 * 6;
yoff += 396 * 6;
}
SDL_Surface *dst = SDL_GetWindowSurface(__sdl_window);
@ -72,13 +91,13 @@ int sdl_frame_end(dsurface_t *surface)
static int __sdl_configure(void)
{
printf("[drv] LCD: fake driver initialized\n");
__sdl_window = SDL_CreateWindow(
"vxKernel",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
396,
224,
396 * 2,
224 * 2,
0
);
return 0;