wifi working tested on hardware
This commit is contained in:
@@ -43,6 +43,7 @@ if (TARGET tinyusb_host)
|
||||
keyboard_input.cpp
|
||||
command_processor.cpp
|
||||
epaper_manager.cpp
|
||||
wifi_manager.cpp
|
||||
)
|
||||
|
||||
add_subdirectory(pico-ssd1306 commands)
|
||||
@@ -61,7 +62,7 @@ if (TARGET tinyusb_host)
|
||||
)
|
||||
|
||||
# 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
|
||||
pico_enable_stdio_usb(hello_usb 0)
|
||||
|
||||
@@ -7,13 +7,11 @@ CommandAction parse_command(const char* input) {
|
||||
return CMD_NONE;
|
||||
}
|
||||
|
||||
if (strcmp(input, "/refresh") == 0) {
|
||||
return CMD_REFRESH;
|
||||
} else if (strcmp(input, "/clear") == 0) {
|
||||
return CMD_CLEAR;
|
||||
} else if (strcmp(input, "/wifisetup") == 0) {
|
||||
return CMD_WIFI;
|
||||
}
|
||||
if (strcmp(input, "/refresh") == 0) return CMD_REFRESH;
|
||||
if (strcmp(input, "/clear") == 0) return CMD_CLEAR;
|
||||
if (strcmp(input, "/scan") == 0) return CMD_SCAN;
|
||||
if (strncmp(input, "/connect ", 9) == 0 || strcmp(input, "/connect") == 0) return CMD_CONNECT;
|
||||
if (strcmp(input, "/status") == 0) return CMD_STATUS;
|
||||
|
||||
return CMD_UNKNOWN;
|
||||
}
|
||||
|
||||
@@ -5,7 +5,9 @@ enum CommandAction {
|
||||
CMD_NONE,
|
||||
CMD_REFRESH,
|
||||
CMD_CLEAR,
|
||||
CMD_WIFI,
|
||||
CMD_SCAN,
|
||||
CMD_CONNECT,
|
||||
CMD_STATUS,
|
||||
CMD_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "epaper_manager.h"
|
||||
#include "wifi_manager.h"
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/multicore.h"
|
||||
#include <stdlib.h>
|
||||
@@ -97,6 +98,9 @@ static void init_epaper_display() {
|
||||
* Core 1 function: Runs display initialization and update handling
|
||||
*/
|
||||
static void core1_display_init() {
|
||||
// Initialize WiFi on Core 1 so IRQs are handled here
|
||||
wifi_init();
|
||||
|
||||
init_epaper_display();
|
||||
g_display_ready = true;
|
||||
|
||||
|
||||
@@ -10,12 +10,14 @@
|
||||
#include <ctype.h>
|
||||
#include <cstring>
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "display.h"
|
||||
#include "commands/echo.h"
|
||||
#include "keyboard_input.h"
|
||||
#include "command_processor.h"
|
||||
#include "epaper_manager.h"
|
||||
#include "wifi_manager.h"
|
||||
|
||||
// Holds last echoed line for display
|
||||
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 int g_buffer_index = 0;
|
||||
|
||||
static bool execute_command(CommandAction action) {
|
||||
static bool execute_command(CommandAction action, const char* input) {
|
||||
switch (action) {
|
||||
case CMD_REFRESH:
|
||||
printf("Command: /refresh\n");
|
||||
@@ -38,9 +40,54 @@ static bool execute_command(CommandAction action) {
|
||||
printf("Command: /clear\n");
|
||||
epaper_clear();
|
||||
return true;
|
||||
case CMD_WIFI:
|
||||
printf("Command: /wifisetup (Not implemented)\n");
|
||||
case CMD_SCAN:
|
||||
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;
|
||||
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:
|
||||
return false;
|
||||
}
|
||||
@@ -64,34 +111,35 @@ static void process_kbd_report(hid_keyboard_report_t const *report) {
|
||||
} else if (event.is_enter) {
|
||||
printf("\n");
|
||||
|
||||
CommandAction action = parse_command(g_input_buffer);
|
||||
if (execute_command(action)) {
|
||||
// Command handled, clear buffer but don't commit line
|
||||
g_buffer_index = 0;
|
||||
g_input_buffer[0] = '\0';
|
||||
// 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);
|
||||
if (execute_command(action, g_input_buffer)) {
|
||||
// Command handled
|
||||
if (g_display_manager) {
|
||||
g_display_manager->set_last_echo("Command Executed");
|
||||
g_display_manager->refresh("", "Command Executed");
|
||||
}
|
||||
} else {
|
||||
// Update e-Paper (commit line)
|
||||
epaper_send_update(g_input_buffer, true);
|
||||
// Not a command, just text (already committed to e-Paper above)
|
||||
|
||||
// Save to last echo
|
||||
strncpy(g_last_echo, g_input_buffer, sizeof(g_last_echo) - 1);
|
||||
g_last_echo[sizeof(g_last_echo) - 1] = '\0';
|
||||
|
||||
// Clear buffer
|
||||
g_buffer_index = 0;
|
||||
g_input_buffer[0] = '\0';
|
||||
|
||||
// Update OLED
|
||||
if (g_display_manager) {
|
||||
g_display_manager->set_last_echo(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) {
|
||||
printf("%c", event.ascii);
|
||||
if (g_buffer_index < MAX_INPUT_LEN - 1) {
|
||||
@@ -178,7 +226,12 @@ int main() {
|
||||
display.init();
|
||||
g_display_manager = &display;
|
||||
|
||||
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");
|
||||
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