chipKIT® Development Platform

Inspired by Arduino™

Need some help with I2s in MPIDE/UECIDE

Created Wed, 31 Dec 2014 11:40:27 +0000 by madias


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


madias

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


pito

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.

http://www.analog.com/en/rfif-components/direct-digital-synthesis-dds/products/index.html#Direct_Digital_Synthesis


madias

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


madias

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


majenko

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.


madias

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 ;)


madias

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.


cooperr1

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

:)


cooperr1

Tue, 17 Feb 2015 18:14:16 +0000

[Duplicate post removed]


madias

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); 
	}

cooperr1

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


madias

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:

  1. Which board have you installed? I use the DP32 for my generic home built PIC32MX250F128B MCU. You can install it with the plugin manager -> PIC32/chipkit/chipkit DP32 [color=#FF0000]<edit>[/color] than choose the DP32 board in UECIDE: Hardware->Boards->chipKIT->chipKIT DP32
  2. You didn't specified your board you use: Is it with a PIC32MX250xx? [color=#FF0000]<edit>[/color] you can't add the p32xxx file as library with right mouse click, it's a core thing and you must #include it within sketch.

majenko

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.


madias

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 ;)


cooperr1

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


madias

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)


cooperr1

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 :)


madias

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


cooperr1

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 :)


madias

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.