mattb5906 February 2016

graphic drawing class organisation

I have a basic 4x20 character LCD that I would like to use for displaying a menu with buttons using an Arduino as the driver (limited standard library support).

Example LCD menu and buttons

I'm thinking of producing an interface class GraphicObject that all graphical objects then inherit from (such as Button, MenuItem etc.). It seems logical that the GraphicObject class should have a draw method which can be overridden.

At the moment, I have a class called Lcd which covers the low level drawing of text and character positioning. In order to draw anything, I will need access to one of these Lcd objects. If I include a pointer to the Lcd object within my GraphicObject or derived objects, I couple them and make them Lcd only objects. If I change the type of display device these classes aren't suitable any more.

How can the classes be organised to keep them loosely coupled and allow for a change in display types at a later date? Should I have LCDButton LCDMenuItem which then inherit from a Button and MenuItem interface, then create additional objects for the other display device (OtherDisplayButton OtherDisplayMenuItem)?

Any suggested reading? I've looked at many examples, but none of them seem to go into details about the function of a draw method and whether the device should be accessed directly or through another controlling object.

Thanks

Edit 1

Brief code idea overview

#include "Arduino.h"

class Lcd {
public:
  struct Parameters {
    uint_fast8_t numberLines;
    uint_fast8_t numberCharacters;
//  uint_fast8_t* lineOffsets;
    Print* serial; // Can be any Serial device (all inherit from Print).
  };

protected:
  Parameters parameters_;
  const uint_fast8_t escapeCode_ = 0x1B;
  const uint_fast8_t directCode_ = 0xFE;

  void sendCommand_(uint_fast8_t command, uint_fast8_t parameter = 0);
  void sen        

Answers


ul90 February 2016

There are different ways to do this. In principle, you should define an interface (API) to your low-level LCD driver module(s) and call only functions of your low level api to draw something. The implementations of this api can then exchanged without the need to change the high level code.

The simplest way to do this is to define an abstract c++ base class where all lcd driver implementations have to be derived from. The base class should have virtual methods that need to be overloaded by the derived implementations.

But a litte information: virtual methods in c++ classes requires the compiler to generate a method pointer table for every object that is created when the object is instantiated; this needs some more memory. Also, all function calls to objects of these classes are indirect (the compiler generates code that first lookup the real function pointer and then calls the function using this pointer), which makes the resulting code slightly slower.

Post Status

Asked in February 2016
Viewed 2,370 times
Voted 9
Answered 1 times

Search




Leave an answer