Frästisch mit elektronischer Höhenverstellung mittels Schrittmotoren.
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

Display.cpp 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  1. /*
  2. * Display.cpp
  3. *
  4. * Wrapper class for Adafruit OLED display.
  5. *
  6. * Created on: 28.01.2022
  7. * Author: FSmilari
  8. */
  9. #include "Display.h"
  10. // Array of all bitmaps for convenience. (Total bytes used to store images in PROGMEM = 48)
  11. const int epd_rotate_bitmap_allArray_LEN = 8;
  12. const static unsigned char *epd_rotate_bitmap_allArray[epd_rotate_bitmap_allArray_LEN] = {
  13. epd_bitmap_Rotate_0,
  14. epd_bitmap_Rotate_45,
  15. epd_bitmap_Rotate_90,
  16. epd_bitmap_Rotate_135,
  17. epd_bitmap_Rotate_180,
  18. epd_bitmap_Rotate_225,
  19. epd_bitmap_Rotate_270,
  20. epd_bitmap_Rotate_315
  21. };
  22. /*****************
  23. ** Constructors.
  24. ****************/
  25. Display::Display() : mode(FAST) {
  26. ssd1306 = Adafruit_SSD1306(SCREEN_WIDTH, SCREEN_HEIGHT);
  27. u8g2_gfx.begin(ssd1306);
  28. wlsConnected = false;
  29. angle = 0;
  30. starttime = millis();
  31. refreshScreen = true;
  32. distanceValue = 0.0;
  33. distanceUnit = "mm";
  34. maxDiveDistance = 0.0;
  35. levelHeightDiving = 0.0;
  36. }
  37. /******************
  38. ** Public methods
  39. *****************/
  40. void Display::init() {
  41. if (!ssd1306.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS, true, true)) {
  42. Serial.println(F("SSD1306 allocation failed"));
  43. for (;;)
  44. ; // Don't proceed, loop forever
  45. }
  46. }
  47. void Display::setRefreshScreen() {
  48. refreshScreen = true;
  49. }
  50. void Display::display() {
  51. if (refreshScreen) {
  52. refreshScreen = false;
  53. ssd1306.display();
  54. }
  55. }
  56. void Display::clearDisplay() {
  57. ssd1306.clearDisplay();
  58. }
  59. void Display::showBrand() {
  60. ssd1306.clearDisplay();
  61. ssd1306.drawBitmap(0, 0, epd_bitmap_SFTools_Logo, imageWidth, imageHeight, SSD1306_WHITE);
  62. char *s = &String("Frästisch N172")[0];
  63. int16_t w = 0, h = 0;
  64. u8g2_gfx.setFont(u8g2_font_helvB12_tf);
  65. w = u8g2_gfx.getUTF8Width(s);
  66. h = u8g2_gfx.getFontAscent() - u8g2_gfx.getFontDescent();
  67. u8g2_gfx.setForegroundColor(SSD1306_WHITE);
  68. u8g2_gfx.setCursor((SCREEN_WIDTH - w) / 2, 63 - (30 - h) / 2);
  69. u8g2_gfx.println(F(s));
  70. display();
  71. }
  72. void Display::showInitialization() {
  73. ssd1306.clearDisplay();
  74. char *s = &String("Initialisieren")[0];
  75. int16_t w = 0;
  76. u8g2_gfx.setFont(u8g2_font_helvB12_tf);
  77. w = u8g2_gfx.getUTF8Width(s);
  78. u8g2_gfx.setForegroundColor(SSD1306_WHITE);
  79. u8g2_gfx.setCursor((SCREEN_WIDTH - w) / 2, 30);
  80. u8g2_gfx.println(F(s));
  81. char *g;
  82. w = u8g2_gfx.getUTF8Width(". . . . .");
  83. u8g2_gfx.setCursor((SCREEN_WIDTH - w) / 2, 50);
  84. String gauge = "";
  85. for (int i = 0; i < 6; i++) {
  86. g = &gauge[0];
  87. u8g2_gfx.print(g);
  88. setRefreshScreen();
  89. display();
  90. delay(500);
  91. if (i < 4) {
  92. gauge = ". ";
  93. g = &gauge[0];
  94. } else {
  95. gauge = ".";
  96. g = &gauge[0];
  97. }
  98. }
  99. }
  100. void Display::showFrame(Status status) {
  101. switch (status) {
  102. case MOVING_ELEVATOR:
  103. rotateAndDrawRotationBitmap();
  104. break;
  105. case TOOL_CHANGE:
  106. redrawFrame();
  107. drawStatusText(STATUS_TXT_TOOLCHG);
  108. drawBitmap(37 + (SCREEN_WIDTH - 37 - imageSide) / 2, (SCREEN_HEIGHT - imageSide) / 2, imageSide, imageSide, epd_bitmap_Tools);
  109. break;
  110. case CONFIGURATION:
  111. redrawFrame();
  112. ssd1306.drawLine(37, SCREEN_HEIGHT / 2 - 1, SCREEN_WIDTH - 1, SCREEN_HEIGHT / 2 - 1, SSD1306_WHITE);
  113. drawStatusText(STATUS_TXT_CFG);
  114. drawConfigText(this->configText);
  115. drawConfigOption(this->configOption);
  116. break;
  117. case IDLE:
  118. redrawFrame();
  119. ssd1306.drawLine(37, 43, SCREEN_WIDTH - 1, 43, SSD1306_WHITE);
  120. drawStatusText(STATUS_TXT_IDLE);
  121. drawDistanceValue(distanceValue);
  122. drawDistanceUnit(distanceUnit);
  123. drawMode(this->mode);
  124. break;
  125. case NULLING:
  126. case NULLING_TLS:
  127. redrawFrame();
  128. drawStatusText(STATUS_TXT_NULLING);
  129. drawBitmap(37 + (SCREEN_WIDTH - 37 - imageSide) / 2, (SCREEN_HEIGHT - imageSide) / 2, imageSide, imageSide, epd_bitmap_Nulling);
  130. break;
  131. case DIVING:
  132. redrawFrame();
  133. drawStatusText(STATUS_TXT_DIVING);
  134. drawBitmap((37 - imageSide_R) / 2, 47, imageSide_D, imageSide_D, epd_bitmap_Dive);
  135. drawDistanceValue(distanceValue);
  136. drawDistanceUnit(distanceUnit);
  137. drawActualDiveStep(maxDiveDistance, levelHeightDiving, distanceValue);
  138. drawMaxDiveDistance(maxDiveDistance);
  139. break;
  140. default:
  141. break;
  142. }
  143. display();
  144. }
  145. void Display::drawConfigText(String txt) {
  146. char *s = &txt[0];
  147. int16_t w = 0, h = 0;
  148. u8g2_gfx.setFont(u8g2_font_helvB12_tf); // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
  149. w = u8g2_gfx.getUTF8Width(s);
  150. h = u8g2_gfx.getFontAscent() - u8g2_gfx.getFontDescent();
  151. u8g2_gfx.setCursor((SCREEN_WIDTH + 37 - w) / 2, SCREEN_HEIGHT / 4 + h / 2 - 1); // start writing at this position
  152. u8g2_gfx.println(F(s));
  153. }
  154. void Display::drawConfigOption(String txt) {
  155. char *s = &txt[0];
  156. int16_t w = 0, h = 0;
  157. u8g2_gfx.setFont(u8g2_font_helvB12_tf);
  158. w = u8g2_gfx.getUTF8Width(s);
  159. h = u8g2_gfx.getFontAscent() - u8g2_gfx.getFontDescent();
  160. u8g2_gfx.setCursor((SCREEN_WIDTH + 37 - w) / 2, SCREEN_HEIGHT / 4 * 3 + h / 2 - 1);
  161. u8g2_gfx.println(F(s));
  162. }
  163. const String& Display::getConfigOption() const {
  164. return configOption;
  165. }
  166. void Display::setConfigOption(const String &configOption) {
  167. if (!this->configOption.equals(configOption)) {
  168. this->configOption = configOption;
  169. setRefreshScreen();
  170. }
  171. }
  172. const String& Display::getConfigText() const {
  173. return configText;
  174. }
  175. void Display::setConfigText(const String &configText) {
  176. if (!this->configText.equals(configText)) {
  177. this->configText = configText;
  178. setRefreshScreen();
  179. }
  180. }
  181. void Display::setWlsConnected(bool wlsConnected) {
  182. if (this->wlsConnected != wlsConnected) {
  183. this->wlsConnected = wlsConnected;
  184. setRefreshScreen();
  185. }
  186. }
  187. void Display::setLevelHeightDiving(float levelHeightDiving) {
  188. if (this->levelHeightDiving != levelHeightDiving) {
  189. this->levelHeightDiving = levelHeightDiving;
  190. setRefreshScreen();
  191. }
  192. }
  193. void Display::setMaxDiveDistance(float maxDiveDistance) {
  194. if (this->maxDiveDistance != maxDiveDistance) {
  195. this->maxDiveDistance = maxDiveDistance;
  196. setRefreshScreen();
  197. }
  198. }
  199. void Display::setDistanceUnit(const String &distanceUnit) {
  200. if (this->distanceUnit != distanceUnit) {
  201. this->distanceUnit = distanceUnit;
  202. setRefreshScreen();
  203. }
  204. }
  205. void Display::setDistanceValue(const float &distanceValue) {
  206. if (this->distanceValue != distanceValue) {
  207. this->distanceValue = distanceValue;
  208. setRefreshScreen();
  209. }
  210. }
  211. void Display::setMode(const ValueMode &mode) {
  212. if (!this->mode.equals(mode)) {
  213. this->mode = mode;
  214. setRefreshScreen();
  215. }
  216. }
  217. void Display::drawWLSStatus() {
  218. String txt = wlsConnected ? "WLS" : "";
  219. char *s = &txt[0];
  220. int16_t w = 0;
  221. u8g2_gfx.setFont(u8g2_font_helvR08_tf); // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
  222. w = u8g2_gfx.getUTF8Width(s);
  223. u8g2_gfx.setCursor((37 - w) / 2, 27);
  224. u8g2_gfx.println(F(s));
  225. }
  226. void Display::drawMode(ValueMode mode) {
  227. String txt = mode.toString();
  228. char *s = &txt[0];
  229. int16_t w = 0;
  230. u8g2_gfx.setFont(u8g2_font_helvB08_tf);
  231. w = u8g2_gfx.getUTF8Width(s);
  232. u8g2_gfx.setCursor((SCREEN_WIDTH - w - 6), 63 - 6);
  233. u8g2_gfx.println(F(s));
  234. }
  235. void Display::drawDistanceValue(float distance) {
  236. String txt = String(distance, 2);
  237. if (txt.equals("-0.00")) {
  238. txt.replace("-", "");
  239. }
  240. char *s = &txt[0];
  241. int16_t w = 0, h = 0;
  242. u8g2_gfx.setFont(u8g2_font_logisoso22_tf);
  243. w = u8g2_gfx.getUTF8Width(s);
  244. h = u8g2_gfx.getFontAscent() - u8g2_gfx.getFontDescent();
  245. u8g2_gfx.setCursor((SCREEN_WIDTH - w - 6), h);
  246. u8g2_gfx.println(F(s));
  247. }
  248. void Display::drawDistanceUnit(String unit) {
  249. String txt = unit;
  250. char *s = &txt[0];
  251. int16_t w = 0;
  252. u8g2_gfx.setFont(u8g2_font_helvB12_tf);
  253. w = u8g2_gfx.getUTF8Width(s);
  254. u8g2_gfx.setCursor((SCREEN_WIDTH - w - 6), 41);
  255. u8g2_gfx.println(F(s));
  256. }
  257. void Display::drawMaxDiveDistance(float maxDiveDistance) {
  258. String txt = String(maxDiveDistance, 2) + "mm";
  259. char *s = &txt[0];
  260. int16_t w = 0;
  261. u8g2_gfx.setFont(u8g2_font_helvB10_tf);
  262. w = u8g2_gfx.getUTF8Width(s);
  263. u8g2_gfx.setCursor((SCREEN_WIDTH - w - 6), 59);
  264. u8g2_gfx.println(F(s));
  265. }
  266. void Display::drawActualDiveStep(float maxDiveDistance, float levelHeightDiving, float distance) {
  267. int totalSteps = ceil(maxDiveDistance / levelHeightDiving);
  268. int actualStep = ceil(distance / levelHeightDiving);
  269. String txt = String(actualStep) + "/" + String(totalSteps);
  270. char *s = &txt[0];
  271. int16_t w = 0;
  272. u8g2_gfx.setFont(u8g2_font_helvB10_tf);
  273. w = u8g2_gfx.getUTF8Width(s);
  274. u8g2_gfx.setCursor(42, 59);
  275. u8g2_gfx.println(F(s));
  276. }
  277. /********************************
  278. ** Private methods
  279. *******************************/
  280. void Display::drawStatusText(String txt) {
  281. char *s = &txt[0];
  282. int16_t w = 0;
  283. u8g2_gfx.setFont(u8g2_font_helvR08_tf); // select u8g2 font from here: https://github.com/olikraus/u8g2/wiki/fntlistall
  284. w = u8g2_gfx.getUTF8Width(s);
  285. u8g2_gfx.setCursor((37 - w) / 2, 12);
  286. u8g2_gfx.println(F(s));
  287. }
  288. void Display::drawBitmap(int x, int y, int w, int h, const uint8_t bitmap[]) {
  289. ssd1306.drawBitmap(x, y, bitmap, w, h, SSD1306_WHITE);
  290. }
  291. void Display::redrawFrame() {
  292. ssd1306.clearDisplay();
  293. ssd1306.drawRoundRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, 3, SSD1306_WHITE);
  294. ssd1306.drawLine(37, 0, 37, SCREEN_HEIGHT - 1, SSD1306_WHITE);
  295. ssd1306.drawLine(0, 15, 37, 15, SSD1306_WHITE);
  296. drawWLSStatus();
  297. }
  298. void Display::rotateAndDrawRotationBitmap() {
  299. if (millis() - starttime >= 125) {
  300. int xOffset = 0;
  301. int yOffset = 0;
  302. switch (angle) {
  303. case 0:
  304. xOffset = imageSide_R / 2;
  305. yOffset = 0;
  306. break;
  307. case 1:
  308. xOffset = imageSide_R / 2;
  309. yOffset = imageSide_R / 4;
  310. break;
  311. case 2:
  312. xOffset = imageSide_R / 2;
  313. yOffset = imageSide_R / 2;
  314. break;
  315. case 3:
  316. xOffset = imageSide_R / 4;
  317. yOffset = imageSide_R / 2;
  318. break;
  319. case 4:
  320. xOffset = 0;
  321. yOffset = imageSide_R / 2;
  322. break;
  323. case 5:
  324. xOffset = 0;
  325. yOffset = imageSide_R / 4;
  326. break;
  327. case 6:
  328. xOffset = 0;
  329. yOffset = 0;
  330. break;
  331. case 7:
  332. xOffset = imageSide_R / 4;
  333. yOffset = 0;
  334. break;
  335. default:
  336. break;
  337. }
  338. ssd1306.fillRect((37 - imageSide_R) / 2 + xOffset, 30 + yOffset, imageSide_R / 2 + 1, imageSide_R / 2 + 1, SSD1306_BLACK);
  339. ssd1306.display();
  340. drawBitmap((37 - imageSide_R) / 2, 30, imageSide_R, imageSide_R, epd_rotate_bitmap_allArray[angle]);
  341. angle = (angle + 1) % 8;
  342. starttime = millis();
  343. setRefreshScreen();
  344. display();
  345. }
  346. }