Add sam3n bechmark into nightly test.
[bertos.git] / bertos / drv / i2s.h
index e010470f0de85c7b0d926758afaa29b25f661e36..8758cb0080cb7e2a18e0340743495214603c1893 100644 (file)
-#ifndef I2S_H
-#define I2S_H
+/**
+ * \file
+ * <!--
+ * This file is part of BeRTOS.
+ *
+ * Bertos is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ * As a special exception, you may use this file as part of a free software
+ * library without restriction.  Specifically, if other files instantiate
+ * templates or use macros or inline functions from this file, or you compile
+ * this file and link it with other files to produce an executable, this
+ * file does not by itself cause the resulting executable to be covered by
+ * the GNU General Public License.  This exception does not however
+ * invalidate any other reasons why the executable file might be covered by
+ * the GNU General Public License.
+ *
+ * Copyright 2011 Develer S.r.l. (http://www.develer.com/)
+ *
+ * -->
+ *
+ * \defgroup i2s Generic I2S driver
+ * \ingroup drivers
+ * \{
+ * \brief
+ *
+ * <b>Configuration file</b>: cfg_i2s.h
+ *
+ * \author Daniele Basile <asterix@develer.com>
+ *
+ * $WIZ$ module_name = "i2s"
+ * $WIZ$ module_configuration = "bertos/cfg/cfg_i2s.h"
+ * $WIZ$ module_supports = "not all"
+ */
+
+
+#ifndef DRV_I2S_H
+#define DRV_I2S_H
+
+#warning __FILTER_NEXT_WARNING__
+#warning This API is ALPHA! we could change it..
 
 #include <cfg/compiler.h>
+#include <cfg/debug.h>
+#include <cfg/macros.h>
+
+#include <cpu/attr.h>
+
+#include CPU_HEADER(i2s)
+
+struct I2sContext;
+struct I2s;
+
+typedef int (*i2s_write_t) (struct I2s *i2s, uint32_t sample);
+typedef uint32_t (*i2s_read_t) (struct I2s *i2s);
+typedef void (*i2s_dma_tx_buf_t) (struct I2s *i2s, void *buf, size_t len);
+typedef void (*i2s_dma_rx_buf_t) (struct I2s *i2s, void *buf, size_t len);
+typedef bool (*i2s_dma_tx_is_finished_t) (struct I2s *i2s);
+typedef bool (*i2s_dma_rx_is_finished_t) (struct I2s *i2s);
+typedef void (*i2s_dma_callback_t) (struct I2s *i2s, void *_buf, size_t len);
+typedef void (*i2s_dma_start_streaming_t) (struct I2s *i2s, void *buf, size_t len, size_t slice_len);
+typedef void (*i2s_dma_wait_t) (struct I2s *i2s);
+typedef void (*i2s_dma_stop_t) (struct I2s *i2s);
+
+typedef struct I2sContext
+{
+       i2s_write_t                write;
+       i2s_dma_tx_buf_t           tx_buf;
+       i2s_dma_tx_is_finished_t   tx_isFinish;
+       i2s_dma_callback_t         tx_callback;
+       i2s_dma_start_streaming_t  tx_start;
+       i2s_dma_wait_t             tx_wait;
+       i2s_dma_stop_t             tx_stop;
+       size_t tx_slice_len;
+
+       i2s_read_t                 read;
+       i2s_dma_rx_buf_t           rx_buf;
+       i2s_dma_rx_is_finished_t   rx_isFinish;
+       i2s_dma_callback_t         rx_callback;
+       i2s_dma_start_streaming_t  rx_start;
+       i2s_dma_wait_t             rx_wait;
+       i2s_dma_stop_t             rx_stop;
+       size_t rx_slice_len;
+
+       DB(id_t _type);
+
+} I2sContext;
+
+typedef struct I2s
+{
+       I2sContext ctx;
+       struct I2sHardware *hw;
+} I2s;
+
+INLINE int i2s_write(I2s *i2s, uint32_t sample)
+{
+       ASSERT(i2s->ctx.write);
+       return i2s->ctx.write(i2s, sample);
+}
+
+
+INLINE uint32_t i2s_read(I2s *i2s)
+{
+       ASSERT(i2s->ctx.read);
+       return i2s->ctx.read(i2s);
+}
+
+/*
+ * Check if a dma transfer is finished.
+ *
+ * Useful for kernel-less applications.
+ */
+INLINE bool i2s_dmaTxIsFinished(I2s *i2s)
+{
+       ASSERT(i2s->ctx.tx_isFinish);
+       return i2s->ctx.tx_isFinish(i2s);
+}
+
+INLINE bool i2s_dmaRxIsFinished(I2s *i2s)
+{
+       ASSERT(i2s->ctx.rx_isFinish);
+       return i2s->ctx.rx_isFinish(i2s);
+}
+
+INLINE void i2s_dmaTxBuffer(I2s *i2s, void *buf, size_t len)
+{
+       ASSERT(i2s->ctx.tx_buf);
+       i2s->ctx.tx_buf(i2s, buf, len);
+}
+
+INLINE void i2s_dmaRxBuffer(I2s *i2s, void *buf, size_t len)
+{
+       ASSERT(i2s->ctx.rx_buf);
+       i2s->ctx.rx_buf(i2s, buf, len);
+}
+
+
+INLINE void i2s_dmaTxWait(I2s *i2s)
+{
+       ASSERT(i2s->ctx.tx_wait);
+       i2s->ctx.tx_wait(i2s);
+}
+
+
+INLINE void i2s_dmaStartTxStreaming(I2s *i2s, void *buf, size_t len, size_t slice_len, i2s_dma_callback_t callback)
+{
+       ASSERT(i2s->ctx.tx_start);
+       ASSERT(len % slice_len == 0);
+       ASSERT(callback);
+
+       i2s->ctx.tx_callback = callback;
+       i2s->ctx.tx_slice_len = slice_len;
+       i2s->ctx.tx_start(i2s, buf, len, slice_len);
+}
 
-#define CONFIG_PLAY_BUF_LEN 16
-#define I2S_FIRST_BUF  1
-#define I2S_SECOND_BUF 2
+INLINE void i2s_dmaTxStop(I2s *i2s)
+{
+       ASSERT(i2s->ctx.tx_stop);
+       i2s->ctx.tx_stop(i2s);
+}
 
-void i2s_init(void);
+INLINE void i2s_dmaStartRxStreaming(I2s *i2s, void *buf, size_t len, size_t slice_len, i2s_dma_callback_t callback)
+{
+       ASSERT(i2s->ctx.rx_start);
+       ASSERT(len % slice_len == 0);
+       ASSERT(callback);
 
-/* Low level call that returns one of the two buffers or NULL if none is available */
-uint8_t *i2s_getBuffer(unsigned buf_num);
+       i2s->ctx.rx_callback = callback;
+       i2s->ctx.rx_slice_len = slice_len;
+       i2s->ctx.rx_start(i2s, buf, len, slice_len);
+}
 
-/* Returns a buffer that will be played after the current one. Blocking call */
-uint8_t *i2s_getFreeBuffer(void);
+INLINE void i2s_dmaRxStop(I2s *i2s)
+{
+       ASSERT(i2s->ctx.rx_stop);
+       i2s->ctx.rx_stop(i2s);
+}
 
-/* Starts playing from I2S_FIRST_BUFFER. You must have filled both buffers before calling this
- * function. Does nothing if already playing. */
-bool i2s_start(void);
+void i2s_init(I2s *i2s, int channel);
 
-#endif /* I2S_H */
+/** \} */ //defgroup i2s
+#endif /* DRV_I2S_H */