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