diff options
Diffstat (limited to 'hal/sdl2/display.cpp')
-rw-r--r-- | hal/sdl2/display.cpp | 137 |
1 files changed, 137 insertions, 0 deletions
diff --git a/hal/sdl2/display.cpp b/hal/sdl2/display.cpp new file mode 100644 index 0000000..ecb6870 --- /dev/null +++ b/hal/sdl2/display.cpp @@ -0,0 +1,137 @@ +#ifdef SDL2_BUILD +#include <SDL.h> +#include "display.hpp" +#include "../../buttons.hpp" +#include <iostream> + +#define SCREEN_HEIGHT 64 +#define SCREEN_WIDTH 128 + +SDLDisplay::SDLDisplay() { + SDL_Init(SDL_INIT_VIDEO); + SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0"); + /* scale here to make the window larger than the surface itself. + Int*eger scalings only as set by function below. */ + m_window = SDL_CreateWindow("SDL2 pico-watch build", SDL_WINDOWPOS_UNDEFINED, + SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, 0); + if (m_window == nullptr) { + SDL_Log("Unable to create renderer: %s", SDL_GetError()); + m_should_quit = true; + return; + } + + m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_PRESENTVSYNC); + if (m_renderer == nullptr) { + SDL_Log("Unable to create renderer: %s", SDL_GetError()); + m_should_quit = true; + return; + } + + const int width = SCREEN_WIDTH; + const int height = SCREEN_HEIGHT; + + /* Since we are going to display a low resolution buffer, + i t i*s best to limit the window size so that it cannot be + smaller than our internal buffer size. */ + SDL_SetWindowMinimumSize(m_window, width, height); + SDL_RenderSetLogicalSize(m_renderer, width, height); + SDL_RenderSetIntegerScale(m_renderer, SDL_bool(1)); + + /* A one-bit-per-pixel Surface, indexed to these colors */ + m_surface = SDL_CreateRGBSurfaceWithFormat(SDL_SWSURFACE, + width, height, 1, SDL_PIXELFORMAT_INDEX1MSB); + SDL_Color colors[2] = {{0, 0, 0, 255}, {255, 255, 255, 255}}; + SDL_SetPaletteColors(m_surface->format->palette, colors, 0, 2); +} + +bool SDLDisplay::update_display(const uint8_t* oled_screen) { + if (m_should_quit) return true; + + SDL_Event e; + while (SDL_PollEvent(&e) != 0) { + switch (e.type) { + case SDL_QUIT: + m_should_quit = true; + break; + case SDL_KEYDOWN: + case SDL_KEYUP: + uint button = get_button(e.key.keysym.sym); + if (button) + gpio_interrupt_cb(button, e.type == SDL_KEYDOWN); + break; + } + } + + // NOTE: hardcoded display size (might be fine, see todo.md and oledWriteDataBlock in ss_oled.c) + // memcpy(m_surface->pixels, oled_screen, (size_t)(128*8)); + convert_display(oled_screen); + + // render on screen + SDL_RenderClear(m_renderer); + SDL_Texture* screen_texture = SDL_CreateTextureFromSurface(m_renderer, m_surface); + SDL_RenderCopy(m_renderer, screen_texture, NULL, NULL); + SDL_RenderPresent(m_renderer); + SDL_DestroyTexture(screen_texture); + return false; +} + +SDLDisplay::~SDLDisplay() { + SDL_DestroyTexture(m_texture); + SDL_DestroyRenderer(m_renderer); + SDL_DestroyWindow(m_window); + SDL_Quit(); +} + +unsigned char rorb(unsigned char x, unsigned char n) { + return __rorb(x,n); +} + +unsigned char rolb(unsigned char x, unsigned char n) { + return __rolb(x,n); +} + +void SDLDisplay::convert_display(const uint8_t* in) { + unsigned char* out = (unsigned char*)m_surface->pixels; + // clear screen + for (int i = 0; i < 8*128; ++i) + out[i] = 0x00; + + // draw to screen + for (int i = 0; i < 8*128; ++i) { + int row = i / 128; // "super-row" consisting of 8 subrows + int col = i % 128; + + // create a column of a subrow + // int subrow represents which bit of byte i + for (int subrow = 0; subrow < 8; ++subrow) + // OR instead of XOR seems to do exactly the same thing? + out[col/8 + (row*8 + subrow)*16] ^= rorb( + (bool)(in[i] & rolb(1, subrow)), (col % 8) + 1); + } +} + +uint SDLDisplay::get_button(SDL_Keycode key) { + switch (key) { + case SDLK_w: + case SDLK_UP: + return BUTTON_UP; + case SDLK_s: + case SDLK_DOWN: + return BUTTON_DOWN; + case SDLK_RETURN: + case SDLK_o: + return BUTTON_SELECT; + case SDLK_TAB: + case SDLK_m: + return BUTTON_MODE; + case SDLK_BACKSPACE: + case SDLK_h: + return BUTTON_HOME; + case SDLK_x: + m_testbool = !m_testbool; + default: + return 0; + } +} + +#endif |