Skip to content

Commit db738ef

Browse files
committed
I2S Working - Rough Draft
- Add I2S option for begin() - Adjust default pins for I2S output - Set I2S default sample rate to 16kHz - Adjust buffering for I2S - Accepted Sample Rates adjusted to 16000, 20000, 32000, 44000
1 parent 655c742 commit db738ef

File tree

3 files changed

+92
-72
lines changed

3 files changed

+92
-72
lines changed

src/AutoAnalogAudio.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class AutoAnalog
4949
AutoAnalog();
5050

5151
/** Setup the timer(s) */
52-
void begin(bool enADC, bool enDAC);
52+
void begin(bool enADC, bool enDAC, uint8_t _useI2S = false);
5353

5454
/**
5555
* @note This function is no longer required and does nothing
@@ -208,6 +208,7 @@ class AutoAnalog
208208
int clkPin;
209209
int8_t gain;
210210
inline static uint32_t sampleCounter;
211+
bool useI2S;
211212

212213
#elif defined (ARDUINO_ARCH_NRF52840) || defined (ARDUINO_ARCH_NRF52) || defined (ARDUINO_NRF52840_FEATHER) && !defined __MBED__
213214
uint16_t dacBuf0[MAX_BUFFER_SIZE];
@@ -227,6 +228,7 @@ class AutoAnalog
227228
int8_t gain;
228229
uint32_t sampleCounter;
229230
//void DACC_Handler();
231+
bool useI2S;
230232
#endif
231233

232234
private:

src/AutoAnalog_config.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
#elif defined ESP32 || defined ARDUINO_ARCH_NRF52840 || defined (ARDUINO_ARCH_NRF52) || defined ARDUINO_NRF52840_FEATHER
2626

27-
#define MAX_BUFFER_SIZE 1600
27+
#define MAX_BUFFER_SIZE 6400
2828

2929
#else
3030

src/NRF52840/AutoAnalogAudio.cpp

Lines changed: 88 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,7 @@
2222

2323
#include "../AutoAnalogAudio.h"
2424
#include <hal/nrf_pdm.h>
25-
26-
//#define USE_I2s
27-
28-
#if defined USE_I2s
29-
#include <hal/nrf_i2s.h>
30-
#endif
25+
#include <hal/nrf_i2s.h>
3126

3227
#if !defined __MBED__
3328
#define myPDM NRF_PDM0
@@ -55,11 +50,15 @@
5550
/******************* USER DEFINES - Configure pins etc here *****************/
5651
#define DEFAULT_PDM_GAIN 40
5752

58-
/* I2s config */
59-
#define PIN_MCK 15//(13)
60-
#define PIN_SCK 13//(14)
61-
#define PIN_LRCK 14//(15)
62-
#define PIN_SDOUT (5) // GPIO Pin numbers
53+
/* I2s config */ // MAX98357A Breakout also needs SD pin set HIGH
54+
#define PIN_MCK 2 // Not used with MAX98357A
55+
#define PORT_MCK 0
56+
#define PIN_SCK 3 // BCLK
57+
#define PORT_SCK 0
58+
#define PIN_LRCK 29 // LRCK
59+
#define PORT_LRCK 0
60+
#define PIN_SDOUT 5 // GPIO Pin numbers
61+
#define PORT_SDOUT 0
6362

6463
/* PWM Config */
6564
#define DEFAULT_PWM_PIN 5 //GPIO Pin number
@@ -105,7 +104,7 @@ AutoAnalog::AutoAnalog(){
105104

106105
}
107106

108-
void AutoAnalog::begin(bool enADC, bool enDAC){
107+
void AutoAnalog::begin(bool enADC, bool enDAC, uint8_t _useI2S){
109108

110109
#if defined __MBED__
111110
if(enADC){
@@ -238,7 +237,7 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
238237

239238

240239
if(enDAC){
241-
#if defined USE_I2s
240+
if(_useI2S){
242241
// Enable transmission
243242
NRF_I2S->CONFIG.TXEN = (I2S_CONFIG_TXEN_TXEN_ENABLE << I2S_CONFIG_TXEN_TXEN_Pos);
244243

@@ -255,8 +254,8 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
255254
NRF_I2S->CONFIG.MODE = I2S_CONFIG_MODE_MODE_MASTER << I2S_CONFIG_MODE_MODE_Pos;
256255

257256
NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_16BIT << I2S_CONFIG_SWIDTH_SWIDTH_Pos;
258-
NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV8 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
259-
NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_256X << I2S_CONFIG_RATIO_RATIO_Pos;
257+
NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV16 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
258+
NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_128X << I2S_CONFIG_RATIO_RATIO_Pos;
260259
NRF_I2S->CONFIG.ALIGN = I2S_CONFIG_ALIGN_ALIGN_LEFT << I2S_CONFIG_ALIGN_ALIGN_Pos;
261260

262261
// Format = I2S
@@ -266,20 +265,17 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
266265
NRF_I2S->CONFIG.CHANNELS = I2S_CONFIG_CHANNELS_CHANNELS_LEFT << I2S_CONFIG_CHANNELS_CHANNELS_Pos;
267266

268267
// Configure pins
269-
NRF_I2S->PSEL.MCK = (PIN_MCK << I2S_PSEL_MCK_PIN_Pos);
270-
NRF_I2S->PSEL.SCK = (PIN_SCK << I2S_PSEL_SCK_PIN_Pos);
271-
NRF_I2S->PSEL.LRCK = (PIN_LRCK << I2S_PSEL_LRCK_PIN_Pos);
272-
NRF_I2S->PSEL.SDOUT = (PIN_SDOUT << I2S_PSEL_SDOUT_PIN_Pos);
273-
/*NRF_I2S->PSEL.MCK = (PIN_MCK << I2S_PSEL_MCK_PIN_Pos) | (I2S_PSEL_MCK_CONNECT_Connected << I2S_PSEL_MCK_CONNECT_Pos);
274-
NRF_I2S->PSEL.SCK = (PIN_SCK << I2S_PSEL_SCK_PIN_Pos) | (I2S_PSEL_SCK_CONNECT_Connected << I2S_PSEL_SCK_CONNECT_Pos);
275-
NRF_I2S->PSEL.LRCK = (PIN_LRCK << I2S_PSEL_LRCK_PIN_Pos) | (I2S_PSEL_LRCK_CONNECT_Connected << I2S_PSEL_LRCK_CONNECT_Pos);
276-
NRF_I2S->PSEL.SDOUT = (PIN_SDOUT << I2S_PSEL_SDOUT_PIN_Pos) | (I2S_PSEL_SDOUT_CONNECT_Connected << I2S_PSEL_SDOUT_CONNECT_Pos);*/
268+
NRF_I2S->PSEL.MCK = (PIN_MCK << I2S_PSEL_MCK_PIN_Pos) | (I2S_PSEL_MCK_CONNECT_Connected << I2S_PSEL_MCK_CONNECT_Pos) | (PORT_MCK << I2S_PSEL_MCK_PORT_Pos);
269+
NRF_I2S->PSEL.SCK = (PIN_SCK << I2S_PSEL_SCK_PIN_Pos) | (I2S_PSEL_SCK_CONNECT_Connected << I2S_PSEL_SCK_CONNECT_Pos) | (PORT_SCK << I2S_PSEL_SCK_PORT_Pos);
270+
NRF_I2S->PSEL.LRCK = (PIN_LRCK << I2S_PSEL_LRCK_PIN_Pos) | (I2S_PSEL_LRCK_CONNECT_Connected << I2S_PSEL_LRCK_CONNECT_Pos) | (PORT_LRCK << I2S_PSEL_LRCK_PORT_Pos);
271+
NRF_I2S->PSEL.SDOUT = (PIN_SDOUT << I2S_PSEL_SDOUT_PIN_Pos) | (I2S_PSEL_SDOUT_CONNECT_Connected << I2S_PSEL_LRCK_CONNECT_Pos) | (PORT_SDOUT << I2S_PSEL_SDOUT_PORT_Pos);
272+
277273

278274
//NRF_I2S->INTENSET = I2S_INTEN_TXPTRUPD_Enabled << I2S_INTEN_TXPTRUPD_Pos;
279275
//NVIC_EnableIRQ(I2S_IRQn);
280276

281277
// Configure data pointer
282-
NRF_I2S->TXD.PTR = (uint32_t)dacBuf0;
278+
NRF_I2S->TXD.PTR = (uint32_t)&dacBuf0[0];
283279
NRF_I2S->RXD.PTR = (uint32_t)dacBuf1;
284280
NRF_I2S->RXTXD.MAXCNT = 16;// / sizeof(uint32_t);
285281

@@ -289,9 +285,9 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
289285
//NRF_I2S->TXD.PTR = (uint32_t)&sine_table[0];
290286
//NRF_I2S->RXTXD.MAXCNT = sizeof(sine_table) / sizeof(uint32_t);
291287
NRF_I2S->ENABLE = 1;
292-
// Start transmitting I2S data
293288
NRF_I2S->TASKS_START = 1;
294-
#else
289+
useI2S = _useI2S;
290+
}else{
295291

296292
NRF_PWM0->PSEL.OUT[0] = (DEFAULT_PWM_PIN << PWM_PSEL_OUT_PIN_Pos) | (PWM_PSEL_OUT_CONNECT_Connected << PWM_PSEL_OUT_CONNECT_Pos | DEFAULT_PWM_PORT << PWM_PSEL_OUT_PORT_Pos);
297293
#if defined DEFAULT_PWM_PIN2
@@ -311,7 +307,7 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
311307
//NRF_PWM0->INTENSET = PWM_INTENSET_SEQEND0_Enabled << PWM_INTENSET_SEQEND0_Pos;
312308
//NVIC_EnableIRQ(PWM0_IRQn);
313309
NRF_PWM0->TASKS_SEQSTART[0] = 1;
314-
#endif //USE_I2s
310+
}
315311
}
316312

317313

@@ -322,14 +318,48 @@ void AutoAnalog::begin(bool enADC, bool enDAC){
322318

323319
void AutoAnalog::setSampleRate(uint32_t sampRate, bool stereo){
324320

325-
NRF_PWM0->TASKS_STOP = 1;
326-
uint32_t timer = millis();
327-
while(NRF_PWM0->EVENTS_STOPPED == 0){ if(millis() - timer > 1000){break;} }
328-
329-
NRF_PWM0->COUNTERTOP = (((uint16_t)((16000000/sampRate))) << PWM_COUNTERTOP_COUNTERTOP_Pos);
330-
NRF_PWM0->TASKS_SEQSTART[0] = 1;
331-
321+
if(!useI2S){
322+
NRF_PWM0->TASKS_STOP = 1;
323+
uint32_t timer = millis();
324+
while(NRF_PWM0->EVENTS_STOPPED == 0){ if(millis() - timer > 1000){break;} }
332325

326+
NRF_PWM0->COUNTERTOP = (((uint16_t)((16000000/sampRate))) << PWM_COUNTERTOP_COUNTERTOP_Pos);
327+
NRF_PWM0->TASKS_SEQSTART[0] = 1;
328+
}else{
329+
// Stop transmitting I2S data
330+
NRF_I2S->TASKS_STOP = 1;
331+
NRF_I2S->ENABLE = 0;
332+
333+
/*if(dacBitsPerSample == 8){
334+
NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_8BIT << I2S_CONFIG_SWIDTH_SWIDTH_Pos;
335+
}else
336+
if(dacBitsPerSample == 16){
337+
NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_16BIT << I2S_CONFIG_SWIDTH_SWIDTH_Pos;
338+
}else
339+
if(dacBitsPerSample == 24){
340+
NRF_I2S->CONFIG.SWIDTH = I2S_CONFIG_SWIDTH_SWIDTH_24BIT << I2S_CONFIG_SWIDTH_SWIDTH_Pos;
341+
} */
342+
343+
if(sampRate <= 16000){
344+
NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV16 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
345+
NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_128X << I2S_CONFIG_RATIO_RATIO_Pos;
346+
}else
347+
if(sampRate <= 20000){
348+
NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV8 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
349+
NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_256X << I2S_CONFIG_RATIO_RATIO_Pos;
350+
}else
351+
if(sampRate <= 32000){
352+
NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV16 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
353+
NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_64X << I2S_CONFIG_RATIO_RATIO_Pos;
354+
}else
355+
if(sampRate <= 44000){
356+
NRF_I2S->CONFIG.MCKFREQ = I2S_CONFIG_MCKFREQ_MCKFREQ_32MDIV23 << I2S_CONFIG_MCKFREQ_MCKFREQ_Pos;
357+
NRF_I2S->CONFIG.RATIO = I2S_CONFIG_RATIO_RATIO_32X << I2S_CONFIG_RATIO_RATIO_Pos;
358+
}
359+
NRF_I2S->ENABLE = 1;
360+
NRF_I2S->TASKS_START = 1;
361+
}
362+
333363
if(sampRate <= 16000){
334364
//Set default 16khz sample rate
335365
NRF_PDM->RATIO = ((PDM_RATIO_RATIO_Ratio80 << PDM_RATIO_RATIO_Pos) & PDM_RATIO_RATIO_Msk);
@@ -347,15 +377,15 @@ void AutoAnalog::setSampleRate(uint32_t sampRate, bool stereo){
347377
nrf_pdm_clock_set(myPDM,NRF_PDM_FREQ_1280K);
348378
#endif
349379
}else
350-
if(sampRate <= 31250){
380+
if(sampRate <= 32000){
351381
NRF_PDM->RATIO = ((PDM_RATIO_RATIO_Ratio64 << PDM_RATIO_RATIO_Pos) & PDM_RATIO_RATIO_Msk);
352382
#if defined __MBED__
353383
nrf_pdm_clock_set(NRF_PDM_FREQ_2000K); //2667 / 64 = 33.337khz, /80 = 41.667
354384
#else
355385
nrf_pdm_clock_set(myPDM, NRF_PDM_FREQ_2000K); //2667 / 64 = 33.337khz, /80 = 41.667
356386
#endif
357387
}else
358-
if(sampRate <= 41672){
388+
if(sampRate <= 44000){ //41.67khz
359389
NRF_PDM->RATIO = ((PDM_RATIO_RATIO_Ratio64 << PDM_RATIO_RATIO_Pos) & PDM_RATIO_RATIO_Msk);
360390
#if defined __MBED__
361391
nrf_pdm_clock_set(NRF_PDM_FREQ_2667K);
@@ -409,53 +439,41 @@ bool whichBuf = 0;
409439

410440
void AutoAnalog::feedDAC(uint8_t dacChannel, uint32_t samples, bool startInterrupts){
411441

412-
#if defined USE_I2s
442+
if(useI2S){
413443
uint32_t ctr = millis();
414444
//while(!nrf_i2s_event_check(NRF_I2S,NRF_I2S_EVENT_TXPTRUPD));//{ if(millis() - ctr > 5){break;}};
415445

416446

417447

418-
419448
while(NRF_I2S->EVENTS_TXPTRUPD == 0){}
420-
NRF_I2S->EVENTS_TXPTRUPD = 0;
421449

450+
422451
if(dacBitsPerSample == 8){
423-
//memcpy(dacBuf0,dacBuffer, samples);
424-
for(uint32_t i=0; i<samples; i++){
425-
dacBuf0[i] = dacBuffer[i] << 8;
452+
for(uint32_t i=0; i< samples; i++){
453+
dacBuf0[i] = dacBuffer[i] << 7;
426454
}
427-
NRF_I2S->TXD.PTR = (uint32_t)dacBuf0;
428-
}else{
429-
if(whichBuf == 0){
430-
for(uint32_t i=0; i<samples; i++){
431-
dacBuf0[i] = dacBuffer16[i];
432-
}
433-
NRF_I2S->TXD.PTR = (uint32_t)dacBuf0;
434-
}else{
435-
for(uint32_t i=0; i<samples; i++){
436-
dacBuf1[i] = dacBuffer16[i];
437-
}
438-
NRF_I2S->TXD.PTR = (uint32_t)dacBuf1;
439-
}
440-
whichBuf = !whichBuf;
455+
NRF_I2S->TXD.PTR = (uint32_t)&dacBuf0[0];
456+
}else
457+
if(dacBitsPerSample == 16){
458+
memcpy(dacBuf0,dacBuffer16,samples * 2);
459+
NRF_I2S->TXD.PTR = (uint32_t)&dacBuf0[0];
441460
}
442-
//memcpy(dacBuf0, dacBuffer16, samples * 2);
443-
444-
//NRF_I2S->TXD.PTR = (uint32_t)&dacBuf0[0];
445-
//memcpy(&dacBuf[0], &dacBuffer16[0], samples);
446-
uint32_t bytes = samples;
447-
461+
462+
uint8_t divider = 2;
448463
if(dacBitsPerSample == 16){
449-
bytes *= 2;
464+
divider = 2;
465+
}else
466+
if(dacBitsPerSample == 24){
467+
divider = 1;
450468
}
451469

452-
NRF_I2S->RXTXD.MAXCNT = samples / sizeof(uint32_t);
453-
//nrf_i2s_event_clear(NRF_I2S,NRF_I2S_EVENT_TXPTRUPD);
454-
455-
#else
456-
uint32_t timer = millis();
470+
NRF_I2S->RXTXD.MAXCNT = samples / divider;
471+
NRF_I2S->EVENTS_TXPTRUPD = 0;
472+
473+
}else{
474+
uint32_t timer = millis() + 1000;
457475
while(NRF_PWM0->EVENTS_SEQEND[0] == 0){
458-
if(millis() - timer > 1000){ NRF_PWM0->TASKS_SEQSTART[0] = 1; return; }
476+
if(millis() > timer ){ NRF_PWM0->TASKS_SEQSTART[0] = 1; return; }
459477
}
460478
NRF_PWM0->EVENTS_SEQEND[0] = 0;
461479

@@ -469,7 +487,7 @@ void AutoAnalog::feedDAC(uint8_t dacChannel, uint32_t samples, bool startInterru
469487
NRF_PWM0->SEQ[0].PTR = ((uint32_t)(&dacBuf0[0]) << PWM_SEQ_PTR_PTR_Pos);
470488
NRF_PWM0->SEQ[0].CNT = (samples << PWM_SEQ_CNT_CNT_Pos);
471489
NRF_PWM0->TASKS_SEQSTART[0] = 1;
472-
#endif //USE_I2s
490+
}
473491

474492
}
475493

0 commit comments

Comments
 (0)