Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Revision 0:6d43d111bdc1, committed 2010-01-20
- Comitter:
- macaba
- Date:
- Wed Jan 20 11:44:57 2010 +0000
- Commit message:
Changed in this revision
--- /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
+******************************************************************************/
--- /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 +****************************************************************************/
--- /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
+******************************************************************************/
+
--- /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 +*****************************************************************************/
--- /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__ */
--- /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;
+}
--- /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