summaryrefslogtreecommitdiff
path: root/src/draw_qrcode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/draw_qrcode.cpp')
-rw-r--r--src/draw_qrcode.cpp94
1 files changed, 94 insertions, 0 deletions
diff --git a/src/draw_qrcode.cpp b/src/draw_qrcode.cpp
new file mode 100644
index 0000000..594e47c
--- /dev/null
+++ b/src/draw_qrcode.cpp
@@ -0,0 +1,94 @@
+#include <GxEPD2_BW.h>
+#include <Fonts/FreeSansBold9pt7b.h>
+#include <Fonts/FreeSans9pt7b.h>
+#include <qrcode.h>
+
+#define BLOCK_WIDTH 4
+
+static uint16_t sizes[] = {
+ 17, 32, 53, 78, 106, 134, 154, 192, 230,
+};
+
+static void escape_strings(String &text) {
+ text.replace("\\", "\\\\");
+ text.replace("\"", "\\\"");
+ text.replace(";", "\\;");
+ text.replace(",", "\\,");
+ text.replace(":", "\\:");
+}
+
+static int version_for_len(int length) {
+ /* assuming ECC_LOW byte qrcodes
+ sizes taken from table in https://github.com/ricmoo/QRCode/blob/master/README.md */
+
+ for (int i = 0; i < sizeof(sizes)/sizeof(uint16_t); i++) {
+ if (length <= sizes[i])
+ return i + 1;
+ }
+ return -1;
+}
+
+int draw_qrcode(GxEPD2_GFX_BASE_CLASS &display, int16_t x, int16_t y, String &text) {
+ QRCode qrcode;
+ int version = version_for_len(text.length());
+ if (version <= 0)
+ return 0;
+
+ uint8_t bytes[qrcode_getBufferSize(version)];
+ qrcode_initText(&qrcode, bytes, version, ECC_LOW, text.c_str());
+
+ /* add quiet zone */
+ x += 4 * BLOCK_WIDTH;
+ y += 4 * BLOCK_WIDTH;
+
+ for (int row = 0; row < qrcode.size; row++) {
+ for (int col = 0; col < qrcode.size; col++) {
+ if (!qrcode_getModule(&qrcode, row, col)) {
+ continue;
+ }
+ display.fillRect(x + BLOCK_WIDTH * row, y + BLOCK_WIDTH * col, BLOCK_WIDTH, BLOCK_WIDTH, GxEPD_BLACK);
+ }
+ }
+ return qrcode.size * BLOCK_WIDTH + 8 * BLOCK_WIDTH;
+}
+
+void draw_qrcode_wlan(GxEPD2_GFX_BASE_CLASS &display, int16_t x, int16_t y, const char *ssid, const char *psk) {
+ String ssid_str = String(ssid);
+ String psk_str = String(psk);
+ escape_strings(ssid_str);
+ escape_strings(psk_str);
+
+ /* assuming WPA network; (H)idden attribute is kept at default */
+ String wifi_str = "WIFI:S:" + ssid_str;
+ if (psk_str.length() == 0) {
+ /* open network */
+ wifi_str += ";;;;";
+ } else {
+ wifi_str += ";P:" + psk_str + ";T:WPA;;";
+ }
+
+ int size = draw_qrcode(display, x, y, wifi_str);
+
+ /* draw text */
+ int16_t x2, y2;
+ uint16_t w, h;
+ String text_ssid = String("SSID:");
+ String text_psk = String("PSK:");
+
+ display.setFont(&FreeSansBold9pt7b);
+ display.getTextBounds(text_ssid, 0, 0, &x2, &y2, &w, &h);
+ display.setCursor(x, y + size + h);
+ display.print(text_ssid);
+ display.setFont(&FreeSans9pt7b);
+ display.setCursor(x + w, y + size + h);
+ display.print(" " + ssid_str);
+
+ if (psk_str.length() > 0) {
+ display.setFont(&FreeSansBold9pt7b);
+ display.setCursor(x, y + size + 2 * h + 10);
+ display.print(text_psk);
+ display.setFont(&FreeSans9pt7b);
+ display.setCursor(x + w, y + size + 2 * h + 10);
+ display.print(" " + psk_str);
+ }
+}