Merge branch 'master' into patch-1
This commit is contained in:
commit
c46f3d3e12
|
@ -13,6 +13,29 @@ on:
|
|||
|
||||
jobs:
|
||||
|
||||
build-rp2040:
|
||||
name: Build RP2040
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
chunk: [0, 1, 2, 3, 4]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: true
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: '3.x'
|
||||
- name: Build Sketches
|
||||
env:
|
||||
TRAVIS_BUILD_DIR: ${{ github.workspace }}
|
||||
TRAVIS_TAG: ${{ github.ref }}
|
||||
BUILD_TYPE: build_rp2040
|
||||
BUILD_MOD: 5
|
||||
BUILD_REM: ${{ matrix.chunk }}
|
||||
run: |
|
||||
bash ./tests/common.sh
|
||||
|
||||
build-esp8266:
|
||||
name: Build ESP8266
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -36,7 +59,6 @@ jobs:
|
|||
run: |
|
||||
bash ./tests/common.sh
|
||||
|
||||
|
||||
build-esp32:
|
||||
name: Build ESP-32
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -84,7 +106,11 @@ jobs:
|
|||
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./mp3
|
||||
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./aac
|
||||
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./wav
|
||||
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./flac
|
||||
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./mod
|
||||
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./wav
|
||||
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./midi
|
||||
valgrind --leak-check=full --track-origins=yes -v --error-limit=no --show-leak-kinds=all --error-exitcode=999 ./opus
|
||||
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
|
@ -108,5 +134,5 @@ jobs:
|
|||
- name: Run codespell
|
||||
uses: codespell-project/actions-codespell@master
|
||||
with:
|
||||
skip: ./src/libmad,./src/libhelix-aac,./src/libopus
|
||||
skip: ./src/libmad,./src/libhelix-aac,./src/libopus,./src/libflac
|
||||
ignore_words_list: ESP8266,esp8266,esp,dout,DOUT,ser,ans,inout,numer,hist
|
||||
|
|
48
README.md
48
README.md
|
@ -1,4 +1,4 @@
|
|||
# ESP8266Audio - supports ESP8266 & ESP32 & Raspberry Pi RP2040[![Gitter](https://badges.gitter.im/ESP8266Audio/community.svg)](https://gitter.im/ESP8266Audio/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
# ESP8266Audio - supports ESP8266 & ESP32 & Raspberry Pi Pico RP2040 [![Gitter](https://badges.gitter.im/ESP8266Audio/community.svg)](https://gitter.im/ESP8266Audio/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
Arduino library for parsing and decoding MOD, WAV, MP3, FLAC, MIDI, AAC, and RTTL files and playing them on an I2S DAC or even using a software-simulated delta-sigma DAC with dynamic 32x-128x oversampling.
|
||||
|
||||
ESP8266 is fully supported and most mature, but ESP32 is also mostly there with built-in DAC as well as external ones.
|
||||
|
@ -6,34 +6,25 @@ ESP8266 is fully supported and most mature, but ESP32 is also mostly there with
|
|||
For real-time, autonomous speech synthesis, check out [ESP8266SAM](https://github.com/earlephilhower/ESP8266SAM), a library which uses this one and a port of an ancient format-based synthesis program to allow your ESP8266 to talk with low memory and no network required.
|
||||
|
||||
## Disclaimer
|
||||
All this code is released under the GPL, and all of it is to be used at your own risk. If you find any bugs, please let me know via the GitHub issue tracker or drop me an email. The MOD and MP3 routines were taken from StellaPlayer and libMAD respectively. The software I2S delta-sigma 32x oversampling DAC was my own creation, and sounds quite good if I do say so myself.
|
||||
All this code is released under the GPL, and all of it is to be used at your own risk. If you find any bugs, please let me know via the GitHub issue tracker or drop me an email.
|
||||
|
||||
The AAC decode code is from the Helix project and licensed under RealNetwork's RSPL license. For commercial use you're still going to need the usual AAC licensing from [Via Licensing](http://www.via-corp.com/us/en/licensing/aac/overview.html).
|
||||
|
||||
On the ESP32, AAC-SBR is supported (many webradio stations use this to reduce bandwidth even further). The ESP8266, however, does not support it due to a lack of onboard RAM.
|
||||
|
||||
MIDI decoding comes from a highly ported [MIDITONES](https://github.com/LenShustek/miditones) combined with a massively memory-optimized [TinySoundFont](https://github.com/schellingb/TinySoundFont), see the respective source files for more information.
|
||||
|
||||
Opus, OGG, and OpusFile are from [Xiph.org](https://xiph.org) with the Xiph license and patent described in src/{opusfile,libggg,libopus}/COPYING.. **NOTE** Opus decoding currently only works on the ESP32 due to the large memory requirements of opusfile. PRs to rewrite it to be less memory intensive would be much appreciated.
|
||||
* The MOD and MP3 routines were taken from StellarPlayer and libMAD respectively.
|
||||
* The software I2S delta-sigma 32x oversampling DAC was my own creation, and sounds quite good if I do say so myself.
|
||||
* The AAC decode code is from the Helix project and licensed under RealNetwork's RSPL license. For commercial use you're still going to need the usual AAC licensing from [Via Licensing](http://www.via-corp.com/us/en/licensing/aac/overview.html). On the ESP32, AAC-SBR is supported (many webradio stations use this to reduce bandwidth even further). The ESP8266, however, does not support it due to a lack of onboard RAM.
|
||||
* MIDI decoding comes from a highly ported [MIDITONES](https://github.com/LenShustek/miditones) combined with a massively memory-optimized [TinySoundFont](https://github.com/schellingb/TinySoundFont), see the respective source files for more information.
|
||||
* Opus, OGG, and OpusFile are from [Xiph.org](https://xiph.org) with the Xiph license and patent described in src/{opusfile,libggg,libopus}/COPYING.. **NOTE** Opus decoding currently only works on the ESP32 due to the large memory requirements of opusfile. PRs to rewrite it to be less memory intensive would be much appreciated.
|
||||
|
||||
## Neat Things People Have Done With ESP8266Audio
|
||||
If you have a neat use for this library, [I'd love to hear about it](mailto:earlephilhower@yahoo.com)!
|
||||
|
||||
My personal use of the ESP8266Audio library is only to drive a 3D-printed, network-time-setting alarm clock for my kids which can play an MP3 instead of a bell to wake them up, called [Psychoclock](https://github.com/earlephilhower/psychoclock).
|
||||
|
||||
Harald Sattler has built a neat German [word clock with MP3 alarm](http://www.harald-sattler.de/html/mini-wecker.htm). Detailed discussion on the process and models are included.
|
||||
|
||||
Erich Heinemann has developed a Stomper (instrument for playing samples in real-time during a live stage performance) that you can find more info about [here](https://github.com/ErichHeinemann/hman-stomper).
|
||||
|
||||
Dagnall53 has integrated this into a really neat MQTT based model train controller to add sounds to his set. More info is available [here](https://github.com/dagnall53/ESPMQTTRocnetSound), including STL files for 3D printed components!
|
||||
|
||||
JohannesMTC has built a similar project especially for model trains: https://github.com/JohannesMTC/ESP32_MAS
|
||||
|
||||
A neat MQTT-driven ESP8266 light-and-sound device (alarm? toy? who can say!) was built by @CosmicMac, available at https://github.com/CosmicMac/ESParkle
|
||||
|
||||
A very interesting "linear clock" with a stepper motor, NTP time keeping, and configurable recorded chimes with schematics, 3D printer plans, and source code, is now available https://janderogee.com/projects/linear_clock/linear_clock.htm
|
||||
|
||||
Source and instructions for a gorgeous wooden MP3-playing clock, FM radio and a walkie-talkie using the ESP8266 and AVR microcontrollers is available https://github.com/zduka/mp3-player
|
||||
* My personal use of the ESP8266Audio library is only to drive a 3D-printed, network-time-setting alarm clock for my kids which can play an MP3 instead of a bell to wake them up, called [Psychoclock](https://github.com/earlephilhower/psychoclock).
|
||||
* Harald Sattler has built a neat German [word clock with MP3 alarm](http://www.harald-sattler.de/html/mini-wecker.htm). Detailed discussion on the process and models are included.
|
||||
* Erich Heinemann has developed a Stomper (instrument for playing samples in real-time during a live stage performance) that you can find more info about [here](https://github.com/ErichHeinemann/hman-stomper).
|
||||
* Dagnall53 has integrated this into a really neat MQTT based model train controller to add sounds to his set. More info is available [here](https://github.com/dagnall53/ESPMQTTRocnetSound), including STL files for 3D printed components!
|
||||
* JohannesMTC has built a similar project especially for model trains: https://github.com/JohannesMTC/ESP32_MAS
|
||||
* A neat MQTT-driven ESP8266 light-and-sound device (alarm? toy? who can say!) was built by @CosmicMac, available at https://github.com/CosmicMac/ESParkle
|
||||
* A very interesting "linear clock" with a stepper motor, NTP time keeping, and configurable recorded chimes with schematics, 3D printer plans, and source code, is now available https://janderogee.com/projects/linear_clock/linear_clock.htm
|
||||
* Source and instructions for a gorgeous wooden MP3-playing clock, FM radio and a walkie-talkie using the ESP8266 and AVR microcontrollers is available https://github.com/zduka/mp3-player
|
||||
|
||||
## Prerequisites
|
||||
First, make sure you are running the 2.6.3/later or GIT head version of the Arduino libraries for ESP8266, or the latest ESP32 SDK from Espressif.
|
||||
|
@ -181,7 +172,7 @@ I've used several versions of PCM5102 DAC boards purchased from eBay. They've a
|
|||
|
||||
|
||||
### Others
|
||||
There are many other variants out there, and they should all work reasonably well with this code and the ESP8266. Please be certain you've read the datasheet and are applying proper input voltages, and be sure to tie off any unused inputs to GND or VCC as appropriate. LEaving an input pin floating on any integrated circuit can cause unstable operation as it may pick up noise from the environment (very low input capacitance) and cause havoc with internal IC settings.
|
||||
There are many other variants out there, and they should all work reasonably well with this code and the ESP8266. Please be certain you've read the datasheet and are applying proper input voltages, and be sure to tie off any unused inputs to GND or VCC as appropriate. Leaving an input pin floating on any integrated circuit can cause unstable operation as it may pick up noise from the environment (very low input capacitance) and cause havoc with internal IC settings.
|
||||
|
||||
## Software I2S Delta-Sigma DAC (i.e. playing music with a single transistor and speaker)
|
||||
For the best fidelity, and stereo to boot, spend the money on a real I2S DAC. Adafruit makes a great mono one with amplifier, and you can find stereo unamplified ones on eBay or elsewhere quite cheaply. However, thanks to the software delta-sigma DAC with 32x oversampling (up to 128x if the audio rate is low enough) you can still have pretty good sound!
|
||||
|
@ -216,7 +207,7 @@ USB-5V -- Speaker + Terminal
|
|||
|
||||
*NOTE*: A prior version of this schematic had a direct connection from the ESP8266 to the base of the transistor. While this does provide the maximum amplitude, it also can draw more current from the 8266 than is safe, and can also cause the transistor to overheat.
|
||||
|
||||
As of the latest ESP8266Audio release, with the software delta-sigma DAC the LRCLK and BCLK pins *can* be used by an application. Simply use normal `pinMode` and `dicitalWrite` or `digitalRead` as desired.
|
||||
As of the latest ESP8266Audio release, with the software delta-sigma DAC the LRCLK and BCLK pins *can* be used by an application. Simply use normal `pinMode` and `digitalWrite` or `digitalRead` as desired.
|
||||
|
||||
### High pitched buzzing with the 1-T circuit
|
||||
The 1-T amp can _NOT_ drive any sort of amplified speaker. If there is a power or USB input to the speaker, or it has lights or Bluetooth or a battery, it can _NOT_ be used with this circuit.
|
||||
|
@ -249,7 +240,7 @@ ESP Pin -------|____|--------+
|
|||
|
|
||||
Ground ---------------------+
|
||||
```
|
||||
For ESP8266 with red LED (~1.9Vf drop) you need minimum 150Ohm resistor (12mA max per pin), and output pin is fixed (GPIO3/RX0).On ESP32 it is confgurable with `AudioOutputSPDIF(gpio_num)`.
|
||||
For ESP8266 with red LED (~1.9Vf drop) you need minimum 150Ohm resistor (12mA max per pin), and output pin is fixed (GPIO3/RX0).On ESP32 it is configurable with `AudioOutputSPDIF(gpio_num)`.
|
||||
|
||||
## Using external SPI RAM to increase buffer
|
||||
A class allows you to use a 23lc1024 SPI RAM from Microchip as input buffer. This chip connects to ESP8266 HSPI port and provides a large buffer to help avoid hiccus in playback of web streams.
|
||||
|
@ -265,10 +256,11 @@ I've been told the Wemos SD card shield uses GPIO15 as the SD chip select. This
|
|||
There's no ESP8266-specific code in the AudioGenerator routines, so porting to other controllers should be relatively easy assuming they have the same endianness as the Xtensa core used. Drop me a line if you're doing this, I may be able to help point you in the right direction.
|
||||
|
||||
## Thanks
|
||||
Thanks to the authors of StellaPlayer and libMAD for releasing their code freely, and to the maintainers and contributors to the ESP8266 Arduino port.
|
||||
Thanks to the authors of StellarPlayer and libMAD for releasing their code freely, and to the maintainers and contributors to the ESP8266 Arduino port.
|
||||
|
||||
Also, big thanks to @tueddy for getting the initial ESP32 porting into the tree!
|
||||
|
||||
-Earle F. Philhower, III
|
||||
|
||||
earlephilhower@yahoo.com
|
||||
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
#include <Arduino.h>
|
||||
#ifdef ESP32
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#define WIFI_OFF
|
||||
class __x { public: __x() {}; void mode() {}; };
|
||||
__x WiFi;
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#include "AudioFileSourceSD.h"
|
||||
#include "AudioOutputSPDIF.h"
|
||||
#include "AudioGeneratorFLAC.h"
|
||||
|
@ -66,3 +70,5 @@ void loop() {
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -6,7 +6,13 @@
|
|||
}
|
||||
void loop() {}
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#define WIFI_OFF
|
||||
class __x { public: __x() {}; void mode() {}; };
|
||||
__x WiFi;
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
#endif
|
||||
#include <AudioOutputI2S.h>
|
||||
#include <AudioGeneratorMIDI.h>
|
||||
#include <AudioFileSourceLittleFS.h>
|
||||
|
@ -42,7 +48,6 @@ void loop()
|
|||
{
|
||||
if (midi->isRunning()) {
|
||||
if (!midi->loop()) {
|
||||
uint32_t e = millis();
|
||||
midi->stop();
|
||||
}
|
||||
} else {
|
||||
|
|
|
@ -1,4 +1,11 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
// Do not build on GCC8, GCC8 has a compiler bug
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040) || ((__GNUC__ == 8) && (__XTENSA__))
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#ifdef ESP32
|
||||
#include <WiFi.h>
|
||||
#include "SPIFFS.h"
|
||||
|
@ -44,7 +51,6 @@ void loop()
|
|||
{
|
||||
if (midi->isRunning()) {
|
||||
if (!midi->loop()) {
|
||||
uint32_t e = millis();
|
||||
midi->stop();
|
||||
}
|
||||
} else {
|
||||
|
@ -53,4 +59,4 @@ void loop()
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
#include "AudioFileSourcePROGMEM.h"
|
||||
#include "AudioGeneratorMOD.h"
|
||||
#include "AudioOutputI2S.h"
|
||||
#ifdef ESP32
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#define WIFI_OFF
|
||||
class __x { public: __x() {}; void mode() {}; };
|
||||
__x WiFi;
|
||||
#elif defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,47 @@
|
|||
#include <Arduino.h>
|
||||
#include "AudioFileSourcePROGMEM.h"
|
||||
#include "AudioGeneratorMOD.h"
|
||||
#include "AudioOutputPWM.h"
|
||||
|
||||
#if !defined(ARDUINO_ARCH_RP2040)
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
Serial.printf("Only for the RP2040/Raspberry Pi Pico\n");
|
||||
}
|
||||
|
||||
void loop() {
|
||||
}
|
||||
#else
|
||||
|
||||
// 5_steps.mod sample from the mod archive: https://modarchive.org/
|
||||
#include "5steps.h"
|
||||
|
||||
AudioGeneratorMOD *mod;
|
||||
AudioFileSourcePROGMEM *file;
|
||||
AudioOutputPWM *out;
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
|
||||
audioLogger = &Serial;
|
||||
file = new AudioFileSourcePROGMEM(steps_mod, sizeof(steps_mod));
|
||||
out = new AudioOutputPWM();
|
||||
mod = new AudioGeneratorMOD();
|
||||
mod->SetBufferSize(3*1024);
|
||||
mod->SetSampleRate(44100);
|
||||
mod->SetStereoSeparation(32);
|
||||
mod->begin(file, out);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (mod->isRunning()) {
|
||||
if (!mod->loop()) mod->stop();
|
||||
} else {
|
||||
Serial.printf("MOD done\n");
|
||||
delay(1000);
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,4 +1,9 @@
|
|||
#include <Arduino.h>
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#ifdef ESP32
|
||||
#include <WiFi.h>
|
||||
#include "SPIFFS.h"
|
||||
|
@ -70,3 +75,4 @@ void loop()
|
|||
delay(1000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#ifdef ESP32
|
||||
#include "SPIFFS.h"
|
||||
#endif
|
||||
|
@ -97,3 +101,4 @@ void loop()
|
|||
delay(1000);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#ifdef ESP32
|
||||
#include <WiFi.h>
|
||||
#include "SPIFFS.h"
|
||||
|
@ -39,3 +43,5 @@ void loop()
|
|||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,11 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
#ifdef ESP32
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
|
||||
#else
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
|
@ -104,4 +109,4 @@ void loop()
|
|||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include <Arduino.h>
|
||||
#ifdef ARDUINO_ARCH_RP2040
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#ifdef ESP32
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
|
@ -140,3 +144,5 @@ void loop()
|
|||
ESP.restart();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
#include <Arduino.h>
|
||||
#ifdef ESP32
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
|
@ -101,4 +105,4 @@ void loop()
|
|||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,7 +29,8 @@ class AudioOutputNullSlow : public AudioOutput
|
|||
AudioOutputNullSlow() { };
|
||||
~AudioOutputNullSlow() {};
|
||||
virtual bool begin() { samples = 0; startms = millis(); return true; }
|
||||
virtual bool ConsumeSample([[maybe_unused]] int16_t sample[2]) {
|
||||
virtual bool ConsumeSample(int16_t sample[2]) {
|
||||
(void) sample;
|
||||
// return false (= output buffer full)
|
||||
// sometimes to let the main loop running
|
||||
constexpr int everylog2 = 10;
|
||||
|
|
|
@ -1,6 +1,10 @@
|
|||
#include <Arduino.h>
|
||||
|
||||
#ifdef ESP32
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
|
@ -9,10 +13,10 @@
|
|||
#include "AudioFileSourceBuffer.h"
|
||||
#include "AudioGeneratorMP3.h"
|
||||
#if AUDIO
|
||||
#pragma message("Outputting audio")
|
||||
// #pragma message("Outputting audio")
|
||||
#include "AudioOutputLinuxDSP.h"
|
||||
#else
|
||||
#pragma message("No audio")
|
||||
// #pragma message("No audio")
|
||||
#include "AudioOutputNullSlow.h"
|
||||
#endif
|
||||
|
||||
|
@ -115,4 +119,4 @@ void loop()
|
|||
delay(1000);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -2,7 +2,14 @@
|
|||
// https://github.com/going-digital/Talkie/blob/master/Talkie/examples/Vocab_US_Clock/Vocab_US_Clock.ino
|
||||
// Released under GPL v2
|
||||
|
||||
#ifdef ESP32
|
||||
#include <Arduino.h>
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
|
@ -183,3 +190,4 @@ void loop()
|
|||
sayTime(tmstruct.tm_hour, tmstruct.tm_min, talkie);
|
||||
delay(1000);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -19,7 +19,15 @@
|
|||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#ifdef ESP32
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
void setup() {}
|
||||
void loop() {}
|
||||
#else
|
||||
|
||||
// ESP8266 server.available() is now server.accept()
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
#if defined(ESP32)
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
#include <ESP8266WiFi.h>
|
||||
|
@ -439,3 +447,4 @@ void loop()
|
|||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
// Nothing here
|
||||
#else
|
||||
#ifdef ESP32
|
||||
#include <WiFi.h>
|
||||
#else
|
||||
|
@ -308,7 +311,4 @@ void Read4Int(char *str, byte *p)
|
|||
str += ParseInt(str, &i); p[2] = i; if (*str) str++;
|
||||
str += ParseInt(str, &i); p[3] = i;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -23,6 +23,7 @@ AudioOutput KEYWORD1
|
|||
AudioOutputI2S KEYWORD1
|
||||
AudioOutputI2SNoDAC KEYWORD1
|
||||
AudioOutputI2SClass KEYWORD1
|
||||
AudioOutputPWM KEYWORD1
|
||||
AudioOutputNull KEYWORD1
|
||||
AudioOutputBuffer KEYWORD1
|
||||
AudioOutputSerialWAV KEYWORD1
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"type": "git",
|
||||
"url": "https://github.com/earlephilhower/ESP8266Audio"
|
||||
},
|
||||
"version": "1.9.6",
|
||||
"version": "1.9.7",
|
||||
"homepage": "https://github.com/earlephilhower/ESP8266Audio",
|
||||
"frameworks": "Arduino",
|
||||
"examples": [
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
name=ESP8266Audio
|
||||
version=1.9.6
|
||||
version=1.9.7
|
||||
author=Earle F. Philhower, III
|
||||
maintainer=Earle F. Philhower, III
|
||||
sentence=Audio file and I2S sound playing routines for ESP8266, ESP32, and Raspberry Pi Pico RP2040
|
||||
|
|
|
@ -25,14 +25,14 @@ AudioFileSourceFunction::AudioFileSourceFunction(float sec, uint16_t channels, u
|
|||
uint32_t len = uint32_t(sec * (float)bytes_per_sec);
|
||||
|
||||
// RIFF chunk
|
||||
strncpy(wav_header.riff.chunk_id, "RIFF", 4);
|
||||
memcpy(wav_header.riff.chunk_id, "RIFF", 4);
|
||||
wav_header.riff.chunk_size = 4 // size of riff chunk w/o chunk_id and chunk_size
|
||||
+ 8 + 16 // size of format chunk
|
||||
+ 8 + len; // size of data chunk
|
||||
strncpy(wav_header.riff.format, "WAVE", 4);
|
||||
memcpy(wav_header.riff.format, "WAVE", 4);
|
||||
|
||||
// format chunk
|
||||
strncpy(wav_header.format.chunk_id, "fmt ", 4);
|
||||
memcpy(wav_header.format.chunk_id, "fmt ", 4);
|
||||
wav_header.format.chunk_size = 16;
|
||||
wav_header.format.format_tag = 0x0001; // PCM
|
||||
wav_header.format.channels = channels;
|
||||
|
@ -42,7 +42,7 @@ AudioFileSourceFunction::AudioFileSourceFunction(float sec, uint16_t channels, u
|
|||
wav_header.format.bits_per_sample = bits_per_sample;
|
||||
|
||||
// data chunk
|
||||
strncpy(wav_header.data.chunk_id, "data", 4);
|
||||
memcpy(wav_header.data.chunk_id, "data", 4);
|
||||
wav_header.data.chunk_size = len;
|
||||
|
||||
funcs.reserve(channels);
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
|
||||
#if defined(ESP32) || defined(ESP8266)
|
||||
|
||||
#ifdef _GNU_SOURCE
|
||||
#undef _GNU_SOURCE
|
||||
#endif
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "AudioFileSourceICYStream.h"
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
#include "AudioFileSource.h"
|
||||
#include "AudioFileSourceFS.h"
|
||||
|
||||
// Yes, I know SPIFFS is deprecated
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
class AudioFileSourceSPIFFS : public AudioFileSourceFS
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -62,6 +62,9 @@ bool AudioGeneratorFLAC::begin(AudioFileSource *source, AudioOutput *output)
|
|||
|
||||
output->begin();
|
||||
running = true;
|
||||
lastSample[0] = 0;
|
||||
lastSample[1] = 0;
|
||||
channels = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -71,7 +74,7 @@ bool AudioGeneratorFLAC::loop()
|
|||
|
||||
if (!running) goto done;
|
||||
|
||||
if (!output->ConsumeSample(lastSample)) goto done; // Try and send last buffered sample
|
||||
if (channels && !output->ConsumeSample(lastSample)) goto done; // Try and send last buffered sample
|
||||
|
||||
do {
|
||||
if (buffPtr == buffLen) {
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
|
||||
#include "AudioGeneratorMIDI.h"
|
||||
|
||||
#if __GNUC__ == 8
|
||||
#if (__GNUC__ == 8) && (__XTENSA__)
|
||||
// Do not build, GCC8 has a compiler bug
|
||||
#else // __GNUC__ == 8
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#ifndef _AUDIOGENERATORMIDI_H
|
||||
#define _AUDIOGENERATORMIDI_H
|
||||
|
||||
#if __GNUC__ == 8
|
||||
#if (__GNUC__ == 8) && (__XTENSA__)
|
||||
// Do not build, GCC8 has a compiler bug
|
||||
#else // __GNUC__ == 8
|
||||
|
||||
|
|
|
@ -791,7 +791,7 @@ void AudioGeneratorMOD::GetSample(int16_t sample[2])
|
|||
Mixer.channelSampleNumber[channel] != FatBuffer.channelSampleNumber[channel]) {
|
||||
|
||||
uint32_t toRead = Mixer.sampleEnd[Mixer.channelSampleNumber[channel]] - samplePointer + 1;
|
||||
if (toRead > fatBufferSize) toRead = fatBufferSize;
|
||||
if (toRead > (uint32_t)fatBufferSize) toRead = fatBufferSize;
|
||||
|
||||
if (!file->seek(samplePointer, SEEK_SET)) {
|
||||
stop();
|
||||
|
|
|
@ -248,6 +248,10 @@ retry:
|
|||
running = false;
|
||||
goto done;
|
||||
}
|
||||
if (lastChannels == 1)
|
||||
{
|
||||
lastSample[1] = lastSample[0];
|
||||
}
|
||||
} while (running && output->ConsumeSample(lastSample));
|
||||
|
||||
done:
|
||||
|
|
|
@ -127,7 +127,7 @@ bool AudioGeneratorWAV::ReadWAVInfo()
|
|||
return false;
|
||||
};
|
||||
if (u32 != 0x46464952) {
|
||||
Serial.printf_P(PSTR("AudioGeneratorWAV::ReadWAVInfo: cannot read WAV, invalid RIFF header, got: %08X \n"), (uint32_t) u32);
|
||||
Serial.printf_P(PSTR("AudioGeneratorWAV::ReadWAVInfo: cannot read WAV, invalid RIFF header\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ bool AudioGeneratorWAV::ReadWAVInfo()
|
|||
return false;
|
||||
};
|
||||
if (u32 != 0x45564157) {
|
||||
Serial.printf_P(PSTR("AudioGeneratorWAV::ReadWAVInfo: cannot read WAV, invalid WAVE header, got: %08X \n"), (uint32_t) u32);
|
||||
Serial.printf_P(PSTR("AudioGeneratorWAV::ReadWAVInfo: cannot read WAV, invalid WAVE header\n"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,9 +85,31 @@ AudioOutputI2S::AudioOutputI2S(int port, int output_mode, int dma_buf_count, int
|
|||
bclkPin = 26;
|
||||
wclkPin = 25;
|
||||
doutPin = 22;
|
||||
mclkPin = 0;
|
||||
SetGain(1.0);
|
||||
}
|
||||
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
AudioOutputI2S::AudioOutputI2S(long sampleRate, pin_size_t sck, pin_size_t data) {
|
||||
i2sOn = false;
|
||||
mono = false;
|
||||
bps = 16;
|
||||
channels = 2;
|
||||
hertz = sampleRate;
|
||||
bclkPin = sck;
|
||||
doutPin = data;
|
||||
mclkPin = 0;
|
||||
use_mclk = false;
|
||||
swap_clocks = false;
|
||||
SetGain(1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
AudioOutputI2S::~AudioOutputI2S()
|
||||
{
|
||||
stop();
|
||||
}
|
||||
|
||||
bool AudioOutputI2S::SetPinout()
|
||||
{
|
||||
#ifdef ESP32
|
||||
|
@ -95,6 +117,9 @@ bool AudioOutputI2S::SetPinout()
|
|||
return false; // Not allowed
|
||||
|
||||
i2s_pin_config_t pins = {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
.mck_io_num = mclkPin,
|
||||
#endif
|
||||
.bck_io_num = bclkPin,
|
||||
.ws_io_num = wclkPin,
|
||||
.data_out_num = doutPin,
|
||||
|
@ -105,6 +130,8 @@ bool AudioOutputI2S::SetPinout()
|
|||
(void)bclkPin;
|
||||
(void)wclkPin;
|
||||
(void)doutPin;
|
||||
(void)mclkPin;
|
||||
(void)use_mclk;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
@ -119,33 +146,20 @@ bool AudioOutputI2S::SetPinout(int bclk, int wclk, int dout)
|
|||
|
||||
return true;
|
||||
}
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
AudioOutputI2S::AudioOutputI2S(long sampleRate, pin_size_t sck, pin_size_t data) {
|
||||
i2sOn = false;
|
||||
mono = false;
|
||||
bps = 16;
|
||||
channels = 2;
|
||||
hertz = sampleRate;
|
||||
bclkPin = sck;
|
||||
doutPin = data;
|
||||
SetGain(1.0);
|
||||
}
|
||||
#endif
|
||||
|
||||
AudioOutputI2S::~AudioOutputI2S()
|
||||
bool AudioOutputI2S::SetPinout(int bclk, int wclk, int dout, int mclk)
|
||||
{
|
||||
bclkPin = bclk;
|
||||
wclkPin = wclk;
|
||||
doutPin = dout;
|
||||
#ifdef ESP32
|
||||
if (i2sOn) {
|
||||
audioLogger->printf("UNINSTALL I2S\n");
|
||||
i2s_driver_uninstall((i2s_port_t)portNo); //stop & destroy i2s driver
|
||||
}
|
||||
#elif defined(ESP8266)
|
||||
mclkPin = mclk;
|
||||
if (i2sOn)
|
||||
i2s_end();
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
stop();
|
||||
return SetPinout();
|
||||
#else
|
||||
(void)mclk;
|
||||
#endif
|
||||
i2sOn = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputI2S::SetRate(int hz)
|
||||
|
@ -159,7 +173,7 @@ bool AudioOutputI2S::SetRate(int hz)
|
|||
#elif defined(ESP8266)
|
||||
i2s_set_rate(AdjustI2SRate(hz));
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
I2S.setFrequency(hz);
|
||||
i2s.setFrequency(hz);
|
||||
#endif
|
||||
}
|
||||
return true;
|
||||
|
@ -191,6 +205,26 @@ bool AudioOutputI2S::SetLsbJustified(bool lsbJustified)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputI2S::SwapClocks(bool swap_clocks)
|
||||
{
|
||||
if (i2sOn) {
|
||||
return false; // Not allowed
|
||||
}
|
||||
this->swap_clocks = swap_clocks;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputI2S::SetMclk(bool enabled){
|
||||
(void)enabled;
|
||||
#ifdef ESP32
|
||||
if (output_mode == INTERNAL_DAC || output_mode == INTERNAL_PDM)
|
||||
return false; // Not allowed
|
||||
|
||||
use_mclk = enabled;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputI2S::begin(bool txDAC)
|
||||
{
|
||||
#ifdef ESP32
|
||||
|
@ -249,7 +283,13 @@ bool AudioOutputI2S::begin(bool txDAC)
|
|||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // lowest interrupt priority
|
||||
.dma_buf_count = dma_buf_count,
|
||||
.dma_buf_len = 128,
|
||||
.use_apll = use_apll // Use audio PLL
|
||||
.use_apll = use_apll, // Use audio PLL
|
||||
.tx_desc_auto_clear = true, // Silence on underflow
|
||||
.fixed_mclk = use_mclk, // Unused
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
.mclk_multiple = I2S_MCLK_MULTIPLE_256, // Unused
|
||||
.bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT // Use bits per sample
|
||||
#endif
|
||||
};
|
||||
audioLogger->printf("+%d %p\n", portNo, &i2s_config_dac);
|
||||
if (i2s_driver_install((i2s_port_t)portNo, &i2s_config_dac, 0, NULL) != ESP_OK)
|
||||
|
@ -294,9 +334,12 @@ bool AudioOutputI2S::begin(bool txDAC)
|
|||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
(void)txDAC;
|
||||
if (!i2sOn) {
|
||||
I2S.setBCLK(bclkPin);
|
||||
I2S.setDOUT(doutPin);
|
||||
I2S.begin(hertz);
|
||||
i2s.setBCLK(bclkPin);
|
||||
i2s.setDATA(doutPin);
|
||||
if (swap_clocks) {
|
||||
i2s.swapClocks();
|
||||
}
|
||||
i2s.begin(hertz);
|
||||
}
|
||||
#endif
|
||||
i2sOn = true;
|
||||
|
@ -344,7 +387,8 @@ bool AudioOutputI2S::ConsumeSample(int16_t sample[2])
|
|||
uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff);
|
||||
return i2s_write_sample_nb(s32); // If we can't store it, return false. OTW true
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
return !!I2S.write((void*)ms, 4);
|
||||
uint32_t s32 = ((Amplify(ms[RIGHTCHANNEL])) << 16) | (Amplify(ms[LEFTCHANNEL]) & 0xffff);
|
||||
return !!i2s.write((int32_t)s32, false);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -362,7 +406,7 @@ void AudioOutputI2S::flush()
|
|||
}
|
||||
}
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
I2S.flush();
|
||||
i2s.flush();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -373,8 +417,12 @@ bool AudioOutputI2S::stop()
|
|||
|
||||
#ifdef ESP32
|
||||
i2s_zero_dma_buffer((i2s_port_t)portNo);
|
||||
audioLogger->printf("UNINSTALL I2S\n");
|
||||
i2s_driver_uninstall((i2s_port_t)portNo); //stop & destroy i2s driver
|
||||
#elif defined(ESP8266)
|
||||
i2s_end();
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
I2S.end();
|
||||
i2s.end();
|
||||
#endif
|
||||
i2sOn = false;
|
||||
return true;
|
||||
|
|
|
@ -22,17 +22,23 @@
|
|||
|
||||
#include "AudioOutput.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#include <Arduino.h>
|
||||
#include <I2S.h>
|
||||
#endif
|
||||
|
||||
class AudioOutputI2S : public AudioOutput
|
||||
{
|
||||
public:
|
||||
#if defined(ESP32) || defined(ESP8266)
|
||||
AudioOutputI2S(int port=0, int output_mode=EXTERNAL_I2S, int dma_buf_count = 8, int use_apll=APLL_DISABLE);
|
||||
bool SetPinout(int bclkPin, int wclkPin, int doutPin);
|
||||
enum : int { APLL_AUTO = -1, APLL_ENABLE = 1, APLL_DISABLE = 0 };
|
||||
enum : int { EXTERNAL_I2S = 0, INTERNAL_DAC = 1, INTERNAL_PDM = 2 };
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
AudioOutputI2S(long sampleRate = 44100, pin_size_t sck = 26, pin_size_t data = 28);
|
||||
#endif
|
||||
bool SetPinout(int bclkPin, int wclkPin, int doutPin);
|
||||
bool SetPinout(int bclkPin, int wclkPin, int doutPin, int mclkPin);
|
||||
virtual ~AudioOutputI2S() override;
|
||||
virtual bool SetRate(int hz) override;
|
||||
virtual bool SetBitsPerSample(int bits) override;
|
||||
|
@ -45,6 +51,8 @@ class AudioOutputI2S : public AudioOutput
|
|||
bool begin(bool txDAC);
|
||||
bool SetOutputModeMono(bool mono); // Force mono output no matter the input
|
||||
bool SetLsbJustified(bool lsbJustified); // Allow supporting non-I2S chips, e.g. PT8211
|
||||
bool SetMclk(bool enabled); // Enable MCLK output (if supported)
|
||||
bool SwapClocks(bool swap_clocks); // Swap BCLK and WCLK
|
||||
|
||||
protected:
|
||||
bool SetPinout();
|
||||
|
@ -56,6 +64,8 @@ class AudioOutputI2S : public AudioOutput
|
|||
bool i2sOn;
|
||||
int dma_buf_count;
|
||||
int use_apll;
|
||||
bool use_mclk;
|
||||
bool swap_clocks;
|
||||
// We can restore the old values and free up these pins when in NoDAC mode
|
||||
uint32_t orig_bck;
|
||||
uint32_t orig_ws;
|
||||
|
@ -63,4 +73,9 @@ class AudioOutputI2S : public AudioOutput
|
|||
uint8_t bclkPin;
|
||||
uint8_t wclkPin;
|
||||
uint8_t doutPin;
|
||||
uint8_t mclkPin;
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
I2S i2s;
|
||||
#endif
|
||||
};
|
||||
|
|
|
@ -119,9 +119,6 @@ bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2])
|
|||
|
||||
// Either send complete pulse stream or nothing
|
||||
#ifdef ESP32
|
||||
//"i2s_write_bytes" has been removed in the ESP32 Arduino 2.0.0, use "i2s_write" instead.
|
||||
// if (!i2s_write_bytes((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), 0))
|
||||
|
||||
size_t i2s_bytes_written;
|
||||
i2s_write((i2s_port_t)portNo, (const char *)dsBuff, sizeof(uint32_t) * (oversample/32), &i2s_bytes_written, 0);
|
||||
if (!i2s_bytes_written){
|
||||
|
@ -134,9 +131,8 @@ bool AudioOutputI2SNoDAC::ConsumeSample(int16_t sample[2])
|
|||
for (int i = 32; i < oversample; i+=32)
|
||||
i2s_write_sample( dsBuff[i / 32]);
|
||||
#elif defined(ARDUINO_ARCH_RP2040)
|
||||
int16_t *p = (int16_t *) dsBuff;
|
||||
for (int i = 0; i < oversample / 16; i++) {
|
||||
I2S.write(*(p++));
|
||||
for (int i = 0; i < oversample / 32; i++) {
|
||||
i2s.write((int32_t)dsBuff[i], true);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
|
|
|
@ -43,7 +43,7 @@ class AudioOutputI2SNoDAC : public AudioOutputI2S
|
|||
|
||||
protected:
|
||||
virtual int AdjustI2SRate(int hz) override { return hz * oversample/32; }
|
||||
uint8_t oversample;
|
||||
int oversample;
|
||||
void DeltaSigma(int16_t sample[2], uint32_t dsBuff[4]);
|
||||
typedef int32_t fixed24p8_t;
|
||||
enum {fixedPosValue=0x007fff00}; /* 24.8 of max-signed-int */
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
/*
|
||||
AudioOutputPWM
|
||||
Base class for the RP2040 PWM audio
|
||||
|
||||
Copyright (C) 2023 Earle F. Philhower, III
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#include <Arduino.h>
|
||||
#include "AudioOutputPWM.h"
|
||||
|
||||
AudioOutputPWM::AudioOutputPWM(long sampleRate, pin_size_t data) {
|
||||
pwmOn = false;
|
||||
mono = false;
|
||||
bps = 16;
|
||||
channels = 2;
|
||||
hertz = sampleRate;
|
||||
doutPin = data;
|
||||
SetGain(1.0);
|
||||
pwm.setStereo(true);
|
||||
}
|
||||
|
||||
AudioOutputPWM::~AudioOutputPWM() {
|
||||
stop();
|
||||
}
|
||||
|
||||
bool AudioOutputPWM::SetRate(int hz) {
|
||||
this->hertz = hz;
|
||||
if (pwmOn) {
|
||||
pwm.setFrequency(hz);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputPWM::SetBitsPerSample(int bits) {
|
||||
if ( (bits != 16) && (bits != 8) ) return false;
|
||||
this->bps = bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputPWM::SetChannels(int channels) {
|
||||
if ( (channels < 1) || (channels > 2) ) return false;
|
||||
this->channels = channels;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputPWM::SetOutputModeMono(bool mono) {
|
||||
this->mono = mono;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputPWM::begin() {
|
||||
if (!pwmOn) {
|
||||
pwm.setPin(doutPin);
|
||||
pwm.begin(hertz);
|
||||
}
|
||||
pwmOn = true;
|
||||
SetRate(hertz); // Default
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioOutputPWM::ConsumeSample(int16_t sample[2]) {
|
||||
|
||||
if (!pwmOn)
|
||||
return false;
|
||||
|
||||
int16_t ms[2];
|
||||
|
||||
ms[0] = sample[0];
|
||||
ms[1] = sample[1];
|
||||
MakeSampleStereo16( ms );
|
||||
|
||||
if (this->mono) {
|
||||
// Average the two samples and overwrite
|
||||
int32_t ttl = ms[LEFTCHANNEL] + ms[RIGHTCHANNEL];
|
||||
ms[LEFTCHANNEL] = ms[RIGHTCHANNEL] = (ttl>>1) & 0xffff;
|
||||
}
|
||||
|
||||
if (pwm.available()) {
|
||||
pwm.write((int16_t) ms[0]);
|
||||
pwm.write((int16_t) ms[1]);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AudioOutputPWM::flush() {
|
||||
pwm.flush();
|
||||
}
|
||||
|
||||
bool AudioOutputPWM::stop() {
|
||||
if (!pwmOn)
|
||||
return false;
|
||||
|
||||
pwm.end();
|
||||
pwmOn = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
AudioOutputPWM
|
||||
Base class for the RP2040 PWM audio output
|
||||
|
||||
Copyright (C) 2023 Earle F. Philhower, III
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "AudioOutput.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_RP2040)
|
||||
#include <Arduino.h>
|
||||
#include <PWMAudio.h>
|
||||
|
||||
class AudioOutputPWM : public AudioOutput
|
||||
{
|
||||
public:
|
||||
AudioOutputPWM(long sampleRate = 44100, pin_size_t data = 0);
|
||||
virtual ~AudioOutputPWM() override;
|
||||
virtual bool SetRate(int hz) override;
|
||||
virtual bool SetBitsPerSample(int bits) override;
|
||||
virtual bool SetChannels(int channels) override;
|
||||
virtual bool begin() override;
|
||||
virtual bool ConsumeSample(int16_t sample[2]) override;
|
||||
virtual void flush() override;
|
||||
virtual bool stop() override;
|
||||
|
||||
bool SetOutputModeMono(bool mono); // Force mono output no matter the input
|
||||
|
||||
protected:
|
||||
bool SetPinout();
|
||||
virtual int AdjustI2SRate(int hz) { return hz; }
|
||||
uint8_t portNo;
|
||||
int output_mode;
|
||||
bool mono;
|
||||
bool pwmOn;
|
||||
|
||||
uint8_t doutPin;
|
||||
|
||||
PWMAudio pwm;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -102,7 +102,13 @@ AudioOutputSPDIF::AudioOutputSPDIF(int dout_pin, int port, int dma_buf_count)
|
|||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // lowest interrupt priority
|
||||
.dma_buf_count = dma_buf_count,
|
||||
.dma_buf_len = DMA_BUF_SIZE_DEFAULT, // bigger buffers, reduces interrupts
|
||||
.use_apll = true // Audio PLL is needed for low clock jitter
|
||||
.use_apll = true, // Audio PLL is needed for low clock jitter
|
||||
.tx_desc_auto_clear = true, // Silence on underflow
|
||||
.fixed_mclk = 0, // Unused
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
.mclk_multiple = I2S_MCLK_MULTIPLE_DEFAULT, // Unused
|
||||
.bits_per_chan = I2S_BITS_PER_CHAN_DEFAULT // Use bits per sample
|
||||
#endif
|
||||
};
|
||||
if (i2s_driver_install((i2s_port_t)portNo, &i2s_config_spdif, 0, NULL) != ESP_OK) {
|
||||
audioLogger->println(F("ERROR: Unable to install I2S drivers"));
|
||||
|
@ -147,6 +153,9 @@ bool AudioOutputSPDIF::SetPinout(int bclk, int wclk, int dout)
|
|||
{
|
||||
#if defined(ESP32)
|
||||
i2s_pin_config_t pins = {
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0)
|
||||
.mck_io_num = 0, // unused
|
||||
#endif
|
||||
.bck_io_num = bclk,
|
||||
.ws_io_num = wclk,
|
||||
.data_out_num = dout,
|
||||
|
|
|
@ -18,12 +18,18 @@
|
|||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(ARDUINO_ARCH_RP2040)
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
#ifdef ESP32
|
||||
#include "SPIFFS.h"
|
||||
#endif
|
||||
|
||||
// Yes, I know SPIFFS is deprecated
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
|
||||
|
||||
#include "AudioOutputSPIFFSWAV.h"
|
||||
|
||||
static const uint8_t wavHeaderTemplate[] PROGMEM = { // Hardcoded simple WAV header with 0xffffffff lengths all around
|
||||
|
@ -110,4 +116,6 @@ bool AudioOutputSPIFFSWAV::stop()
|
|||
f.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
#ifndef _AUDIOOUTPUTSPIFFSWAV_H
|
||||
#define _AUDIOOUTPUTSPIFFSWAV_H
|
||||
|
||||
#if !defined(ARDUINO_ARCH_RP2040)
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <FS.h>
|
||||
|
||||
|
@ -43,3 +45,4 @@ class AudioOutputSPIFFSWAV : public AudioOutput
|
|||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
#include "AudioOutput.h"
|
||||
#include "AudioOutputI2S.h"
|
||||
#include "AudioOutputI2SNoDAC.h"
|
||||
#include "AudioOutputPWM.h"
|
||||
#include "AudioOutputMixer.h"
|
||||
#include "AudioOutputNull.h"
|
||||
#include "AudioOutputSerialWAV.h"
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
* print an error message if it fails (ie returns a value < 0).
|
||||
*
|
||||
* Ideally, a library should not print anything, but this macro is only used
|
||||
* for things that extremely unlikely to fail, like `chown` to a previoulsy
|
||||
* for things that extremely unlikely to fail, like `chown` to a previously
|
||||
* saved `uid`.
|
||||
*/
|
||||
|
||||
|
|
|
@ -2783,7 +2783,7 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_
|
|||
if(rice_parameter < pesc) {
|
||||
partitioned_rice_contents->raw_bits[partition] = 0;
|
||||
u = (partition_order == 0 || partition > 0)? partition_samples : partition_samples - predictor_order;
|
||||
if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, residual + sample, u, rice_parameter))
|
||||
if(!FLAC__bitreader_read_rice_signed_block(decoder->private_->input, (int *)(residual + sample), u, rice_parameter))
|
||||
return false; /* read_callback_ sets the state for us */
|
||||
sample += u;
|
||||
}
|
||||
|
@ -2792,7 +2792,7 @@ FLAC__bool read_residual_partitioned_rice_(FLAC__StreamDecoder *decoder, uint32_
|
|||
return false; /* read_callback_ sets the state for us */
|
||||
partitioned_rice_contents->raw_bits[partition] = rice_parameter;
|
||||
for(u = (partition_order == 0 || partition > 0)? 0 : predictor_order; u < partition_samples; u++, sample++) {
|
||||
if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, &i, rice_parameter))
|
||||
if(!FLAC__bitreader_read_raw_int32(decoder->private_->input, (FLAC__int32 *)&i, rice_parameter))
|
||||
return false; /* read_callback_ sets the state for us */
|
||||
residual[sample] = i;
|
||||
}
|
||||
|
|
|
@ -222,7 +222,8 @@ static void PostMultiply64(int *fft1, int nSampsOut)
|
|||
* Notes: this is carefully written to be efficient on ARM
|
||||
* use the assembly code version in sbrqmfak.s when building for ARM!
|
||||
**************************************************************************************/
|
||||
#if (defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))
|
||||
//TODO - ADD IN .S SOURCES SOMEHOW
|
||||
#if 0 //(defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
|
@ -395,7 +396,7 @@ int QMFAnalysis(int *inbuf, int *delay, int *XBuf, int fBitsIn, int *delayIdx, i
|
|||
* Notes: this is carefully written to be efficient on ARM
|
||||
* use the assembly code version in sbrqmfsk.s when building for ARM!
|
||||
**************************************************************************************/
|
||||
#if (defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))
|
||||
#if 0 //(defined (__arm) && defined (__ARMCC_VERSION)) || (defined (_WIN32) && defined (_WIN32_WCE) && defined (ARM)) || (defined(__GNUC__) && defined(__arm__))
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
#endif
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
|
||||
#pragma GCC optimize ("O3")
|
||||
#pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
|
||||
#include <pgmspace.h>
|
||||
# include "config.h"
|
||||
|
|
|
@ -1440,6 +1440,7 @@ static void tsf_voice_render_fast(tsf* f, struct tsf_voice* v, short* outputBuff
|
|||
//double tmpSampleEndDbl = (double)v->sampleEnd, tmpLoopEndDbl = (double)tmpLoopEnd + 1.0;
|
||||
//double tmpSourceSamplePosition = v->sourceSamplePosition;
|
||||
fixed32p32 tmpSampleEndF32P32 = ((fixed32p32)(region->end)) << 32;
|
||||
fixed32p32 tmpLoopStartF32P32 = ((fixed32p32)(tmpLoopStart + 1)) << 32;
|
||||
fixed32p32 tmpLoopEndF32P32 = ((fixed32p32)(tmpLoopEnd + 1)) << 32;
|
||||
fixed32p32 tmpSourceSamplePositionF32P32 = v->sourceSamplePositionF32P32;
|
||||
struct tsf_voice_lowpass tmpLowpass = v->lowpass;
|
||||
|
@ -1513,7 +1514,7 @@ static void tsf_voice_render_fast(tsf* f, struct tsf_voice* v, short* outputBuff
|
|||
// Next sample.
|
||||
tmpSourceSamplePositionF32P32 += pitchRatioF32P32;
|
||||
if (tmpSourceSamplePositionF32P32 >= tmpLoopEndF32P32 && isLooping)
|
||||
tmpSourceSamplePositionF32P32 -= (tmpLoopEndF32P32 - tmpLoopStart + (1LL<<32));
|
||||
tmpSourceSamplePositionF32P32 -= (tmpLoopEndF32P32 - tmpLoopStartF32P32 + (1LL<<32));
|
||||
}
|
||||
|
||||
if (tmpSourceSamplePositionF32P32 >= tmpSampleEndF32P32 || v->ampenv.segment == TSF_SEGMENT_DONE)
|
||||
|
|
|
@ -1422,7 +1422,7 @@ static int op_open_seekable2_impl(OggOpusFile *_of){
|
|||
_of->end=sr[0].offset+sr[0].size;
|
||||
if(OP_UNLIKELY(_of->end<data_offset)){free(sr); return OP_EBADLINK;}
|
||||
/*Now enumerate the bitstream structure.*/
|
||||
ret = op_bisect_forward_serialno(_of,data_offset,sr,sizeof(sr)/sizeof(*sr),
|
||||
ret = op_bisect_forward_serialno(_of,data_offset,sr,64,
|
||||
&_of->serialnos,&_of->nserialnos,&_of->cserialnos);
|
||||
free(sr);
|
||||
return ret;
|
||||
|
|
|
@ -337,9 +337,9 @@ class ESP8266SPIRAM {
|
|||
}
|
||||
digitalWrite(csPin, HIGH);
|
||||
|
||||
pinMode(sck, SPECIAL);
|
||||
pinMode(miso, SPECIAL);
|
||||
pinMode(mosi, SPECIAL);
|
||||
pinMode(sck, OUTPUT);
|
||||
pinMode(miso, INPUT);
|
||||
pinMode(mosi, OUTPUT);
|
||||
pinMode(csPin, OUTPUT);
|
||||
|
||||
// Enable streaming read/write mode
|
||||
|
|
169
tests/common.sh
169
tests/common.sh
|
@ -2,98 +2,17 @@
|
|||
|
||||
set -ex
|
||||
|
||||
function print_size_info()
|
||||
{
|
||||
elf_file=$1
|
||||
|
||||
if [ -z "$elf_file" ]; then
|
||||
printf "sketch data rodata bss text irom0.text dram flash\n"
|
||||
return 0
|
||||
fi
|
||||
|
||||
elf_name=$(basename $elf_file)
|
||||
sketch_name="${elf_name%.*}"
|
||||
# echo $sketch_name
|
||||
declare -A segments
|
||||
while read -a tokens; do
|
||||
seg=${tokens[0]}
|
||||
seg=${seg//./}
|
||||
size=${tokens[1]}
|
||||
addr=${tokens[2]}
|
||||
if [ "$addr" -eq "$addr" -a "$addr" -ne "0" ] 2>/dev/null; then
|
||||
segments[$seg]=$size
|
||||
fi
|
||||
|
||||
|
||||
done < <(xtensa-lx106-elf-size --format=sysv $elf_file)
|
||||
|
||||
total_ram=$((${segments[data]} + ${segments[rodata]} + ${segments[bss]}))
|
||||
total_flash=$((${segments[data]} + ${segments[rodata]} + ${segments[text]} + ${segments[irom0text]}))
|
||||
|
||||
printf "%-28s %-8d %-8d %-8d %-8d %-8d %-8d %-8d\n" $sketch_name ${segments[data]} ${segments[rodata]} ${segments[bss]} ${segments[text]} ${segments[irom0text]} $total_ram $total_flash
|
||||
return 0
|
||||
}
|
||||
|
||||
function build_sketches()
|
||||
{
|
||||
set +e
|
||||
local arduino=$1
|
||||
local srcpath=$2
|
||||
local build_arg=$3
|
||||
local build_dir=build.tmp
|
||||
local build_mod=$BUILD_MOD
|
||||
local build_rem=$BUILD_REM
|
||||
mkdir -p $build_dir
|
||||
local build_cmd="python3 $arduino/$BUILD_PY -p $PWD/$build_dir $build_arg "
|
||||
local sketches=$(find $srcpath -name *.ino)
|
||||
print_size_info >size.log
|
||||
export ARDUINO_IDE_PATH=$arduino
|
||||
for sketch in $sketches; do
|
||||
testcnt=$(( ($testcnt + 1) % $build_mod ))
|
||||
if [ $testcnt -ne $build_rem ]; then
|
||||
continue # Not ours to do
|
||||
fi
|
||||
rm -rf $build_dir/*
|
||||
local sketchdir=$(dirname $sketch)
|
||||
local sketchdirname=$(basename $sketchdir)
|
||||
local sketchname=$(basename $sketch)
|
||||
if [[ "${sketchdirname}.ino" != "$sketchname" ]]; then
|
||||
echo "Skipping $sketch, because it is not the main sketch file";
|
||||
continue
|
||||
fi;
|
||||
if [[ -f "$sketchdir/.test.skip" ]]; then
|
||||
echo -e "\n ------------ Skipping $sketch ------------ \n";
|
||||
continue
|
||||
fi
|
||||
echo -e "\n ------------ Building $sketch ------------ \n";
|
||||
# $arduino --verify $sketch;
|
||||
echo "$build_cmd $sketch"
|
||||
time ($build_cmd $sketch >build.log)
|
||||
local result=$?
|
||||
if [ $result -ne 0 ]; then
|
||||
echo "Build failed ($1)"
|
||||
echo "Build log:"
|
||||
cat build.log
|
||||
set -e
|
||||
return $result
|
||||
fi
|
||||
rm build.log
|
||||
#print_size_info $build_dir/*.elf >>size.log
|
||||
done
|
||||
set -e
|
||||
}
|
||||
|
||||
function install_libraries()
|
||||
{
|
||||
mkdir -p $HOME/Arduino/libraries
|
||||
cp -a $TRAVIS_BUILD_DIR $HOME/Arduino/libraries/ESP8266Audio
|
||||
cp -a $GITHUB_WORKSPACE $HOME/Arduino/libraries/ESP8266Audio
|
||||
git clone https://github.com/earlephilhower/ESP8266SAM $HOME/Arduino/libraries/ESP8266SAM
|
||||
}
|
||||
|
||||
function install_ide()
|
||||
{
|
||||
local ide_path=$1
|
||||
wget -q -O arduino.tar.xz https://www.arduino.cc/download.php?f=/arduino-nightly-linux64.tar.xz
|
||||
wget -q -O arduino.tar.xz https://downloads.arduino.cc/arduino-nightly-linux64.tar.xz
|
||||
tar xf arduino.tar.xz
|
||||
mv arduino-nightly $ide_path
|
||||
export PATH="$ide_path:$PATH"
|
||||
|
@ -111,84 +30,100 @@ function install_esp8266()
|
|||
# Set custom warnings for all builds (i.e. could add -Wextra at some point)
|
||||
echo "compiler.c.extra_flags=-Wall -Wextra -Werror $debug_flags" > ../platform.local.txt
|
||||
echo "compiler.cpp.extra_flags=-Wall -Wextra -Werror $debug_flags" >> ../platform.local.txt
|
||||
echo "mkbuildoptglobals.extra_flags=--ci --cache_core" >> ../platform.local.txt
|
||||
echo -e "\n----platform.local.txt----"
|
||||
cat ../platform.local.txt
|
||||
git submodule init
|
||||
git submodule update
|
||||
python3 get.py
|
||||
python3 get.py -q
|
||||
export PATH="$ide_path/hardware/esp8266com/esp8266/tools/xtensa-lx106-elf/bin:$PATH"
|
||||
popd
|
||||
cd esp8266
|
||||
}
|
||||
|
||||
function install_rp2040()
|
||||
{
|
||||
local ide_path=$1
|
||||
mkdir -p $ide_path/hardware
|
||||
cd $ide_path/hardware
|
||||
mkdir pico
|
||||
cd pico
|
||||
git clone https://github.com/earlephilhower/arduino-pico rp2040
|
||||
pushd rp2040/tools
|
||||
# Set custom warnings for all builds (i.e. could add -Wextra at some point)
|
||||
echo "compiler.c.extra_flags=-Wall -Wextra -Werror $debug_flags" > ../platform.local.txt
|
||||
echo "compiler.cpp.extra_flags=-Wall -Wextra -Werror $debug_flags" >> ../platform.local.txt
|
||||
echo -e "\n----platform.local.txt----"
|
||||
cat ../platform.local.txt
|
||||
git submodule update --init
|
||||
cd ../pico-sdk
|
||||
git submodule update --init
|
||||
cd ../tools
|
||||
python3 get.py -q
|
||||
export PATH="$ide_path/hardware/pico/rp2040/system/arm-none-eabi/bin:$PATH"
|
||||
popd
|
||||
cd rp2040
|
||||
}
|
||||
|
||||
function install_esp32()
|
||||
{
|
||||
local ide_path=$1
|
||||
sudo pip install pyserial
|
||||
pip install pyserial
|
||||
pip3 install pyserial
|
||||
cd $ide_path/hardware
|
||||
mkdir espressif
|
||||
cd espressif
|
||||
git clone https://github.com/espressif/arduino-esp32.git esp32
|
||||
pushd esp32
|
||||
# Set custom warnings for all builds (i.e. could add -Wextra at some point)
|
||||
# Set custom warnings for all builds
|
||||
|
||||
echo "compiler.c.extra_flags=-Wall -Wextra -Werror $debug_flags" > platform.local.txt
|
||||
echo "compiler.cpp.extra_flags=-Wall -Wextra -Werror $debug_flags" >> platform.local.txt
|
||||
echo -e "\n----platform.local.txt----"
|
||||
cat platform.local.txt
|
||||
git submodule init
|
||||
git submodule update
|
||||
git submodule update --init
|
||||
cd tools
|
||||
python3 get.py
|
||||
export PATH="$ide_path/hardware/espressif/esp32/tools/xtensa-esp32-elf/bin/:$PATH"
|
||||
popd
|
||||
|
||||
cd esp32
|
||||
}
|
||||
|
||||
function install_arduino()
|
||||
{
|
||||
# Install Arduino IDE and required libraries
|
||||
echo -e "travis_fold:start:sketch_test_env_prepare"
|
||||
cd $TRAVIS_BUILD_DIR
|
||||
install_ide $HOME/arduino_ide $TRAVIS_BUILD_DIR
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
install_ide "$HOME/arduino_ide" "$GITHUB_WORKSPACE"
|
||||
which arduino
|
||||
cd $TRAVIS_BUILD_DIR
|
||||
cd "$GITHUB_WORKSPACE"
|
||||
install_libraries
|
||||
echo -e "travis_fold:end:sketch_test_env_prepare"
|
||||
}
|
||||
|
||||
function build_sketches_with_arduino()
|
||||
{
|
||||
# Compile sketches
|
||||
echo -e "travis_fold:start:sketch_test"
|
||||
build_sketches $HOME/arduino_ide $HOME/Arduino/libraries "-l $HOME/Arduino/libraries"
|
||||
echo -e "travis_fold:end:sketch_test"
|
||||
# Generate size report
|
||||
echo -e "travis_fold:start:size_report"
|
||||
cat size.log
|
||||
echo -e "travis_fold:end:size_report"
|
||||
}
|
||||
|
||||
set -e
|
||||
|
||||
if [ "$BUILD_MOD" == "" ]; then
|
||||
export BUILD_MOD=1
|
||||
export BUILD_REM=0
|
||||
fi
|
||||
|
||||
export cache_dir=$(mktemp -d)
|
||||
if [ "$BUILD_TYPE" = "build" ]; then
|
||||
export BUILD_PY="hardware/esp8266com/esp8266/tools/build.py -b generic -s 4M1M -v -k "
|
||||
install_arduino
|
||||
install_esp8266 "$HOME/arduino_ide"
|
||||
build_sketches_with_arduino
|
||||
source "$HOME/arduino_ide/hardware/esp8266com/esp8266/tests/common.sh"
|
||||
export ESP8266_ARDUINO_SKETCHES=$(find $HOME/Arduino/libraries/ESP8266Audio -name *.ino | sort)
|
||||
# ESP8266 scripts now expect tools in wrong spot. Use simple and dumb fix
|
||||
mkdir -p "$HOME/work/ESP8266Audio/ESP8266Audio"
|
||||
ln -s "$HOME/arduino_ide/hardware/esp8266com/esp8266/tools" "$HOME/work/ESP8266Audio/ESP8266Audio/tools"
|
||||
build_sketches "$TRAVIS_BUILD_DIR" "$HOME/arduino_ide" "$HOME/arduino_ide/hardware" "$HOME/Arduino/libraries" "$BUILD_MOD" "$BUILD_REM" "lm2f"
|
||||
elif [ "$BUILD_TYPE" = "build_esp32" ]; then
|
||||
install_arduino
|
||||
install_esp32 "$HOME/arduino_ide"
|
||||
export ide_path=$HOME/arduino_ide
|
||||
export FQBN="espressif:esp32:esp32:PSRAM=enabled,PartitionScheme=huge_app"
|
||||
export GITHUB_WORKSPACE="$TRAVIS_BUILD_DIR"
|
||||
export GITHUB_REPOSITORY="$TRAVIS_REPO_SLUG"
|
||||
source $ide_path/hardware/espressif/esp32/.github/scripts/install-arduino-ide.sh
|
||||
source $ide_path/hardware/espressif/esp32/.github/scripts/install-arduino-core-esp32.sh
|
||||
build_sketches "$FQBN" "$HOME/Arduino/libraries" "$BUILD_REM" "$BUILD_MOD"
|
||||
mkdir -p "$GITHUB_WORKSPACE/hardware"
|
||||
ln -s "$GITHUB_WORKSPACE/../" "$GITHUB_WORKSPACE/libraries"
|
||||
source "$HOME/arduino_ide/hardware/espressif/esp32/.github/scripts/sketch_utils.sh" chunk_build -ai "$HOME/arduino_ide" -au "$GITHUB_WORKSPACE" -fqbn "$FQBN" -t esp32 -p "$GITHUB_WORKSPACE" -i $BUILD_REM -m $BUILD_MOD
|
||||
elif [ "$BUILD_TYPE" = "build_rp2040" ]; then
|
||||
install_arduino
|
||||
install_rp2040 "$HOME/arduino_ide"
|
||||
source "$HOME/arduino_ide/hardware/pico/rp2040/tests/common.sh"
|
||||
build_sketches "$HOME/arduino_ide" "$TRAVIS_BUILD_DIR" "-l $HOME/Arduino/libraries" "$BUILD_MOD" "$BUILD_REM"
|
||||
fi
|
||||
|
||||
|
|
Loading…
Reference in New Issue