Minor header/directrory cleanup (#802)
This commit is contained in:
parent
257db5ac7d
commit
064dd4794f
32 changed files with 1226 additions and 1116 deletions
|
|
@ -71,8 +71,6 @@ static int __usb_task_irq;
|
||||||
|
|
||||||
#define EPNUM_HID 0x83
|
#define EPNUM_HID 0x83
|
||||||
|
|
||||||
#define EPNUM_MIDI 0x01
|
|
||||||
|
|
||||||
|
|
||||||
const uint8_t *tud_descriptor_device_cb(void) {
|
const uint8_t *tud_descriptor_device_cb(void) {
|
||||||
static tusb_desc_device_t usbd_desc_device = {
|
static tusb_desc_device_t usbd_desc_device = {
|
||||||
|
|
@ -91,7 +89,7 @@ const uint8_t *tud_descriptor_device_cb(void) {
|
||||||
.iSerialNumber = USBD_STR_SERIAL,
|
.iSerialNumber = USBD_STR_SERIAL,
|
||||||
.bNumConfigurations = 1
|
.bNumConfigurations = 1
|
||||||
};
|
};
|
||||||
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallJoystick && !__USBInstallMIDI) {
|
if (__USBInstallSerial && !__USBInstallKeyboard && !__USBInstallMouse && !__USBInstallJoystick) {
|
||||||
// Can use as-is, this is the default USB case
|
// Can use as-is, this is the default USB case
|
||||||
return (const uint8_t *)&usbd_desc_device;
|
return (const uint8_t *)&usbd_desc_device;
|
||||||
}
|
}
|
||||||
|
|
@ -105,9 +103,6 @@ const uint8_t *tud_descriptor_device_cb(void) {
|
||||||
if (__USBInstallJoystick) {
|
if (__USBInstallJoystick) {
|
||||||
usbd_desc_device.idProduct |= 0x0100;
|
usbd_desc_device.idProduct |= 0x0100;
|
||||||
}
|
}
|
||||||
if (__USBInstallMIDI) {
|
|
||||||
usbd_desc_device.idProduct |= 0x2000;
|
|
||||||
}
|
|
||||||
// Set the device class to 0 to indicate multiple device classes
|
// Set the device class to 0 to indicate multiple device classes
|
||||||
usbd_desc_device.bDeviceClass = 0;
|
usbd_desc_device.bDeviceClass = 0;
|
||||||
usbd_desc_device.bDeviceSubClass = 0;
|
usbd_desc_device.bDeviceSubClass = 0;
|
||||||
|
|
@ -228,7 +223,7 @@ void __SetupUSBDescriptor() {
|
||||||
if (!usbd_desc_cfg) {
|
if (!usbd_desc_cfg) {
|
||||||
bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallJoystick;
|
bool hasHID = __USBInstallKeyboard || __USBInstallMouse || __USBInstallJoystick;
|
||||||
|
|
||||||
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0) + (__USBInstallMIDI ? 2 : 0);
|
uint8_t interface_count = (__USBInstallSerial ? 2 : 0) + (hasHID ? 1 : 0);
|
||||||
|
|
||||||
uint8_t cdc_desc[TUD_CDC_DESC_LEN] = {
|
uint8_t cdc_desc[TUD_CDC_DESC_LEN] = {
|
||||||
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
// Interface number, string index, protocol, report descriptor len, EP In & Out address, size & polling interval
|
||||||
|
|
@ -243,13 +238,7 @@ void __SetupUSBDescriptor() {
|
||||||
TUD_HID_DESCRIPTOR(hid_itf, 0, HID_ITF_PROTOCOL_NONE, hid_report_len, EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
|
TUD_HID_DESCRIPTOR(hid_itf, 0, HID_ITF_PROTOCOL_NONE, hid_report_len, EPNUM_HID, CFG_TUD_HID_EP_BUFSIZE, 10)
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t midi_itf = hid_itf + (hasHID ? 1 : 0);
|
int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0);
|
||||||
uint8_t midi_desc[TUD_MIDI_DESC_LEN] = {
|
|
||||||
// Interface number, string index, EP Out & EP In address, EP size
|
|
||||||
TUD_MIDI_DESCRIPTOR(midi_itf, 0, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64)
|
|
||||||
};
|
|
||||||
|
|
||||||
int usbd_desc_len = TUD_CONFIG_DESC_LEN + (__USBInstallSerial ? sizeof(cdc_desc) : 0) + (hasHID ? sizeof(hid_desc) : 0) + (__USBInstallMIDI ? sizeof(midi_desc) : 0);
|
|
||||||
|
|
||||||
uint8_t tud_cfg_desc[TUD_CONFIG_DESC_LEN] = {
|
uint8_t tud_cfg_desc[TUD_CONFIG_DESC_LEN] = {
|
||||||
// Config number, interface count, string index, total length, attribute, power in mA
|
// Config number, interface count, string index, total length, attribute, power in mA
|
||||||
|
|
@ -271,9 +260,6 @@ void __SetupUSBDescriptor() {
|
||||||
memcpy(ptr, hid_desc, sizeof(hid_desc));
|
memcpy(ptr, hid_desc, sizeof(hid_desc));
|
||||||
ptr += sizeof(hid_desc);
|
ptr += sizeof(hid_desc);
|
||||||
}
|
}
|
||||||
if (__USBInstallMIDI) {
|
|
||||||
memcpy(ptr, midi_desc, sizeof(midi_desc));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ extern void __USBInstallSerial() __attribute__((weak));
|
||||||
extern void __USBInstallKeyboard() __attribute__((weak));
|
extern void __USBInstallKeyboard() __attribute__((weak));
|
||||||
extern void __USBInstallJoystick() __attribute__((weak));
|
extern void __USBInstallJoystick() __attribute__((weak));
|
||||||
extern void __USBInstallMouse() __attribute__((weak));
|
extern void __USBInstallMouse() __attribute__((weak));
|
||||||
extern void __USBInstallMIDI() __attribute__((weak));
|
|
||||||
|
|
||||||
// Big, global USB mutex, shared with all USB devices to make sure we don't
|
// Big, global USB mutex, shared with all USB devices to make sure we don't
|
||||||
// have multiple cores updating the TUSB state in parallel
|
// have multiple cores updating the TUSB state in parallel
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,24 @@
|
||||||
|
/*
|
||||||
|
Arduino OTA.cpp - Simple Arduino IDE OTA handler
|
||||||
|
Modified 2022 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
Taken from the ESP8266 core libraries, (c) various authors.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
#include "ArduinoOTA.h"
|
#include "ArduinoOTA.h"
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,24 @@
|
||||||
|
/*
|
||||||
|
Arduino OTA.h - Simple Arduino IDE OTA handler
|
||||||
|
Modified 2022 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
Taken from the ESP8266 core libraries, (c) various authors.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,9 @@ void loop() {
|
||||||
WiFi.disconnect();
|
WiFi.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (s == WL_CONNECTED) { MDNS.update(); }
|
if (s == WL_CONNECTED) {
|
||||||
|
MDNS.update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Do work:
|
// Do work:
|
||||||
// DNS
|
// DNS
|
||||||
|
|
|
||||||
|
|
@ -57,21 +57,23 @@ void handleWifi() {
|
||||||
+ String(softAP_ssid) + F("</td></tr>"
|
+ String(softAP_ssid) + F("</td></tr>"
|
||||||
"<tr><td>IP ")
|
"<tr><td>IP ")
|
||||||
+ toStringIp(WiFi.softAPIP()) + F("</td></tr>"
|
+ toStringIp(WiFi.softAPIP()) + F("</td></tr>"
|
||||||
"</table>"
|
"</table>"
|
||||||
"\r\n<br />"
|
"\r\n<br />"
|
||||||
"<table><tr><th align='left'>WLAN config</th></tr>"
|
"<table><tr><th align='left'>WLAN config</th></tr>"
|
||||||
"<tr><td>SSID ")
|
"<tr><td>SSID ")
|
||||||
+ String(ssid) + F("</td></tr>"
|
+ String(ssid) + F("</td></tr>"
|
||||||
"<tr><td>IP ")
|
"<tr><td>IP ")
|
||||||
+ toStringIp(WiFi.localIP()) + F("</td></tr>"
|
+ toStringIp(WiFi.localIP()) + F("</td></tr>"
|
||||||
"</table>"
|
"</table>"
|
||||||
"\r\n<br />"
|
"\r\n<br />"
|
||||||
"<table><tr><th align='left'>WLAN list (refresh if any missing)</th></tr>");
|
"<table><tr><th align='left'>WLAN list (refresh if any missing)</th></tr>");
|
||||||
Serial.println("scan start");
|
Serial.println("scan start");
|
||||||
int n = WiFi.scanNetworks();
|
int n = WiFi.scanNetworks();
|
||||||
Serial.println("scan done");
|
Serial.println("scan done");
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
for (int i = 0; i < n; i++) { Page += String(F("\r\n<tr><td>SSID ")) + WiFi.SSID(i) + ((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? F(" ") : F(" *")) + F(" (") + WiFi.RSSI(i) + F(")</td></tr>"); }
|
for (int i = 0; i < n; i++) {
|
||||||
|
Page += String(F("\r\n<tr><td>SSID ")) + WiFi.SSID(i) + ((WiFi.encryptionType(i) == ENC_TYPE_NONE) ? F(" ") : F(" *")) + F(" (") + WiFi.RSSI(i) + F(")</td></tr>");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
Page += F("<tr><td>No WLAN found</td></tr>");
|
Page += F("<tr><td>No WLAN found</td></tr>");
|
||||||
}
|
}
|
||||||
|
|
@ -114,7 +116,9 @@ void handleNotFound() {
|
||||||
message += server.args();
|
message += server.args();
|
||||||
message += F("\n");
|
message += F("\n");
|
||||||
|
|
||||||
for (uint8_t i = 0; i < server.args(); i++) { message += String(F(" ")) + server.argName(i) + F(": ") + server.arg(i) + F("\n"); }
|
for (uint8_t i = 0; i < server.args(); i++) {
|
||||||
|
message += String(F(" ")) + server.argName(i) + F(": ") + server.arg(i) + F("\n");
|
||||||
|
}
|
||||||
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate");
|
||||||
server.sendHeader("Pragma", "no-cache");
|
server.sendHeader("Pragma", "no-cache");
|
||||||
server.sendHeader("Expires", "-1");
|
server.sendHeader("Expires", "-1");
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,9 @@
|
||||||
boolean isIp(String str) {
|
boolean isIp(String str) {
|
||||||
for (size_t i = 0; i < str.length(); i++) {
|
for (size_t i = 0; i < str.length(); i++) {
|
||||||
int c = str.charAt(i);
|
int c = str.charAt(i);
|
||||||
if (c != '.' && (c < '0' || c > '9')) { return false; }
|
if (c != '.' && (c < '0' || c > '9')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -10,7 +12,9 @@ boolean isIp(String str) {
|
||||||
/** IP to String? */
|
/** IP to String? */
|
||||||
String toStringIp(IPAddress ip) {
|
String toStringIp(IPAddress ip) {
|
||||||
String res = "";
|
String res = "";
|
||||||
for (int i = 0; i < 3; i++) { res += String((ip >> (8 * i)) & 0xFF) + "."; }
|
for (int i = 0; i < 3; i++) {
|
||||||
|
res += String((ip >> (8 * i)) & 0xFF) + ".";
|
||||||
|
}
|
||||||
res += String(((ip >> 8 * 3)) & 0xFF);
|
res += String(((ip >> 8 * 3)) & 0xFF);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,29 @@
|
||||||
|
/*
|
||||||
|
DNSServer.cpp - Simple DNS server for the Pico
|
||||||
|
Modified 2022 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
Taken from the ESP8266 core libraries, (c) various authors.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#include "WiFi.h"
|
#include "WiFi.h"
|
||||||
#include "DNSServer.h"
|
#include "DNSServer.h"
|
||||||
#include <lwip/def.h>
|
#include <lwip/def.h>
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
||||||
extern struct rst_info resetInfo;
|
|
||||||
|
|
||||||
#ifdef DEBUG_ESP_PORT
|
#ifdef DEBUG_ESP_PORT
|
||||||
#define CONSOLE DEBUG_ESP_PORT
|
#define CONSOLE DEBUG_ESP_PORT
|
||||||
#else
|
#else
|
||||||
|
|
@ -49,399 +68,389 @@ extern struct rst_info resetInfo;
|
||||||
// Want to keep IDs unique across restarts and continquious
|
// Want to keep IDs unique across restarts and continquious
|
||||||
static uint32_t _ids __attribute__((section(".noinit")));
|
static uint32_t _ids __attribute__((section(".noinit")));
|
||||||
|
|
||||||
DNSServer::DNSServer()
|
DNSServer::DNSServer() {
|
||||||
{
|
// I have observed that using 0 for captive and non-zero (600) when
|
||||||
// I have observed that using 0 for captive and non-zero (600) when
|
// forwarding, will help Android devices recognize the change in connectivity.
|
||||||
// forwarding, will help Android devices recognize the change in connectivity.
|
// They will then report connected.
|
||||||
// They will then report connected.
|
_ttl = lwip_htonl(60);
|
||||||
_ttl = lwip_htonl(60);
|
|
||||||
|
|
||||||
srand(rp2040.getCycleCount());
|
srand(rp2040.getCycleCount());
|
||||||
_ids = random(0, (1UL << 16) - 1);
|
_ids = random(0, (1UL << 16) - 1);
|
||||||
|
|
||||||
_errorReplyCode = DNSReplyCode::NonExistentDomain;
|
_errorReplyCode = DNSReplyCode::NonExistentDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::disableForwarder(const String &domainName, bool freeResources)
|
void DNSServer::disableForwarder(const String &domainName, bool freeResources) {
|
||||||
{
|
_forwarder = false;
|
||||||
_forwarder = false;
|
if (domainName != "") {
|
||||||
if (domainName != "") {
|
_domainName = domainName;
|
||||||
_domainName = domainName;
|
downcaseAndRemoveWwwPrefix(_domainName);
|
||||||
downcaseAndRemoveWwwPrefix(_domainName);
|
}
|
||||||
}
|
if (freeResources) {
|
||||||
if (freeResources) {
|
_dns = (uint32_t)0;
|
||||||
_dns = (uint32_t)0;
|
if (_que) {
|
||||||
if (_que) {
|
_que = nullptr;
|
||||||
_que = nullptr;
|
DEBUG_PRINTF("from stop, deleted _que\r\n");
|
||||||
DEBUG_PRINTF("from stop, deleted _que\r\n");
|
DEBUG_(({
|
||||||
DEBUG_(({
|
if (_que_ov) {
|
||||||
if (_que_ov) {
|
DEBUG_PRINTLN2("DNS forwarder que overflow or no reply to request: ", (_que_ov));
|
||||||
DEBUG_PRINTLN2("DNS forwarder que overflow or no reply to request: ", (_que_ov));
|
}
|
||||||
}
|
if (_que_drop) {
|
||||||
if (_que_drop) {
|
DEBUG_PRINTLN2("DNS forwarder que wrapped, reply dropped: ", (_que_drop));
|
||||||
DEBUG_PRINTLN2("DNS forwarder que wrapped, reply dropped: ", (_que_drop));
|
}
|
||||||
}
|
}));
|
||||||
}));
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DNSServer::enableForwarder(const String &domainName, const IPAddress &dns)
|
bool DNSServer::enableForwarder(const String &domainName, const IPAddress &dns) {
|
||||||
{
|
disableForwarder(domainName, false); // Just happens to have the same logic needed here.
|
||||||
disableForwarder(domainName, false); // Just happens to have the same logic needed here.
|
|
||||||
|
|
||||||
if (dns.isSet()) {
|
if (dns.isSet()) {
|
||||||
_dns = dns;
|
_dns = dns;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_dns.isSet()) {
|
if (_dns.isSet()) {
|
||||||
if (!_que) {
|
if (!_que) {
|
||||||
_que = std::unique_ptr<DNSS_REQUESTER[]> (new (std::nothrow) DNSS_REQUESTER[kDNSSQueSize]);
|
_que = std::unique_ptr<DNSS_REQUESTER[]> (new (std::nothrow) DNSS_REQUESTER[kDNSSQueSize]);
|
||||||
DEBUG_PRINTF("Created new _que\r\n");
|
DEBUG_PRINTF("Created new _que\r\n");
|
||||||
if (_que) {
|
if (_que) {
|
||||||
for (size_t i = 0; i < kDNSSQueSize; i++) {
|
for (size_t i = 0; i < kDNSSQueSize; i++) {
|
||||||
_que[i].ip = 0;
|
_que[i].ip = 0;
|
||||||
|
}
|
||||||
|
DEBUG_((_que_ov = 0));
|
||||||
|
DEBUG_((_que_drop = 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_que) {
|
||||||
|
_forwarder = true;
|
||||||
}
|
}
|
||||||
DEBUG_((_que_ov = 0));
|
|
||||||
DEBUG_((_que_drop = 0));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (_que) {
|
return _forwarder;
|
||||||
_forwarder = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return _forwarder;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DNSServer::start(const uint16_t &port, const String &domainName,
|
bool DNSServer::start(const uint16_t &port, const String &domainName,
|
||||||
const IPAddress &resolvedIP, const IPAddress &dns)
|
const IPAddress &resolvedIP, const IPAddress &dns) {
|
||||||
{
|
_port = (port) ? port : IANA_DNS_PORT;
|
||||||
_port = (port) ? port : IANA_DNS_PORT;
|
|
||||||
|
|
||||||
_resolvedIP[0] = resolvedIP[0];
|
_resolvedIP[0] = resolvedIP[0];
|
||||||
_resolvedIP[1] = resolvedIP[1];
|
_resolvedIP[1] = resolvedIP[1];
|
||||||
_resolvedIP[2] = resolvedIP[2];
|
_resolvedIP[2] = resolvedIP[2];
|
||||||
_resolvedIP[3] = resolvedIP[3];
|
_resolvedIP[3] = resolvedIP[3];
|
||||||
|
|
||||||
if (!enableForwarder(domainName, dns) && (dns.isSet() || _dns.isSet())) {
|
if (!enableForwarder(domainName, dns) && (dns.isSet() || _dns.isSet())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return _udp.begin(_port) == 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode)
|
|
||||||
{
|
|
||||||
_errorReplyCode = replyCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DNSServer::setTTL(const uint32_t &ttl)
|
|
||||||
{
|
|
||||||
_ttl = lwip_htonl(ttl);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t DNSServer::getTTL()
|
|
||||||
{
|
|
||||||
return lwip_ntohl(_ttl);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DNSServer::stop()
|
|
||||||
{
|
|
||||||
_udp.stop();
|
|
||||||
disableForwarder("", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName)
|
|
||||||
{
|
|
||||||
domainName.toLowerCase();
|
|
||||||
if (domainName.startsWith("www."))
|
|
||||||
domainName.remove(0, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DNSServer::forwardReply(uint8_t *buffer, size_t length)
|
|
||||||
{
|
|
||||||
if (!_forwarder || !_que) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DNSHeader *dnsHeader = (DNSHeader *)buffer;
|
|
||||||
uint16_t id = dnsHeader->ID;
|
|
||||||
// if (kDNSSQueSize <= (uint16_t)((uint16_t)_ids - id)) {
|
|
||||||
if ((uint16_t)kDNSSQueSize <= (uint16_t)_ids - id) {
|
|
||||||
DEBUG_((++_que_drop));
|
|
||||||
DEBUG_PRINTLN2("Forward reply ID: 0x", (String(id, HEX) + F(" dropped!")));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
size_t i = id & (kDNSSQueSize - 1);
|
|
||||||
|
|
||||||
// Drop duplicate packets
|
|
||||||
if (0 == _que[i].ip) {
|
|
||||||
DEBUG_PRINTLN2("Duplicate reply dropped ID: 0x", String(id, HEX));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
dnsHeader->ID = _que[i].id;
|
|
||||||
_udp.beginPacket(_que[i].ip, _que[i].port);
|
|
||||||
_udp.write(buffer, length);
|
|
||||||
_udp.endPacket();
|
|
||||||
DEBUG_PRINTLN2("Forward reply ID: 0x", (String(id, HEX) + F(" to ") + IPAddress(_que[i].ip).toString()));
|
|
||||||
_que[i].ip = 0; // This gets used to detect duplicate packets and overflow
|
|
||||||
}
|
|
||||||
|
|
||||||
void DNSServer::forwardRequest(uint8_t *buffer, size_t length)
|
|
||||||
{
|
|
||||||
if (!_forwarder || !_dns.isSet() || !_que) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DNSHeader *dnsHeader = (DNSHeader *)buffer;
|
|
||||||
++_ids;
|
|
||||||
size_t i = _ids & (kDNSSQueSize - 1);
|
|
||||||
DEBUG_(({
|
|
||||||
if (0 != _que[i].ip) {
|
|
||||||
++_que_ov;
|
|
||||||
}
|
}
|
||||||
}));
|
|
||||||
_que[i].ip = _udp.remoteIP();
|
return _udp.begin(_port) == 1;
|
||||||
_que[i].port = _udp.remotePort();
|
|
||||||
_que[i].id = dnsHeader->ID;
|
|
||||||
dnsHeader->ID = (uint16_t)_ids;
|
|
||||||
_udp.beginPacket(_dns, IANA_DNS_PORT);
|
|
||||||
_udp.write(buffer, length);
|
|
||||||
_udp.endPacket();
|
|
||||||
DEBUG_PRINTLN2("Forward request ID: 0x", (String(dnsHeader->ID, HEX) + F(" to ") + _dns.toString()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DNSServer::respondToRequest(uint8_t *buffer, size_t length)
|
void DNSServer::setErrorReplyCode(const DNSReplyCode &replyCode) {
|
||||||
{
|
_errorReplyCode = replyCode;
|
||||||
DNSHeader *dnsHeader;
|
}
|
||||||
uint8_t *query, *start;
|
|
||||||
const char *matchString;
|
|
||||||
size_t remaining, labelLength, queryLength;
|
|
||||||
uint16_t qtype, qclass;
|
|
||||||
|
|
||||||
dnsHeader = (DNSHeader *)buffer;
|
void DNSServer::setTTL(const uint32_t &ttl) {
|
||||||
|
_ttl = lwip_htonl(ttl);
|
||||||
|
}
|
||||||
|
|
||||||
// Must be a query for us to do anything with it
|
uint32_t DNSServer::getTTL() {
|
||||||
if (dnsHeader->QR != DNS_QR_QUERY) {
|
return lwip_ntohl(_ttl);
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If operation is anything other than query, we don't do it
|
void DNSServer::stop() {
|
||||||
if (dnsHeader->OPCode != DNS_OPCODE_QUERY) {
|
_udp.stop();
|
||||||
replyWithError(dnsHeader, DNSReplyCode::NotImplemented);
|
disableForwarder("", true);
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Only support requests containing single queries - everything else
|
void DNSServer::downcaseAndRemoveWwwPrefix(String &domainName) {
|
||||||
// is badly defined
|
domainName.toLowerCase();
|
||||||
if (dnsHeader->QDCount != lwip_htons(1)) {
|
if (domainName.startsWith("www.")) {
|
||||||
replyWithError(dnsHeader, DNSReplyCode::FormError);
|
domainName.remove(0, 4);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// We must return a FormError in the case of a non-zero ARCount to
|
|
||||||
// be minimally compatible with EDNS resolvers
|
|
||||||
if (dnsHeader->ANCount != 0 || dnsHeader->NSCount != 0
|
|
||||||
|| dnsHeader->ARCount != 0) {
|
|
||||||
replyWithError(dnsHeader, DNSReplyCode::FormError);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Even if we're not going to use the query, we need to parse it
|
|
||||||
// so we can check the address type that's being queried
|
|
||||||
|
|
||||||
query = start = buffer + DNS_HEADER_SIZE;
|
|
||||||
remaining = length - DNS_HEADER_SIZE;
|
|
||||||
while (remaining != 0 && *start != 0) {
|
|
||||||
labelLength = *start;
|
|
||||||
if (labelLength + 1 > remaining) {
|
|
||||||
replyWithError(dnsHeader, DNSReplyCode::FormError);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
remaining -= (labelLength + 1);
|
}
|
||||||
start += (labelLength + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 1 octet labelLength, 2 octet qtype, 2 octet qclass
|
void DNSServer::forwardReply(uint8_t *buffer, size_t length) {
|
||||||
if (remaining < 5) {
|
if (!_forwarder || !_que) {
|
||||||
replyWithError(dnsHeader, DNSReplyCode::FormError);
|
return;
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
start += 1; // Skip the 0 length label that we found above
|
|
||||||
|
|
||||||
memcpy(&qtype, start, sizeof(qtype));
|
|
||||||
start += 2;
|
|
||||||
memcpy(&qclass, start, sizeof(qclass));
|
|
||||||
start += 2;
|
|
||||||
|
|
||||||
queryLength = start - query;
|
|
||||||
|
|
||||||
if (qclass != lwip_htons(DNS_QCLASS_ANY)
|
|
||||||
&& qclass != lwip_htons(DNS_QCLASS_IN)) {
|
|
||||||
replyWithError(dnsHeader, DNSReplyCode::NonExistentDomain, query, queryLength);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (qtype != lwip_htons(DNS_QTYPE_A)
|
|
||||||
&& qtype != lwip_htons(DNS_QTYPE_ANY)) {
|
|
||||||
replyWithError(dnsHeader, DNSReplyCode::NonExistentDomain, query, queryLength);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we have no domain name configured, just return an error
|
|
||||||
if (_domainName == "") {
|
|
||||||
if (_forwarder) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
replyWithError(dnsHeader, _errorReplyCode, query, queryLength);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
DNSHeader *dnsHeader = (DNSHeader *)buffer;
|
||||||
|
uint16_t id = dnsHeader->ID;
|
||||||
|
// if (kDNSSQueSize <= (uint16_t)((uint16_t)_ids - id)) {
|
||||||
|
if ((uint16_t)kDNSSQueSize <= (uint16_t)_ids - id) {
|
||||||
|
DEBUG_((++_que_drop));
|
||||||
|
DEBUG_PRINTLN2("Forward reply ID: 0x", (String(id, HEX) + F(" dropped!")));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
size_t i = id & (kDNSSQueSize - 1);
|
||||||
|
|
||||||
// If we're running with a wildcard we can just return a result now
|
// Drop duplicate packets
|
||||||
if (_domainName == "*") {
|
if (0 == _que[i].ip) {
|
||||||
DEBUG_PRINTF("dnsServer - replyWithIP\r\n");
|
DEBUG_PRINTLN2("Duplicate reply dropped ID: 0x", String(id, HEX));
|
||||||
replyWithIP(dnsHeader, query, queryLength);
|
return;
|
||||||
return false;
|
}
|
||||||
}
|
dnsHeader->ID = _que[i].id;
|
||||||
|
_udp.beginPacket(_que[i].ip, _que[i].port);
|
||||||
|
_udp.write(buffer, length);
|
||||||
|
_udp.endPacket();
|
||||||
|
DEBUG_PRINTLN2("Forward reply ID: 0x", (String(id, HEX) + F(" to ") + IPAddress(_que[i].ip).toString()));
|
||||||
|
_que[i].ip = 0; // This gets used to detect duplicate packets and overflow
|
||||||
|
}
|
||||||
|
|
||||||
matchString = _domainName.c_str();
|
void DNSServer::forwardRequest(uint8_t *buffer, size_t length) {
|
||||||
|
if (!_forwarder || !_dns.isSet() || !_que) {
|
||||||
start = query;
|
return;
|
||||||
|
}
|
||||||
// If there's a leading 'www', skip it
|
DNSHeader *dnsHeader = (DNSHeader *)buffer;
|
||||||
if (*start == 3 && strncasecmp("www", (char *) start + 1, 3) == 0)
|
++_ids;
|
||||||
start += 4;
|
size_t i = _ids & (kDNSSQueSize - 1);
|
||||||
|
DEBUG_(({
|
||||||
while (*start != 0) {
|
if (0 != _que[i].ip) {
|
||||||
labelLength = *start;
|
++_que_ov;
|
||||||
start += 1;
|
|
||||||
while (labelLength > 0) {
|
|
||||||
if (tolower(*start) != *matchString) {
|
|
||||||
if (_forwarder) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
replyWithError(dnsHeader, _errorReplyCode, query, queryLength);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}));
|
||||||
++start;
|
_que[i].ip = _udp.remoteIP();
|
||||||
++matchString;
|
_que[i].port = _udp.remotePort();
|
||||||
--labelLength;
|
_que[i].id = dnsHeader->ID;
|
||||||
}
|
dnsHeader->ID = (uint16_t)_ids;
|
||||||
if (*start == 0 && *matchString == '\0') {
|
_udp.beginPacket(_dns, IANA_DNS_PORT);
|
||||||
replyWithIP(dnsHeader, query, queryLength);
|
_udp.write(buffer, length);
|
||||||
return false;
|
_udp.endPacket();
|
||||||
}
|
DEBUG_PRINTLN2("Forward request ID: 0x", (String(dnsHeader->ID, HEX) + F(" to ") + _dns.toString()));
|
||||||
|
|
||||||
if (*matchString != '.') {
|
|
||||||
replyWithError(dnsHeader, _errorReplyCode, query, queryLength);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
++matchString;
|
|
||||||
}
|
|
||||||
|
|
||||||
replyWithError(dnsHeader, _errorReplyCode, query, queryLength);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::processNextRequest()
|
bool DNSServer::respondToRequest(uint8_t *buffer, size_t length) {
|
||||||
{
|
DNSHeader *dnsHeader;
|
||||||
size_t currentPacketSize;
|
uint8_t *query, *start;
|
||||||
|
const char *matchString;
|
||||||
|
size_t remaining, labelLength, queryLength;
|
||||||
|
uint16_t qtype, qclass;
|
||||||
|
|
||||||
currentPacketSize = _udp.parsePacket();
|
dnsHeader = (DNSHeader *)buffer;
|
||||||
if (currentPacketSize == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// The DNS RFC requires that DNS packets be less than 512 bytes in size,
|
// Must be a query for us to do anything with it
|
||||||
// so just discard them if they are larger
|
if (dnsHeader->QR != DNS_QR_QUERY) {
|
||||||
if (currentPacketSize > MAX_DNS_PACKETSIZE)
|
return false;
|
||||||
return;
|
}
|
||||||
|
|
||||||
// If the packet size is smaller than the DNS header, then someone is
|
// If operation is anything other than query, we don't do it
|
||||||
// messing with us
|
if (dnsHeader->OPCode != DNS_OPCODE_QUERY) {
|
||||||
if (currentPacketSize < DNS_HEADER_SIZE)
|
replyWithError(dnsHeader, DNSReplyCode::NotImplemented);
|
||||||
return;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[currentPacketSize]);
|
// Only support requests containing single queries - everything else
|
||||||
if (buffer == nullptr)
|
// is badly defined
|
||||||
return;
|
if (dnsHeader->QDCount != lwip_htons(1)) {
|
||||||
|
replyWithError(dnsHeader, DNSReplyCode::FormError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
_udp.read(buffer.get(), currentPacketSize);
|
// We must return a FormError in the case of a non-zero ARCount to
|
||||||
if (_dns.isSet() && _udp.remoteIP() == _dns) {
|
// be minimally compatible with EDNS resolvers
|
||||||
// _forwarder may have been set to false; however, for now allow in-flight
|
if (dnsHeader->ANCount != 0 || dnsHeader->NSCount != 0
|
||||||
// replies to finish. //??
|
|| dnsHeader->ARCount != 0) {
|
||||||
forwardReply(buffer.get(), currentPacketSize);
|
replyWithError(dnsHeader, DNSReplyCode::FormError);
|
||||||
} else
|
return false;
|
||||||
if (respondToRequest(buffer.get(), currentPacketSize)) {
|
}
|
||||||
forwardRequest(buffer.get(), currentPacketSize);
|
|
||||||
}
|
// Even if we're not going to use the query, we need to parse it
|
||||||
|
// so we can check the address type that's being queried
|
||||||
|
|
||||||
|
query = start = buffer + DNS_HEADER_SIZE;
|
||||||
|
remaining = length - DNS_HEADER_SIZE;
|
||||||
|
while (remaining != 0 && *start != 0) {
|
||||||
|
labelLength = *start;
|
||||||
|
if (labelLength + 1 > remaining) {
|
||||||
|
replyWithError(dnsHeader, DNSReplyCode::FormError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
remaining -= (labelLength + 1);
|
||||||
|
start += (labelLength + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1 octet labelLength, 2 octet qtype, 2 octet qclass
|
||||||
|
if (remaining < 5) {
|
||||||
|
replyWithError(dnsHeader, DNSReplyCode::FormError);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
start += 1; // Skip the 0 length label that we found above
|
||||||
|
|
||||||
|
memcpy(&qtype, start, sizeof(qtype));
|
||||||
|
start += 2;
|
||||||
|
memcpy(&qclass, start, sizeof(qclass));
|
||||||
|
start += 2;
|
||||||
|
|
||||||
|
queryLength = start - query;
|
||||||
|
|
||||||
|
if (qclass != lwip_htons(DNS_QCLASS_ANY)
|
||||||
|
&& qclass != lwip_htons(DNS_QCLASS_IN)) {
|
||||||
|
replyWithError(dnsHeader, DNSReplyCode::NonExistentDomain, query, queryLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtype != lwip_htons(DNS_QTYPE_A)
|
||||||
|
&& qtype != lwip_htons(DNS_QTYPE_ANY)) {
|
||||||
|
replyWithError(dnsHeader, DNSReplyCode::NonExistentDomain, query, queryLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we have no domain name configured, just return an error
|
||||||
|
if (_domainName == "") {
|
||||||
|
if (_forwarder) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
replyWithError(dnsHeader, _errorReplyCode, query, queryLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're running with a wildcard we can just return a result now
|
||||||
|
if (_domainName == "*") {
|
||||||
|
DEBUG_PRINTF("dnsServer - replyWithIP\r\n");
|
||||||
|
replyWithIP(dnsHeader, query, queryLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
matchString = _domainName.c_str();
|
||||||
|
|
||||||
|
start = query;
|
||||||
|
|
||||||
|
// If there's a leading 'www', skip it
|
||||||
|
if (*start == 3 && strncasecmp("www", (char *) start + 1, 3) == 0) {
|
||||||
|
start += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*start != 0) {
|
||||||
|
labelLength = *start;
|
||||||
|
start += 1;
|
||||||
|
while (labelLength > 0) {
|
||||||
|
if (tolower(*start) != *matchString) {
|
||||||
|
if (_forwarder) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
replyWithError(dnsHeader, _errorReplyCode, query, queryLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++start;
|
||||||
|
++matchString;
|
||||||
|
--labelLength;
|
||||||
|
}
|
||||||
|
if (*start == 0 && *matchString == '\0') {
|
||||||
|
replyWithIP(dnsHeader, query, queryLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*matchString != '.') {
|
||||||
|
replyWithError(dnsHeader, _errorReplyCode, query, queryLength);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
++matchString;
|
||||||
|
}
|
||||||
|
|
||||||
|
replyWithError(dnsHeader, _errorReplyCode, query, queryLength);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::writeNBOShort(uint16_t value)
|
void DNSServer::processNextRequest() {
|
||||||
{
|
size_t currentPacketSize;
|
||||||
_udp.write((unsigned char *)&value, 2);
|
|
||||||
|
currentPacketSize = _udp.parsePacket();
|
||||||
|
if (currentPacketSize == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// The DNS RFC requires that DNS packets be less than 512 bytes in size,
|
||||||
|
// so just discard them if they are larger
|
||||||
|
if (currentPacketSize > MAX_DNS_PACKETSIZE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the packet size is smaller than the DNS header, then someone is
|
||||||
|
// messing with us
|
||||||
|
if (currentPacketSize < DNS_HEADER_SIZE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<uint8_t[]> buffer(new (std::nothrow) uint8_t[currentPacketSize]);
|
||||||
|
if (buffer == nullptr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_udp.read(buffer.get(), currentPacketSize);
|
||||||
|
if (_dns.isSet() && _udp.remoteIP() == _dns) {
|
||||||
|
// _forwarder may have been set to false; however, for now allow in-flight
|
||||||
|
// replies to finish. //??
|
||||||
|
forwardReply(buffer.get(), currentPacketSize);
|
||||||
|
} else if (respondToRequest(buffer.get(), currentPacketSize)) {
|
||||||
|
forwardRequest(buffer.get(), currentPacketSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DNSServer::writeNBOShort(uint16_t value) {
|
||||||
|
_udp.write((unsigned char *)&value, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::replyWithIP(DNSHeader *dnsHeader,
|
void DNSServer::replyWithIP(DNSHeader *dnsHeader,
|
||||||
unsigned char * query,
|
unsigned char * query,
|
||||||
size_t queryLength)
|
size_t queryLength) {
|
||||||
{
|
uint16_t value;
|
||||||
uint16_t value;
|
|
||||||
|
|
||||||
dnsHeader->QR = DNS_QR_RESPONSE;
|
dnsHeader->QR = DNS_QR_RESPONSE;
|
||||||
dnsHeader->QDCount = lwip_htons(1);
|
dnsHeader->QDCount = lwip_htons(1);
|
||||||
dnsHeader->ANCount = lwip_htons(1);
|
dnsHeader->ANCount = lwip_htons(1);
|
||||||
dnsHeader->NSCount = 0;
|
dnsHeader->NSCount = 0;
|
||||||
dnsHeader->ARCount = 0;
|
dnsHeader->ARCount = 0;
|
||||||
|
|
||||||
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
||||||
_udp.write((unsigned char *) dnsHeader, sizeof(DNSHeader));
|
_udp.write((unsigned char *) dnsHeader, sizeof(DNSHeader));
|
||||||
_udp.write(query, queryLength);
|
_udp.write(query, queryLength);
|
||||||
|
|
||||||
// Rather than restate the name here, we use a pointer to the name contained
|
// Rather than restate the name here, we use a pointer to the name contained
|
||||||
// in the query section. Pointers have the top two bits set.
|
// in the query section. Pointers have the top two bits set.
|
||||||
value = 0xC000 | DNS_HEADER_SIZE;
|
value = 0xC000 | DNS_HEADER_SIZE;
|
||||||
writeNBOShort(lwip_htons(value));
|
writeNBOShort(lwip_htons(value));
|
||||||
|
|
||||||
// Answer is type A (an IPv4 address)
|
// Answer is type A (an IPv4 address)
|
||||||
writeNBOShort(lwip_htons(DNS_QTYPE_A));
|
writeNBOShort(lwip_htons(DNS_QTYPE_A));
|
||||||
|
|
||||||
// Answer is in the Internet Class
|
// Answer is in the Internet Class
|
||||||
writeNBOShort(lwip_htons(DNS_QCLASS_IN));
|
writeNBOShort(lwip_htons(DNS_QCLASS_IN));
|
||||||
|
|
||||||
// Output TTL (already NBO)
|
// Output TTL (already NBO)
|
||||||
_udp.write((unsigned char*)&_ttl, 4);
|
_udp.write((unsigned char*)&_ttl, 4);
|
||||||
|
|
||||||
// Length of RData is 4 bytes (because, in this case, RData is IPv4)
|
// Length of RData is 4 bytes (because, in this case, RData is IPv4)
|
||||||
writeNBOShort(lwip_htons(sizeof(_resolvedIP)));
|
writeNBOShort(lwip_htons(sizeof(_resolvedIP)));
|
||||||
_udp.write(_resolvedIP, sizeof(_resolvedIP));
|
_udp.write(_resolvedIP, sizeof(_resolvedIP));
|
||||||
_udp.endPacket();
|
_udp.endPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::replyWithError(DNSHeader *dnsHeader,
|
void DNSServer::replyWithError(DNSHeader *dnsHeader,
|
||||||
DNSReplyCode rcode,
|
DNSReplyCode rcode,
|
||||||
unsigned char *query,
|
unsigned char *query,
|
||||||
size_t queryLength)
|
size_t queryLength) {
|
||||||
{
|
dnsHeader->QR = DNS_QR_RESPONSE;
|
||||||
dnsHeader->QR = DNS_QR_RESPONSE;
|
dnsHeader->RCode = (unsigned char) rcode;
|
||||||
dnsHeader->RCode = (unsigned char) rcode;
|
if (query) {
|
||||||
if (query)
|
dnsHeader->QDCount = lwip_htons(1);
|
||||||
dnsHeader->QDCount = lwip_htons(1);
|
} else {
|
||||||
else
|
dnsHeader->QDCount = 0;
|
||||||
dnsHeader->QDCount = 0;
|
}
|
||||||
dnsHeader->ANCount = 0;
|
dnsHeader->ANCount = 0;
|
||||||
dnsHeader->NSCount = 0;
|
dnsHeader->NSCount = 0;
|
||||||
dnsHeader->ARCount = 0;
|
dnsHeader->ARCount = 0;
|
||||||
|
|
||||||
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
_udp.beginPacket(_udp.remoteIP(), _udp.remotePort());
|
||||||
_udp.write((unsigned char *)dnsHeader, sizeof(DNSHeader));
|
_udp.write((unsigned char *)dnsHeader, sizeof(DNSHeader));
|
||||||
if (query != NULL)
|
if (query != NULL) {
|
||||||
_udp.write(query, queryLength);
|
_udp.write(query, queryLength);
|
||||||
_udp.endPacket();
|
}
|
||||||
|
_udp.endPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DNSServer::replyWithError(DNSHeader *dnsHeader,
|
void DNSServer::replyWithError(DNSHeader *dnsHeader,
|
||||||
DNSReplyCode rcode)
|
DNSReplyCode rcode) {
|
||||||
{
|
replyWithError(dnsHeader, rcode, NULL, 0);
|
||||||
replyWithError(dnsHeader, rcode, NULL, 0);
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,25 @@
|
||||||
#ifndef DNSServer_h
|
/*
|
||||||
#define DNSServer_h
|
DNSServer.cwhcpp - Simple DNS server for the Pico
|
||||||
|
Modified 2022 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
Taken from the ESP8266 core libraries, (c) various authors.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
|
|
@ -25,90 +45,97 @@ constexpr inline uint16_t kIanaDnsPort = IANA_DNS_PORT;
|
||||||
#define MAX_DNSNAME_LENGTH 253
|
#define MAX_DNSNAME_LENGTH 253
|
||||||
#define MAX_DNS_PACKETSIZE 512
|
#define MAX_DNS_PACKETSIZE 512
|
||||||
|
|
||||||
enum class DNSReplyCode
|
enum class DNSReplyCode {
|
||||||
{
|
NoError = 0,
|
||||||
NoError = 0,
|
FormError = 1,
|
||||||
FormError = 1,
|
ServerFailure = 2,
|
||||||
ServerFailure = 2,
|
NonExistentDomain = 3,
|
||||||
NonExistentDomain = 3,
|
NotImplemented = 4,
|
||||||
NotImplemented = 4,
|
Refused = 5,
|
||||||
Refused = 5,
|
YXDomain = 6,
|
||||||
YXDomain = 6,
|
YXRRSet = 7,
|
||||||
YXRRSet = 7,
|
NXRRSet = 8
|
||||||
NXRRSet = 8
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DNSHeader
|
struct DNSHeader {
|
||||||
{
|
uint16_t ID; // identification number
|
||||||
uint16_t ID; // identification number
|
unsigned char RD : 1; // recursion desired
|
||||||
unsigned char RD : 1; // recursion desired
|
unsigned char TC : 1; // truncated message
|
||||||
unsigned char TC : 1; // truncated message
|
unsigned char AA : 1; // authoritative answer
|
||||||
unsigned char AA : 1; // authoritative answer
|
unsigned char OPCode : 4; // message_type
|
||||||
unsigned char OPCode : 4; // message_type
|
unsigned char QR : 1; // query/response flag
|
||||||
unsigned char QR : 1; // query/response flag
|
unsigned char RCode : 4; // response code
|
||||||
unsigned char RCode : 4; // response code
|
unsigned char Z : 3; // its z! reserved
|
||||||
unsigned char Z : 3; // its z! reserved
|
unsigned char RA : 1; // recursion available
|
||||||
unsigned char RA : 1; // recursion available
|
uint16_t QDCount; // number of question entries
|
||||||
uint16_t QDCount; // number of question entries
|
uint16_t ANCount; // number of answer entries
|
||||||
uint16_t ANCount; // number of answer entries
|
uint16_t NSCount; // number of authority entries
|
||||||
uint16_t NSCount; // number of authority entries
|
uint16_t ARCount; // number of resource entries
|
||||||
uint16_t ARCount; // number of resource entries
|
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr inline size_t kDNSSQueSizeAddrBits = 3; // The number of bits used to address que entries
|
constexpr inline size_t kDNSSQueSizeAddrBits = 3; // The number of bits used to address que entries
|
||||||
constexpr inline size_t kDNSSQueSize = (1UL << (kDNSSQueSizeAddrBits));
|
constexpr inline size_t kDNSSQueSize = (1UL << (kDNSSQueSizeAddrBits));
|
||||||
|
|
||||||
struct DNSS_REQUESTER {
|
struct DNSS_REQUESTER {
|
||||||
uint32_t ip;
|
uint32_t ip;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
uint16_t id;
|
uint16_t id;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DNSServer
|
class DNSServer {
|
||||||
{
|
public:
|
||||||
public:
|
|
||||||
DNSServer();
|
DNSServer();
|
||||||
~DNSServer() {
|
~DNSServer() {
|
||||||
stop();
|
stop();
|
||||||
};
|
};
|
||||||
/*
|
/*
|
||||||
If specified, `enableForwarder` will update the `domainName` that is used
|
If specified, `enableForwarder` will update the `domainName` that is used
|
||||||
to match DNS request to this AP's IP Address. A non-matching request will
|
to match DNS request to this AP's IP Address. A non-matching request will
|
||||||
be forwarded to the DNS server specified by `dns`.
|
be forwarded to the DNS server specified by `dns`.
|
||||||
|
|
||||||
Returns `true` on success.
|
Returns `true` on success.
|
||||||
|
|
||||||
Returns `false`,
|
Returns `false`,
|
||||||
* when forwarding `dns` is not set, or
|
when forwarding `dns` is not set, or
|
||||||
* unable to allocate resources for managing the DNS forward function.
|
unable to allocate resources for managing the DNS forward function.
|
||||||
*/
|
*/
|
||||||
bool enableForwarder(const String &domainName = String(""), const IPAddress &dns = (uint32_t)0);
|
bool enableForwarder(const String &domainName = String(""), const IPAddress &dns = (uint32_t)0);
|
||||||
/*
|
/*
|
||||||
`disableForwarder` will stop forwarding DNS requests. If specified,
|
`disableForwarder` will stop forwarding DNS requests. If specified,
|
||||||
updates the `domainName` that is matched for returning this AP's IP Address.
|
updates the `domainName` that is matched for returning this AP's IP Address.
|
||||||
Optionally, resources used for the DNS forward function can be freed.
|
Optionally, resources used for the DNS forward function can be freed.
|
||||||
*/
|
*/
|
||||||
void disableForwarder(const String &domainName = String(""), bool freeResources = false);
|
void disableForwarder(const String &domainName = String(""), bool freeResources = false);
|
||||||
bool isForwarding() { return _forwarder && _dns.isSet(); }
|
bool isForwarding() {
|
||||||
void setDNS(const IPAddress& dns) { _dns = dns; }
|
return _forwarder && _dns.isSet();
|
||||||
IPAddress getDNS() { return _dns; }
|
}
|
||||||
bool isDNSSet() { return _dns.isSet(); }
|
void setDNS(const IPAddress& dns) {
|
||||||
|
_dns = dns;
|
||||||
|
}
|
||||||
|
IPAddress getDNS() {
|
||||||
|
return _dns;
|
||||||
|
}
|
||||||
|
bool isDNSSet() {
|
||||||
|
return _dns.isSet();
|
||||||
|
}
|
||||||
|
|
||||||
void processNextRequest();
|
void processNextRequest();
|
||||||
void setErrorReplyCode(const DNSReplyCode &replyCode);
|
void setErrorReplyCode(const DNSReplyCode &replyCode);
|
||||||
void setTTL(const uint32_t &ttl);
|
void setTTL(const uint32_t &ttl);
|
||||||
uint32_t getTTL();
|
uint32_t getTTL();
|
||||||
String getDomainName() { return _domainName; }
|
String getDomainName() {
|
||||||
|
return _domainName;
|
||||||
|
}
|
||||||
|
|
||||||
// Returns true if successful, false if there are no sockets available
|
// Returns true if successful, false if there are no sockets available
|
||||||
bool start(const uint16_t &port,
|
bool start(const uint16_t &port,
|
||||||
const String &domainName,
|
const String &domainName,
|
||||||
const IPAddress &resolvedIP,
|
const IPAddress &resolvedIP,
|
||||||
const IPAddress &dns = (uint32_t)0);
|
const IPAddress &dns = (uint32_t)0);
|
||||||
// stops the DNS server
|
// stops the DNS server
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WiFiUDP _udp;
|
WiFiUDP _udp;
|
||||||
String _domainName;
|
String _domainName;
|
||||||
IPAddress _dns;
|
IPAddress _dns;
|
||||||
|
|
@ -128,17 +155,16 @@ class DNSServer
|
||||||
|
|
||||||
void downcaseAndRemoveWwwPrefix(String &domainName);
|
void downcaseAndRemoveWwwPrefix(String &domainName);
|
||||||
void replyWithIP(DNSHeader *dnsHeader,
|
void replyWithIP(DNSHeader *dnsHeader,
|
||||||
unsigned char * query,
|
unsigned char * query,
|
||||||
size_t queryLength);
|
size_t queryLength);
|
||||||
void replyWithError(DNSHeader *dnsHeader,
|
void replyWithError(DNSHeader *dnsHeader,
|
||||||
DNSReplyCode rcode,
|
DNSReplyCode rcode,
|
||||||
unsigned char *query,
|
unsigned char *query,
|
||||||
size_t queryLength);
|
size_t queryLength);
|
||||||
void replyWithError(DNSHeader *dnsHeader,
|
void replyWithError(DNSHeader *dnsHeader,
|
||||||
DNSReplyCode rcode);
|
DNSReplyCode rcode);
|
||||||
bool respondToRequest(uint8_t *buffer, size_t length);
|
bool respondToRequest(uint8_t *buffer, size_t length);
|
||||||
void forwardRequest(uint8_t *buffer, size_t length);
|
void forwardRequest(uint8_t *buffer, size_t length);
|
||||||
void forwardReply(uint8_t *buffer, size_t length);
|
void forwardReply(uint8_t *buffer, size_t length);
|
||||||
void writeNBOShort(uint16_t value);
|
void writeNBOShort(uint16_t value);
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -19,8 +19,7 @@
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EEPROM_h
|
#pragma once
|
||||||
#define EEPROM_h
|
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
@ -85,6 +84,3 @@ protected:
|
||||||
};
|
};
|
||||||
|
|
||||||
extern EEPROMClass EEPROM;
|
extern EEPROMClass EEPROM;
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
@ -1,3 +1,24 @@
|
||||||
|
/*
|
||||||
|
HTTPUpdateServer - Support simple web based OTA
|
||||||
|
Modified 2022 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
Ported from the ESP8266 Arduino core, (c) copyright multiple authors
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,24 @@
|
||||||
|
/*
|
||||||
|
HTTPUpdateServer - Support simple web based OTA
|
||||||
|
Modified 2022 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
Ported from the ESP8266 Arduino core, (c) copyright multiple authors
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <WebServer.h>
|
#include <WebServer.h>
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,7 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MDNS_PRIV_H
|
#pragma once
|
||||||
#define MDNS_PRIV_H
|
|
||||||
|
|
||||||
namespace esp8266 {
|
namespace esp8266 {
|
||||||
|
|
||||||
|
|
@ -186,5 +185,3 @@ namespace MDNSImplementation {
|
||||||
|
|
||||||
// Include the main header, so the submodlues only need to include this header
|
// Include the main header, so the submodlues only need to include this header
|
||||||
#include "LEAmDNS.h"
|
#include "LEAmDNS.h"
|
||||||
|
|
||||||
#endif // MDNS_PRIV_H
|
|
||||||
|
|
|
||||||
|
|
@ -22,9 +22,6 @@
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MDNS_LWIPDEFS_H
|
#pragma once
|
||||||
#define MDNS_LWIPDEFS_H
|
|
||||||
|
|
||||||
#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT
|
#include <lwip/prot/dns.h> // DNS_RRTYPE_xxx, DNS_MQUERY_PORT
|
||||||
|
|
||||||
#endif // MDNS_LWIPDEFS_H
|
|
||||||
|
|
|
||||||
|
|
@ -23,9 +23,7 @@
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef __LITTLEFS_H
|
|
||||||
#define __LITTLEFS_H
|
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
|
|
@ -681,6 +679,3 @@ protected:
|
||||||
extern FS LittleFS;
|
extern FS LittleFS;
|
||||||
using littlefs_impl::LittleFSConfig;
|
using littlefs_impl::LittleFSConfig;
|
||||||
#endif // ARDUINO
|
#endif // ARDUINO
|
||||||
|
|
||||||
|
|
||||||
#endif // !defined(__LITTLEFS_H)
|
|
||||||
|
|
|
||||||
|
|
@ -52,7 +52,7 @@ void loop() {
|
||||||
|
|
||||||
// Print samples to the serial monitor or plotter
|
// Print samples to the serial monitor or plotter
|
||||||
for (int i = 0; i < samplesRead; i++) {
|
for (int i = 0; i < samplesRead; i++) {
|
||||||
if(channels == 2) {
|
if (channels == 2) {
|
||||||
Serial.print("L:");
|
Serial.print("L:");
|
||||||
Serial.print(sampleBuffer[i]);
|
Serial.print(sampleBuffer[i]);
|
||||||
Serial.print(" R:");
|
Serial.print(" R:");
|
||||||
|
|
@ -67,9 +67,9 @@ void loop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Callback function to process the data from the PDM microphone.
|
Callback function to process the data from the PDM microphone.
|
||||||
* NOTE: This callback is executed as part of an ISR.
|
NOTE: This callback is executed as part of an ISR.
|
||||||
* Therefore using `Serial` to print messages inside this function isn't supported.
|
Therefore using `Serial` to print messages inside this function isn't supported.
|
||||||
* */
|
* */
|
||||||
void onPDMdata() {
|
void onPDMdata() {
|
||||||
// Query the number of available bytes
|
// Query the number of available bytes
|
||||||
|
|
|
||||||
|
|
@ -1,74 +1,72 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2019 Arduino LLC. All right reserved.
|
Copyright (c) 2019 Arduino LLC. All right reserved.
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
See the GNU Lesser General Public License for more details.
|
See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _PDM_H_INCLUDED
|
#pragma once
|
||||||
#define _PDM_H_INCLUDED
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
//#include <pinDefinitions.h>
|
//#include <pinDefinitions.h>
|
||||||
|
|
||||||
#include "utility/PDMDoubleBuffer.h"
|
#include "utility/PDMDoubleBuffer.h"
|
||||||
|
|
||||||
class PDMClass
|
class PDMClass {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
PDMClass(int dinPin, int clkPin, int pwrPin);
|
PDMClass(int dinPin, int clkPin, int pwrPin);
|
||||||
virtual ~PDMClass();
|
virtual ~PDMClass();
|
||||||
|
|
||||||
int begin(int channels, int sampleRate);
|
int begin(int channels, int sampleRate);
|
||||||
void end();
|
void end();
|
||||||
|
|
||||||
virtual int available();
|
virtual int available();
|
||||||
virtual int read(void* buffer, size_t size);
|
virtual int read(void* buffer, size_t size);
|
||||||
|
|
||||||
void onReceive(void(*)(void));
|
void onReceive(void(*)(void));
|
||||||
|
|
||||||
//PORTENTA_H7 min -12 max 51
|
//PORTENTA_H7 min -12 max 51
|
||||||
//NANO 33 BLE SENSe min 0 max 80
|
//NANO 33 BLE SENSe min 0 max 80
|
||||||
void setGain(int gain);
|
void setGain(int gain);
|
||||||
void setBufferSize(int bufferSize);
|
void setBufferSize(int bufferSize);
|
||||||
size_t getBufferSize();
|
size_t getBufferSize();
|
||||||
|
|
||||||
// private:
|
// private:
|
||||||
void IrqHandler(bool halftranfer);
|
void IrqHandler(bool halftranfer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _dinPin;
|
int _dinPin;
|
||||||
int _clkPin;
|
int _clkPin;
|
||||||
int _pwrPin;
|
int _pwrPin;
|
||||||
|
|
||||||
int _channels;
|
int _channels;
|
||||||
int _samplerate;
|
int _samplerate;
|
||||||
|
|
||||||
int _gain;
|
int _gain;
|
||||||
int _init;
|
int _init;
|
||||||
|
|
||||||
// Hardware peripherals used
|
// Hardware peripherals used
|
||||||
uint _dmaChannel;
|
uint _dmaChannel;
|
||||||
PIO _pio;
|
PIO _pio;
|
||||||
int _smIdx;
|
int _smIdx;
|
||||||
int _pgmOffset;
|
int _pgmOffset;
|
||||||
|
|
||||||
PDMDoubleBuffer _doubleBuffer;
|
PDMDoubleBuffer _doubleBuffer;
|
||||||
|
|
||||||
void (*_onReceive)(void);
|
void (*_onReceive)(void);
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef PIN_PDM_DIN
|
#ifdef PIN_PDM_DIN
|
||||||
extern PDMClass PDM;
|
extern PDMClass PDM;
|
||||||
#endif
|
#endif
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,30 @@
|
||||||
/**
|
/**
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* @file OpenPDMFilter.c
|
@file OpenPDMFilter.c
|
||||||
* @author CL
|
@author CL
|
||||||
* @version V1.0.0
|
@version V1.0.0
|
||||||
* @date 9-September-2015
|
@date 9-September-2015
|
||||||
* @brief Open PDM audio software decoding Library.
|
@brief Open PDM audio software decoding Library.
|
||||||
* This Library is used to decode and reconstruct the audio signal
|
This Library is used to decode and reconstruct the audio signal
|
||||||
* produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx).
|
produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx).
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* @attention
|
@attention
|
||||||
*
|
|
||||||
* <h2><center>© COPYRIGHT 2018 STMicroelectronics</center></h2>
|
<h2><center>© COPYRIGHT 2018 STMicroelectronics</center></h2>
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
limitations under the License.
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Includes ------------------------------------------------------------------*/
|
/* Includes ------------------------------------------------------------------*/
|
||||||
|
|
@ -48,266 +48,255 @@ int32_t lut[256][DECIMATION_MAX / 8][SINCN];
|
||||||
/* Functions -----------------------------------------------------------------*/
|
/* Functions -----------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifdef USE_LUT
|
#ifdef USE_LUT
|
||||||
int32_t filter_table_mono_64(uint8_t *data, uint8_t sincn)
|
int32_t filter_table_mono_64(uint8_t *data, uint8_t sincn) {
|
||||||
{
|
return (int32_t)
|
||||||
return (int32_t)
|
lut[data[0]][0][sincn] +
|
||||||
lut[data[0]][0][sincn] +
|
lut[data[1]][1][sincn] +
|
||||||
lut[data[1]][1][sincn] +
|
lut[data[2]][2][sincn] +
|
||||||
lut[data[2]][2][sincn] +
|
lut[data[3]][3][sincn] +
|
||||||
lut[data[3]][3][sincn] +
|
lut[data[4]][4][sincn] +
|
||||||
lut[data[4]][4][sincn] +
|
lut[data[5]][5][sincn] +
|
||||||
lut[data[5]][5][sincn] +
|
lut[data[6]][6][sincn] +
|
||||||
lut[data[6]][6][sincn] +
|
lut[data[7]][7][sincn];
|
||||||
lut[data[7]][7][sincn];
|
|
||||||
}
|
}
|
||||||
int32_t filter_table_stereo_64(uint8_t *data, uint8_t sincn)
|
int32_t filter_table_stereo_64(uint8_t *data, uint8_t sincn) {
|
||||||
{
|
return (int32_t)
|
||||||
return (int32_t)
|
lut[data[0]][0][sincn] +
|
||||||
lut[data[0]][0][sincn] +
|
lut[data[2]][1][sincn] +
|
||||||
lut[data[2]][1][sincn] +
|
lut[data[4]][2][sincn] +
|
||||||
lut[data[4]][2][sincn] +
|
lut[data[6]][3][sincn] +
|
||||||
lut[data[6]][3][sincn] +
|
lut[data[8]][4][sincn] +
|
||||||
lut[data[8]][4][sincn] +
|
lut[data[10]][5][sincn] +
|
||||||
lut[data[10]][5][sincn] +
|
lut[data[12]][6][sincn] +
|
||||||
lut[data[12]][6][sincn] +
|
lut[data[14]][7][sincn];
|
||||||
lut[data[14]][7][sincn];
|
|
||||||
}
|
}
|
||||||
int32_t filter_table_mono_128(uint8_t *data, uint8_t sincn)
|
int32_t filter_table_mono_128(uint8_t *data, uint8_t sincn) {
|
||||||
{
|
return (int32_t)
|
||||||
return (int32_t)
|
lut[data[0]][0][sincn] +
|
||||||
lut[data[0]][0][sincn] +
|
lut[data[1]][1][sincn] +
|
||||||
lut[data[1]][1][sincn] +
|
lut[data[2]][2][sincn] +
|
||||||
lut[data[2]][2][sincn] +
|
lut[data[3]][3][sincn] +
|
||||||
lut[data[3]][3][sincn] +
|
lut[data[4]][4][sincn] +
|
||||||
lut[data[4]][4][sincn] +
|
lut[data[5]][5][sincn] +
|
||||||
lut[data[5]][5][sincn] +
|
lut[data[6]][6][sincn] +
|
||||||
lut[data[6]][6][sincn] +
|
lut[data[7]][7][sincn] +
|
||||||
lut[data[7]][7][sincn] +
|
lut[data[8]][8][sincn] +
|
||||||
lut[data[8]][8][sincn] +
|
lut[data[9]][9][sincn] +
|
||||||
lut[data[9]][9][sincn] +
|
lut[data[10]][10][sincn] +
|
||||||
lut[data[10]][10][sincn] +
|
lut[data[11]][11][sincn] +
|
||||||
lut[data[11]][11][sincn] +
|
lut[data[12]][12][sincn] +
|
||||||
lut[data[12]][12][sincn] +
|
lut[data[13]][13][sincn] +
|
||||||
lut[data[13]][13][sincn] +
|
lut[data[14]][14][sincn] +
|
||||||
lut[data[14]][14][sincn] +
|
lut[data[15]][15][sincn];
|
||||||
lut[data[15]][15][sincn];
|
|
||||||
}
|
}
|
||||||
int32_t filter_table_stereo_128(uint8_t *data, uint8_t sincn)
|
int32_t filter_table_stereo_128(uint8_t *data, uint8_t sincn) {
|
||||||
{
|
return (int32_t)
|
||||||
return (int32_t)
|
lut[data[0]][0][sincn] +
|
||||||
lut[data[0]][0][sincn] +
|
lut[data[2]][1][sincn] +
|
||||||
lut[data[2]][1][sincn] +
|
lut[data[4]][2][sincn] +
|
||||||
lut[data[4]][2][sincn] +
|
lut[data[6]][3][sincn] +
|
||||||
lut[data[6]][3][sincn] +
|
lut[data[8]][4][sincn] +
|
||||||
lut[data[8]][4][sincn] +
|
lut[data[10]][5][sincn] +
|
||||||
lut[data[10]][5][sincn] +
|
lut[data[12]][6][sincn] +
|
||||||
lut[data[12]][6][sincn] +
|
lut[data[14]][7][sincn] +
|
||||||
lut[data[14]][7][sincn] +
|
lut[data[16]][8][sincn] +
|
||||||
lut[data[16]][8][sincn] +
|
lut[data[18]][9][sincn] +
|
||||||
lut[data[18]][9][sincn] +
|
lut[data[20]][10][sincn] +
|
||||||
lut[data[20]][10][sincn] +
|
lut[data[22]][11][sincn] +
|
||||||
lut[data[22]][11][sincn] +
|
lut[data[24]][12][sincn] +
|
||||||
lut[data[24]][12][sincn] +
|
lut[data[26]][13][sincn] +
|
||||||
lut[data[26]][13][sincn] +
|
lut[data[28]][14][sincn] +
|
||||||
lut[data[28]][14][sincn] +
|
lut[data[30]][15][sincn];
|
||||||
lut[data[30]][15][sincn];
|
|
||||||
}
|
}
|
||||||
int32_t (* filter_tables_64[2]) (uint8_t *data, uint8_t sincn) = {filter_table_mono_64, filter_table_stereo_64};
|
int32_t (* filter_tables_64[2])(uint8_t *data, uint8_t sincn) = {filter_table_mono_64, filter_table_stereo_64};
|
||||||
int32_t (* filter_tables_128[2]) (uint8_t *data, uint8_t sincn) = {filter_table_mono_128, filter_table_stereo_128};
|
int32_t (* filter_tables_128[2])(uint8_t *data, uint8_t sincn) = {filter_table_mono_128, filter_table_stereo_128};
|
||||||
#else
|
#else
|
||||||
int32_t filter_table(uint8_t *data, uint8_t sincn, TPDMFilter_InitStruct *param)
|
int32_t filter_table(uint8_t *data, uint8_t sincn, TPDMFilter_InitStruct *param) {
|
||||||
{
|
uint8_t c, i;
|
||||||
uint8_t c, i;
|
uint16_t data_index = 0;
|
||||||
uint16_t data_index = 0;
|
uint32_t *coef_p = &coef[sincn][0];
|
||||||
uint32_t *coef_p = &coef[sincn][0];
|
int32_t F = 0;
|
||||||
int32_t F = 0;
|
uint8_t decimation = param->Decimation;
|
||||||
uint8_t decimation = param->Decimation;
|
uint8_t channels = param->In_MicChannels;
|
||||||
uint8_t channels = param->In_MicChannels;
|
|
||||||
|
|
||||||
for (i = 0; i < decimation; i += 8) {
|
for (i = 0; i < decimation; i += 8) {
|
||||||
c = data[data_index];
|
c = data[data_index];
|
||||||
F += ((c >> 7) ) * coef_p[i ] +
|
F += ((c >> 7)) * coef_p[i ] +
|
||||||
((c >> 6) & 0x01) * coef_p[i + 1] +
|
((c >> 6) & 0x01) * coef_p[i + 1] +
|
||||||
((c >> 5) & 0x01) * coef_p[i + 2] +
|
((c >> 5) & 0x01) * coef_p[i + 2] +
|
||||||
((c >> 4) & 0x01) * coef_p[i + 3] +
|
((c >> 4) & 0x01) * coef_p[i + 3] +
|
||||||
((c >> 3) & 0x01) * coef_p[i + 4] +
|
((c >> 3) & 0x01) * coef_p[i + 4] +
|
||||||
((c >> 2) & 0x01) * coef_p[i + 5] +
|
((c >> 2) & 0x01) * coef_p[i + 5] +
|
||||||
((c >> 1) & 0x01) * coef_p[i + 6] +
|
((c >> 1) & 0x01) * coef_p[i + 6] +
|
||||||
((c ) & 0x01) * coef_p[i + 7];
|
((c) & 0x01) * coef_p[i + 7];
|
||||||
data_index += channels;
|
data_index += channels;
|
||||||
}
|
}
|
||||||
return F;
|
return F;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void convolve(uint32_t Signal[/* SignalLen */], unsigned short SignalLen,
|
void convolve(uint32_t Signal[/* SignalLen */], unsigned short SignalLen,
|
||||||
uint32_t Kernel[/* KernelLen */], unsigned short KernelLen,
|
uint32_t Kernel[/* KernelLen */], unsigned short KernelLen,
|
||||||
uint32_t Result[/* SignalLen + KernelLen - 1 */])
|
uint32_t Result[/* SignalLen + KernelLen - 1 */]) {
|
||||||
{
|
uint16_t n;
|
||||||
uint16_t n;
|
|
||||||
|
|
||||||
for (n = 0; n < SignalLen + KernelLen - 1; n++)
|
for (n = 0; n < SignalLen + KernelLen - 1; n++) {
|
||||||
{
|
unsigned short kmin, kmax, k;
|
||||||
unsigned short kmin, kmax, k;
|
|
||||||
|
|
||||||
Result[n] = 0;
|
Result[n] = 0;
|
||||||
|
|
||||||
kmin = (n >= KernelLen - 1) ? n - (KernelLen - 1) : 0;
|
kmin = (n >= KernelLen - 1) ? n - (KernelLen - 1) : 0;
|
||||||
kmax = (n < SignalLen - 1) ? n : SignalLen - 1;
|
kmax = (n < SignalLen - 1) ? n : SignalLen - 1;
|
||||||
|
|
||||||
for (k = kmin; k <= kmax; k++) {
|
for (k = kmin; k <= kmax; k++) {
|
||||||
Result[n] += Signal[k] * Kernel[n - k];
|
Result[n] += Signal[k] * Kernel[n - k];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Open_PDM_Filter_Init(TPDMFilter_InitStruct *Param)
|
void Open_PDM_Filter_Init(TPDMFilter_InitStruct *Param) {
|
||||||
{
|
uint16_t i, j;
|
||||||
uint16_t i, j;
|
int64_t sum = 0;
|
||||||
int64_t sum = 0;
|
|
||||||
|
|
||||||
uint8_t decimation = Param->Decimation;
|
uint8_t decimation = Param->Decimation;
|
||||||
|
|
||||||
for (i = 0; i < SINCN; i++) {
|
for (i = 0; i < SINCN; i++) {
|
||||||
Param->Coef[i] = 0;
|
Param->Coef[i] = 0;
|
||||||
Param->bit[i] = 0;
|
Param->bit[i] = 0;
|
||||||
}
|
}
|
||||||
for (i = 0; i < decimation; i++) {
|
|
||||||
sinc1[i] = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Param->OldOut = Param->OldIn = Param->OldZ = 0;
|
|
||||||
Param->LP_ALFA = (Param->LP_HZ != 0 ? (uint16_t) (Param->LP_HZ * 256 / (Param->LP_HZ + Param->Fs / (2 * 3.14159))) : 0);
|
|
||||||
Param->HP_ALFA = (Param->HP_HZ != 0 ? (uint16_t) (Param->Fs * 256 / (2 * 3.14159 * Param->HP_HZ + Param->Fs)) : 0);
|
|
||||||
|
|
||||||
Param->FilterLen = decimation * SINCN;
|
|
||||||
sinc[0] = 0;
|
|
||||||
sinc[decimation * SINCN - 1] = 0;
|
|
||||||
convolve(sinc1, decimation, sinc1, decimation, sinc2);
|
|
||||||
convolve(sinc2, decimation * 2 - 1, sinc1, decimation, &sinc[1]);
|
|
||||||
for(j = 0; j < SINCN; j++) {
|
|
||||||
for (i = 0; i < decimation; i++) {
|
for (i = 0; i < decimation; i++) {
|
||||||
coef[j][i] = sinc[j * decimation + i];
|
sinc1[i] = 1;
|
||||||
sum += sinc[j * decimation + i];
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sub_const = sum >> 1;
|
Param->OldOut = Param->OldIn = Param->OldZ = 0;
|
||||||
div_const = sub_const * Param->MaxVolume / 32768 / Param->filterGain;
|
Param->LP_ALFA = (Param->LP_HZ != 0 ? (uint16_t)(Param->LP_HZ * 256 / (Param->LP_HZ + Param->Fs / (2 * 3.14159))) : 0);
|
||||||
div_const = (div_const == 0 ? 1 : div_const);
|
Param->HP_ALFA = (Param->HP_HZ != 0 ? (uint16_t)(Param->Fs * 256 / (2 * 3.14159 * Param->HP_HZ + Param->Fs)) : 0);
|
||||||
|
|
||||||
|
Param->FilterLen = decimation * SINCN;
|
||||||
|
sinc[0] = 0;
|
||||||
|
sinc[decimation * SINCN - 1] = 0;
|
||||||
|
convolve(sinc1, decimation, sinc1, decimation, sinc2);
|
||||||
|
convolve(sinc2, decimation * 2 - 1, sinc1, decimation, &sinc[1]);
|
||||||
|
for (j = 0; j < SINCN; j++) {
|
||||||
|
for (i = 0; i < decimation; i++) {
|
||||||
|
coef[j][i] = sinc[j * decimation + i];
|
||||||
|
sum += sinc[j * decimation + i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sub_const = sum >> 1;
|
||||||
|
div_const = sub_const * Param->MaxVolume / 32768 / Param->filterGain;
|
||||||
|
div_const = (div_const == 0 ? 1 : div_const);
|
||||||
|
|
||||||
#ifdef USE_LUT
|
#ifdef USE_LUT
|
||||||
/* Look-Up Table. */
|
/* Look-Up Table. */
|
||||||
uint16_t c, d, s;
|
uint16_t c, d, s;
|
||||||
for (s = 0; s < SINCN; s++)
|
for (s = 0; s < SINCN; s++) {
|
||||||
{
|
uint32_t *coef_p = &coef[s][0];
|
||||||
uint32_t *coef_p = &coef[s][0];
|
for (c = 0; c < 256; c++)
|
||||||
for (c = 0; c < 256; c++)
|
for (d = 0; d < decimation / 8; d++)
|
||||||
for (d = 0; d < decimation / 8; d++)
|
lut[c][d][s] = ((c >> 7)) * coef_p[d * 8 ] +
|
||||||
lut[c][d][s] = ((c >> 7) ) * coef_p[d * 8 ] +
|
((c >> 6) & 0x01) * coef_p[d * 8 + 1] +
|
||||||
((c >> 6) & 0x01) * coef_p[d * 8 + 1] +
|
((c >> 5) & 0x01) * coef_p[d * 8 + 2] +
|
||||||
((c >> 5) & 0x01) * coef_p[d * 8 + 2] +
|
((c >> 4) & 0x01) * coef_p[d * 8 + 3] +
|
||||||
((c >> 4) & 0x01) * coef_p[d * 8 + 3] +
|
((c >> 3) & 0x01) * coef_p[d * 8 + 4] +
|
||||||
((c >> 3) & 0x01) * coef_p[d * 8 + 4] +
|
((c >> 2) & 0x01) * coef_p[d * 8 + 5] +
|
||||||
((c >> 2) & 0x01) * coef_p[d * 8 + 5] +
|
((c >> 1) & 0x01) * coef_p[d * 8 + 6] +
|
||||||
((c >> 1) & 0x01) * coef_p[d * 8 + 6] +
|
((c) & 0x01) * coef_p[d * 8 + 7];
|
||||||
((c ) & 0x01) * coef_p[d * 8 + 7];
|
}
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Open_PDM_Filter_64(uint8_t* data, int16_t* dataOut, uint16_t volume, TPDMFilter_InitStruct *Param)
|
void Open_PDM_Filter_64(uint8_t* data, int16_t* dataOut, uint16_t volume, TPDMFilter_InitStruct *Param) {
|
||||||
{
|
uint8_t i, data_out_index;
|
||||||
uint8_t i, data_out_index;
|
uint8_t channels = Param->In_MicChannels;
|
||||||
uint8_t channels = Param->In_MicChannels;
|
uint8_t data_inc = ((DECIMATION_MAX >> 4) * channels);
|
||||||
uint8_t data_inc = ((DECIMATION_MAX >> 4) * channels);
|
int64_t Z, Z0, Z1, Z2;
|
||||||
int64_t Z, Z0, Z1, Z2;
|
int64_t OldOut, OldIn, OldZ;
|
||||||
int64_t OldOut, OldIn, OldZ;
|
|
||||||
|
|
||||||
OldOut = Param->OldOut;
|
OldOut = Param->OldOut;
|
||||||
OldIn = Param->OldIn;
|
OldIn = Param->OldIn;
|
||||||
OldZ = Param->OldZ;
|
OldZ = Param->OldZ;
|
||||||
|
|
||||||
#ifdef USE_LUT
|
#ifdef USE_LUT
|
||||||
uint8_t j = channels - 1;
|
uint8_t j = channels - 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) {
|
for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) {
|
||||||
#ifdef USE_LUT
|
#ifdef USE_LUT
|
||||||
Z0 = filter_tables_64[j](data, 0);
|
Z0 = filter_tables_64[j](data, 0);
|
||||||
Z1 = filter_tables_64[j](data, 1);
|
Z1 = filter_tables_64[j](data, 1);
|
||||||
Z2 = filter_tables_64[j](data, 2);
|
Z2 = filter_tables_64[j](data, 2);
|
||||||
#else
|
#else
|
||||||
Z0 = filter_table(data, 0, Param);
|
Z0 = filter_table(data, 0, Param);
|
||||||
Z1 = filter_table(data, 1, Param);
|
Z1 = filter_table(data, 1, Param);
|
||||||
Z2 = filter_table(data, 2, Param);
|
Z2 = filter_table(data, 2, Param);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Z = Param->Coef[1] + Z2 - sub_const;
|
Z = Param->Coef[1] + Z2 - sub_const;
|
||||||
Param->Coef[1] = Param->Coef[0] + Z1;
|
Param->Coef[1] = Param->Coef[0] + Z1;
|
||||||
Param->Coef[0] = Z0;
|
Param->Coef[0] = Z0;
|
||||||
|
|
||||||
OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8;
|
OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8;
|
||||||
OldIn = Z;
|
OldIn = Z;
|
||||||
OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8;
|
OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8;
|
||||||
|
|
||||||
Z = OldZ * volume;
|
Z = OldZ * volume;
|
||||||
Z = RoundDiv(Z, div_const);
|
Z = RoundDiv(Z, div_const);
|
||||||
Z = SaturaLH(Z, -32700, 32700);
|
Z = SaturaLH(Z, -32700, 32700);
|
||||||
|
|
||||||
dataOut[data_out_index] = Z;
|
dataOut[data_out_index] = Z;
|
||||||
data += data_inc;
|
data += data_inc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Param->OldOut = OldOut;
|
Param->OldOut = OldOut;
|
||||||
Param->OldIn = OldIn;
|
Param->OldIn = OldIn;
|
||||||
Param->OldZ = OldZ;
|
Param->OldZ = OldZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Open_PDM_Filter_128(uint8_t* data, int16_t* dataOut, uint16_t volume, TPDMFilter_InitStruct *Param)
|
void Open_PDM_Filter_128(uint8_t* data, int16_t* dataOut, uint16_t volume, TPDMFilter_InitStruct *Param) {
|
||||||
{
|
uint8_t i, data_out_index;
|
||||||
uint8_t i, data_out_index;
|
uint8_t channels = Param->In_MicChannels;
|
||||||
uint8_t channels = Param->In_MicChannels;
|
uint8_t data_inc = ((DECIMATION_MAX >> 3) * channels);
|
||||||
uint8_t data_inc = ((DECIMATION_MAX >> 3) * channels);
|
int64_t Z, Z0, Z1, Z2;
|
||||||
int64_t Z, Z0, Z1, Z2;
|
int64_t OldOut, OldIn, OldZ;
|
||||||
int64_t OldOut, OldIn, OldZ;
|
|
||||||
|
|
||||||
OldOut = Param->OldOut;
|
OldOut = Param->OldOut;
|
||||||
OldIn = Param->OldIn;
|
OldIn = Param->OldIn;
|
||||||
OldZ = Param->OldZ;
|
OldZ = Param->OldZ;
|
||||||
|
|
||||||
#ifdef USE_LUT
|
#ifdef USE_LUT
|
||||||
uint8_t j = channels - 1;
|
uint8_t j = channels - 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) {
|
for (i = 0, data_out_index = 0; i < Param->nSamples; i++, data_out_index += channels) {
|
||||||
#ifdef USE_LUT
|
#ifdef USE_LUT
|
||||||
Z0 = filter_tables_128[j](data, 0);
|
Z0 = filter_tables_128[j](data, 0);
|
||||||
Z1 = filter_tables_128[j](data, 1);
|
Z1 = filter_tables_128[j](data, 1);
|
||||||
Z2 = filter_tables_128[j](data, 2);
|
Z2 = filter_tables_128[j](data, 2);
|
||||||
#else
|
#else
|
||||||
Z0 = filter_table(data, 0, Param);
|
Z0 = filter_table(data, 0, Param);
|
||||||
Z1 = filter_table(data, 1, Param);
|
Z1 = filter_table(data, 1, Param);
|
||||||
Z2 = filter_table(data, 2, Param);
|
Z2 = filter_table(data, 2, Param);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Z = Param->Coef[1] + Z2 - sub_const;
|
Z = Param->Coef[1] + Z2 - sub_const;
|
||||||
Param->Coef[1] = Param->Coef[0] + Z1;
|
Param->Coef[1] = Param->Coef[0] + Z1;
|
||||||
Param->Coef[0] = Z0;
|
Param->Coef[0] = Z0;
|
||||||
|
|
||||||
OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8;
|
OldOut = (Param->HP_ALFA * (OldOut + Z - OldIn)) >> 8;
|
||||||
OldIn = Z;
|
OldIn = Z;
|
||||||
OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8;
|
OldZ = ((256 - Param->LP_ALFA) * OldZ + Param->LP_ALFA * OldOut) >> 8;
|
||||||
|
|
||||||
Z = OldZ * volume;
|
Z = OldZ * volume;
|
||||||
Z = RoundDiv(Z, div_const);
|
Z = RoundDiv(Z, div_const);
|
||||||
Z = SaturaLH(Z, -32700, 32700);
|
Z = SaturaLH(Z, -32700, 32700);
|
||||||
|
|
||||||
dataOut[data_out_index] = Z;
|
dataOut[data_out_index] = Z;
|
||||||
data += data_inc;
|
data += data_inc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Param->OldOut = OldOut;
|
Param->OldOut = OldOut;
|
||||||
Param->OldIn = OldIn;
|
Param->OldIn = OldIn;
|
||||||
Param->OldZ = OldZ;
|
Param->OldZ = OldZ;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,30 @@
|
||||||
/**
|
/**
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* @file OpenPDMFilter.h
|
@file OpenPDMFilter.h
|
||||||
* @author CL
|
@author CL
|
||||||
* @version V1.0.0
|
@version V1.0.0
|
||||||
* @date 9-September-2015
|
@date 9-September-2015
|
||||||
* @brief Header file for Open PDM audio software decoding Library.
|
@brief Header file for Open PDM audio software decoding Library.
|
||||||
* This Library is used to decode and reconstruct the audio signal
|
This Library is used to decode and reconstruct the audio signal
|
||||||
* produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx).
|
produced by ST MEMS microphone (MP45Dxxx, MP34Dxxx).
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
* @attention
|
@attention
|
||||||
*
|
|
||||||
* <h2><center>© COPYRIGHT 2018 STMicroelectronics</center></h2>
|
<h2><center>© COPYRIGHT 2018 STMicroelectronics</center></h2>
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
You may obtain a copy of the License at
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
limitations under the License.
|
||||||
*******************************************************************************
|
*******************************************************************************
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Define to prevent recursive inclusion -------------------------------------*/
|
/* Define to prevent recursive inclusion -------------------------------------*/
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
#define __OPENPDMFILTER_H
|
#define __OPENPDMFILTER_H
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -45,10 +45,10 @@
|
||||||
/* Definitions ---------------------------------------------------------------*/
|
/* Definitions ---------------------------------------------------------------*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Enable to use a Look-Up Table to improve performances while using more FLASH
|
Enable to use a Look-Up Table to improve performances while using more FLASH
|
||||||
* and RAM memory.
|
and RAM memory.
|
||||||
* Note: Without Look-Up Table up to stereo@16KHz configuration is supported.
|
Note: Without Look-Up Table up to stereo@16KHz configuration is supported.
|
||||||
*/
|
*/
|
||||||
#define USE_LUT
|
#define USE_LUT
|
||||||
|
|
||||||
#define SINCN 3
|
#define SINCN 3
|
||||||
|
|
@ -63,24 +63,24 @@
|
||||||
/* Types ---------------------------------------------------------------------*/
|
/* Types ---------------------------------------------------------------------*/
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/* Public */
|
/* Public */
|
||||||
float LP_HZ;
|
float LP_HZ;
|
||||||
float HP_HZ;
|
float HP_HZ;
|
||||||
uint16_t Fs;
|
uint16_t Fs;
|
||||||
unsigned int nSamples;
|
unsigned int nSamples;
|
||||||
uint8_t In_MicChannels;
|
uint8_t In_MicChannels;
|
||||||
uint8_t Out_MicChannels;
|
uint8_t Out_MicChannels;
|
||||||
uint8_t Decimation;
|
uint8_t Decimation;
|
||||||
uint8_t MaxVolume;
|
uint8_t MaxVolume;
|
||||||
/* Private */
|
/* Private */
|
||||||
uint32_t Coef[SINCN];
|
uint32_t Coef[SINCN];
|
||||||
uint16_t FilterLen;
|
uint16_t FilterLen;
|
||||||
int64_t OldOut, OldIn, OldZ;
|
int64_t OldOut, OldIn, OldZ;
|
||||||
uint16_t LP_ALFA;
|
uint16_t LP_ALFA;
|
||||||
uint16_t HP_ALFA;
|
uint16_t HP_ALFA;
|
||||||
uint16_t bit[5];
|
uint16_t bit[5];
|
||||||
uint16_t byte;
|
uint16_t byte;
|
||||||
uint16_t filterGain;
|
uint16_t filterGain;
|
||||||
} TPDMFilter_InitStruct;
|
} TPDMFilter_InitStruct;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,179 +30,168 @@ int16_t* volatile finalBuffer;
|
||||||
TPDMFilter_InitStruct filter;
|
TPDMFilter_InitStruct filter;
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
__attribute__((__used__)) void dmaHandler(void)
|
__attribute__((__used__)) void dmaHandler(void) {
|
||||||
{
|
PDM.IrqHandler(true);
|
||||||
PDM.IrqHandler(true);
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PDMClass::PDMClass(int dinPin, int clkPin, int pwrPin) :
|
PDMClass::PDMClass(int dinPin, int clkPin, int pwrPin) :
|
||||||
_dinPin(dinPin),
|
_dinPin(dinPin),
|
||||||
_clkPin(clkPin),
|
_clkPin(clkPin),
|
||||||
_pwrPin(pwrPin),
|
_pwrPin(pwrPin),
|
||||||
_onReceive(NULL),
|
_onReceive(NULL),
|
||||||
_gain(-1),
|
_gain(-1),
|
||||||
_channels(-1),
|
_channels(-1),
|
||||||
_samplerate(-1),
|
_samplerate(-1),
|
||||||
_init(-1),
|
_init(-1),
|
||||||
_dmaChannel(0),
|
_dmaChannel(0),
|
||||||
_pio(nullptr),
|
_pio(nullptr),
|
||||||
_smIdx(-1),
|
_smIdx(-1),
|
||||||
_pgmOffset(-1)
|
_pgmOffset(-1) {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PDMClass::~PDMClass()
|
PDMClass::~PDMClass() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int PDMClass::begin(int channels, int sampleRate)
|
int PDMClass::begin(int channels, int sampleRate) {
|
||||||
{
|
//_channels = channels; // only one channel available
|
||||||
//_channels = channels; // only one channel available
|
|
||||||
|
|
||||||
// clear the final buffers
|
// clear the final buffers
|
||||||
_doubleBuffer.reset();
|
_doubleBuffer.reset();
|
||||||
finalBuffer = (int16_t*)_doubleBuffer.data();
|
finalBuffer = (int16_t*)_doubleBuffer.data();
|
||||||
int finalBufferLength = _doubleBuffer.availableForWrite() / sizeof(int16_t);
|
int finalBufferLength = _doubleBuffer.availableForWrite() / sizeof(int16_t);
|
||||||
_doubleBuffer.swap(0);
|
_doubleBuffer.swap(0);
|
||||||
|
|
||||||
int rawBufferLength = RAW_BUFFER_SIZE / (decimation / 8);
|
int rawBufferLength = RAW_BUFFER_SIZE / (decimation / 8);
|
||||||
// Saturate number of samples. Remaining bytes are dropped.
|
// Saturate number of samples. Remaining bytes are dropped.
|
||||||
if (rawBufferLength > finalBufferLength) {
|
if (rawBufferLength > finalBufferLength) {
|
||||||
rawBufferLength = finalBufferLength;
|
rawBufferLength = finalBufferLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize Open PDM library */
|
/* Initialize Open PDM library */
|
||||||
filter.Fs = sampleRate;
|
filter.Fs = sampleRate;
|
||||||
filter.nSamples = rawBufferLength;
|
filter.nSamples = rawBufferLength;
|
||||||
filter.LP_HZ = sampleRate/2;
|
filter.LP_HZ = sampleRate / 2;
|
||||||
filter.HP_HZ = 10;
|
filter.HP_HZ = 10;
|
||||||
filter.In_MicChannels = 1;
|
filter.In_MicChannels = 1;
|
||||||
filter.Out_MicChannels = 1;
|
filter.Out_MicChannels = 1;
|
||||||
filter.Decimation = decimation;
|
filter.Decimation = decimation;
|
||||||
if(_gain == -1) {
|
if (_gain == -1) {
|
||||||
_gain = FILTER_GAIN;
|
_gain = FILTER_GAIN;
|
||||||
}
|
}
|
||||||
filter.filterGain = _gain;
|
|
||||||
Open_PDM_Filter_Init(&filter);
|
|
||||||
|
|
||||||
// Configure PIO state machine
|
|
||||||
float clkDiv = (float)clock_get_hz(clk_sys) / sampleRate / decimation / 2;
|
|
||||||
|
|
||||||
if (!_pdmPgm.prepare(&_pio, &_smIdx, &_pgmOffset)) {
|
|
||||||
// ERROR, no free slots
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
pdm_pio_program_init(_pio, _smIdx, _pgmOffset, _clkPin, _dinPin, clkDiv);
|
|
||||||
|
|
||||||
// Wait for microphone
|
|
||||||
delay(100);
|
|
||||||
|
|
||||||
// Configure DMA for transferring PIO rx buffer to raw buffers
|
|
||||||
_dmaChannel = dma_claim_unused_channel(false);
|
|
||||||
dma_channel_config c = dma_channel_get_default_config(_dmaChannel);
|
|
||||||
channel_config_set_read_increment(&c, false);
|
|
||||||
channel_config_set_write_increment(&c, true);
|
|
||||||
channel_config_set_dreq(&c, pio_get_dreq(_pio, _smIdx, false));
|
|
||||||
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
|
|
||||||
|
|
||||||
// Clear DMA interrupts
|
|
||||||
dma_hw->ints0 = 1u << _dmaChannel;
|
|
||||||
// Enable DMA interrupts
|
|
||||||
dma_channel_set_irq0_enabled(_dmaChannel, true);
|
|
||||||
// Share but allocate a high priority to the interrupt
|
|
||||||
irq_add_shared_handler(DMA_IRQ_0, dmaHandler, 0);
|
|
||||||
irq_set_enabled(DMA_IRQ_0, true);
|
|
||||||
|
|
||||||
dma_channel_configure(_dmaChannel, &c,
|
|
||||||
rawBuffer[rawBufferIndex], // Destinatinon pointer
|
|
||||||
&_pio->rxf[_smIdx], // Source pointer
|
|
||||||
RAW_BUFFER_SIZE, // Number of transfers
|
|
||||||
true // Start immediately
|
|
||||||
);
|
|
||||||
|
|
||||||
_init = 1;
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PDMClass::end()
|
|
||||||
{
|
|
||||||
dma_channel_abort(_dmaChannel);
|
|
||||||
pinMode(_clkPin, INPUT);
|
|
||||||
}
|
|
||||||
|
|
||||||
int PDMClass::available()
|
|
||||||
{
|
|
||||||
//NVIC_DisableIRQ(DMA_IRQ_0n);
|
|
||||||
//uint32_t interrupts = save_and_disable_interrupts();
|
|
||||||
irq_set_enabled(DMA_IRQ_0, false);
|
|
||||||
size_t avail = _doubleBuffer.available();
|
|
||||||
irq_set_enabled(DMA_IRQ_0, true);
|
|
||||||
//restore_interrupts(interrupts);
|
|
||||||
//NVIC_EnableIRQ(DMA_IRQ_0n);
|
|
||||||
return avail;
|
|
||||||
}
|
|
||||||
|
|
||||||
int PDMClass::read(void* buffer, size_t size)
|
|
||||||
{
|
|
||||||
irq_set_enabled(DMA_IRQ_0, false);
|
|
||||||
int read = _doubleBuffer.read(buffer, size);
|
|
||||||
irq_set_enabled(DMA_IRQ_0, true);
|
|
||||||
return read;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PDMClass::onReceive(void(*function)(void))
|
|
||||||
{
|
|
||||||
_onReceive = function;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PDMClass::setGain(int gain)
|
|
||||||
{
|
|
||||||
_gain = gain;
|
|
||||||
if(_init == 1) {
|
|
||||||
filter.filterGain = _gain;
|
filter.filterGain = _gain;
|
||||||
Open_PDM_Filter_Init(&filter);
|
Open_PDM_Filter_Init(&filter);
|
||||||
}
|
|
||||||
|
// Configure PIO state machine
|
||||||
|
float clkDiv = (float)clock_get_hz(clk_sys) / sampleRate / decimation / 2;
|
||||||
|
|
||||||
|
if (!_pdmPgm.prepare(&_pio, &_smIdx, &_pgmOffset)) {
|
||||||
|
// ERROR, no free slots
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pdm_pio_program_init(_pio, _smIdx, _pgmOffset, _clkPin, _dinPin, clkDiv);
|
||||||
|
|
||||||
|
// Wait for microphone
|
||||||
|
delay(100);
|
||||||
|
|
||||||
|
// Configure DMA for transferring PIO rx buffer to raw buffers
|
||||||
|
_dmaChannel = dma_claim_unused_channel(false);
|
||||||
|
dma_channel_config c = dma_channel_get_default_config(_dmaChannel);
|
||||||
|
channel_config_set_read_increment(&c, false);
|
||||||
|
channel_config_set_write_increment(&c, true);
|
||||||
|
channel_config_set_dreq(&c, pio_get_dreq(_pio, _smIdx, false));
|
||||||
|
channel_config_set_transfer_data_size(&c, DMA_SIZE_8);
|
||||||
|
|
||||||
|
// Clear DMA interrupts
|
||||||
|
dma_hw->ints0 = 1u << _dmaChannel;
|
||||||
|
// Enable DMA interrupts
|
||||||
|
dma_channel_set_irq0_enabled(_dmaChannel, true);
|
||||||
|
// Share but allocate a high priority to the interrupt
|
||||||
|
irq_add_shared_handler(DMA_IRQ_0, dmaHandler, 0);
|
||||||
|
irq_set_enabled(DMA_IRQ_0, true);
|
||||||
|
|
||||||
|
dma_channel_configure(_dmaChannel, &c,
|
||||||
|
rawBuffer[rawBufferIndex], // Destinatinon pointer
|
||||||
|
&_pio->rxf[_smIdx], // Source pointer
|
||||||
|
RAW_BUFFER_SIZE, // Number of transfers
|
||||||
|
true // Start immediately
|
||||||
|
);
|
||||||
|
|
||||||
|
_init = 1;
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDMClass::setBufferSize(int bufferSize)
|
void PDMClass::end() {
|
||||||
{
|
dma_channel_abort(_dmaChannel);
|
||||||
_doubleBuffer.setSize(bufferSize);
|
pinMode(_clkPin, INPUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDMClass::IrqHandler(bool halftranfer)
|
int PDMClass::available() {
|
||||||
{
|
//NVIC_DisableIRQ(DMA_IRQ_0n);
|
||||||
static int cutSamples = 100;
|
//uint32_t interrupts = save_and_disable_interrupts();
|
||||||
|
irq_set_enabled(DMA_IRQ_0, false);
|
||||||
|
size_t avail = _doubleBuffer.available();
|
||||||
|
irq_set_enabled(DMA_IRQ_0, true);
|
||||||
|
//restore_interrupts(interrupts);
|
||||||
|
//NVIC_EnableIRQ(DMA_IRQ_0n);
|
||||||
|
return avail;
|
||||||
|
}
|
||||||
|
|
||||||
// Clear the interrupt request.
|
int PDMClass::read(void* buffer, size_t size) {
|
||||||
dma_hw->ints0 = 1u << _dmaChannel;
|
irq_set_enabled(DMA_IRQ_0, false);
|
||||||
// Restart dma pointing to the other buffer
|
int read = _doubleBuffer.read(buffer, size);
|
||||||
int shadowIndex = rawBufferIndex ^ 1;
|
irq_set_enabled(DMA_IRQ_0, true);
|
||||||
dma_channel_set_write_addr(_dmaChannel, rawBuffer[shadowIndex], true);
|
return read;
|
||||||
|
}
|
||||||
|
|
||||||
if (_doubleBuffer.available()) {
|
void PDMClass::onReceive(void(*function)(void)) {
|
||||||
// buffer overflow, stop
|
_onReceive = function;
|
||||||
return end();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// fill final buffer with PCM samples
|
void PDMClass::setGain(int gain) {
|
||||||
Open_PDM_Filter_64(rawBuffer[rawBufferIndex], finalBuffer, 1, &filter);
|
_gain = gain;
|
||||||
|
if (_init == 1) {
|
||||||
|
filter.filterGain = _gain;
|
||||||
|
Open_PDM_Filter_Init(&filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (cutSamples) {
|
void PDMClass::setBufferSize(int bufferSize) {
|
||||||
memset(finalBuffer, 0, cutSamples);
|
_doubleBuffer.setSize(bufferSize);
|
||||||
cutSamples = 0;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// swap final buffer and raw buffers' indexes
|
void PDMClass::IrqHandler(bool halftranfer) {
|
||||||
finalBuffer = (int16_t*)_doubleBuffer.data();
|
static int cutSamples = 100;
|
||||||
_doubleBuffer.swap(filter.nSamples * sizeof(int16_t));
|
|
||||||
rawBufferIndex = shadowIndex;
|
|
||||||
|
|
||||||
if (_onReceive) {
|
// Clear the interrupt request.
|
||||||
_onReceive();
|
dma_hw->ints0 = 1u << _dmaChannel;
|
||||||
}
|
// Restart dma pointing to the other buffer
|
||||||
|
int shadowIndex = rawBufferIndex ^ 1;
|
||||||
|
dma_channel_set_write_addr(_dmaChannel, rawBuffer[shadowIndex], true);
|
||||||
|
|
||||||
|
if (_doubleBuffer.available()) {
|
||||||
|
// buffer overflow, stop
|
||||||
|
return end();
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill final buffer with PCM samples
|
||||||
|
Open_PDM_Filter_64(rawBuffer[rawBufferIndex], finalBuffer, 1, &filter);
|
||||||
|
|
||||||
|
if (cutSamples) {
|
||||||
|
memset(finalBuffer, 0, cutSamples);
|
||||||
|
cutSamples = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// swap final buffer and raw buffers' indexes
|
||||||
|
finalBuffer = (int16_t*)_doubleBuffer.data();
|
||||||
|
_doubleBuffer.swap(filter.nSamples * sizeof(int16_t));
|
||||||
|
rawBufferIndex = shadowIndex;
|
||||||
|
|
||||||
|
if (_onReceive) {
|
||||||
|
_onReceive();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#ifdef PIN_PDM_DIN
|
#ifdef PIN_PDM_DIN
|
||||||
PDMClass PDM(PIN_PDM_DIN, PIN_PDM_CLK, -1);
|
PDMClass PDM(PIN_PDM_DIN, PIN_PDM_CLK, -1);
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,10 @@
|
||||||
#define pdm_pio_wrap 1
|
#define pdm_pio_wrap 1
|
||||||
|
|
||||||
static const uint16_t pdm_pio_program_instructions[] = {
|
static const uint16_t pdm_pio_program_instructions[] = {
|
||||||
// .wrap_target
|
// .wrap_target
|
||||||
0x9040, // 0: push iffull noblock side 1
|
0x9040, // 0: push iffull noblock side 1
|
||||||
0x4001, // 1: in pins, 1 side 0
|
0x4001, // 1: in pins, 1 side 0
|
||||||
// .wrap
|
// .wrap
|
||||||
};
|
};
|
||||||
|
|
||||||
#if !PICO_NO_HARDWARE
|
#if !PICO_NO_HARDWARE
|
||||||
|
|
@ -36,21 +36,21 @@ static inline pio_sm_config pdm_pio_program_get_default_config(uint offset) {
|
||||||
|
|
||||||
#include "hardware/gpio.h"
|
#include "hardware/gpio.h"
|
||||||
static inline void pdm_pio_program_init(PIO pio, uint sm, uint offset, uint clkPin, uint dataPin, float clkDiv) {
|
static inline void pdm_pio_program_init(PIO pio, uint sm, uint offset, uint clkPin, uint dataPin, float clkDiv) {
|
||||||
pio_sm_config c = pdm_pio_program_get_default_config(offset);
|
pio_sm_config c = pdm_pio_program_get_default_config(offset);
|
||||||
sm_config_set_sideset(&c, 1, false, false);
|
sm_config_set_sideset(&c, 1, false, false);
|
||||||
//sm_config_set_in_shift(&c, false, true, 8);
|
//sm_config_set_in_shift(&c, false, true, 8);
|
||||||
sm_config_set_in_shift(&c, false, false, 8);
|
sm_config_set_in_shift(&c, false, false, 8);
|
||||||
sm_config_set_in_pins(&c, dataPin);
|
sm_config_set_in_pins(&c, dataPin);
|
||||||
sm_config_set_sideset_pins(&c, clkPin);
|
sm_config_set_sideset_pins(&c, clkPin);
|
||||||
sm_config_set_clkdiv(&c, clkDiv);
|
sm_config_set_clkdiv(&c, clkDiv);
|
||||||
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_RX);
|
||||||
pio_sm_set_consecutive_pindirs(pio, sm, dataPin, 1, false);
|
pio_sm_set_consecutive_pindirs(pio, sm, dataPin, 1, false);
|
||||||
pio_sm_set_consecutive_pindirs(pio, sm, clkPin, 1, true);
|
pio_sm_set_consecutive_pindirs(pio, sm, clkPin, 1, true);
|
||||||
pio_sm_set_pins_with_mask(pio, sm, 0, (1u << clkPin) );
|
pio_sm_set_pins_with_mask(pio, sm, 0, (1u << clkPin));
|
||||||
//pio_gpio_init(pio, dataPin);
|
//pio_gpio_init(pio, dataPin);
|
||||||
pio_gpio_init(pio, clkPin);
|
pio_gpio_init(pio, clkPin);
|
||||||
pio_sm_init(pio, sm, offset, &c);
|
pio_sm_init(pio, sm, offset, &c);
|
||||||
pio_sm_set_enabled(pio, sm, true);
|
pio_sm_set_enabled(pio, sm, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2016 Arduino LLC. All right reserved.
|
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
See the GNU Lesser General Public License for more details.
|
See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -22,118 +22,106 @@
|
||||||
#include "PDMDoubleBuffer.h"
|
#include "PDMDoubleBuffer.h"
|
||||||
|
|
||||||
PDMDoubleBuffer::PDMDoubleBuffer() :
|
PDMDoubleBuffer::PDMDoubleBuffer() :
|
||||||
_size(DEFAULT_PDM_BUFFER_SIZE)
|
_size(DEFAULT_PDM_BUFFER_SIZE) {
|
||||||
{
|
reset();
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PDMDoubleBuffer::~PDMDoubleBuffer()
|
PDMDoubleBuffer::~PDMDoubleBuffer() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDMDoubleBuffer::setSize(int size)
|
void PDMDoubleBuffer::setSize(int size) {
|
||||||
{
|
_size = size;
|
||||||
_size = size;
|
reset();
|
||||||
reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t PDMDoubleBuffer::getSize()
|
size_t PDMDoubleBuffer::getSize() {
|
||||||
{
|
return _size;
|
||||||
return _size;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PDMDoubleBuffer::reset()
|
void PDMDoubleBuffer::reset() {
|
||||||
{
|
_buffer[0] = (uint8_t*)realloc(_buffer[0], _size);
|
||||||
_buffer[0] = (uint8_t*)realloc(_buffer[0], _size);
|
_buffer[1] = (uint8_t*)realloc(_buffer[1], _size);
|
||||||
_buffer[1] = (uint8_t*)realloc(_buffer[1], _size);
|
|
||||||
|
|
||||||
memset(_buffer[0], 0x00, _size);
|
memset(_buffer[0], 0x00, _size);
|
||||||
memset(_buffer[1], 0x00, _size);
|
memset(_buffer[1], 0x00, _size);
|
||||||
|
|
||||||
_index = 0;
|
|
||||||
_length[0] = 0;
|
|
||||||
_length[1] = 0;
|
|
||||||
_readOffset[0] = 0;
|
|
||||||
_readOffset[1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PDMDoubleBuffer::availableForWrite()
|
|
||||||
{
|
|
||||||
return (_size - (_length[_index] - _readOffset[_index]));
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PDMDoubleBuffer::write(const void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
size_t space = availableForWrite();
|
|
||||||
|
|
||||||
if (size > space) {
|
|
||||||
size = space;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&_buffer[_index][_length[_index]], buffer, size);
|
|
||||||
|
|
||||||
_length[_index] += size;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PDMDoubleBuffer::read(void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
size_t avail = available();
|
|
||||||
|
|
||||||
if (size > avail) {
|
|
||||||
size = avail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer, &_buffer[_index][_readOffset[_index]], size);
|
|
||||||
_readOffset[_index] += size;
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PDMDoubleBuffer::peek(void *buffer, size_t size)
|
|
||||||
{
|
|
||||||
size_t avail = available();
|
|
||||||
|
|
||||||
if (size > avail) {
|
|
||||||
size = avail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buffer, &_buffer[_index][_readOffset[_index]], size);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void* PDMDoubleBuffer::data()
|
|
||||||
{
|
|
||||||
return (void*)_buffer[_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t PDMDoubleBuffer::available()
|
|
||||||
{
|
|
||||||
return _length[_index] - _readOffset[_index];
|
|
||||||
}
|
|
||||||
|
|
||||||
void PDMDoubleBuffer::swap(int length)
|
|
||||||
{
|
|
||||||
if (_index == 0) {
|
|
||||||
_index = 1;
|
|
||||||
} else {
|
|
||||||
_index = 0;
|
_index = 0;
|
||||||
}
|
_length[0] = 0;
|
||||||
|
_length[1] = 0;
|
||||||
_length[_index] = length;
|
_readOffset[0] = 0;
|
||||||
_readOffset[_index] = 0;
|
_readOffset[1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::availableForWrite() {
|
||||||
|
return (_size - (_length[_index] - _readOffset[_index]));
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::write(const void *buffer, size_t size) {
|
||||||
|
size_t space = availableForWrite();
|
||||||
|
|
||||||
|
if (size > space) {
|
||||||
|
size = space;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&_buffer[_index][_length[_index]], buffer, size);
|
||||||
|
|
||||||
|
_length[_index] += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::read(void *buffer, size_t size) {
|
||||||
|
size_t avail = available();
|
||||||
|
|
||||||
|
if (size > avail) {
|
||||||
|
size = avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, &_buffer[_index][_readOffset[_index]], size);
|
||||||
|
_readOffset[_index] += size;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::peek(void *buffer, size_t size) {
|
||||||
|
size_t avail = available();
|
||||||
|
|
||||||
|
if (size > avail) {
|
||||||
|
size = avail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buffer, &_buffer[_index][_readOffset[_index]], size);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* PDMDoubleBuffer::data() {
|
||||||
|
return (void*)_buffer[_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t PDMDoubleBuffer::available() {
|
||||||
|
return _length[_index] - _readOffset[_index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void PDMDoubleBuffer::swap(int length) {
|
||||||
|
if (_index == 0) {
|
||||||
|
_index = 1;
|
||||||
|
} else {
|
||||||
|
_index = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
_length[_index] = length;
|
||||||
|
_readOffset[_index] = 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,19 @@
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2016 Arduino LLC. All right reserved.
|
Copyright (c) 2016 Arduino LLC. All right reserved.
|
||||||
|
|
||||||
This library is free software; you can redistribute it and/or
|
This library is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the GNU Lesser General Public
|
modify it under the terms of the GNU Lesser General Public
|
||||||
License as published by the Free Software Foundation; either
|
License as published by the Free Software Foundation; either
|
||||||
version 2.1 of the License, or (at your option) any later version.
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
This library is distributed in the hope that it will be useful,
|
This library is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
See the GNU Lesser General Public License for more details.
|
See the GNU Lesser General Public License for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU Lesser General Public
|
You should have received a copy of the GNU Lesser General Public
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _PDM_DOUBLE_BUFFER_H_INCLUDED
|
#ifndef _PDM_DOUBLE_BUFFER_H_INCLUDED
|
||||||
|
|
@ -24,31 +24,30 @@
|
||||||
|
|
||||||
#define DEFAULT_PDM_BUFFER_SIZE 512
|
#define DEFAULT_PDM_BUFFER_SIZE 512
|
||||||
|
|
||||||
class PDMDoubleBuffer
|
class PDMDoubleBuffer {
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
PDMDoubleBuffer();
|
PDMDoubleBuffer();
|
||||||
virtual ~PDMDoubleBuffer();
|
virtual ~PDMDoubleBuffer();
|
||||||
|
|
||||||
void setSize(int size);
|
void setSize(int size);
|
||||||
size_t getSize();
|
size_t getSize();
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
size_t availableForWrite();
|
size_t availableForWrite();
|
||||||
size_t write(const void *buffer, size_t size);
|
size_t write(const void *buffer, size_t size);
|
||||||
size_t read(void *buffer, size_t size);
|
size_t read(void *buffer, size_t size);
|
||||||
size_t peek(void *buffer, size_t size);
|
size_t peek(void *buffer, size_t size);
|
||||||
void* data();
|
void* data();
|
||||||
size_t available();
|
size_t available();
|
||||||
void swap(int length = 0);
|
void swap(int length = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t* _buffer[2] __attribute__((aligned (16)));
|
uint8_t* _buffer[2] __attribute__((aligned(16)));
|
||||||
int _size;
|
int _size;
|
||||||
volatile int _length[2];
|
volatile int _length[2];
|
||||||
volatile int _readOffset[2];
|
volatile int _readOffset[2];
|
||||||
volatile int _index;
|
volatile int _index;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -17,8 +17,7 @@
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __SD_H__
|
#pragma once
|
||||||
#define __SD_H__
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
|
|
@ -218,5 +217,3 @@ static inline uint8_t FAT_SECOND(uint16_t fatTime) {
|
||||||
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SD)
|
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_SD)
|
||||||
extern SDClass SD;
|
extern SDClass SD;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
#ifndef SDFS_H
|
|
||||||
#define SDFS_H
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
SDFS.h - file system wrapper for SdLib
|
SDFS.h - file system wrapper for SdLib
|
||||||
Copyright (c) 2019 Earle F. Philhower, III. All rights reserved.
|
Copyright (c) 2019 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
@ -27,6 +24,9 @@
|
||||||
License along with this library; if not, write to the Free Software
|
License along with this library; if not, write to the Free Software
|
||||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
|
|
@ -508,5 +508,3 @@ protected:
|
||||||
extern FS SDFS;
|
extern FS SDFS;
|
||||||
using sdfs::SDFSConfig;
|
using sdfs::SDFSConfig;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif // SDFS.h
|
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,7 @@
|
||||||
detach() - Stops an attached servos from pulsing its i/o pin.
|
detach() - Stops an attached servos from pulsing its i/o pin.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef Servo_h
|
#pragma once
|
||||||
#define Servo_h
|
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <hardware/pio.h>
|
#include <hardware/pio.h>
|
||||||
|
|
@ -89,5 +88,3 @@ private:
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,22 @@
|
||||||
|
/*
|
||||||
|
StackThunk - Implements a simple 2nd stack for BSSL and others
|
||||||
|
Copyright (c) 2022 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,22 @@
|
||||||
|
/*
|
||||||
|
StackThunk - Implements a simple 2nd stack for BSSL and others
|
||||||
|
Copyright (c) 2022 Earle F. Philhower, III. All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
|
||||||
|
|
@ -72,8 +72,7 @@
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __ADDRLIST_H
|
#pragma once
|
||||||
#define __ADDRLIST_H
|
|
||||||
|
|
||||||
#include <IPAddress.h>
|
#include <IPAddress.h>
|
||||||
#include <api/String.h>
|
#include <api/String.h>
|
||||||
|
|
@ -254,6 +253,3 @@ inline AddressList::const_iterator end(const AddressList& a) {
|
||||||
} // esp8266
|
} // esp8266
|
||||||
|
|
||||||
extern esp8266::AddressListImplementation::AddressList addrList;
|
extern esp8266::AddressListImplementation::AddressList addrList;
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,25 @@
|
||||||
|
/*
|
||||||
|
LwipEthernet.h
|
||||||
|
|
||||||
|
Arduino interface for lwIP generic callbacks and functions
|
||||||
|
|
||||||
|
Original Copyright (c) 2020 esp8266 Arduino All rights reserved.
|
||||||
|
|
||||||
|
This library is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 2.1 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
This library is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with this library; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
//#include <ESP8266WiFi.h> // tcp API
|
//#include <ESP8266WiFi.h> // tcp API
|
||||||
//#include <debug.h>
|
//#include <debug.h>
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,12 @@
|
||||||
for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S \
|
for dir in ./cores/rp2040 ./libraries/EEPROM ./libraries/I2S \
|
||||||
./libraries/LittleFS/src ./libraries/LittleFS/examples \
|
./libraries/LittleFS/src ./libraries/LittleFS/examples \
|
||||||
./libraries/rp2040 ./libraries/SD ./libraries/ESP8266SdFat \
|
./libraries/rp2040 ./libraries/SD ./libraries/ESP8266SdFat \
|
||||||
./libraries/Servo ./libraries/SPI ./libraries/Wire \
|
./libraries/Servo ./libraries/SPI ./libraries/Wire ./libraries/PDM \
|
||||||
./libraries/WiFi ./libraries/lwIP_Ethernet ./libraries/lwIP_CYW43 \
|
./libraries/WiFi ./libraries/lwIP_Ethernet ./libraries/lwIP_CYW43 \
|
||||||
./libraries/FreeRTOS/src ./libraries/LEAmDNS ./libraries/MD5Builder \
|
./libraries/FreeRTOS/src ./libraries/LEAmDNS ./libraries/MD5Builder \
|
||||||
./libraries/PicoOTA ./libraries/SDFS ./libraries/ArduinoOTA \
|
./libraries/PicoOTA ./libraries/SDFS ./libraries/ArduinoOTA \
|
||||||
./libraries/Updater ./libraries/HTTPClient ./libraries/HTTPUpdate \
|
./libraries/Updater ./libraries/HTTPClient ./libraries/HTTPUpdate \
|
||||||
./libraries/WebServer ./libraries/HTTPUpdateServer ; do
|
./libraries/WebServer ./libraries/HTTPUpdateServer ./libraries/DNSServer ; do
|
||||||
find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" \) -a \! -path '*api*' -exec astyle --suffix=none --options=./tests/astyle_core.conf \{\} \;
|
find $dir -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" \) -a \! -path '*api*' -exec astyle --suffix=none --options=./tests/astyle_core.conf \{\} \;
|
||||||
find $dir -type f -name "*.ino" -exec astyle --suffix=none --options=./tests/astyle_examples.conf \{\} \;
|
find $dir -type f -name "*.ino" -exec astyle --suffix=none --options=./tests/astyle_examples.conf \{\} \;
|
||||||
done
|
done
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue