📄 ad1836_reg_init_viasports.asm
字号:
/*** 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:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -