Distanz-/Tiefenmesser mit JSN-SR40T
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

Display.cpp 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. /*
  2. * Display.cpp
  3. *
  4. * Created on: 05.01.2026
  5. * Author: FSmilari
  6. */
  7. #include "Display.h"
  8. #include "Adafruit_ST7735.h"
  9. #include "images/SFToolsLogo.h"
  10. #include "fonts/titillium_web_regular16pt7b.h" // Add a custom font
  11. #include "fonts/titillium_web_regular10pt7b.h" // Add a custom font
  12. #include "fonts/titillium_web_semibold10pt7b.h" // Add a custom font
  13. #include "fonts/titillium_web_regular8pt7b.h" // Add a custom font
  14. #include "fonts/titillium_web_semibold8pt7b.h" // Add a custom font
  15. #include <Fonts/FreeSans9pt7b.h> // Add a custom font
  16. #include "images/stm32duino_logo.h"
  17. #include "images/thermometer_32.h"
  18. #include "images/gear.h"
  19. #include "images/zzz.h"
  20. #include "images/ruler.h"
  21. #include "images/air.h"
  22. #include "images/water.h"
  23. #include "images/water_s.h"
  24. //#define LED -1 // to +5v
  25. //#define SCK PA5
  26. //#define SDA PA7
  27. //#define MISO -1
  28. //#define MOSI SDA
  29. #define CS PA2
  30. #define DC PA1
  31. #define RST PA0
  32. #define ST7735_ARDUINOGREEN 0x04b3
  33. #define ST7735_STM32BLUE 0x03d6
  34. #define ST7735_DODGERBLUE 0x249f
  35. /*****************
  36. ** Constructors.
  37. ****************/
  38. Display::Display() : tft(Adafruit_ST7735(CS, DC, RST)) { // @suppress("Abstract class cannot be instantiated")
  39. starttime = 0;
  40. configValue = 0.0;
  41. configUnit = "m/s";
  42. distance = 0;
  43. environment = 1;
  44. waterTemp = 20.0;
  45. airTemp = 20.0;
  46. refreshScreen = true;
  47. doMeasureAnimation = false;
  48. }
  49. void Display::init(void) {
  50. tft.initR(INITR_BLACKTAB);
  51. tft.fillScreen(ST7735_BLACK);
  52. tft.setRotation(1);
  53. tft.setTextWrap(false);
  54. tft.setTextColor(ST7735_WHITE);
  55. refreshScreen = true;
  56. }
  57. void Display::setRefreshScreen() {
  58. refreshScreen = true;
  59. }
  60. void Display::drawXCenteredText(String txt, const GFXfont *font, uint8_t size, uint16_t col, int16_t y) {
  61. int16_t x1, y1; // Top-left corner of text
  62. uint16_t w, h; // Width and height
  63. tft.setFont(font);
  64. tft.setTextSize(size); // Set text size. Goes from 0 (the smallest) to 20 (very big)
  65. tft.setTextColor(col);
  66. // Get bounds starting from (0, 0)
  67. tft.getTextBounds(txt, 0, 0, &x1, &y1, &w, &h);
  68. // Calculate centered position
  69. int16_t centered_x = (SCREEN_WIDTH - w) / 2 - 3;
  70. // Set cursor and print
  71. tft.setCursor(centered_x, y);
  72. tft.print(txt);
  73. }
  74. void Display::drawRightAlignedText(String txt, const GFXfont *font, uint8_t size, uint16_t col, int16_t xOffset, int16_t y) {
  75. int16_t x1, y1; // Top-left corner of text
  76. uint16_t w, h; // Width and height
  77. tft.setFont(font);
  78. tft.setTextSize(size); // Set text size. Goes from 0 (the smallest) to 20 (very big)
  79. tft.setTextColor(col);
  80. // Get bounds starting from (0, 0)
  81. tft.getTextBounds(txt, 0, 0, &x1, &y1, &w, &h);
  82. // Calculate position
  83. int16_t rightAligned_x = (SCREEN_WIDTH - xOffset) - w;
  84. // Set cursor and print
  85. tft.setCursor(rightAligned_x, y);
  86. tft.print(txt);
  87. }
  88. void Display::drawText(String txt, const GFXfont *font, uint8_t size, uint16_t col, int16_t x, int16_t y) {
  89. tft.setFont(font);
  90. tft.setTextSize(size); // Set text size. Goes from 0 (the smallest) to 20 (very big)
  91. tft.setTextColor(col);
  92. tft.setCursor(x, y);
  93. tft.print(txt);
  94. }
  95. void Display::drawCircle(int16_t x0, int16_t y0, int16_t r, uint16_t color) {
  96. tft.drawCircle(x0, y0, r, color);
  97. }
  98. void Display::clearDisplay(void) {
  99. tft.fillScreen(ST7735_BLACK);
  100. }
  101. void Display::showBrand(int16_t x, int16_t y) {
  102. drawBitmap(x, y, 128, 34, SFTools_Logo, ST7735_ORANGE);
  103. }
  104. void Display::showInitialization(void) {
  105. redrawFrame();
  106. drawXCenteredText("EchoLoT", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 36);
  107. drawXCenteredText("designed by", &FreeSans9pt7b, 1, ST7735_WHITE, 64);
  108. showBrand(16, 84);
  109. delay(500);
  110. redrawFrame();
  111. drawText("powered by", &FreeSans9pt7b, 1, ST7735_CYAN, 35, 30);
  112. tft.fillRoundRect(46, 42, 68, 68, 7, ST7735_STM32BLUE);
  113. drawBitmap(48, 44, 64, 64, epd_bitmap_stm32duino_logo_icon, ST7735_WHITE);
  114. // tft.drawBitmap(5, 100, epd_bitmap_gear, 24, 24, ST7735_YELLOW);
  115. // tft.drawBitmap(40, 100, epd_bitmap_Zzz_24, 24, 24, ST7735_CYAN);
  116. // tft.drawBitmap(75, 100, epd_bitmap_Measure_25, 25, 25, ST7735_RED);
  117. // tft.fillTriangle(75, 98, 80, 102, 75, 107, ST7735_RED);
  118. // tft.fillTriangle(82, 98, 87, 102, 82, 107, ST7735_RED);
  119. // tft.fillTriangle(89, 98, 94, 102, 89, 107, ST7735_RED);
  120. // tft.fillTriangle(96, 98, 101, 102, 96, 107, ST7735_RED);
  121. //
  122. // tft.drawBitmap(110, 100, epd_bitmap_air, 24, 24, ST7735_CYAN);
  123. // tft.drawBitmap(110, 100, epd_bitmap_water, 24, 24, ST7735_BLUE);
  124. // tft.drawBitmap(110, 100, epd_bitmap_water_s, 24, 24, ST7735_BLUE);
  125. // tft.drawBitmap(1, 160 - 32, thermometer_icon_32, 32, 32, 0xE71C);
  126. delay(500);
  127. }
  128. void Display::display(void) {
  129. if (!refreshScreen) {
  130. return;
  131. }
  132. refreshScreen = false;
  133. }
  134. void Display::showFrame(Status status) {
  135. switch (status) {
  136. case Status::INITIALIZATION:
  137. redrawFrame();
  138. break;
  139. case Status::IDLE:
  140. if (refreshScreen) {
  141. redrawIdleStatus();
  142. refreshScreen = false;
  143. }
  144. break;
  145. case Status::CONFIGURATION:
  146. if (refreshScreen) {
  147. redrawConfigStatus();
  148. refreshScreen = false;
  149. }
  150. break;
  151. default:
  152. break;
  153. }
  154. }
  155. void Display::setStatusValues(float airTemp, float waterTemp) {
  156. this->airTemp = airTemp;
  157. this->waterTemp = waterTemp;
  158. }
  159. void Display::setEnvironment(int environment) {
  160. if (this->environment != environment) {
  161. this->environment = environment;
  162. redrawEnvIcon();
  163. }
  164. }
  165. void Display::setDistance(uint32_t distance) {
  166. if (this->distance != distance) {
  167. this->distance = distance;
  168. redrawDistance();
  169. }
  170. }
  171. /* ===== Private methods ===== */
  172. void Display::drawBitmap(int x, int y, int w, int h, const uint8_t bitmap[], uint16_t col) {
  173. tft.drawBitmap(x, y, bitmap, w, h, col);
  174. }
  175. void Display::drawRGBBitmap(int x, int y, int w, int h, const uint16_t bitmap[]) {
  176. tft.drawRGBBitmap(x, y, bitmap, w, h);
  177. }
  178. void Display::redrawFrame() {
  179. clearDisplay();
  180. tft.drawRoundRect(0, 0, 160, 128, 9, ST7735_CYAN);
  181. tft.drawRoundRect(1, 1, 158, 126, 8, ST7735_CYAN);
  182. }
  183. void Display::redrawGrid() {
  184. redrawFrame();
  185. tft.drawLine(0, 31, 160, 31, ST7735_CYAN);
  186. tft.drawLine(0, 32, 160, 32, ST7735_CYAN);
  187. tft.drawLine(0, 89, 160, 89, ST7735_CYAN);
  188. tft.drawLine(0, 90, 160, 90, ST7735_CYAN);
  189. tft.drawLine(80, 90, 80, 128, ST7735_CYAN);
  190. tft.drawLine(81, 90, 81, 128, ST7735_CYAN);
  191. }
  192. void Display::redrawIdleStatus() {
  193. redrawGrid();
  194. tft.drawBitmap(25, 4, epd_bitmap_Zzz_24, 24, 24, ST7735_CYAN);
  195. drawText("OPERATIV", &titillium_web_semibold8pt7b, 1, ST7735_WHITE, 55, 21);
  196. float temp = environment == 1 ? airTemp : waterTemp;
  197. uint16_t col = temp <= 17.0 ? ST7735_WHITE : temp <= 24.0 ? ST7735_GREEN : ST7735_ORANGE;
  198. uint16_t thH = temp <= 17.0 ? 0 : temp <= 24.0 ? 5 : 9;
  199. tft.drawBitmap(0, 92, thermometer_icon_32, 32, 32, col);
  200. tft.drawRect(15, 107 - thH, 2, thH, col);
  201. drawText(String(temp, 1), &titillium_web_semibold8pt7b, 1, col, 35, 114);
  202. drawCircle(72, 102, 2, col);
  203. redrawEnvIcon();
  204. redrawDistance();
  205. }
  206. void Display::redrawConfigStatus() {
  207. redrawGrid();
  208. tft.drawBitmap(35, 4, epd_bitmap_gear, 24, 24, ST7735_YELLOW);
  209. drawText("KONFIG.", &titillium_web_semibold8pt7b, 1, ST7735_WHITE, 65, 21);
  210. }
  211. void Display::redrawEnvIcon() {
  212. const uint8_t *environmentIcon = environment == 1 ? epd_bitmap_air : environment == 2 ? epd_bitmap_water : epd_bitmap_water_s;
  213. uint16_t col = environment == 1 ? ST7735_WHITE : ST7735_DODGERBLUE;
  214. tft.fillRect(83, 92, 72, 33, ST7735_BLACK);
  215. tft.drawBitmap(108, 97, environmentIcon, 24, 24, col);
  216. }
  217. void Display::runMeasureAnimation(bool run) {
  218. if (!this->doMeasureAnimation && run) {
  219. this->starttime = millis();
  220. this->doMeasureAnimation = run;
  221. } else if (this->doMeasureAnimation && !run) {
  222. this->starttime = 0;
  223. this->doMeasureAnimation = run;
  224. }
  225. tft.fillRect(24, 3, 28, 28, ST7735_BLACK);
  226. if (this->doMeasureAnimation && starttime != 0) {
  227. uint8_t lvl = ((millis() - starttime) / 1000) % 4;
  228. tft.drawBitmap(25, 4, epd_bitmap_Measure_25, 25, 25, ST7735_RED);
  229. switch (lvl) {
  230. case 0:
  231. tft.fillTriangle(25, 4, 30, 9, 25, 13, ST7735_RED);
  232. tft.fillTriangle(32, 4, 37, 9, 32, 13, ST7735_BLACK);
  233. tft.fillTriangle(39, 4, 44, 9, 39, 13, ST7735_BLACK);
  234. tft.fillTriangle(46, 4, 51, 9, 46, 13, ST7735_BLACK);
  235. break;
  236. case 1:
  237. tft.fillTriangle(25, 4, 30, 9, 25, 13, ST7735_BLACK);
  238. tft.fillTriangle(32, 4, 37, 9, 32, 13, ST7735_RED);
  239. tft.fillTriangle(39, 4, 44, 9, 39, 13, ST7735_BLACK);
  240. tft.fillTriangle(46, 4, 51, 9, 46, 13, ST7735_BLACK);
  241. break;
  242. case 2:
  243. tft.fillTriangle(25, 4, 30, 9, 25, 13, ST7735_BLACK);
  244. tft.fillTriangle(32, 4, 37, 9, 32, 13, ST7735_BLACK);
  245. tft.fillTriangle(39, 4, 44, 9, 39, 13, ST7735_RED);
  246. tft.fillTriangle(46, 4, 51, 9, 46, 13, ST7735_BLACK);
  247. break;
  248. case 3:
  249. tft.fillTriangle(25, 4, 30, 9, 25, 13, ST7735_BLACK);
  250. tft.fillTriangle(32, 4, 37, 9, 32, 13, ST7735_BLACK);
  251. tft.fillTriangle(39, 4, 44, 9, 39, 13, ST7735_BLACK);
  252. tft.fillTriangle(46, 4, 51, 9, 46, 13, ST7735_RED);
  253. break;
  254. default:
  255. break;
  256. }
  257. } else {
  258. tft.drawBitmap(25, 4, epd_bitmap_Zzz_24, 24, 24, ST7735_CYAN);
  259. }
  260. }
  261. void Display::redrawDistance() {
  262. tft.fillRect(4, 34, 152, 56, ST7735_BLACK);
  263. if (distance == 0) {
  264. drawXCenteredText("- - -", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 69);
  265. } else {
  266. if (environment == 1) {
  267. uint16_t dist_CM = distance / 10;
  268. drawXCenteredText(String(dist_CM) + " cm", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 69);
  269. } else {
  270. float dist_M = float(distance) / 1000;
  271. drawXCenteredText(String(dist_M, 1) + " m", &titillium_web_regular16pt7b, 1, ST7735_CYAN, 69);
  272. }
  273. }
  274. }