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 
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 
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  };
204  };
205 
206  static_assert(sizeof(Header) == 1, "Header wrong size");
207 
215  using Callback = void (*)(void* parameterData);
216 
220  struct Entry {
224  void* data;
228  };
229 
235  DisplayList(AddressWindow& addrWindow, size_t bufferSize) : addrWindow(addrWindow), capacity(bufferSize)
236  {
237  buffer.reset(new uint8_t[bufferSize]{});
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 
280  {
281  return capacity - size;
282  }
283 
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 
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;
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 }
DisplayList(AddressWindow &addrWindow, const FSTR::ObjectBase &data)
Create pre-defined display list from flash data.
Definition: DisplayList.h:245
String toString(Graphics::DisplayList::Code code)
Definition: DisplayList.h:578
void(*)(void *parameterData) Callback
Queued callback.
Definition: DisplayList.h:215
static String toString(Code code)
uint32_t alpha
Definition: Colors.h:341
bool writeCommand(uint8_t command, uint32_t data, uint8_t length)
Write command with 1-4 bytes of parameter data.
Definition: DisplayList.h:342
void(*)(FillInfo &info) Callback
Definition: DisplayList.h:65
void write(const void *data, uint16_t length)
Write a block of data into the display list buffer.
Definition: DisplayList.h:489
size_t length() const
Get the length of the object data in bytes.
bool setMode(Mode mode)
Definition: AddressWindow.h:102
Manages a rectangular area of display memory with position information.
Definition: AddressWindow.h:56
static constexpr uint8_t lenMax
Definition: DisplayList.h:197
size_t read(size_t offset, void *buffer, size_t count) const
Read contents of a String into RAM.
Definition: ObjectBase.hpp:110
void * param
Definition: DisplayList.h:561
Location and size of rectangular area (x, y, w, h)
Definition: Libraries/Graphics/src/include/Graphics/Types.h:306
void * data
Definition: DisplayList.h:224
uint16_t offset
Current read position.
Definition: DisplayList.h:564
The String class.
Definition: WString.h:136
Code
Definition: DisplayList.h:151
uint8_t * getBuffer(uint16_t minBytes, uint16_t &available)
Get some space in the list to write pixel data.
Definition: DisplayList.h:326
uint8_t * getBuffer(uint16_t &available)
Get some space in the list to write pixel data.
Timer2Clock::Ticks< uint32_t > read()
Get elapsed watchdog time since last reset.
uint16_t length
Definition: DisplayList.h:69
uint8_t u8
Definition: DisplayList.h:203
bool canLockBuffer()
Enforce maximum number of locked buffers to conserve memory.
Definition: DisplayList.h:409
uint32_t makeWord(uint16_t w1, uint16_t w2)
Definition: DisplayList.h:82
std::unique_ptr< uint8_t[]> buffer
Definition: DisplayList.h:562
uint8_t cmd
Definition: DisplayList.h:227
uint16_t length
Definition: DisplayList.h:222
bool readEntry(Entry &info)
Read next command list entry.
Used when defining data structures.
Definition: ObjectBase.hpp:51
uint16_t value
Definition: DisplayList.h:226
bool isEmpty() const
Determine if any commands have been stored for execution.
Definition: DisplayList.h:271
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.
void write(uint8_t c)
Write a byte into the display list buffer.
Definition: DisplayList.h:454
size_t size() const
Get the object data size in bytes.
Definition: ObjectBase.hpp:82
uint16_t size
Number of bytes stored in buffer.
Definition: DisplayList.h:563
Definition: Virtual.h:30
uint8_t len
Definition: DisplayList.h:201
CodeArgLengths
Obtain maximum size for command, not including variable data which may be added.
Definition: DisplayList.h:162
static void callbackRGB565(FillInfo &info)
Definition: DisplayList.h:71
XX(code, arglen, desc)
static uint16_t blendRGB565(uint16_t src, uint16_t dst, uint8_t alpha)
void commit(uint16_t length)
Commit block of data to the list.
Code code
Definition: DisplayList.h:221
uint32_t value
Definition: Colors.h:340
bool require(uint16_t length)
Check if list has space for the given number of bytes.
Definition: DisplayList.h:423
Code getReadCode()
Get the appropriate command code to use for a read operation.
Definition: DisplayList.h:524
static constexpr size_t maxLockedBuffers
Definition: DisplayList.h:558
uint16_t used() const
Get number of bytes stored in buffer.
Definition: DisplayList.h:295
uint8_t * dstptr
Definition: DisplayList.h:67
Code code
Definition: DisplayList.h:200
Each list entry starts with a header.
Definition: DisplayList.h:195
uint16_t freeSpace() const
Get number of bytes remaining in buffer.
Definition: DisplayList.h:279
bool writeCallback(Callback callback, void *params, uint16_t paramLength)
Request a callback.
bool fill(const Rect &rect, PackedColor color, uint8_t bytesPerPixel, FillInfo::Callback callback)
Perform a block fill operation with blending.
bool setPixel(PackedColor color, uint8_t bytesPerPixel, Point pt)
Set a single pixel.
Stores list of low-level display commands.
Definition: DisplayList.h:148
bool writeData(const void *data, uint16_t length)
Add WRITE command plus data.
Callback callback
Definition: DisplayList.h:560
#define GRAPHICS_DL_COMMAND_LIST(XX)
DisplayList command codes.
Definition: DisplayList.h:46
void internalSetAddrWindow(const Rect &rect)
Shared heap-allocated data buffer.
Definition: Graphics/src/include/Graphics/Buffer.h:54
uint16_t repeats
Definition: DisplayList.h:223
void read(void *data, uint16_t len)
Read block of data from buffer.
Definition: DisplayList.h:536
PackedColor color
Definition: DisplayList.h:68
Values returned from readEntry
Definition: DisplayList.h:220
bool readMem(void *buffer, uint16_t length)
Read a block of display memory.
void writeVar(uint16_t count)
Write a value using 1 or 2 bytes as required.
Definition: DisplayList.h:500
void prepare(Callback callback, void *param)
Prepare for playback.
Definition: DisplayList.h:443
DisplayList(AddressWindow &addrWindow, size_t bufferSize)
Definition: DisplayList.h:235
Code getWriteCode()
Get the appropriate command code to use for a write operation.
Definition: DisplayList.h:514
bool writeDataBuffer(SharedBuffer &data, size_t offset, uint16_t length)
Add WRITE command plus external data.
void write16(uint16_t c)
Write a value as 2 bytes.
Definition: DisplayList.h:480
bool setAddrWindow(const Rect &rect)
Set window for read/write operations.
uint16_t readOffset() const
Get current read position.
Definition: DisplayList.h:287
const uint8_t * getContent() const
Get read-only pointer to start of buffer.
Definition: DisplayList.h:304
Colour in device pixel format.
Definition: Colors.h:339
Callback callback
Definition: DisplayList.h:225
DisplayList(AddressWindow &addrWindow, const void *data, size_t length)
Create initialised display list from RAM data.
Definition: DisplayList.h:256
bool lockBuffer(SharedBuffer &buffer)
Lock a shared buffer by storing a reference to it. This will be released when reset() is called.
Supports DisplayList blend operations.
Definition: DisplayList.h:64
void reset()
Reset the display list ready for re-use List MUST NOT be in use!
void writeHeader(Code code, uint16_t length)
Write a Header structure to the buffer.
Definition: DisplayList.h:464
uint16_t swapBytes(uint16_t w)
Definition: DisplayList.h:77