311 lines
7.6 KiB
C++
Executable File
311 lines
7.6 KiB
C++
Executable File
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "hardware/i2c.h"
|
|
extern "C" {
|
|
#include "hardware/watchdog.h"
|
|
#include "pico/cyw43_arch.h"
|
|
#include "pico/stdlib.h"
|
|
}
|
|
#include <bme280.h>
|
|
#include <server.h>
|
|
|
|
#include <font.hpp>
|
|
#include <format>
|
|
#include <string>
|
|
#include <tft.hpp>
|
|
|
|
// #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);
|
|
}
|
|
}
|