DisplayList.h
Go to the documentation of this file.
1 /****
2  * DisplayList.h
3  *
4  * Copyright 2021 mikee47 <mike@sillyhouse.net>
5  *
6  * This file is part of the Sming-Graphics Library
7  *
8  * This library is free software: you can redistribute it and/or modify it under the terms of the
9  * GNU General Public License as published by the Free Software Foundation, version 3 or later.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
12  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13  * See the GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along with this library.
16  * If not, see <https://www.gnu.org/licenses/>.
17  *
18  * @author: May 2021 - mikee47 <mike@sillyhouse.net>
19  *
20  ****/
21 
22 #pragma once
23 
24 #include <HSPI/Request.h>
25 #include "AddressWindow.h"
26 #include "Buffer.h"
27 #include "Blend.h"
28 #include <FlashString/Array.hpp>
29 #include <memory>
30 
31 #define DEFINE_RB_COMMAND(cmd, len, ...) uint8_t(uint8_t(DisplayList::Code::command) | (len << 4)), cmd, ##__VA_ARGS__,
32 #define DEFINE_RB_COMMAND_LONG(cmd, len, ...) \
33  uint8_t(uint8_t(DisplayList::Code::command) | 0xf0), len, cmd, ##__VA_ARGS__,
34 #define DEFINE_RB_DELAY(ms) uint8_t(DisplayList::Code::delay), ms,
35 #define DEFINE_RB_ARRAY(name, ...) DEFINE_FSTR_ARRAY_LOCAL(name, uint8_t, ##__VA_ARGS__)
36 
37 namespace Graphics
38 {
46 #define GRAPHICS_DL_COMMAND_LIST(XX) \
47  XX(none, 0, "") \
48  XX(command, 2 + 1, "General command: arglen, cmd, args") \
49  XX(repeat, 1 + 2 + 2, "Repeated data block: WRITE, len, repeat, data") \
50  XX(setColumn, 2 + 2, "Set column: len, start") \
51  XX(setRow, 2 + 2, "Set row: len, start") \
52  XX(writeStart, 0, "Start writing command") \
53  XX(writeData, 2, "Write data: len, data") \
54  XX(writeDataBuffer, 1 + 2 + sizeof(void*), "Write data: cmd, len, dataptr") \
55  XX(readStart, 2 + sizeof(void*), "Read data: len, bufptr (first packet after setting address)") \
56  XX(read, 2 + sizeof(void*), "Read data: len, bufptr (Second and subsequent packets)") \
57  XX(callback, 2 + sizeof(void*) + 3, "Callback: paramlen, callback, ALIGN4, params") \
58  XX(delay, 1, "Wait n milliseconds before continuing")
59 
64 struct FillInfo {
65  using Callback = void (*)(FillInfo& info);
66 
67  uint8_t* dstptr;
69  uint16_t length;
70 
71  static IRAM_ATTR void callbackRGB565(FillInfo& info)
72  {
73  BlendAlpha::blendRGB565(__builtin_bswap16(info.color.value), info.dstptr, info.length, info.color.alpha);
74  }
75 };
76 
77 __forceinline uint16_t swapBytes(uint16_t w)
78 {
79  return (w >> 8) | (w << 8);
80 }
81 
82 __forceinline uint32_t makeWord(uint16_t w1, uint16_t w2)
83 {
84  return uint32_t(swapBytes(w1)) | (swapBytes(w2) << 16);
85 }
86 
149 {
150 public:
151  enum class Code : uint8_t {
152 #define XX(code, arglen, desc) code,
154 #undef XX
155  };
156 
162  enum CodeArgLengths : uint8_t {
163 #define XX(code, arglen, desc) codelen_##code = 1 + arglen,
165 #undef XX
166  };
167 
168  static String toString(Code code);
169 
195  union Header {
196  // Maximum value for header len field. 31 means 'length follows header'
197  static constexpr uint8_t lenMax{15};
198 
199  struct {
200  Code code : 4;
201  uint8_t len : 4; // Set to lenMax if length follows buffer
202  };
203  uint8_t u8;
204  };
205 
206  static_assert(sizeof(Header) == 1, "Header wrong size");
207 
215  using Callback = void (*)(void* parameterData);
216 
220  struct Entry {
222  uint16_t length;
223  uint16_t repeats;
224  void* data;
226  uint16_t value;
227  uint8_t cmd;
228  };
229 
235  DisplayList(AddressWindow& addrWindow, size_t bufferSize)
236  : buffer(new uint8_t[bufferSize]{}), addrWindow(addrWindow), capacity(bufferSize)
237  {
238  }
239 
245  DisplayList(AddressWindow& addrWindow, const FSTR::ObjectBase& data) : DisplayList(addrWindow, data.size())
246  {
247  data.read(0, buffer.get(), data.size());
248  size = data.length();
249  }
250 
256  DisplayList(AddressWindow& addrWindow, const void* data, size_t length) : DisplayList(addrWindow, length)
257  {
258  memcpy(buffer.get(), data, length);
259  size = length;
260  }
261 
266  void reset();
267 
271  bool isEmpty() const
272  {
273  return size == 0;
274  }
275 
279  uint16_t freeSpace() const
280  {
281  return capacity - size;
282  }
283 
287  uint16_t readOffset() const
288  {
289  return offset;
290  }
291 
295  uint16_t used() const
296  {
297  assert(size <= capacity);
298  return size;
299  }
300 
304  const uint8_t* getContent() const
305  {
306  return buffer.get();
307  }
308 
316  uint8_t* getBuffer(uint16_t& available);
317 
326  uint8_t* getBuffer(uint16_t minBytes, uint16_t& available)
327  {
328  auto buf = getBuffer(available);
329  return (buf != nullptr && available >= minBytes) ? buf : nullptr;
330  }
331 
337  void commit(uint16_t length);
338 
342  bool writeCommand(uint8_t command, uint32_t data, uint8_t length)
343  {
344  return writeCommand(command, &data, length);
345  }
346 
350  bool writeCommand(uint8_t command, const void* data, uint16_t length);
351 
355  bool writeData(const void* data, uint16_t length);
356 
361  bool writeDataBuffer(SharedBuffer& data, size_t offset, uint16_t length);
362 
366  bool blockFill(const void* data, uint16_t length, uint32_t repeat);
367 
371  bool setAddrWindow(const Rect& rect);
372 
376  bool setPixel(PackedColor color, uint8_t bytesPerPixel, Point pt);
377 
381  bool readMem(void* buffer, uint16_t length);
382 
391  bool writeCallback(Callback callback, void* params, uint16_t paramLength);
392 
403  bool fill(const Rect& rect, PackedColor color, uint8_t bytesPerPixel, FillInfo::Callback callback);
404 
410  {
411  return lockCount < maxLockedBuffers;
412  }
413 
418 
423  bool require(uint16_t length)
424  {
425  return size + length <= capacity;
426  }
427 
436  bool readEntry(Entry& info);
437 
444  {
445  this->callback = callback;
446  this->param = param;
447  offset = 0;
448  }
449 
450 protected:
454  void write(uint8_t c)
455  {
456  buffer[size++] = c;
457  }
458 
464  void writeHeader(Code code, uint16_t length)
465  {
466  // debug_i("%p writeHeader(%s, %u)", this, toString(code).c_str(), length);
467  if(length < Header::lenMax) {
468  Header hdr{{code, uint8_t(length)}};
469  write(hdr.u8);
470  } else {
471  Header hdr{{code, Header::lenMax}};
472  write(hdr.u8);
473  writeVar(length);
474  }
475  }
476 
480  void write16(uint16_t c)
481  {
482  write((c >> 8) | 0x80);
483  write(c & 0xff);
484  }
485 
489  void write(const void* data, uint16_t length)
490  {
491  if(length != 0) {
492  memcpy(&buffer[size], data, length);
493  size += length;
494  }
495  }
496 
500  void writeVar(uint16_t count)
501  {
502  if(count >= 0x80) {
503  write16(count);
504  } else {
505  write(count);
506  }
507  }
508 
515  {
516  return addrWindow.setMode(AddressWindow::Mode::write) ? Code::writeStart : Code::writeData;
517  }
518 
525  {
526  return addrWindow.setMode(AddressWindow::Mode::read) ? Code::readStart : Code::read;
527  }
528 
529  void internalSetAddrWindow(const Rect& rect);
530 
536  void IRAM_ATTR read(void* data, uint16_t len)
537  {
538  memcpy(data, &buffer[offset], len);
539  offset += len;
540  }
541 
547  uint16_t IRAM_ATTR readVar()
548  {
549  uint16_t var = buffer[offset++];
550  if(var & 0x80) {
551  var = (var & 0x7f) << 8;
552  var |= buffer[offset++];
553  }
554  return var;
555  }
556 
558  static constexpr size_t maxLockedBuffers{8};
559 
560  Callback callback{nullptr};
561  void* param{nullptr};
562  std::unique_ptr<uint8_t[]> buffer;
563  uint16_t size{0};
564  uint16_t offset{0};
565 
566 private:
567  AddressWindow& addrWindow;
568  uint16_t capacity;
569  SharedBuffer lockedBuffers[maxLockedBuffers];
570 #ifdef ENABLE_GRAPHICS_RAM_TRACKING
571  size_t maxBufferUsage{0};
572 #endif
573  uint8_t lockCount{0};
574 };
575 
576 } // namespace Graphics
577 
579 {
580  return Graphics::DisplayList::toString(code);
581 }
String toString(Graphics::DisplayList::Code code)
Definition: DisplayList.h:578
#define GRAPHICS_DL_COMMAND_LIST(XX)
DisplayList command codes.
Definition: DisplayList.h:46
Used when defining data structures.
Definition: ObjectBase.hpp:33
constexpr FSTR_NOINLINE const size_t length() const
Get the length of the object data in bytes.
Definition: ObjectBase.hpp:38
size_t read(size_t offset, void *buffer, size_t count) const
Read contents of a String into RAM.
constexpr const size_t size() const
Get the object data size in bytes.
Definition: ObjectBase.hpp:54
static uint16_t blendRGB565(uint16_t src, uint16_t dst, uint8_t alpha)
Stores list of low-level display commands.
Definition: DisplayList.h:149
Code
Definition: DisplayList.h:151
bool writeData(const void *data, uint16_t length)
Add WRITE command plus data.
DisplayList(AddressWindow &addrWindow, size_t bufferSize)
Definition: DisplayList.h:235
uint8_t * getBuffer(uint16_t minBytes, uint16_t &available)
Get some space in the list to write pixel data.
Definition: DisplayList.h:326
bool fill(const Rect &rect, PackedColor color, uint8_t bytesPerPixel, FillInfo::Callback callback)
Perform a block fill operation with blending.
static String toString(Code code)
void(*)(void *parameterData) Callback
Queued callback.
Definition: DisplayList.h:215
const uint8_t * getContent() const
Get read-only pointer to start of buffer.
Definition: DisplayList.h:304
bool require(uint16_t length)
Check if list has space for the given number of bytes.
Definition: DisplayList.h:423
void reset()
Reset the display list ready for re-use List MUST NOT be in use!
void writeVar(uint16_t count)
Write a value using 1 or 2 bytes as required.
Definition: DisplayList.h:500
bool writeDataBuffer(SharedBuffer &data, size_t offset, uint16_t length)
Add WRITE command plus external data.
void prepare(Callback callback, void *param)
Prepare for playback.
Definition: DisplayList.h:443
Callback callback
Definition: DisplayList.h:560
void writeHeader(Code code, uint16_t length)
Write a Header structure to the buffer.
Definition: DisplayList.h:464
std::unique_ptr< uint8_t[]> buffer
Definition: DisplayList.h:562
static constexpr size_t maxLockedBuffers
Definition: DisplayList.h:558
bool writeCallback(Callback callback, void *params, uint16_t paramLength)
Request a callback.
uint16_t readVar()
Read variable-length value from buffer.
Definition: DisplayList.h:547
bool setPixel(PackedColor color, uint8_t bytesPerPixel, Point pt)
Set a single pixel.
void internalSetAddrWindow(const Rect &rect)
bool isEmpty() const
Determine if any commands have been stored for execution.
Definition: DisplayList.h:271
uint16_t offset
Current read position.
Definition: DisplayList.h:564
uint16_t readOffset() const
Get current read position.
Definition: DisplayList.h:287
bool readMem(void *buffer, uint16_t length)
Read a block of display memory.
uint16_t size
Number of bytes stored in buffer.
Definition: DisplayList.h:563
void commit(uint16_t length)
Commit block of data to the list.
void write(const void *data, uint16_t length)
Write a block of data into the display list buffer.
Definition: DisplayList.h:489
Code getWriteCode()
Get the appropriate command code to use for a write operation.
Definition: DisplayList.h:514
DisplayList(AddressWindow &addrWindow, const void *data, size_t length)
Create initialised display list from RAM data.
Definition: DisplayList.h:256
void read(void *data, uint16_t len)
Read block of data from buffer.
Definition: DisplayList.h:536
uint16_t used() const
Get number of bytes stored in buffer.
Definition: DisplayList.h:295
bool lockBuffer(SharedBuffer &buffer)
Lock a shared buffer by storing a reference to it. This will be released when reset() is called.
void * param
Definition: DisplayList.h:561
void write(uint8_t c)
Write a byte into the display list buffer.
Definition: DisplayList.h:454
bool writeCommand(uint8_t command, uint32_t data, uint8_t length)
Write command with 1-4 bytes of parameter data.
Definition: DisplayList.h:342
bool setAddrWindow(const Rect &rect)
Set window for read/write operations.
bool canLockBuffer()
Enforce maximum number of locked buffers to conserve memory.
Definition: DisplayList.h:409
CodeArgLengths
Obtain maximum size for command, not including variable data which may be added.
Definition: DisplayList.h:162
XX(code, arglen, desc)
uint16_t freeSpace() const
Get number of bytes remaining in buffer.
Definition: DisplayList.h:279
bool writeCommand(uint8_t command, const void *data, uint16_t length)
Write command with variable amount of parameter data.
uint8_t * getBuffer(uint16_t &available)
Get some space in the list to write pixel data.
void write16(uint16_t c)
Write a value as 2 bytes.
Definition: DisplayList.h:480
DisplayList(AddressWindow &addrWindow, const FSTR::ObjectBase &data)
Create pre-defined display list from flash data.
Definition: DisplayList.h:245
bool blockFill(const void *data, uint16_t length, uint32_t repeat)
Perform a block fill operation with repeat, e.g. multiple pixel fill or repeated pattern.
Code getReadCode()
Get the appropriate command code to use for a read operation.
Definition: DisplayList.h:524
bool readEntry(Entry &info)
Read next command list entry.
Shared heap-allocated data buffer.
Definition: Graphics/src/include/Graphics/Buffer.h:36
The String class.
Definition: WString.h:137
Definition: Virtual.h:31
uint32_t makeWord(uint16_t w1, uint16_t w2)
Definition: DisplayList.h:82
uint16_t swapBytes(uint16_t w)
Definition: DisplayList.h:77
Timer2Clock::Ticks< uint32_t > read()
Get elapsed watchdog time since last reset.
Manages a rectangular area of display memory with position information.
Definition: AddressWindow.h:37
bool setMode(Mode mode)
Definition: AddressWindow.h:64
Values returned from readEntry
Definition: DisplayList.h:220
uint16_t repeats
Definition: DisplayList.h:223
uint8_t cmd
Definition: DisplayList.h:227
Callback callback
Definition: DisplayList.h:225
Code code
Definition: DisplayList.h:221
uint16_t length
Definition: DisplayList.h:222
uint16_t value
Definition: DisplayList.h:226
void * data
Definition: DisplayList.h:224
Supports DisplayList blend operations.
Definition: DisplayList.h:64
uint8_t * dstptr
Definition: DisplayList.h:67
void(*)(FillInfo &info) Callback
Definition: DisplayList.h:65
PackedColor color
Definition: DisplayList.h:68
uint16_t length
Definition: DisplayList.h:69
static void callbackRGB565(FillInfo &info)
Definition: DisplayList.h:71
Colour in device pixel format.
Definition: Colors.h:339
uint32_t value
Definition: Colors.h:340
uint32_t alpha
Definition: Colors.h:341
Location and size of rectangular area (x, y, w, h)
Definition: Libraries/Graphics/src/include/Graphics/Types.h:287
Each list entry starts with a header.
Definition: DisplayList.h:195
uint8_t len
Definition: DisplayList.h:201
Code code
Definition: DisplayList.h:200
static constexpr uint8_t lenMax
Definition: DisplayList.h:197
uint8_t u8
Definition: DisplayList.h:203