Skip to content

Commit

Permalink
i2s: Add stream for i2s_out
Browse files Browse the repository at this point in the history
Code provides wrapper to use i2s with streaming API

Signed-off-by: Jerzy Kasenberg <[email protected]>
  • Loading branch information
kasjer committed Jun 10, 2024
1 parent 1ac7f5e commit d0e9954
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 0 deletions.
46 changes: 46 additions & 0 deletions hw/drivers/i2s/include/i2s/i2s_stream.h
Original file line number Diff line number Diff line change
@@ -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 */
93 changes: 93 additions & 0 deletions hw/drivers/i2s/src/i2s_stream.c
Original file line number Diff line number Diff line change
@@ -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;
}

0 comments on commit d0e9954

Please sign in to comment.