Created Wed, 31 Dec 2014 11:40:27 +0000 by madias
Wed, 31 Dec 2014 11:40:27 +0000
Hello, I ordered some TDA1543 I2s-DAC's for playing around with DDS. Since there is no I2s library for MPIDE or UECIDE I've to do it the manually way. There is a nice side http://ackspace.nl/wiki/DSP_experiments getting (basically) the I2s to work (written for MPLAB) so I'm trying to do a conversation for UECIDE and I got conflict problems with the interrupts, and got an error message I cannot translate/solve. So my guess is, there must be some pre definitions done in UECIDE/MIDE.
At first the error message: • Compiling sketch... /var/folders/ln/8kb3rdvx5651l9tgm4j8nkt80000gn/T//ccCWBQGj.s: Assembler messages: /var/folders/ln/8kb3rdvx5651l9tgm4j8nkt80000gn/T//ccCWBQGj.s:2873: Error: symbol `__vector_dispatch_31' is already defined Failed compiling sketch
According to http://chipkit.net/pic32-interrupt-vectors/ the IRQ 23 (_SPI_1_VECTOR) should be unused...i tried all numbers(xx) up to 44 and every interrupt gives me an error back: void __ISR(xx, ipl3) SPI1handler() The code (problem is the interrupt routine):
[color=#FF0000]EDIT:[/color] deleted irrelevant code example
thank you and regards Matthias
Wed, 31 Dec 2014 12:27:14 +0000
Ok, I've put the ISR-routine within an
extern "C" {}
No compiling errors anymore, but no time to test, yet :/
More details: http://chipkit.net/forum/viewtopic.php?f=14&t=2850
Thu, 01 Jan 2015 13:12:09 +0000
To do DDS with I2C DACs is something I would not recommend, unless you going to generate signals up to few kHz. You need fast SPI or better a fast parallel input DACs, with latter you may get maybe a megahertz.
The best bet is to ask Analog Devices for samples and play with ie. AD98xx, AD99xx DDS chips, they can do up to 500MHz output :)
On ebay there is a module for few bugs available with an older AD9850/51 (goes up to 30/60MHz output).
You load the frequency word via SPI in it and you get the required sin/cos/rect/triangle etc. frequency at the output immediately. You may change the frequency millions times per second (frequency hopping, spread spectrum), with microHz resolution (24-32-48bit frequency words based on type), output frequency from zero up to DDS_clock/3 (or /2 with more noise).
AD produces maybe 30 various DDS chips.
Thu, 01 Jan 2015 15:22:58 +0000
Dear pito, I use the DDS for a synthesizer (audio) project, so the few kHz are okay! I know the ADxx DDS chips well, but you cannot use them for wavetables. In my last project I used TLC7528 8-bit parallel DAC's. They have an excellent performance, but on the downside you need building a 4-voice synth 8-bit ~34 pins. Ordinary SPI DAC's like the MCP49xx are much too slow, see my post at http://chipkit.net/forum/viewtopic.php?f=19&t=3116 My goal is to cascade some of the I2s chips for a 4-6 voice synth with one MCU. regards Matthias
Mon, 05 Jan 2015 15:20:10 +0000
I've now written a working code for the TDA1543. But there is a strange issue: I got only (the first) 8bits working! I'm brooding around with different settings, but no luck, so playing a 8-bit sine wave on left and a 8-bit saw on the right - no problem, but 16 bits are impossible. I even wired up my logic analyzer with i2s protocol support: everything out of the PIC32 looks correct without errors. I also used a potentiometer for calibrating the vref-offset. The sine in 16bit looks like the data will repeat and are overwritten. I also get the full voltage out of the DAC. The specs (clock rate, max MHZ) are all within and below the specs. Maybe I missed something completely or I've got faulty china fake parts?
Some Infos from the datasheet: The TDA1543 accepts input serial data formats in two's complement with any bit length. Left and right data words are time multiplexed. The most significant bit (bit 1) must always be first.
With a LOW level on the word select (WS) input data is placed in the left input register and with a HIGH level on the WS input data is placed in the right input register. The data in the input registers is simultaneously latched in the output registers which control the bit switches.
Here is the protocol from the TDA1543 datasheet and my code:
// basic I2s with TDA1543 test. currently only 8-bit available
int unsigned sinetable[256] = {
128, 131, 134, 137, 140, 143, 146, 149, 152, 156, 159, 162, 165, 168, 171, 174,
176, 179, 182, 185, 188, 191, 193, 196, 199, 201, 204, 206, 209, 211, 213, 216,
218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 237, 239, 240, 242, 243, 245,
246, 247, 248, 249, 250, 251, 252, 252, 253, 254, 254, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 254, 254, 253, 252, 252, 251, 250, 249, 248, 247,
246, 245, 243, 242, 240, 239, 237, 236, 234, 232, 230, 228, 226, 224, 222, 220,
218, 216, 213, 211, 209, 206, 204, 201, 199, 196, 193, 191, 188, 185, 182, 179,
176, 174, 171, 168, 165, 162, 159, 156, 152, 149, 146, 143, 140, 137, 134, 131,
128, 124, 121, 118, 115, 112, 109, 106, 103, 99, 96, 93, 90, 87, 84, 81,
79, 76, 73, 70, 67, 64, 62, 59, 56, 54, 51, 49, 46, 44, 42, 39,
37, 35, 33, 31, 29, 27, 25, 23, 21, 19, 18, 16, 15, 13, 12, 10,
9, 8, 7, 6, 5, 4, 3, 3, 2, 1, 1, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 5, 6, 7, 8,
9, 10, 12, 13, 15, 16, 18, 19, 21, 23, 25, 27, 29, 31, 33, 35,
37, 39, 42, 44, 46, 49, 51, 54, 56, 59, 62, 64, 67, 70, 73, 76,
79, 81, 84, 87, 90, 93, 96, 99, 103, 106, 109, 112, 115, 118, 121, 124
};
volatile boolean channel=0;
#include <p32xxxx.h>
#define refclock 6 // Referenzclock auf pin6 als test
#define mosipin 18
#define sspin 9
volatile int unsigned xx=0;
void setup() {
// setup pins & mapping
pinMode(refclock, OUTPUT); // System Clock Output for analyse
pinMode(mosipin, OUTPUT); // data
pinMode(sspin, OUTPUT); // bck
mapPps(refclock, PPS_OUT_REFCLKO);
mapPps(mosipin, PPS_OUT_SDO1);
mapPps(sspin, PPS_OUT_SS1);
// setup reference clock
REFOCONbits.ROSEL = 6; // Reference Clock Source Select USB
REFOCONbits.RODIV = 3;
REFOTRIMbits.ROTRIM = 464; // 48khz; 452 for 44,1khz ->FPB=40mhz
REFOCONbits.ON = 1; // Reference Oscillator Module enabled
REFOCONbits.OE = 1; // Reference clock is driven out on REFCLKO pin
// Configure the SPI port to take its clock from the REFCLK and
// operate in I2S mode
SPI1CONbits.ON = 0; // 0 SPI off
SPI1CONbits.FRMEN = 0; // 0 Framed SPI support is disabled
SPI1CONbits.FRMSYNC = 0; // 0 Frame sync pulse output (Master mode)
SPI1CONbits.FRMPOL = 0; // 0 Frame pulse is active-low
SPI1CONbits.MSSEN = 0; // 0 Slave select SPI support is disabled
SPI1CONbits.FRMSYPW = 0; // 0 Frame sync pulse is one clock wide
SPI1CONbits.FRMCNT = 0b000; // 000 = Generate a frame sync pulse on every data character
SPI1CONbits.MCLKSEL = 1; // Master clock: 1 = MCLK is used by the Baud Rate Generator 0 = PBCLK is used by the Baud Rate Generator
SPI1CONbits.SPIFE = 0; // Frame Sync Pulse Edge Select bit 0 = Frame synchronization pulse precedes the first bit clock
SPI1CONbits.ENHBUF = 1; // 1 = Enhanced Buffer mode is enabled
SPI1CONbits.SIDL = 0; // 0 = Continue operation in Idle mode
SPI1CONbits.DISSDO = 0; // Disable SDOx pin bit 1 = SDOx pin is not used by the module (pin is controlled by associated PORT register)
SPI1CONbits.MODE32 = 0; // 16 bit per channel
SPI1CONbits.MODE16 = 0; // 16 bit per channel
SPI1CONbits.SMP = 0; // SPI Data Input Sample Phase bit 1 = Input data sampled at end of data output time 0 = Input data sampled at middle of data output time
SPI1CONbits.CKE = 0; // SPI Clock Edge Select bit 1 = Serial output data changes on transition from active clock state to idle clock state (see CKP bit) = Serial output data changes on transition from idle clock state to active clock state (see CKP bit)
SPI1CONbits.SSEN = 0; // Slave Select Enable (Slave mode) bit 1 = SSx pin used for Slave mode 0 = SSx pin not used for Slave mode, pin controlled by port unction.
SPI1CONbits.CKP = 0; // Clock Polarity Select bit 1 = Idle state for clock is a high level; active state is a low level 0 = Idle state for clock is a lowlevel; active state is a high level
SPI1CONbits.MSTEN = 1; // 1=Master mode
SPI1CONbits.DISSDI = 1; // 0 = Disable SDI bit
SPI1CONbits.STXISEL = 0b11; // 11 = SPIxTXIF is set when the buffer is not full (has one or more empty elements)
SPI1CONbits.SRXISEL = 0b00; //
SPI1CON2bits.SPISGNEXT = 0; // 0 = Data from RX FIFO is not sign extened
SPI1CON2bits.FRMERREN = 0; // 0 = Frame Error does not generate error interrupts
SPI1CON2bits.SPIROVEN = 0; // 0 = Receive overflow does not generate error interrupts
SPI1CON2bits.SPITUREN = 0; // 0 = Transmit Underrun does not generate error interrupts
SPI1CON2bits.IGNROV = 1; // Ignore Receive Overflow bit (for Audio Data Transmissions)
SPI1CON2bits.IGNTUR = 1; // Ignore Transmit Underrun bit (for Audio Data Transmissions) 1 = A TUR is not a critical error and zeros are transmitted until thSPIxTXB is not empty 0 = A TUR is a critical error which stop SPI operation
SPI1CON2bits.AUDEN = 1; // Enable audio mode
SPI1CON2bits.AUDMONO = 0; // Stereo audio
SPI1CON2bits.AUDMOD = 0b00; // I2S mode
SPI1BRG = 3; // 192000Hz SPI clock = 4 bytes per sample @ 48000sps
SPI1CONbits.ON = 1; // Turn it on
// setup SPI interrupt
INTSetVectorPriority(INT_SPI_1_VECTOR, INT_PRIORITY_LEVEL_4);
INTSetVectorSubPriority(INT_SPI_1_VECTOR, INT_SUB_PRIORITY_LEVEL_0);
INTEnable(INT_SPI1TX, INT_ENABLED);
}
void loop() {
delay(5); //nothing to do here
}
extern "C"
{
void __ISR(_SPI_1_VECTOR, ipl4) SPI1InterruptHandler(void) { // I2s Data out
if (SPI1BUF ==0)
channel=!channel; // flip L-R channels
if (channel==0)
{
xx++; // next sinus value in table
if (xx>=255)
xx=0;
SPI1BUF = (sinetable[xx]); // create sinus channel A
}
else SPI1BUF = xx; // create saw channel B
{
}
INTClearFlag(INT_SPI1TX);
}
}
Has somebody any hint or clue?
Thanks & regards Matthias
Mon, 05 Jan 2015 17:37:53 +0000
Attached is a sketch that I have used with the PIC32MX470F512H chip. It plays raw audio from an SD card at CD quality.
#include <FFT.h>
#include <DSPI.h>
#include <SD.h>
#include <DebouncedInput.h>
File myFile;
DSPI0 sdcard;
//DSPI1 audio;
Sd2Card card(&sdcard, 27);
//Sd2Card card(PIN_G8, PIN_G7, PIN_G6, PIN_C2);
SDClass myCard(card);
DebouncedInput button(PIN_BTN1, 30, false);
const int BSIZE = 2048;
int16_t bufferA[BSIZE];
int16_t bufferB[BSIZE];
int16_t bufferC[BSIZE];
int16_t real[1024];
int16_t complex[1024];
volatile uint8_t bufferAFull = 0;
volatile uint8_t bufferBFull = 0;
int fnum = 1;
int maxfile = 12;
int16_t bassValue = 0;
int16_t midValue = 0;
const uint8_t bassPin = 22;
const uint8_t midPin = 23;
const int16_t bassBucket = 1;
const int16_t midBucket = 4;
const int16_t bassThresh = 750;
const int16_t midThresh = 750;
void __attribute__((interrupt(),nomips16)) DMA1ISR(void) {
DCH2CONbits.CHEN = 1;
clearIntFlag(_DMA1_IRQ);
DCH1INTbits.CHSDIF = 0;
bufferAFull = 0;
}
void __attribute__((interrupt(),nomips16)) DMA2ISR(void) {
DCH1CONbits.CHEN = 1;
clearIntFlag(_DMA2_IRQ);
DCH2INTbits.CHSDIF = 0;
bufferBFull = 0;
}
void initDMA() {
DCH1INTbits.CHSDIE = 1;
DCH1SSA = ((unsigned int)bufferA) & 0x1FFFFFFF;
DCH1DSA = ((unsigned int)&SPI1BUF) & 0x1FFFFFFF;
DCH1SSIZ = BSIZE*2;
DCH1DSIZ = 2;
DCH1CSIZ = 2;
DCH1ECONbits.SIRQEN = 1;
DCH1ECONbits.CHSIRQ = _SPI1_TX_IRQ;
setIntVector(_DMA_1_VECTOR, (isrFunc)DMA1ISR);
setIntPriority(_DMA_1_VECTOR, 2, 0);
setIntEnable(_DMA1_IRQ);
DCH1CONbits.CHAEN = 0;
DCH1CONbits.CHEN = 1;
DCH2INTbits.CHSDIE = 1;
DCH2SSA = ((unsigned int)bufferB) & 0x1FFFFFFF;
DCH2DSA = ((unsigned int)&SPI1BUF) & 0x1FFFFFFF;
DCH2SSIZ = BSIZE*2;
DCH2DSIZ = 2;
DCH2CSIZ = 2;
DCH2ECONbits.SIRQEN = 1;
DCH2ECONbits.CHSIRQ = _SPI1_TX_IRQ;
setIntVector(_DMA_2_VECTOR, (isrFunc)DMA2ISR);
setIntPriority(_DMA_2_VECTOR, 2, 0);
setIntEnable(_DMA2_IRQ);
DCH2CONbits.CHAEN = 0;
DCH2CONbits.CHEN = 0;
DMACONbits.ON = 1;
}
void setup() {
Serial.begin(9600);
button.begin();
pinMode(bassPin, OUTPUT);
pinMode(midPin, OUTPUT);
// Power cycle the SD card
pinMode(PIN_POWER, OUTPUT);
digitalWrite(PIN_POWER, LOW);
delay(1000);
digitalWrite(PIN_POWER, HIGH);
if (!myCard.begin(27)) {
Serial.println("Unable to init SD card");
} else {
Serial.println("Configured SD card OK");
}
// 256x oversample clock output on D12 (pin 79)
unsigned long sampleRate = 44100;
// unsigned long sampleRate = 8000;
unsigned long serialClock = sampleRate * 32;
unsigned long referenceClock = serialClock * 8;
unsigned long inputFrequency = F_CPU / 2;
unsigned long referenceDiv = inputFrequency / referenceClock;
unsigned long referenceTrim = (((float)inputFrequency / (float)referenceClock) - referenceDiv) * 512.0;
pinMode(1, OUTPUT);
mapPps(1, PPS_OUT_REFCLKO);
REFOCONbits.ON=0;
REFOCONbits.ACTIVE=0;
REFOCONbits.OE=1;
REFOCONbits.ROSEL=0;
REFOCONbits.RODIV=referenceDiv; // 3
REFOTRIMbits.ROTRIM=referenceTrim; // 464;
REFOCONbits.ACTIVE=1;
REFOCONbits.ON=1;
// audio.begin();
// Map an SPI port to pins in the same area
// mapPps(PIN_D3, PPS_IN_SDI1);
pinMode(10, OUTPUT);
mapPps(10, PPS_OUT_SS1);
pinMode(9, OUTPUT);
mapPps(9, PPS_OUT_SDO1);
// Configure the SPI port to take its clock from the REFCLK and
// operate in I2S mode
SPI1CONbits.ON = 0;
SPI1CONbits.FRMEN = 0;
SPI1CONbits.FRMSYNC = 0;
SPI1CONbits.FRMPOL = 0;
SPI1CONbits.MSSEN = 0;
SPI1CONbits.FRMSYPW = 0;
SPI1CONbits.FRMCNT = 0b000;
SPI1CONbits.MCLKSEL = 1; // REFCLK
SPI1CONbits.SPIFE = 0;
SPI1CONbits.ENHBUF = 1;
SPI1CONbits.SIDL = 0;
SPI1CONbits.DISSDO = 0;
SPI1CONbits.MODE32 = 0; // 16 bit per channel
SPI1CONbits.MODE16 = 0; // 16 bit per channel
SPI1CONbits.SMP = 0;
SPI1CONbits.CKE = 1;
SPI1CONbits.SSEN = 0;
SPI1CONbits.CKP = 1;
SPI1CONbits.MSTEN = 1; // Master mode
SPI1CONbits.DISSDI = 1; // No SDI for now
SPI1CONbits.STXISEL = 0b11;
SPI1CONbits.SRXISEL = 0b00;
SPI1CON2bits.SPISGNEXT = 0;
SPI1CON2bits.FRMERREN = 0;
SPI1CON2bits.SPIROVEN = 0;
SPI1CON2bits.SPITUREN = 0;
SPI1CON2bits.IGNROV = 0;
SPI1CON2bits.IGNTUR = 1;
SPI1CON2bits.AUDEN = 1; // Enable audio mode
SPI1CON2bits.AUDMONO = 0; // Stereo audio
SPI1CON2bits.AUDMOD = 0b00; // I2S mode
SPI1BRG = 3; // 192000Hz SPI clock = 4 bytes per sample @ 48000sps
SPI1CONbits.ON = 1; // Turn it on
myFile = myCard.open("MUSIC1.RAW", FILE_READ);
if (!myFile) {
Serial.println("Unable to open music file");
while(1);
}
initDMA();
}
void nextFile() {
char temp[30];
myFile.close();
while (!myFile) {
fnum++;
sprintf(temp, "MUSIC%d.RAW", fnum);
Serial.println(temp);
myFile = myCard.open(temp, FILE_READ);
if (!myFile) {
fnum = 0;
}
}
}
void readChunk(int16_t *buf) {
// Serial.println(midValue);
digitalWrite(bassPin, bassValue > bassThresh);
digitalWrite(midPin, midValue > midThresh);
bassValue -= 100;
midValue -= 100;
if (bassValue < 0) {
bassValue = 0;
}
if (midValue < 0) {
midValue = 0;
}
int volume = analogRead(A0);
int n = myFile.read(bufferC, BSIZE * 2);
if (n != BSIZE*2) {
nextFile();
myFile.read(bufferC + n, BSIZE * 2 - n);
}
for (int i = 0; i < BSIZE; i++) {
int x = (int)bufferC[i] * volume / 512; // Allow for 2x volume boost
if (x > 32767) x = 32767;
if (x < -32767) x = -32767;
buf[i] = x;
}
for (int i = 0; i < 1024; i++) {
int x = ((int)bufferC[i*2] + (int)bufferC[i*2+1]) / 2;
real[i] = x;
complex[i] = 0;
}
FFT::convert(real, complex, 10);
int v = sqrt(real[bassBucket] * real[bassBucket] + complex[bassBucket] + complex[bassBucket]); //FFT::vector(bufferC[0], bufferD[0]);
if (v > bassValue) {
bassValue = v;
}
v = sqrt(real[midBucket] * real[midBucket] + complex[midBucket] + complex[midBucket]); //FFT::vector(bufferC[0], bufferD[0]);
if (v > midValue) {
midValue = v;
}
}
void loop() {
if (bufferAFull == 0) {
readChunk(bufferA);
bufferAFull = 1;
}
if (bufferBFull == 0) {
readChunk(bufferB);
bufferBFull = 1;
}
if (button.changedTo(LOW)) {
nextFile();
}
}
Make of it what you will.
Tue, 06 Jan 2015 00:49:38 +0000
Thank you, majenko! Nice example how to create a lightweight SD-Card pcm player! :) ...but it doesn't solved my problems, the configuration is - more or less - the same as in my example. The curious thing is, that the output switches every 256 values back to zero and start to raise again, so the DAC takes only the 8 bit, no matter where I start if its exactly after 8 bits (example: start at 256, end 512, nice rising slope, from 512 to 767, rise again,....) I also checked out, if the DAC's are wrong labeled and TDA1543**[color=#BF0000]A[/color]** these on have instead of I2S the japanese format...but this wouldn't explain this behavior. Ok, the DAC's had cost a few bugs (less than 6 Euro for 20 pieces), but I spent hours about this....without solving the problem, this makes me angry ;)
Mon, 02 Feb 2015 23:57:45 +0000
Ok, I've bought some CS4334 DAC's and they run "out of the box", so the TDA1543 [color=#BF0000]are[/color] faulty. So keep your fingers away from them on ali or ebay and buy some "modern" DAC's for less.
Tue, 17 Feb 2015 17:47:08 +0000
Hey!
I'm new here so go easy on me please but I'm also struggling with I2S.
I'm using the PmodI2S modules which have the CS4344 stereo DACs on which I think should share functionality with the CS4334's so presumably the code you've pasted above should also work for me but when I compile it in MPIDE It comes back with quite a few errors. Is there an updated version of this sketch or am I going wrong somewhere else?
Thanks for any help you can give me
:)
Tue, 17 Feb 2015 18:14:16 +0000
[Duplicate post removed]
Tue, 17 Feb 2015 19:57:29 +0000
At first: I don't use MPIDE, but UECIDE, this IDE is MUCH more advantaged than MPIDE. Look at uecide.org. Second: The interrupt routine is for the old compiler. So maybe this is the reason for your problem. Third: I use a PIC32MX250 (DIP version) So please, try this sketch:
// I2S mode test.
//pin7 Clock
//pin9 WS
//pin18 MOSI
int16_t sinus16[256] =
{0, 804, 1608, 2410, 3212, 4011, 4808, 5602, 6393, 7179, 7962, 8739, 9512, 10278, 11039, 11793, 12539,
13279, 14010, 14732, 15446, 16151, 16846, 17530, 18204, 18868, 19519, 20159, 20787, 21403, 22005, 22594,
23170, 23731, 24279, 24811, 25329, 25832, 26319, 26790, 27245, 27683, 28105, 28510, 28898, 29268, 29621,
29956, 30273, 30571, 30852, 31113, 31356, 31580, 31785, 31971, 32137, 32285, 32412, 32521, 32609, 32678,
32728, 32757, 32767, 32757, 32728, 32678, 32609, 32521, 32412, 32285, 32137, 31971, 31785, 31580, 31356,
31113, 30852, 30571, 30273, 29956, 29621, 29268, 28898, 28510, 28105, 27683, 27245, 26790, 26319, 25832,
25329, 24811, 24279, 23731, 23170, 22594, 22005, 21403, 20787, 20159, 19519, 18868, 18204, 17530, 16846,
16151, 15446, 14732, 14010, 13279, 12539, 11793, 11039, 10278, 9512, 8739, 7962, 7179, 6393, 5602, 4808,
4011, 3212, 2410, 1608, 804, 0, -804, -1608, -2410, -3212, -4011, -4808, -5602, -6393, -7179, -7962, -8739,
-9512, -10278, -11039, -11793, -12539, -13279, -14010, -14732, -15446, -16151, -16846, -17530, -18204,
-18868, -19519, -20159, -20787, -21403, -22005, -22594, -23170, -23731, -24279, -24811, -25329, -25832,
-26319, -26790, -27245, -27683, -28105, -28510, -28898, -29268, -29621, -29956, -30273, -30571, -30852,
-31113, -31356, -31580, -31785, -31971, -32137, -32285, -32412, -32521, -32609, -32678, -32728, -32757,
-32767, -32757, -32728, -32678, -32609, -32521, -32412, -32285, -32137, -31971, -31785, -31580, -31356,
-31113, -30852, -30571, -30273, -29956, -29621, -29268, -28898, -28510, -28105, -27683, -27245, -26790,
-26319, -25832, -25329, -24811, -24279, -23731, -23170, -22594, -22005, -21403, -20787, -20159, -19519,
-18868, -18204, -17530, -16846, -16151, -15446, -14732, -14010, -13279, -12539, -11793, -11039, -10278,
-9512, -8739, -7962, -7179, -6393, -5602, -4808, -4011, -3212, -2410, -1608, -804 };
volatile boolean channel=0;
volatile boolean square=0;
#include <p32xxxx.h>
#define refclock 6 // Referenzclock auf pin6 als test
#define mosipin 18
#define sspin 9
volatile uint16_t xx=0;
int bit16=0;
void setup() {
// setup pins & mapping
pinMode(refclock, OUTPUT); // System Clock Output for analyse
pinMode(mosipin, OUTPUT); // data
pinMode(sspin, OUTPUT); // bck
mapPps(refclock, PPS_OUT_REFCLKO);
mapPps(mosipin, PPS_OUT_SDO1);
mapPps(sspin, PPS_OUT_SS1);
// setup reference clock
REFOCONbits.ON=0;
REFOCONbits.ACTIVE=0;
REFOCONbits.ROSEL = 6; // Reference Clock Source Select POSC
REFOCONbits.RODIV = 4;
REFOTRIMbits.ROTRIM = 128; // 128 44,1khz
REFOCONbits.OE = 1; // Reference clock is driven out on REFCLKO pin
REFOCONbits.ACTIVE=1;
REFOCONbits.ON = 1; // Reference Oscillator Module enabled
// Configure the SPI port to take its clock from the REFCLK and
// operate in I2S mode
SPI1CONbits.ON = 0; // 0 SPI off
SPI1CONbits.FRMEN = 0; // 0 Framed SPI support is disabled
SPI1CONbits.FRMSYNC = 0; // 0 Frame sync pulse output (Master mode)
SPI1CONbits.FRMPOL = 0; // 0 Frame pulse is active-low
SPI1CONbits.MSSEN = 0; // 0 Slave select SPI support is disabled
SPI1CONbits.FRMSYPW = 0; // 0 Frame sync pulse is one clock wide
SPI1CONbits.FRMCNT = 0b000; // 000 = Generate a frame sync pulse on every data character
SPI1CONbits.MCLKSEL = 1; // Master clock: 1 = MCLK is used by the Baud Rate Generator 0 = PBCLK is used by the Baud Rate Generator
SPI1CONbits.SPIFE = 0; // Frame Sync Pulse Edge Select bit 0 = Frame synchronization pulse precedes the first bit clock
SPI1CONbits.ENHBUF = 1; // 1 = Enhanced Buffer mode is enabled
SPI1CONbits.SIDL = 0; // 0 = Continue operation in Idle mode
SPI1CONbits.DISSDO = 0; // Disable SDOx pin bit 1 = SDOx pin is not used by the module (pin is controlled by associated PORT register)
SPI1CONbits.MODE32 = 0; // 16 bit per channel
SPI1CONbits.MODE16 = 0; // 16 bit per channel
SPI1CONbits.SMP = 0; // SPI Data Input Sample Phase bit 1 = Input data sampled at end of data output time 0 = Input data sampled at middle of data output time
SPI1CONbits.CKE = 1; // SPI Clock Edge Select bit 1 = Serial output data changes on transition from active clock state to idle clock state (see CKP bit) = Serial output data changes on transition from idle clock state to active clock state (see CKP bit)
SPI1CONbits.SSEN = 0; // Slave Select Enable (Slave mode) bit 1 = SSx pin used for Slave mode 0 = SSx pin not used for Slave mode, pin controlled by port unction.
SPI1CONbits.CKP = 1; // Clock Polarity Select bit 1 = Idle state for clock is a high level; active state is a low level 0 = Idle state for clock is a lowlevel; active state is a high level
SPI1CONbits.MSTEN = 1; // 1=Master mode
SPI1CONbits.DISSDI = 1; // 0 = Disable SDI bit
SPI1CONbits.STXISEL = 0b11; // 11 = SPIxTXIF is set when the buffer is not full (has one or more empty elements)
SPI1CONbits.SRXISEL = 0b00; //
SPI1CON2bits.SPISGNEXT = 0; // 0 = Data from RX FIFO is not sign extened
SPI1CON2bits.FRMERREN = 0; // 0 = Frame Error does not generate error interrupts
SPI1CON2bits.SPIROVEN = 0; // 0 = Receive overflow does not generate error interrupts
SPI1CON2bits.SPITUREN = 0; // 0 = Transmit Underrun does not generate error interrupts
SPI1CON2bits.IGNROV = 1; // Ignore Receive Overflow bit (for Audio Data Transmissions)
SPI1CON2bits.IGNTUR = 1; // Ignore Transmit Underrun bit (for Audio Data Transmissions) 1 = A TUR is not a critical error and zeros are transmitted until thSPIxTXB is not empty 0 = A TUR is a critical error which stop SPI operation
SPI1CON2bits.AUDEN = 1; // Enable audio mode
SPI1CON2bits.AUDMONO = 0; // Stereo audio
SPI1CON2bits.AUDMOD = 0b00; // I2S mode
SPI1BRG = 3; // 44,1khz
SPI1CONbits.ON = 1; // Turn it on
// setup SPI interrupt
setIntVector(_SPI_1_VECTOR, (isrFunc)SPI1InterruptHandler);
setIntPriority(_SPI_1_VECTOR, 4, 0);
clearIntFlag(_SPI1_TX_IRQ);
setIntEnable(_SPI1_TX_IRQ);
}
void loop() {
delay(5); //nothing to do here
}
void __attribute__((interrupt)) SPI1InterruptHandler() { // I2s Data out
channel=!channel; // flip L-R channels
if (channel==0)
{
xx+=1; // next sinus value in table
if (xx>=256)
xx=0;
uint16_t out=(sinus16[xx]/512*512);
if (out>0)
out-=0;
SPI1BUF =out;
}
else
{
square=!square;
//long outB=0;
bit16+=256;
//if (bit24>=65535)
//bit24=0;
SPI1BUF =bit16;
}
clearIntFlag(_SPI1_TX_IRQ);
}
Wed, 18 Feb 2015 11:54:02 +0000
Thanks for the quick reply and sketch, but I still seem to be having problems. when i go to compile it comes back with errors that quite a few things haven't been declared in this scope. I think it could be that UECIDE isn't recognising where the library is but I don't know why.
I've installed it using the Plugin-> PIC32 Boards-> Compilers-> pic32-tools
and when i go through the file paths in windows explorer i can see the library <p32xxxx.h> is there, but when i go back to UECIDE and right click on libraries all i see is the chipKIT library.
I've tried moving the pic32 folder from compilers to cores and zipping it then using the install library function but still nothing.
Any ideas where I'm going wrong this time?
Thanks again
Wed, 18 Feb 2015 12:35:51 +0000
Hm. I'm at work at the moment, so I haven't access to my Macbook. A fewthings:
Wed, 18 Feb 2015 13:23:10 +0000
I think you're doing some very strange things with the UECIDE internals. Unless you're a developer there's really no need to be messing with the files in your UECIDE data directory.
p32xxxx.h is part of the compiler. It's not needed to have anything done with it. In fact, it has been superseded by "xc.h" in the latest compiler.
There is no need to include p32xxxx.h in your sketch, or anywhere else, since the chipKIT core already includes it in wiring.h.
In UECIDE, everything under "compilers" is to stay under "compilers" and shouldn't be touched. The same with "cores". Nothing there has anything to do with any libraries (other than core-bundled libraries), and trying to install anything like that as a library is doomed to failure from the start.
Your best bet is to delete everything in your UECIDE data directory and reinstall it from the plugin manager to undo whatever nasty things you have done to it. You also want to check the contents of your libraries folder to delete anything nasty that you have now dumped in there.
Wed, 18 Feb 2015 13:48:41 +0000
hehe, nice thing to know, that there is no need for including the p32xxxx.h anymore. I think, I'm not really up to date, yet ;)
Wed, 18 Feb 2015 14:23:08 +0000
okay so i've undone everything that i had done to the compiler and core files and used the plugin manager to add the board, cores and compilers instead but i stil get the following errors;
C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino: In function 'void setup()': C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:41:18: error: 'PPS_OUT_REFCLKO' was not declared in this scope C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:41:33: error: 'mapPps' was not declared in this scope C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:42:17: error: 'PPS_OUT_SDO1' was not declared in this scope C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:43:15: error: 'PPS_OUT_SS1' was not declared in this scope C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:46:1: error: 'REFOCONbits' was not declared in this scope C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:50:1: error: 'REFOTRIMbits' was not declared in this scope C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:64:13: error: 'volatile union __SPI1CONbits_t' has no member named 'MCLKSEL' C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:76:13: error: 'volatile union __SPI1CONbits_t' has no member named 'DISSDI' C:\Users\Ryan\AppData\Local\Temp\untitled22\untitled22.ino:79:1: error: 'SPI1CON2bits' was not declared in this scope Failed compiling
I'm using the chipkit Max32 board, which uses the PIC32MX795F512L, any idea where i'm going wrong?
Cheers for all the help
Wed, 18 Feb 2015 14:29:43 +0000
I'm using the chipkit Max32 board, which uses the PIC32MX795F512L, any idea where i'm going wrong?
You have done everything right, with a little misunderstanding: The PIC32MX795F512L cannot handle I2s or any other audio stream. (Look at the datasheet). [color=#BF0040]<edit> [/color]and even not pin mapping (pps)
Wed, 18 Feb 2015 15:02:49 +0000
Ah, so then i guess this PIC won't be able to handle an audio input via SPI either then?
looks like i may need to find an alternative MCU for this project
thanks for all the help :)
Wed, 18 Feb 2015 15:09:13 +0000
Right. How about a self built PIC32MX250? Look at majenkos Ebay store: http://tinyurl.com/kvha6ek
or a DP32? http://www.digilentinc.com/Products/Detail.cfm?Prod=CHIPKIT-DP32
Wed, 18 Feb 2015 15:40:32 +0000
I was just looking at the DP32, they look pretty good and are suprisingly cheap!
Think I'll order a couple in and then give this another try, fingers crosed i'll be a bit more successful. The DP32 should also be capable of supporting an audio input via SPI, such as that from the PmodMIC ([url]http://www.digilentinc.com/Products/Detail.cfm?Prod=PMOD-MIC[/url]), unless i'm mistaken?
Thanks again :)
Wed, 18 Feb 2015 15:49:17 +0000
Should work. In my code I've disabled the SDO (input) port. I've played with audio in yet.