Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
macaba
Date:
Wed Jan 20 11:44:57 2010 +0000
Commit message:

Changed in this revision

i2s/dma.cpp Show annotated file Show diff for this revision Revisions of this file
i2s/dma.h Show annotated file Show diff for this revision Revisions of this file
i2s/i2s.cpp Show annotated file Show diff for this revision Revisions of this file
i2s/i2s.h Show annotated file Show diff for this revision Revisions of this file
i2s/type.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r 6d43d111bdc1 i2s/dma.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i2s/dma.cpp	Wed Jan 20 11:44:57 2010 +0000
@@ -0,0 +1,151 @@
+/*****************************************************************************
+ *   dma.c:  DMA module file for NXP LPC17xx Family Microprocessors
+ *
+ *   Copyright(C) 2009, NXP Semiconductor
+ *   All rights reserved.
+ *
+ *   History
+ *   2009.05.26  ver 1.00    Prelimnary version, first Release
+ *
+******************************************************************************/
+#include "mbed.h"
+#include "type.h"
+#include "i2s.h"
+#include "dma.h"
+
+#if I2S_DMA_ENABLED
+volatile uint32_t DMATCCount = 0;
+volatile uint32_t DMAErrCount = 0;
+volatile uint32_t I2SDMA0Done = 0;
+volatile uint32_t I2SDMA1Done = 0;
+
+/******************************************************************************
+** Function name:		DMA_IRQHandler
+**
+** Descriptions:		DMA interrupt handler
+**
+** parameters:			None
+** Returned value:		None
+** 
+******************************************************************************/
+void DMA_IRQHandler(void) 
+{
+  uint32_t regVal;
+
+  regVal = LPC_GPDMA->DMACIntTCStat;
+  if ( regVal )
+  {
+	DMATCCount++;
+	LPC_GPDMA->DMACIntTCClear |= regVal;
+	if ( regVal & 0x01 )
+	{
+	  I2SDMA0Done = 1;
+	}
+	else if ( regVal & 0x02 )
+	{
+	  I2SDMA1Done = 1;
+	}
+  } 
+
+  regVal = LPC_GPDMA->DMACIntErrStat;
+  if ( regVal )
+  {
+	DMAErrCount++;
+	LPC_GPDMA->DMACIntErrClr |= regVal;
+  }
+
+}
+
+/******************************************************************************
+** Function name:		DMA_Init
+**
+** Descriptions:		
+**
+** parameters:			
+** Returned value:		
+** 
+******************************************************************************/
+uint32_t DMA_Init( uint32_t ChannelNum, uint32_t DMAMode )
+{
+  if ( ChannelNum == 0 )
+  {
+	LPC_GPDMA->DMACIntTCClear = 0x01;   
+	if ( DMAMode == M2P )
+	{
+	  /* Ch0 set for M2P transfer from mempry to I2S TX FIFO. */
+	  LPC_GPDMACH0->DMACCSrcAddr = DMA_SRC;
+	  LPC_GPDMACH0->DMACCDestAddr = DMA_I2S_TX_FIFO;
+	  /* The burst size is set to 1. Terminal Count Int enable */
+	  LPC_GPDMACH0->DMACCControl = (DMA_SIZE & 0x0FFF) | (0x00 << 12) | (0x00 << 15)
+		| (1 << 26) | 0x80000000;
+	}
+	else if ( DMAMode == P2M )
+	{
+	  /* Ch0 set for P2M transfer from I2S RX FIFO to memory. */
+	  LPC_GPDMACH0->DMACCSrcAddr = DMA_I2S_RX_FIFO;
+	  LPC_GPDMACH0->DMACCDestAddr = DMA_DST;
+	  /* The burst size is set to 1. Terminal Count Int enable. */
+	  LPC_GPDMACH0->DMACCControl = (DMA_SIZE & 0x0FFF) | (0x00 << 12) | (0x00 << 15)
+		| (1 << 27) | 0x80000000;
+	}
+	else if ( DMAMode == P2P )
+	{
+	  /* Ch0 set for P2P transfer from I2S DAO to I2S DAI. */
+	  LPC_GPDMACH0->DMACCSrcAddr = DMA_I2S_TX_FIFO;
+	  LPC_GPDMACH0->DMACCDestAddr = DMA_I2S_RX_FIFO;
+	  /* The burst size is set to 32. */
+	  LPC_GPDMACH0->DMACCControl = (DMA_SIZE & 0x0FFF) | (0x04 << 12) | (0x04 << 15) 
+		| 0x80000000;
+	}
+	else
+	{
+	  return ( FALSE );
+	}
+  }
+  else if ( ChannelNum == 1 )
+  {   
+	LPC_GPDMA->DMACIntTCClear = 0x02;
+	if ( DMAMode == M2P )
+	{
+	  /* Ch1 set for M2P transfer from mempry to I2S TX FIFO. */
+	  LPC_GPDMACH1->DMACCSrcAddr = DMA_SRC;
+	  LPC_GPDMACH1->DMACCDestAddr = DMA_I2S_TX_FIFO;
+	  /* The burst size is set to 1. Terminal Count Int enable. */
+	  LPC_GPDMACH1->DMACCControl = (DMA_SIZE & 0x0FFF) | (0x00 << 12) | (0x00 << 15)
+		| (1 << 26) | 0x80000000;
+	}
+	else if ( DMAMode == P2M )
+	{
+	  /* Ch1 set for P2M transfer from I2S RX FIFO to memory. */
+	  LPC_GPDMACH1->DMACCSrcAddr = DMA_I2S_RX_FIFO;
+	  LPC_GPDMACH1->DMACCDestAddr = DMA_DST;
+	  /* The burst size is set to 1. Terminal Count Int enable. */
+	  LPC_GPDMACH1->DMACCControl = (DMA_SIZE & 0x0FFF) | (0x00 << 12) | (0x00 << 15)
+		| (1 << 27) | 0x80000000;
+	}
+	else if ( DMAMode == P2P )
+	{
+	  /* Ch1 set for P2P transfer from I2S DAO to I2S DAI. */
+	  LPC_GPDMACH1->DMACCSrcAddr = DMA_I2S_TX_FIFO;
+	  LPC_GPDMACH1->DMACCDestAddr = DMA_I2S_RX_FIFO;
+	  /* The burst size is set to 32. */
+	  LPC_GPDMACH1->DMACCControl = (DMA_SIZE & 0x0FFF) | (0x04 << 12) | (0x04 << 15) 
+		| 0x80000000;
+	}
+	else
+	{
+	  return ( FALSE );
+	}
+  }
+  else
+  {
+	return ( FALSE );
+  }
+  return( TRUE );
+}
+
+#endif	/* end if DMA_ENABLED */
+
+/******************************************************************************
+**                            End Of File
+******************************************************************************/
diff -r 000000000000 -r 6d43d111bdc1 i2s/dma.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i2s/dma.h	Wed Jan 20 11:44:57 2010 +0000
@@ -0,0 +1,39 @@
+/*****************************************************************************
+ *   dma.h:  Header file for NXP LPC17xx Family Microprocessors
+ *
+ *   Copyright(C) 2009, NXP Semiconductor
+ *   All rights reserved.
+ *
+ *   History
+ *   2009.05.26  ver 1.00    Prelimnary version, first Release
+ *
+******************************************************************************/
+#ifndef __DMA_H 
+#define __DMA_H
+
+/* USB RAM is used for GPDMA operation. */
+//#define DMA_SRC			0x7FD00000	
+//#define DMA_DST			0x7FD01000		
+//#define DMA_I2S_TX_FIFO	0xE0088008
+//#define	DMA_I2S_RX_FIFO	0xE008800C
+
+#define DMA_SRC			0x20080000	
+#define DMA_DST			0x20081000
+#define DMA_I2S_TX_FIFO	0x400A8008
+#define	DMA_I2S_RX_FIFO	0x400A800C
+ 
+#define DMA_SIZE		0x200
+
+/* DMA mode */
+#define M2M				0x00
+#define M2P				0x01
+#define P2M				0x02
+#define P2P				0x03
+
+extern void DMA_IRQHandler( void ); 
+extern uint32_t DMA_Init( uint32_t ChannelNum, uint32_t DMAMode );
+
+#endif /* end __DMA_H */
+/****************************************************************************
+**                            End Of File
+****************************************************************************/
diff -r 000000000000 -r 6d43d111bdc1 i2s/i2s.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i2s/i2s.cpp	Wed Jan 20 11:44:57 2010 +0000
@@ -0,0 +1,147 @@
+/*****************************************************************************
+ *   i2s.c:  I2S C file for NXP LPC17xx Family Microprocessors
+ *
+ *   Copyright(C) 2009, NXP Semiconductor
+ *   All rights reserved.
+ *
+ *   History
+ *   2009.05.26  ver 1.00    Prelimnary version, first Release
+ *
+*****************************************************************************/
+#include "mbed.h"
+#include "type.h"
+#include "i2s.h"
+#include "dma.h"
+
+/* treat I2S TX and RX as a constant address, make the code and buffer 
+easier for both DMA and non-DMA test */
+volatile uint8_t *I2STXBuffer = (uint8_t *)(DMA_SRC); 
+volatile uint8_t *I2SRXBuffer = (uint8_t *)(DMA_DST);
+volatile uint32_t I2SReadLength = 0;
+volatile uint32_t I2SWriteLength = 0;
+volatile uint32_t I2SRXDone = 0, I2STXDone = 0;
+
+/*****************************************************************************
+** Function name:		I2S_IRQHandler
+**
+** Descriptions:		I2S interrupt handler, only RX interrupt is enabled
+**						for simplicity.
+**
+** parameters:			None
+** Returned value:		None
+** 
+*****************************************************************************/
+void I2S_IRQHandler (void)  
+{
+  uint32_t RxCount = 0;
+
+  if ( LPC_I2S->I2SSTATE & 0x01 )
+  {
+	RxCount = (LPC_I2S->I2SSTATE >> 8) & 0xFF;
+	if ( (RxCount != RXFIFO_EMPTY) && !I2SRXDone )
+	{
+	  while ( RxCount > 0 )
+	  {
+		if ( I2SReadLength == BUFSIZE )
+		{
+		  LPC_I2S->I2SDAI |= ((0x01 << 3) | (0x01 << 4));
+		  LPC_I2S->I2SIRQ &= ~(0x01 << 0);	/* Disable RX */	
+		  I2SRXDone = 1;
+		  break;
+		}
+		else
+		{
+		  I2SRXBuffer[I2SReadLength++] = LPC_I2S->I2SRXFIFO;
+		}
+		RxCount--;
+	  }
+	}
+  }
+  return;
+}
+
+/*****************************************************************************
+** Function name:		I2SStart
+**
+** Descriptions:		Start I2S DAI and DAO
+**
+** parameters:			None
+** Returned value:		None
+** 
+*****************************************************************************/
+void I2SStart( void )
+{
+  uint32_t DAIValue, DAOValue;
+  
+  /* Audio output is the master, audio input is the slave, */
+  /* 16 bit data, stereo, reset, master mode, not mute. */
+  DAOValue = LPC_I2S->I2SDAO;
+  DAIValue = LPC_I2S->I2SDAI;
+  LPC_I2S->I2SDAO = DAOValue & (~((0x01 << 4)|(0x01 <<3)));
+  /* 16 bit data, stereo, reset, slave mode, not mute. */
+  LPC_I2S->I2SDAI = DAIValue & (~((0x01 << 4)|(0x01 <<3)));
+  return;
+}
+
+/*****************************************************************************
+** Function name:		I2SStop
+**
+** Descriptions:		Stop I2S DAI and DAO
+**
+** parameters:			None
+** Returned value:		None
+** 
+*****************************************************************************/
+void I2SStop( void )
+{
+  uint32_t DAIValue, DAOValue;
+
+  /* Stop the I2S to start. Audio output is master, audio input is the slave. */
+  /* 16 bit data, set STOP and RESET bits to reset the channels */
+  DAOValue = LPC_I2S->I2SDAO;
+  /* Switch to master mode, TX channel, no mute */
+  DAOValue &= ~((0x01 << 5)|(0x01 << 15));
+  DAIValue = LPC_I2S->I2SDAI;
+  DAIValue &= ~(0x01 << 15);
+  LPC_I2S->I2SDAO = (0x01 << 4) | (0x01 << 3) | DAOValue;	/* Master */
+  LPC_I2S->I2SDAI = (0x01 << 4) | (0x01 << 3) | DAIValue;	/* Slave */
+  return;
+}
+
+/*****************************************************************************
+** Function name:		I2SInit
+**
+** Descriptions:		Initialize I2S controller
+**
+** parameters:			None
+** Returned value:		true or false, return false if the I2S
+**						interrupt handler was not installed correctly
+** 
+*****************************************************************************/
+uint32_t I2SInit( void ) 
+{
+
+  /*enable I2S in the PCONP register. I2S is disabled on reset*/
+  LPC_SC->PCONP |= (1 << 27);
+
+  /*connect the I2S sigals to port pins(P0.4-P0.9)*/
+  LPC_PINCON->PINSEL0 &= ~0x000FFF00;
+  LPC_PINCON->PINSEL0 |= 0x00055500;
+
+  /* Please note, in order to generate accurate TX/RX clock rate for I2S, 
+  PCLK and CCLK needs to be carefully reconsidered. For this test 
+  program, the TX is looped back to RX without external I2S device, 
+  clock rate is not critical in this matter. */
+  LPC_I2S->I2STXRATE = 0x241;
+  LPC_I2S->I2SRXRATE = 0x241;
+
+  I2SStop();
+
+  NVIC_EnableIRQ(I2S_IRQn);
+  return( TRUE );
+}
+
+/******************************************************************************
+**                            End Of File
+******************************************************************************/
+
diff -r 000000000000 -r 6d43d111bdc1 i2s/i2s.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i2s/i2s.h	Wed Jan 20 11:44:57 2010 +0000
@@ -0,0 +1,28 @@
+/*****************************************************************************
+ *   i2s.h:  Header file for NXP LPC17xx Family Microprocessors
+ *
+ *   Copyright(C) 2009, NXP Semiconductor
+ *   All rights reserved.
+ *
+ *   History
+ *   2009.05.26  ver 1.00    Prelimnary version, first Release
+ *
+******************************************************************************/
+#ifndef __I2S_H
+#define __I2S_H
+
+#define I2S_DMA_ENABLED		1
+
+#define BUFSIZE				0x200
+#define RXFIFO_EMPTY		0
+#define TXFIFO_FULL			8
+
+extern void I2S_IRQHandler( void );
+extern void I2SStart( void );
+extern void I2SStop( void );
+extern uint32_t I2SInit( void );
+
+#endif /* end __I2S_H */
+/****************************************************************************
+**                            End Of File
+*****************************************************************************/
diff -r 000000000000 -r 6d43d111bdc1 i2s/type.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/i2s/type.h	Wed Jan 20 11:44:57 2010 +0000
@@ -0,0 +1,33 @@
+/*****************************************************************************
+ *   type.h:  Type definition Header file for NXP LPC17xx Family 
+ *   Microprocessors
+ *
+ *   Copyright(C) 2009, NXP Semiconductor
+ *   All rights reserved.
+ *
+ *   History
+ *   2009.05.25  ver 1.00    Prelimnary version, first Release
+ *
+******************************************************************************/
+#include <stdint.h>
+
+#ifndef __TYPE_H__
+#define __TYPE_H__
+
+#ifndef NULL
+#define NULL    ((void *)0)
+#endif
+
+#ifndef FALSE
+#define FALSE   (0)
+#endif
+
+#ifndef TRUE
+#define TRUE    (1)
+#endif
+
+
+typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
+typedef enum {DISABLE = 0, ENABLE = !DISABLE} FunctionalState;
+
+#endif  /* __TYPE_H__ */
diff -r 000000000000 -r 6d43d111bdc1 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed Jan 20 11:44:57 2010 +0000
@@ -0,0 +1,80 @@
+#include "mbed.h"
+#include "i2s.h"
+#include "type.h"
+#include "dma.h"
+
+extern volatile uint8_t *I2STXBuffer, *I2SRXBuffer;
+extern volatile uint32_t I2SReadLength;
+extern volatile uint32_t I2SWriteLength;
+extern volatile uint32_t I2SRXDone, I2STXDone;
+extern volatile uint32_t I2SDMA0Done, I2SDMA1Done;
+
+DigitalOut myled(LED1);
+
+
+int main() {
+    uint32_t i;
+    /* Configure temp register before reading */
+    for ( i = 0; i < BUFSIZE; i++ ) {	/* clear buffer */
+        I2STXBuffer[i] = i;
+        I2SRXBuffer[i] = 0;
+    }
+
+    if ( I2SInit() == FALSE ) {	/* initialize I2S */
+        while ( 1 );			/* Fatal error */
+    }
+
+#if I2S_DMA_ENABLED
+    /* USB RAM is used for test.
+    Please note, Ethernet has its own SRAM, but GPDMA can't access
+    that. GPDMA can access USB SRAM and IRAM. Ethernet DMA controller can
+    access both IRAM and Ethernet SRAM. */
+    LPC_SC->PCONP |= (1 << 29);	/* Enable GPDMA clock */
+
+    LPC_GPDMA->DMACIntTCClear = 0x03;
+    LPC_GPDMA->DMACIntErrClr = 0x03;
+
+    LPC_GPDMA->DMACConfig = 0x01;	/* Enable DMA channels, little endian */
+    while ( !(LPC_GPDMA->DMACConfig & 0x01) );
+
+    /* on DMA channel 0, Source is memory, destination is I2S TX FIFO,
+    on DMA channel 1, source is I2S RX FIFO, Destination is memory */
+    /* Enable channel and IE bit */
+    DMA_Init( 0, M2P );
+    LPC_GPDMACH0->DMACCConfig |= 0x18001 | (0x00 << 1) | (0x05 << 6) | (0x01 << 11);
+    DMA_Init( 1, P2M );
+    LPC_GPDMACH1->DMACCConfig |= 0x08001 | (0x06 << 1) | (0x00 << 6) | (0x02 << 11);
+
+    NVIC_EnableIRQ(DMA_IRQn);
+
+    I2SStart();
+
+    LPC_I2S->I2SDMA2 = (0x01<<0) | (0x08<<8);	/* Channel 2 is for RX, enable RX first. */
+    LPC_I2S->I2SDMA1 = (0x01<<1) | (0x01<<16);/* Channel 1 is for TX. */
+
+    /* Wait for both DMA0 and DMA1 to finish before verifying. */
+    while ( !I2SDMA0Done || !I2SDMA1Done );
+#else
+    /* Not DMA mode, enable I2S interrupts. */
+    /* RX FIFO depth is 1, TX FIFO depth is 8. */
+    I2SStart();
+    LPC_I2S->I2SIRQ = (8 << 16) | (1 << 8) | (0x01 << 0);
+
+    while ( I2SWriteLength < BUFSIZE ) {
+        while (((LPC_I2S->I2SSTATE >> 16) & 0xFF) == TXFIFO_FULL);
+        LPC_I2S->I2STXFIFO = I2STXBuffer[I2SWriteLength++];
+    }
+
+    I2STXDone = 1;
+    /* Wait for RX and TX complete before comparison */
+    while ( !I2SRXDone || !I2STXDone );
+#endif
+
+    /* Validate TX and RX buffer */
+    for ( i=1; i<BUFSIZE; i++ ) {
+        if ( I2SRXBuffer[i] != I2STXBuffer[i-1] ) {
+            while ( 1 );	/* Validation error */
+        }
+    }
+    return 0;
+}
diff -r 000000000000 -r 6d43d111bdc1 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Jan 20 11:44:57 2010 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/49a220cc26e0