now actionified & adding proper test files for all examples!
This commit is contained in:
parent
44362b4297
commit
f0de90d0e9
350 changed files with 1128 additions and 432 deletions
46
.github/ISSUE_TEMPLATE.md
vendored
Normal file
46
.github/ISSUE_TEMPLATE.md
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
Thank you for opening an issue on an Adafruit Arduino library repository. To
|
||||
improve the speed of resolution please review the following guidelines and
|
||||
common troubleshooting steps below before creating the issue:
|
||||
|
||||
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
|
||||
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
|
||||
something isn't working as expected. In many cases the problem is a common issue
|
||||
that you will more quickly receive help from the forum community. GitHub issues
|
||||
are meant for known defects in the code. If you don't know if there is a defect
|
||||
in the code then start with troubleshooting on the forum first.
|
||||
|
||||
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
|
||||
check all of the steps and commands to run have been followed. Consult the
|
||||
forum if you're unsure or have questions about steps in a guide/tutorial.
|
||||
|
||||
- **For Arduino projects check these very common issues to ensure they don't apply**:
|
||||
|
||||
- For uploading sketches or communicating with the board make sure you're using
|
||||
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
|
||||
very hard to tell the difference between a data and charge cable! Try using the
|
||||
cable with other devices or swapping to another cable to confirm it is not
|
||||
the problem.
|
||||
|
||||
- **Be sure you are supplying adequate power to the board.** Check the specs of
|
||||
your board and plug in an external power supply. In many cases just
|
||||
plugging a board into your computer is not enough to power it and other
|
||||
peripherals.
|
||||
|
||||
- **Double check all soldering joints and connections.** Flakey connections
|
||||
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
|
||||
|
||||
- **Ensure you are using an official Arduino or Adafruit board.** We can't
|
||||
guarantee a clone board will have the same functionality and work as expected
|
||||
with this code and don't support them.
|
||||
|
||||
If you're sure this issue is a defect in the code and checked the steps above
|
||||
please fill in the following fields to provide enough troubleshooting information.
|
||||
You may delete the guideline and text above to just leave the following details:
|
||||
|
||||
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
|
||||
|
||||
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
|
||||
VERSION HERE**
|
||||
|
||||
- List the steps to reproduce the problem below (if possible attach a sketch or
|
||||
copy the sketch code in too): **LIST REPRO STEPS BELOW**
|
||||
26
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
26
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
|
||||
Before you open the request please review the following guidelines and tips to
|
||||
help it be more easily integrated:
|
||||
|
||||
- **Describe the scope of your change--i.e. what the change does and what parts
|
||||
of the code were modified.** This will help us understand any risks of integrating
|
||||
the code.
|
||||
|
||||
- **Describe any known limitations with your change.** For example if the change
|
||||
doesn't apply to a supported platform of the library please mention it.
|
||||
|
||||
- **Please run any tests or examples that can exercise your modified code.** We
|
||||
strive to not break users of the code and running tests/examples helps with this
|
||||
process.
|
||||
|
||||
Thank you again for contributing! We will try to test and integrate the change
|
||||
as soon as we can, but be aware we have many GitHub repositories to manage and
|
||||
can't immediately respond to every request. There is no need to bump or check in
|
||||
on a pull request (it will clutter the discussion of the request).
|
||||
|
||||
Also don't be worried if the request is closed or not integrated--sometimes the
|
||||
priorities of Adafruit's GitHub code (education, ease of use) might not match the
|
||||
priorities of the pull request. Don't fret, the open source community thrives on
|
||||
forks and GitHub makes it easy to keep your changes in a forked repo.
|
||||
|
||||
After reviewing the guidelines above you can delete this text from the pull request.
|
||||
63
.github/workflows/githubci.yml
vendored
63
.github/workflows/githubci.yml
vendored
|
|
@ -3,9 +3,46 @@ name: Arduino Library CI
|
|||
on: [pull_request, push, repository_dispatch]
|
||||
|
||||
jobs:
|
||||
arduino:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arduino-platform: ["uno", "nrf52832", "cpx_ada", "pyportal", "protrinket_3v", "protrinket_5v", "metro_m0", "esp8266", "esp32", "trinket_3v", "trinket_5v", "gemma", "flora", "feather32u4", "feather_m0_express", "gemma_m0", "trinket_m0", "hallowing_m0", "monster_m4sk", "hallowing_m4", "neotrellis_m4", "pybadge", "cpb"]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
#needs: pylint
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
repository: adafruit/ci-arduino
|
||||
path: ci
|
||||
|
||||
- name: pre-install
|
||||
run: bash ci/actions_install.sh
|
||||
|
||||
# manually install some libraries
|
||||
- name: extra libraries
|
||||
run: |
|
||||
git clone --quiet https://github.com/adafruit/Cryptosuite.git /home/runner/Arduino/libraries/Cryptosuite
|
||||
git clone --quiet https://github.com/adafruit/WiFiNINA.git /home/runner/Arduino/libraries/WiFiNINA
|
||||
git clone --quiet https://github.com/adafruit/Adafruit_LSM303.git /home/runner/Arduino/libraries/Adafruit_LSM303
|
||||
git clone --quiet https://github.com/moderndevice/CapSense.git /home/runner/Arduino/libraries/CapSense
|
||||
git clone --quiet https://github.com/PaintYourDragon/ffft.git /home/runner/Arduino/libraries/ffft
|
||||
git clone --quiet https://github.com/adafruit/RadioHead.git /home/runner/Arduino/libraries/RadioHead
|
||||
git clone --quiet https://github.com/me-no-dev/ESPAsyncTCP /home/runner/Arduino/libraries/ESPAsyncTCP
|
||||
git clone --quiet https://github.com/adafruit/Talkie /home/runner/Arduino/libraries/Talkie
|
||||
|
||||
- name: test platforms
|
||||
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
|
||||
|
||||
pylint:
|
||||
runs-on: ubuntu-latest
|
||||
# needs: build
|
||||
needs: arduino
|
||||
steps:
|
||||
- name: Set up Python 3.6
|
||||
uses: actions/setup-python@v1
|
||||
|
|
@ -22,27 +59,3 @@ jobs:
|
|||
|
||||
- name: lint
|
||||
run: ./pylint_check.sh
|
||||
|
||||
arduino:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
arduino-platform: ["uno", "cpx_ada", "pyportal"]
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/setup-python@v1
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
repository: adafruit/ci-arduino
|
||||
path: ci
|
||||
|
||||
- name: pre-install
|
||||
run: bash ci/actions_install.sh
|
||||
|
||||
- name: test platforms
|
||||
run: python3 ci/build_platform.py ${{ matrix.arduino-platform }}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,295 @@
|
|||
/*
|
||||
ESP32BootROM - part of the Firmware Updater for the
|
||||
Arduino MKR WiFi 1010, Arduino MKR Vidor 4000, and Arduino UNO WiFi Rev.2.
|
||||
|
||||
Copyright (c) 2018 Arduino SA. 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 "ESP32BootROM.h"
|
||||
|
||||
//#define DEBUG 1
|
||||
|
||||
ESP32BootROMClass::ESP32BootROMClass(HardwareSerial& serial, int gpio0Pin, int resetnPin) :
|
||||
_serial(&serial),
|
||||
_gpio0Pin(gpio0Pin),
|
||||
_resetnPin(resetnPin)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::begin(unsigned long baudrate)
|
||||
{
|
||||
_serial->begin(115200);
|
||||
|
||||
pinMode(_gpio0Pin, OUTPUT);
|
||||
pinMode(_resetnPin, OUTPUT);
|
||||
|
||||
digitalWrite(_gpio0Pin, LOW);
|
||||
|
||||
digitalWrite(_resetnPin, LOW);
|
||||
delay(10);
|
||||
digitalWrite(_resetnPin, HIGH);
|
||||
delay(100);
|
||||
|
||||
int synced = 0;
|
||||
|
||||
for (int retries = 0; !synced && (retries < 5); retries++) {
|
||||
synced = sync();
|
||||
}
|
||||
|
||||
if (!synced) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(ARDUINO_SAMD_MKRVIDOR4000) || defined(ARDUINO_AVR_UNO_WIFI_REV2)
|
||||
(void)baudrate;
|
||||
#else
|
||||
if (baudrate != 115200) {
|
||||
if (!changeBaudrate(baudrate)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
delay(100);
|
||||
|
||||
_serial->end();
|
||||
_serial->begin(baudrate);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!spiAttach()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ESP32BootROMClass::end() {
|
||||
_serial->end();
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::sync()
|
||||
{
|
||||
const uint8_t data[] = {
|
||||
0x07, 0x07, 0x12, 0x20,
|
||||
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55
|
||||
};
|
||||
|
||||
command(0x08, data, sizeof(data));
|
||||
|
||||
int results[8];
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
results[i] = response(0x08, 100);
|
||||
}
|
||||
|
||||
return (results[0] == 0);
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::changeBaudrate(unsigned long baudrate)
|
||||
{
|
||||
const uint32_t data[2] = {
|
||||
baudrate,
|
||||
0
|
||||
};
|
||||
|
||||
command(0x0f, data, sizeof(data));
|
||||
|
||||
return (response(0x0f, 3000) == 0);
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::spiAttach()
|
||||
{
|
||||
const uint8_t data[] = {
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
command(0x0d, data, sizeof(data));
|
||||
|
||||
return (response(0x0d, 3000) == 0);
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::beginFlash(uint32_t offset, uint32_t size, uint32_t chunkSize) {
|
||||
const uint32_t data[4] = {
|
||||
size,
|
||||
size / chunkSize,
|
||||
chunkSize,
|
||||
offset
|
||||
};
|
||||
|
||||
command(0x02, data, sizeof(data));
|
||||
|
||||
_flashSequenceNumber = 0;
|
||||
_chunkSize = chunkSize;
|
||||
|
||||
return (response(0x02, 120000) == 0);
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::dataFlash(const void* data, uint32_t length)
|
||||
{
|
||||
uint32_t cmdData[4 + (_chunkSize / 4)];
|
||||
|
||||
cmdData[0] = length;
|
||||
cmdData[1] = _flashSequenceNumber++;
|
||||
cmdData[2] = 0;
|
||||
cmdData[3] = 0;
|
||||
|
||||
memcpy(&cmdData[4], data, length);
|
||||
|
||||
if (length < _chunkSize) {
|
||||
memset(&cmdData[4 + (length / 4)], 0xff, _chunkSize - length);
|
||||
}
|
||||
|
||||
command(0x03, cmdData, sizeof(cmdData));
|
||||
|
||||
return (response(0x03, 3000) == 0);
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::endFlash(uint32_t reboot) {
|
||||
const uint32_t data[1] = {
|
||||
reboot
|
||||
};
|
||||
|
||||
command(0x04, data, sizeof(data));
|
||||
|
||||
return (response(0x04, 3000) == 0);
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::md5Flash(uint32_t offset, uint32_t size, uint8_t* result)
|
||||
{
|
||||
const uint32_t data[4] = {
|
||||
offset,
|
||||
size,
|
||||
0,
|
||||
0
|
||||
};
|
||||
|
||||
command(0x13, data, sizeof(data));
|
||||
|
||||
uint8_t asciiResult[32];
|
||||
|
||||
if (response(0x13, 3000, asciiResult) != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char temp[3] = { 0, 0, 0 };
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
temp[0] = asciiResult[i * 2];
|
||||
temp[1] = asciiResult[i * 2 + 1];
|
||||
|
||||
result[i] = strtoul(temp, NULL, 16);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ESP32BootROMClass::command(int opcode, const void* data, uint16_t length)
|
||||
{
|
||||
uint32_t checksum = 0;
|
||||
|
||||
if (opcode == 0x03) {
|
||||
checksum = 0xef; // seed
|
||||
|
||||
for (uint16_t i = 16; i < length; i++) {
|
||||
checksum ^= ((const uint8_t*)data)[i];
|
||||
}
|
||||
}
|
||||
|
||||
_serial->write(0xc0);
|
||||
_serial->write((uint8_t)0x00); // direction
|
||||
_serial->write(opcode);
|
||||
_serial->write((uint8_t*)&length, sizeof(length));
|
||||
writeEscapedBytes((uint8_t*)&checksum, sizeof(checksum));
|
||||
writeEscapedBytes((uint8_t*)data, length);
|
||||
_serial->write(0xc0);
|
||||
#ifdef ARDUINO_SAMD_MKRVIDOR4000
|
||||
// _serial->flush(); // doesn't work!
|
||||
#else
|
||||
_serial->flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
int ESP32BootROMClass::response(int opcode, unsigned long timeout, void* body)
|
||||
{
|
||||
uint8_t data[10 + 256];
|
||||
uint16_t index = 0;
|
||||
|
||||
uint8_t responseLength = 4;
|
||||
|
||||
for (unsigned long start = millis(); (index < (uint16_t)(10 + responseLength)) && (millis() - start) < timeout;) {
|
||||
if (_serial->available()) {
|
||||
data[index] = _serial->read();
|
||||
|
||||
if (index == 3) {
|
||||
responseLength = data[index];
|
||||
}
|
||||
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
if (index) {
|
||||
for (int i = 0; i < index; i++) {
|
||||
byte b = data[i];
|
||||
|
||||
if (b < 0x10) {
|
||||
Serial.print('0');
|
||||
}
|
||||
|
||||
Serial.print(b, HEX);
|
||||
Serial.print(' ');
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
#endif
|
||||
|
||||
if (index != (uint16_t)(10 + responseLength)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (data[0] != 0xc0 || data[1] != 0x01 || data[2] != opcode || data[responseLength + 5] != 0x00 || data[responseLength + 6] != 0x00 || data[responseLength + 9] != 0xc0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (body) {
|
||||
memcpy(body, &data[9], responseLength - 4);
|
||||
}
|
||||
|
||||
return data[responseLength + 5];
|
||||
}
|
||||
|
||||
void ESP32BootROMClass::writeEscapedBytes(const uint8_t* data, uint16_t length)
|
||||
{
|
||||
uint16_t written = 0;
|
||||
|
||||
while (written < length) {
|
||||
uint8_t b = data[written++];
|
||||
|
||||
if (b == 0xdb) {
|
||||
_serial->write(0xdb);
|
||||
_serial->write(0xdd);
|
||||
} else if (b == 0xc0) {
|
||||
_serial->write(0xdb);
|
||||
_serial->write(0xdc);
|
||||
} else {
|
||||
_serial->write(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ESP32BootROMClass ESP32BootROM(SerialNina, NINA_GPIO0, NINA_RESETN);
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
ESP32BootROM - part of the Firmware Updater for the
|
||||
Arduino MKR WiFi 1010, Arduino MKR Vidor 4000, and Arduino UNO WiFi Rev.2.
|
||||
|
||||
Copyright (c) 2018 Arduino SA. 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 <Arduino.h>
|
||||
|
||||
class ESP32BootROMClass {
|
||||
public:
|
||||
ESP32BootROMClass(HardwareSerial& hwSerial, int gpio0Pin, int resetnPin);
|
||||
|
||||
int begin(unsigned long baudrate);
|
||||
void end();
|
||||
|
||||
int beginFlash(uint32_t offset, uint32_t size, uint32_t chunkSize);
|
||||
int dataFlash(const void* data, uint32_t length);
|
||||
int endFlash(uint32_t reboot);
|
||||
|
||||
int md5Flash(uint32_t offset, uint32_t size, uint8_t* result);
|
||||
|
||||
private:
|
||||
int sync();
|
||||
int changeBaudrate(unsigned long baudrate);
|
||||
int spiAttach();
|
||||
|
||||
void command(int opcode, const void* data, uint16_t length);
|
||||
int response(int opcode, unsigned long timeout, void* body = NULL);
|
||||
|
||||
void writeEscapedBytes(const uint8_t* data, uint16_t length);
|
||||
|
||||
private:
|
||||
HardwareSerial* _serial;
|
||||
int _gpio0Pin;
|
||||
int _resetnPin;
|
||||
|
||||
uint32_t _flashSequenceNumber;
|
||||
uint32_t _chunkSize;
|
||||
};
|
||||
|
||||
extern ESP32BootROMClass ESP32BootROM;
|
||||
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
FirmwareUpdater - Firmware Updater for the
|
||||
Arduino MKR WiFi 1010, Arduino MKR Vidor 4000, and Arduino UNO WiFi Rev.2.
|
||||
|
||||
Copyright (c) 2018 Arduino SA. 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 "ESP32BootROM.h"
|
||||
#include <SD.h>
|
||||
|
||||
static const int MAX_PAYLOAD_SIZE = 1024;
|
||||
uint32_t firmsize;
|
||||
static uint8_t payload[MAX_PAYLOAD_SIZE];
|
||||
|
||||
#define SD_CS 32
|
||||
File myFile;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
delay(100);
|
||||
|
||||
if (!SD.begin(SD_CS)) {
|
||||
Serial.println("Card init. failed!");
|
||||
while (1);
|
||||
} else {
|
||||
Serial.println("SD OK!");
|
||||
}
|
||||
|
||||
|
||||
myFile = SD.open("/NINAW102.bin", FILE_READ);
|
||||
if (!myFile) {
|
||||
Serial.println("Failed to open firmware file");
|
||||
while (1);
|
||||
}
|
||||
firmsize = myFile.size();
|
||||
Serial.print(firmsize); Serial.println(" bytes");
|
||||
|
||||
}
|
||||
|
||||
void loop() {
|
||||
while (!ESP32BootROM.begin(921600)) {
|
||||
Serial.println("Unable to communicate with ESP32 boot ROM!");
|
||||
delay(100);
|
||||
return;
|
||||
}
|
||||
Serial.println("Ready!");
|
||||
|
||||
uint32_t timestamp = millis();
|
||||
|
||||
while (!ESP32BootROM.beginFlash(0, firmsize, MAX_PAYLOAD_SIZE)) {
|
||||
Serial.println("Failed to erase flash");
|
||||
delay(100);
|
||||
return;
|
||||
}
|
||||
Serial.println("Erase OK");
|
||||
|
||||
for (uint32_t i=0; i<firmsize; i+=MAX_PAYLOAD_SIZE) {
|
||||
memset(payload, 0xFF, MAX_PAYLOAD_SIZE);
|
||||
uint32_t num_read = myFile.read(&payload, MAX_PAYLOAD_SIZE);
|
||||
Serial.print("Packet #"); Serial.print(i/MAX_PAYLOAD_SIZE); Serial.print(": ");
|
||||
Serial.print(num_read); Serial.print(" byte payload...");
|
||||
|
||||
if (!ESP32BootROM.dataFlash(payload, MAX_PAYLOAD_SIZE)) {
|
||||
Serial.print("Failed to flash data");
|
||||
while (1);
|
||||
} else {
|
||||
Serial.println("OK");
|
||||
}
|
||||
}
|
||||
|
||||
myFile.close();
|
||||
|
||||
uint8_t md5[16];
|
||||
if (!ESP32BootROM.md5Flash(0, firmsize, md5)) {
|
||||
Serial.println("Error calculating MD5");
|
||||
} else {
|
||||
Serial.print("MD5 OK: ");
|
||||
for (int i=0; i<16; i++) {
|
||||
Serial.print("0x"); Serial.print(md5[i], HEX); Serial.print(" ");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
Serial.print("Took "); Serial.print(millis()-timestamp); Serial.println(" millis");
|
||||
while (1);
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
Endianess.ino - Network byte order conversion functions.
|
||||
Copyright (c) 2015 Arduino LLC. All right 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 <Arduino.h>
|
||||
|
||||
bool isBigEndian() {
|
||||
uint32_t test = 0x11223344;
|
||||
uint8_t *pTest = reinterpret_cast<uint8_t *>(&test);
|
||||
return pTest[0] == 0x11;
|
||||
}
|
||||
|
||||
uint32_t fromNetwork32(uint32_t from) {
|
||||
static const bool be = isBigEndian();
|
||||
if (be) {
|
||||
return from;
|
||||
} else {
|
||||
uint8_t *pFrom = reinterpret_cast<uint8_t *>(&from);
|
||||
uint32_t to;
|
||||
to = pFrom[0]; to <<= 8;
|
||||
to |= pFrom[1]; to <<= 8;
|
||||
to |= pFrom[2]; to <<= 8;
|
||||
to |= pFrom[3];
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t fromNetwork16(uint16_t from) {
|
||||
static bool be = isBigEndian();
|
||||
if (be) {
|
||||
return from;
|
||||
} else {
|
||||
uint8_t *pFrom = reinterpret_cast<uint8_t *>(&from);
|
||||
uint16_t to;
|
||||
to = pFrom[0]; to <<= 8;
|
||||
to |= pFrom[1];
|
||||
return to;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t toNetwork32(uint32_t to) {
|
||||
return fromNetwork32(to);
|
||||
}
|
||||
|
||||
uint16_t toNetwork16(uint16_t to) {
|
||||
return fromNetwork16(to);
|
||||
}
|
||||
|
|
@ -71,6 +71,8 @@ unsigned long baud = 115200;
|
|||
#define ESP32_RESETN 5 // Reset pin
|
||||
#define ESP32_GPIO0 -1 // Not connected
|
||||
#define NEOPIXEL_PIN 8
|
||||
#elif defined(ADAFRUIT_PYPORTAL)
|
||||
#define NEOPIXEL_PIN 2
|
||||
#endif
|
||||
|
||||
Adafruit_NeoPixel pixel = Adafruit_NeoPixel(1, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
|
||||
|
|
@ -110,4 +112,4 @@ void loop() {
|
|||
pixel.setPixelColor(0, 0, 0, 10); pixel.show();
|
||||
Serial.write(SerialESP32.read());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
#define SECRET_SSID "ssid"
|
||||
#define SECRET_PASS "password"
|
||||
|
|
@ -0,0 +1,284 @@
|
|||
// Stream MP3s over WiFi on Metro M4 Express and play via music maker shield
|
||||
|
||||
//#define DEBUG_OUTPUT
|
||||
|
||||
#include <ArduinoHttpClient.h>
|
||||
#include <WiFiNINA.h>
|
||||
#include <CircularBuffer.h> // From Agileware
|
||||
#include "Adafruit_MP3.h"
|
||||
#include "arduino_secrets.h"
|
||||
|
||||
///////please enter your sensitive data in the Secret tab/arduino_secrets.h
|
||||
char ssid[] = SECRET_SSID; // your network SSID (name)
|
||||
char pass[] = SECRET_PASS; // your network password (use for WPA, or use as key for WEP)
|
||||
|
||||
// Use ~64Kbps streams if possible, 128kb+ is too much data ;)
|
||||
|
||||
// CircuitPython weekly
|
||||
//const char *xmlfeed = "http://adafruit-podcasts.s3.amazonaws.com/circuitpython_weekly_meeting/audio-podcast.xml";
|
||||
const char *xmlfeed = "http://www.2600.com/oth.xml"; // yay they have a 16 kbps
|
||||
|
||||
// Too high bitrate!
|
||||
//const char *xmlfeed = "http://feeds.soundcloud.com/users/soundcloud:users:93913472/sounds.rss";
|
||||
//const char *xmlfeed = "https://theamphour.com/feed/";
|
||||
|
||||
/************* WiFi over ESP32 client for MP3 datastream */
|
||||
WiFiClient http_client; // Use WiFiClient class to create HTTP/TCP connection
|
||||
WiFiSSLClient https_client; // Use WiFiClient class to create HTTP/TCP connection
|
||||
char *stream_host, *stream_path;
|
||||
int stream_port = 80;
|
||||
|
||||
/************* Native MP3 decoding supported on M4 chips */
|
||||
Adafruit_MP3 player; // The MP3 player
|
||||
#define BUFFER_SIZE 8000 // we need a lot of buffer to keep from underruns! but not too big?
|
||||
CircularBuffer<uint8_t, BUFFER_SIZE> buffer;
|
||||
bool paused = true;
|
||||
float gain = 1;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
while (!Serial);
|
||||
delay(100);
|
||||
Serial.println("\nAdafruit Native MP3 Podcast Radio");
|
||||
|
||||
/************************* INITIALIZE WIFI */
|
||||
Serial.print("Connecting to SSID "); Serial.println(ssid);
|
||||
WiFi.begin(ssid, pass);
|
||||
|
||||
while (WiFi.status() != WL_CONNECTED) {
|
||||
delay(500);
|
||||
Serial.print(".");
|
||||
}
|
||||
Serial.print("WiFi connected. ");
|
||||
Serial.print("My IP address: "); Serial.println(WiFi.localIP());
|
||||
|
||||
|
||||
char *mp3_stream, *pubdate;
|
||||
getLatestMP3(xmlfeed, &mp3_stream, &pubdate);
|
||||
Serial.println(mp3_stream);
|
||||
Serial.println(pubdate);
|
||||
|
||||
splitURL(mp3_stream, &stream_host, &stream_port, &stream_path);
|
||||
if (stream_port == 443) {
|
||||
Serial.println("We don't support SSL MP3 playback, defaulting back to port 80");
|
||||
stream_port = 80;
|
||||
}
|
||||
player.begin();
|
||||
|
||||
//do this when there are samples ready
|
||||
player.setSampleReadyCallback(writeDacs);
|
||||
|
||||
//do this when more data is required
|
||||
player.setBufferCallback(getMoreData);
|
||||
|
||||
analogWrite(A0, 2048);
|
||||
player.play();
|
||||
player.pause();
|
||||
|
||||
|
||||
connectStream();
|
||||
}
|
||||
|
||||
bool getLatestMP3(String xmlfeed, char **mp3_url, char **date_str) {
|
||||
char *xml_host, *xml_path;
|
||||
int xml_port = 80;
|
||||
|
||||
bool found_mp3=false, found_date=false;
|
||||
|
||||
splitURL(xmlfeed, &xml_host, &xml_port, &xml_path);
|
||||
|
||||
Serial.print("XML Server: "); Serial.println(xml_host);
|
||||
Serial.print("XML Port #"); Serial.println(xml_port);
|
||||
Serial.print("XML Path: "); Serial.println(xml_path);
|
||||
|
||||
WiFiClient *xml_client;
|
||||
if (xml_port == 443) {
|
||||
xml_client = &https_client;
|
||||
} else {
|
||||
xml_client = &http_client;
|
||||
}
|
||||
|
||||
if (!xml_client->connect(xml_host, xml_port)) {
|
||||
Serial.println("Connection failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
// We now create a URI for the request
|
||||
Serial.print("Requesting XML URL: "); Serial.println(xml_path);
|
||||
|
||||
// This will send the request to the server
|
||||
xml_client->print(String("GET ") + xml_path + " HTTP/1.1\r\n" +
|
||||
"Host: " + xml_host + "\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
|
||||
while (xml_client->connected()) {
|
||||
if (!xml_client->available()) { continue; }
|
||||
char c = xml_client->read();
|
||||
Serial.print(c);
|
||||
if (c == '<') {
|
||||
String tag = xml_client->readStringUntil('>');
|
||||
Serial.print(tag);
|
||||
|
||||
if (!found_mp3 && (tag.indexOf("enclosure") != -1)) { // get first enclosure
|
||||
int i = tag.indexOf("url=\"");
|
||||
if (i == -1) continue;
|
||||
tag = tag.substring(i+5);
|
||||
int end = tag.indexOf("\"");
|
||||
if (end == -1) continue;
|
||||
tag = tag.substring(0, end);
|
||||
*mp3_url = (char *)malloc(tag.length()+1);
|
||||
tag.toCharArray(*mp3_url, tag.length()+1);
|
||||
// Serial.print("****"); Serial.println(*mp3_url);
|
||||
found_mp3 = true;
|
||||
}
|
||||
|
||||
if (!found_date && (tag.indexOf("pubDate") != -1)) { // get first pubdate
|
||||
String date = xml_client->readStringUntil('<');
|
||||
*date_str = (char *)malloc(date.length()+1);
|
||||
date.toCharArray(*date_str, date.length()+1);
|
||||
// Serial.print("****"); Serial.println(*date_str);
|
||||
found_date = true;
|
||||
}
|
||||
}
|
||||
if (found_date && found_mp3) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
xml_client->stop();
|
||||
return (found_date && found_mp3);
|
||||
}
|
||||
|
||||
void connectStream(void) {
|
||||
http_client.stop();
|
||||
/************************* INITIALIZE STREAM */
|
||||
Serial.print("Stream Server: "); Serial.println(stream_host);
|
||||
Serial.print("Stream Port #"); Serial.println(stream_port);
|
||||
Serial.print("Stream Path: "); Serial.println(stream_path);
|
||||
|
||||
if (!http_client.connect(stream_host, stream_port)) {
|
||||
Serial.println("Connection failed");
|
||||
while (1);
|
||||
}
|
||||
|
||||
// We now create a URI for the request
|
||||
Serial.print("Requesting URL: "); Serial.println(stream_path);
|
||||
|
||||
// This will send the request to the server
|
||||
http_client.print(String("GET ") + stream_path + " HTTP/1.1\r\n" +
|
||||
"Host: " + stream_host + "\r\n" +
|
||||
"Connection: close\r\n\r\n");
|
||||
}
|
||||
|
||||
|
||||
void loop() {
|
||||
if (!http_client.connected()) {
|
||||
connectStream();
|
||||
}
|
||||
#ifdef DEBUG_OUTPUT
|
||||
Serial.print("Client Avail: "); Serial.print(http_client.available());
|
||||
Serial.print("\tBuffer Avail: "); Serial.println(buffer.available());
|
||||
#endif
|
||||
int ret = player.tick();
|
||||
|
||||
if (ret != 0) { // some error, best to pause & rebuffer
|
||||
Serial.print("MP3 error: "); Serial.println(ret);
|
||||
player.pause(); paused = true;
|
||||
}
|
||||
if ( paused && (buffer.size() > 6000)) { // buffered, restart!
|
||||
player.resume(); paused = false;
|
||||
}
|
||||
|
||||
// Prioritize reading data from the ESP32 into the buffer (it sometimes stalls)
|
||||
if (http_client.available() && buffer.available()) {
|
||||
|
||||
uint8_t minibuff[BUFFER_SIZE];
|
||||
|
||||
int bytesread = http_client.read(minibuff, buffer.available());
|
||||
#ifdef DEBUG_OUTPUT
|
||||
Serial.print("Client read: "); Serial.print(bytesread);
|
||||
#endif
|
||||
|
||||
noInterrupts();
|
||||
for (int i=0; i<bytesread; i++) {
|
||||
buffer.push(minibuff[i]); // push every byte we read
|
||||
}
|
||||
interrupts();
|
||||
#ifdef DEBUG_OUTPUT
|
||||
Serial.println(" OK");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void writeDacs(int16_t l, int16_t r){
|
||||
uint16_t val = map(l, -32768, 32767, 0, 4095 * gain);
|
||||
analogWrite(A0, val);
|
||||
}
|
||||
|
||||
|
||||
int getMoreData(uint8_t *writeHere, int thisManyBytes){
|
||||
#ifdef DEBUG_OUTPUT
|
||||
Serial.print("Wants: "); Serial.print(thisManyBytes);
|
||||
#endif
|
||||
int toWrite = min(buffer.size(), thisManyBytes);
|
||||
#ifdef DEBUG_OUTPUT
|
||||
Serial.print(" have: "); Serial.println(toWrite);
|
||||
#endif
|
||||
// this is a bit of a hack but otherwise the decoder chokes
|
||||
if (toWrite < 128) {
|
||||
//return 0; // we'll try again later!
|
||||
}
|
||||
for (int i=0; i<toWrite; i++) {
|
||||
writeHere[i] = buffer.shift();
|
||||
}
|
||||
return toWrite;
|
||||
}
|
||||
|
||||
|
||||
bool splitURL(String url, char **host, int *port, char **path){
|
||||
Serial.println(url);
|
||||
if (url.startsWith("http://")) {
|
||||
Serial.println("Regular HTTP stream");
|
||||
url = url.substring(7);
|
||||
*port = 80;
|
||||
}
|
||||
if (url.startsWith("https://")) {
|
||||
Serial.println("Secure HTTPS stream");
|
||||
url = url.substring(8);
|
||||
*port = 443;
|
||||
}
|
||||
|
||||
// extract host before port
|
||||
int colon = url.indexOf(':');
|
||||
int slash = url.indexOf('/');
|
||||
if ((slash != -1) && (colon != -1) && (colon < slash)) {
|
||||
String host_str = url.substring(0, colon);
|
||||
*host = (char *)malloc(host_str.length()+1);
|
||||
host_str.toCharArray(*host, host_str.length()+1);
|
||||
url = url.substring(colon+1);
|
||||
// extract port before /
|
||||
slash = url.indexOf('/');
|
||||
if (slash != -1) {
|
||||
String port_str = url.substring(0, slash);
|
||||
*port = port_str.toInt();
|
||||
} else {
|
||||
Serial.println("Couldn't locate path /");
|
||||
return false;
|
||||
}
|
||||
url = url.substring(slash);
|
||||
} else {
|
||||
// extract host before /
|
||||
slash = url.indexOf('/');
|
||||
if (slash != -1) {
|
||||
String host_str = url.substring(0, slash);
|
||||
*host = (char *)malloc(host_str.length()+1);
|
||||
host_str.toCharArray(*host, host_str.length()+1);
|
||||
url = url.substring(slash);
|
||||
} else {
|
||||
Serial.println("Couldn't locate path /");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*path = (char *)malloc(url.length()+1);
|
||||
url.toCharArray(*path, url.length()+1);
|
||||
}
|
||||
|
|
@ -63,7 +63,7 @@ http://www.adafruit.com/products/14
|
|||
|
||||
// Green LED does a "sleep throb" when camera is idle. This table
|
||||
// contains the brightness levels over time (reverse for second half).
|
||||
PROGMEM byte sleepTab[] = {
|
||||
const PROGMEM byte sleepTab[] = {
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 2, 3, 4, 5, 6, 8, 10, 13,
|
||||
15, 19, 22, 26, 31, 36, 41, 47, 54, 61,
|
||||
|
|
|
|||
BIN
Adafruit_LED_Sequins/.DS_Store
vendored
BIN
Adafruit_LED_Sequins/.DS_Store
vendored
Binary file not shown.
0
Adafruit_LED_Sequins/.gemma.test.only
Normal file
0
Adafruit_LED_Sequins/.gemma.test.only
Normal file
|
|
@ -1,10 +1,10 @@
|
|||
/ Test code for Adafruit GPS modules using MTK driver
|
||||
// Test code for Adafruit GPS modules using MTK driver
|
||||
// such as www.adafruit.com/products/660 (discontinued)
|
||||
// For new use see www.adafruit.com/products/746 (needs different code)
|
||||
// help support open source hardware & software! -adafruit
|
||||
|
||||
#include <SoftSerial.h>
|
||||
SoftSerial mySerial(2, 3);
|
||||
#include <SoftwareSerial.h>
|
||||
SoftwareSerial mySerial(2, 3);
|
||||
|
||||
// Connect the GPS Power pin to 3.3V
|
||||
// Connect the GPS Ground pin to ground
|
||||
|
|
|
|||
0
Adafruit_TPL5111_Breakout/tpl5111demo/.esp8266.test.only
Normal file
0
Adafruit_TPL5111_Breakout/tpl5111demo/.esp8266.test.only
Normal file
0
Adafruit_TPL5111_Breakout/tpl5111demo/.uno.test.only
Normal file
0
Adafruit_TPL5111_Breakout/tpl5111demo/.uno.test.only
Normal file
|
|
@ -131,7 +131,7 @@ unsigned long
|
|||
currentTime = 0L;
|
||||
EthernetClient
|
||||
client;
|
||||
PROGMEM byte
|
||||
const PROGMEM byte
|
||||
sleepTab[] = { // "Sleep throb" brightness table (reverse for second half)
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 1,
|
||||
1, 1, 2, 3, 4, 5, 6, 8, 10, 13,
|
||||
|
|
|
|||
0
Adafruit_UDA1334A/SineTone/.metro_m0.test.only
Normal file
0
Adafruit_UDA1334A/SineTone/.metro_m0.test.only
Normal file
|
|
@ -199,10 +199,9 @@ void setup(void) {
|
|||
// from either mirrorOLED[] (first eye) or rotateOLED[] (others).
|
||||
// The OLED library doesn't normally use the remap reg (TFT does).
|
||||
for(e=0; e<NUM_EYES; e++) {
|
||||
eye[e].display->writeCommand(SSD1351_CMD_SETREMAP);
|
||||
eye[e].display->writeData(e ?
|
||||
rotateOLED[eyeInfo[e].rotation & 3] :
|
||||
mirrorOLED[eyeInfo[e].rotation & 3]);
|
||||
uint8_t d = e ? rotateOLED[eyeInfo[e].rotation & 3] :
|
||||
mirrorOLED[eyeInfo[e].rotation & 3];
|
||||
eye[e].display->sendCommand(SSD1351_CMD_SETREMAP, &d, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
0
Animated_NeoPixel_Glow_Fur_Scarf/.gemma.test.only
Normal file
0
Animated_NeoPixel_Glow_Fur_Scarf/.gemma.test.only
Normal file
0
AtariFruit_Joystick/.nrf52832.test.only
Normal file
0
AtariFruit_Joystick/.nrf52832.test.only
Normal file
0
Bluetooth_NeoMatrix_Snowflake/basic/.uno.test.only
Normal file
0
Bluetooth_NeoMatrix_Snowflake/basic/.uno.test.only
Normal file
|
|
@ -273,6 +273,7 @@ void SnowFlake12(uint32_t c){
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
void showAllSnowflakes(uint32_t c){
|
||||
SnowFlake1(matrix.Color(red, green, blue));
|
||||
matrix.show(); // This sends the updated pixel colors to the hardware.
|
||||
|
|
@ -322,3 +323,4 @@ void showAllSnowflakes(uint32_t c){
|
|||
matrix.show(); // This sends the updated pixel colors to the hardware.
|
||||
delay(500);
|
||||
}
|
||||
*/
|
||||
0
Buzzing_Mindfulness_Bracelet/.gemma.test.only
Normal file
0
Buzzing_Mindfulness_Bracelet/.gemma.test.only
Normal file
0
CPX_Compass/.ada_cpx.test.only
Normal file
0
CPX_Compass/.ada_cpx.test.only
Normal file
0
Chirping_Plush_Owl_Toy/.gemma.test.only
Normal file
0
Chirping_Plush_Owl_Toy/.gemma.test.only
Normal file
0
Close_Encounters_Hat/.gemma_m0.test.only
Normal file
0
Close_Encounters_Hat/.gemma_m0.test.only
Normal file
0
Crickit_AdafruitIO/crickit_io/.esp8266.test.only
Normal file
0
Crickit_AdafruitIO/crickit_io/.esp8266.test.only
Normal file
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue