Here is my first Audio project that uses PIC32MX470 CPU (MIP32 M4K from Microchip) and WM8904 Audio codec.
Here is scope (Digilent Analog Discovery 2
) connected to Headphones outputs (both
channels) and few digital signals:
And here detail of I2S signals (that transmit digital Audio). It is important that next DMA transfer starts before new I2S frame - otherwise extra 0 sample will be inserted and will cause noticeable clicks in sound:
And Digilent WaveForms
Workspace file:
I recently acquired:
-
PIC32MX470-Curiosity DM320103 development board
-
PIC32 Audio Codec Daughter Board WM8904 AC328904 codec board that uses pair of connectors known as X32
WARNING! Official recommended codec for this card is PIC32 Audio Codec Daughter Board - AK4642EN but it is harder to get. So all codec stuff or recommendations are WITHOUT ANY WARRANTY!
However I need somehow to start with some introductory projects.
Most important links regarding Curiosity board:
- Official start URL for PIC32MX470-Curiosity DM320103
- PIC32MX470 Curiosity Development Board User’s Guide
Links for CPU PIC32MX470F512H
- datasheet PIC32MX470F512H - DS60001185H
- errata - IMPORTANT!: DS80000574
- it is
MIPS32(R) M4K
CPU Core.- MIPS32 M4K Manual from mips.com
- MIPS32 M4K Core Datasheet from mips.com
- MIPS32 Instruction Set from mips.com
- MIPS32 Instruction Set Quick Reference from mips.com
Required hardware:
- PIC32MX470-Curiosity DM320103 development board
- PIC32 Audio Codec Daughter Board WM8904 AC328904 inserted on X32 connector of development board
Ensure that Jumpers are in these default positions - see PIC32MX470 Curiosity Development Board User’s Guide for details:
Power Jumper J8
:
- middle position, left label
PKOB
(PicKit on board debugger)
External/internal Debugger Jumper J2
:
- Pins 1-2 and 3-4 shorted (using single rectangular Jumper)
Audio Codec setup:
- All Jumpers on Audio card (J6,J7,J8,J9) should be on right position (where is small white circle) to use I2S1 signals (only these are connected on MX470 Curiosity board)
- Codec card has to be properly inserted to X32 slots of Curiosity mainboard (there are 2 connectors that must properly match)
Important information on Audio Codec Daughter card:
- codec WM8904 and WM8904 Datasheet
Connecting board to USB:
- use
USB mini-B (J3)
- it is located at Left BOTTOM of board (!)
- there is also white label
USB DEBUG
- NOTE: That Left-top micro-USB connector is for USB connection to PIC32MX! (that can work both as Host and/or as Device) using recent USB OTG (On-The-Go) protocol.
Extracted from manual PIC32MX470 Curiosity Development Board User’s Guide.
- CPU is
U9
partPIC32MX470F512H-120/PT
,- package: code
PT
=> 64-pin, TQFP (visible pins) - Note: it is important to know proper package when using Pin-Manager tool in MCC Harmony tool
- package: code
- X2 20 MHz crystal oscillator - this precision clock source
is required when using USB on PIC32MX CPU and should be also
used when working with Audio Codec that is sensitive to any kind
of jitter. It must be configured on this PIC as
Primary HS
(Primary High Speed oscillator).
To see known peripheral you can also look at Board Support Package (BSP)
Here is my curated list:
PIC32MX Pin | PIC32MX Function | Peripheral | Active level (0/1) |
---|---|---|---|
7 | /MCLR | RESET Button /MCLR (between USB connectors) | 0 |
54 | RD6 | Switch S1 | 0 |
64 | RE4 | LED1 red | 1 |
2 | RE6 | LED2 yellow | 1 |
3 | RE7 | LED3 green | 1 |
23 | RB10 | RGB LED4 - red | 0 |
13 | RB3 | RGB LED4- green | 0 |
14 | RB2 | RGB LED4 - blue | 0 |
39 | OSC1 | 20 MHz crystal - CPU osc input | - |
40 | OSC2 | 20 MHz crystal - CPU osc output | - |
Currently all project use:
- MPLAB X IDE v6.15 (latest version as of Sep 2023)
- XC32 v4.30 (latest version as of Sep 2023)
- MCC Harmony generator
Common project properties:
- on TRAP, RGB LED should permanently lit RED, and all 3 LED1, LED2 and LED3 should be lit.
This "warm up" project just tests (using PWM to divide 20 MHz High-Speed resonator clock to 1 Mhz and outputs it on OC1 pin.
Please see dedicated mx470osctest/
The goal is to produce two tone siren on Headphones Output of Audio Coded Daughter card. It is an adventurous attempt to reproduce project for SAME70: https://github.com/Microchip-MPLAB-Harmony/audio/wiki/quick_start
- However there is important catch! We may not use Audio template to setup all components and their binding, because such Template is empty for PIC32MX
Status: Finally It Works properly!
Current function:
- produces 1 kHz Sine waveform on WM8904 Codec Headphones stereo output
- S1 switch can be used to (un)mute audio output. When muted, orange LED3 is On.
- green LED2 Toggles on every "DMA Complete" interrupt.
- red LED1 is On in case of fatal error.
- RGB LED is Red or Magenta on fatal exception.
- various Debug and status messages on UART (mikroBus 1, pin TX -> PIC output, PC input), speed 115200 Baud, 8-bit data, 1 stop bit, no parity, no flow control
Important manual fixes to code Generated with MCC Tool:
2023-09-19:
- fixed latency (caused extra 0 sample inserted on DMA start) by adding 2nd DMA buffer to Queue right after 1st buffer (do not wait for "DMA Complete" interrupt.
- this fixed also clicking issue.
2023-09-17:
- it generally works (produces 1 kHz sine output on headphones), but there are two unresolved problems:
- when new buffer is added on DMA there is spurious extra 0 Frame on sine waveform. Shown on picture below:
- also provided
Digilent Analog Discovery 2
workspace file on: - assets/wm8904/i2s/problems/MX470-Curiosity-siren-i2s-bclk-analog-trigger.dwf3work
NOW I know where is the problem: For some reason, ENHBUF=0 and setup of new DMA transfer takes
15 micro-seconds. (RE3_ADDBUF
on Digital analyzer)
Here is detail from Digital Analyzer:
-
Power Up Startup is wonky - after pushing MCLR/RESET button it works properly
-
There are noticeable clicks heard in headphones with frequency similar to DMA switches - however I'm unable to spot them on scope (I think that this extra 0 in sine does not produce such click sound)
TIP: Switch S1 now mutes/unmutes Audio. Mute change also printed on UART output.
Other notes:
Had to manually set FRMPOL=0
as required for standard I2S (symptom was that left
and right channel output was offset by 1 sample):
// mx470siren/firmware/src/config/default/audio/peripheral/i2s/plib_i2s2.c
#define SPI2_CON_FRMPOL (0 << _SPI2CON_FRMPOL_POSITION)
Some clever guy decided that this setting should be hidden, as can be seen under:
# .../harmony-repo/audio/peripheral/spi_01329/config/spi.py
def instantiateComponent(i2sComponent):
i2sSym_SPI_SPICON_FRMPOL = i2sComponent.createIntegerSymbol("I2S_SPICON_FRMPOL", None)
i2sSym_SPI_SPICON_FRMPOL.setDefaultValue(1)
i2sSym_SPI_SPICON_FRMPOL.setVisible(False)
Buffer debug info:
app.c:124 data: 0,4276,...,-8480,-4276
app.c:126 bufsize=38400
The 38400 is buffer size in bytes, to get number of samples divide it by 4 (because there are 2 bytes for left channel and 2 bytes for right channel, per sample): 9600
channel=0
srcAddr=0xA0009960
srcSize=0x00009600
destAddr=0xBF805A20
destSize=2
cellSize=2
When ratio is 4, DMA parameters are exactly same(!)
WARNING!
MCC Harmony tool sometimes screws I2S0 instance component, removing required sources on Generate action. The remedy is to always check:
- Project Graph -> I2S Driver -> click on
Instance 0
.- if
Configuration Options
tab is empty (onlyI2S
word is shown), you are in trouble- in such case Do NOT click on Generate, but close and open MCC Harmony - it usually helps(!)
2023-09-15
- Got it working! Not sure abto
- Most important discovery:
- when WM8904 is set to be Slave
- I2S2 MUST be Master ! (opposite)
- because Plib somehow does not like
- Most important discovery:
Today looking at I2S clock issue (no clock output).
-
fixed MCLK, BCLK and LRCLK - need to verify remainder of things
-
using debug message got:
_samplingRateSet:1814 bitClk=1,536,000 mclk=12,288,000
-
where
mclk = bitClk * 8
-
and 1,536,000 / 32 = 48,000 (our sample rate)
-
generated code is expecting internal MCLK signal from REFCLOKO, which was not yet entable...
Stored analysis data are under:
-
where:
*.dwf3work
- I2C capture Workspace forDigilent Analog Discovery 2
, softwareDigilent WaveForms
Workspace v3.20.1*.ods
- spreadsheet in LibreOffice 7.5 format
-
WARNING! These data are very incomplete as can be compared with debug messages...
-
finished import of skeleton from: https://github.com/Microchip-MPLAB-Harmony/audio/wiki/quick_start + many fixes.
-
there is one task, that copies S1 button state to LED3
-
there is Debug console output on UART1 (see below for more info)
-
on startup it produces output:
Starting ../src/app.c:143 - Codec App v1.00 ../src/app.c:148 Finished APP_Initialize(). ../src/app.c:171 Initializing codec... ../src../src/app.c:189 OK: Codec initialized ../src/app.c:202 Setting Up codec buffers... ../src/app.c:216 Playing sound (Buffer ping-pong)...
-
the wrong src line is probably from overflown ring buffer... or some kind of thread race with other app
Current diagnostics:
- soldered J9 and J11 on PIC32MC470 Curiosity to get access to second I2C (Codec control) and some SPI2/I2S2 signals (but not all)
- I2C with Digilent Analog Discovery 2
- Init sequence: 0x1A write 0x00 ACK, 0xFF ACK,0xFF ACK, STOP
CPU pin | Curiosity Pin J14 | Curiosity Signal J14 | Board signal | WM8904 Pin | WM8904 Signal |
---|---|---|---|---|---|
X | 6 | RPD0/INT0 | UART1_RTS# |
1 | IRQ/GPIO1 |
32 | 7 | RPF5/SCL2 | SCL1 | 2 | SCL |
31 | 9 | RPF4/SDA2 | SDA1 | 3 | SDA |
8 | 10 | RPG9/SS2 (out) | I2S1_RCL |
30 | LRCLK |
5 | 11 | RPG7/SDI2 | I2S1_MISO |
31 | ADCDAT |
4 | 12 | RPG6/SCK2 | I2S1_BCLK |
29 | BCLK |
6 | 13 | RPG8/SDO2 | I2S1_MOSI |
32 | DACDAT |
21 | 14 | RPB8/REFCLKO | I2S1_MCLK |
MCLK |
Additional Peripherals:
- Pin 12, RB4, mikroBus 1, J5, pin 1 "AN" - trigger for scope when transfer starts
- RGB LED:
- Lits RED on general exception forever
- Lits Magenta on bootstrap exception forever
- Application #2: Copies state of Button S1 to LED3.
- Console output redirected to UART1, using J5 mikroBus1 connector
RX (Input to PIC) and TX (Output from PIC)
- connect using any cand of 3.3V TTL UART cable to USB, and set 115200 Baud, 8-bit data, no-parity, no flow-control
Regarding MCC Harmony code generator - there is Audio Codec Library for WM8904 on:
- https://github.com/Microchip-MPLAB-Harmony/audio/tree/master/driver/codec/WM8904
- and here is even Example for SAM Atmel: Harmony WM8904 Example
This does not work (probably PIC470MX not supported):
- Device Resources -> Libraries -> Harmony -> Audio -> Templates -> WM8904 Codec
Tips:
How to resolve error - missing include system/dma/sys_dma.h
- invoke MCC
- select
Project Graph
tab - click on
Core / Harmony Core Service
- Enable checkbox
Enable System DMA
- click on
Generate ...
Once you resolve this error you will get another one related to SYS_TIME...
- to fix it again invoke MCC
- add Device Resources -> Libraries -> Harmony -> System Services -> TIME
- you need to also add TMR provider
- so also add Device Resources -> Libraies ->
Harmony -> Peripherals -> CORE TIMER -> CORE TIEMR
- keep Comapre period 1ms (not sure if it is not too much)
- Do NOT touch any other settings! They will be modified automatically in next step!
- now on Project Graph connect CORE TIMER -> TMR to TIME System Service -> TMR
This time I got following error:
../src/config/default/audio/peripheral/i2s/plib_i2s2.c: In function 'I2S2_LRCLK_Get':
../src/config/default/audio/peripheral/i2s/plib_i2s2.c:114:31: \
error: 'PORTA' undeclared (first use in this function); did you mean 'PORTG'?
volatile uint32_t ret = ((PORTA >> 0) & 0x1);
While looking for Temperature sensor applications (!) I have found even more simplistic Tone generator version for SAM:
- https://github.com/Microchip-MPLAB-Harmony/audio_apps/blob/master/apps/simple_tone_generator/firmware/src/app.c
- it is clear that above source was copy & pasted from Temperature sensor source...
- however it is not much practical in most cases because it uses polling for I2S. But there are some trivial cases where it can be good enough, like simple signal generators...