Nut/OS  4.10.3
API Reference
tlv320dac.c
Go to the documentation of this file.
00001 
00057 #include <cfg/os.h>
00058 #include <cfg/clock.h>
00059 #include <dev/board.h>
00060 #include <dev/irqreg.h>
00061 #include <dev/twif.h>
00062 
00063 #include <stdlib.h>
00064 #include <string.h>
00065 #include <memdebug.h>
00066 
00067 #include <sys/event.h>
00068 #include <sys/timer.h>
00069 
00070 #include <dev/tlv320dac.h>
00071 
00072 #ifndef TWI_SLA_DAC
00073 #define TWI_SLA_DAC     0x1A
00074 #endif
00075 
00076 /*
00077  * Initial volume.
00078  */
00079 #ifndef TLV320DAC_VOL
00080 #define TLV320DAC_VOL   0x18
00081 #endif
00082 
00083 /*
00084  * Number of PCM buffers.
00085  */
00086 #ifndef SAMPLE_BUFFERS
00087 #if defined (AT91SAM9260_EK)
00088 #define SAMPLE_BUFFERS  32
00089 #else
00090 #define SAMPLE_BUFFERS  3
00091 #endif
00092 #endif
00093 
00094 /*
00095  * Select I2S pins.
00096  */
00097 #if defined (MCU_AT91SAM9260) /* _EK */
00098 
00099 #define DACI2S_PIO_ID   PIOB_ID
00100 #define DACI2S_PINS_A   _BV(PB18_TD0_A) | _BV(PB17_TF0_A) | _BV(PB16_TK0_A)
00101 #define DACI2S_PINS_B   0
00102 
00103 #else                           /* _EK */
00104 #define DACI2S_PIO_ID   PIOA_ID
00105 #define DACI2S_PINS_A   _BV(PA23_TD_A) | _BV(PA21_TF_A) | _BV(PA22_TK_A)
00106 #define DACI2S_PINS_B   0
00107 #endif                          /* _EK */
00108 
00109 /*
00110  * Determine PIO used by I2S.
00111  */
00112 #if DACI2S_PIO_ID == PIOA_ID    /* DACI2S_PIO_ID */
00113 #define DACI2S_PDR  PIOA_PDR
00114 #define DACI2S_ASR  PIOA_ASR
00115 #define DACI2S_BSR  PIOA_BSR
00116 #elif DACI2S_PIO_ID == PIOB_ID  /* DACI2S_PIO_ID */
00117 #define DACI2S_PDR  PIOB_PDR
00118 #define DACI2S_ASR  PIOB_ASR
00119 #define DACI2S_BSR  PIOB_BSR
00120 #endif                          /* DACI2S_PIO_ID */
00121 
00122 volatile uint32_t irq_counter;
00123 
00127 static HANDLE i2s_que;
00128 
00132 #define PCM_CHANS   2
00133 
00137 #define PCM_BITS    16
00138 
00142 typedef struct _PCM_BUFFER {
00143     u_short *wbf_dat;           
00144     int wbf_siz;                
00145     int wbf_len;                
00146 } PCM_BUFFER;
00147 
00148 /* Enable PDC hardware. */
00149 unsigned int use_pdc = 1;
00150 /* PCM buffer queue. */
00151 static PCM_BUFFER pcm_bufq[SAMPLE_BUFFERS];
00152 /* PCM buffer read index. */
00153 static volatile unsigned int brd_idx;
00154 /* PCM buffer read position. */
00155 static volatile int brd_pos;
00156 /* PCM buffer write index. */
00157 static unsigned int bwr_idx;
00158 
00164 static void I2sPdcFill(void)
00165 {
00166     if (brd_idx != bwr_idx) {
00167         if (inr(SSC_TNCR) == 0) {
00168             if (++brd_idx >= SAMPLE_BUFFERS) {
00169                 brd_idx = 0;
00170             }
00171             outr(SSC_TNPR, (unsigned int) pcm_bufq[brd_idx].wbf_dat);
00172             outr(SSC_TNCR, pcm_bufq[brd_idx].wbf_len);
00173         }
00174     }
00175 }
00176 
00182 static void I2sInterrupt(void *arg)
00183 {
00184     irq_counter++;
00185     if (use_pdc) {
00186         I2sPdcFill();
00187         NutEventPostFromIrq(&i2s_que);
00188     } else {
00189         if (brd_pos >= pcm_bufq[brd_idx].wbf_len) {
00190             brd_pos = 0;
00191             NutEventPostFromIrq(&i2s_que);
00192             if (brd_idx == bwr_idx) {
00193                 outr(SSC_THR, 0);
00194                 return;
00195             }
00196             if (++brd_idx >= SAMPLE_BUFFERS) {
00197                 brd_idx = 0;
00198             }
00199         }
00200         outr(SSC_THR, pcm_bufq[brd_idx].wbf_dat[brd_pos]);
00201         brd_pos++;
00202     }
00203 }
00204 
00214 u_char Tlv320DacReadReg(unsigned int reg)
00215 {
00216     return 0xFF;
00217 }
00218 
00227 void Tlv320DacWriteReg(unsigned int reg, unsigned int val)
00228 {
00229     u_char txdata[2];
00230 
00231     txdata[0] = (u_char)(reg << 1) | (u_char)(val >> 8);
00232     txdata[1] = (u_char)val;
00233     TwMasterTransact(TWI_SLA_DAC, txdata, 2, NULL, 0, 0);
00234 }
00235 
00243 static int Tlv320I2sEnable(unsigned int rate)
00244 {
00245     /* Enable SSC clock. */
00246     outr(PMC_PCER, _BV(SSC_ID));
00247 
00248     /* Select SSC peripheral functions. */
00249     outr(DACI2S_ASR, DACI2S_PINS_A);
00250     outr(DACI2S_BSR, DACI2S_PINS_B);
00251 
00252     /* Enable SSC peripheral pins. */
00253     outr(DACI2S_PDR, DACI2S_PINS_A | DACI2S_PINS_B);
00254 
00255     /* Configure 16-bit stereo I2S transmit format. */
00256     outr(SSC_CMR, 0);
00257     outr(SSC_TCMR,              /* Set transmit clock mode. */
00258         SSC_CKS_PIN |            /* Use external clock at TK. */
00259         SSC_START_EDGE_RF |     /* Start transmission on any edge. */
00260         (1 << SSC_STTDLY_LSB)); /* Delay start by 1 cycle. */
00261     outr(SSC_TFMR,              /* Set transmit frame mode. */
00262         ((PCM_BITS - 1) << SSC_DATLEN_LSB) |   /* Transmit 16 bits. */
00263         SSC_MSBF);              /* Most significant bit first. */
00264 
00265     if (use_pdc) {
00266         /* Enable transmitter in PDC mode. */
00267         outr(SSC_PTCR, PDC_TXTEN);
00268     }
00269     outr(SSC_CR, SSC_TXEN);
00270 
00271     return 0;
00272 }
00273 
00279 static int Tlv320I2sDisable(void)
00280 {
00281     /* Disable all interrupts. */
00282     outr(SSC_IDR, 0xFFFFFFFF);
00283 
00284     /* Disable SSC interrupt. */
00285     NutIrqDisable(&sig_SSC);
00286 
00287     /* Disable SSC clock. */
00288     outr(PMC_PCDR, _BV(SSC_ID));
00289 
00290     /* Reset receiver and transmitter. */
00291     outr(SSC_CR, SSC_SWRST | SSC_RXDIS | SSC_TXDIS);
00292     outr(SSC_RCMR, 0);
00293     outr(SSC_RFMR, 0);
00294     outr(SSC_PTCR, PDC_RXTDIS);
00295     outr(SSC_PTCR, PDC_TXTDIS);
00296     outr(SSC_TNCR, 0);
00297     outr(SSC_TCR, 0);
00298 
00299     return 0;
00300 }
00301 
00309 static int Tlv320I2sInit(unsigned int rate)
00310 {
00311     /* Register SSC interrupt handler. */
00312     NutRegisterIrqHandler(&sig_SSC, I2sInterrupt, 0);
00313 
00314     Tlv320I2sDisable();
00315     Tlv320I2sEnable(rate);
00316 
00317     /* Enable SSC interrupt. */
00318     NutIrqEnable(&sig_SSC);
00319 
00320     return 0;
00321 }
00322 
00323 int Tlv320DacSetRate(unsigned int rate)
00324 {
00325     switch(rate) {
00326     case 8000:
00327 #ifdef AT91SAM7X_EK
00328         Tlv320DacWriteReg(DAC_SRATE, (3 << DAC_SRATE_SR_LSB));
00329 #else
00330         Tlv320DacWriteReg(DAC_SRATE, (3 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00331 #endif
00332         break;
00333     case 8021:      
00334         Tlv320DacWriteReg(DAC_SRATE, (11 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00335         break;
00336     case 44100:     
00337         Tlv320DacWriteReg(DAC_SRATE, (8 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00338         break;
00339     case 48000:     
00340         Tlv320DacWriteReg(DAC_SRATE, (0 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00341         break;
00342     case 88200:     
00343         Tlv320DacWriteReg(DAC_SRATE, (15 << DAC_SRATE_SR_LSB) | DAC_SRATE_BOSR | DAC_SRATE_USB);
00344         break;
00345     case 96000:     
00346         Tlv320DacWriteReg(DAC_SRATE, (7 << DAC_SRATE_SR_LSB) | DAC_SRATE_USB);
00347         break;
00348     default:        
00349         return -1;
00350     }
00351     return 0;
00352 }
00353 
00361 int Tlv320DacInit(unsigned int rate)
00362 {
00363     /* Initialize TWI. */
00364     TwInit(0);
00365 
00366     Tlv320DacWriteReg(DAC_RESET, 0);
00367     /* Power down line in. */
00368     Tlv320DacWriteReg(DAC_PWRDN, DAC_PWRDN_LINE);
00369     Tlv320DacWriteReg(DAC_PWRDN, 0);
00370     /* Set sampling rate. */
00371     if (Tlv320DacSetRate(rate)) {
00372         Tlv320DacWriteReg(DAC_RESET, 0);
00373         return -1;
00374     }
00375     Tlv320DacWriteReg(DAC_ANA_PATH, DAC_ANA_PATH_DAC | DAC_ANA_PATH_INSEL | DAC_ANA_PATH_MICB);
00376     Tlv320DacWriteReg(DAC_DIG_PATH, 0);
00377     /* I2S master. */
00378     Tlv320DacWriteReg(DAC_DAI_FMT, DAC_DAI_FMT_MS | DAC_DAI_FMT_FOR_I2S);
00379     Tlv320DacWriteReg(DAC_DI_ACT, DAC_DI_ACT_ACT);
00380 
00381     Tlv320DacWriteReg(DAC_LHP_VOL, DAC_LHP_VOL_LRS | (0x60 << DAC_LHP_VOL_LHV_LSB));
00382 
00383     /* Initialize I2S. */
00384     return Tlv320I2sInit(rate);
00385 }
00386 
00392 static int Tlv320DacStart(void)
00393 {
00394     NutIrqDisable(&sig_SSC);
00395     if (use_pdc) {
00396         outr(SSC_IDR, SSC_TXEMPTY);
00397         /* Enable transmitter in PDC mode. */
00398         outr(SSC_PTCR, PDC_TXTEN);
00399         I2sPdcFill();
00400         outr(SSC_IER, SSC_ENDTX);
00401     } else {
00402         outr(SSC_IDR, SSC_ENDTX);
00403         /* Disable transmitter in PDC mode. */
00404         outr(SSC_PTCR, PDC_TXTDIS);
00405         outr(SSC_IER, SSC_TXEMPTY);
00406     }
00407     /* Enable transmitter. */
00408     outr(SSC_CR, SSC_TXEN);
00409     NutIrqEnable(&sig_SSC);
00410 
00411     return 0;
00412 }
00413 
00419 int Tlv320DacFlush(void)
00420 {
00421     int rc = 0;
00422 
00423     while (bwr_idx != brd_idx) {
00424         Tlv320DacStart();
00425         if ((rc = NutEventWait(&i2s_que, 500)) != 0) {
00426             break;
00427         }
00428     }
00429     return rc;
00430 }
00431 
00440 int Tlv320DacWrite(void *buf, int len)
00441 {
00442     unsigned int idx;
00443 
00444     /* Move to the next buffer to write to. */
00445     idx = bwr_idx + 1;
00446     if (idx >= SAMPLE_BUFFERS) {
00447         idx = 0;
00448     }
00449 
00450     /* If all buffers are filled, wait for an event posted by the
00451        interrupt routine. */
00452     while (idx == brd_idx) {
00453         if (NutEventWait(&i2s_que, 100)) {
00454             Tlv320DacStart();
00455         }
00456     }
00457 
00458     /*
00459      * Check, if the current buffer size is too small or not allocated.
00460      */
00461     if (pcm_bufq[idx].wbf_siz < len) {
00462         if (pcm_bufq[idx].wbf_siz) {
00463             free(pcm_bufq[idx].wbf_dat);
00464             pcm_bufq[idx].wbf_siz = 0;
00465         }
00466         pcm_bufq[idx].wbf_dat = malloc(len * 2);
00467         if (pcm_bufq[idx].wbf_dat == NULL) {
00468             /* Out of memory. */
00469             return -1;
00470         }
00471         pcm_bufq[idx].wbf_siz = len;
00472     }
00473 
00474     /*
00475      * At this point we got an available buffer with sufficient size.
00476      * Move the data to it, set the number of valid bytes and update
00477      * the write (producer) index.
00478      */
00479     memcpy(pcm_bufq[idx].wbf_dat, buf, len * 2);
00480     pcm_bufq[idx].wbf_len = len;
00481     bwr_idx = idx;
00482 
00483     return 0;
00484 }
00485 
00496 int Tlv320DacSetVolume(int left, int right)
00497 {
00498     /* Cut to limits. */
00499     if (left > DAC_MAX_VOLUME) {
00500         left = DAC_MAX_VOLUME;
00501     }
00502     else if (left < DAC_MIN_VOLUME) {
00503         left = DAC_MIN_VOLUME;
00504     }
00505     if (right > DAC_MAX_VOLUME) {
00506         right = DAC_MAX_VOLUME;
00507     }
00508     else if (right < DAC_MIN_VOLUME) {
00509         right = DAC_MIN_VOLUME;
00510     }
00511     Tlv320DacWriteReg(DAC_LHP_VOL, (unsigned int)(left + 121));
00512     Tlv320DacWriteReg(DAC_RHP_VOL, (unsigned int)(right + 121));
00513 
00514     return 0;
00515 }
00516 
00517 int Tlv320SwitchMode(void)
00518 {
00519     NutIrqDisable(&sig_SSC);
00520     use_pdc = !use_pdc;
00521     Tlv320DacStart();
00522     return 0;
00523 }