i2s_at91.c

Go to the documentation of this file.
00001 
00038 #include "i2s_at91.h"
00039 
00040 #include <drv/timer.h>
00041 #include <cfg/log.h>
00042 #include <io/arm.h>
00043 
00044 #define DATALEN (15 & SSC_DATLEN_MASK)
00045 // FIXME: this is not correct for 16 <= DATALEN < 24
00046 #define PDC_DIV ((DATALEN / 8) + 1)
00047 /* PDC_DIV must be 1, 2 or 4, which are the bytes that are transferred
00048  * each time the PDC reads from memory.
00049  */
00050 STATIC_ASSERT(PDC_DIV % 2 == 0);
00051 #define PDC_COUNT (CONFIG_PLAY_BUF_LEN / PDC_DIV)
00052 
00053 static uint8_t play_buf1[CONFIG_PLAY_BUF_LEN];
00054 static uint8_t play_buf2[CONFIG_PLAY_BUF_LEN];
00055 
00056 // the buffer in PDC next is play_buf2
00057 volatile bool is_second_buf_next;
00058 
00059 uint8_t *i2s_getBuffer(unsigned buf_num)
00060 {
00061     LOG_INFO("getBuffer start\n");
00062 
00063     if (i2s_isPlaying())
00064     {
00065         ASSERT(0);
00066         return 0;
00067     }
00068 
00069     if (buf_num == I2S_SECOND_BUF)
00070         return play_buf2;
00071     else if (buf_num == I2S_FIRST_BUF)
00072         return play_buf1;
00073     else
00074         return 0;
00075 }
00076 
00077 uint8_t *i2s_getFreeBuffer(void)
00078 {
00079     if (!i2s_isPlaying())
00080     {
00081         ASSERT(0);
00082         return 0;
00083     }
00084 
00085     // wait PDC transmission end
00086     if (!(SSC_SR & BV(SSC_ENDTX)))
00087         return 0;
00088 
00089     uint8_t *ret_buf = 0;
00090     // the last time we got called, the second buffer was in PDC next
00091     if (is_second_buf_next)
00092     {
00093         is_second_buf_next = false;
00094         ret_buf = play_buf1;
00095     }
00096     // the last time the first buffer was in PDC next
00097     else
00098     {
00099         is_second_buf_next = true;
00100         ret_buf = play_buf2;
00101     }
00102 
00103     if (ret_buf)
00104     {
00105         SSC_TNPR = (reg32_t) ret_buf;
00106         SSC_TNCR = PDC_COUNT;
00107     }
00108     return ret_buf;
00109 }
00110 
00111 bool i2s_start(void)
00112 {
00113     /* Some time must pass between disabling and enabling again the transmission
00114      * on SSC. A good empirical value seems >15 us. We try to avoid putting an
00115      * explicit delay, instead we disable the transmitter when a sound finishes
00116      * and hope that the delay has passed before we enter here again.
00117      */
00118     SSC_CR = BV(SSC_TXDIS);
00119     timer_delay(10);
00120 
00121     SSC_PTCR = BV(PDC_TXTDIS);
00122     SSC_TPR = (reg32_t)play_buf1;
00123     SSC_TCR = PDC_COUNT;
00124     SSC_TNPR = (reg32_t)play_buf2;
00125     SSC_TNCR = PDC_COUNT;
00126     is_second_buf_next = true;
00127 
00128     SSC_PTCR = BV(PDC_TXTEN);
00129 
00130     /* enable output */
00131     SSC_CR = BV(SSC_TXEN);
00132 
00133     return true;
00134 }
00135 
00136 #define BITS_PER_CHANNEL 16
00137 #define N_OF_CHANNEL 2
00138 // TODO: check the computed value?
00139 /* The last parameter (2) is due to the hadware on at91sam7s. */
00140 #define MCK_DIV (CPU_FREQ / CONFIG_SAMPLE_FREQ / BITS_PER_CHANNEL / N_OF_CHANNEL / 2)
00141 
00142 #define CONFIG_DELAY 1
00143 #define CONFIG_PERIOD 15
00144 #define CONFIG_DATNB  1
00145 #define CONFIG_FSLEN 15
00146 
00147 #define DELAY ((CONFIG_DELAY << SSC_STTDLY_SHIFT) & SSC_STTDLY_MASK)
00148 #define PERIOD ((CONFIG_PERIOD << (SSC_PERIOD_SHIFT)) & SSC_PERIOD_MASK)
00149 #define DATNB ((CONFIG_DATNB << SSC_DATNB_SHIFT) & SSC_DATNB_MASK)
00150 #define FSLEN ((CONFIG_FSLEN << SSC_FSLEN_SHIFT) & SSC_FSLEN_MASK)
00151 
00152 #define SSC_DMA_IRQ_PRIORITY 5
00153 
00154 void i2s_init(void)
00155 {
00156     PIOA_PDR = BV(SSC_TK) | BV(SSC_TF) | BV(SSC_TD);
00157     /* reset device */
00158     SSC_CR = BV(SSC_SWRST);
00159 
00160     SSC_CMR = MCK_DIV & SSC_DIV_MASK;
00161     SSC_TCMR = SSC_CKS_DIV | SSC_CKO_CONT | SSC_CKG_NONE | DELAY | PERIOD | SSC_START_FALL_F;
00162     SSC_TFMR = DATALEN | DATNB | FSLEN | BV(SSC_MSBF) | SSC_FSOS_NEGATIVE;
00163 
00164     /* Disable all irqs */
00165     SSC_IDR = 0xFFFFFFFF;
00166 
00167     /* Enable the SSC IRQ */
00168     AIC_IECR = BV(SSC_ID);
00169 
00170     /* enable i2s */
00171     PMC_PCER = BV(SSC_ID);
00172 
00173     /* Enable SSC */
00174     SSC_CR = BV(SSC_TXEN);
00175 }