/ src / Adafruit_dvhstx.cpp
Adafruit_dvhstx.cpp
  1  #include "Adafruit_dvhstx.h"
  2  
  3  // This code is heavily adapted from Adafruit_GFX_Library. The existin
  4  // GFXcanvas classes were not suitable, as the hstx instance controls
  5  // framebuffer allocation including double-buffering
  6  
  7  
  8  #if 0
  9  /**************************************************************************/
 10  /*!
 11      @brief  Draw a pixel to the canvas framebuffer
 12      @param  x   x coordinate
 13      @param  y   y coordinate
 14      @param  color 8-bit Color index to fill with. Only lower byte of uint16_t is used.
 15  */
 16  /**************************************************************************/
 17  void DVHSTX8::drawPixel(int16_t x, int16_t y, uint16_t color) {
 18    uint8_t *buffer = getBuffer();
 19    if (buffer) {
 20      if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height))
 21        return;
 22  
 23      int16_t t;
 24      switch (rotation) {
 25      case 1:
 26        t = x;
 27        x = _width - 1 - y;
 28        y = t;
 29        break;
 30      case 2:
 31        x = _width - 1 - x;
 32        y = _height - 1 - y;
 33        break;
 34      case 3:
 35        t = x;
 36        x = y;
 37        y = _height - 1 - t;
 38        break;
 39      }
 40  
 41      buffer[x + y * _width] = color;
 42    }
 43  }
 44  
 45  /**********************************************************************/
 46  /*!
 47          @brief    Get the pixel color index at a given coordinate
 48          @param    x   x coordinate
 49          @param    y   y coordinate
 50          @returns  The desired pixel's 8-bit color index
 51  */
 52  /**********************************************************************/
 53  uint8_t DVHSTX8::getPixel(int16_t x, int16_t y) const {
 54    int16_t t;
 55    switch (rotation) {
 56    case 1:
 57      t = x;
 58      x = _width - 1 - y;
 59      y = t;
 60      break;
 61    case 2:
 62      x = _width - 1 - x;
 63      y = _height - 1 - y;
 64      break;
 65    case 3:
 66      t = x;
 67      x = y;
 68      y = _height - 1 - t;
 69      break;
 70    }
 71    return getRawPixel(x, y);
 72  }
 73  
 74  /**********************************************************************/
 75  /*!
 76          @brief    Get the pixel index value at a given, unrotated coordinate.
 77                This method is intended for hardware drivers to get pixel value
 78                in physical coordinates.
 79          @param    x   x coordinate
 80          @param    y   y coordinate
 81          @returns  The desired pixel's 8-bit color value
 82  */
 83  /**********************************************************************/
 84  uint8_t DVHSTX8::getRawPixel(int16_t x, int16_t y) const {
 85    if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height))
 86      return 0;
 87    uint8_t *buffer = getBuffer();
 88    if (buffer) {
 89      return buffer[x + y * _width];
 90    }
 91    return 0;
 92  }
 93  
 94  /**************************************************************************/
 95  /*!
 96      @brief  Fill the framebuffer completely with one color
 97      @param  color 8-bit Color to fill with. Only lower byte of uint16_t is used.
 98  */
 99  /**************************************************************************/
100  void DVHSTX8::fillScreen(uint16_t color) {
101    uint8_t *buffer = getBuffer();
102    if (buffer) {
103      memset(buffer, color, _width * _height);
104    }
105  }
106  
107  /**************************************************************************/
108  /*!
109     @brief  Speed optimized vertical line drawing
110     @param  x      Line horizontal start point
111     @param  y      Line vertical start point
112     @param  h      Length of vertical line to be drawn, including first point
113     @param  color  8-bit Color to fill with. Only lower byte of uint16_t is
114                    used.
115  */
116  /**************************************************************************/
117  void DVHSTX8::drawFastVLine(int16_t x, int16_t y, int16_t h,
118                                 uint16_t color) {
119    uint8_t *buffer = getBuffer();
120    if (!buffer) return;
121  
122    if (h < 0) { // Convert negative heights to positive equivalent
123      h *= -1;
124      y -= h - 1;
125      if (y < 0) {
126        h += y;
127        y = 0;
128      }
129    }
130  
131    // Edge rejection (no-draw if totally off canvas)
132    if ((x < 0) || (x >= width()) || (y >= height()) || ((y + h - 1) < 0)) {
133      return;
134    }
135  
136    if (y < 0) { // Clip top
137      h += y;
138      y = 0;
139    }
140    if (y + h > height()) { // Clip bottom
141      h = height() - y;
142    }
143  
144    if (getRotation() == 0) {
145      drawFastRawVLine(x, y, h, color);
146    } else if (getRotation() == 1) {
147      int16_t t = x;
148      x = _width - 1 - y;
149      y = t;
150      x -= h - 1;
151      drawFastRawHLine(x, y, h, color);
152    } else if (getRotation() == 2) {
153      x = _width - 1 - x;
154      y = _height - 1 - y;
155  
156      y -= h - 1;
157      drawFastRawVLine(x, y, h, color);
158    } else if (getRotation() == 3) {
159      int16_t t = x;
160      x = y;
161      y = _height - 1 - t;
162      drawFastRawHLine(x, y, h, color);
163    }
164  }
165  
166  /**************************************************************************/
167  /*!
168     @brief  Speed optimized horizontal line drawing
169     @param  x      Line horizontal start point
170     @param  y      Line vertical start point
171     @param  w      Length of horizontal line to be drawn, including 1st point
172     @param  color  8-bit Color to fill with. Only lower byte of uint16_t is
173                    used.
174  */
175  /**************************************************************************/
176  void DVHSTX8::drawFastHLine(int16_t x, int16_t y, int16_t w,
177                                 uint16_t color) {
178    uint8_t *buffer = getBuffer();
179    if (!buffer) return;
180  
181    if (w < 0) { // Convert negative widths to positive equivalent
182      w *= -1;
183      x -= w - 1;
184      if (x < 0) {
185        w += x;
186        x = 0;
187      }
188    }
189  
190    // Edge rejection (no-draw if totally off canvas)
191    if ((y < 0) || (y >= height()) || (x >= width()) || ((x + w - 1) < 0)) {
192      return;
193    }
194  
195    if (x < 0) { // Clip left
196      w += x;
197      x = 0;
198    }
199    if (x + w >= width()) { // Clip right
200      w = width() - x;
201    }
202  
203    if (getRotation() == 0) {
204      drawFastRawHLine(x, y, w, color);
205    } else if (getRotation() == 1) {
206      int16_t t = x;
207      x = _width - 1 - y;
208      y = t;
209      drawFastRawVLine(x, y, w, color);
210    } else if (getRotation() == 2) {
211      x = _width - 1 - x;
212      y = _height - 1 - y;
213  
214      x -= w - 1;
215      drawFastRawHLine(x, y, w, color);
216    } else if (getRotation() == 3) {
217      int16_t t = x;
218      x = y;
219      y = _height - 1 - t;
220      y -= w - 1;
221      drawFastRawVLine(x, y, w, color);
222    }
223  }
224  
225  /**************************************************************************/
226  /*!
227     @brief    Speed optimized vertical line drawing into the raw canvas buffer
228     @param    x   Line horizontal start point
229     @param    y   Line vertical start point
230     @param    h   length of vertical line to be drawn, including first point
231     @param    color   8-bit Color to fill with. Only lower byte of uint16_t is
232     used.
233  */
234  /**************************************************************************/
235  void DVHSTX8::drawFastRawVLine(int16_t x, int16_t y, int16_t h,
236                                    uint16_t color) {
237    // x & y already in raw (rotation 0) coordinates, no need to transform.
238    uint8_t *buffer_ptr = buffer + y * _width + x;
239    for (int16_t i = 0; i < h; i++) {
240      (*buffer_ptr) = color;
241      buffer_ptr += _width;
242    }
243  }
244  
245  /**************************************************************************/
246  /*!
247     @brief    Speed optimized horizontal line drawing into the raw canvas buffer
248     @param    x   Line horizontal start point
249     @param    y   Line vertical start point
250     @param    w   length of horizontal line to be drawn, including first point
251     @param    color   8-bit Color to fill with. Only lower byte of uint16_t is
252     used.
253  */
254  /**************************************************************************/
255  void DVHSTX8::drawFastRawHLine(int16_t x, int16_t y, int16_t w,
256                                    uint16_t color) {
257    // x & y already in raw (rotation 0) coordinates, no need to transform.
258    memset(buffer + y * _width + x, color, w);
259  }
260  #endif
261  
262  /**************************************************************************/
263  /*!
264      @brief  Draw a pixel to the canvas framebuffer
265      @param  x   x coordinate
266      @param  y   y coordinate
267      @param  color 16-bit 5-6-5 Color to fill with
268  */
269  /**************************************************************************/
270  void DVHSTX16::drawPixel(int16_t x, int16_t y, uint16_t color) {
271    uint16_t *buffer = getBuffer();
272    if (buffer) {
273      if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height))
274        return;
275  
276      int16_t t;
277      switch (rotation) {
278      case 1:
279        t = x;
280        x = _width - 1 - y;
281        y = t;
282        break;
283      case 2:
284        x = _width - 1 - x;
285        y = _height - 1 - y;
286        break;
287      case 3:
288        t = x;
289        x = y;
290        y = _height - 1 - t;
291        break;
292      }
293  
294      buffer[x + y * _width] = color;
295    }
296  }
297  
298  /**********************************************************************/
299  /*!
300          @brief    Get the pixel color value at a given coordinate
301          @param    x   x coordinate
302          @param    y   y coordinate
303          @returns  The desired pixel's 16-bit 5-6-5 color value
304  */
305  /**********************************************************************/
306  uint16_t DVHSTX16::getPixel(int16_t x, int16_t y) const {
307    uint16_t *buffer = getBuffer();
308    if (!buffer) return 0;
309    int16_t t;
310    switch (rotation) {
311    case 1:
312      t = x;
313      x = _width - 1 - y;
314      y = t;
315      break;
316    case 2:
317      x = _width - 1 - x;
318      y = _height - 1 - y;
319      break;
320    case 3:
321      t = x;
322      x = y;
323      y = _height - 1 - t;
324      break;
325    }
326    return getRawPixel(x, y);
327  }
328  
329  /**********************************************************************/
330  /*!
331          @brief    Get the pixel color value at a given, unrotated coordinate.
332                This method is intended for hardware drivers to get pixel value
333                in physical coordinates.
334          @param    x   x coordinate
335          @param    y   y coordinate
336          @returns  The desired pixel's 16-bit 5-6-5 color value
337  */
338  /**********************************************************************/
339  uint16_t DVHSTX16::getRawPixel(int16_t x, int16_t y) const {
340    if ((x < 0) || (y < 0) || (x >= _width) || (y >= _height))
341      return 0;
342    uint16_t *buffer = getBuffer();
343    if (buffer) {
344      return buffer[x + y * _width];
345    }
346    return 0;
347  }
348  
349  /**************************************************************************/
350  /*!
351      @brief  Fill the framebuffer completely with one color
352      @param  color 16-bit 5-6-5 Color to fill with
353  */
354  /**************************************************************************/
355  void DVHSTX16::fillScreen(uint16_t color) {
356    uint16_t *buffer = getBuffer();
357    if (buffer) {
358      uint8_t hi = color >> 8, lo = color & 0xFF;
359      if (hi == lo) {
360        memset(buffer, lo, _width * _height * 2);
361      } else {
362        uint32_t i, pixels = _width * _height;
363        for (i = 0; i < pixels; i++)
364          buffer[i] = color;
365      }
366    }
367  }
368  
369  #if 0
370  /**************************************************************************/
371  /*!
372      @brief  Reverses the "endian-ness" of each 16-bit pixel within the
373              canvas; little-endian to big-endian, or big-endian to little.
374              Most microcontrollers (such as SAMD) are little-endian, while
375              most displays tend toward big-endianness. All the drawing
376              functions (including RGB bitmap drawing) take care of this
377              automatically, but some specialized code (usually involving
378              DMA) can benefit from having pixel data already in the
379              display-native order. Note that this does NOT convert to a
380              SPECIFIC endian-ness, it just flips the bytes within each word.
381  */
382  /**************************************************************************/
383  void DVHSTX16::byteSwap(void) {
384    uint16_t *buffer = getBuffer();
385    if (buffer) {
386      uint32_t i, pixels = _width * _height;
387      for (i = 0; i < pixels; i++)
388        buffer[i] = __builtin_bswap16(buffer[i]);
389    }
390  }
391  #endif
392  
393  /**************************************************************************/
394  /*!
395     @brief    Speed optimized vertical line drawing
396     @param    x   Line horizontal start point
397     @param    y   Line vertical start point
398     @param    h   length of vertical line to be drawn, including first point
399     @param    color   color 16-bit 5-6-5 Color to draw line with
400  */
401  /**************************************************************************/
402  void DVHSTX16::drawFastVLine(int16_t x, int16_t y, int16_t h,
403                                  uint16_t color) {
404    uint16_t *buffer = getBuffer();
405    if (!buffer) return;
406    if (h < 0) { // Convert negative heights to positive equivalent
407      h *= -1;
408      y -= h - 1;
409      if (y < 0) {
410        h += y;
411        y = 0;
412      }
413    }
414  
415    // Edge rejection (no-draw if totally off canvas)
416    if ((x < 0) || (x >= width()) || (y >= height()) || ((y + h - 1) < 0)) {
417      return;
418    }
419  
420    if (y < 0) { // Clip top
421      h += y;
422      y = 0;
423    }
424    if (y + h > height()) { // Clip bottom
425      h = height() - y;
426    }
427  
428    if (getRotation() == 0) {
429      drawFastRawVLine(x, y, h, color);
430    } else if (getRotation() == 1) {
431      int16_t t = x;
432      x = _width - 1 - y;
433      y = t;
434      x -= h - 1;
435      drawFastRawHLine(x, y, h, color);
436    } else if (getRotation() == 2) {
437      x = _width - 1 - x;
438      y = _height - 1 - y;
439  
440      y -= h - 1;
441      drawFastRawVLine(x, y, h, color);
442    } else if (getRotation() == 3) {
443      int16_t t = x;
444      x = y;
445      y = _height - 1 - t;
446      drawFastRawHLine(x, y, h, color);
447    }
448  }
449  
450  /**************************************************************************/
451  /*!
452     @brief  Speed optimized horizontal line drawing
453     @param  x      Line horizontal start point
454     @param  y      Line vertical start point
455     @param  w      Length of horizontal line to be drawn, including 1st point
456     @param  color  Color 16-bit 5-6-5 Color to draw line with
457  */
458  /**************************************************************************/
459  void DVHSTX16::drawFastHLine(int16_t x, int16_t y, int16_t w,
460                                  uint16_t color) {
461    uint16_t *buffer = getBuffer();
462    if (!buffer) return;
463    if (w < 0) { // Convert negative widths to positive equivalent
464      w *= -1;
465      x -= w - 1;
466      if (x < 0) {
467        w += x;
468        x = 0;
469      }
470    }
471  
472    // Edge rejection (no-draw if totally off canvas)
473    if ((y < 0) || (y >= height()) || (x >= width()) || ((x + w - 1) < 0)) {
474      return;
475    }
476  
477    if (x < 0) { // Clip left
478      w += x;
479      x = 0;
480    }
481    if (x + w >= width()) { // Clip right
482      w = width() - x;
483    }
484  
485    if (getRotation() == 0) {
486      drawFastRawHLine(x, y, w, color);
487    } else if (getRotation() == 1) {
488      int16_t t = x;
489      x = _width - 1 - y;
490      y = t;
491      drawFastRawVLine(x, y, w, color);
492    } else if (getRotation() == 2) {
493      x = _width - 1 - x;
494      y = _height - 1 - y;
495  
496      x -= w - 1;
497      drawFastRawHLine(x, y, w, color);
498    } else if (getRotation() == 3) {
499      int16_t t = x;
500      x = y;
501      y = _height - 1 - t;
502      y -= w - 1;
503      drawFastRawVLine(x, y, w, color);
504    }
505  }
506  
507  /**************************************************************************/
508  /*! 
509     @brief    Speed optimized horizontal line drawing into the raw canvas buffer
510     @param    x   Line horizontal start point
511     @param    y   Line vertical start point
512     @param    w   length of horizontal line to be drawn, including first point
513     @param    color   color 16-bit 5-6-5 Color to draw line with
514  */
515  /**************************************************************************/
516  void DVHSTX16::drawFastRawHLine(int16_t x, int16_t y, int16_t w,
517                                     uint16_t color) {
518    // x & y already in raw (rotation 0) coordinates, no need to transform.
519    uint16_t *buffer = getBuffer();
520    uint32_t buffer_index = y * WIDTH + x;
521    for (uint32_t i = buffer_index; i < buffer_index + w; i++) {
522      buffer[i] = color;
523    }
524  }
525  
526  /**************************************************************************/
527  /*!
528     @brief    Speed optimized vertical line drawing into the raw canvas buffer
529     @param    x   Line horizontal start point
530     @param    y   Line vertical start point
531     @param    h   length of vertical line to be drawn, including first point
532     @param    color   color 16-bit 5-6-5 Color to draw line with
533  */
534  /**************************************************************************/
535  void DVHSTX16::drawFastRawVLine(int16_t x, int16_t y, int16_t h,
536                                     uint16_t color) {
537    // x & y already in raw (rotation 0) coordinates, no need to transform.
538    uint16_t *buffer = getBuffer();
539    uint16_t *buffer_ptr = buffer + y * _width + x;
540    for (int16_t i = 0; i < h; i++) {
541      (*buffer_ptr) = color;
542      buffer_ptr += _width;
543    }
544  }
545  
546  
547  int16_t dvhstx_width(DVHSTXResolution r) {
548      switch(r) {
549  default:
550          case DVHSTX_RESOLUTION_320x180: return 320;
551          case DVHSTX_RESOLUTION_640x360: return 640;
552          case DVHSTX_RESOLUTION_480x270: return 480;
553          case DVHSTX_RESOLUTION_400x225: return 400;
554          case DVHSTX_RESOLUTION_320x240: return 320;
555          case DVHSTX_RESOLUTION_360x240: return 360;
556          case DVHSTX_RESOLUTION_360x200: return 360;
557          case DVHSTX_RESOLUTION_360x288: return 360;
558          case DVHSTX_RESOLUTION_400x300: return 400;
559          case DVHSTX_RESOLUTION_512x384: return 512;
560          case DVHSTX_RESOLUTION_400x240: return 400;
561      }
562      return 0;
563  }
564  
565  int16_t dvhstx_height(DVHSTXResolution r) {
566      switch(r) {
567  default:
568          case DVHSTX_RESOLUTION_320x180: return 180;
569          case DVHSTX_RESOLUTION_640x360: return 360;
570          case DVHSTX_RESOLUTION_480x270: return 270;
571          case DVHSTX_RESOLUTION_400x225: return 225;
572          case DVHSTX_RESOLUTION_320x240: return 240;
573          case DVHSTX_RESOLUTION_360x240: return 240;
574          case DVHSTX_RESOLUTION_360x200: return 200;
575          case DVHSTX_RESOLUTION_360x288: return 288;
576          case DVHSTX_RESOLUTION_400x300: return 300;
577          case DVHSTX_RESOLUTION_512x384: return 384;
578          case DVHSTX_RESOLUTION_400x240: return 240;
579      }
580  }
581