/*** SPORTs1&3_SPI_Emulation.ASM ******************************************** * * * AD1836/ADSP-21161 SPI Code Register Initialization via SPI Emulation * * * * * *********************************************************************************/ /* ADSP-21161 System Register bit definitions */ /* refer to latest DEF21161.H file for SPORT bitfield definitions */ #include "def21161.h" .GLOBAL Program_AD1836_regs_via_SPI; .GLOBAL Count_SPORT1_RX_IRQs; .GLOBAL Count_SPORT3_TX_IRQs; //.EXTERN Wait_Approx_999us; .GLOBAL Wait_Approx_1500ms; .GLOBAL Wait_Approx_167ms; // AD1836 codec SPI control/status register definitions #define READ_REG 0x0800 #define WRITE_REG 0x0000 #define DAC_CONTROL1 0x0000 #define DAC_CONTROL2 0x1000 #define DAC_VOLUME0 0x2000 #define DAC_VOLUME1 0x3000 #define DAC_VOLUME2 0x4000 #define DAC_VOLUME3 0x5000 #define DAC_VOLUME4 0x6000 #define DAC_VOLUME5 0x7000 #define ADC0_PEAK_LEVEL 0x8000 #define ADC1_PEAK_LEVEL 0x9000 #define ADC2_PEAK_LEVEL 0xA000 #define ADC3_PEAK_LEVEL 0xB000 #define ADC_CONTROL1 0xC000 #define ADC_CONTROL2 0xD000 #define ADC_CONTROL3 0xE000 #define RESERVED_REG 0xF000 .SEGMENT/dm dm_data; /* Powerdown ADCs and DACs twice to get around AD1836 SPI/powerdown anomaly */ .var powerdown_AD1836[4] = DAC_CONTROL1 | WRITE_REG | 0x004, DAC_CONTROL1 | WRITE_REG | 0x004, ADC_CONTROL1 | WRITE_REG | 0x080, ADC_CONTROL1 | WRITE_REG | 0x080; .var 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 .var tx_buf3a[21] = //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, ADC_CONTROL1 | WRITE_REG | 0x000, // write ADC_CTL1 twice to workaround pwdwn SPI anomaly ADC_CONTROL1 | WRITE_REG | 0x000, ADC_CONTROL3 | WRITE_REG | 0x000, // 256*Fs Clock Mode !!!, differential PGA mode 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; .var rx_buf1a[21]; /* ISR counters, for debug purposes to see how many times SPORT DMA interrupts are serviced */ .VAR SP1I_counter = 0; .VAR SP3I_counter = 0; .endseg; .segment /pm pm_code; ///////////////////////////////////////////////////////////////////////////////////////// // // // Program SPORT1 & SPORT3 Control Registers for SPI emulation control // // // ///////////////////////////////////////////////////////////////////////////////////////// Program_AD1836_regs_via_SPI: r0=0x00000000; // initially clear SPORT control register dm(SPCTL1)=r0; dm(SPCTL3)=r0; ustat1=dm(SPCTL3); ustat2=dm(SPCTL1); ustat3=dm(SP13MCTL); powerdown_reset_AD1836: r0=powerdown_AD1836; dm(II3A)=r0; /* Internal DMA6 memory address */ r0=1; dm(IM3A)=r0; /* Internal DMA6 memory access modifier */ r0=@powerdown_AD1836; dm(C3A)=r0; /* Contains number of DMA6 transfers to be done */ r0=powerdown_rx_buf0a; dm(II1A)=r0; /* Internal DMA2 memory address */ r0=1; dm(IM1A)=r0; /* Internal DMA2 memory access modifier */ r0=@powerdown_rx_buf0a; dm(C1A)=r0; /* Contains number of DMA2 transfers to be done */ /* clear multichannel/miscellaneous control register for SPORT1 & SPORT3 */ R0 = 0x0; dm(SP13MCTL) = R0; R0 = 0x0011002B; dm(DIV3) = R0; R0 = 0; dm(DIV1) = R0; bit set ustat1 DDIR | SDEN_A | LAFS | LFS | IFS | FSR | CKRE | ICLK | SLEN16 | SPEN_A; dm(SPCTL3) = ustat1; bit set ustat2 SDEN_A | LAFS | LFS | FSR | CKRE | SLEN16 | SPEN_A; bit clr ustat2 DDIR | IFS | ICLK; dm(SPCTL1) = ustat2; bit set imask SP1I | SP3I; // enable SPORT1 RX and SPORT3 TX interrupts powerdwm_not_done_yet: idle; R1 = 0x00000008; // Test for SPORT3 R0 = DM(DMASTAT); R0 = R0 AND R1; IF NE jump powerdwm_not_done_yet; bit clr imask SP1I|SP3I; // disable SPORT1 RX and SPORT3 TX interrupts Wait_Approx_1s: lcntr = 3000, do waitloop until lce; nop; nop; nop; waitloop: nop; bit clr ustat1 0xFFFFFFFF; dm(SPCTL1) = ustat1; dm(SPCTL3) = ustat1; IRPTL=0; bit clr IMASK SP1I | SP3I; SPORT_DMA_setup: r0=0x00000000; // initially clear SPORT control register dm(SPCTL1)=r0; dm(SPCTL3)=r0; ustat1=dm(SPCTL3); ustat2=dm(SPCTL1); ustat3=dm(SP13MCTL); r0=tx_buf3a; dm(II3A)=r0; /* Internal DMA6 memory address */ r0=1; dm(IM3A)=r0; /* Internal DMA6 memory access modifier */ r0=@tx_buf3a; dm(C3A)=r0; /* Contains number of DMA6 transfers to be done */ r0=rx_buf1a; dm(II1A)=r0; /* Internal DMA2 memory address */ r0=1; dm(IM1A)=r0; /* Internal DMA2 memory access modifier */ r0=@rx_buf1a; dm(C1A)=r0; /* Contains number of DMA2 transfers to be done */ /* clear multichannel/miscellaneous control register for SPORT1 & SPORT3 */ R0 = 0x0; dm(SP13MCTL) = R0; /* internally generating FS3 and *HARDWARE* looping it back to FS1 for SPORT1/3 SPI control */ /* Maximum SPI serial bit clock rate is 8MHz... select 1 MHz to allow safety factor of 8 according to 9-42 of user's manual, xCLKDIV = ((2 x fCLKIN)/(serial clock frequency)) - 1 Thus, xCLKDIV = ((2 x 30 MHz)/(1 MHz)) - 1 = 59 = 0011 1011 (binary) = 0x003B Now, since we want 16 bit clocks per frame, set FSDIV to 16-1 = 15 = 0x000F */ // R0 = 0x00270004; dm(DIV3) = R0; // R0 = 0x000F003B; dm(DIV3) = R0; R0 = 0x0011002B; dm(DIV3) = R0; R0 = 0; dm(DIV1) = R0; /* SPCTL3 SPORT CONTROL REGISTER BITs 31:26 -- Read-only status bits 25 -- DDIR Bit = 1, Transmitter 24 -- SPORT Enable B: 0 Disabled 23 -- reserved 22 -- Word Select: 0 issue if data in either Tx 21:20 -- DMA chaining and DMA enables for Channel B: 0:0 Disabled 19 -- SPORT xmit DMA chaining enable A: 0 disable 18 -- SPORT xmit DMA enable A: 0 disable 17 -- Late FS: 1 Late (see p.7 of 1836 data sheet) 16 -- Active Low FS: 1 Active Low 15 -- TFS data dependency: 0 TFS signal generated only when new data is in SPORT channel's transmit data buffer 14 -- IFS Source: 1 internal 13 -- FSR Requirement: 1 FS required 12 -- Active Clock Edge: 1 rising edge 11 -- Operation mode: 0 non-I2S mode 10 -- Xmit Clk source: 1 internal 9 -- 16/32-bit pack: 0 no unpacking of 32-bit words into separate 16-bit words for transmission 8:4 -- Serial Word Length minus 1: 01111 3 -- Endian word format: 0 MSB first 2:1 -- Data Type: 0:0 r-justify; fill MSBs w/0s 0 -- SPORT Enable A: 1 enable A */ // R0 = 0x020374F1; bit set ustat1 DDIR | SDEN_A | LAFS | LFS | IFS | FSR | CKRE | ICLK | SLEN16 | SPEN_A; dm(SPCTL3) = ustat1; /* SRCTL0 SPORT CONTROL REGISTER BITs 31:26 -- Read-only status bits 25 -- DDIR Bit = 0, Receiver 24 -- SPORT Enable B: 0 Disabled 23 -- MCE - SPORT Mode: 0 DSP SPORT Mode 22 -- SPORT Loopback: 0 disable 21:20 -- DMA chaining and DMA enables for Channel B: 0:0 Disabled 19 -- SPORT Rcv DMA chaining enable A: 0 disabled 18 -- SPORT Rcv DMA enable A: 0 disabled 17 -- Late RFS: 1 Late (see 9-54 of workshop manual and p.7 of 1836 data sheet) 16 -- Active Low RFS: 1 Active Low (again, see 9-54 of workshop manual and p.7 of...) 15 -- reserved 14 -- IRFS - RFS Source: 0 external 13 -- RFS Requirement: 1 RFS required 12 -- Active Clock Edge: 1 rising edge 11 -- Operation mode: 0 non-I2S mode 10 -- Rcv Clk source: 0 external 9 -- 16/32-bit pack: 0 no packing of received 16-bit words into 32-bit words 8:4 -- Serial Word Length minus 1: 01111 3 -- Endian word format: 0 MSB first 2:1 -- Data Type: 0:0 r-justify; fill MSBs w/0s 0 -- SPORT Enable A: 1 enable A NOTE: SPORT1 & SPORT3 clock and frame syncs tied together, generated by SPORT3 */ // R0 = 0x000330F1; bit set ustat2 SDEN_A | LAFS | LFS | FSR | CKRE | SLEN16 | SPEN_A; bit clr ustat2 DDIR | IFS | ICLK; dm(SPCTL1) = ustat2; bit set imask SP1I | SP3I; // enable SPORT0 RX and SPORT2 TX interrupts SPORT_DMAs_not_done_yet: idle; R1 = 0x0000000A; // Test for SPORT1 and SPORT3 DMA completion R0 = DM(DMASTAT); R0 = R0 AND R1; IF NE jump SPORT_DMAs_not_done_yet; bit clr ustat1 0xFFFFFFFF; dm(SPCTL1) = ustat1; dm(SPCTL3) = ustat1; IRPTL=0; bit clr IMASK SP1I | SP3I; // disable SPORT1 and SPORT3 interrupts rts; Program_AD1836_regs_via_SPI.end: /* With lcntr = 1000, this actually waits roughly 1s*/ Wait_Approx_1500ms: lcntr = 1000, do waitloop250ms until lce; nop; nop; nop; //call Wait_Approx_999us; nop; nop; waitloop250ms: nop; nop; nop; rts; Wait_Approx_1500ms.end: /* This loop has been cut to approx length 110ms instead of 167ms*/ Wait_Approx_167ms: lcntr = 110, do waitloop200ms until lce; nop; nop; nop; //call Wait_Approx_999us; nop; nop; waitloop200ms: nop; nop; nop; rts; Wait_Approx_167ms.end: ///////////////////////////////////////////////////////////// // // // SPORT1 and SPORT3 Interrupt Service Routines // // // ///////////////////////////////////////////////////////////// Count_SPORT1_RX_IRQs: r0=dm(SP1I_counter); /* get last count */ r0=r0+1; /* increment count */ dm(SP1I_counter)=r0; /* save updated count */ RTI; Count_SPORT1_RX_IRQs.end: Count_SPORT3_TX_IRQs: r0=dm(SP3I_counter); /* get last count */ r0=r0+1; /* increment count */ dm(SP3I_counter)=r0; /* save updated count */ RTI; Count_SPORT3_TX_IRQs.end: