add support for NEMU
This commit is contained in:
parent
131f308ca1
commit
7f20619e00
|
@ -72,9 +72,11 @@ public:
|
|||
virtual void update_gui();
|
||||
virtual void update_state();
|
||||
};
|
||||
|
||||
#ifdef MODE_NEMU
|
||||
void init_components(SDL_Renderer *renderer, uint32_t* vmem, int MODE800x600);
|
||||
#else
|
||||
void init_components(SDL_Renderer *renderer);
|
||||
|
||||
#endif
|
||||
void delete_components();
|
||||
|
||||
#define GET_SEGA(i) (output_pin(int(output_pin::SEG0A) + 8 * i))
|
||||
|
|
|
@ -34,4 +34,6 @@
|
|||
|
||||
//#define VSYNC
|
||||
|
||||
#define MODE_NEMU
|
||||
|
||||
#endif
|
|
@ -32,6 +32,7 @@ class KEYBOARD : public Component{
|
|||
KEYBOARD(SDL_Renderer *rend, int cnt, int init_val, int it, int ct);
|
||||
~KEYBOARD();
|
||||
void push_key(uint8_t scancode, bool is_keydown);
|
||||
uint8_t pop_key(bool* succ);
|
||||
virtual void update_state();
|
||||
};
|
||||
|
||||
|
|
|
@ -2,10 +2,43 @@
|
|||
#define VFPGA_RENDER_H
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <vga.h>
|
||||
#include <configs.h>
|
||||
|
||||
#define WINDOW_WIDTH 640
|
||||
#define WINDOW_HEIGHT 480
|
||||
#ifdef MODE_NEMU
|
||||
#define WINDOW_WIDTH 800
|
||||
#define WINDOW_HEIGHT 600
|
||||
|
||||
#define SWITCH_X 100
|
||||
#define SWITCH_Y 400
|
||||
#define SWITCH_SEP 10
|
||||
#define SWITCH_WIDTH 20
|
||||
#define SWITCH_HEIGHT 40
|
||||
|
||||
#define BTNC_X 650
|
||||
#define BTNC_Y 200
|
||||
#define BTNC_SEP 20
|
||||
#define BTNC_WIDTH 20
|
||||
#define BTNC_HEIGHT 20
|
||||
|
||||
#define LED_X 105
|
||||
#define LED_Y 360
|
||||
#define LED_SEP 20
|
||||
#define LED_WIDTH 10
|
||||
#define LED_HEIGHT 4
|
||||
|
||||
#define SEG_X 100
|
||||
#define SEG_Y 240
|
||||
|
||||
#define SEG_VER_WIDTH 2
|
||||
#define SEG_VER_HEIGHT 40
|
||||
#define SEG_HOR_WIDTH 40
|
||||
#define SEG_HOR_HEIGHT 2
|
||||
#define SEG_DOT_WIDTH SEG_VER_WIDTH
|
||||
#define SEG_DOT_HEIGHT SEG_HOR_HEIGHT
|
||||
#else
|
||||
#define WINDOW_WIDTH VGA_DEFAULT_WIDTH
|
||||
#define WINDOW_HEIGHT VGA_DEFAULT_HEIGHT
|
||||
#define SWITCH_X 80
|
||||
#define SWITCH_Y 400
|
||||
#define SWITCH_SEP 10
|
||||
|
@ -33,6 +66,8 @@
|
|||
#define SEG_HOR_HEIGHT 2
|
||||
#define SEG_DOT_WIDTH SEG_VER_WIDTH
|
||||
#define SEG_DOT_HEIGHT SEG_HOR_HEIGHT
|
||||
#endif
|
||||
|
||||
|
||||
#define SEG_SEP 2
|
||||
|
||||
|
|
|
@ -4,12 +4,13 @@
|
|||
#include <component.h>
|
||||
#include <constrs.h>
|
||||
#include <SDL2/SDL.h>
|
||||
#include <nvboard.h>
|
||||
|
||||
#define VGA_DEFAULT_WIDTH 640
|
||||
#define VGA_DEFAULT_HEIGHT 480
|
||||
|
||||
enum { //VGA_MOD_ID
|
||||
VGA_MODE_640_480, NR_VGA_MODE
|
||||
VGA_MODE_640_480, VGA_MODE_800_600, NR_VGA_MODE
|
||||
};
|
||||
|
||||
struct VGA_MODE{
|
||||
|
@ -25,7 +26,11 @@ private:
|
|||
int vga_pre_clk, vga_pre_vsync, vga_pre_hsync;
|
||||
int vga_vaddr, vga_haddr;
|
||||
public:
|
||||
#ifdef MODE_NEMU
|
||||
VGA(SDL_Renderer *rend, int cnt, int init_val, int it, int ct, uint32_t* vmem, int MODE800x600);
|
||||
#else
|
||||
VGA(SDL_Renderer *rend, int cnt, int init_val, int it, int ct);
|
||||
#endif
|
||||
~VGA();
|
||||
|
||||
virtual void update_gui();
|
||||
|
|
|
@ -157,6 +157,114 @@ SDL_Rect operator+(const SDL_Rect &A, const SDL_Rect &B) {
|
|||
|
||||
SDL_Texture *segs_texture(int index, int val);
|
||||
|
||||
#ifdef MODE_NEMU
|
||||
void init_components(SDL_Renderer *renderer, uint32_t* vmem, int MODE800x600) {
|
||||
Component *ptr = nullptr;
|
||||
SDL_Rect *rect_ptr = nullptr;
|
||||
|
||||
// init buttons
|
||||
for (int i = 0; i < 6; ++i) {
|
||||
ptr = new Component(renderer, 2, 0, INPUT_TYPE, BUTTON_TYPE);
|
||||
|
||||
// off
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = btn_rects[i];
|
||||
ptr->set_rect(rect_ptr, 0);
|
||||
ptr->set_texture(tbutton_off, 0);
|
||||
|
||||
// on
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = btn_rects[i];
|
||||
ptr->set_rect(rect_ptr, 1);
|
||||
ptr->set_texture(tbutton_on, 1);
|
||||
|
||||
ptr->add_input(input_pin(int(input_pin::BTNC) + i));
|
||||
components.push_back(ptr);
|
||||
}
|
||||
|
||||
// init switches
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
ptr = new Component(renderer, 2, 0, INPUT_TYPE, SWICTH_TYPE);
|
||||
|
||||
// off
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = (SDL_Rect){SWITCH_X + (15 - i) * (SWITCH_WIDTH + SWITCH_SEP), SWITCH_Y, SWITCH_WIDTH, SWITCH_HEIGHT};
|
||||
ptr->set_rect(rect_ptr, 0);
|
||||
ptr->set_texture(tswitch_off, 0);
|
||||
|
||||
// on
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = (SDL_Rect){SWITCH_X + (15 - i) * (SWITCH_WIDTH + SWITCH_SEP), SWITCH_Y, SWITCH_WIDTH, SWITCH_HEIGHT};
|
||||
ptr->set_rect(rect_ptr, 1);
|
||||
ptr->set_texture(tswitch_on, 1);
|
||||
|
||||
ptr->add_input(input_pin(int(input_pin::SW0) + i));
|
||||
components.push_back(ptr);
|
||||
}
|
||||
|
||||
// init naive leds
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
ptr = new Component(renderer, 2, 0, OUTPUT_TYPE, NAIVE_LED_TYPE);
|
||||
|
||||
// off
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = (SDL_Rect){LED_X + (15 - i) * (LED_WIDTH + LED_SEP), LED_Y, LED_WIDTH, LED_HEIGHT};
|
||||
ptr->set_rect(rect_ptr, 0);
|
||||
ptr->set_texture(tled_off, 0);
|
||||
|
||||
// on
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = (SDL_Rect){LED_X + (15 - i) * (LED_WIDTH + LED_SEP), LED_Y, LED_WIDTH, LED_HEIGHT};
|
||||
ptr->set_rect(rect_ptr, 1);
|
||||
ptr->set_texture(tled_g, 1);
|
||||
|
||||
ptr->add_output(output_pin(int(output_pin::LD0) + i));
|
||||
components.push_back(ptr);
|
||||
}
|
||||
|
||||
// init 7-segment display
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
SDL_Rect mv = {(7 - i) * (SEG_HOR_WIDTH + SEG_DOT_WIDTH + SEG_SEP * 4), 0, 0, 0};
|
||||
ptr = new SEGS7(renderer, 16, 0x5555, OUTPUT_TYPE, SEGS7_TYPE);
|
||||
for (int j = 0; j < 8; ++j) {
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = mv + segs_rect[j];
|
||||
ptr->set_texture(segs_texture(j, 0), j << 1 | 0);
|
||||
ptr->set_rect(rect_ptr, j << 1 | 0);
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = mv + segs_rect[j];
|
||||
ptr->set_texture(segs_texture(j, 1), j << 1 | 1);
|
||||
ptr->set_rect(rect_ptr, j << 1 | 1);
|
||||
}
|
||||
|
||||
for (output_pin p = GET_SEGA(i); p <= GET_DECP(i); p = output_pin(int(p) + 1)) {
|
||||
ptr->add_output(p);
|
||||
}
|
||||
components.push_back(ptr);
|
||||
}
|
||||
|
||||
#ifdef VGA_ENA
|
||||
// init vga
|
||||
ptr = new VGA(renderer, 1, 0, OUTPUT_TYPE, VGA_TYPE, vmem, MODE800x600);
|
||||
rect_ptr = new SDL_Rect;
|
||||
*rect_ptr = (SDL_Rect){WINDOW_WIDTH, 0, WINDOW_WIDTH, WINDOW_HEIGHT};
|
||||
ptr->set_rect(rect_ptr, 0);
|
||||
for (output_pin p = output_pin::VGA_CLK; p <= output_pin::VGA_B7; p = output_pin(int(p) + 1)) {
|
||||
ptr->add_output(p);
|
||||
}
|
||||
components.push_back(ptr);
|
||||
#endif
|
||||
|
||||
// init keyboard
|
||||
extern KEYBOARD* kb;
|
||||
kb = new KEYBOARD(renderer, 0, 0, INPUT_TYPE, KEYBOARD_TYPE);
|
||||
for (input_pin p = input_pin::PS2_CLK; p <= input_pin::PS2_DAT; p = input_pin(int(p) + 1)){
|
||||
kb->add_input(p);
|
||||
}
|
||||
// components.push_back(kb);
|
||||
|
||||
}
|
||||
#else
|
||||
void init_components(SDL_Renderer *renderer) {
|
||||
Component *ptr = nullptr;
|
||||
SDL_Rect *rect_ptr = nullptr;
|
||||
|
@ -263,6 +371,7 @@ void init_components(SDL_Renderer *renderer) {
|
|||
// components.push_back(kb);
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
void delete_components() {
|
||||
for (auto comp_ptr : components) {
|
||||
|
|
|
@ -31,6 +31,10 @@ KEYBOARD::KEYBOARD(SDL_Renderer *rend, int cnt, int init_val, int it, int ct):
|
|||
|
||||
|
||||
void KEYBOARD::push_key(uint8_t sdl_key, bool is_keydown){
|
||||
#ifdef MODE_NEMU
|
||||
all_keys.push(sdl_key);
|
||||
all_keys.push(is_keydown);
|
||||
#else
|
||||
uint8_t at_key = sdl2at(sdl_key, 1);
|
||||
if(at_key == 0xe0){
|
||||
all_keys.push(0xe0);
|
||||
|
@ -38,8 +42,14 @@ void KEYBOARD::push_key(uint8_t sdl_key, bool is_keydown){
|
|||
}
|
||||
if(!is_keydown) all_keys.push(0x0f);
|
||||
all_keys.push(at_key);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef MODE_NEMU
|
||||
void KEYBOARD::update_state(){
|
||||
|
||||
}
|
||||
#else
|
||||
void KEYBOARD::update_state(){
|
||||
if(cur_key == NOT_A_KEY){
|
||||
if(all_keys.empty()) return;
|
||||
|
@ -68,4 +78,16 @@ void KEYBOARD::update_state(){
|
|||
else{
|
||||
left_clk --;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t KEYBOARD::pop_key(bool* succ){
|
||||
if(all_keys.empty()) {
|
||||
*succ = false;
|
||||
return 0;
|
||||
}
|
||||
*succ = true;
|
||||
uint8_t top = all_keys.front();
|
||||
all_keys.pop();
|
||||
return top;
|
||||
}
|
|
@ -78,6 +78,73 @@ static void nvboard_update_all_output() {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef MODE_NEMU
|
||||
extern "C" {
|
||||
void nvboard_update() {
|
||||
|
||||
if(render_flag) {
|
||||
update_components(main_renderer);
|
||||
SDL_RenderPresent(main_renderer);
|
||||
render_flag = false;
|
||||
}
|
||||
|
||||
nvboard_event_handler();
|
||||
}
|
||||
|
||||
uint8_t nvboard_get_key(bool* succ){
|
||||
extern KEYBOARD* kb;
|
||||
return kb->pop_key(succ);
|
||||
}
|
||||
|
||||
void nvboard_init(uint32_t* vmem, int MODE800x600) {
|
||||
printf("nvboard v0.2\n");
|
||||
// init SDL and SDL_image
|
||||
SDL_Init(SDL_INIT_TIMER | SDL_INIT_VIDEO | SDL_INIT_EVENTS);
|
||||
IMG_Init(IMG_INIT_PNG);
|
||||
|
||||
main_window = SDL_CreateWindow("nvboard", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH * 2, WINDOW_HEIGHT, SDL_WINDOW_SHOWN);
|
||||
main_renderer = SDL_CreateRenderer(main_window, -1,
|
||||
#ifdef VSYNC
|
||||
SDL_RENDERER_PRESENTVSYNC |
|
||||
#endif
|
||||
#ifdef HARDWARE_ACC
|
||||
SDL_RENDERER_ACCELERATED |
|
||||
#else
|
||||
SDL_RENDERER_SOFTWARE |
|
||||
#endif
|
||||
0
|
||||
);
|
||||
|
||||
nvboard_home = getenv("NVBOARD_HOME");
|
||||
|
||||
load_background(main_renderer);
|
||||
load_texture(main_renderer);
|
||||
init_components(main_renderer, vmem, MODE800x600);
|
||||
init_gui(main_renderer);
|
||||
|
||||
update_components(main_renderer);
|
||||
struct sigaction s;
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.sa_handler = alarm_sig_handler;
|
||||
int ret = sigaction(SIGVTALRM, &s, NULL);
|
||||
assert(ret == 0);
|
||||
|
||||
struct itimerval it = {};
|
||||
it.it_value.tv_sec = 0;
|
||||
it.it_value.tv_usec = 1000000 / 60;
|
||||
it.it_interval = it.it_value;
|
||||
ret = setitimer(ITIMER_VIRTUAL, &it, NULL);
|
||||
assert(ret == 0);
|
||||
}
|
||||
void nvboard_quit(){
|
||||
delete_components();
|
||||
SDL_DestroyWindow(main_window);
|
||||
SDL_DestroyRenderer(main_renderer);
|
||||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
}
|
||||
}
|
||||
#else
|
||||
void nvboard_update() {
|
||||
nvboard_update_all_input();
|
||||
nvboard_update_all_output();
|
||||
|
@ -148,6 +215,7 @@ void nvboard_quit(){
|
|||
IMG_Quit();
|
||||
SDL_Quit();
|
||||
}
|
||||
#endif
|
||||
|
||||
void nvboard_bind_pin(vector<output_pin> &pin, void *signal) {
|
||||
output_pin_map[signal] = pin;
|
||||
|
|
38
src/vga.cpp
38
src/vga.cpp
|
@ -2,7 +2,9 @@
|
|||
#include <nvboard.h>
|
||||
#include <macro.h>
|
||||
#include <assert.h>
|
||||
#include <configs.h>
|
||||
|
||||
// http://tinyvga.com/vga-timing/800x600@60Hz
|
||||
VGA_MODE vga_mod_accepted[NR_VGA_MODE] = {
|
||||
[VGA_MODE_640_480] = {
|
||||
.h_frontporch = 96,
|
||||
|
@ -14,9 +16,31 @@ VGA_MODE vga_mod_accepted[NR_VGA_MODE] = {
|
|||
.v_backporch = 515,
|
||||
.v_total = 525,
|
||||
},
|
||||
[VGA_MODE_800_600] = {
|
||||
.h_frontporch = 128,
|
||||
.h_active = 216,
|
||||
.h_backporch = 1016,
|
||||
.h_total = 1056,
|
||||
.v_frontporch = 4,
|
||||
.v_active = 27,
|
||||
.v_backporch = 627,
|
||||
.v_total = 628,
|
||||
},
|
||||
};
|
||||
|
||||
VGA::VGA(SDL_Renderer *rend, int cnt, int init_val, int it, int ct):
|
||||
#ifdef MODE_NEMU
|
||||
VGA::VGA(SDL_Renderer *rend, int cnt, int init_val, int it, int ct, uint32_t* vmem, int MODE800x600):
|
||||
Component(rend, cnt, init_val, it, ct),
|
||||
vga_screen_width(MODE800x600? 800: 400), vga_screen_height(MODE800x600? 600:300),
|
||||
vga_pre_clk(0), vga_pre_hsync(0), vga_pre_vsync(0),
|
||||
vga_pos(0), vga_vaddr(0), vga_haddr(0) {
|
||||
SDL_Texture *temp_texture = SDL_CreateTexture(rend, SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STATIC, vga_screen_width, vga_screen_height);
|
||||
set_texture(temp_texture, 0);
|
||||
pixels = vmem;
|
||||
}
|
||||
#else
|
||||
VGA::VGA(SDL_Renderer *rend, int cnt, int init_val, int it, int ct):
|
||||
Component(rend, cnt, init_val, it, ct),
|
||||
vga_screen_width(VGA_DEFAULT_WIDTH), vga_screen_height(VGA_DEFAULT_HEIGHT),
|
||||
vga_pre_clk(0), vga_pre_hsync(0), vga_pre_vsync(0),
|
||||
|
@ -27,16 +51,21 @@ VGA::VGA(SDL_Renderer *rend, int cnt, int init_val, int it, int ct):
|
|||
pixels = new uint32_t[vga_screen_width * vga_screen_height];
|
||||
memset(pixels, 0, vga_screen_width * vga_screen_height * sizeof(uint32_t));
|
||||
}
|
||||
#endif
|
||||
|
||||
VGA::~VGA() {
|
||||
SDL_DestroyTexture(get_texture(0));
|
||||
#ifndef MODE_NEMU
|
||||
delete []pixels;
|
||||
#endif
|
||||
}
|
||||
|
||||
void VGA::update_gui() {
|
||||
#ifndef MODE_NEMU
|
||||
static int frames = 0;
|
||||
frames ++;
|
||||
printf("%d frames\n", frames);
|
||||
#endif
|
||||
SDL_Texture *temp_texture = get_texture(0);
|
||||
SDL_Renderer *temp_renderer = get_renderer();
|
||||
SDL_Rect *temp_rect = get_rect(0);
|
||||
|
@ -45,6 +74,12 @@ void VGA::update_gui() {
|
|||
SDL_RenderCopy(temp_renderer, temp_texture, NULL, temp_rect);
|
||||
}
|
||||
|
||||
#ifdef MODE_NEMU
|
||||
void VGA::update_state() {
|
||||
update_gui();
|
||||
}
|
||||
#else
|
||||
|
||||
void VGA::update_state() {
|
||||
int vga_clk = output_map[output_pin::VGA_CLK];
|
||||
int vga_vsync = output_map[output_pin::VGA_VSYNC];
|
||||
|
@ -91,3 +126,4 @@ void VGA::update_state() {
|
|||
vga_pre_vsync = vga_vsync;
|
||||
vga_pre_clk = vga_clk;
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue