wifi working tested on hardware
This commit is contained in:
@@ -43,6 +43,7 @@ if (TARGET tinyusb_host)
|
|||||||
keyboard_input.cpp
|
keyboard_input.cpp
|
||||||
command_processor.cpp
|
command_processor.cpp
|
||||||
epaper_manager.cpp
|
epaper_manager.cpp
|
||||||
|
wifi_manager.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_subdirectory(pico-ssd1306 commands)
|
add_subdirectory(pico-ssd1306 commands)
|
||||||
@@ -61,7 +62,7 @@ if (TARGET tinyusb_host)
|
|||||||
)
|
)
|
||||||
|
|
||||||
# pull in common dependencies
|
# pull in common dependencies
|
||||||
target_link_libraries(hello_usb pico_stdlib pico_ssd1306 hardware_i2c Config ePaper GUI Fonts hardware_spi pico_multicore tinyusb_host tinyusb_board)
|
target_link_libraries(hello_usb pico_stdlib pico_ssd1306 hardware_i2c Config ePaper GUI Fonts hardware_spi pico_multicore tinyusb_host tinyusb_board pico_cyw43_arch_lwip_threadsafe_background)
|
||||||
|
|
||||||
# enable usb output, disable uart output
|
# enable usb output, disable uart output
|
||||||
pico_enable_stdio_usb(hello_usb 0)
|
pico_enable_stdio_usb(hello_usb 0)
|
||||||
|
|||||||
@@ -7,13 +7,11 @@ CommandAction parse_command(const char* input) {
|
|||||||
return CMD_NONE;
|
return CMD_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(input, "/refresh") == 0) {
|
if (strcmp(input, "/refresh") == 0) return CMD_REFRESH;
|
||||||
return CMD_REFRESH;
|
if (strcmp(input, "/clear") == 0) return CMD_CLEAR;
|
||||||
} else if (strcmp(input, "/clear") == 0) {
|
if (strcmp(input, "/scan") == 0) return CMD_SCAN;
|
||||||
return CMD_CLEAR;
|
if (strncmp(input, "/connect ", 9) == 0 || strcmp(input, "/connect") == 0) return CMD_CONNECT;
|
||||||
} else if (strcmp(input, "/wifisetup") == 0) {
|
if (strcmp(input, "/status") == 0) return CMD_STATUS;
|
||||||
return CMD_WIFI;
|
|
||||||
}
|
|
||||||
|
|
||||||
return CMD_UNKNOWN;
|
return CMD_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ enum CommandAction {
|
|||||||
CMD_NONE,
|
CMD_NONE,
|
||||||
CMD_REFRESH,
|
CMD_REFRESH,
|
||||||
CMD_CLEAR,
|
CMD_CLEAR,
|
||||||
CMD_WIFI,
|
CMD_SCAN,
|
||||||
|
CMD_CONNECT,
|
||||||
|
CMD_STATUS,
|
||||||
CMD_UNKNOWN
|
CMD_UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "epaper_manager.h"
|
#include "epaper_manager.h"
|
||||||
|
#include "wifi_manager.h"
|
||||||
#include "pico/stdlib.h"
|
#include "pico/stdlib.h"
|
||||||
#include "pico/multicore.h"
|
#include "pico/multicore.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -97,6 +98,9 @@ static void init_epaper_display() {
|
|||||||
* Core 1 function: Runs display initialization and update handling
|
* Core 1 function: Runs display initialization and update handling
|
||||||
*/
|
*/
|
||||||
static void core1_display_init() {
|
static void core1_display_init() {
|
||||||
|
// Initialize WiFi on Core 1 so IRQs are handled here
|
||||||
|
wifi_init();
|
||||||
|
|
||||||
init_epaper_display();
|
init_epaper_display();
|
||||||
g_display_ready = true;
|
g_display_ready = true;
|
||||||
|
|
||||||
|
|||||||
@@ -10,12 +10,14 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
#include "commands/echo.h"
|
#include "commands/echo.h"
|
||||||
#include "keyboard_input.h"
|
#include "keyboard_input.h"
|
||||||
#include "command_processor.h"
|
#include "command_processor.h"
|
||||||
#include "epaper_manager.h"
|
#include "epaper_manager.h"
|
||||||
|
#include "wifi_manager.h"
|
||||||
|
|
||||||
// Holds last echoed line for display
|
// Holds last echoed line for display
|
||||||
static char g_last_echo[128] = "";
|
static char g_last_echo[128] = "";
|
||||||
@@ -28,7 +30,7 @@ static DisplayManager* g_display_manager = nullptr;
|
|||||||
static char g_input_buffer[MAX_INPUT_LEN];
|
static char g_input_buffer[MAX_INPUT_LEN];
|
||||||
static int g_buffer_index = 0;
|
static int g_buffer_index = 0;
|
||||||
|
|
||||||
static bool execute_command(CommandAction action) {
|
static bool execute_command(CommandAction action, const char* input) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case CMD_REFRESH:
|
case CMD_REFRESH:
|
||||||
printf("Command: /refresh\n");
|
printf("Command: /refresh\n");
|
||||||
@@ -38,9 +40,54 @@ static bool execute_command(CommandAction action) {
|
|||||||
printf("Command: /clear\n");
|
printf("Command: /clear\n");
|
||||||
epaper_clear();
|
epaper_clear();
|
||||||
return true;
|
return true;
|
||||||
case CMD_WIFI:
|
case CMD_SCAN:
|
||||||
printf("Command: /wifisetup (Not implemented)\n");
|
printf("Command: /scan\n");
|
||||||
|
if (g_display_manager) g_display_manager->refresh("Scanning WiFi...", nullptr);
|
||||||
|
epaper_send_update("Scanning WiFi...", true);
|
||||||
|
wifi_scan();
|
||||||
return true;
|
return true;
|
||||||
|
case CMD_CONNECT: {
|
||||||
|
printf("Command: /connect\n");
|
||||||
|
char ssid[33] = {0};
|
||||||
|
char password[64] = {0};
|
||||||
|
// Skip "/connect " (9 chars)
|
||||||
|
const char* args = input + 9;
|
||||||
|
|
||||||
|
// Simple parsing: first word is ssid, rest is password
|
||||||
|
int parsed = sscanf(args, "%32s %63s", ssid, password);
|
||||||
|
if (parsed < 2) {
|
||||||
|
printf("Usage: /connect <ssid> <password>\n");
|
||||||
|
if (g_display_manager) g_display_manager->refresh("Usage: /connect <ssid> <pass>", nullptr);
|
||||||
|
// epaper_send_update("Usage: /connect <ssid> <pass>", true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_display_manager) g_display_manager->refresh("Connecting...", ssid);
|
||||||
|
// epaper_send_update("Connecting...", true);
|
||||||
|
|
||||||
|
if (wifi_connect(ssid, password)) {
|
||||||
|
if (g_display_manager) g_display_manager->refresh("Connected!", ssid);
|
||||||
|
// epaper_send_update("Connected!", true);
|
||||||
|
// wifi_save_credentials(ssid, password);
|
||||||
|
} else {
|
||||||
|
if (g_display_manager) g_display_manager->refresh("Connection Failed", nullptr);
|
||||||
|
// epaper_send_update("Connection Failed", true);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
case CMD_STATUS: {
|
||||||
|
printf("Command: /status\n");
|
||||||
|
struct mallinfo m = mallinfo();
|
||||||
|
char status_msg[64];
|
||||||
|
// fordblks is the free chunk size in the arena.
|
||||||
|
// Note: This might not account for the total available system RAM if the heap hasn't grown to fill it yet.
|
||||||
|
// But it gives an idea of fragmentation and available malloc-able memory within the current arena.
|
||||||
|
snprintf(status_msg, sizeof(status_msg), "Heap: %d B, IP: %s", m.fordblks, wifi_get_ip());
|
||||||
|
printf("%s\n", status_msg);
|
||||||
|
if (g_display_manager) g_display_manager->refresh(status_msg, nullptr);
|
||||||
|
epaper_send_update(status_msg, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -64,34 +111,35 @@ static void process_kbd_report(hid_keyboard_report_t const *report) {
|
|||||||
} else if (event.is_enter) {
|
} else if (event.is_enter) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
|
// Always commit the input line to e-Paper so commands are visible
|
||||||
|
if (g_buffer_index > 0) {
|
||||||
|
epaper_send_update(g_input_buffer, true);
|
||||||
|
}
|
||||||
|
|
||||||
CommandAction action = parse_command(g_input_buffer);
|
CommandAction action = parse_command(g_input_buffer);
|
||||||
if (execute_command(action)) {
|
if (execute_command(action, g_input_buffer)) {
|
||||||
// Command handled, clear buffer but don't commit line
|
// Command handled
|
||||||
g_buffer_index = 0;
|
|
||||||
g_input_buffer[0] = '\0';
|
|
||||||
|
|
||||||
if (g_display_manager) {
|
if (g_display_manager) {
|
||||||
g_display_manager->set_last_echo("Command Executed");
|
g_display_manager->set_last_echo("Command Executed");
|
||||||
g_display_manager->refresh("", "Command Executed");
|
g_display_manager->refresh("", "Command Executed");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Update e-Paper (commit line)
|
// Not a command, just text (already committed to e-Paper above)
|
||||||
epaper_send_update(g_input_buffer, true);
|
|
||||||
|
|
||||||
// Save to last echo
|
// Save to last echo
|
||||||
strncpy(g_last_echo, g_input_buffer, sizeof(g_last_echo) - 1);
|
strncpy(g_last_echo, g_input_buffer, sizeof(g_last_echo) - 1);
|
||||||
g_last_echo[sizeof(g_last_echo) - 1] = '\0';
|
g_last_echo[sizeof(g_last_echo) - 1] = '\0';
|
||||||
|
|
||||||
// Clear buffer
|
|
||||||
g_buffer_index = 0;
|
|
||||||
g_input_buffer[0] = '\0';
|
|
||||||
|
|
||||||
// Update OLED
|
// Update OLED
|
||||||
if (g_display_manager) {
|
if (g_display_manager) {
|
||||||
g_display_manager->set_last_echo(g_last_echo);
|
g_display_manager->set_last_echo(g_last_echo);
|
||||||
g_display_manager->refresh("", g_last_echo);
|
g_display_manager->refresh("", g_last_echo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clear buffer
|
||||||
|
g_buffer_index = 0;
|
||||||
|
g_input_buffer[0] = '\0';
|
||||||
} else if (event.is_printable) {
|
} else if (event.is_printable) {
|
||||||
printf("%c", event.ascii);
|
printf("%c", event.ascii);
|
||||||
if (g_buffer_index < MAX_INPUT_LEN - 1) {
|
if (g_buffer_index < MAX_INPUT_LEN - 1) {
|
||||||
@@ -178,7 +226,12 @@ int main() {
|
|||||||
display.init();
|
display.init();
|
||||||
g_display_manager = &display;
|
g_display_manager = &display;
|
||||||
|
|
||||||
display.refresh("Waiting for Keyboard", nullptr);
|
if (wifi_try_auto_connect()) {
|
||||||
|
display.refresh("WiFi Auto-Connected", nullptr);
|
||||||
|
epaper_send_update("WiFi Auto-Connected", true);
|
||||||
|
} else {
|
||||||
|
display.refresh("Waiting for Keyboard", nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
printf("Initializing TinyUSB Host...\n");
|
printf("Initializing TinyUSB Host...\n");
|
||||||
tuh_init(BOARD_TUH_RHPORT);
|
tuh_init(BOARD_TUH_RHPORT);
|
||||||
|
|||||||
53
lwipopts.h
Normal file
53
lwipopts.h
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
#ifndef _LWIPOPTS_H
|
||||||
|
#define _LWIPOPTS_H
|
||||||
|
|
||||||
|
// Common settings used in most of the pico_w examples
|
||||||
|
#define NO_SYS 1
|
||||||
|
#define LWIP_SOCKET 0
|
||||||
|
|
||||||
|
#define MEM_LIBC_MALLOC 0
|
||||||
|
|
||||||
|
#define MEM_ALIGNMENT 4
|
||||||
|
#define MEM_SIZE 4000
|
||||||
|
#define MEMP_NUM_TCP_SEG 32
|
||||||
|
#define MEMP_NUM_ARP_QUEUE 10
|
||||||
|
#define PBUF_POOL_SIZE 24
|
||||||
|
#define LWIP_ARP 1
|
||||||
|
#define LWIP_ETHERNET 1
|
||||||
|
#define LWIP_ICMP 1
|
||||||
|
#define LWIP_RAW 1
|
||||||
|
#define TCP_WND (8 * TCP_MSS)
|
||||||
|
#define TCP_MSS 1460
|
||||||
|
#define TCP_SND_BUF (8 * TCP_MSS)
|
||||||
|
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
|
||||||
|
#define LWIP_NETIF_STATUS_CALLBACK 1
|
||||||
|
#define LWIP_NETIF_LINK_CALLBACK 1
|
||||||
|
#define LWIP_NETIF_HOSTNAME 1
|
||||||
|
#define LWIP_NETCONN 0
|
||||||
|
#define MEM_STATS 0
|
||||||
|
#define SYS_STATS 0
|
||||||
|
#define MEMP_STATS 0
|
||||||
|
#define LINK_STATS 0
|
||||||
|
#define LWIP_CHKSUM_ALGORITHM 3
|
||||||
|
#define LWIP_DHCP 1
|
||||||
|
#define LWIP_IPV4 1
|
||||||
|
#define LWIP_TCP 1
|
||||||
|
#define LWIP_UDP 1
|
||||||
|
#define LWIP_DNS 1
|
||||||
|
#define LWIP_TCP_KEEPALIVE 1
|
||||||
|
#define LWIP_NETIF_TX_SINGLE_PBUF 1
|
||||||
|
#define DHCP_DOES_ARP_CHECK 0
|
||||||
|
#define LWIP_DHCP_DOES_ACD_CHECK 0
|
||||||
|
|
||||||
|
// Enable debugging
|
||||||
|
#ifndef NDEBUG
|
||||||
|
#define LWIP_DEBUG 1
|
||||||
|
#define LWIP_STATS 1
|
||||||
|
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
|
||||||
|
#else
|
||||||
|
#define LWIP_DEBUG 0
|
||||||
|
#define LWIP_STATS 0
|
||||||
|
#define LWIP_PLATFORM_DIAG(x) do {} while(0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _LWIPOPTS_H */
|
||||||
125
wifi_manager.cpp
Normal file
125
wifi_manager.cpp
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
#include "wifi_manager.h"
|
||||||
|
#include "pico/cyw43_arch.h"
|
||||||
|
#include "hardware/flash.h"
|
||||||
|
#include "hardware/sync.h"
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// Use the last sector of the 2MB flash
|
||||||
|
#define FLASH_TARGET_OFFSET (2 * 1024 * 1024 - FLASH_SECTOR_SIZE)
|
||||||
|
#define WIFI_CREDS_MAGIC 0x42574946 // 'BWIF'
|
||||||
|
|
||||||
|
struct WifiCreds {
|
||||||
|
uint32_t magic;
|
||||||
|
char ssid[33];
|
||||||
|
char password[64];
|
||||||
|
};
|
||||||
|
|
||||||
|
static volatile bool g_wifi_initialized = false;
|
||||||
|
static bool g_wifi_connected = false;
|
||||||
|
|
||||||
|
bool wifi_init() {
|
||||||
|
if (g_wifi_initialized) return true;
|
||||||
|
|
||||||
|
if (cyw43_arch_init()) {
|
||||||
|
printf("WiFi init failed!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
cyw43_arch_enable_sta_mode();
|
||||||
|
g_wifi_initialized = true;
|
||||||
|
printf("WiFi initialized on Core %u\n", get_core_num());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scan_result(void *env, const cyw43_ev_scan_result_t *result) {
|
||||||
|
if (result) {
|
||||||
|
printf("SSID: %-32s RSSI: %4d Auth: %u\n", result->ssid, result->rssi, result->auth_mode);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_scan() {
|
||||||
|
// Wait for initialization
|
||||||
|
int timeout = 500; // 5 seconds
|
||||||
|
while (!g_wifi_initialized && timeout > 0) {
|
||||||
|
sleep_ms(10);
|
||||||
|
timeout--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_wifi_initialized) {
|
||||||
|
printf("WiFi not initialized!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Starting WiFi scan...\n");
|
||||||
|
cyw43_wifi_scan_options_t scan_options = {0};
|
||||||
|
int err = cyw43_wifi_scan(&cyw43_state, &scan_options, NULL, scan_result);
|
||||||
|
if (err != 0) {
|
||||||
|
printf("Failed to start scan: %d\n", err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wifi_save_credentials(const char* ssid, const char* password) {
|
||||||
|
WifiCreds creds;
|
||||||
|
creds.magic = WIFI_CREDS_MAGIC;
|
||||||
|
strncpy(creds.ssid, ssid, sizeof(creds.ssid) - 1);
|
||||||
|
creds.ssid[sizeof(creds.ssid) - 1] = '\0';
|
||||||
|
strncpy(creds.password, password, sizeof(creds.password) - 1);
|
||||||
|
creds.password[sizeof(creds.password) - 1] = '\0';
|
||||||
|
|
||||||
|
uint32_t ints = save_and_disable_interrupts();
|
||||||
|
flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE);
|
||||||
|
flash_range_program(FLASH_TARGET_OFFSET, (const uint8_t*)&creds, sizeof(creds));
|
||||||
|
restore_interrupts(ints);
|
||||||
|
|
||||||
|
printf("WiFi credentials saved to flash.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_try_auto_connect() {
|
||||||
|
const WifiCreds* creds = (const WifiCreds*)(XIP_BASE + FLASH_TARGET_OFFSET);
|
||||||
|
|
||||||
|
if (creds->magic != WIFI_CREDS_MAGIC) {
|
||||||
|
printf("No saved WiFi credentials found.\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Found saved credentials for SSID: %s\n", creds->ssid);
|
||||||
|
return wifi_connect(creds->ssid, creds->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_connect(const char* ssid, const char* password) {
|
||||||
|
// Wait for initialization
|
||||||
|
int timeout = 500; // 5 seconds
|
||||||
|
while (!g_wifi_initialized && timeout > 0) {
|
||||||
|
sleep_ms(10);
|
||||||
|
timeout--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!g_wifi_initialized) {
|
||||||
|
printf("WiFi not initialized!\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("Connecting to WiFi: %s...\n", ssid);
|
||||||
|
|
||||||
|
// Connect in blocking mode for simplicity
|
||||||
|
if (cyw43_arch_wifi_connect_timeout_ms(ssid, password, CYW43_AUTH_WPA2_AES_PSK, 30000)) {
|
||||||
|
printf("WiFi connection failed!\n");
|
||||||
|
g_wifi_connected = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("WiFi connected!\n");
|
||||||
|
g_wifi_connected = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool wifi_is_connected() {
|
||||||
|
return g_wifi_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* wifi_get_ip() {
|
||||||
|
if (!g_wifi_connected) return "Disconnected";
|
||||||
|
return ip4addr_ntoa(netif_ip4_addr(&cyw43_state.netif[0]));
|
||||||
|
}
|
||||||
44
wifi_manager.h
Normal file
44
wifi_manager.h
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
#ifndef WIFI_MANAGER_H
|
||||||
|
#define WIFI_MANAGER_H
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes the WiFi hardware.
|
||||||
|
* Returns true on success.
|
||||||
|
*/
|
||||||
|
bool wifi_init();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans for available WiFi networks and prints them to stdout.
|
||||||
|
*/
|
||||||
|
void wifi_scan();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connects to the specified WiFi network.
|
||||||
|
* Returns true if connected successfully.
|
||||||
|
*/
|
||||||
|
bool wifi_connect(const char* ssid, const char* password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the WiFi credentials to flash memory for auto-connect.
|
||||||
|
*/
|
||||||
|
void wifi_save_credentials(const char* ssid, const char* password);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to connect using saved credentials.
|
||||||
|
* Returns true if connected.
|
||||||
|
*/
|
||||||
|
bool wifi_try_auto_connect();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if currently connected to WiFi.
|
||||||
|
*/
|
||||||
|
bool wifi_is_connected();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the current IP address as a string, or "Disconnected".
|
||||||
|
*/
|
||||||
|
const char* wifi_get_ip();
|
||||||
|
|
||||||
|
#endif // WIFI_MANAGER_H
|
||||||
Reference in New Issue
Block a user