Initialize makefile
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
build
|
||||
main/build
|
||||
sdkconfig.old
|
||||
*.bak
|
||||
*.old
|
||||
.vscode
|
42
.gitmodules
vendored
Normal file
42
.gitmodules
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
[submodule "esp-idf"]
|
||||
path = esp-idf
|
||||
url = https://github.com/espressif/esp-idf.git
|
||||
[submodule "components/bus-i2c"]
|
||||
path = components/bus-i2c
|
||||
url = https://github.com/Nicolai-Electronics/esp32-component-bus-i2c.git
|
||||
[submodule "components/i2c-bno055"]
|
||||
path = components/i2c-bno055
|
||||
url = https://github.com/Nicolai-Electronics/esp32-component-i2c-bno055.git
|
||||
[submodule "components/spi-ili9341"]
|
||||
path = components/spi-ili9341
|
||||
url = https://github.com/Nicolai-Electronics/esp32-component-spi-ili9341.git
|
||||
[submodule "components/spi-ice40"]
|
||||
path = components/spi-ice40
|
||||
url = https://github.com/Nicolai-Electronics/esp32-component-spi-ice40.git
|
||||
[submodule "components/sdcard"]
|
||||
path = components/sdcard
|
||||
url = https://github.com/Nicolai-Electronics/esp32-component-sdcard.git
|
||||
[submodule "components/pax-graphics"]
|
||||
path = components/pax-graphics
|
||||
url = https://github.com/robotman2412/pax-graphics.git
|
||||
[submodule "components/mch2022-rp2040"]
|
||||
path = components/mch2022-rp2040
|
||||
url = https://github.com/badgeteam/esp32-component-mch2022-rp2040.git
|
||||
[submodule "components/esp32-component-appfs"]
|
||||
path = components/appfs
|
||||
url = https://github.com/badgeteam/esp32-component-appfs.git
|
||||
[submodule "components/ws2812"]
|
||||
path = components/ws2812
|
||||
url = https://github.com/badgeteam/esp32-component-ws2812.git
|
||||
[submodule "components/mch2022-efuse"]
|
||||
path = components/mch2022-efuse
|
||||
url = https://github.com/badgeteam/esp32-component-mch2022-efuse.git
|
||||
[submodule "components/mch2022-bsp"]
|
||||
path = components/mch2022-bsp
|
||||
url = https://github.com/badgeteam/esp32-component-mch2022-bsp.git
|
||||
[submodule "components/pax-codecs"]
|
||||
path = components/pax-codecs
|
||||
url = https://github.com/robotman2412/pax-codecs.git
|
||||
[submodule "main/pax-keyboard"]
|
||||
path = components/pax-keyboard
|
||||
url = https://github.com/robotman2412/pax-keyboard
|
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
set(PROJECT_NAME "MCH2022 launcher")
|
||||
set(PROJECT_VER "0.1")
|
||||
|
||||
project(main)
|
||||
|
9
LICENSE
Normal file
9
LICENSE
Normal file
@@ -0,0 +1,9 @@
|
||||
Copyright 2022 Julian Scheffers
|
||||
Copyright 2022 Jeroen Domburg
|
||||
Copyright 2022 Renze Nicolai
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
31
Makefile
Normal file
31
Makefile
Normal file
@@ -0,0 +1,31 @@
|
||||
PORT ?= /dev/ttyACM0
|
||||
BUILDDIR ?= build
|
||||
IDF_PATH ?= $(shell pwd)/esp-idf
|
||||
IDF_EXPORT_QUIET ?= 0
|
||||
SHELL := /usr/bin/env bash
|
||||
|
||||
.PHONY: prepare clean build flash erase monitor menuconfig
|
||||
|
||||
all: prepare build
|
||||
|
||||
prepare:
|
||||
git submodule update --init --recursive
|
||||
cd esp-idf; bash install.sh
|
||||
|
||||
clean:
|
||||
rm -rf "$(BUILDDIR)"
|
||||
|
||||
build:
|
||||
source "$(IDF_PATH)/export.sh" && idf.py build
|
||||
|
||||
flash: build
|
||||
source "$(IDF_PATH)/export.sh" && idf.py flash -p $(PORT)
|
||||
|
||||
erase:
|
||||
source "$(IDF_PATH)/export.sh" && idf.py erase-flash -p $(PORT)
|
||||
|
||||
monitor:
|
||||
source "$(IDF_PATH)/export.sh" && idf.py monitor -p $(PORT)
|
||||
|
||||
menuconfig:
|
||||
source "$(IDF_PATH)/export.sh" && idf.py menuconfig
|
31
README.md
Normal file
31
README.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# MCH2022 template app
|
||||
|
||||
This repository contains a template app for the MCH2022 badge.
|
||||
|
||||
## License
|
||||
|
||||
The source code contained in this repository is licensed under terms of the MIT license, more information can be found in the LICENSE file.
|
||||
|
||||
Source code included as submodules is licensed separately, please check the following table for details.
|
||||
|
||||
| Submodule | License | Author |
|
||||
|-----------------------------|-----------------------------------|--------------------------------------------------------|
|
||||
| esp-idf | Apache License 2.0 | Espressif Systems (Shanghai) CO LTD |
|
||||
| components/appfs | THE BEER-WARE LICENSE Revision 42 | Jeroen Domburg <jeroen@spritesmods.com> |
|
||||
| components/bus-i2c | MIT | Nicolai Electronics |
|
||||
| components/i2c-bno055 | MIT | Nicolai Electronics |
|
||||
| components/mch2022-rp2040 | MIT | Renze Nicolai |
|
||||
| components/pax-graphics | MIT | Julian Scheffers |
|
||||
| components/pax-keyboard | MIT | Julian Scheffers |
|
||||
| components/sdcard | MIT | Nicolai Electronics |
|
||||
| components/spi-ice40 | MIT | Nicolai Electronics |
|
||||
| components/spi-ili9341 | MIT | Nicolai Electronics |
|
||||
| components/ws2812 | MIT | Unlicense / Public domain |
|
||||
|
||||
## How to make
|
||||
```sh
|
||||
git clone --recursive https://github.com/badgeteam/mch2022-template-app
|
||||
cd mch2022-template-app
|
||||
make prepare
|
||||
make
|
||||
```
|
1
components/appfs
Submodule
1
components/appfs
Submodule
Submodule components/appfs added at 3311e975db
1
components/bus-i2c
Submodule
1
components/bus-i2c
Submodule
Submodule components/bus-i2c added at f775f174c3
5
components/i2c-bme680/CMakeLists.txt
Normal file
5
components/i2c-bme680/CMakeLists.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "bme680.c"
|
||||
INCLUDE_DIRS include
|
||||
REQUIRES "bus-i2c"
|
||||
)
|
47
components/i2c-bme680/bme680.c
Normal file
47
components/i2c-bme680/bme680.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Copyright (c) 2022 Nicolai Electronics
|
||||
*
|
||||
* SPDX-License-Identifier: MIT
|
||||
*/
|
||||
|
||||
#include <sdkconfig.h>
|
||||
#include <esp_log.h>
|
||||
#include <driver/gpio.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include <freertos/task.h>
|
||||
#include "bme680.h"
|
||||
#include "managed_i2c.h"
|
||||
|
||||
static const char *TAG = "BME680";
|
||||
|
||||
esp_err_t bme680_check_id(BME680* device) {
|
||||
uint8_t chip_id;
|
||||
esp_err_t res = i2c_read_reg(device->i2c_bus, device->i2c_address, BME680_REG_CHIP_ID, &chip_id, 1);
|
||||
if (res != ESP_OK) return res;
|
||||
if (chip_id != BME680_CHIP_ID) {
|
||||
ESP_LOGE(TAG, "Unexpected chip id value 0x%02X, expected 0x%02X", chip_id, BME680_CHIP_ID);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t bme680_reset(BME680* device) {
|
||||
uint8_t value = 0xFF;
|
||||
esp_err_t res = i2c_write_reg_n(device->i2c_bus, device->i2c_address, BME680_REG_RESET, &value, 1);
|
||||
if (res != ESP_OK) return res;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t bme680_init(BME680* device) {
|
||||
esp_err_t res = bme680_reset(device);
|
||||
if (res != ESP_OK) return res;
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
res = bme680_check_id(device);
|
||||
if (res != ESP_OK) return res;
|
||||
return res;
|
||||
}
|
||||
|
||||
esp_err_t bme680_deinit(BME680* device) {
|
||||
return bme680_reset(device);
|
||||
}
|
19
components/i2c-bme680/include/bme680.h
Normal file
19
components/i2c-bme680/include/bme680.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include <esp_err.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define BME680_REG_RESET 0xE0
|
||||
#define BME680_REG_CHIP_ID 0xD0
|
||||
|
||||
#define BME680_CHIP_ID 0x61
|
||||
|
||||
typedef struct BME680 {
|
||||
int i2c_bus;
|
||||
int i2c_address;
|
||||
} BME680;
|
||||
|
||||
esp_err_t bme680_init(BME680* device);
|
||||
esp_err_t bme680_deinit(BME680* device);
|
||||
esp_err_t bme680_check_id(BME680* device);
|
||||
esp_err_t bme680_reset(BME680* device);
|
1
components/i2c-bno055
Submodule
1
components/i2c-bno055
Submodule
Submodule components/i2c-bno055 added at 0812d28db9
1
components/mch2022-bsp
Submodule
1
components/mch2022-bsp
Submodule
Submodule components/mch2022-bsp added at cb7764d843
1
components/mch2022-efuse
Submodule
1
components/mch2022-efuse
Submodule
Submodule components/mch2022-efuse added at e45054f561
1
components/mch2022-rp2040
Submodule
1
components/mch2022-rp2040
Submodule
Submodule components/mch2022-rp2040 added at 3c859b52f3
1
components/pax-codecs
Submodule
1
components/pax-codecs
Submodule
Submodule components/pax-codecs added at 11b9e4f964
1
components/pax-graphics
Submodule
1
components/pax-graphics
Submodule
Submodule components/pax-graphics added at 18b0ea1324
1
components/pax-keyboard
Submodule
1
components/pax-keyboard
Submodule
Submodule components/pax-keyboard added at adad199c55
1
components/sdcard
Submodule
1
components/sdcard
Submodule
Submodule components/sdcard added at 2b6630e85e
1
components/spi-ice40
Submodule
1
components/spi-ice40
Submodule
Submodule components/spi-ice40 added at abdc7b2350
1
components/spi-ili9341
Submodule
1
components/spi-ili9341
Submodule
Submodule components/spi-ili9341 added at 62f7cef36f
1
components/ws2812
Submodule
1
components/ws2812
Submodule
Submodule components/ws2812 added at c1c750d2ce
1
esp-idf
Submodule
1
esp-idf
Submodule
Submodule esp-idf added at 9f303290d8
41
fpga/fpga.py
Normal file
41
fpga/fpga.py
Normal file
@@ -0,0 +1,41 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import binascii, serial, time, sys, argparse
|
||||
|
||||
parser = argparse.ArgumentParser(description='MCH2022 badge FPGA bitstream programming tool')
|
||||
parser.add_argument("port", help="Serial port")
|
||||
parser.add_argument("bitstream", help="Bitstream binary")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.bitstream, "rb") as f:
|
||||
bitstream = f.read()
|
||||
|
||||
port = serial.Serial(args.port, 921600, timeout=1)
|
||||
print("Waiting for badge...")
|
||||
while True:
|
||||
data = port.read(4)
|
||||
if (data == b"FPGA"):
|
||||
break
|
||||
port.write(b'FPGA' + (len(bitstream).to_bytes(4, byteorder='little')) + binascii.crc32(bitstream).to_bytes(4, byteorder='little'))
|
||||
time.sleep(0.5)
|
||||
sent = 0
|
||||
print("Sending data", end="")
|
||||
while len(bitstream) - sent > 0:
|
||||
print(".", end="")
|
||||
sys.stdout.flush()
|
||||
txLength = len(bitstream)
|
||||
if txLength > 2048:
|
||||
txLength = 2048
|
||||
port.write(bitstream[sent:sent + txLength])
|
||||
time.sleep(0.05)
|
||||
sent += txLength
|
||||
while port.is_open:
|
||||
inLen = port.in_waiting
|
||||
if inLen > 0:
|
||||
data = port.read(inLen).decode('utf-8','ignore');
|
||||
if data == 'FPGA':
|
||||
print(data)
|
||||
else:
|
||||
print(data, end='')
|
||||
port.close()
|
||||
print("\n")
|
8
main/CMakeLists.txt
Normal file
8
main/CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
idf_component_register(
|
||||
SRCS
|
||||
"main.c"
|
||||
"wifi_connect.c"
|
||||
"wifi_connection.c"
|
||||
INCLUDE_DIRS
|
||||
"." "include"
|
||||
)
|
0
main/include/main.h
Normal file
0
main/include/main.h
Normal file
5
main/include/wifi_connect.h
Normal file
5
main/include/wifi_connect.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool wifi_connect_to_stored();
|
46
main/include/wifi_connection.h
Normal file
46
main/include/wifi_connection.h
Normal file
@@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "esp_wifi.h"
|
||||
#include "esp_wifi_types.h"
|
||||
#include "esp_wpa2.h"
|
||||
|
||||
#define WIFI_MCH2022_SSID "MCH2022"
|
||||
#define WIFI_MCH2022_USER "mch2022"
|
||||
#define WIFI_MCH2022_IDENT "mch2022"
|
||||
#define WIFI_MCH2022_PASSWORD "mch2022"
|
||||
#define WIFI_MCH2022_AUTH WIFI_AUTH_WPA2_ENTERPRISE
|
||||
#define WIFI_MCH2022_PHASE2 ESP_EAP_TTLS_PHASE2_MSCHAPV2
|
||||
|
||||
// Simpler interpretation of WiFi signal strength.
|
||||
typedef enum {
|
||||
WIFI_STRENGTH_VERY_BAD,
|
||||
WIFI_STRENGTH_BAD,
|
||||
WIFI_STRENGTH_GOOD,
|
||||
WIFI_STRENGTH_VERY_GOOD,
|
||||
} wifi_strength_t;
|
||||
|
||||
// Thresholds for aforementioned signal strength definitions.
|
||||
#define WIFI_THRESH_BAD -80
|
||||
#define WIFI_THRESH_GOOD -70
|
||||
#define WIFI_THRESH_VERY_GOOD -67
|
||||
|
||||
// Firt time initialisation of the WiFi stack.
|
||||
void wifi_init();
|
||||
|
||||
// Connect to a traditional username/password WiFi network.
|
||||
bool wifi_connect(const char* aSsid, const char* aPassword, wifi_auth_mode_t aAuthmode, uint8_t aRetryMax);
|
||||
|
||||
// Connect to a WPA2 enterprise WiFi network.
|
||||
bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonIdent, const char* aPassword, esp_eap_ttls_phase2_types phase2, uint8_t aRetryMax);
|
||||
|
||||
// Scan for WiFi networks.
|
||||
// Updates the APs pointer if non-null.
|
||||
// Returns the number of APs found.
|
||||
size_t wifi_scan(wifi_ap_record_t **aps);
|
||||
|
||||
// Get the strength value for a given RSSI.
|
||||
wifi_strength_t wifi_rssi_to_strength(int8_t rssi);
|
54
main/main.c
Normal file
54
main/main.c
Normal file
@@ -0,0 +1,54 @@
|
||||
|
||||
// This file contains a simple hello world app which you can base you own apps on.
|
||||
|
||||
#include "main.h"
|
||||
#include "hardware.h"
|
||||
#include "pax_gfx.h"
|
||||
#include "pax_codecs.h"
|
||||
#include "ili9341.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "esp_system.h"
|
||||
|
||||
static pax_buf_t buf;
|
||||
xQueueHandle buttonQueue;
|
||||
|
||||
static const char *TAG = "mch2022-demo-app";
|
||||
|
||||
void disp_flush() {
|
||||
ili9341_write(get_ili9341(), buf.buf);
|
||||
}
|
||||
|
||||
void app_main() {
|
||||
// Init HW.
|
||||
bsp_init();
|
||||
bsp_rp2040_init();
|
||||
buttonQueue = get_rp2040()->queue;
|
||||
|
||||
// Init GFX.
|
||||
pax_buf_init(&buf, NULL, 320, 240, PAX_BUF_16_565RGB);
|
||||
|
||||
while (1) {
|
||||
// Pick a random background color.
|
||||
int hue = esp_random() & 255;
|
||||
pax_col_t col = pax_col_hsv(hue, 255 /*saturation*/, 255 /*brighness*/);
|
||||
|
||||
// Show some random color hello world.
|
||||
pax_background(&buf, col);
|
||||
char *text = "Hello, World!";
|
||||
const pax_font_t *font = pax_get_font("saira condensed");
|
||||
pax_vec1_t dims = pax_text_size(font, font->default_size, text);
|
||||
pax_draw_text(
|
||||
&buf, 0xff000000, font, font->default_size,
|
||||
(buf.width - dims.x) / 2.0,
|
||||
(buf.height - dims.y) / 2.0,
|
||||
text
|
||||
);
|
||||
disp_flush();
|
||||
|
||||
// Await any button press and do another cycle.
|
||||
rp2040_input_message_t message;
|
||||
xQueueReceive(buttonQueue, &message, portMAX_DELAY);
|
||||
}
|
||||
}
|
102
main/wifi_connect.c
Normal file
102
main/wifi_connect.c
Normal file
@@ -0,0 +1,102 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sdkconfig.h>
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
#include <freertos/queue.h>
|
||||
#include <esp_system.h>
|
||||
#include <esp_err.h>
|
||||
#include <esp_log.h>
|
||||
#include <nvs_flash.h>
|
||||
#include <nvs.h>
|
||||
#include "pax_gfx.h"
|
||||
#include "wifi_connection.h"
|
||||
|
||||
static const char *TAG = "wifi_connect";
|
||||
|
||||
bool wifi_connect_to_stored() {
|
||||
bool result = false;
|
||||
// Open NVS.
|
||||
nvs_handle_t handle;
|
||||
nvs_open("system", NVS_READWRITE, &handle);
|
||||
wifi_auth_mode_t authmode = 0;
|
||||
esp_eap_ttls_phase2_types phase2 = 0;
|
||||
char *ssid = NULL;
|
||||
char *ident = NULL;
|
||||
char *anon_ident = NULL;
|
||||
char *password = NULL;
|
||||
size_t len;
|
||||
|
||||
// Read NVS.
|
||||
esp_err_t res;
|
||||
// Read SSID.
|
||||
res = nvs_get_str(handle, "wifi.ssid", NULL, &len);
|
||||
if (res) goto errcheck;
|
||||
ssid = malloc(len);
|
||||
res = nvs_get_str(handle, "wifi.ssid", ssid, &len);
|
||||
if (res) goto errcheck;
|
||||
|
||||
// Check whether connection is enterprise.
|
||||
res = nvs_get_u8(handle, "wifi.authmode", &authmode);
|
||||
bool use_ent = authmode == WIFI_AUTH_WPA2_ENTERPRISE;
|
||||
if (res) goto errcheck;
|
||||
|
||||
if (use_ent) {
|
||||
// Read enterprise-specific parameters.
|
||||
|
||||
// Read phase2 mode.
|
||||
res = nvs_get_u8(handle, "wifi.phase2", &phase2);
|
||||
if (res) goto errcheck;
|
||||
|
||||
// Read identity.
|
||||
res = nvs_get_str(handle, "wifi.username", NULL, &len);
|
||||
if (res) goto errcheck;
|
||||
ident = malloc(len);
|
||||
res = nvs_get_str(handle, "wifi.username", ident, &len);
|
||||
|
||||
// Read anonymous identity.
|
||||
res = nvs_get_str(handle, "wifi.anon_ident", NULL, &len);
|
||||
if (res == ESP_ERR_NVS_NOT_FOUND) {
|
||||
// Default is use the same thing.
|
||||
anon_ident = strdup(ident);
|
||||
} else {
|
||||
if (res) goto errcheck;
|
||||
anon_ident = malloc(len);
|
||||
res = nvs_get_str(handle, "wifi.anon_ident", anon_ident, &len);
|
||||
if (res) goto errcheck;
|
||||
}
|
||||
}
|
||||
// Read password.
|
||||
res = nvs_get_str(handle, "wifi.password", NULL, &len);
|
||||
if (res) goto errcheck;
|
||||
password = malloc(len);
|
||||
res = nvs_get_str(handle, "wifi.password", password, &len);
|
||||
if (res) goto errcheck;
|
||||
|
||||
// Close NVS.
|
||||
nvs_close(handle);
|
||||
|
||||
// Open the appropriate connection.
|
||||
if (use_ent) {
|
||||
result = wifi_connect_ent(ssid, ident, anon_ident, password, phase2, 3);
|
||||
} else {
|
||||
result = wifi_connect(ssid, password, authmode, 3);
|
||||
}
|
||||
|
||||
errcheck:
|
||||
if (res == ESP_ERR_NVS_NOT_FOUND || res == ESP_ERR_NVS_NOT_INITIALIZED) {
|
||||
// When NVS is not initialised.
|
||||
ESP_LOGI(TAG, "WiFi settings not stored in NVS.");
|
||||
} else if (res) {
|
||||
// Other errors.
|
||||
ESP_LOGE(TAG, "Error connecting to WiFi: %s", esp_err_to_name(res));
|
||||
}
|
||||
|
||||
// Free memory.
|
||||
if (ssid) free(ssid);
|
||||
if (ident) free(ident);
|
||||
if (anon_ident) free(anon_ident);
|
||||
if (password) free(password);
|
||||
|
||||
return result;
|
||||
}
|
287
main/wifi_connection.c
Normal file
287
main/wifi_connection.c
Normal file
@@ -0,0 +1,287 @@
|
||||
#include <string.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
#include "wifi_connection.h"
|
||||
|
||||
static const char *TAG = "wifi_connection";
|
||||
|
||||
#define WIFI_CONNECTED_BIT BIT0
|
||||
#define WIFI_FAIL_BIT BIT1
|
||||
#define WIFI_STARTED_BIT BIT2
|
||||
|
||||
static EventGroupHandle_t wifiEventGroup;
|
||||
|
||||
static uint8_t retryCount = 0;
|
||||
static uint8_t maxRetries = 3;
|
||||
static bool isScanning = false;
|
||||
|
||||
#define WIFI_SORT_ERRCHECK(err) do {int res = (err); if(res) {ESP_LOGE(TAG, "WiFi connection error: %s", esp_err_to_name(res)); goto error; } } while(0)
|
||||
|
||||
static void event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {
|
||||
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
|
||||
xEventGroupSetBits(wifiEventGroup, WIFI_STARTED_BIT);
|
||||
if (!isScanning) {
|
||||
// Connect only if we're not scanning the WiFi.
|
||||
esp_wifi_connect();
|
||||
}
|
||||
ESP_LOGI(TAG, "WiFi station start.");
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_STOP) {
|
||||
xEventGroupClearBits(wifiEventGroup, WIFI_STARTED_BIT);
|
||||
ESP_LOGI(TAG, "WiFi station stop.");
|
||||
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
|
||||
if (retryCount < 3) {
|
||||
esp_wifi_connect();
|
||||
retryCount++;
|
||||
ESP_LOGI(TAG, "Retrying connection");
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Connection failed");
|
||||
xEventGroupSetBits(wifiEventGroup, WIFI_FAIL_BIT);
|
||||
}
|
||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
|
||||
ESP_LOGI(TAG, "Got ip:" IPSTR, IP2STR(&event->ip_info.ip));
|
||||
retryCount = 0;
|
||||
xEventGroupSetBits(wifiEventGroup, WIFI_CONNECTED_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
void wifi_init() {
|
||||
// Create an event group for WiFi things.
|
||||
wifiEventGroup = xEventGroupCreate();
|
||||
|
||||
// Initialise WiFi stack.
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
esp_netif_create_default_wifi_sta();
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
// Register event handlers for WiFi.
|
||||
esp_event_handler_instance_t instance_any_id;
|
||||
esp_event_handler_instance_t instance_got_ip;
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, &instance_any_id));
|
||||
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, &instance_got_ip));
|
||||
|
||||
// Turn off WiFi hardware.
|
||||
ESP_ERROR_CHECK(esp_wifi_stop());
|
||||
}
|
||||
|
||||
bool wifi_connect(const char* aSsid, const char* aPassword, wifi_auth_mode_t aAuthmode, uint8_t aRetryMax) {
|
||||
// Set the retry counts.
|
||||
retryCount = 0;
|
||||
maxRetries = aRetryMax;
|
||||
|
||||
// Create a config.
|
||||
wifi_config_t wifi_config = {0};
|
||||
strcpy((char*) wifi_config.sta.ssid, aSsid);
|
||||
strcpy((char*) wifi_config.sta.password, aPassword);
|
||||
wifi_config.sta.threshold.authmode = aAuthmode;
|
||||
|
||||
// Set WiFi config.
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
// Disable 11b as NOC asked.
|
||||
esp_wifi_config_11b_rate(WIFI_IF_STA, true);
|
||||
// Start WiFi.
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "Connecting to WiFi...");
|
||||
|
||||
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
||||
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
|
||||
EventBits_t bits = xEventGroupWaitBits(wifiEventGroup, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually happened. */
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
ESP_LOGI(TAG, "Connected to WiFi");
|
||||
return true;
|
||||
} else if (bits & WIFI_FAIL_BIT) {
|
||||
ESP_LOGE(TAG, "Failed to connect");
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_stop());
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unknown event received while waiting on connection");
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_stop());
|
||||
}
|
||||
error:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool wifi_connect_ent(const char* aSsid, const char *aIdent, const char *aAnonIdent, const char* aPassword, esp_eap_ttls_phase2_types phase2, uint8_t aRetryMax) {
|
||||
retryCount = 0;
|
||||
maxRetries = aRetryMax;
|
||||
wifi_config_t wifi_config = {0};
|
||||
if (strlen(aSsid) > 32) {
|
||||
ESP_LOGE(TAG, "SSID is too long (%zu > 32)!", strlen(aSsid));
|
||||
return false;
|
||||
}
|
||||
strncpy((char*) wifi_config.sta.ssid, aSsid, 32);
|
||||
|
||||
// Set WiFi config.
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_set_mode(WIFI_MODE_STA) );
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config) );
|
||||
|
||||
// Set WPA2 ENT config.
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_sta_wpa2_ent_set_identity((const uint8_t *) aAnonIdent, strlen(aAnonIdent)));
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_sta_wpa2_ent_set_username((const uint8_t *) aIdent, strlen(aIdent)));
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_sta_wpa2_ent_set_password((const uint8_t *) aPassword, strlen(aPassword)));
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_sta_wpa2_ent_set_ttls_phase2_method(phase2));
|
||||
// Enable enterprise auth.
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_sta_wpa2_ent_enable());
|
||||
// Disable 11b as NOC asked.
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_config_11b_rate(WIFI_IF_STA, true));
|
||||
// Start the connection.
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "Connecting to '%s' as '%s'/'%s': %s", aSsid, aIdent, aAnonIdent, aPassword);
|
||||
ESP_LOGI(TAG, "Phase2 mode: %d", phase2);
|
||||
|
||||
/* Waiting until either the connection is established (WIFI_CONNECTED_BIT) or connection failed for the maximum
|
||||
* number of re-tries (WIFI_FAIL_BIT). The bits are set by event_handler() (see above) */
|
||||
EventBits_t bits = xEventGroupWaitBits(wifiEventGroup, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, portMAX_DELAY);
|
||||
/* xEventGroupWaitBits() returns the bits before the call returned, hence we can test which event actually happened. */
|
||||
if (bits & WIFI_CONNECTED_BIT) {
|
||||
ESP_LOGI(TAG, "Connected to WiFi");
|
||||
return true;
|
||||
} else if (bits & WIFI_FAIL_BIT) {
|
||||
ESP_LOGE(TAG, "Failed to connect");
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_stop());
|
||||
} else {
|
||||
ESP_LOGE(TAG, "Unknown event received while waiting on connection");
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_stop());
|
||||
}
|
||||
error:
|
||||
return false;
|
||||
}
|
||||
|
||||
// Shows a nice info message describing an AP record.
|
||||
static inline void wifi_desc_record(wifi_ap_record_t *record) {
|
||||
// Make a string representation of BSSID.
|
||||
char *bssid_str = malloc(3*6);
|
||||
if (!bssid_str) return;
|
||||
snprintf(bssid_str, 3*6, "%02X:%02X:%02X:%02X:%02X:%02X",
|
||||
record->bssid[0], record->bssid[1], record->bssid[2],
|
||||
record->bssid[3], record->bssid[4], record->bssid[5]
|
||||
);
|
||||
|
||||
// Make a string representation of 11b/g/n modes.
|
||||
char *phy_str = malloc(9);
|
||||
if (!phy_str) {
|
||||
free(bssid_str);
|
||||
return;
|
||||
}
|
||||
*phy_str = 0;
|
||||
if (record->phy_11b | record->phy_11g | record->phy_11n) {
|
||||
strcpy(phy_str, " 1");
|
||||
}
|
||||
if (record->phy_11b) {
|
||||
strcat(phy_str, "/b");
|
||||
}
|
||||
if (record->phy_11g) {
|
||||
strcat(phy_str, "/g");
|
||||
}
|
||||
if (record->phy_11n) {
|
||||
strcat(phy_str, "/n");
|
||||
}
|
||||
phy_str[2] = '1';
|
||||
|
||||
ESP_LOGI(TAG, "AP %s %s rssi=%hhd%s", bssid_str, record->ssid, record->rssi, phy_str);
|
||||
free(bssid_str);
|
||||
free(phy_str);
|
||||
}
|
||||
|
||||
// Scan for WiFi access points.
|
||||
size_t wifi_scan(wifi_ap_record_t **aps_out) {
|
||||
isScanning = true;
|
||||
wifi_ap_record_t *aps = NULL;
|
||||
// Scan for any non-hidden APs on all channels.
|
||||
wifi_scan_config_t cfg = {
|
||||
.ssid = NULL,
|
||||
.bssid = NULL,
|
||||
.channel = 0,
|
||||
.scan_type = WIFI_SCAN_TYPE_ACTIVE,
|
||||
.scan_time = { .active={ 0, 0 } },
|
||||
};
|
||||
|
||||
// Start the scan now.
|
||||
ESP_LOGI(TAG, "Starting scan...");
|
||||
esp_err_t res = esp_wifi_scan_start(&cfg, true);
|
||||
// Whether to call esp_wifi_stop() on finish.
|
||||
bool stopWhenDone = false;
|
||||
if (res == ESP_ERR_WIFI_NOT_STARTED) {
|
||||
// If it complains that the wifi wasn't started, then do so.
|
||||
ESP_LOGI(TAG, "Starting WiFi for scan");
|
||||
|
||||
// Set to station but don't connect.
|
||||
res = esp_wifi_set_mode(WIFI_MODE_STA);
|
||||
if (res) goto ohno;
|
||||
|
||||
// Start WiFi.
|
||||
res = esp_wifi_start();
|
||||
if (res) goto ohno;
|
||||
stopWhenDone = true;
|
||||
|
||||
// Await the STA started bit.
|
||||
xEventGroupWaitBits(wifiEventGroup, WIFI_STARTED_BIT, pdFALSE, pdFALSE, pdMS_TO_TICKS(2000));
|
||||
|
||||
// Try again.
|
||||
res = esp_wifi_scan_start(&cfg, true);
|
||||
}
|
||||
if (res) {
|
||||
ohno:
|
||||
ESP_LOGE(TAG, "Error in WiFi scan: %s", esp_err_to_name(res));
|
||||
isScanning = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Allocate memory for AP list.
|
||||
uint16_t num_ap = 0;
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_scan_get_ap_num(&num_ap));
|
||||
aps = malloc(sizeof(wifi_ap_record_t) * num_ap);
|
||||
if (!aps) {
|
||||
ESP_LOGE(TAG, "Out of memory (%zd bytes)", sizeof(wifi_ap_record_t) * num_ap);
|
||||
num_ap = 0;
|
||||
esp_wifi_scan_get_ap_records(&num_ap, NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Collect APs and report findings.
|
||||
WIFI_SORT_ERRCHECK(esp_wifi_scan_get_ap_records(&num_ap, aps));
|
||||
for (uint16_t i = 0; i < num_ap; i++) {
|
||||
wifi_desc_record(&aps[i]);
|
||||
}
|
||||
|
||||
// Clean up.
|
||||
if (aps_out) {
|
||||
// Output pointer is non-null, return the APs list.
|
||||
*aps_out = aps;
|
||||
} else {
|
||||
// Output pointer is null, free the APs list.
|
||||
free(aps);
|
||||
}
|
||||
if (stopWhenDone) {
|
||||
// Stop WiFi because it was started only for this scan.
|
||||
esp_wifi_stop();
|
||||
}
|
||||
isScanning = false;
|
||||
return num_ap;
|
||||
|
||||
error:
|
||||
if (aps) free(aps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Get the strength value for a given RSSI.
|
||||
wifi_strength_t wifi_rssi_to_strength(int8_t rssi) {
|
||||
if (rssi > WIFI_THRESH_VERY_GOOD) return WIFI_STRENGTH_VERY_GOOD;
|
||||
else if (rssi > WIFI_THRESH_GOOD) return WIFI_STRENGTH_GOOD;
|
||||
else if (rssi > WIFI_THRESH_BAD) return WIFI_STRENGTH_BAD;
|
||||
else return WIFI_STRENGTH_VERY_BAD;
|
||||
}
|
9
partitions.csv
Normal file
9
partitions.csv
Normal file
@@ -0,0 +1,9 @@
|
||||
# ESP-IDF Partition Table
|
||||
# Name, Type, SubType, Offset, Size, Flags
|
||||
nvs, data, nvs, 0xA000, 12K,
|
||||
otadata, data, ota, 0xD000, 8K,
|
||||
phy_init, data, phy, 0xF000, 4K,
|
||||
ota_0, 0, ota_0, 0x10000, 1600K,
|
||||
ota_1, 0, ota_1, 0x1A0000, 1600K,
|
||||
appfs, 0x43, 3, 0x330000, 8000K,
|
||||
locfd, data, fat, 0xB00000, 5120K,
|
|
BIN
partitions.ods
Normal file
BIN
partitions.ods
Normal file
Binary file not shown.
Reference in New Issue
Block a user