*/
+
+#include "hw/hw_i2s.h"
+
#include "cfg/cfg_i2s.h"
// Define log settings for cfg/log.h.
uint32_t ctrla;
uint32_t ctrlb;
-
static void i2s_dmac_irq(uint32_t status)
{
- PIOA_SODR = BV(13);
+ I2S_STROBE_ON();
if (single_transfer)
{
single_transfer = false;
if (status & (BV(I2S_DMAC_CH) << DMAC_EBCIDR_ERR0))
{
error = true;
+ // Disable to reset channel and clear fifo
DMAC_CHDR = BV(I2S_DMAC_CH);
- kprintf("irq_err[%08lx]\n", DMAC_EBCISR);
}
else
{
remaing_size = transfer_size;
next_idx = 0;
}
-
}
}
event_do(&data_ready);
- PIOA_CODR = BV(13);
+ I2S_STROBE_OFF();
}
static void sam3_i2s_txStart(I2s *i2s, void *buf, size_t len, size_t slice_len)
//Confing DMAC
-
DMAC_CHDR = BV(I2S_DMAC_CH);
- kprintf("Start streaming [%08lx]\n", DMAC_EBCISR);
+ reg32_t reg = DMAC_EBCISR;
- cfg = BV(DMAC_CFG_DST_H2SEL) | BV(DMAC_CFG_SOD) |
- ((3 << DMAC_CFG_DST_PER_SHIFT) & DMAC_CFG_DST_PER_MASK) | (3 & DMAC_CFG_SRC_PER_MASK);
+ LOG_INFO("Start streaming [%08lx]\n", reg);
- ctrla = DMAC_CTRLA_SRC_WIDTH_HALF_WORD |
- DMAC_CTRLA_DST_WIDTH_HALF_WORD;
-
- ctrlb = DMAC_CTRLB_FC_MEM2PER_DMA_FC |
- DMAC_CTRLB_DST_INCR_FIXED |
- DMAC_CTRLB_SRC_INCR_INCREMENTING;
+ cfg = BV(DMAC_CFG_DST_H2SEL) | BV(DMAC_CFG_SOD) |
+ ((3 << DMAC_CFG_DST_PER_SHIFT) & DMAC_CFG_DST_PER_MASK) | (3 & DMAC_CFG_SRC_PER_MASK);
+ ctrla = DMAC_CTRLA_SRC_WIDTH_HALF_WORD | DMAC_CTRLA_DST_WIDTH_HALF_WORD;
+ ctrlb = DMAC_CTRLB_FC_MEM2PER_DMA_FC | DMAC_CTRLB_DST_INCR_FIXED | DMAC_CTRLB_SRC_INCR_INCREMENTING;
prev = &lli0;
curr = &lli0;
lli0.src_addr = (uint32_t)&sample_buff[0];
lli0.dst_addr = (uint32_t)&SSC_THR;
lli0.dsc_addr = (uint32_t)next;
- lli0.ctrla = ctrla | (chunk_size & 0xffff) ;
+ lli0.ctrla = ctrla | (chunk_size & 0xffff);
lli0.ctrlb = ctrlb & ~BV(DMAC_CTRLB_IEN);
remaing_size -= chunk_size;
dmac_configureDmaCfgLLI(I2S_DMAC_CH, &lli0, cfg);
if (dmac_start(I2S_DMAC_CH) < 0)
- kprintf("start erros[%x]\n", dmac_error(I2S_DMAC_CH));
+ {
+ LOG_ERR("DMAC start[%x]\n", dmac_error(I2S_DMAC_CH));
+ return;
+ }
error = false;
SSC_CR = BV(SSC_TXEN);
event_wait(&data_ready);
if (error)
{
- kputs("Errore\n");
+ LOG_ERR("Errow while streaming.\n");
break;
}
static bool sam3_i2s_isRxFinish(struct I2s *i2s)
{
(void)i2s;
- return dmac_isDone(I2S_DMAC_CH);
+ return 0;
}
static void sam3_i2s_txBuf(struct I2s *i2s, void *buf, size_t len)
static int sam3_i2s_write(struct I2s *i2s, uint32_t sample)
{
(void)i2s;
+
SSC_CR = BV(SSC_TXEN);
- while(!(SSC_SR & BV(SSC_TXRDY)));
+ while(!(SSC_SR & BV(SSC_TXRDY)))
+ cpu_relax();
+
SSC_THR = sample;
return 0;
}
static uint32_t sam3_i2s_read(struct I2s *i2s)
{
(void)i2s;
- SSC_CR = BV(SSC_RXEN);
- while(!(SSC_SR & BV(SSC_RXRDY)));
- return SSC_RHR;
-}
+ SSC_CR = BV(SSC_RXEN);
+ while(!(SSC_SR & BV(SSC_RXRDY)))
+ cpu_relax();
-static DECLARE_ISR(irq_ssc)
-{
+ return SSC_RHR;
}
-
-
/* We divite for 2 because the min clock for i2s i MCLK/2 */
#define MCK_DIV (CPU_FREQ / (CONFIG_SAMPLE_FREQ * CONFIG_WORD_BIT_SIZE * CONFIG_CHANNEL_NUM * 2))
#define DATALEN ((CONFIG_WORD_BIT_SIZE - 1) & SSC_DATLEN_MASK)
DB(i2s->ctx._type = I2S_SAM3X;)
i2s->hw = &i2s_hw;
+ I2S_STROBE_INIT();
+
PIOA_PDR = BV(SSC_TK) | BV(SSC_TF) | BV(SSC_TD);
PIO_PERIPH_SEL(PIOA_BASE, BV(SSC_TK) | BV(SSC_TF) | BV(SSC_TD), PIO_PERIPH_B);
PIOB_PDR = BV(SSC_RD) | BV(SSC_RF);