GxEPD2_WiFi_Native7c.h 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. uint8_t color7(uint16_t red, uint16_t green, uint16_t blue)
  2. {
  3. uint8_t cv7 = 0x00;
  4. if ((red < 0x80) && (green < 0x80) && (blue < 0x80)) cv7 = 0x00; // black
  5. else if ((red >= 0x80) && (green >= 0x80) && (blue >= 0x80)) cv7 = 0x01; // white
  6. else if ((red >= 0x80) && (blue >= 0x80)) cv7 = red > blue ? 0x04 : 0x03; // red, blue
  7. else if ((green >= 0x80) && (blue >= 0x80)) cv7 = green > blue ? 0x02 : 0x03; // green, blue
  8. else if ((red >= 0x80) && (green >= 0xC0)) cv7 = 0x05; // yellow
  9. else if ((red >= 0x80) && (green >= 0x40)) cv7 = 0x06; // orange
  10. else if (red >= 0x80) cv7 = 0x04; // red
  11. else if (green >= 0x80) cv7 = 0x02; // green
  12. else cv7 = 0x03; // blue
  13. return cv7;
  14. }
  15. void whiteLine()
  16. {
  17. for (size_t i = 0; i < sizeof(output_row_native4c_buffer); i++) output_row_native4c_buffer[i] = 0x11;
  18. }
  19. void showNative7cFrom_HTTP(const char* host, const char* path, const char* filename, int16_t x, int16_t y)
  20. {
  21. WiFiClient client;
  22. bool connection_ok = false;
  23. bool valid = false; // valid format to be handled
  24. bool flip = true; // bitmap is stored bottom-to-top
  25. uint32_t startTime = millis();
  26. if ((x >= display.epd2.WIDTH) || (y >= display.epd2.HEIGHT)) return;
  27. Serial.println(); Serial.print("downloading file \""); Serial.print(filename); Serial.println("\"");
  28. Serial.print("connecting to "); Serial.println(host);
  29. if (!client.connect(host, httpPort))
  30. {
  31. Serial.println("connection failed");
  32. return;
  33. }
  34. Serial.print("requesting URL: ");
  35. Serial.println(String("http://") + host + path + filename);
  36. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  37. "Host: " + host + "\r\n" +
  38. "User-Agent: GxEPD2_WiFi_Example\r\n" +
  39. "Connection: close\r\n\r\n");
  40. Serial.println("request sent");
  41. while (client.connected())
  42. {
  43. String line = client.readStringUntil('\n');
  44. if (!connection_ok)
  45. {
  46. connection_ok = line.startsWith("HTTP/1.1 200 OK");
  47. if (connection_ok) Serial.println(line);
  48. }
  49. if (!connection_ok) Serial.println(line);
  50. if (line == "\r")
  51. {
  52. Serial.println("headers received");
  53. break;
  54. }
  55. }
  56. if (!connection_ok) return;
  57. // Parse BMP header
  58. if (read16(client) == 0x4D42) // BMP signature
  59. {
  60. uint32_t fileSize = read32(client);
  61. uint32_t creatorBytes = read32(client); (void)creatorBytes; //unused
  62. uint32_t imageOffset = read32(client); // Start of image data
  63. uint32_t headerSize = read32(client);
  64. uint32_t width = read32(client);
  65. int32_t height = (int32_t) read32(client);
  66. uint16_t planes = read16(client);
  67. uint16_t depth = read16(client); // bits per pixel
  68. uint32_t format = read32(client);
  69. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  70. if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
  71. {
  72. Serial.print("File size: "); Serial.println(fileSize);
  73. Serial.print("Image Offset: "); Serial.println(imageOffset);
  74. Serial.print("Header size: "); Serial.println(headerSize);
  75. Serial.print("Bit Depth: "); Serial.println(depth);
  76. Serial.print("Image size: ");
  77. Serial.print(width);
  78. Serial.print('x');
  79. Serial.println(abs(height));
  80. // BMP rows are padded (if needed) to 4-byte boundary
  81. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  82. if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
  83. if (height < 0)
  84. {
  85. height = -height;
  86. flip = false;
  87. }
  88. uint16_t w = width;
  89. uint16_t h = height;
  90. if ((x + w - 1) >= display.epd2.WIDTH) w = display.epd2.WIDTH - x;
  91. if ((y + h - 1) >= display.epd2.HEIGHT) h = display.epd2.HEIGHT - y;
  92. if (w <= max_row_width) // handle with direct drawing
  93. {
  94. valid = true;
  95. uint8_t bitmask = 0xFF;
  96. uint8_t bitshift = 8 - depth;
  97. uint16_t red, green, blue;
  98. uint8_t cv7 = 0x00;
  99. if (depth <= 8)
  100. {
  101. if (depth < 8) bitmask >>= depth;
  102. bytes_read += skip(client, imageOffset - (4 << depth) - bytes_read); // 54 for regular, diff for colorsimportant
  103. for (uint16_t pn = 0; pn < (1 << depth); pn++)
  104. {
  105. blue = client.read();
  106. green = client.read();
  107. red = client.read();
  108. client.read();
  109. bytes_read += 4;
  110. rgb_palette_buffer[pn] = color7(red, green, blue);
  111. }
  112. }
  113. display.epd2.setPaged();
  114. whiteLine();
  115. for (uint16_t l = 0; l < y; l++)
  116. {
  117. display.writeNative(output_row_native4c_buffer, 0, 0, l, display.epd2.WIDTH, 1, false, false, false);
  118. }
  119. uint32_t rowPosition = imageOffset;
  120. bytes_read += skip(client, rowPosition - bytes_read);
  121. for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
  122. {
  123. if (!connection_ok || !(client.connected() || client.available())) break;
  124. delay(1); // yield() to avoid WDT
  125. uint32_t in_remain = rowSize;
  126. uint32_t in_idx = 0;
  127. uint32_t in_bytes = 0;
  128. uint8_t in_byte = 0; // for depth <= 8
  129. uint8_t in_bits = 0; // for depth <= 8
  130. uint8_t out_cv7_byte = 0x00;
  131. uint32_t out_idx = 0;
  132. for (uint16_t col = 0; col < w; col++) // for each pixel
  133. {
  134. yield();
  135. if (!connection_ok || !(client.connected() || client.available())) break;
  136. // Time to read more pixel data?
  137. if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
  138. {
  139. uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
  140. uint32_t got = read8n(client, input_buffer, get);
  141. while ((got < get) && connection_ok)
  142. {
  143. //Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
  144. uint32_t gotmore = read8n(client, input_buffer + got, get - got);
  145. got += gotmore;
  146. connection_ok = gotmore > 0;
  147. }
  148. in_bytes = got;
  149. in_remain -= got;
  150. bytes_read += got;
  151. in_idx = 0;
  152. }
  153. if (!connection_ok)
  154. {
  155. Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
  156. break;
  157. }
  158. switch (depth)
  159. {
  160. case 32:
  161. blue = input_buffer[in_idx++];
  162. green = input_buffer[in_idx++];
  163. red = input_buffer[in_idx++];
  164. in_idx++; // skip alpha
  165. cv7 = color7(red, green, blue);
  166. break;
  167. case 24:
  168. blue = input_buffer[in_idx++];
  169. green = input_buffer[in_idx++];
  170. red = input_buffer[in_idx++];
  171. cv7 = color7(red, green, blue);
  172. break;
  173. case 16:
  174. {
  175. uint8_t lsb = input_buffer[in_idx++];
  176. uint8_t msb = input_buffer[in_idx++];
  177. if (format == 0) // 555
  178. {
  179. blue = (lsb & 0x1F) << 3;
  180. green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
  181. red = (msb & 0x7C) << 1;
  182. }
  183. else // 565
  184. {
  185. blue = (lsb & 0x1F) << 3;
  186. green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
  187. red = (msb & 0xF8);
  188. }
  189. }
  190. cv7 = color7(red, green, blue);
  191. break;
  192. case 1:
  193. case 2:
  194. case 4:
  195. case 8:
  196. {
  197. if (0 == in_bits)
  198. {
  199. in_byte = input_buffer[in_idx++];
  200. in_bits = 8;
  201. }
  202. uint16_t pn = (in_byte >> bitshift) & bitmask;
  203. cv7 = rgb_palette_buffer[pn];
  204. in_byte <<= depth;
  205. in_bits -= depth;
  206. }
  207. break;
  208. }
  209. out_cv7_byte |= cv7 << (4 * (1 - col % 2));
  210. if ((1 == col % 2) || (col == w - 1)) // write that last byte! (for w%2!=0 border)
  211. {
  212. uint32_t bx = flip ? (display.epd2.WIDTH - x) / 2 - out_idx++ : x / 2 + out_idx++;
  213. output_row_native4c_buffer[bx] = out_cv7_byte;
  214. out_cv7_byte = 0x00;
  215. }
  216. } // end pixel
  217. display.writeNative(output_row_native4c_buffer, 0, 0, y + row, display.epd2.WIDTH, 1, false, false, false);
  218. } // end line
  219. Serial.print("downloaded in ");
  220. Serial.print(millis() - startTime);
  221. Serial.println(" ms");
  222. whiteLine();
  223. for (uint16_t l = y + h; l < display.epd2.HEIGHT; l++)
  224. {
  225. display.writeNative(output_row_native4c_buffer, 0, 0, l, display.epd2.WIDTH, 1, false, false, false);
  226. }
  227. display.refresh();
  228. }
  229. Serial.print("bytes read "); Serial.println(bytes_read);
  230. }
  231. }
  232. client.stop();
  233. if (!valid)
  234. {
  235. Serial.println("bitmap format not handled.");
  236. }
  237. }
  238. void showNative7cFrom_HTTPS(const char* host, const char* path, const char* filename, const char* fingerprint, int16_t x, int16_t y, bool with_color, const char* certificate)
  239. {
  240. // Use WiFiClientSecure class to create TLS connection
  241. #if defined (ESP8266) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
  242. BearSSL::WiFiClientSecure client;
  243. BearSSL::X509List cert(certificate ? certificate : certificate_rawcontent);
  244. #else
  245. WiFiClientSecure client;
  246. #endif
  247. bool connection_ok = false;
  248. bool valid = false; // valid format to be handled
  249. bool flip = true; // bitmap is stored bottom-to-top
  250. uint32_t startTime = millis();
  251. if ((x >= display.epd2.WIDTH) || (y >= display.epd2.HEIGHT)) return;
  252. Serial.println(); Serial.print("downloading file \""); Serial.print(filename); Serial.println("\"");
  253. Serial.print("connecting to "); Serial.println(host);
  254. #if defined (ESP8266) || defined(ARDUINO_RASPBERRY_PI_PICO_W)
  255. if (certificate) client.setTrustAnchors(&cert);
  256. else if (fingerprint) client.setFingerprint(fingerprint);
  257. else client.setInsecure();
  258. #elif defined (ESP32)
  259. if (certificate) client.setCACert(certificate);
  260. #endif
  261. if (!client.connect(host, httpsPort))
  262. {
  263. Serial.println("connection failed");
  264. return;
  265. }
  266. Serial.print("requesting URL: ");
  267. Serial.println(String("https://") + host + path + filename);
  268. client.print(String("GET ") + path + filename + " HTTP/1.1\r\n" +
  269. "Host: " + host + "\r\n" +
  270. "User-Agent: GxEPD2_WiFi_Example\r\n" +
  271. "Connection: close\r\n\r\n");
  272. Serial.println("request sent");
  273. while (client.connected())
  274. {
  275. String line = client.readStringUntil('\n');
  276. if (!connection_ok)
  277. {
  278. connection_ok = line.startsWith("HTTP/1.1 200 OK");
  279. if (connection_ok) Serial.println(line);
  280. }
  281. if (!connection_ok) Serial.println(line);
  282. if (line == "\r")
  283. {
  284. Serial.println("headers received");
  285. break;
  286. }
  287. }
  288. if (!connection_ok) return;
  289. // Parse BMP header
  290. uint16_t signature = 0;
  291. for (int16_t i = 0; i < 50; i++)
  292. {
  293. if (!client.available()) delay(100);
  294. else signature = read16(client);
  295. if (signature == 0x4D42) break;
  296. }
  297. if (signature == 0x4D42) // BMP signature
  298. {
  299. uint32_t fileSize = read32(client);
  300. uint32_t creatorBytes = read32(client); (void)creatorBytes; //unused
  301. uint32_t imageOffset = read32(client); // Start of image data
  302. uint32_t headerSize = read32(client);
  303. uint32_t width = read32(client);
  304. int32_t height = (int32_t) read32(client);
  305. uint16_t planes = read16(client);
  306. uint16_t depth = read16(client); // bits per pixel
  307. uint32_t format = read32(client);
  308. uint32_t bytes_read = 7 * 4 + 3 * 2; // read so far
  309. if ((planes == 1) && ((format == 0) || (format == 3))) // uncompressed is handled, 565 also
  310. {
  311. Serial.print("File size: "); Serial.println(fileSize);
  312. Serial.print("Image Offset: "); Serial.println(imageOffset);
  313. Serial.print("Header size: "); Serial.println(headerSize);
  314. Serial.print("Bit Depth: "); Serial.println(depth);
  315. Serial.print("Image size: ");
  316. Serial.print(width);
  317. Serial.print('x');
  318. Serial.println(abs(height));
  319. // BMP rows are padded (if needed) to 4-byte boundary
  320. uint32_t rowSize = (width * depth / 8 + 3) & ~3;
  321. if (depth < 8) rowSize = ((width * depth + 8 - depth) / 8 + 3) & ~3;
  322. if (height < 0)
  323. {
  324. height = -height;
  325. flip = false;
  326. }
  327. uint16_t w = width;
  328. uint16_t h = height;
  329. if ((x + w - 1) >= display.epd2.WIDTH) w = display.epd2.WIDTH - x;
  330. if ((y + h - 1) >= display.epd2.HEIGHT) h = display.epd2.HEIGHT - y;
  331. if (w <= max_row_width) // handle with direct drawing
  332. {
  333. valid = true;
  334. uint8_t bitmask = 0xFF;
  335. uint8_t bitshift = 8 - depth;
  336. uint16_t red, green, blue;
  337. uint8_t cv7 = 0x00;
  338. if (depth <= 8)
  339. {
  340. if (depth < 8) bitmask >>= depth;
  341. bytes_read += skip(client, imageOffset - (4 << depth) - bytes_read); // 54 for regular, diff for colorsimportant
  342. for (uint16_t pn = 0; pn < (1 << depth); pn++)
  343. {
  344. blue = client.read();
  345. green = client.read();
  346. red = client.read();
  347. client.read();
  348. bytes_read += 4;
  349. rgb_palette_buffer[pn] = color7(red, green, blue);
  350. }
  351. }
  352. display.epd2.setPaged();
  353. whiteLine();
  354. for (uint16_t l = 0; l < y; l++)
  355. {
  356. display.writeNative(output_row_native4c_buffer, 0, 0, l, display.epd2.WIDTH, 1, false, false, false);
  357. }
  358. uint32_t rowPosition = imageOffset;
  359. bytes_read += skip(client, rowPosition - bytes_read);
  360. for (uint16_t row = 0; row < h; row++, rowPosition += rowSize) // for each line
  361. {
  362. if (!connection_ok || !(client.connected() || client.available())) break;
  363. delay(1); // yield() to avoid WDT
  364. uint32_t in_remain = rowSize;
  365. uint32_t in_idx = 0;
  366. uint32_t in_bytes = 0;
  367. uint8_t in_byte = 0; // for depth <= 8
  368. uint8_t in_bits = 0; // for depth <= 8
  369. uint8_t out_cv7_byte = 0x00;
  370. uint32_t out_idx = 0;
  371. for (uint16_t col = 0; col < w; col++) // for each pixel
  372. {
  373. yield();
  374. if (!connection_ok || !(client.connected() || client.available())) break;
  375. // Time to read more pixel data?
  376. if (in_idx >= in_bytes) // ok, exact match for 24bit also (size IS multiple of 3)
  377. {
  378. uint32_t get = in_remain > sizeof(input_buffer) ? sizeof(input_buffer) : in_remain;
  379. uint32_t got = read8n(client, input_buffer, get);
  380. while ((got < get) && connection_ok)
  381. {
  382. //Serial.print("got "); Serial.print(got); Serial.print(" < "); Serial.print(get); Serial.print(" @ "); Serial.println(bytes_read);
  383. uint32_t gotmore = read8n(client, input_buffer + got, get - got);
  384. got += gotmore;
  385. connection_ok = gotmore > 0;
  386. }
  387. in_bytes = got;
  388. in_remain -= got;
  389. bytes_read += got;
  390. in_idx = 0;
  391. }
  392. if (!connection_ok)
  393. {
  394. Serial.print("Error: got no more after "); Serial.print(bytes_read); Serial.println(" bytes read!");
  395. break;
  396. }
  397. switch (depth)
  398. {
  399. case 32:
  400. blue = input_buffer[in_idx++];
  401. green = input_buffer[in_idx++];
  402. red = input_buffer[in_idx++];
  403. in_idx++; // skip alpha
  404. cv7 = color7(red, green, blue);
  405. break;
  406. case 24:
  407. blue = input_buffer[in_idx++];
  408. green = input_buffer[in_idx++];
  409. red = input_buffer[in_idx++];
  410. cv7 = color7(red, green, blue);
  411. break;
  412. case 16:
  413. {
  414. uint8_t lsb = input_buffer[in_idx++];
  415. uint8_t msb = input_buffer[in_idx++];
  416. if (format == 0) // 555
  417. {
  418. blue = (lsb & 0x1F) << 3;
  419. green = ((msb & 0x03) << 6) | ((lsb & 0xE0) >> 2);
  420. red = (msb & 0x7C) << 1;
  421. }
  422. else // 565
  423. {
  424. blue = (lsb & 0x1F) << 3;
  425. green = ((msb & 0x07) << 5) | ((lsb & 0xE0) >> 3);
  426. red = (msb & 0xF8);
  427. }
  428. }
  429. cv7 = color7(red, green, blue);
  430. break;
  431. case 1:
  432. case 2:
  433. case 4:
  434. case 8:
  435. {
  436. if (0 == in_bits)
  437. {
  438. in_byte = input_buffer[in_idx++];
  439. in_bits = 8;
  440. }
  441. uint16_t pn = (in_byte >> bitshift) & bitmask;
  442. cv7 = rgb_palette_buffer[pn];
  443. in_byte <<= depth;
  444. in_bits -= depth;
  445. }
  446. break;
  447. }
  448. out_cv7_byte |= cv7 << (4 * (1 - col % 2));
  449. if ((1 == col % 2) || (col == w - 1)) // write that last byte! (for w%2!=0 border)
  450. {
  451. uint32_t bx = flip ? (display.epd2.WIDTH - x) / 2 - out_idx++ : x / 2 + out_idx++;
  452. output_row_native4c_buffer[bx] = out_cv7_byte;
  453. out_cv7_byte = 0x00;
  454. }
  455. } // end pixel
  456. display.writeNative(output_row_native4c_buffer, 0, 0, y + row, display.epd2.WIDTH, 1, false, false, false);
  457. } // end line
  458. Serial.print("downloaded in ");
  459. Serial.print(millis() - startTime);
  460. Serial.println(" ms");
  461. whiteLine();
  462. for (uint16_t l = y + h; l < display.epd2.HEIGHT; l++)
  463. {
  464. display.writeNative(output_row_native4c_buffer, 0, 0, l, display.epd2.WIDTH, 1, false, false, false);
  465. }
  466. display.refresh();
  467. }
  468. Serial.print("bytes read "); Serial.println(bytes_read);
  469. }
  470. }
  471. client.stop();
  472. if (!valid)
  473. {
  474. Serial.println("bitmap format not handled.");
  475. }
  476. }