Skip to content

Commit

Permalink
added reusable MonchromeReader
Browse files Browse the repository at this point in the history
  • Loading branch information
TomSaw committed Aug 4, 2021
1 parent 3011530 commit ca9176d
Show file tree
Hide file tree
Showing 14 changed files with 309 additions and 499 deletions.
51 changes: 22 additions & 29 deletions src/modm/driver/display/ili9341.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,30 +109,20 @@ class Ili9341 : public Interface,
modm::ResumableResult<void>
writePattern(Rectangle rectangle, P pattern);

// Write equal colored Buffer (compiletime poly)
template<typename R_, class Painter_>
modm::ResumableResult<void>
writeBuffer(const Buffer<colorType, R_, Painter_> &buffer, Point origin = {0, 0});

// Write equal colored BufferInterface (runtime poly)
// Write equal colored BufferInterface
modm::ResumableResult<void>
writeBuffer(const BufferInterface<colorType> *buffer, Point origin = {0, 0});

// Write different colored Buffer (compiletime poly)
template<typename C_, typename R_, class Painter_>
// Write different colored BufferInterface
template<Color C_>
modm::ResumableResult<void>
writeBuffer(const Buffer<C_, R_, Painter_> &buffer, Point origin = {0, 0});
writeBuffer(const BufferInterface<C_> *buffer, Point origin = {0, 0});

// Write monochrome Buffer (compiletime poly)
template<typename R_, class Painter_>
modm::ResumableResult<void>
writeBuffer(const Buffer<bool, R_, Painter_> &buffer, Point origin = {0, 0});

// Write monochrome BufferInterface (runtime poly)
// Write monochrome BufferInterface
modm::ResumableResult<void>
writeBuffer(const BufferInterface<bool> *buffer, Point origin = {0, 0});

// Write monochrome Flash (runtime poly)
// Write monochrome Flash
modm::ResumableResult<void>
writeFlash(modm::accessor::Flash<uint8_t> data, uint16_t width, uint16_t height,
Point origin = {0, 0}) final;
Expand All @@ -159,6 +149,9 @@ class Ili9341 : public Interface,
protected:
modm::ResumableResult<void>
drawQuadPoints(Point center, Point point);
private:
// Static variables for resumable functions
Section section;
// ##################################################################

protected:
Expand All @@ -184,7 +177,12 @@ class Ili9341 : public Interface,
modm::ResumableResult<colorType>
getFast(Point point) const;

private:
// Static variables for resumable functions
void scannerNextRow() {
p.scanner.x++;
p.scanner.y = this->clipping.topLeft.y;
}
union {
// Buffers for commands & configuration
uint8_t buff_cmd8[15];
Expand All @@ -195,23 +193,18 @@ class Ili9341 : public Interface,
struct
{
uint16_t buff_cmd_clipping[2];
colorType buffer[BC]; // Primary Pixelbuffer
size_t i; // Current Index in Primary Pixelbuffer
Point scanner; // Current Index on Display

// Primary Pixelbuffer
colorType buffer[BC];
size_t buffer_i;

size_t pixels_to_write, pixel_bulk;

// Keep track of current position in
Point scanner;
ScannerBufferBool bool_scanner;
size_t pixels; // Pixels of whole transaction
size_t pixels_bulk; // Pixels of current bulk

MonochromeReader mono_reader; // Helper to read monochrome data

colorType temp_color;
colorType temp_color; // Temporary storage for a color
} p; // p for parallel
};

// BUG Static variables for resumable functions RemotePainter
Section section;
};

} // namespace modm
Expand Down
149 changes: 71 additions & 78 deletions src/modm/driver/display/ili9341_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ modm::Ili9341<Interface, Reset, BC>::updateClipping()
RF_CALL(this->writeCommand(Command::ColumnAddressSet, (uint8_t *)(p.buff_cmd_clipping), 4));

RF_CALL(this->writeCommand(Command::MemoryWrite));
p.pixels_to_write = this->clipping.getPixels();
p.pixels = this->clipping.getPixels();

RF_END();
}
Expand All @@ -248,111 +248,95 @@ modm::Ili9341<Interface, Reset, BC>::writePattern(Rectangle rectangle, P pattern

p.scanner = this->clipping.topLeft;

while (p.pixels_to_write)
while (p.pixels)
{
// Generate next bulk
for(p.buffer_i = 0; p.buffer_i < std::min<uint32_t>(p.pixels_to_write, BC); p.buffer_i++) {
for(p.i = 0; p.i < std::min<uint32_t>(p.pixels, BC); p.i++) {
// OPTIMIZE inefficient, cause pattern recalculates color for each pixel
// Let's investigate a solution
p.buffer[p.buffer_i] = pattern(p.scanner);

// Update scanner
// even when it could already know, under withc conditions the return-value changes!
// Need some kind of caching!?
p.buffer[p.i] = pattern(p.scanner);

if (++p.scanner.y == this->clipping.bottomRight.y) {
p.scanner.x++;
p.scanner.y = this->clipping.topLeft.y;
scannerNextRow();
}
}

// Transfer
RF_CALL(this->writeData((uint8_t *)(p.buffer), 2 * p.buffer_i));

p.pixels_to_write-= p.buffer_i;
RF_CALL(this->writeData((uint8_t *)(p.buffer), 2 * p.i));
p.pixels-= p.i;
}

RF_END();
}

// -- Write equal colored Buffer ----------------------------------
// -- Write equal colored BufferInterface -----------------------------
template<class Interface, class Reset, size_t BC>
template<typename R_, class Painter_>
modm::ResumableResult<void>
modm::Ili9341<Interface, Reset, BC>::writeBuffer(
const Buffer<colorType, R_, Painter_> &buffer, Point origin)
{
const BufferInterface<colorType> *buffer, Point origin) {
RF_BEGIN();

this->clipping = this->getIntersection(Rectangle(origin, R_::asPoint()));
this->clipping = this->getIntersection(Rectangle(origin, buffer->getSize()));
RF_CALL(updateClipping());

// FIXME take this->clipping into account
RF_CALL(this->writeData(buffer.getPlainBuffer(), p.pixels_to_write * 2));
if (yInCanvas(origin.y) and yInCanvas(origin.y + buffer->getSize().y))
{
p.pixels = this->clipping.getPixels();
// Calculate left buffer-offset
p.pixels_bulk = origin.x < 0 ? -origin.x * this->clipping.getHeight() : 0;
RF_CALL(this->writeData(buffer->getPlainBuffer() + p.pixels_bulk, 2 * p.pixels));
} else
{
// IMPLEMENT Can't transfer buffer continuously
// What's the best strategy? copy to p.buffer (using DMA2D if available) or send row by row?
RF_RETURN();
}

RF_END();
}

// -- Write equal colored BufferInterface -----------------------------
// -- Write different colored BufferInterface -----------------------------
template<class Interface, class Reset, size_t BC>
template<Color C_>
modm::ResumableResult<void>
modm::Ili9341<Interface, Reset, BC>::writeBuffer(
const BufferInterface<colorType> *buffer, Point origin) {
const BufferInterface<C_> *buffer, Point origin) {
RF_BEGIN();

this->clipping = this->getIntersection(Rectangle(origin, buffer->getResolution()));
this->clipping = this->getIntersection(Rectangle(origin, buffer->getSize()));
RF_CALL(updateClipping());

// Reload scanner
p.bool_scanner = ScannerBufferBool(origin);
p.bool_scanner.print_top();
p.bool_scanner.print_state();

RF_END();
}

// -- Write monochrome Buffer -----------------------------
// -- Write monochrome BufferInterface -------------------
template<class Interface, class Reset, size_t BC>
template<typename R_, class Painter_>
modm::ResumableResult<void>
modm::Ili9341<Interface, Reset, BC>::writeBuffer(
const Buffer<bool, R_, Painter_> &buffer, Point origin)
{
const BufferInterface<bool> *buffer, Point origin) {
RF_BEGIN();

// Reload scanner
p.bool_scanner = ScannerBufferBool(buffer.getPlainBuffer(), origin);
p.bool_scanner.print_top();

this->clipping = this->getIntersection(Rectangle(origin, R_::asPoint()));
this->clipping = this->getIntersection(Rectangle(origin, buffer->getSize()));
RF_CALL(updateClipping());

while (p.pixels_to_write)
p.mono_reader = MonochromeReader(buffer->getPlainBuffer(), buffer->getSize().x, origin);
p.scanner = this->clipping.topLeft;

while (p.pixels)
{
p.temp_color = html::Red;

// Convert next Bulk
p.pixel_bulk = std::min<size_t>(p.pixels_to_write, BC);
for(p.buffer_i = 0; p.buffer_i < p.pixel_bulk; p.buffer_i++) {
// p.bool_scanner.print_state();
// p.buffer[p.buffer_i] = p.bool_scanner() ? color : colorType(html::Black);
p.temp_color.color++;
p.buffer[p.buffer_i] = p.temp_color;
for(p.i = 0; p.i < std::min<uint32_t>(p.pixels, BC); p.i++) {
p.buffer[p.i] = p.mono_reader() ? color : colorType(html::Black);
if (++p.scanner.y == this->clipping.bottomRight.y) {
scannerNextRow();
p.mono_reader.nextRow();
}
}

// Transfer
RF_CALL(this->writeData((uint8_t *)(p.buffer), 2 * p.pixel_bulk));
p.pixels_to_write -= p.pixel_bulk;
RF_CALL(this->writeData((uint8_t *)(p.buffer), 2 * p.i));
p.pixels -= p.i;
}
RF_END();
}

// -- Write monochrome BufferInterface -------------------
template<class Interface, class Reset, size_t BC>
modm::ResumableResult<void>
modm::Ili9341<Interface, Reset, BC>::writeBuffer(
const BufferInterface<bool> *buffer, Point origin) {
RF_BEGIN();

MODM_LOG_DEBUG << __FUNCTION__ << modm::endl;
MODM_LOG_DEBUG << "origin: " << origin << ", resolution: " << buffer->getResolution() << modm::endl;

RF_END();
}

Expand All @@ -363,20 +347,29 @@ modm::Ili9341<Interface, Reset, BC>::writeFlash(modm::accessor::Flash<uint8_t> d
uint16_t width, uint16_t height, Point origin) {
RF_BEGIN();

this->clipping = this->getIntersection(Rectangle(origin, Point(width, height)));
this->clipping = this->getIntersection(Rectangle(origin, {width, height}));
RF_CALL(updateClipping());

// Reload scanner
// p.bool_scanner = ScannerBufferBool(data, origin);
// p.bool_scanner.print_top();
// p.bool_scanner.print_state();

(void)data;
(void)width;
(void)height;
(void)origin;
// FIXME MonochromeReader must learn to handle modm::accessor::Flash<uint8_t>
// p.mono_reader = MonochromeReader(data, width, origin);
p.scanner = this->clipping.topLeft;

while (p.pixels)
{
// Convert next Bulk
for(p.i = 0; p.i < std::min<uint32_t>(p.pixels, BC); p.i++) {
// p.buffer[p.i] = p.mono_reader() ? color : colorType(html::Black);
if (++p.scanner.y == this->clipping.bottomRight.y) {
scannerNextRow();
// p.mono_reader.nextRow();
}
}
// Transfer
RF_CALL(this->writeData((uint8_t *)(p.buffer), 2 * p.i));
p.pixels -= p.i;
}

RF_END();
RF_END();
}

// -- Draw primitive Shapes ------------------------------
Expand Down Expand Up @@ -421,14 +414,14 @@ modm::Ili9341<Interface, Reset, BC>::drawFast(Section section)
// See https://github.com/modm-io/modm/issues/666

// Without DMA, at least this could be parallelised to updateClipping(..) above
p.pixel_bulk = std::min<size_t>(BC, p.pixels_to_write);
std::fill(p.buffer, p.buffer + p.pixel_bulk, color);
p.pixels_bulk = std::min<size_t>(BC, p.pixels);
std::fill(p.buffer, p.buffer + p.pixels_bulk, color);

while (p.pixels_to_write)
while (p.pixels)
{
p.pixels_to_write -= p.pixel_bulk;
RF_CALL(this->writeData((uint8_t *)(p.buffer), 2 * p.pixel_bulk));
p.pixel_bulk = std::min<size_t>(BC, p.pixels_to_write);
p.pixels -= p.pixels_bulk;
RF_CALL(this->writeData((uint8_t *)(p.buffer), 2 * p.pixels_bulk));
p.pixels_bulk = std::min<size_t>(BC, p.pixels);
}
RF_END();
}
Expand Down
8 changes: 1 addition & 7 deletions src/modm/driver/display/sh1106.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,11 @@ class Sh1106 : public Ssd1306<I2cMaster, H>

Sh1106(uint8_t address = 0x3C) : Ssd1306<I2cMaster, H>(address) {}

// Write monochrome Buffer via BufferInterface
// Write monochrome BufferInterface
// Caution: origin.y rounds to multiples of 8
modm::ResumableResult<bool>
writeBuffer(const BufferInterface<colorType> *buffer, Point origin = {0, 0});

// Write monochrome Buffer
// Caution: origin.y rounds to multiples of 8
template<typename R_, class Painter_>
modm::ResumableResult<bool>
writeBuffer(const Buffer<colorType, R_, Painter_> &buffer, Point origin = {0, 0});

protected:
modm::ResumableResult<bool>
initializeMemoryMode() override;
Expand Down
37 changes: 2 additions & 35 deletions src/modm/driver/display/sh1106_impl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ modm::ResumableResult<bool>
modm::Sh1106<I2cMaster, H>::writeBuffer(const BufferInterface<colorType> *buffer, Point origin) {
RF_BEGIN();

this->clipping = Rectangle(origin, buffer->getResolution());
this->clipping = Rectangle(origin, buffer->getSize());

if (this->pointInCanvas(this->clipping.bottomRight - Point(1, 1)))
{
Expand All @@ -63,7 +63,7 @@ modm::Sh1106<I2cMaster, H>::writeBuffer(const BufferInterface<colorType> *buffer
this->commandBuffer[2] = ssd1306::AdressingCommands::PageStartAddress | yd;
this->transaction_success &= RF_CALL(this->writeCommands(3));

RF_WAIT_UNTIL(this->transaction.configureDisplayWrite(buffer.getPlainBuffer() + (buffer->getResolution().x * yb++), buffer->getResolution()));
RF_WAIT_UNTIL(this->transaction.configureDisplayWrite(buffer->getPlainBuffer() + (this->clipping.getWidth() * yb++), this->clipping.getWidth()));
RF_WAIT_UNTIL(this->startTransaction());
RF_WAIT_WHILE(this->isTransactionRunning());
this->transaction_success &= this->wasTransactionSuccessful();
Expand All @@ -73,37 +73,4 @@ modm::Sh1106<I2cMaster, H>::writeBuffer(const BufferInterface<colorType> *buffer
this->transaction_success = false;
}
RF_END_RETURN(this->transaction_success);
}

template<class I2cMaster, uint16_t H>
template<typename R_, class Painter_>
modm::ResumableResult<bool>
modm::Sh1106<I2cMaster, H>::writeBuffer(const Buffer<colorType, R_, Painter_> &buffer, Point origin)
{
RF_BEGIN();

this->clipping = Rectangle(origin, R_::asPoint());

if (this->pointInCanvas(this->clipping.bottomRight - Point(1, 1)))
{
RF_CALL(updateClipping());

this->transaction_success = true;
yb = 0;

for (yd = yd_start; yd <= yd_end; yd++)
{
this->commandBuffer[2] = ssd1306::AdressingCommands::PageStartAddress | yd;
this->transaction_success &= RF_CALL(this->writeCommands(3));

RF_WAIT_UNTIL(this->transaction.configureDisplayWrite(
buffer.getPlainBuffer() + (R_::W * yb++), R_::W));
RF_WAIT_UNTIL(this->startTransaction());
RF_WAIT_WHILE(this->isTransactionRunning());
this->transaction_success &= this->wasTransactionSuccessful();
};
} else {
this->transaction_success = false;
}
RF_END_RETURN(this->transaction_success);
}
Loading

0 comments on commit ca9176d

Please sign in to comment.