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>
90 lines
2.3 KiB
C
90 lines
2.3 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
#include "pico/stdlib.h"
|
|
#include "pico/stdio_usb.h"
|
|
#include "pico/cyw43_arch.h"
|
|
#include "hardware/pio.h"
|
|
|
|
#include "board.h"
|
|
#include "config.h"
|
|
#include "channels.h"
|
|
#include "dmx_out.h"
|
|
#include "artnet.h"
|
|
#include "wifi_mgr.h"
|
|
#include "http_server.h"
|
|
|
|
static dmx_out_t g_dmx[BOARD_NUM_UNIVERSES];
|
|
static uint8_t g_frames[BOARD_NUM_UNIVERSES][BOARD_DMX_FRAME_LEN];
|
|
|
|
static bool dmx_timer_cb(repeating_timer_t *rt) {
|
|
(void)rt;
|
|
for (unsigned u = 0; u < BOARD_NUM_UNIVERSES; u++) {
|
|
if (dmx_out_busy(&g_dmx[u])) {
|
|
continue;
|
|
}
|
|
channels_build_frame(u, g_frames[u]);
|
|
dmx_out_write(&g_dmx[u], g_frames[u], BOARD_DMX_FRAME_LEN);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
int main(void) {
|
|
stdio_init_all();
|
|
/* Give USB CDC a moment so early boot logs are visible after flash/reboot. */
|
|
for (int i = 0; i < 40 && !stdio_usb_connected(); i++) {
|
|
sleep_ms(50);
|
|
}
|
|
sleep_ms(200);
|
|
printf("\nArtNetDMX starting\n");
|
|
fflush(stdout);
|
|
|
|
config_init();
|
|
channels_init();
|
|
|
|
if (!dmx_out_init(&g_dmx[0], BOARD_DMX_A_PIN, pio0)) {
|
|
printf("DMX A init failed\n");
|
|
}
|
|
if (!dmx_out_init(&g_dmx[1], BOARD_DMX_B_PIN, pio1)) {
|
|
printf("DMX B init failed\n");
|
|
}
|
|
|
|
if (!wifi_mgr_start(config_get())) {
|
|
printf("WiFi start failed\n");
|
|
while (true) {
|
|
tight_loop_contents();
|
|
}
|
|
}
|
|
|
|
if (!http_server_start()) {
|
|
printf("HTTP start failed\n");
|
|
}
|
|
if (!artnet_start()) {
|
|
printf("Art-Net start failed\n");
|
|
}
|
|
|
|
static repeating_timer_t dmx_timer;
|
|
if (!add_repeating_timer_ms(-BOARD_DMX_PERIOD_MS, dmx_timer_cb, NULL, &dmx_timer)) {
|
|
printf("DMX timer failed\n");
|
|
} else {
|
|
printf("DMX output at %d Hz\n", BOARD_DMX_HZ);
|
|
}
|
|
|
|
printf("Ready — mode=%s primary=%s mDNS http://%s/\n",
|
|
wifi_mode_name(wifi_mgr_active_mode()),
|
|
wifi_mgr_ip_str(),
|
|
wifi_mgr_mdns_name());
|
|
if (wifi_mgr_ap_up()) {
|
|
printf("SoftAP http://%s/ (ssid ArtNetDMX)\n", wifi_mgr_ap_ip_str());
|
|
} else {
|
|
printf("Joining STA (SoftAP starts only if join fails)...\n");
|
|
}
|
|
|
|
while (true) {
|
|
wifi_mgr_poll();
|
|
artnet_poll();
|
|
tight_loop_contents();
|
|
sleep_ms(10);
|
|
}
|
|
}
|