drv_fb.c 19 KB

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