Skip to content

Commit 189bef6

Browse files
committed
Add support for AP in Pico 2 W (valid for Pico W)
1 parent c84826e commit 189bef6

File tree

7 files changed

+295
-0
lines changed

7 files changed

+295
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
cmake_minimum_required(VERSION 3.13)
2+
include(pico_sdk_import.cmake)
3+
4+
project(firmware)
5+
pico_sdk_init()
6+
7+
add_executable(firmware
8+
main.c
9+
mongoose.c
10+
)
11+
12+
target_include_directories(firmware PUBLIC
13+
.
14+
)
15+
16+
target_link_libraries(firmware pico_stdlib pico_rand pico_cyw43_driver pico_cyw43_arch_none)
17+
pico_add_extra_outputs(firmware) # create map/bin/hex file etc.
18+
19+
pico_enable_stdio_usb(firmware 1) # Route stdio
20+
21+
add_definitions(-DMG_ENABLE_TCPIP_DRIVER_INIT=0)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
CWD = $(realpath $(PWD))
2+
SDK_PATH ?= $(CWD)/pico-sdk
3+
4+
all example:
5+
true
6+
7+
build: build/firmware.uf2
8+
9+
build/firmware.uf2: pico-sdk main.c
10+
mkdir -p build && cd build && PICO_SDK_PATH=$(SDK_PATH) cmake -DPICO_BOARD="pico2_w" -G "Unix Makefiles" .. && make
11+
12+
pico-sdk:
13+
git clone --depth 1 -b 2.1.0 https://github.com/raspberrypi/pico-sdk $@
14+
cd $@ && git submodule update --init
15+
16+
clean:
17+
rm -rf build pico-sdk
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
// Copyright (c) 2022 Cesanta Software Limited
2+
// All rights reserved
3+
4+
#include "mongoose.h"
5+
6+
7+
#define WIFI_SSID "YOUR_WIFI_NETWORK_NAME" // SET THIS!
8+
#define WIFI_PASS "YOUR_WIFI_PASSWORD" // SET THIS!
9+
10+
static uint32_t s_ip, s_mask;
11+
12+
13+
// mif user states
14+
enum {AP, SCANNING, STOPPING_AP, CONNECTING, READY};
15+
static unsigned int state;
16+
17+
static void mif_fn(struct mg_tcpip_if *ifp, int ev, void *ev_data) {
18+
// TODO(): should we include this inside ifp ? add an fn_data ?
19+
if (ev == MG_TCPIP_EV_ST_CHG) {
20+
MG_INFO(("State change: %u", *(uint8_t *) ev_data));
21+
}
22+
switch(state) {
23+
case AP: // we are in AP mode, wait for a user connection to trigger a scan or a connection to a network
24+
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_UP) {
25+
MG_INFO(("Access Point started"));
26+
s_ip = ifp->ip, ifp->ip = MG_IPV4(192, 168, 169, 1);
27+
s_mask = ifp->mask, ifp->mask = MG_IPV4(255, 255, 255, 0);
28+
ifp->enable_dhcp_client = false;
29+
ifp->enable_dhcp_server = true;
30+
} else if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_READY) {
31+
MG_INFO(("Access Point READY !"));
32+
33+
// simulate user request to scan for networks
34+
bool res = mg_wifi_scan();
35+
MG_INFO(("Starting scan: %s", res ? "OK":"FAIL"));
36+
if (res) state = SCANNING;
37+
}
38+
break;
39+
case SCANNING:
40+
if (ev == MG_TCPIP_EV_WIFI_SCAN_RESULT) {
41+
struct mg_wifi_scan_bss_data *bss = (struct mg_wifi_scan_bss_data *) ev_data;
42+
MG_INFO(("BSS: %.*s (%u) (%M) %d dBm %u", bss->SSID.len, bss->SSID.buf, bss->channel, mg_print_mac, bss->BSSID, (int) bss->RSSI, bss->security));
43+
} else if (ev == MG_TCPIP_EV_WIFI_SCAN_END) {
44+
struct mg_tcpip_driver_pico_w_data *d = (struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
45+
MG_INFO(("Wi-Fi scan finished"));
46+
47+
// simulate user selection of a network (1/2: stop AP)
48+
bool res = mg_wifi_ap_stop();
49+
MG_INFO(("Manually stopping AP: %s", res ? "OK":"FAIL"));
50+
if (res) state = STOPPING_AP;
51+
// else we have a hw/fw problem
52+
}
53+
break;
54+
case STOPPING_AP:
55+
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_DOWN) {
56+
struct mg_tcpip_driver_pico_w_data *d = (struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
57+
d->apmode = false;
58+
59+
// simulate user selection of a network (2/2: actual connect)
60+
bool res = mg_wifi_connect(d->ssid, d->pass);
61+
MG_INFO(("Manually connecting: %s", res ? "OK":"FAIL"));
62+
if (res) {
63+
state = CONNECTING;
64+
ifp->ip = s_ip;
65+
ifp->mask = s_mask;
66+
if (ifp->ip == 0) ifp->enable_dhcp_client = true;
67+
ifp->enable_dhcp_server = false;
68+
} // else manually start AP as below
69+
}
70+
break;
71+
case CONNECTING:
72+
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_READY) {
73+
MG_INFO(("READY!"));
74+
state = READY;
75+
76+
// simulate user code disconnection and go back to AP mode (1/2: disconnect)
77+
bool res = mg_wifi_disconnect();
78+
MG_INFO(("Manually disconnecting: %s", res ? "OK":"FAIL"));
79+
} else if (ev == MG_TCPIP_EV_WIFI_CONNECT_ERR) {
80+
MG_ERROR(("Wi-Fi connect failed"));
81+
// manually start AP as below
82+
}
83+
break;
84+
case READY:
85+
// go back to AP mode after a disconnection (simulation 2/2), you could retry
86+
if (ev == MG_TCPIP_EV_ST_CHG && *(uint8_t *) ev_data == MG_TCPIP_STATE_DOWN) {
87+
struct mg_tcpip_driver_pico_w_data *d = (struct mg_tcpip_driver_pico_w_data *) ifp->driver_data;
88+
bool res = mg_wifi_ap_start(d->apssid, d->appass, d->apchannel);
89+
MG_INFO(("Disconnected"));
90+
MG_INFO(("Manually starting AP: %s", res ? "OK":"FAIL"));
91+
if (res) {
92+
state = AP;
93+
d->apmode = true;
94+
}
95+
}
96+
break;
97+
}
98+
}
99+
100+
101+
int main(void) {
102+
// initialize stdio
103+
stdio_init_all();
104+
sleep_ms(4000);
105+
106+
struct mg_mgr mgr; // Initialise Mongoose event manager
107+
mg_mgr_init(&mgr); // and attach it to the interface
108+
109+
// Initialise WiFi creds
110+
struct mg_tcpip_driver_pico_w_data driver_data = {
111+
.ssid = WIFI_SSID,
112+
.pass = WIFI_PASS,
113+
.apssid = "mongoose",
114+
.appass = "eightchars",
115+
.security = 0,
116+
.apsecurity = 0,
117+
.apchannel = 10,
118+
.apmode = true
119+
};
120+
121+
state = driver_data.apmode ? AP : CONNECTING;
122+
123+
// Initialise Mongoose network stack
124+
// Either set use_dhcp or enter a static config.
125+
// For static configuration, specify IP/mask/GW in network byte order
126+
struct mg_tcpip_if mif = {
127+
.ip = 0,
128+
.driver = &mg_tcpip_driver_pico_w,
129+
.driver_data = &driver_data,
130+
.recv_queue.size = 8192,
131+
.fn = mif_fn
132+
};
133+
134+
mg_tcpip_init(&mgr, &mif);
135+
MG_INFO(("Init done, starting main loop"));
136+
137+
MG_INFO(("Initialising application..."));
138+
139+
MG_INFO(("Starting event loop"));
140+
for (;;) {
141+
mg_mgr_poll(&mgr, 0);
142+
}
143+
144+
return 0;
145+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../mongoose.c
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../mongoose.h
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#pragma once
2+
3+
// See https://mongoose.ws/documentation/#build-options
4+
#define MG_ARCH MG_ARCH_PICOSDK
5+
#define MG_OTA MG_OTA_PICOSDK
6+
7+
#define MG_ENABLE_TCPIP 1
8+
#define MG_ENABLE_DRIVER_PICO_W 1
9+
#define MG_ENABLE_PACKED_FS 1
10+
11+
// For static IP configuration, define MG_TCPIP_{IP,MASK,GW}
12+
// By default, those are set to zero, meaning that DHCP is used
13+
//
14+
// #define MG_TCPIP_IP MG_IPV4(192, 168, 1, 10)
15+
// #define MG_TCPIP_GW MG_IPV4(192, 168, 1, 1)
16+
// #define MG_TCPIP_MASK MG_IPV4(255, 255, 255, 0)
17+
18+
// MAC address is read from OTP by the driver
19+
20+
// Set your Wi-Fi credentials
21+
// Using a build-time constant:
22+
// #define MG_SET_WIFI_CREDS(ssid, pass) do { *ssid = "this"; *pass = "that"; } while (0)
23+
//
24+
// Using a custom function:
25+
extern void main_setcreds(char **ssid, char **pass);
26+
#define MG_SET_WIFI_CREDS(ssid, pass) main_setcreds(ssid, pass)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
2+
3+
# This can be dropped into an external project to help locate this SDK
4+
# It should be include()ed prior to project()
5+
6+
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
7+
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
8+
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
9+
endif ()
10+
11+
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
12+
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
13+
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
14+
endif ()
15+
16+
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
17+
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
18+
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
19+
endif ()
20+
21+
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
22+
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
23+
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
24+
endif ()
25+
26+
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
27+
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
28+
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
29+
endif()
30+
31+
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
32+
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable")
33+
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
34+
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
35+
36+
if (NOT PICO_SDK_PATH)
37+
if (PICO_SDK_FETCH_FROM_GIT)
38+
include(FetchContent)
39+
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
40+
if (PICO_SDK_FETCH_FROM_GIT_PATH)
41+
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
42+
endif ()
43+
# GIT_SUBMODULES_RECURSE was added in 3.17
44+
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
45+
FetchContent_Declare(
46+
pico_sdk
47+
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
48+
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
49+
GIT_SUBMODULES_RECURSE FALSE
50+
)
51+
else ()
52+
FetchContent_Declare(
53+
pico_sdk
54+
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
55+
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
56+
)
57+
endif ()
58+
59+
if (NOT pico_sdk)
60+
message("Downloading Raspberry Pi Pico SDK")
61+
FetchContent_Populate(pico_sdk)
62+
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
63+
endif ()
64+
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
65+
else ()
66+
message(FATAL_ERROR
67+
"SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
68+
)
69+
endif ()
70+
endif ()
71+
72+
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
73+
if (NOT EXISTS ${PICO_SDK_PATH})
74+
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
75+
endif ()
76+
77+
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
78+
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
79+
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK")
80+
endif ()
81+
82+
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
83+
84+
include(${PICO_SDK_INIT_CMAKE_FILE})

0 commit comments

Comments
 (0)