diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt index 22cbffe..154e8c3 100644 --- a/libs/CMakeLists.txt +++ b/libs/CMakeLists.txt @@ -1,4 +1,3 @@ #include e-Paper subdirectories add_subdirectory(epaper) add_subdirectory(mare) - diff --git a/libs/mare/CMakeLists.txt b/libs/mare/CMakeLists.txt index 096dc06..ffc8c94 100644 --- a/libs/mare/CMakeLists.txt +++ b/libs/mare/CMakeLists.txt @@ -10,4 +10,4 @@ include_directories(../epaper/Fonts) # Generate the link library add_library(Mare ${DIR_Config_SRCS}) -target_link_libraries(Mare PUBLIC Config ePaper Fonts pico_stdlib hardware_spi) \ No newline at end of file +target_link_libraries(Mare PUBLIC Config ePaper Fonts pico_stdlib pico_printf pico_mem_ops hardware_spi) \ No newline at end of file diff --git a/libs/mare/mare.cpp b/libs/mare/mare.cpp index fb96c41..4201ea1 100644 --- a/libs/mare/mare.cpp +++ b/libs/mare/mare.cpp @@ -19,14 +19,17 @@ namespace Render { clearBuffer(_screenBufferBackground, _bufferDim, Color::White); // init display - DEV_Delay_ms(500); + 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(){ @@ -45,7 +48,7 @@ namespace Render { for (auto d: _drawables) { if (d != nullptr) d->render(); - } + }; EPD_2IN9_V2_Display_Partial(_screenBufferBackground); } @@ -54,17 +57,15 @@ namespace Render { std::memset(buffer, col == Color::White ? 0xff : 0x00, len); } - bool Mare::applyRotation(uint16_t* x, uint16_t* y) { + bool Mare::applyScreenRotation(uint16_t* x, uint16_t* y) { uint16_t ax,ay; switch(_rotation){ case ScreenRotation::Rot0 : { - if (*x >= _screenSize.x || *y >= _screenSize.y) return false; break; } case ScreenRotation::Rot90 : { - if (*x >= _screenSize.y || *y >= _screenSize.x) return false; ax = *x; ay = *y; *x = _screenSize.x - ay; *y = ax; @@ -72,21 +73,20 @@ namespace Render { } case ScreenRotation::Rot180 : { - if (*x >= _screenSize.x || *y >= _screenSize.y) return false; ax = *x; ay = *y; *x = _screenSize.x - ax; - *y = _screenSize.y - ay; + *y = _screenSize.y - ay; break; } case ScreenRotation::Rot270 : { - if (*x >= _screenSize.y || *y >= _screenSize.x) return false; 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; } @@ -105,12 +105,22 @@ namespace Render { return rv; } - void Mare::setPixel(uint8_t* img, uint16_t x, uint16_t y, bool value) { - if (!applyRotation(&x,&y)) return; + 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 (value) *img &= ~(0x80 >> (x%8)); - else *img |= (0x80 >> (x%8)); + if (bm == BlendMode::Add) *img &= ~(0x80 >> (x%8)); + else if (bm == BlendMode::Intersect) *img = ~*img ^ ~(0x80 >> (x%8)); + } + + spos_t Mare::rotateXY(int16_t x, int16_t y, float rot){ + // apply rotation matrix xy + spos_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() { diff --git a/libs/mare/mare.h b/libs/mare/mare.h index 3889121..268d6cc 100644 --- a/libs/mare/mare.h +++ b/libs/mare/mare.h @@ -2,8 +2,10 @@ * Most Awesome Renderer Ever *******************************************/ -#include +//#include #include +#include +#include #include extern "C" { @@ -24,6 +26,11 @@ namespace Render{ uint16_t y; }; + struct spos_t { + int16_t x; + int16_t y; + }; + struct bbox2d_t { uint16_t xMin, Ymin; uint16_t Xmax, Ymax; @@ -92,12 +99,13 @@ namespace Render{ //render private: void clearBuffer(uint8_t* buffer, uint16_t len, Color col); - bool applyRotation(uint16_t* x, uint16_t* y); + bool applyScreenRotation(uint16_t* x, uint16_t* y); void visitDrawables(Drawable* parent) {}; public: void render(); - void setPixel(uint8_t* img, uint16_t x, uint16_t y, bool value); + void setPixel(uint8_t* img, uint16_t x, uint16_t y, BlendMode bm); + spos_t rotateXY(int16_t x, int16_t y, float rot); void clearScreen(); // members @@ -129,7 +137,7 @@ namespace Render{ void setOrigin(const pos_t origin) { _origin = origin; }; void setDirty() {_dirty = true;}; void resetDirty() {_dirty = false;}; - void setBlendMode(const BlendMode mode) { _blendMode = BlendMode::Intersect; }; + void setBlendMode(const BlendMode mode) { _blendMode = mode; }; const bool isDirty() {return _dirty;} const pos_t getOrigin() { return _origin; }; @@ -186,6 +194,8 @@ namespace Render{ const float getRotation() {return _rotation;}; void setLength(uint16_t length) {_lenght = length;}; const uint16_t getLength() {return _lenght;}; + void setOutline(bool outline) {_outline = outline;}; + const bool getOutline() {return _outline;}; private: void render(); // difficult business @@ -195,6 +205,7 @@ namespace Render{ uint16_t _thickness; uint16_t _lenght; float _rotation; + bool _outline; }; class DrawableRectangle: public Drawable { diff --git a/libs/mare/mare_drawables.cpp b/libs/mare/mare_drawables.cpp index b2b2e8d..83fd7e4 100644 --- a/libs/mare/mare_drawables.cpp +++ b/libs/mare/mare_drawables.cpp @@ -8,7 +8,7 @@ namespace Render { _engine(engine), _origin({0,0}), _bbox({0,0,0,0}), - _blendMode(Render::BlendMode::Intersect), + _blendMode(Render::BlendMode::Add), _dirty(false) { } @@ -32,6 +32,7 @@ namespace Render { void DrawablePoint::render() { uint8_t *buf; + pos_t o = getOrigin(); if (isDirty()){ buf = getBuffer(); //TODO: implement screen rotation and margin check @@ -40,7 +41,7 @@ namespace Render { for (uint16_t xx(0); xx< _size.x; xx++){ for (uint16_t yy(0); yy < _size.y; yy++) { - engine()->setPixel(buf,dx-(getOrigin().x+xx),getOrigin().y+yy,true); + engine()->setPixel(buf,o.x+xx,o.y+yy,getBlendMode()); } } resetDirty(); @@ -54,7 +55,8 @@ namespace Render { Drawable(id, parent,engine), _thickness(1), _lenght(0), - _rotation(0.0f) + _rotation(0.0f), + _outline(false) { } @@ -67,40 +69,55 @@ namespace Render { uint8_t* buf = getBuffer(); auto tt = _thickness; auto e = engine(); - auto square = [buf,e,tt](uint16_t x, uint16_t y){ - uint8_t c = tt > 1 ? tt>>1 : 0; //sprite render - x -= c; - y -= c; - for (auto xx(0); xx <= tt; ++xx) - for (auto yy(0); yy <= tt; ++yy){ - e->setPixel(buf,xx+x,yy+y,true); - } - }; + // auto square = [buf,e,tt](uint16_t x, uint16_t y){ + // uint8_t c = tt > 1 ? tt>>1 : 0; //sprite render + // x -= c; + // y -= c; + // for (auto xx(0); xx <= tt; ++xx) + // for (auto yy(0); yy <= tt; ++yy){ + // e->setPixel(buf,xx+x,yy+y,getBlendMode()); + // } + // }; - if (isDirty()) { - _rotation = fmod(_rotation, M_TWOPI); - float cx,sx; - sincosf(_rotation,&sx,&cx); // use optimized float instructions - uint16_t endX = fabs(round(cx*(float)_lenght)); - uint16_t endY = fabs(round(sx*(float)_lenght)); + // if (isDirty() && false) { + // _rotation = fmod(_rotation, M_TWOPI); + // float cx,sx; + // sincosf(_rotation,&sx,&cx); // use optimized float instructions + // uint16_t endX = fabs(round(cx*(float)_lenght)); + // uint16_t endY = fabs(round(sx*(float)_lenght)); - int8_t mult = (_rotation <= 3*M_PI_4 || _rotation >= 7*M_PI_4) ? 1 : -1; + // int8_t mult = (_rotation <= 3*M_PI_4 || _rotation >= 7*M_PI_4) ? 1 : -1; - if ((_rotation >= 7*M_PI_4 || _rotation <= M_PI_4) || - (_rotation >= 3*M_PI_4 && _rotation <= 5*M_PI_4)) { + // if ((_rotation >= 7*M_PI_4 || _rotation <= M_PI_4) || + // (_rotation >= 3*M_PI_4 && _rotation <= 5*M_PI_4)) { - for(uint16_t xx(0); xx <= endX; ++xx){ - float dydx = cx == 0.0f ? 0 : (sx/cx); - uint16_t y = getOrigin().y+xx*mult*dydx; - uint16_t x = getOrigin().x+xx*mult; - square(x,y); - } - } else { - for (uint16_t yy(0); yy <= endY; ++yy){ - float dxdy = sx == 0.0f ? 0 : (cx/sx); - uint16_t y = getOrigin().y+yy*mult; - uint16_t x = getOrigin().x+yy*mult*dxdy; - square(x,y); + // for(uint16_t xx(0); xx <= endX; ++xx){ + // float dydx = cx == 0.0f ? 0 : (sx/cx); + // uint16_t y = getOrigin().y+xx*mult*dydx; + // uint16_t x = getOrigin().x+xx*mult; + // square(x,y); + // } + // } else { + // for (uint16_t yy(0); yy <= endY; ++yy){ + // float dxdy = sx == 0.0f ? 0 : (cx/sx); + // uint16_t y = getOrigin().y+yy*mult; + // uint16_t x = getOrigin().x+yy*mult*dxdy; + // square(x,y); + // } + // } + // resetDirty(); + // } + + if (isDirty() && true) { + _rotation = fmod(_rotation, M_TWOPI); + pos_t o = getOrigin(); + static spos_t res = {0,0}; + for (uint16_t t(0); t < _thickness; ++t) { + for (uint16_t xx(0); xx < _lenght; ++xx) { + if (!_outline || (_outline && (xx == 0 || xx == _lenght - 1 || t == 0 || t == _thickness - 1))) { + res = e->rotateXY(xx,t-(_thickness>>1),_rotation); + e->setPixel(buf,res.x+o.x,res.y+o.y,getBlendMode()); + } } } resetDirty(); diff --git a/src/main.cpp b/src/main.cpp index be21ac9..aed056d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,7 +9,7 @@ int main(){ gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT); bool s=false; - uint i(2); + uint i(16); Render::dim_t ssize; ssize.x = EPD_2IN9_V2_WIDTH; ssize.y = EPD_2IN9_V2_HEIGHT; @@ -17,40 +17,39 @@ int main(){ auto viewer = Render::Mare(ssize, Render::ScreenRotation::Rot90); - Render::dim_t ps; ps.x=0; ps.y=0; - - auto line = viewer.addDrawable(); - auto line2 = viewer.addDrawable(); + auto c1 = viewer.addDrawable(); + auto c2 = viewer.addDrawable(); auto line3 = viewer.addDrawable(); - line->setOrigin(ps); - line->setLength(256); - line2->setLength(256); + c1->setOrigin({0,63}); + c1->setLength(296); + c1->setThickness(2); + c1->setBlendMode(Render::BlendMode::Add); + + c2->setOrigin({296/2-1, 1}); + c2->setLength(128); + c2->setRotation(M_PI_2); + c2->setThickness(2); + c1->setBlendMode(Render::BlendMode::Add); + line3->setLength(64); line3->setOrigin(viewer.getCenter()); + line3->setBlendMode(Render::BlendMode::Add); + line3->setOutline(false); + while (true){ - ps.x = ssize.y-i; - line2->setOrigin(ps); - line->setThickness(i); - line2->setThickness(i); line3->setThickness(i++); - for (float a(0); a<=M_TWOPI; a+=(M_TWOPI/90.0f)){ - line->setRotation(a); - line2->setRotation(M_PI-a); + for (float a(0); a<=M_TWOPI; a+=(M_TWOPI/36.0f)){ line3->setRotation(a); - line->setDirty(); - line2->setDirty(); line3->setDirty(); + c1->setDirty(); + c2->setDirty(); viewer.render(); - printf("Angle: %4.3f\n", a/M_PI*180.0f); } viewer.clearScreen(); - } - while(true){ + //line3->setOutline(s); gpio_put(LED_PIN,s); s = s ? false : true; - sleep_ms(500); } - return 0; } \ No newline at end of file