This is an automated email from the ASF dual-hosted git repository.

jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git

commit d0e99540372d50b961f2b139937e566cef35d715
Author: Jerzy Kasenberg <[email protected]>
AuthorDate: Fri May 24 14:13:20 2024 +0200

    i2s: Add stream for i2s_out
    
    Code provides wrapper to use i2s with streaming API
    
    Signed-off-by: Jerzy Kasenberg <[email protected]>
---
 hw/drivers/i2s/include/i2s/i2s_stream.h | 46 ++++++++++++++++
 hw/drivers/i2s/src/i2s_stream.c         | 93 +++++++++++++++++++++++++++++++++
 2 files changed, 139 insertions(+)

diff --git a/hw/drivers/i2s/include/i2s/i2s_stream.h 
b/hw/drivers/i2s/include/i2s/i2s_stream.h
new file mode 100644
index 000000000..83849a1ab
--- /dev/null
+++ b/hw/drivers/i2s/include/i2s/i2s_stream.h
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _HW_DRIVERS_I2S_STREAM_H
+#define _HW_DRIVERS_I2S_STREAM_H
+
+#include <stdint.h>
+#include <i2s/i2s.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct i2s_out_stream {
+    struct out_stream ostream;
+    struct i2s *i2s;
+    struct i2s_sample_buffer *buffer;
+};
+
+#define I2S_OUT_STREAM_DEF(var) \
+    extern const struct out_stream_vft i2s_out_stream_vft; \
+    struct i2s_out_stream var = { \
+        OSTREAM_INIT(i2s_out_stream, ostream), \
+    };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _HW_DRIVERS_I2S_STREAM_H */
diff --git a/hw/drivers/i2s/src/i2s_stream.c b/hw/drivers/i2s/src/i2s_stream.c
new file mode 100644
index 000000000..93a4e8a13
--- /dev/null
+++ b/hw/drivers/i2s/src/i2s_stream.c
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+
+#include <os/util.h>
+#include <stream/stream.h>
+#include <i2s/i2s.h>
+#include <i2s/i2s_stream.h>
+
+OSTREAM_DEF(i2s_out_stream);
+
+static int
+i2s_out_stream_pump_from(struct out_stream *ostream, struct in_stream 
*istream, uint32_t count)
+{
+    struct i2s_out_stream *i2s_str = CONTAINER_OF(ostream, struct 
i2s_out_stream, ostream);
+    struct i2s_sample_buffer *buffer = i2s_str->buffer;
+    struct i2s *i2s = i2s_str->i2s;
+    int written = 0;
+    uint32_t available = istream_available(istream);
+    uint32_t sample_count;
+
+    if (available < count) {
+        count = available;
+    }
+    sample_count = count / i2s->sample_size_in_bytes;
+
+    while (sample_count) {
+        if (buffer == NULL) {
+            buffer = i2s_buffer_get(i2s, 0);
+            if (buffer == NULL) {
+                break;
+            }
+            buffer->sample_count = 0;
+        }
+        uint32_t space = buffer->capacity - buffer->sample_count;
+        size_t copied = min(space, sample_count);
+        if (copied) {
+            uint8_t *buf = buffer->sample_data;
+            istream_read(istream, buf + buffer->sample_count * 
i2s->sample_size_in_bytes,
+                         copied * i2s->sample_size_in_bytes);
+            buffer->sample_count += copied;
+            written += copied;
+            sample_count -= copied;
+        }
+        if (buffer->sample_count >= buffer->capacity) {
+            i2s_buffer_put(i2s, buffer);
+            buffer = NULL;
+        }
+    }
+    i2s_str->buffer = buffer;
+    return written * i2s_str->i2s->sample_size_in_bytes;
+}
+
+static int
+i2s_out_stream_write(struct out_stream *ostream, const uint8_t *buf, uint32_t 
count)
+{
+    struct mem_in_stream mstr;
+    mem_istream_init(&mstr, buf, count);
+
+    return i2s_out_stream_pump_from(ostream, (struct in_stream *)&mstr, count);
+}
+
+static int
+i2s_out_stream_flush(struct out_stream *ostream)
+{
+    struct i2s_out_stream *str = CONTAINER_OF(ostream, struct i2s_out_stream, 
ostream);
+    struct i2s *i2s = str->i2s;
+    struct i2s_sample_buffer *buffer = str->buffer;
+
+    str->buffer = NULL;
+    if (buffer) {
+        i2s_buffer_put(i2s, buffer);
+    }
+
+    return 0;
+}

Reply via email to