diff --git a/src/AutoAnalogAudio.h b/src/AutoAnalogAudio.h
index b0fb8e8..d9e66e5 100644
--- a/src/AutoAnalogAudio.h
+++ b/src/AutoAnalogAudio.h
@@ -100,10 +100,12 @@ class AutoAnalog
* 10 or 12-bit samples are read directly from this buffer after calling getADC()
* @see adcBitsPerSample
*/
- #if !defined(ARDUINO_ARCH_NRF52840) && !defined (ARDUINO_ARCH_NRF52) || defined ARDUINO_NRF52840_FEATHER
+ #if !defined (ARDUINO_ARCH_NRF52840) && !defined (ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER
uint16_t adcBuffer16[MAX_BUFFER_SIZE];
+ #elif defined __MBED__
+ inline static uint16_t adcBuffer16[MAX_BUFFER_SIZE];
#else
- inline static int16_t adcBuffer16[MAX_BUFFER_SIZE];
+ static uint16_t adcBuffer16[MAX_BUFFER_SIZE];
#endif
/** Set sample rate. 0 enables the default rate specified in AutoAnalog_config.h
@@ -189,7 +191,7 @@ class AutoAnalog
/**@}*/
-#if defined (ARDUINO_ARCH_NRF52840) || defined (ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER
+#if defined (ARDUINO_ARCH_NRF52840) || defined (ARDUINO_ARCH_NRF52) && !defined ARDUINO_NRF52840_FEATHER && defined __MBED__
inline static uint8_t aCtr;
inline static uint32_t aSize;
inline static uint16_t *buf0 = NULL;
@@ -198,19 +200,31 @@ class AutoAnalog
inline static void adcCallback(uint16_t *buf, uint32_t buf_len);
inline static void set_callback(void(*function)(uint16_t *buf, uint32_t buf_len));
inline static bool adcReady;
- inline static uint16_t dacBuf0[MAX_BUFFER_SIZE];
- inline static uint16_t dacBuf1[MAX_BUFFER_SIZE];
+ inline static int16_t dacBuf0[MAX_BUFFER_SIZE];
+ inline static int16_t dacBuf1[MAX_BUFFER_SIZE];
bool micOn;
int pwrPin;
int dinPin;
int clkPin;
int8_t gain;
inline static uint32_t sampleCounter;
-#endif
-
-#if defined ARDUINO_NRF52840_FEATHER
+#elif defined (ARDUINO_ARCH_NRF52840) || defined (ARDUINO_ARCH_NRF52) || defined (ARDUINO_NRF52840_FEATHER) && !defined __MBED__
uint16_t dacBuf0[MAX_BUFFER_SIZE];
uint16_t dacBuf1[MAX_BUFFER_SIZE];
+ static uint8_t aCtr;
+ static uint32_t aSize;
+ static uint16_t *buf0;
+ static uint16_t *buf1;
+ static void (*_onReceive)(uint16_t *buf, uint32_t buf_len);
+ static void adcCallback(uint16_t *buf, uint32_t buf_len);
+ void set_callback(void(*function)(uint16_t *buf, uint32_t buf_len));
+ static bool adcReady;
+ bool micOn;
+ int pwrPin;
+ int dinPin;
+ int clkPin;
+ int8_t gain;
+ uint32_t sampleCounter;
#endif
private:
diff --git a/src/NRF52840/AutoAnalogAudio.cpp b/src/NRF52840/AutoAnalogAudio.cpp
index eb33c63..b06cb2b 100644
--- a/src/NRF52840/AutoAnalogAudio.cpp
+++ b/src/NRF52840/AutoAnalogAudio.cpp
@@ -24,15 +24,30 @@
#include
#include
+//#define USE_I2s
+
+#if !defined __MBED__
+ #define myPDM NRF_PDM0
+ uint16_t AutoAnalog::adcBuffer16[MAX_BUFFER_SIZE];
+ bool AutoAnalog::adcReady;
+ uint32_t AutoAnalog::aSize;
+ uint8_t AutoAnalog::aCtr;
+ uint16_t *AutoAnalog::buf0;
+ uint16_t *AutoAnalog::buf1;
+ void (*AutoAnalog::_onReceive)(uint16_t *buf, uint32_t buf_len);
+#endif
+
#if !defined ARDUINO_NRF52840_FEATHER
#define PDM_IRQ_PRIORITY 7
- #define NRF_PDM_FREQ_1280K (nrf_pdm_freq_t)(0x0A000000UL) ///< PDM_CLK= 1.280 MHz (32 MHz / 25) => Fs= 20000 Hz
+ #ifndef NRF_PDM_FREQ_1280K
+ #define NRF_PDM_FREQ_1280K (nrf_pdm_freq_t)(0x0A000000UL) ///< PDM_CLK= 1.280 MHz (32 MHz / 25) => Fs= 20000 Hz
+ #endif
#define DEFAULT_PDM_GAIN 40
#endif
- #define PIN_MCK 12//(13)
+ #define PIN_MCK 15//(13)
#define PIN_SCK 13//(14)
#define PIN_LRCK 14//(15)
- #define PIN_SDOUT (28)
+ #define PIN_SDOUT (5)
#define DEFAULT_PWM_PIN 5
/****************************************************************************/
/* Public Functions */
@@ -46,29 +61,29 @@
//int16_t sine_table[] = { 0, 0, 23170, 23170, 32767, 32767, 23170, 23170, 0, 0, -23170, -23170, -32768, -32768, -23170, -23170};
AutoAnalog::AutoAnalog(){
-#if !defined ARDUINO_NRF52840_FEATHER
+
adcReady = true;
adcBitsPerSample = 8;
-#endif
+
dacBitsPerSample = 8;
autoAdjust = true;
for(int i=0; iEVENTS_HFCLKSTARTED == 0) {
+ NRF_CLOCK->TASKS_HFCLKSTART = 1;
+ while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0) { }
+ }
+ //Set default 16khz sample rate
+ NRF_PDM->RATIO = ((PDM_RATIO_RATIO_Ratio80 << PDM_RATIO_RATIO_Pos) & PDM_RATIO_RATIO_Msk);
+ nrf_pdm_clock_set(myPDM,NRF_PDM_FREQ_1280K);
+//nrf_pdm_clock_set(NRF_PDM_FREQ_1032K);
+ //nrf_pdm_clock_set(NRF_PDM_FREQ_1067K);
+ // NRF_PDM_FREQ_1000K = PDM_PDMCLKCTRL_FREQ_1000K, ///< PDM_CLK = 1.000 MHz.
+ // NRF_PDM_FREQ_1032K = PDM_PDMCLKCTRL_FREQ_Default, ///< PDM_CLK = 1.032 MHz.
+ // NRF_PDM_FREQ_1067K = PDM_PDMCLKCTRL_FREQ_1067K ///< PDM_CLK = 1.067 MHz.
+
+ //Set default channel mono
+ nrf_pdm_mode_set(myPDM,NRF_PDM_MODE_MONO, NRF_PDM_EDGE_LEFTFALLING);
+ if(gain == -1) {
+ gain = DEFAULT_PDM_GAIN;
+ }
+ nrf_pdm_gain_set(myPDM,gain, gain);
+
+ pinMode(clkPin, OUTPUT);
+ digitalWrite(clkPin, LOW);
+
+ pinMode(dinPin, INPUT);
+
+ nrf_pdm_psel_connect(myPDM,digitalPinToPinName(clkPin), digitalPinToPinName(dinPin));
+
+ //Enable PDM interrupts and clear events
+ nrf_pdm_event_clear(myPDM,NRF_PDM_EVENT_STARTED);
+ nrf_pdm_event_clear(myPDM,NRF_PDM_EVENT_END);
+ nrf_pdm_event_clear(myPDM,NRF_PDM_EVENT_STOPPED);
+ nrf_pdm_int_enable(myPDM,NRF_PDM_INT_STARTED | NRF_PDM_INT_STOPPED);
+
+ //Turn on the mic
+ if (pwrPin > -1) {
+ pinMode(pwrPin, OUTPUT);
+ digitalWrite(pwrPin, HIGH);
+ micOn=1;
+ }else{
+ Serial.println(pwrPin);
+ }
+
+ // set the PDM IRQ priority and enable
+ NVIC_SetPriority(PDM_IRQn, PDM_IRQ_PRIORITY);
+ NVIC_ClearPendingIRQ(PDM_IRQn);
+ NVIC_EnableIRQ(PDM_IRQn);
+
+ // enable and trigger start task
+ nrf_pdm_enable(myPDM);
+ nrf_pdm_event_clear(myPDM,NRF_PDM_EVENT_STARTED);
+ nrf_pdm_task_trigger(myPDM,NRF_PDM_TASK_START);
+ }
+ #endif
+
+
if(enDAC){
+ #if defined USE_I2s
// Enable transmission
- /*NRF_I2S->CONFIG.TXEN = (I2S_CONFIG_TXEN_TXEN_ENABLE << I2S_CONFIG_TXEN_TXEN_Pos);
+ NRF_I2S->CONFIG.TXEN = (I2S_CONFIG_TXEN_TXEN_ENABLE << I2S_CONFIG_TXEN_TXEN_Pos);
// Enable MCK generator
NRF_I2S->CONFIG.MCKEN = (I2S_CONFIG_MCKEN_MCKEN_ENABLE << I2S_CONFIG_MCKEN_MCKEN_Pos);
// MCKFREQ = 4 MHz
- NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV31 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
- //NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV63 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
+ //NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV31 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
+ NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV16 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
// Ratio = 64
- NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_64X << I2S_CONFIG_RATIO_RATIO_Pos;
+ NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_256X << I2S_CONFIG_RATIO_RATIO_Pos;
//NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_256X << I2S_CONFIG_RATIO_RATIO_Pos;
// Master mode, 16Bit, left aligned
@@ -167,23 +247,32 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
NRF_I2S->CONFIG.CHANNELS = I2S_CONFIG_CHANNELS_CHANNELS_LEFT << I2S_CONFIG_CHANNELS_CHANNELS_Pos;
// Configure pins
- NRF_I2S->PSEL.MCK = (PIN_MCK << I2S_PSEL_MCK_PIN_Pos);
- NRF_I2S->PSEL.SCK = (PIN_SCK << I2S_PSEL_SCK_PIN_Pos);
- NRF_I2S->PSEL.LRCK = (PIN_LRCK << I2S_PSEL_LRCK_PIN_Pos);
- NRF_I2S->PSEL.SDOUT = (PIN_SDOUT << I2S_PSEL_SDOUT_PIN_Pos);
-
-
+ //NRF_I2S->PSEL.MCK = (PIN_MCK << I2S_PSEL_MCK_PIN_Pos);
+ //NRF_I2S->PSEL.SCK = (PIN_SCK << I2S_PSEL_SCK_PIN_Pos);
+ //NRF_I2S->PSEL.LRCK = (PIN_LRCK << I2S_PSEL_LRCK_PIN_Pos);
+ //NRF_I2S->PSEL.SDOUT = (PIN_SDOUT << I2S_PSEL_SDOUT_PIN_Pos);
+ NRF_I2S->PSEL.MCK = (PIN_MCK << I2S_PSEL_MCK_PIN_Pos) | (I2S_PSEL_MCK_CONNECT_Connected << I2S_PSEL_MCK_CONNECT_Pos);
+ NRF_I2S->PSEL.SCK = (PIN_SCK << I2S_PSEL_SCK_PIN_Pos) | (I2S_PSEL_SCK_CONNECT_Connected << I2S_PSEL_SCK_CONNECT_Pos);
+ NRF_I2S->PSEL.LRCK = (PIN_LRCK << I2S_PSEL_LRCK_PIN_Pos) | (I2S_PSEL_LRCK_CONNECT_Connected << I2S_PSEL_LRCK_CONNECT_Pos);
+ NRF_I2S->PSEL.SDOUT = (PIN_SDOUT << I2S_PSEL_SDOUT_PIN_Pos) | (I2S_PSEL_SDOUT_CONNECT_Connected << I2S_PSEL_SDOUT_CONNECT_Pos);
+
+ //NRF_I2S->INTENSET = I2S_INTEN_TXPTRUPD_Enabled << I2S_INTEN_TXPTRUPD_Pos;
+ //NVIC_EnableIRQ(I2S_IRQn);
// Configure data pointer
NRF_I2S->TXD.PTR = (uint32_t)dacBuf0;
NRF_I2S->RXD.PTR = (uint32_t)dacBuf1;
- NRF_I2S->RXTXD.MAXCNT = MAX_BUFFER_SIZE / sizeof(uint32_t);
+ NRF_I2S->RXTXD.MAXCNT = 16;// / sizeof(uint32_t);
+
+
+ //NRF_I2S->INTENSET = I2S_INTENSET_TXPTRUPD_Enabled << I2S_INTENSET_TXPTRUPD_Pos;
+ //NVIC_EnableIRQ(I2S_IRQn);
//NRF_I2S->TXD.PTR = (uint32_t)&sine_table[0];
//NRF_I2S->RXTXD.MAXCNT = sizeof(sine_table) / sizeof(uint32_t);
NRF_I2S->ENABLE = 1;
// Start transmitting I2S data
- NRF_I2S->TASKS_START = 1;*/
-
+ NRF_I2S->TASKS_START = 1;
+ #else
pinMode(DEFAULT_PWM_PIN,OUTPUT);
digitalWrite(DEFAULT_PWM_PIN,LOW);
@@ -200,7 +289,7 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
NRF_PWM0->SEQ[0].ENDDELAY = 0;
NRF_PWM0->TASKS_SEQSTART[0] = 1;
-
+ #endif //USE_I2s
}
@@ -211,12 +300,12 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
void AutoAnalog::setSampleRate(uint32_t sampRate, bool stereo){
- NRF_PWM0->TASKS_STOP = 1;
+/* NRF_PWM0->TASKS_STOP = 1;
uint32_t timer = millis();
while(NRF_PWM0->EVENTS_STOPPED == 0){ if(millis() - timer > 1000){break;} }
NRF_PWM0->COUNTERTOP = (((uint16_t)((16000000/sampRate) + 5)) << PWM_COUNTERTOP_COUNTERTOP_Pos);
- NRF_PWM0->TASKS_SEQSTART[0] = 1;
+ NRF_PWM0->TASKS_SEQSTART[0] = 1;*/
}
/****************************************************************************/
@@ -230,48 +319,72 @@ void AutoAnalog::triggerADC(){
/****************************************************************************/
void AutoAnalog::enableAdcChannel(uint8_t pinAx){
-#if !defined ARDUINO_NRF52840_FEATHER
+#if defined __MBED__
nrf_pdm_enable();
+#else
+ nrf_pdm_enable(myPDM);
#endif
}
/****************************************************************************/
void AutoAnalog::disableAdcChannel(uint8_t pinAx){
-#if !defined ARDUINO_NRF52840_FEATHER
+#if defined __MBED__
nrf_pdm_disable();
+#else
+ nrf_pdm_disable(myPDM);
#endif
}
/****************************************************************************/
void AutoAnalog::getADC(uint32_t samples){
- #if !defined ARDUINO_NRF52840_FEATHER
+// #if defined __MBED__
while(!adcReady){__WFE();};
aSize = samples;
adcReady = false;
- #endif
+// #endif
}
/****************************************************************************/
-bool dacBufCtr = 0;
+
+bool whichBuf = 0;
void AutoAnalog::feedDAC(uint8_t dacChannel, uint32_t samples, bool startInterrupts){
-
- /*uint32_t ctr = millis();
- while(!nrf_i2s_event_check(NRF_I2S,NRF_I2S_EVENT_TXPTRUPD));//{ if(millis() - ctr > 5){break;}};
- nrf_i2s_event_clear(NRF_I2S,NRF_I2S_EVENT_TXPTRUPD);
+
+ #if defined USE_I2s
+ uint32_t ctr = millis();
+ //while(!nrf_i2s_event_check(NRF_I2S,NRF_I2S_EVENT_TXPTRUPD));//{ if(millis() - ctr > 5){break;}};
+
+
+
- for(uint32_t i=0; iEVENTS_TXPTRUPD == 0){}
+ NRF_I2S->EVENTS_TXPTRUPD = 0;
+
+ if(whichBuf == 0){
+ for(uint32_t i=0; iTXD.PTR = (uint32_t)dacBuf0;
+ }else{
+ for(uint32_t i=0; iTXD.PTR = (uint32_t)dacBuf1;
+ }
+ whichBuf = !whichBuf;
//memcpy(dacBuf0, dacBuffer16, samples * 2);
+
+ //NRF_I2S->TXD.PTR = (uint32_t)&dacBuf0[0];
+ //memcpy(&dacBuf[0], &dacBuffer16[0], samples);
+ uint32_t bytes = samples * 2;
+ NRF_I2S->RXTXD.MAXCNT = samples / sizeof(uint32_t);
+ //nrf_i2s_event_clear(NRF_I2S,NRF_I2S_EVENT_TXPTRUPD);
- //NRF_I2S->TXD.PTR = (uint32_t)&dacBuf0[0];
- //memcpy(&dacBuf[0], &dacBuffer16[0], samples);
- NRF_I2S->RXTXD.MAXCNT = 8;// * 2 / sizeof(uint32_t);*/
+ #else
uint32_t timer = millis();
while(NRF_PWM0->EVENTS_SEQEND[0] == 0){
if(millis() - timer > 1000){ Serial.println("return"); NRF_PWM0->TASKS_SEQSTART[0] = 1; return; }
@@ -288,6 +401,7 @@ void AutoAnalog::feedDAC(uint8_t dacChannel, uint32_t samples, bool startInterru
NRF_PWM0->SEQ[0].PTR = ((uint32_t)(&dacBuf0[0]) << PWM_SEQ_PTR_PTR_Pos);
NRF_PWM0->SEQ[0].CNT = (samples << PWM_SEQ_CNT_CNT_Pos);
NRF_PWM0->TASKS_SEQSTART[0] = 1;
+ #endif //USE_I2s
}
@@ -331,8 +445,11 @@ void AutoAnalog::dacSetup(void){
/****************************************************************************/
void AutoAnalog::disableDAC(bool withinTask){
- //NRF_I2S->ENABLE = 0;
+ #if defined USE_I2s
+ NRF_I2S->ENABLE = 0;
+ #else
NRF_PWM0->TASKS_STOP = 1;
+ #endif
}
/****************************************************************************/
@@ -358,8 +475,13 @@ void AutoAnalog::tc2Setup (uint32_t sampRate)
}
+void I2S_IRQHandler_v(void){
+ // AutoAnalog::testCounter++;
+}
+
+
/****************************************************************************/
-#if !defined ARDUINO_NRF52840_FEATHER
+#if defined __MBED__
extern "C" {
__attribute__((__used__)) void PDM_IRQHandler_v(void)
{
@@ -408,5 +530,56 @@ void AutoAnalog::adcCallback(uint16_t *buf, uint32_t buf_len){
adcReady = true;
}
-#endif //#if !defined ARDUINO_NRF52840_FEATHER
+#elif !defined MBED
+extern "C" {
+ __attribute__((__used__)) void PDM_IRQHandler(void)
+ {
+if (nrf_pdm_event_check(myPDM,NRF_PDM_EVENT_STARTED)) {
+ nrf_pdm_event_clear(myPDM,NRF_PDM_EVENT_STARTED);
+
+ // switch to fill
+
+ if (AutoAnalog::aCtr) {
+ nrf_pdm_buffer_set(myPDM,(uint32_t*)(AutoAnalog::buf0), AutoAnalog::aSize);
+ if(AutoAnalog::_onReceive){
+ NVIC_DisableIRQ(PDM_IRQn);
+ AutoAnalog::_onReceive(AutoAnalog::buf1, AutoAnalog::aSize);
+ NVIC_EnableIRQ(PDM_IRQn);
+ }
+ } else {
+ nrf_pdm_buffer_set(myPDM,(uint32_t*)(AutoAnalog::buf1), AutoAnalog::aSize);
+ if(AutoAnalog::_onReceive){
+ NVIC_DisableIRQ(PDM_IRQn);
+ AutoAnalog::_onReceive(AutoAnalog::buf0, AutoAnalog::aSize);
+ NVIC_EnableIRQ(PDM_IRQn);
+ }
+ }
+
+ // Flip to next buffer
+ AutoAnalog::aCtr = (AutoAnalog::aCtr + 1) % 2;
+
+
+ } else if (nrf_pdm_event_check(myPDM,NRF_PDM_EVENT_STOPPED)) {
+ nrf_pdm_event_clear(myPDM,NRF_PDM_EVENT_STOPPED);
+ } else if (nrf_pdm_event_check(myPDM,NRF_PDM_EVENT_END)) {
+ nrf_pdm_event_clear(myPDM,NRF_PDM_EVENT_END);
+ }
+ }
+}
+
+void AutoAnalog::set_callback(void(*function)(uint16_t *buf, uint32_t buf_len)){
+ _onReceive = function;
+}
+
+
+
+void AutoAnalog::adcCallback(uint16_t *buf, uint32_t buf_len){
+
+ for(uint32_t i=0; i < buf_len; i++){
+ adcBuffer16[i] = buf[i];
+ }
+
+ adcReady = true;
+}
+#endif
#endif //#if defined (ARDUINO_ARCH_SAM)