#ifdef SDL2_BUILD #include "display.hpp" #include "../../buttons.hpp" #include "pico/types.h" #include #include #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. Integer 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, it'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); } SDLDisplay::~SDLDisplay() { SDL_DestroyTexture(m_texture); SDL_DestroyRenderer(m_renderer); SDL_DestroyWindow(m_window); SDL_Quit(); } bool SDLDisplay::process_input() { 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; } } return m_should_quit; } bool SDLDisplay::update_display(const uint8_t* oled_screen) { // 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 m_should_quit; } bool SDLDisplay::get_datetime(datetime_t* t) { // Get current date and time time_t rawtime; struct tm* timeinfo; time(&rawtime); timeinfo = localtime(&rawtime); // Map ISO C tm struct to Pico's datetime_t t->day = timeinfo->tm_mday; t->dotw = timeinfo->tm_wday; t->month = timeinfo->tm_mon; t->year = timeinfo->tm_year + 1900; t->hour = timeinfo->tm_hour; t->min = timeinfo->tm_min; t->sec = timeinfo->tm_sec; return true; } 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); } } // Get the GPIO pin number corresponding to the button that has been pressed 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