Mark B
/
i2s
i2s/i2s.cpp@0:6d43d111bdc1, 2010-01-20 (annotated)
- Committer:
- macaba
- Date:
- Wed Jan 20 11:44:57 2010 +0000
- Revision:
- 0:6d43d111bdc1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
macaba | 0:6d43d111bdc1 | 1 | /***************************************************************************** |
macaba | 0:6d43d111bdc1 | 2 | * i2s.c: I2S C file for NXP LPC17xx Family Microprocessors |
macaba | 0:6d43d111bdc1 | 3 | * |
macaba | 0:6d43d111bdc1 | 4 | * Copyright(C) 2009, NXP Semiconductor |
macaba | 0:6d43d111bdc1 | 5 | * All rights reserved. |
macaba | 0:6d43d111bdc1 | 6 | * |
macaba | 0:6d43d111bdc1 | 7 | * History |
macaba | 0:6d43d111bdc1 | 8 | * 2009.05.26 ver 1.00 Prelimnary version, first Release |
macaba | 0:6d43d111bdc1 | 9 | * |
macaba | 0:6d43d111bdc1 | 10 | *****************************************************************************/ |
macaba | 0:6d43d111bdc1 | 11 | #include "mbed.h" |
macaba | 0:6d43d111bdc1 | 12 | #include "type.h" |
macaba | 0:6d43d111bdc1 | 13 | #include "i2s.h" |
macaba | 0:6d43d111bdc1 | 14 | #include "dma.h" |
macaba | 0:6d43d111bdc1 | 15 | |
macaba | 0:6d43d111bdc1 | 16 | /* treat I2S TX and RX as a constant address, make the code and buffer |
macaba | 0:6d43d111bdc1 | 17 | easier for both DMA and non-DMA test */ |
macaba | 0:6d43d111bdc1 | 18 | volatile uint8_t *I2STXBuffer = (uint8_t *)(DMA_SRC); |
macaba | 0:6d43d111bdc1 | 19 | volatile uint8_t *I2SRXBuffer = (uint8_t *)(DMA_DST); |
macaba | 0:6d43d111bdc1 | 20 | volatile uint32_t I2SReadLength = 0; |
macaba | 0:6d43d111bdc1 | 21 | volatile uint32_t I2SWriteLength = 0; |
macaba | 0:6d43d111bdc1 | 22 | volatile uint32_t I2SRXDone = 0, I2STXDone = 0; |
macaba | 0:6d43d111bdc1 | 23 | |
macaba | 0:6d43d111bdc1 | 24 | /***************************************************************************** |
macaba | 0:6d43d111bdc1 | 25 | ** Function name: I2S_IRQHandler |
macaba | 0:6d43d111bdc1 | 26 | ** |
macaba | 0:6d43d111bdc1 | 27 | ** Descriptions: I2S interrupt handler, only RX interrupt is enabled |
macaba | 0:6d43d111bdc1 | 28 | ** for simplicity. |
macaba | 0:6d43d111bdc1 | 29 | ** |
macaba | 0:6d43d111bdc1 | 30 | ** parameters: None |
macaba | 0:6d43d111bdc1 | 31 | ** Returned value: None |
macaba | 0:6d43d111bdc1 | 32 | ** |
macaba | 0:6d43d111bdc1 | 33 | *****************************************************************************/ |
macaba | 0:6d43d111bdc1 | 34 | void I2S_IRQHandler (void) |
macaba | 0:6d43d111bdc1 | 35 | { |
macaba | 0:6d43d111bdc1 | 36 | uint32_t RxCount = 0; |
macaba | 0:6d43d111bdc1 | 37 | |
macaba | 0:6d43d111bdc1 | 38 | if ( LPC_I2S->I2SSTATE & 0x01 ) |
macaba | 0:6d43d111bdc1 | 39 | { |
macaba | 0:6d43d111bdc1 | 40 | RxCount = (LPC_I2S->I2SSTATE >> 8) & 0xFF; |
macaba | 0:6d43d111bdc1 | 41 | if ( (RxCount != RXFIFO_EMPTY) && !I2SRXDone ) |
macaba | 0:6d43d111bdc1 | 42 | { |
macaba | 0:6d43d111bdc1 | 43 | while ( RxCount > 0 ) |
macaba | 0:6d43d111bdc1 | 44 | { |
macaba | 0:6d43d111bdc1 | 45 | if ( I2SReadLength == BUFSIZE ) |
macaba | 0:6d43d111bdc1 | 46 | { |
macaba | 0:6d43d111bdc1 | 47 | LPC_I2S->I2SDAI |= ((0x01 << 3) | (0x01 << 4)); |
macaba | 0:6d43d111bdc1 | 48 | LPC_I2S->I2SIRQ &= ~(0x01 << 0); /* Disable RX */ |
macaba | 0:6d43d111bdc1 | 49 | I2SRXDone = 1; |
macaba | 0:6d43d111bdc1 | 50 | break; |
macaba | 0:6d43d111bdc1 | 51 | } |
macaba | 0:6d43d111bdc1 | 52 | else |
macaba | 0:6d43d111bdc1 | 53 | { |
macaba | 0:6d43d111bdc1 | 54 | I2SRXBuffer[I2SReadLength++] = LPC_I2S->I2SRXFIFO; |
macaba | 0:6d43d111bdc1 | 55 | } |
macaba | 0:6d43d111bdc1 | 56 | RxCount--; |
macaba | 0:6d43d111bdc1 | 57 | } |
macaba | 0:6d43d111bdc1 | 58 | } |
macaba | 0:6d43d111bdc1 | 59 | } |
macaba | 0:6d43d111bdc1 | 60 | return; |
macaba | 0:6d43d111bdc1 | 61 | } |
macaba | 0:6d43d111bdc1 | 62 | |
macaba | 0:6d43d111bdc1 | 63 | /***************************************************************************** |
macaba | 0:6d43d111bdc1 | 64 | ** Function name: I2SStart |
macaba | 0:6d43d111bdc1 | 65 | ** |
macaba | 0:6d43d111bdc1 | 66 | ** Descriptions: Start I2S DAI and DAO |
macaba | 0:6d43d111bdc1 | 67 | ** |
macaba | 0:6d43d111bdc1 | 68 | ** parameters: None |
macaba | 0:6d43d111bdc1 | 69 | ** Returned value: None |
macaba | 0:6d43d111bdc1 | 70 | ** |
macaba | 0:6d43d111bdc1 | 71 | *****************************************************************************/ |
macaba | 0:6d43d111bdc1 | 72 | void I2SStart( void ) |
macaba | 0:6d43d111bdc1 | 73 | { |
macaba | 0:6d43d111bdc1 | 74 | uint32_t DAIValue, DAOValue; |
macaba | 0:6d43d111bdc1 | 75 | |
macaba | 0:6d43d111bdc1 | 76 | /* Audio output is the master, audio input is the slave, */ |
macaba | 0:6d43d111bdc1 | 77 | /* 16 bit data, stereo, reset, master mode, not mute. */ |
macaba | 0:6d43d111bdc1 | 78 | DAOValue = LPC_I2S->I2SDAO; |
macaba | 0:6d43d111bdc1 | 79 | DAIValue = LPC_I2S->I2SDAI; |
macaba | 0:6d43d111bdc1 | 80 | LPC_I2S->I2SDAO = DAOValue & (~((0x01 << 4)|(0x01 <<3))); |
macaba | 0:6d43d111bdc1 | 81 | /* 16 bit data, stereo, reset, slave mode, not mute. */ |
macaba | 0:6d43d111bdc1 | 82 | LPC_I2S->I2SDAI = DAIValue & (~((0x01 << 4)|(0x01 <<3))); |
macaba | 0:6d43d111bdc1 | 83 | return; |
macaba | 0:6d43d111bdc1 | 84 | } |
macaba | 0:6d43d111bdc1 | 85 | |
macaba | 0:6d43d111bdc1 | 86 | /***************************************************************************** |
macaba | 0:6d43d111bdc1 | 87 | ** Function name: I2SStop |
macaba | 0:6d43d111bdc1 | 88 | ** |
macaba | 0:6d43d111bdc1 | 89 | ** Descriptions: Stop I2S DAI and DAO |
macaba | 0:6d43d111bdc1 | 90 | ** |
macaba | 0:6d43d111bdc1 | 91 | ** parameters: None |
macaba | 0:6d43d111bdc1 | 92 | ** Returned value: None |
macaba | 0:6d43d111bdc1 | 93 | ** |
macaba | 0:6d43d111bdc1 | 94 | *****************************************************************************/ |
macaba | 0:6d43d111bdc1 | 95 | void I2SStop( void ) |
macaba | 0:6d43d111bdc1 | 96 | { |
macaba | 0:6d43d111bdc1 | 97 | uint32_t DAIValue, DAOValue; |
macaba | 0:6d43d111bdc1 | 98 | |
macaba | 0:6d43d111bdc1 | 99 | /* Stop the I2S to start. Audio output is master, audio input is the slave. */ |
macaba | 0:6d43d111bdc1 | 100 | /* 16 bit data, set STOP and RESET bits to reset the channels */ |
macaba | 0:6d43d111bdc1 | 101 | DAOValue = LPC_I2S->I2SDAO; |
macaba | 0:6d43d111bdc1 | 102 | /* Switch to master mode, TX channel, no mute */ |
macaba | 0:6d43d111bdc1 | 103 | DAOValue &= ~((0x01 << 5)|(0x01 << 15)); |
macaba | 0:6d43d111bdc1 | 104 | DAIValue = LPC_I2S->I2SDAI; |
macaba | 0:6d43d111bdc1 | 105 | DAIValue &= ~(0x01 << 15); |
macaba | 0:6d43d111bdc1 | 106 | LPC_I2S->I2SDAO = (0x01 << 4) | (0x01 << 3) | DAOValue; /* Master */ |
macaba | 0:6d43d111bdc1 | 107 | LPC_I2S->I2SDAI = (0x01 << 4) | (0x01 << 3) | DAIValue; /* Slave */ |
macaba | 0:6d43d111bdc1 | 108 | return; |
macaba | 0:6d43d111bdc1 | 109 | } |
macaba | 0:6d43d111bdc1 | 110 | |
macaba | 0:6d43d111bdc1 | 111 | /***************************************************************************** |
macaba | 0:6d43d111bdc1 | 112 | ** Function name: I2SInit |
macaba | 0:6d43d111bdc1 | 113 | ** |
macaba | 0:6d43d111bdc1 | 114 | ** Descriptions: Initialize I2S controller |
macaba | 0:6d43d111bdc1 | 115 | ** |
macaba | 0:6d43d111bdc1 | 116 | ** parameters: None |
macaba | 0:6d43d111bdc1 | 117 | ** Returned value: true or false, return false if the I2S |
macaba | 0:6d43d111bdc1 | 118 | ** interrupt handler was not installed correctly |
macaba | 0:6d43d111bdc1 | 119 | ** |
macaba | 0:6d43d111bdc1 | 120 | *****************************************************************************/ |
macaba | 0:6d43d111bdc1 | 121 | uint32_t I2SInit( void ) |
macaba | 0:6d43d111bdc1 | 122 | { |
macaba | 0:6d43d111bdc1 | 123 | |
macaba | 0:6d43d111bdc1 | 124 | /*enable I2S in the PCONP register. I2S is disabled on reset*/ |
macaba | 0:6d43d111bdc1 | 125 | LPC_SC->PCONP |= (1 << 27); |
macaba | 0:6d43d111bdc1 | 126 | |
macaba | 0:6d43d111bdc1 | 127 | /*connect the I2S sigals to port pins(P0.4-P0.9)*/ |
macaba | 0:6d43d111bdc1 | 128 | LPC_PINCON->PINSEL0 &= ~0x000FFF00; |
macaba | 0:6d43d111bdc1 | 129 | LPC_PINCON->PINSEL0 |= 0x00055500; |
macaba | 0:6d43d111bdc1 | 130 | |
macaba | 0:6d43d111bdc1 | 131 | /* Please note, in order to generate accurate TX/RX clock rate for I2S, |
macaba | 0:6d43d111bdc1 | 132 | PCLK and CCLK needs to be carefully reconsidered. For this test |
macaba | 0:6d43d111bdc1 | 133 | program, the TX is looped back to RX without external I2S device, |
macaba | 0:6d43d111bdc1 | 134 | clock rate is not critical in this matter. */ |
macaba | 0:6d43d111bdc1 | 135 | LPC_I2S->I2STXRATE = 0x241; |
macaba | 0:6d43d111bdc1 | 136 | LPC_I2S->I2SRXRATE = 0x241; |
macaba | 0:6d43d111bdc1 | 137 | |
macaba | 0:6d43d111bdc1 | 138 | I2SStop(); |
macaba | 0:6d43d111bdc1 | 139 | |
macaba | 0:6d43d111bdc1 | 140 | NVIC_EnableIRQ(I2S_IRQn); |
macaba | 0:6d43d111bdc1 | 141 | return( TRUE ); |
macaba | 0:6d43d111bdc1 | 142 | } |
macaba | 0:6d43d111bdc1 | 143 | |
macaba | 0:6d43d111bdc1 | 144 | /****************************************************************************** |
macaba | 0:6d43d111bdc1 | 145 | ** End Of File |
macaba | 0:6d43d111bdc1 | 146 | ******************************************************************************/ |
macaba | 0:6d43d111bdc1 | 147 |