mirror of
https://github.com/esp8266/Arduino.git
synced 2025-07-30 16:24:09 +03:00
Audio library to the new format
This commit is contained in:
138
libraries/Audio/arch/sam/DAC.cpp
Normal file
138
libraries/Audio/arch/sam/DAC.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2012 by Cristian Maglie <c.maglie@bug.st>
|
||||
* DAC library for Arduino Due.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <DAC.h>
|
||||
|
||||
void DACClass::begin(uint32_t period) {
|
||||
// Enable clock for DAC
|
||||
pmc_enable_periph_clk(dacId);
|
||||
|
||||
dacc_reset(dac);
|
||||
|
||||
// Set transfer mode to double word
|
||||
dacc_set_transfer_mode(dac, 1);
|
||||
|
||||
// Power save:
|
||||
// sleep mode - 0 (disabled)
|
||||
// fast wakeup - 0 (disabled)
|
||||
dacc_set_power_save(dac, 0, 0);
|
||||
|
||||
// DAC refresh/startup timings:
|
||||
// refresh - 0x08 (1024*8 dacc clocks)
|
||||
// max speed mode - 0 (disabled)
|
||||
// startup time - 0x10 (1024 dacc clocks)
|
||||
dacc_set_timing(dac, 0x08, 0, DACC_MR_STARTUP_1024);
|
||||
|
||||
// Flexible channel selection with tags
|
||||
dacc_enable_flexible_selection(dac);
|
||||
|
||||
// Set up analog current
|
||||
dacc_set_analog_control(dac,
|
||||
DACC_ACR_IBCTLCH0(0x02) |
|
||||
DACC_ACR_IBCTLCH1(0x02) |
|
||||
DACC_ACR_IBCTLDACCORE(0x01));
|
||||
|
||||
// Enable output channels
|
||||
dacc_enable_channel(dac, 0);
|
||||
dacc_enable_channel(dac, 1);
|
||||
|
||||
// Configure Timer Counter to trigger DAC
|
||||
// --------------------------------------
|
||||
pmc_enable_periph_clk(ID_TC1);
|
||||
TC_Configure(TC0, 1,
|
||||
TC_CMR_TCCLKS_TIMER_CLOCK2 | // Clock at MCR/8
|
||||
TC_CMR_WAVE | // Waveform mode
|
||||
TC_CMR_WAVSEL_UP_RC | // Counter running up and reset when equals to RC
|
||||
TC_CMR_ACPA_SET | TC_CMR_ACPC_CLEAR);
|
||||
const uint32_t TC = period / 8;
|
||||
TC_SetRA(TC0, 1, TC / 2);
|
||||
TC_SetRC(TC0, 1, TC);
|
||||
TC_Start(TC0, 1);
|
||||
|
||||
// Configure clock source for DAC (2 = TC0 Output Chan. 1)
|
||||
dacc_set_trigger(dac, 2);
|
||||
|
||||
// Configure pins
|
||||
PIO_Configure(g_APinDescription[DAC0].pPort,
|
||||
g_APinDescription[DAC0].ulPinType,
|
||||
g_APinDescription[DAC0].ulPin,
|
||||
g_APinDescription[DAC0].ulPinConfiguration);
|
||||
PIO_Configure(g_APinDescription[DAC1].pPort,
|
||||
g_APinDescription[DAC1].ulPinType,
|
||||
g_APinDescription[DAC1].ulPin,
|
||||
g_APinDescription[DAC1].ulPinConfiguration);
|
||||
|
||||
// Enable interrupt controller for DAC
|
||||
dacc_disable_interrupt(dac, 0xFFFFFFFF);
|
||||
NVIC_DisableIRQ(isrId);
|
||||
NVIC_ClearPendingIRQ(isrId);
|
||||
NVIC_SetPriority(isrId, 0);
|
||||
NVIC_EnableIRQ(isrId);
|
||||
}
|
||||
|
||||
void DACClass::end() {
|
||||
TC_Stop(TC0, 1);
|
||||
NVIC_DisableIRQ(isrId);
|
||||
dacc_disable_channel(dac, 0);
|
||||
dacc_disable_channel(dac, 1);
|
||||
}
|
||||
|
||||
bool DACClass::canQueue() {
|
||||
return (dac->DACC_TNCR == 0);
|
||||
}
|
||||
|
||||
size_t DACClass::queueBuffer(const uint32_t *buffer, size_t size) {
|
||||
// Try the first PDC buffer
|
||||
if ((dac->DACC_TCR == 0) && (dac->DACC_TNCR == 0)) {
|
||||
dac->DACC_TPR = (uint32_t) buffer;
|
||||
dac->DACC_TCR = size;
|
||||
dac->DACC_PTCR = DACC_PTCR_TXTEN;
|
||||
if (cb)
|
||||
dacc_enable_interrupt(dac, DACC_IER_ENDTX);
|
||||
return size;
|
||||
}
|
||||
|
||||
// Try the second PDC buffer
|
||||
if (dac->DACC_TNCR == 0) {
|
||||
dac->DACC_TNPR = (uint32_t) buffer;
|
||||
dac->DACC_TNCR = size;
|
||||
dac->DACC_PTCR = DACC_PTCR_TXTEN;
|
||||
if (cb)
|
||||
dacc_enable_interrupt(dac, DACC_IER_ENDTX);
|
||||
return size;
|
||||
}
|
||||
|
||||
// PDC buffers full, try again later...
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DACClass::setOnTransmitEnd_CB(OnTransmitEnd_CB _cb, void *_data) {
|
||||
cb = _cb;
|
||||
cbData = _data;
|
||||
if (!cb)
|
||||
dacc_disable_interrupt(dac, DACC_IDR_ENDTX);
|
||||
}
|
||||
|
||||
void DACClass::onService() {
|
||||
uint32_t sr = dac->DACC_ISR;
|
||||
if (sr & DACC_ISR_ENDTX) {
|
||||
// There is a free slot, enqueue data
|
||||
dacc_disable_interrupt(dac, DACC_IDR_ENDTX);
|
||||
if (cb)
|
||||
cb(cbData);
|
||||
}
|
||||
}
|
||||
|
||||
DACClass DAC(DACC_INTERFACE, DACC_INTERFACE_ID, DACC_ISR_ID);
|
||||
|
||||
void DACC_ISR_HANDLER(void) {
|
||||
DAC.onService();
|
||||
}
|
||||
|
44
libraries/Audio/arch/sam/DAC.h
Normal file
44
libraries/Audio/arch/sam/DAC.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2012 by Cristian Maglie <c.maglie@bug.st>
|
||||
* DAC library for Arduino Due.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef DAC_INCLUDED
|
||||
#define DAC_INCLUDED
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
typedef void (*OnTransmitEnd_CB)(void *data);
|
||||
|
||||
class DACClass
|
||||
{
|
||||
public:
|
||||
DACClass(Dacc *_dac, uint32_t _dacId, IRQn_Type _isrId) :
|
||||
dac(_dac), dacId(_dacId), isrId(_isrId), cb(NULL) { };
|
||||
void begin(uint32_t period);
|
||||
void end();
|
||||
bool canQueue();
|
||||
size_t queueBuffer(const uint32_t *buffer, size_t size);
|
||||
uint32_t *getCurrentQueuePointer();
|
||||
void setOnTransmitEnd_CB(OnTransmitEnd_CB _cb, void *data);
|
||||
void onService();
|
||||
|
||||
void enableInterrupts() { NVIC_EnableIRQ(isrId); };
|
||||
void disableInterrupts() { NVIC_DisableIRQ(isrId); };
|
||||
|
||||
private:
|
||||
Dacc *dac;
|
||||
uint32_t dacId;
|
||||
IRQn_Type isrId;
|
||||
OnTransmitEnd_CB cb;
|
||||
void *cbData;
|
||||
};
|
||||
|
||||
extern DACClass DAC;
|
||||
|
||||
#endif
|
@ -0,0 +1,83 @@
|
||||
/*
|
||||
Simple Audio Player
|
||||
|
||||
Demonstrates the use of the Audio library for the Arduino Due
|
||||
|
||||
Hardware required :
|
||||
* Arduino shield with a SD card on CS4
|
||||
* A sound file named "test.wav" in the root directory of the SD card
|
||||
* Speaker attched to ground and DAC0
|
||||
|
||||
Original by Massimo Banzi September 20, 2012
|
||||
Modified by Scott Fitzgerald October 19, 2012
|
||||
|
||||
This example code is in the public domain
|
||||
|
||||
http://arduino.cc/en/Tutorial/SimpleAudioPlayer
|
||||
|
||||
*/
|
||||
|
||||
#include <SD.h>
|
||||
#include <SPI.h>
|
||||
#include <Audio.h>
|
||||
|
||||
void setup()
|
||||
{
|
||||
// debug output at 9600 baud
|
||||
Serial.begin(9600);
|
||||
|
||||
// setup SD-card
|
||||
Serial.print("Initializing SD card...");
|
||||
if (!SD.begin(4)) {
|
||||
Serial.println(" failed!");
|
||||
return;
|
||||
}
|
||||
Serial.println(" done.");
|
||||
// hi-speed SPI transfers
|
||||
SPI.setClockDivider(4);
|
||||
|
||||
// 44100Khz stereo => 88200 sample rate
|
||||
// 100 mSec of prebuffering.
|
||||
Audio.begin(88200, 100);
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
int count=0;
|
||||
|
||||
// open wave file from sdcard
|
||||
File myFile = SD.open("test.wav");
|
||||
if (!myFile) {
|
||||
// if the file didn't open, print an error and stop
|
||||
Serial.println("error opening test.wav");
|
||||
while (true);
|
||||
}
|
||||
|
||||
const int S=1024; // Number of samples to read in block
|
||||
short buffer[S];
|
||||
|
||||
Serial.print("Playing");
|
||||
// until the file is not finished
|
||||
while (myFile.available()) {
|
||||
// read from the file into buffer
|
||||
myFile.read(buffer, sizeof(buffer));
|
||||
|
||||
// Prepare samples
|
||||
int volume = 1024;
|
||||
Audio.prepare(buffer, S, volume);
|
||||
// Feed samples to audio
|
||||
Audio.write(buffer, S);
|
||||
|
||||
// Every 100 block print a '.'
|
||||
count++;
|
||||
if (count == 100) {
|
||||
Serial.print(".");
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
myFile.close();
|
||||
|
||||
Serial.println("End of file. Thank you for listening!");
|
||||
while (true) ;
|
||||
}
|
||||
|
21
libraries/Audio/keywords.txt
Normal file
21
libraries/Audio/keywords.txt
Normal file
@ -0,0 +1,21 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Audio
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
|
||||
Audio KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
prepare KEYWORD2
|
||||
write KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
|
10
libraries/Audio/library.properties
Normal file
10
libraries/Audio/library.properties
Normal file
@ -0,0 +1,10 @@
|
||||
name=Audio
|
||||
author=cmaglie
|
||||
email=Cristian Maglie <c.maglie@bug.st>
|
||||
sentence=The libary to play audio files through the DAC outputs of the Arduino Due.
|
||||
paragraph=With this library you can use the Arduino Due DAC outputs to play audio files.<br />The audio files must be in the raw .wav format.
|
||||
url=http://arduino.cc/en/Reference/Audio
|
||||
architectures=sam
|
||||
version=1.0
|
||||
dependencies=
|
||||
core-dependencies=arduino (>=1.5.0)
|
88
libraries/Audio/src/Audio.cpp
Normal file
88
libraries/Audio/src/Audio.cpp
Normal file
@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2012 by Cristian Maglie <c.maglie@bug.st>
|
||||
* Audio library for Arduino Due.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "Audio.h"
|
||||
|
||||
void AudioClass::begin(uint32_t sampleRate, uint32_t msPreBuffer) {
|
||||
// Allocate a buffer to keep msPreBuffer milliseconds of audio
|
||||
bufferSize = msPreBuffer * sampleRate / 1000;
|
||||
if (bufferSize < 1024)
|
||||
bufferSize = 1024;
|
||||
buffer = (uint32_t *) malloc(bufferSize * sizeof(uint32_t));
|
||||
half = buffer + bufferSize / 2;
|
||||
last = buffer + bufferSize;
|
||||
|
||||
// Buffering starts from the beginning
|
||||
running = buffer;
|
||||
next = buffer;
|
||||
|
||||
// Start DAC
|
||||
dac->begin(VARIANT_MCK / sampleRate);
|
||||
dac->setOnTransmitEnd_CB(onTransmitEnd, this);
|
||||
}
|
||||
|
||||
void AudioClass::end() {
|
||||
dac->end();
|
||||
free( buffer);
|
||||
}
|
||||
|
||||
void AudioClass::prepare(int16_t *buffer, int S, int volume){
|
||||
uint16_t *ubuffer = (uint16_t*) buffer;
|
||||
for (int i=0; i<S; i++) {
|
||||
// set volume amplitude (signed multiply)
|
||||
buffer[i] = buffer[i] * volume / 1024;
|
||||
// convert from signed 16 bit to unsigned 12 bit for DAC.
|
||||
ubuffer[i] += 0x8000;
|
||||
ubuffer[i] >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
size_t AudioClass::write(const uint32_t *data, size_t size) {
|
||||
const uint32_t TAG = 0x10000000;
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
*next = data[i] | TAG;
|
||||
next++;
|
||||
|
||||
if (next == half || next == last) {
|
||||
enqueue();
|
||||
while (next == running)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
void AudioClass::enqueue() {
|
||||
if (!dac->canQueue()) {
|
||||
// DMA queue full
|
||||
return;
|
||||
}
|
||||
|
||||
if (next == half) {
|
||||
// Enqueue the first half
|
||||
dac->queueBuffer(buffer, bufferSize / 2);
|
||||
} else {
|
||||
// Enqueue the second half
|
||||
dac->queueBuffer(half, bufferSize / 2);
|
||||
next = buffer; // wrap around
|
||||
}
|
||||
}
|
||||
|
||||
void AudioClass::onTransmitEnd(void *_me) {
|
||||
AudioClass *me = reinterpret_cast<AudioClass *> (_me);
|
||||
if (me->running == me->buffer)
|
||||
me->running = me->half;
|
||||
else
|
||||
me->running = me->buffer;
|
||||
}
|
||||
|
||||
AudioClass Audio(DAC);
|
57
libraries/Audio/src/Audio.h
Normal file
57
libraries/Audio/src/Audio.h
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2012 by Cristian Maglie <c.maglie@bug.st>
|
||||
* Audio library for Arduino Due.
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of either the GNU General Public License version 2
|
||||
* or the GNU Lesser General Public License version 2.1, both as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#ifndef AUDIO_H
|
||||
#define AUDIO_H
|
||||
|
||||
#include "Arduino.h"
|
||||
#include "Print.h"
|
||||
#include "DAC.h"
|
||||
|
||||
class AudioClass : public Print {
|
||||
public:
|
||||
AudioClass(DACClass &_dac) : dac(&_dac) { };
|
||||
void prepare(int16_t *buffer, int S, int volume);
|
||||
void begin(uint32_t sampleRate, uint32_t msPreBuffer);
|
||||
void end();
|
||||
|
||||
virtual size_t write(uint8_t c) { /* not implemented */ };
|
||||
virtual size_t write(const uint8_t *data, size_t size) { return write(reinterpret_cast<const uint32_t*>(data), size/4) * 4; };
|
||||
virtual size_t write(const uint16_t *data, size_t size) { return write(reinterpret_cast<const uint32_t*>(data), size/2) * 2; };
|
||||
virtual size_t write(const int16_t *data, size_t size) { return write(reinterpret_cast<const uint32_t*>(data), size/2) * 2; };
|
||||
virtual size_t write(const uint32_t *data, size_t size);
|
||||
|
||||
void debug() {
|
||||
// Serial1.print(running-buffer, DEC);
|
||||
// Serial1.print(" ");
|
||||
// Serial1.print(current-buffer, DEC);
|
||||
// Serial1.print(" ");
|
||||
// Serial1.print(next-buffer, DEC);
|
||||
// Serial1.print(" ");
|
||||
// Serial1.println(last-buffer, DEC);
|
||||
}
|
||||
private:
|
||||
void enqueue();
|
||||
static void onTransmitEnd(void *me);
|
||||
uint32_t bufferSize;
|
||||
uint32_t *buffer;
|
||||
uint32_t *half;
|
||||
uint32_t *last;
|
||||
uint32_t *volatile running;
|
||||
uint32_t *volatile next;
|
||||
|
||||
uint32_t *cook(const uint32_t *buffer, size_t size);
|
||||
|
||||
DACClass *dac;
|
||||
};
|
||||
|
||||
extern AudioClass Audio;
|
||||
|
||||
#endif
|
@ -1,10 +1,10 @@
|
||||
name=SD
|
||||
author=SparkFun Electronics
|
||||
email=info@arduino.cc
|
||||
sentence=The libary to use the Arduino Ethernet shield or the Arduino Ethernet based on the WizNet W5100 ic.
|
||||
paragraph=With this library you can use the Arduino Ethernet (shield or board) to connect to Internet. The library provides both Client and server functionalities. The library permits you to connect to a local network also with DHCP and to resolve DNS.
|
||||
sentence=With this library you can use an SD card to save data and operate on files.
|
||||
paragraph=Once an SD memory card is connected to the SPI interfare of the Arduino board you are enabled to create files and read/write on them. You can also move through directories on the SD card.
|
||||
url=http://arduino.cc/en/Reference/SD
|
||||
architectures=avr, sam
|
||||
architectures=*
|
||||
version=1.0
|
||||
dependencies= IPAddress, SPI
|
||||
dependencies= SPI
|
||||
core-dependencies=arduino (>=1.5.0)
|
||||
|
@ -17,7 +17,7 @@
|
||||
* along with the Arduino SdFat Library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <SdFat.h>
|
||||
#include "SdFat.h"
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
@ -17,7 +17,7 @@
|
||||
* along with the Arduino SdFat Library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <SdFat.h>
|
||||
#include "SdFat.h"
|
||||
//------------------------------------------------------------------------------
|
||||
// raw block cache
|
||||
// init cacheBlockNumber_to invalid SD block number
|
||||
|
@ -2,8 +2,8 @@ name=Servo
|
||||
author=cmaglie
|
||||
email=Cristian Maglie <c.maglie@bug.st>
|
||||
sentence=Controls a lot of Servos.
|
||||
paragraph=This library can control a great number of servos.<br />It makes careful use of timers: the library can control 12 servos with only 1 timer!<br />
|
||||
url=http://github.com/cmaglie/Servo
|
||||
paragraph=This library can control a great number of servos.<br />It makes careful use of timers: the library can control 12 servos with only 1 timer!<br />On the Arduino Due you can control up to 60 servos.<br />
|
||||
url=http://arduino.cc/en/Reference/Servo
|
||||
architectures=avr,sam
|
||||
version=1.0
|
||||
dependencies=
|
||||
|
Reference in New Issue
Block a user