1
0

drv_fb.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-08-29 zdzn first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include "mbox.h"
  13. #include "drv_fb.h"
  14. #include "mmu.h"
  15. #define CHAR_W 8
  16. #define CHAR_H 12
  17. #define COLOR_DELTA 0.05
  18. static struct rt_hdmi_fb_device _hdmi;
  19. fb_t fb_info;
  20. // https://github.com/xinu-os/xinu/blob/1789b7a50b5b73c2ea76ebd764c54a034097d04d/device/framebuffer_rpi/font.c
  21. unsigned char FONT[] = {
  22. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  23. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  24. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  25. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  26. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  27. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  28. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  29. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  30. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  31. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  32. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  33. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  34. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  35. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  36. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  37. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  38. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  39. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  40. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  41. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  42. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  43. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  44. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  45. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  46. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  47. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  48. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  49. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  50. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  51. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  52. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  53. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  54. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*' '*/
  55. 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*'!'*/
  56. 0x00, 0x14, 0x14, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'"'*/
  57. 0x00, 0x00, 0x14, 0x14, 0x3e, 0x14, 0x3e, 0x14, 0x14, 0x00, 0x00, 0x00, /*'#'*/
  58. 0x00, 0x00, 0x08, 0x3c, 0x0a, 0x1c, 0x28, 0x1e, 0x08, 0x00, 0x00, 0x00, /*'$'*/
  59. 0x00, 0x00, 0x06, 0x26, 0x10, 0x08, 0x04, 0x32, 0x30, 0x00, 0x00, 0x00, /*'%'*/
  60. 0x00, 0x00, 0x1c, 0x02, 0x02, 0x04, 0x2a, 0x12, 0x2c, 0x00, 0x00, 0x00, /*'&'*/
  61. 0x00, 0x18, 0x08, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'''*/
  62. 0x20, 0x10, 0x10, 0x08, 0x08, 0x08, 0x08, 0x08, 0x10, 0x10, 0x20, 0x00, /*'('*/
  63. 0x02, 0x04, 0x04, 0x08, 0x08, 0x08, 0x08, 0x08, 0x04, 0x04, 0x02, 0x00, /*')'*/
  64. 0x00, 0x00, 0x00, 0x08, 0x2a, 0x1c, 0x2a, 0x08, 0x00, 0x00, 0x00, 0x00, /*'*'*/
  65. 0x00, 0x00, 0x00, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /*'+'*/
  66. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /*','*/
  67. 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'-'*/
  68. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /*'.'*/
  69. 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04, 0x04, 0x02, 0x02, 0x00, 0x00, /*'/'*/
  70. 0x00, 0x1c, 0x22, 0x32, 0x2a, 0x26, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'0'*/
  71. 0x00, 0x08, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'1'*/
  72. 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'2'*/
  73. 0x00, 0x1c, 0x22, 0x20, 0x18, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'3'*/
  74. 0x00, 0x10, 0x18, 0x18, 0x14, 0x14, 0x3e, 0x10, 0x38, 0x00, 0x00, 0x00, /*'4'*/
  75. 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x20, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'5'*/
  76. 0x00, 0x18, 0x04, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'6'*/
  77. 0x00, 0x3e, 0x22, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x00, 0x00, 0x00, /*'7'*/
  78. 0x00, 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'8'*/
  79. 0x00, 0x1c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x10, 0x0c, 0x00, 0x00, 0x00, /*'9'*/
  80. 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, /*':'*/
  81. 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x18, 0x18, 0x08, 0x04, 0x00, /*';'*/
  82. 0x00, 0x00, 0x00, 0x30, 0x0c, 0x03, 0x0c, 0x30, 0x00, 0x00, 0x00, 0x00, /*'<'*/
  83. 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, /*'='*/
  84. 0x00, 0x00, 0x00, 0x03, 0x0c, 0x30, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00, /*'>'*/
  85. 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x08, 0x00, 0x08, 0x00, 0x00, 0x00, /*'?'*/
  86. 0x00, 0x00, 0x1c, 0x22, 0x3a, 0x3a, 0x1a, 0x02, 0x1c, 0x00, 0x00, 0x00, /*'@'*/
  87. 0x00, 0x00, 0x08, 0x14, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x00, 0x00, 0x00, /*'A'*/
  88. 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /*'B'*/
  89. 0x00, 0x00, 0x1c, 0x22, 0x02, 0x02, 0x02, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'C'*/
  90. 0x00, 0x00, 0x0e, 0x12, 0x22, 0x22, 0x22, 0x12, 0x0e, 0x00, 0x00, 0x00, /*'D'*/
  91. 0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'E'*/
  92. 0x00, 0x00, 0x3e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'F'*/
  93. 0x00, 0x00, 0x1c, 0x22, 0x02, 0x32, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /*'G'*/
  94. 0x00, 0x00, 0x22, 0x22, 0x22, 0x3e, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'H'*/
  95. 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e, 0x00, 0x00, 0x00, /*'I'*/
  96. 0x00, 0x00, 0x38, 0x20, 0x20, 0x20, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'J'*/
  97. 0x00, 0x00, 0x22, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /*'K'*/
  98. 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'L'*/
  99. 0x00, 0x00, 0x22, 0x36, 0x2a, 0x2a, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'M'*/
  100. 0x00, 0x00, 0x22, 0x26, 0x26, 0x2a, 0x32, 0x32, 0x22, 0x00, 0x00, 0x00, /*'N'*/
  101. 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'O'*/
  102. 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'P'*/
  103. 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x30, 0x00, 0x00, /*'Q'*/
  104. 0x00, 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x0a, 0x12, 0x22, 0x00, 0x00, 0x00, /*'R'*/
  105. 0x00, 0x00, 0x1c, 0x22, 0x02, 0x1c, 0x20, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'S'*/
  106. 0x00, 0x00, 0x3e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'T'*/
  107. 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'U'*/
  108. 0x00, 0x00, 0x22, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /*'V'*/
  109. 0x00, 0x00, 0x22, 0x22, 0x22, 0x2a, 0x2a, 0x36, 0x22, 0x00, 0x00, 0x00, /*'W'*/
  110. 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x14, 0x22, 0x22, 0x00, 0x00, 0x00, /*'X'*/
  111. 0x00, 0x00, 0x22, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, /*'Y'*/
  112. 0x00, 0x00, 0x3e, 0x20, 0x10, 0x08, 0x04, 0x02, 0x3e, 0x00, 0x00, 0x00, /*'Z'*/
  113. 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00, /*'['*/
  114. 0x02, 0x02, 0x04, 0x04, 0x08, 0x08, 0x10, 0x10, 0x20, 0x20, 0x00, 0x00, /*'\'*/
  115. 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x0e, 0x00, /*']'*/
  116. 0x00, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'^'*/
  117. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, /*'_'*/
  118. 0x00, 0x0c, 0x08, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'`'*/
  119. 0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /*'a'*/
  120. 0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x00, 0x00, 0x00, /*'b'*/
  121. 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x02, 0x02, 0x3c, 0x00, 0x00, 0x00, /*'c'*/
  122. 0x00, 0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x00, 0x00, 0x00, /*'d'*/
  123. 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x02, 0x1c, 0x00, 0x00, 0x00, /*'e'*/
  124. 0x00, 0x38, 0x04, 0x04, 0x1e, 0x04, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, /*'f'*/
  125. 0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /*'g'*/
  126. 0x00, 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'h'*/
  127. 0x00, 0x08, 0x08, 0x00, 0x0c, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /*'i'*/
  128. 0x00, 0x10, 0x10, 0x00, 0x1c, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x0e, /*'j'*/
  129. 0x00, 0x02, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x00, 0x00, 0x00, /*'k'*/
  130. 0x00, 0x0c, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x1c, 0x00, 0x00, 0x00, /*'l'*/
  131. 0x00, 0x00, 0x00, 0x00, 0x16, 0x2a, 0x2a, 0x2a, 0x22, 0x00, 0x00, 0x00, /*'m'*/
  132. 0x00, 0x00, 0x00, 0x00, 0x1a, 0x26, 0x22, 0x22, 0x22, 0x00, 0x00, 0x00, /*'n'*/
  133. 0x00, 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c, 0x00, 0x00, 0x00, /*'o'*/
  134. 0x00, 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02, /*'p'*/
  135. 0x00, 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x20, /*'q'*/
  136. 0x00, 0x00, 0x00, 0x00, 0x1a, 0x06, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, /*'r'*/
  137. 0x00, 0x00, 0x00, 0x00, 0x3c, 0x02, 0x1c, 0x20, 0x1e, 0x00, 0x00, 0x00, /*'s'*/
  138. 0x00, 0x08, 0x08, 0x08, 0x3e, 0x08, 0x08, 0x08, 0x30, 0x00, 0x00, 0x00, /*'t'*/
  139. 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x32, 0x2c, 0x00, 0x00, 0x00, /*'u'*/
  140. 0x00, 0x00, 0x00, 0x00, 0x36, 0x14, 0x14, 0x08, 0x08, 0x00, 0x00, 0x00, /*'v'*/
  141. 0x00, 0x00, 0x00, 0x00, 0x22, 0x2a, 0x2a, 0x2a, 0x14, 0x00, 0x00, 0x00, /*'w'*/
  142. 0x00, 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22, 0x00, 0x00, 0x00, /*'x'*/
  143. 0x00, 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20, 0x1c, /*'y'*/
  144. 0x00, 0x00, 0x00, 0x00, 0x3e, 0x10, 0x08, 0x04, 0x3e, 0x00, 0x00, 0x00, /*'z'*/
  145. 0x20, 0x10, 0x10, 0x10, 0x10, 0x08, 0x10, 0x10, 0x10, 0x10, 0x20, 0x00, /*'{'*/
  146. 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, /*'|'*/
  147. 0x02, 0x04, 0x04, 0x04, 0x04, 0x08, 0x04, 0x04, 0x04, 0x04, 0x02, 0x00, /*'}'*/
  148. 0x00, 0x04, 0x2a, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*'~'*/
  149. 0x00, 0x00, 0x00, 0x08, 0x08, 0x14, 0x14, 0x22, 0x3e, 0x00, 0x00, 0x00, /*DEL*/
  150. };
  151. void newline(fb_t* fb)
  152. {
  153. uint8_t* to;
  154. uint8_t* from;
  155. int i;
  156. fb->y++;
  157. fb->x = 0;
  158. if (fb->y == (fb->height / CHAR_H))
  159. {
  160. to = (uint8_t*) fb->addr;
  161. from = to + (CHAR_H * fb->pitch);
  162. for (i = 0; i < ((fb->height - CHAR_H) * fb->pitch); i++)
  163. {
  164. *to++ = *from++;
  165. }
  166. uint32_t *addr = (uint32_t*) (fb->addr) + (fb->height - CHAR_H) * fb->width;
  167. for (i = 0; i < (CHAR_H * fb->width); i++)
  168. {
  169. *addr++ = fb->back;
  170. }
  171. fb->y--;
  172. }
  173. }
  174. void clear_line(fb_t *fb, const int line)
  175. {
  176. int i;
  177. uint32_t* addr;
  178. if (line > fb->height / CHAR_H)
  179. {
  180. fb->y = 0;
  181. }
  182. else
  183. {
  184. fb->y = line;
  185. }
  186. fb->x = 0;
  187. addr = (uint32_t*) (fb->addr + (line * CHAR_H * fb->depth * fb->width));
  188. for (i = 0; i < (CHAR_H * fb->width); i++)
  189. {
  190. *addr++ = fb->back;
  191. }
  192. }
  193. void fb_draw_char(fb_t *fb, char s)
  194. {
  195. unsigned char* addr = (unsigned char*) fb->addr;
  196. unsigned char *glyph = (unsigned char*) FONT + (s) * 12;
  197. // calculate the offset on screen
  198. int offs = (fb->y * CHAR_H * fb->pitch) + (fb->x * (CHAR_W + 1) * 4);
  199. // variables
  200. int i, j, line, mask, bytesperline = (CHAR_W + 7) / 8;
  201. // display a character
  202. for (j = 0; j < CHAR_H; j++)
  203. {
  204. // display one row
  205. line = offs;
  206. mask = 1;
  207. for (i = 0; i < CHAR_W; i++)
  208. {
  209. // if bit set, we use white color, otherwise black
  210. *((unsigned int*) (addr + line)) = ((int) *glyph) & mask ? fb->fore : fb->back;
  211. mask <<= 1;
  212. line += 4;
  213. }
  214. // adjust to next line
  215. glyph += bytesperline;
  216. offs += fb->pitch;
  217. }
  218. }
  219. void fb_print(fb_t *fb, char *s)
  220. {
  221. // draw next character if it's not zero
  222. while (*s)
  223. {
  224. // handle carrige return
  225. if (*s == '\r')
  226. {
  227. fb->x = 0;
  228. }
  229. else if (*s == '\n')
  230. {
  231. newline(fb);
  232. }
  233. else if (*s == '\t')
  234. {
  235. fb->x = ((fb->x + 4) >> 2) << 2;
  236. }
  237. else if (*s == '\b')
  238. {
  239. if (fb->x)
  240. {
  241. fb->x--;
  242. fb_draw_char(fb, ' ');
  243. }
  244. }
  245. else
  246. {
  247. fb_draw_char(fb, *s);
  248. fb->x++;
  249. }
  250. // next character
  251. if (fb->x == fb->width / CHAR_W)
  252. {
  253. newline(fb);
  254. }
  255. s++;
  256. }
  257. }
  258. rt_err_t hdmi_fb_open(rt_device_t dev, rt_uint16_t oflag)
  259. {
  260. return RT_EOK;
  261. }
  262. rt_err_t hdmi_fb_close(rt_device_t dev)
  263. {
  264. return RT_EOK;
  265. }
  266. rt_size_t hdmi_fb_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t size)
  267. {
  268. return 0;
  269. }
  270. rt_size_t hdmi_fb_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  271. {
  272. fb_print(&_hdmi.fb, (char *) buffer);
  273. #ifdef BSP_USING_HDMI_DISPLAY
  274. rt_device_t uart = rt_device_find("uart1");
  275. int old_flag = uart->open_flag;
  276. uart->open_flag |= RT_DEVICE_FLAG_STREAM;
  277. rt_device_write(uart, 0, buffer, size);
  278. uart->open_flag = old_flag;
  279. #endif
  280. return size;
  281. }
  282. rt_err_t hdmi_fb_control(rt_device_t dev, int cmd, void *args)
  283. {
  284. return RT_EOK;
  285. }
  286. const static struct rt_device_ops hdmi_fb_ops =
  287. {
  288. RT_NULL,
  289. hdmi_fb_open,
  290. hdmi_fb_close,
  291. hdmi_fb_read,
  292. hdmi_fb_write,
  293. hdmi_fb_control
  294. };
  295. static struct rt_device_graphic_info _hdmi_info;
  296. static void hdmi_draw_rect(const char* pixel, int x1, int y1, int x2, int y2)
  297. {
  298. int i, j;
  299. int line;
  300. for (j = y1; j <= y2; j++)
  301. {
  302. line = (j * _hdmi.fb.pitch) + (x1 * 4);
  303. for (i = x1; i <= x2; i++)
  304. {
  305. // if bit set, we use white color, otherwise black
  306. *((unsigned int*) (_hdmi_info.framebuffer + line)) = *(unsigned int*) pixel;
  307. line += 4;
  308. }
  309. }
  310. }
  311. static void hdmi_set_pixel(const char* pixel, int x, int y)
  312. {
  313. *(uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)) = *(uint32_t *) pixel;
  314. }
  315. static void hdmi_get_pixel(char* pixel, int x, int y)
  316. {
  317. uint32_t ret = 0;
  318. ret = (*(uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4)) & 0x00FFFFFF);
  319. *pixel = ret;
  320. }
  321. static void hdmi_draw_hline(const char* pixel, int x1, int x2, int y)
  322. {
  323. hdmi_draw_rect(pixel, x1, y, x2, y);
  324. }
  325. static void hdmi_draw_vline(const char* pixel, int x, int y1, int y2)
  326. {
  327. hdmi_draw_rect(pixel, x, y1, x, y2);
  328. }
  329. static void hdmi_blit_line(const char* pixels, int x, int y, rt_size_t size)
  330. {
  331. int i = 0;
  332. uint32_t *pixel_base = (uint32_t*) (_hdmi.fb.addr + (y * _hdmi.fb.pitch + x * 4));
  333. uint32_t *colors = (uint32_t *) pixels;
  334. for (i = 0; i < size; i++)
  335. {
  336. pixel_base[i] = colors[i];
  337. }
  338. }
  339. static struct rt_device_graphic_ops hdmi_ops =
  340. {
  341. hdmi_set_pixel,
  342. hdmi_get_pixel,
  343. hdmi_draw_hline,
  344. hdmi_draw_vline,
  345. hdmi_blit_line
  346. };
  347. rt_err_t rt_hdmi_fb_device_init(struct rt_hdmi_fb_device *hdmi_fb, const char *name)
  348. {
  349. struct rt_device *device;
  350. RT_ASSERT(hdmi_fb != RT_NULL);
  351. device = &hdmi_fb->parent;
  352. device->user_data = &hdmi_ops;
  353. /* set device type */
  354. device->type = RT_Device_Class_Graphic;
  355. /* initialize device interface */
  356. #ifdef RT_USING_DEVICE_OPS
  357. device->ops = &hdmi_fb_ops;
  358. #else
  359. device->init = RT_NULL;
  360. device->open = hdmi_fb_open;
  361. device->close = hdmi_fb_close;
  362. device->read = hdmi_fb_read;
  363. device->write = hdmi_fb_write;
  364. device->control = hdmi_fb_control;
  365. #endif
  366. /* register to device manager */
  367. rt_device_register(device, name, RT_DEVICE_FLAG_RDWR);
  368. return RT_EOK;
  369. }
  370. /**
  371. * Show a picture
  372. */
  373. void print_fb_info()
  374. {
  375. rt_kprintf("FrameBuffer Info: \n \t width %x\t height %x\t depth %x\t addr %x\t size %x\t \n", fb_info.width,
  376. fb_info.height, fb_info.depth, fb_info.addr, fb_info.size);
  377. rt_kprintf("call mbox:%x,%x,%x,%x,%x\n", mbox[0], mbox[1], mbox[2], mbox[3], mbox[4]);
  378. }
  379. int hdmi_fb_init()
  380. {
  381. unsigned int *mbox = (unsigned int*) MBOX_ADDR;
  382. mbox[0] = 35 * 4;
  383. mbox[1] = MBOX_REQUEST;
  384. mbox[2] = 0x48003; //set phy wh
  385. mbox[3] = 8;
  386. mbox[4] = 8;
  387. mbox[5] = 640; //FrameBufferInfo.width
  388. mbox[6] = 480; //FrameBufferInfo.height
  389. mbox[7] = 0x48004; //set virt wh
  390. mbox[8] = 8;
  391. mbox[9] = 8;
  392. mbox[10] = 640; //FrameBufferInfo.virtual_width
  393. mbox[11] = 480; //FrameBufferInfo.virtual_height
  394. mbox[12] = 0x48009; //set virt offset
  395. mbox[13] = 8;
  396. mbox[14] = 8;
  397. mbox[15] = 0; //FrameBufferInfo.x_offset
  398. mbox[16] = 0; //FrameBufferInfo.y.offset
  399. mbox[17] = 0x48005; //set depth
  400. mbox[18] = 4;
  401. mbox[19] = 4;
  402. mbox[20] = 32; //FrameBufferInfo.depth
  403. mbox[21] = 0x48006; //set pixel order
  404. mbox[22] = 4;
  405. mbox[23] = 4;
  406. mbox[24] = 1; //RGB, not BGR preferably
  407. mbox[25] = 0x40001; //get framebuffer, gets alignment on request
  408. mbox[26] = 8;
  409. mbox[27] = 8;
  410. mbox[28] = 4096; //FrameBufferInfo.pointer
  411. mbox[29] = 0; //FrameBufferInfo.size
  412. mbox[30] = 0x40008; //get pitch
  413. mbox[31] = 4;
  414. mbox[32] = 4;
  415. mbox[33] = 0; //FrameBufferInfo.pitch
  416. mbox[34] = MBOX_TAG_LAST;
  417. if (mbox_call(MBOX_CH_PROP, MMU_DISABLE) && mbox[20] == 32 && mbox[28] != 0)
  418. {
  419. mbox[28] &= 0x3FFFFFFF;
  420. _hdmi.fb.width = mbox[5];
  421. _hdmi.fb.height = mbox[6];
  422. _hdmi.fb.pitch = mbox[33];
  423. //_hdmi.fb.addr = (void*)((unsigned long)mbox[28]);
  424. _hdmi.fb.addr = (rt_uint32_t) mbox[28];
  425. _hdmi.fb.size = mbox[29];
  426. _hdmi.fb.depth = 32;
  427. _hdmi.fb.x = 0;
  428. _hdmi.fb.y = 0;
  429. _hdmi.fb.fore = CONSOLE_WHITE;
  430. _hdmi.fb.back = CONSOLE_BLACK;
  431. rt_hdmi_fb_device_init(&_hdmi, "hdmi");
  432. rt_hw_change_mmu_table(_hdmi.fb.addr, _hdmi.fb.size, _hdmi.fb.addr, DEVICE_MEM);
  433. fb_info.width = _hdmi.fb.width;
  434. fb_info.height = _hdmi.fb.height;
  435. fb_info.addr = _hdmi.fb.addr;
  436. fb_info.size = _hdmi.fb.size;
  437. fb_info.pitch = _hdmi.fb.pitch;
  438. fb_info.depth = _hdmi.fb.depth;
  439. _hdmi_info.pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB888;
  440. _hdmi_info.bits_per_pixel = _hdmi.fb.depth;
  441. _hdmi_info.width = _hdmi.fb.width;
  442. _hdmi_info.height = _hdmi.fb.height;
  443. _hdmi_info.framebuffer = (rt_uint8_t *) _hdmi.fb.addr;
  444. }
  445. return 0;
  446. }
  447. INIT_DEVICE_EXPORT(hdmi_fb_init);