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