#include #include #include "hardware/i2c.h" extern "C" { #include "hardware/watchdog.h" #include "pico/cyw43_arch.h" #include "pico/stdlib.h" } #include #include #include #include #include #include // #define MOBILE_WIFI #include "boot.h" #include "wifi.hpp" // FatFS extern "C" { #include "f_util.h" #include "ff.h" #include "hw_config.h" } //////// void BSOD(const char *); void msg(const char *msg) { printf("[INFO] %s\n", msg); } void err(const char *msg) { printf("[ERROR] %s\n", msg); BSOD(msg); } ////////// CONFIG ////////// #define I2C_PORT i2c0 #define I2C_SDA 4 #define I2C_SCL 5 constexpr int PinReboot = 13; constexpr int PinNoWifi = 14; constexpr int WifiError = 15; constexpr uint PinCs = 22; constexpr uint PinDc = 21; constexpr uint PinRst = 20; constexpr uint PinSck = 18; constexpr uint PinSda = 19; //////////////////////////// TFT tft(PinCs, PinDc, PinRst, PinSck, PinSda); #define ClearScreen(c) tft.DrawRect(0, 0, 127, 159, c) void DrawChar(uint8_t x, uint8_t y, char c, uint16_t fg, uint16_t bg) { if (c < 0 || c > 255) return; const uint8_t *chr = &font[c * FONT_HEIGHT]; for (uint8_t row = 0; row < FONT_HEIGHT; ++row) { uint8_t bits = chr[row]; for (uint8_t col = 0; col < FONT_WIDTH; ++col) { uint16_t color = (bits & (1 << (7 - col))) ? fg : bg; tft.DrawPixel(x + col, y + row, color); } } } void DrawText(uint8_t x, uint8_t y, const char *text, uint16_t fg, uint16_t bg) { while (*text) { if (*text == '\n') { y += FONT_HEIGHT; x = 1; *text++; continue; } else if (*text == '\0') { break; } if (x + FONT_WIDTH > 127) { y += FONT_HEIGHT; x = 1; } DrawChar(x, y, *text++, fg, bg); x += FONT_WIDTH; } } // Blue Screen of Death void BSOD(const char *what) { ClearScreen(0xF800); DrawText(1, 5, "ERROR", 0xffff, 0xf800); DrawText(1, 7 + FONT_HEIGHT, what, 0xffff, 0xf800); for (int i = 0; i < 10; i++) { DrawText(1, 140, "Rebooting in\n10 seconds...", 0xffff, 0xf800); sleep_ms(1000); } watchdog_reboot(0, 0, 0); } void ScreenMsg(const char *what, uint16_t fg_col, uint16_t bg_col) { ClearScreen(bg_col); DrawText(1, 5 + FONT_HEIGHT, what, fg_col, bg_col); } static size_t get_mac_ascii(int idx, size_t chr_off, size_t chr_len, char *dest_in) { static const char *hexchr = "0123456789ABCDEF"; uint8_t mac[6]; char *dest = dest_in; assert(chr_off + chr_len <= (2 * sizeof(mac))); cyw43_hal_get_mac(idx, mac); for (; chr_len && (chr_off >> 1) < sizeof(mac); ++chr_off, --chr_len) { *dest++ = hexchr[mac[chr_off >> 1] >> (4 * (1 - (chr_off & 1))) & 0xf]; } return dest - dest_in; } int init_wifi() { msg("Init Wifi"); // Initialise the Wi-Fi chip if (cyw43_arch_init()) { err("Wi-Fi init failed"); return -1; } msg("Enable STA"); cyw43_arch_enable_sta_mode(); msg("Get Hostname / Mac Address"); char hostname[sizeof(CYW43_HOST_NAME) + 4]; memcpy(&hostname[0], CYW43_HOST_NAME, sizeof(CYW43_HOST_NAME) - 1); get_mac_ascii(CYW43_HAL_MAC_WLAN0, 8, 4, &hostname[sizeof(CYW43_HOST_NAME) - 1]); hostname[sizeof(hostname) - 1] = '\0'; netif_set_hostname(&cyw43_state.netif[CYW43_ITF_STA], hostname); msg("Connect Wifi"); if (cyw43_arch_wifi_connect_timeout_ms(WIFI_SSID, WIFI_PASSWORD, CYW43_AUTH_WPA2_AES_PSK, 30000)) { err("Wi-Fi connect failed"); return -1; } cyw43_arch_gpio_put(CYW43_WL_GPIO_LED_PIN, 1); msg("Connected to Wi-Fi!"); return 0; } // #define I2C_PORT i2c0 data _list[1000]; int list_index = 0; int list_count = 0; // Total stored, max 1000 void list_update(float temp, float humidity) { _list[list_index].t = temp; _list[list_index].h = humidity; list_index = (list_index + 1) % 1000; if (list_count < 1000) { list_count++; } } void list_average(float *avg_temp, float *avg_humidity) { if (list_count == 0) { *avg_temp = 0.0f; *avg_humidity = 0.0f; return; } float sum_t = 0.0f; float sum_h = 0.0f; for (int i = 0; i < list_count; i++) { sum_t += _list[i].t; sum_h += _list[i].h; } *avg_temp = sum_t / list_count; *avg_humidity = sum_h / list_count; } bme280_ctx *ctx; int init_fs() { printf("Init FS\n"); FATFS fs; FRESULT fr = f_mount(&fs, "", 1); if (fr != FR_OK) { printf("f_mount error: %s\n", FRESULT_str(fr)); return 1; } FIL fil; const char *fn = "test.txt"; fr = f_open(&fil, fn, FA_OPEN_APPEND | FA_WRITE); if (fr != FR_OK) { printf("f_open error: %s\n", FRESULT_str(fr)); return 1; } if (f_printf(&fil, "Hello World!\n") < 0) { printf("Failed to write!"); return 1; } fr = f_close(&fil); if (fr != FR_OK) { printf("f_close error: %s\n", FRESULT_str(fr)); return 1; } f_unmount(""); return 0; } float __a_te = 0.0f; float __a_hu = 0.0f; float __temp = 0.f; float __humidity = 0.f; int main() { stdio_init_all(); tft.Init(); ClearScreen(0xffff); tft.SetWindow(0, 16, 127, 127); for (int i = 0; i < 16384; i++) { tft.WriteData16(boot_image[i]); } // if (init_fs() != 0) { // return 1; // } /// NO WIFI CHECK /// gpio_init(PinNoWifi); gpio_pull_down(PinNoWifi); gpio_set_dir(PinNoWifi, GPIO_IN); gpio_init(PinReboot); gpio_pull_down(PinReboot); gpio_set_dir(PinReboot, GPIO_IN); bool use_wifi = !gpio_get(PinNoWifi); ///////////////////// if (use_wifi) { gpio_init(WifiError); gpio_set_dir(WifiError, GPIO_OUT); gpio_put(WifiError, 0); if (init_wifi() != 0) { gpio_put(WifiError, 1); return -1; } } else { DrawText(1, 1, "WIFI Disabled...", 0x00ff, 0xffff); sleep_ms(2000); } ClearScreen(0xffff); ctx = bme280_init(I2C_PORT, I2C_SDA, I2C_SCL); if (use_wifi) { DrawText(1, 150, ip4addr_ntoa(netif_ip4_addr(netif_list)), 0x0000, 0xffff); } else { DrawText(1, 150, "WIFI disabled...", 0x00ff, 0xffff); } int __i = 0; while (true) { __temp = ctx->read_temp(ctx); __humidity = ctx->read_humidity(ctx); if (gpio_get(PinReboot)) { ScreenMsg( "D7-System:\nReboot initiated!\n\nYou have 3\nseconds to remove\nthe " "wire!", 0xffff, 0x00df); sleep_ms(3000); watchdog_reboot(0, 0, 0); } if (use_wifi) { DrawText(1, 120, std::format("TCP Errors:\n - {:016X}", __tcp_errors).c_str(), 0x0000, 0xffff); if (cyw43_tcpip_link_status(&cyw43_state, CYW43_ITF_STA) == CYW43_LINK_UP) { // Space to keep the string the same len DrawText(1, 140, "Conected: true ", 0x0000, 0xffff); } else { DrawText(1, 140, "Conected: false", 0x0000, 0xffff); } } ctx->update(ctx); list_average(&__a_te, &__a_hu); std::string text = std::format( "Temp: {:.1f} C\nHumidity: {:.2f}%\nAVG Temp: {:.1f} C\nAVG Hum: " "{:.2f}%", __temp, __humidity, __a_te, __a_hu); DrawText(1, 1, text.c_str(), 0x0000, 0xffff); if (__i >= 10) { list_update(__temp, __humidity); __i = 0; } __i++; printf("Temperatur=%.2f °C, Luftfeuchtigkeit=%.2f %\n", __temp, __humidity); if (use_wifi) { run_http_server(); } sleep_ms(1000); } if (ctx) { bme280_deinit(ctx); } }