#include "ADDS_21161_EzKit.h" #include #include <21160.h> #include asm("#include "); /* Dodatkowe funkcje kodeka: */ // Ponizsze wprowadzic w celu przelaczenia drugiego ADC z wejscia MIC na wejscie CH 2 (MK) //#define LINE_IN_CH2 // Ponizsze wprowadzic w celu zwiekszenia wzmocnienia CH 2 o 12 dB (MK) #define EXTRA_MIC_GAIN /**************************************************************************************************** / / / AD1836 - SETUP and Data Routing / / / / Receives input data from the 2 AD1836 ADCs via SPORT1 and transmits processed audio data / / back out to the 3 AD1836 Stereo DACs/Line Outputs / / / ***************************************************************************************************** / / / This Serial Port 0 Recieve Interrupt Service Routine performs arithmetic computations on / / the SPORT1 receive DMA buffer (rx_buf) and places results to SPORT1 transmit DMA buffer (tx_buf)/ / / / rx0a_buf[8] - DSP SPORT recieve buffer / / Slot # Description DSP Data Memory Address / / ------ -------------------------------------- ----------------------------------------------- / / 0 Internal ADC 0 Left Channel DM(rx0a_buf + 0) = DM(rx0a_buf + Internal_ADC_L0) / / 1 Internal ADC 1 Left Channel DM(rx0a_buf + 1) = DM(rx0a_buf + Internal_ADC_L1) / / 2 External Auxilliary ADC 0 Left Chan. DM(rx0a_buf + 2) = DM(rx0a_buf + AUX_ADC_L0) / / 3 External Auxilliary ADC 1 Left Chan. DM(rx0a_buf + 3) = DM(rx0a_buf + AUX_ADC_L1) / / 4 Internal ADC 1 Right Channel DM(rx0a_buf + 4) = DM(rx0a_buf + Internal_ADC_R0) / / 5 Internal ADC 1 Right Channel DM(rx0a_buf + 5) = DM(rx0a_buf + Internal_ADC_R1) / / 6 External Auxilliary ADC 0 Right Chan. DM(rx0a_buf + 6) = DM(rx0a_buf + AUX_DAC_R0) / / 7 External Auxilliary ADC 1 Right Chan. DM(rx0a_buf + 7) = DM(rx0a_buf + AUX_DAC_R1) / / / / tx2a_buf[8] - DSP SPORT transmit buffer / / Slot # Description DSP Data Memory Address / / ------ -------------------------------------- ----------------------------------------------- / / 0 Internal DAC 0 Left Channel DM(tx0a_buf + 0) = DM(tx0a_buf + Internal_DAC_L0) / / 1 Internal DAC 1 Left Channel DM(tx0a_buf + 1) = DM(tx0a_buf + Internal_DAC_L1) / / 2 Internal DAC 2 Left Channel DM(tx0a_buf + 2) = DM(tx0a_buf + Internal_DAC_L2) / / 3 External Auxilliary DAC 0 Left Chan. DM(rx0a_buf + 3) = DM(tx0a_buf + AUX_DAC_L0) / / 4 Internal DAC 0 Right Channel DM(tx0a_buf + 4) = DM(tx0a_buf + Internal_DAC_R0) / / 5 Internal DAC 1 Right Channel DM(tx0a_buf + 5) = DM(tx0a_buf + Internal_DAC_R1) / / 6 Internal DAC 2 Left Channel DM(tx0a_buf + 6) = DM(tx0a_buf + Internal_DAC_R3) / / 7 External Auxilliary DAC 0 Right Chan. DM(tx0a_buf + 7) = DM(tx0a_buf + AUX_DAC_R0) / / / ****************************************************************************************************/ int powerdown_AD1836[4] = {DAC_CONTROL1 | WRITE_REG | 0x004, DAC_CONTROL1 | WRITE_REG | 0x004, ADC_CONTROL1 | WRITE_REG | 0x080, ADC_CONTROL1 | WRITE_REG | 0x080}; int powerdown_rx_buf0a[4]; // rx dma dummy buffer not used for anything; // AD1836 codec register commands - Serial SPI 16-bit Word Format as follows: // D15 to D12 = Codec Register Address // D11 = Read/Write register (1=rd, 0=wr) // D10 = reserved bit, clear to zero // D9 to D0 = Data Field for codec register #define TX_BUF3A_LEN 21 int tx_buf3a[TX_BUF3A_LEN] = // program register commands { DAC_CONTROL1 | WRITE_REG | 0x000, // we "OR" in address, rd/wr, and register data DAC_CONTROL1 | WRITE_REG | 0x000, // for ease in reading register values DAC_CONTROL2 | WRITE_REG | 0x000, // write DAC_CTL1 twice to workaround pwdwn SPI anomaly DAC_VOLUME0 | WRITE_REG | 0x3FF, DAC_VOLUME1 | WRITE_REG | 0x3FF, DAC_VOLUME2 | WRITE_REG | 0x3FF, DAC_VOLUME3 | WRITE_REG | 0x3FF, DAC_VOLUME4 | WRITE_REG | 0x3FF, DAC_VOLUME5 | WRITE_REG | 0x3FF, #ifdef EXTRA_MIC_GAIN /* CH2 +12dB */ ADC_CONTROL1 | WRITE_REG | 0x024, // write ADC_CTL1 twice to workaround pwdwn SPI anomaly ADC_CONTROL1 | WRITE_REG | 0x024, #else ADC_CONTROL1 | WRITE_REG | 0x000, // write ADC_CTL1 twice to workaround pwdwn SPI anomaly ADC_CONTROL1 | WRITE_REG | 0x000, #endif #ifdef LINE_IN_CH2 /* LINE IN CH2 */ ADC_CONTROL3 | WRITE_REG | 0x03F, // 256*Fs Clock Mode, single ended input MUX/PGA mode #else /* MIC INPUT */ ADC_CONTROL3 | WRITE_REG | 0x03A, // 256*Fs Clock Mode, single ended input MUX/PGA mode #endif ADC_CONTROL2 | WRITE_REG | 0x380, // SOUT MODE = 110 --> TDM Mode, Master device ADC_CONTROL2 | WRITE_REG | 0x380, // read register commands ADC0_PEAK_LEVEL | READ_REG | 0x000, // status will be in rx_buf1a[13-19] memory locations ADC1_PEAK_LEVEL | READ_REG | 0x000, ADC2_PEAK_LEVEL | READ_REG | 0x000, ADC3_PEAK_LEVEL | READ_REG | 0x000, ADC_CONTROL1 | READ_REG | 0x000, ADC_CONTROL2 | READ_REG | 0x000, ADC_CONTROL3 | READ_REG | 0x000 }; #define RX_BUF1A_LEN 21 int rx_buf1a[RX_BUF1A_LEN]; void SPORT_RX_IRQ(int sig_int) {} int Setup_AD1836() { int i; /* Powerdown reset of AD1836 */ *(int *) II3A = (int) powerdown_AD1836; *(int *) IM3A = 1; *(int *) C3A = 4; *(int *) II1A = (int) powerdown_rx_buf0a; *(int *) IM1A = 1; *(int *) C1A = 4; *(int *) SP13MCTL = 0; *(int *) DIV3 = 0x0011002B; // codec SPI port clock *(int *) DIV1 = 0; interruptf( SIG_SP1I, SPORT_RX_IRQ); interruptf( SIG_SP3I, SPORT_RX_IRQ); *(int *) SPCTL3 |= DDIR | SDEN_A | LAFS | LFS | IFS | FSR | CKRE | ICLK | SLEN16 | SPEN_A; *(int *) SPCTL1 |= SDEN_A | LAFS | LFS | FSR | CKRE | SLEN16 | SPEN_A; *(int *) SPCTL1 &= (~DDIR & ~IFS & ~ICLK); while ( (*(int*) DMASTAT) & 0xA ) // zmiana MK: bylo 0x8 asm("idle;"); interruptf( SIG_SP1I, SIG_IGN); interruptf( SIG_SP3I, SIG_IGN); /* Now, stall for about 1 second */ for (i=0;i<3000;i++) asm("nop; nop; nop; nop; nop;"); *(int *) SPCTL1 = 0; *(int *) SPCTL3 = 0; /* SPORT DMA Setup */ *(int *) II3A = (int) tx_buf3a; *(int *) IM3A = 1; *(int *) C3A = TX_BUF3A_LEN; *(int *) II1A = (int) rx_buf1a; *(int *) IM1A = 1; *(int *) C1A = RX_BUF1A_LEN; *(int *) SP13MCTL = 0; *(int *) DIV3 = 0x0011002B; // codec SPI port clock *(int *) DIV1 = 0; interruptf( SIG_SP1I, SPORT_RX_IRQ); interruptf( SIG_SP3I, SPORT_RX_IRQ); *(int *) SPCTL3 |= DDIR | SDEN_A | LAFS | LFS | IFS | FSR | CKRE | ICLK | SLEN16 | SPEN_A; // Active transmit buffers // DMA channel A // Late FS // Framing active low // Internal framing // FS required // Clock edge rising // Internal clock // Word length = 16 // SPORT A enable *(int *) SPCTL1 |= SDEN_A | LAFS | LFS | FSR | CKRE | SLEN16 | SPEN_A; *(int *) SPCTL1 &= (~DDIR & ~IFS & ~ICLK); // DMA channel A // Late FS // Framing active low // FS required // Clock edge rising // Word length = 16 // SPORT A enable // Active receive buffers // External framing // External clock while ( (*(int*) DMASTAT) & 0xA ) asm("idle;"); interruptf( SIG_SP1I, SIG_IGN); interruptf( SIG_SP3I, SIG_IGN); *(int *) SPCTL1 = 0; *(int *) SPCTL3 = 0; return 0; } int rx0a_buf[8]; /* receive buffer (DMA)*/ #pragma retain_name int tx2a_buf[8] = { 0x00000000, /* transmit buffer (DMA)*/ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}; /* TCB = "Transfer Control Block" */ /* TCB format: ECx (length of destination buffer), EMx (destination buffer step size), EIx (destination buffer index (initialized to start address)), GPx ("general purpose"), CPx ("Chain Point register"; points to last address (IIx) of next TCB to jump to upon completion of this TCB.), Cx (length of source buffer), IMx (source buffer step size), IIx (source buffer index (initialized to start address)) */ int rcv0a_tcb[8] = {0, 0, 0, 0, 0, 8, 1, (int) rx0a_buf}; /* SPORT0 receive tcb */ int xmit2a_tcb[8] = {0, 0, 0, 0, 0, 8, 1, (int) tx2a_buf}; /* SPORT2 transmit tcb */ void Program_SPORT02_TDM_Registers() { *(int *) DIV0 = 0; *(int *) DIV2 = 0; /* SPORT0 and SPORT2 are being operated in "multichannel" mode. This is synonymous with TDM mode which is the operating mode for the AD1836 */ /* SPORT 0&2 Miscellaneous Control Bits Registers */ /* SP02MCTL = 0x000000E2, Hold off on MCM enable, and number of TDM slots to 8 active channels */ /* Multichannel Frame Delay=1, Number of Channels = 8, LB disabled */ *(int *) SP02MCTL = NCH_8 | MFD1; /* sport0 control register set up as a receiver in MCM */ /* sport 0 control register SPCTL0 = 0x000C01F0 */ *(int *) SPCTL0 = SCHEN_A | SDEN_A | SLEN32; /* sport2 control register set up as a transmitter in MCM */ /* sport 2 control register, SPCTL2 = 0x000C01F0 */ *(int *) SPCTL2 = SCHEN_A | SDEN_A | SLEN32; /* sport0 & sport2 receive and transmit multichannel word enable registers */ /* enable receive channels 0-7 */ /* enable transmit channels 0-7 */ *(int *) MR0CS0 = *(int *) MT2CS0 =0x000000FF; /* sport0 & sport2 receive & transmit multichannel companding enable registers */ /* no companding for our 8 active timeslots*/ /* no companding on SPORT0 receive */ /* no companding on SPORT2 transmit */ *(int *) MR0CCS0 = *(int *) MT2CCS0 = 0; } void Program_SPORT02_DMA_Channels() { xmit2a_tcb[4] = *(int *) CP2A = ((int) xmit2a_tcb + 7) & 0x3FFFF | (1<<18); rcv0a_tcb[4] = *(int *) CP0A = ((int) rcv0a_tcb + 7) & 0x3FFFF | (1<<18); } #ifdef DEBUG /* TDM audio frame/ISR counter, for debug purposes */ int audio_frame_timer = 0; #endif /* AD1852 Setup */ #define SPI_TX_BUF_LEN 5 int spi_tx_buf[SPI_TX_BUF_LEN] = { RESET_AD1852 | CONTROL_REG, // reset AD1852 DEASSERT_RESET | CONTROL_REG, // remove reset command WL_24_BIT_DATA | I2S_JUSTIFIED | NO_DEMPH_FILTER | CONTROL_REG, 0xFC00 | VOLUME_LEFT, 0xFC00 | VOLUME_RIGHT }; void Init_AD1852_DACs() { // initially clear SPI control register *(int *) SPICTL = 0; *(int *) IISTX = (int) spi_tx_buf; *(int *) IMSTX = 1; *(int *) CSTX = SPI_TX_BUF_LEN; asm("#include "); asm("bit set LIRPTL SPITMSK;"); interruptf( SIG_LP0I, SPORT_RX_IRQ); *(int *) SPICTL |= SPIEN|SPTINT|TDMAEN|MS|FLS1|CPHASE|DF|WL16|BAUDR4|PSSE|DCPH0|SGN|GM; *(int *) SPICTL &= (~CP & ~FLS0 & ~FLS2 & ~FLS3 & ~NSMLS & ~DMISO & ~OPD & ~PACKEN & ~SENDZ & ~RDMAEN & ~SPRINT); while( (*(int*) DMASTAT) & DMA9ST) idle(); interruptf( SIG_LP0I, SIG_IGN); asm("bit clr LIRPTL SPITMSK;"); // *(int *) SPICTL = 0; // usuniete przez MK - wylacza sterowanie SPI i wprowadza // bledny stan CLATCH dla DAC - uniemozliwiajac konfiguracje } /* SDRAM Setup Routine */ void Setup_SDRAM() { /*clear MSx waitstate and mode*/ *(int *)WAIT &= 0xFFF00000; /*refresh rate*/ *(int*) SDRDIV = 0x1000; // SDCTL = 0x02014231; // 1/2 CCLK, no SDRAM buffering option, 2 SDRAM banks // SDRAM mapped to bank 0 only, no self-refresh, page size 256 words // SDRAM powerup mode is prechrg, 8 CRB refs, and then mode reg set cmd // tRCD = 2 cycles, tRP=2 cycles, tRAS=3 cycles, SDCL=1 cycle // SDCLK0, SDCLK1, RAS, CAS and SDCLKE activated *(int *) SDCTL |= SDTRCD2|SDCKR_DIV2|SDBN2|SDEM0|SDPSS|SDPGS256|SDTRP2|SDTRAS3|SDCL1; *(int *) SDCTL &= ~SDBUF & ~SDEM3 & ~SDEM2 & ~SDEM1 & ~SDSRF & ~SDPM & ~DSDCK1 & ~DSDCTL; } /* DSP Setup */ void Setup_ADSP21161N() { /* *** Enable circular buffering in MODE1 Register for revision 0.x silicon. Important when porting 2106x code!!! */ asm("bit set MODE1 CBUFEN;"); /* Setup hardware interrupts, FLAG LEDs and pushbutton */ *(int *) IOFLAG = FLG9|FLG8|FLG7|FLG6|FLG5|FLG4|FLG9O|FLG8O|FLG7O|FLG6O|FLG5O|FLG4O; /* flag 0-3 are inputs from pushbutton switches */ asm("bit clr MODE2 FLG0O | FLG10 | FLG2O | FLG3O;"); /* irqx edge sensitive */ asm("bit set mode2 IRQ2E | IRQ0E | IRQ1E;"); } void Blink_LED_Test( int interations ) { int i,k; for(i=0;i