Add ArtNetDMX Pico W firmware with dual DMX and docs.

Art-Net to two RS-485 outputs over Wi-Fi (AP or STA with SoftAP fallback), web UI, mDNS, and QLC+/ArtPoll notes for unicast on STA.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-11 00:00:23 +12:00
co-authored by Cursor
commit fea6dffa74
26 changed files with 3013 additions and 0 deletions
+57
View File
@@ -0,0 +1,57 @@
#ifndef CONFIG_H
#define CONFIG_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include "board.h"
#define CONFIG_MAGIC 0x414E4458u /* 'ANDX' */
#define CONFIG_VERSION 3
#define CONFIG_SSID_MAX 32
#define CONFIG_PASS_MAX 64
#define CONFIG_HOSTNAME_MAX 32
typedef enum {
WIFI_MODE_AP = 0,
WIFI_MODE_STA = 1,
/** Legacy flash value; treated as STA (with AP fallback on failure). */
WIFI_MODE_AP_STA = 2,
} wifi_mode_t;
typedef struct {
uint32_t magic;
uint32_t version;
uint32_t crc;
wifi_mode_t wifi_mode;
char sta_ssid[CONFIG_SSID_MAX];
char sta_pass[CONFIG_PASS_MAX];
char ap_ssid[CONFIG_SSID_MAX];
char ap_pass[CONFIG_PASS_MAX];
uint16_t universe_a;
uint16_t universe_b;
/* v3: mDNS hostname without ".local" (e.g. "artnetdmx") */
char mdns_host[CONFIG_HOSTNAME_MAX];
} config_t;
void config_set_defaults(config_t *cfg);
bool config_load(config_t *cfg);
bool config_save(const config_t *cfg);
const config_t *config_get(void);
void config_init(void);
/** Lowercase DNS-label sanitize into out; returns false if empty/invalid → uses default. */
bool config_sanitize_hostname(const char *in, char *out, size_t out_sz);
static inline const char *wifi_mode_name(wifi_mode_t m) {
switch (m) {
case WIFI_MODE_STA:
case WIFI_MODE_AP_STA:
return "STA";
case WIFI_MODE_AP:
default:
return "AP";
}
}
#endif