138 lines
4.0 KiB
C++
138 lines
4.0 KiB
C++
/*******************************************
|
|
* 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;
|
|
}
|
|
|
|
} |