/******************************************* * Most Awesome Renderer Ever *******************************************/ #include "mare.h" namespace Render { Mare::Mare(dim_t size, ScreenRotation rot) : _screenSize(size), _screenBufferBackground(nullptr), _screenBufferForeground(nullptr), _rotation(rot), _full(true) { int rv; _bufferDim = (_screenSize.x >> 3) * _screenSize.y; _screenBufferBackground = (uint8_t*)malloc(sizeof(uint8_t)* _bufferDim); _screenBufferForeground = (uint8_t*)malloc(sizeof(uint8_t)* _bufferDim); clearBuffer(_screenBufferForeground, _bufferDim, Color::White); clearBuffer(_screenBufferBackground, _bufferDim, Color::White); // init display sleep_ms(500); if((rv=DEV_Module_Init())!=0){ printf("Init Failed, %d\n",rv); __breakpoint(); return; } EPD_2IN9_V2_Init(); EPD_2IN9_V2_Clear(); printf("Mare render engine created\n"); EPD_2IN9_V2_Display(_screenBufferBackground); sleep_ms(500); } Mare::~Mare(){ for (auto &d :_drawables) { d.reset(); } for (auto &p : _pages){ p.reset(); } free(_screenBufferBackground); free(_screenBufferForeground); } void Mare::render() { clearBuffer(_screenBufferBackground, _bufferDim, Color::White); for (auto d: _drawables) { if (d != nullptr) d->render(); }; if (!_full) EPD_2IN9_V2_Display_Partial(_screenBufferBackground); else { EPD_2IN9_V2_Display(_screenBufferBackground); _full = false; } } void Mare::clearBuffer(uint8_t* buffer, uint16_t len, Color col){ assert(buffer != nullptr); std::memset(buffer, col == Color::White ? 0xff : 0x00, len); } bool Mare::applyScreenRotation(uint16_t* x, uint16_t* y) { uint16_t ax,ay; switch(_rotation){ case ScreenRotation::Rot0 : { break; } case ScreenRotation::Rot90 : { ax = *x; ay = *y; *x = _screenSize.x - ay; *y = ax; break; } case ScreenRotation::Rot180 : { ax = *x; ay = *y; *x = _screenSize.x - ax; *y = _screenSize.y - ay; break; } case ScreenRotation::Rot270 : { ax = *x; ay = *y; *x = ay; *y = _screenSize.y - ax; break; } } if (*x >= _screenSize.x || *y >= _screenSize.y) return false; if (*x < 0 || *y < 0) return false; return true; } // Public const dim_t Mare::getCenter() { dim_t rv; if (_rotation == ScreenRotation::Rot0 || _rotation == ScreenRotation::Rot180){ rv.x = _screenSize.x >> 1; rv.y = _screenSize.y >> 1; } else { rv.x = _screenSize.y >> 1; rv.y = _screenSize.x >> 1; } return rv; } void Mare::setPixel(uint8_t* img, uint16_t x, uint16_t y, BlendMode bm) { if (!applyScreenRotation(&x,&y)) return; // from here the coordinates are natural for the screen img += (sizeof(uint8_t)*y*(_screenSize.x>>3) + sizeof(uint8_t)*(x>>3)); if (bm == BlendMode::Add) *img &= ~(0x80 >> (x%8)); else if (bm == BlendMode::Intersect) *img = ~*img ^ ~(0x80 >> (x%8)); } pos_t Mare::rotateXY(int16_t x, int16_t y, float rot){ // apply rotation matrix xy pos_t rv; float cx,sx; sincosf(rot, &sx, &cx); rv.x = x*cx - y*sx; rv.y = x*sx + y*cx; return rv; } void Mare::clearScreen() { EPD_2IN9_V2_Clear(); clearBuffer(_screenBufferBackground, _bufferDim, Color::White); _full = true; } }