aboutsummaryrefslogtreecommitdiffstats
path: root/hal/sdl2/display.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'hal/sdl2/display.cpp')
-rw-r--r--hal/sdl2/display.cpp137
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