/ src / Adafruit_dvhstx.h
Adafruit_dvhstx.h
  1  #pragma once
  2  
  3  #include "Adafruit_GFX.h"
  4  
  5  #include "drivers/dvhstx/dvhstx.hpp"
  6  
  7  enum DVHSTXResolution {
  8    /* well supported, square pixels on a 16:9 display, actual resolution
  9       1280x720@50Hz */
 10    DVHSTX_RESOLUTION_320x180,
 11    DVHSTX_RESOLUTION_640x360,
 12  
 13    /* sometimes supported, square pixels on a 16:9 display, actual resolution
 14       960x540@60Hz */
 15    DVHSTX_RESOLUTION_480x270,
 16  
 17    /* sometimes supported, square pixels on a 16:9 display, actual resolution
 18       800x450@60Hz */
 19    DVHSTX_RESOLUTION_400x225,
 20  
 21    /* well supported, but pixels aren't square on a 16:9 display */
 22    DVHSTX_RESOLUTION_320x240, /* 4:3, actual resolution 640x480@60Hz */
 23    DVHSTX_RESOLUTION_360x240, /* 3:2, actual resolution 720x480@60Hz */
 24    DVHSTX_RESOLUTION_360x200, /* 18:10, actual resolution 720x400@70Hz */
 25    DVHSTX_RESOLUTION_360x288, /* 5:4, actual resolution 720x576@60Hz */
 26    DVHSTX_RESOLUTION_400x300, /* 4:3, actual resolution 800x600@60Hz */
 27    DVHSTX_RESOLUTION_512x384, /* 4:3, actual resolution 1024x768@60Hz */
 28  
 29    /* sometimes supported, but pixels aren't square on a 16:9 display */
 30    DVHSTX_RESOLUTION_400x240, /* 5:3, actual resolution 800x480@60Hz */
 31  };
 32  
 33  using pimoroni::DVHSTXPinout;
 34  
 35  // If the board definition provides pre-defined pins for the HSTX connection,
 36  // use them to define a default pinout object.
 37  // This object can be used as the first argument of the DVHSTX constructor.
 38  // Otherwise you must provide the pin nubmers directly as a list of 4 numbers
 39  // in curly brackets such as {12, 14, 16, 18}. These give the location of the
 40  // positive ("P") pins in the order: Clock, Data 0, Data 1, Data 2; check your
 41  // board's schematic for details.
 42  #if defined(PIN_CKP)
 43  #define DVHSTX_PINOUT_DEFAULT                                                  \
 44    { PIN_CKP, PIN_D0P, PIN_D1P, PIN_D2P }
 45  #endif
 46  
 47  int16_t dvhstx_width(DVHSTXResolution r);
 48  int16_t dvhstx_height(DVHSTXResolution r);
 49  
 50  class DVHSTX16 : public GFXcanvas16 {
 51  public:
 52    /**************************************************************************/
 53    /*!
 54       @brief    Instatiate a DVHSTX 16-bit canvas context for graphics
 55       @param    res   Display resolution
 56       @param    double_buffered Whether to allocate two buffers
 57    */
 58    /**************************************************************************/
 59    DVHSTX16(DVHSTXPinout pinout, DVHSTXResolution res,
 60             bool double_buffered = false)
 61        : GFXcanvas16(dvhstx_width(res), dvhstx_height(res), false),
 62          pinout(pinout), res{res}, double_buffered{double_buffered} {}
 63    ~DVHSTX16() { end(); }
 64  
 65    bool begin() {
 66      bool result =
 67          hstx.init(dvhstx_width(res), dvhstx_height(res),
 68                    pimoroni::DVHSTX::MODE_RGB565, double_buffered, pinout);
 69      if (!result)
 70        return false;
 71      buffer = hstx.get_back_buffer<uint16_t>();
 72      fillScreen(0);
 73      return true;
 74    }
 75    void end() { hstx.reset(); }
 76  
 77    /**********************************************************************/
 78    /*!
 79      @brief    If double-buffered, wait for retrace and swap buffers. Otherwise,
 80      do nothing (returns immediately)
 81      @param copy_framebuffer if true, copy the new screen to the new back buffer.
 82      Otherwise, the content is undefined.
 83    */
 84    /**********************************************************************/
 85    void swap(bool copy_framebuffer = false);
 86  
 87    /**********************************************************************/
 88    /*!
 89      @brief    Convert 24-bit RGB value to a framebuffer value
 90      @param r The input red value, 0 to 255
 91      @param g The input red value, 0 to 255
 92      @param b The input red value, 0 to 255
 93      @return  The corresponding 16-bit pixel value
 94    */
 95    /**********************************************************************/
 96    uint16_t color565(uint8_t red, uint8_t green, uint8_t blue) {
 97      return ((red & 0xF8) << 8) | ((green & 0xFC) << 3) | (blue >> 3);
 98    }
 99  
100  private:
101    DVHSTXPinout pinout;
102    DVHSTXResolution res;
103    mutable pimoroni::DVHSTX hstx;
104    bool double_buffered;
105  };
106  
107  class DVHSTX8 : public GFXcanvas8 {
108  public:
109    /**************************************************************************/
110    /*!
111       @brief    Instatiate a DVHSTX 8-bit canvas context for graphics
112       @param    res   Display resolution
113       @param    double_buffered Whether to allocate two buffers
114    */
115    /**************************************************************************/
116    DVHSTX8(DVHSTXPinout pinout, DVHSTXResolution res,
117            bool double_buffered = false)
118        : GFXcanvas8(dvhstx_width(res), dvhstx_height(res), false),
119          pinout(pinout), res{res}, double_buffered{double_buffered} {}
120    ~DVHSTX8() { end(); }
121  
122    bool begin() {
123      bool result =
124          hstx.init(dvhstx_width(res), dvhstx_height(res),
125                    pimoroni::DVHSTX::MODE_PALETTE, double_buffered, pinout);
126      if (!result)
127        return false;
128      for (int i = 0; i < 255; i++) {
129        uint8_t r = (i >> 6) * 255 / 3;
130        uint8_t g = ((i >> 2) & 7) * 255 / 7;
131        uint8_t b = (i & 3) * 255 / 3;
132        setColor(i, r, g, b);
133      }
134      buffer = hstx.get_back_buffer<uint8_t>();
135      fillScreen(0);
136      return true;
137    }
138    void end() { hstx.reset(); }
139  
140    void setColor(uint8_t idx, uint8_t red, uint8_t green, uint8_t blue) {
141      hstx.get_palette()[idx] = (red << 16) | (green << 8) | blue;
142    }
143    void setColor(uint8_t idx, uint32_t rgb) { hstx.get_palette()[idx] = rgb; }
144  
145    /**********************************************************************/
146    /*!
147      @brief    If double-buffered, wait for retrace and swap buffers. Otherwise,
148      do nothing (returns immediately)
149      @param copy_framebuffer if true, copy the new screen to the new back buffer.
150      Otherwise, the content is undefined.
151    */
152    /**********************************************************************/
153    void swap(bool copy_framebuffer = false);
154  
155  private:
156    DVHSTXPinout pinout;
157    DVHSTXResolution res;
158    mutable pimoroni::DVHSTX hstx;
159    bool double_buffered;
160  };
161  
162  using TextColor = pimoroni::DVHSTX::TextColour;
163  
164  class DVHSTXText3 : public GFXcanvas16 {
165  public:
166    struct Cell {
167      uint16_t value;
168      Cell(uint8_t c, uint8_t attr = TextColor::TEXT_WHITE)
169          : value(c | (attr << 8)) {}
170    };
171    /**************************************************************************/
172    /*!
173       @brief    Instatiate a DVHSTX 8-bit canvas context for graphics
174       @param    res   Display resolution
175       @param    double_buffered Whether to allocate two buffers
176    */
177    /**************************************************************************/
178    DVHSTXText3(DVHSTXPinout pinout)
179        : GFXcanvas16(91, 30, false),
180          pinout(pinout), res{res}, attr{TextColor::TEXT_WHITE} {}
181    ~DVHSTXText3() { end(); }
182  
183    bool begin() {
184      bool result =
185          hstx.init(91, 30, pimoroni::DVHSTX::MODE_TEXT_RGB111, false, pinout);
186      if (!result)
187        return false;
188      buffer = hstx.get_back_buffer<uint16_t>();
189      return true;
190    }
191    void end() { hstx.reset(); }
192  
193    void clear();
194  
195    void set_color(TextColor a) { attr = a; }
196  
197    void hide_cursor() {
198      cursor_visible = false;
199      hstx.cursor_off();
200    }
201  
202    void show_cursor() {
203      cursor_visible = true;
204      sync_cursor_with_hstx();
205    }
206  
207    void set_cursor(int x, int y) {
208      if (x < 0)
209        x = 0;
210      if (x > _width)
211        x = _width;
212      if (y < 0)
213        y = 0;
214      if (y >= _height)
215        y = _height - 1;
216      cursor_x = x;
217      cursor_y = y;
218      sync_cursor_with_hstx();
219    }
220  
221    size_t write(uint8_t c);
222  
223  private:
224    DVHSTXPinout pinout;
225    DVHSTXResolution res;
226    mutable pimoroni::DVHSTX hstx;
227    bool double_buffered;
228    bool cursor_visible = false;
229    TextColor attr;
230    uint8_t cursor_x = 0, cursor_y = 0;
231  
232    void sync_cursor_with_hstx() {
233      if (cursor_visible) {
234        hstx.set_cursor(cursor_x == _width ? _width - 1 : cursor_x, cursor_y);
235      }
236    }
237  };