/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
/**
\defgroup SDS_Stream_Interface SDS Stream Interface
\brief sds.h: Synchronous Data Stream Interface for record (write) and playback (read) of SDS data streams via a SDSIO interface.
\details
The **SDS Interface** manages recording (write) and playback (read) of SDS data streams through the [SDSIO Interface](../sdsio.md#).
Data streams represent real-world I/O data for DSP and machine learning algorithms. 

The SDS system uses a dedicated worker thread (`sdsThread`) to handle data stream I/O asynchronously. User-facing APIs interact only
with internal circular buffers, allowing efficient, non-blocking data operations.

Each SDS stream is identified by a handle of type \ref sdsId_t, which is returned by the \ref sdsOpen function and is required
for all subsequent operations on that stream.

\b Thread \b Safety

The SDS Interface functions are **thread-safe** during normal operation:

- A single thread may read from or write to a specific data stream at a time.
- Multiple data streams can be used concurrently by separate threads without conflict.

While operational calls are thread-safe, **reuse of closed streams can lead to data corruption**:

- When a stream is closed via \ref sdsClose, its internal control block may be **reallocated** if another stream is opened.
- If a `read` or `write` operation is still pending on a handle after it has been closed, and a new stream is opened
that causes control block reuse, the pending operation may unexpectedly complete on the **newly opened stream**.

To prevent these issues:

- Avoid opening a new stream immediately after closing another unless you can guarantee that all references and asynchronous
operations related to the previous stream have completed or have been canceled.
@{
*/

/**
\defgroup SDS_Return_Codes Function Return Codes
\brief SDS Function Return Codes
\details The following values are returned by most SDS functions.
@{
\def SDS_OK
\def SDS_ERROR
\def SDS_ERROR_PARAMETER
\def SDS_ERROR_TIMEOUT
\def SDS_ERROR_IO
\def SDS_NO_SPACE
\def SDS_NO_DATA
\def SDS_EOS
@}
*/

/**
\defgroup SDS_Event_Codes Event Codes
\brief SDS Event Codes
\details The following values are passed as event value to the \ref sdsEvent_t callback function.
@{
\def SDS_EVENT_ERROR_IO
\def SDS_EVENT_NO_SPACE
\def SDS_EVENT_NO_DATA
@}
*/

/**
\defgroup SDS_Flag_Masks sdsFlags Bitmasks
\brief SDS Flag Bitmasks
\details The following values are used by function \ref sdsFlagsModify and global variable \ref sdsFlags.
@{
\def SDS_FLAG_START
\def SDS_FLAG_TERMINATE
\def SDS_FLAG_PLAYBACK
\def SDS_FLAG_ALIVE
\def SDS_FLAG_RESET
@}
*/

/**
\defgroup SDS_State_Codes sdsState Codes
\brief SDS State Codes
\details The following values are used by global variable \ref sdsState.
@{
\def SDS_STATE_INACTIVE
\def SDS_STATE_CONNECTED
\def SDS_STATE_START
\def SDS_STATE_ACTIVE
\def SDS_STATE_STOP_REQ
\def SDS_STATE_STOP_DONE
\def SDS_STATE_END
\def SDS_STATE_RESET
\def SDS_STATE_TERMINATE
@}
*/

/**
\typedef sdsId_t
\brief Handle to SDS stream
\details
This *pointer* defines the handle to an SDS stream. It is used to identify a data stream across the different functions for
the SDS system.
*/

/**
\typedef sdsMode_t
\brief SDS stream open mode
\details
This *enum* identifies the opening mode of an SDS stream: read or write.
It is a parameter of the \ref sdsOpen function.
*/

/**
\typedef sdsEvent_t
\details
This callback function is registered by passing a pointer to it as a parameter to the \ref sdsInit function.
It is triggered when an event such as insufficient data or space, or an error, occurs during the stream operation.
*/

/**
\var sdsFlags
\brief Configuration options and control information
\details
The sdsFlags variable stores configuration and diagnostic information in a single 32-bit word. This global variable can be directly read by the SDS application.
To update the value from the SDS application use the function \ref sdsFlagsModify.

The highest 8 bits are reserved for SDS control (see \ref SDS_Flag_Masks), and the lower 24 bits are available to the user.
User bits can be used to configure algorithms in A/B tests (e.g., bypassing a filter) and to report status information to the SDSIO-Server.

The SDSIO-Server running on a host computer receives the sdsFlags value periodically (see \ref sdsExchange).
The SDSIO-Server can also update the sdsFlags variable, for example to start recording or configure algorithms.
*/

/**
\var sdsState
\brief State information
\details
This *global variable* contains current state code (see \ref SDS_State_Codes) of the firmware application.

This information is not relayed to the host; it is available only in the firmware.
*/

/**
\typedef sdsError
\brief Error information
\details
This *global structure* stores SDS diagnostic information, including status code, source file, line number,
and an occurrence flag.

This information is relayed to the host in real time as it occurs (see \ref sdsExchange).
*/

/**
\typedef sdsIdleRate
\brief Idle rate information
\details
This *global variable* stores the current idle rate as a percentage. The value 0xFFFFFFFF indicates an unknown value
when idle time measurement is not available.

This information is relayed to the host in real time periodically (see \ref sdsExchange).
*/

/**
\fn          int32_t sdsInit (sdsEvent_t event_cb)
\details
\b Description:

Initializes the SDS system. This function allocates resources, initializes underlying
SDSIO interface, and creates the `sdsThread` worker thread. An optional callback function can be
registered to receive notifications (e.g., I/O errors).  This function must be called once before opening
SDS streams.
*/

/**
\fn          int32_t sdsUninit (void)
\details
\b Description:

De-initializes the SDS system. This function terminates the `sdsThread` worker thread,
and releases the internal resources. All open SDS streams must be closed by the user before calling this function.
After de-initialization, the system must be re-initialized before further use.
*/

/**
\fn          sdsId_t sdsOpen (const char *name, sdsMode_t mode, void *buf, uint32_t buf_size)
\details
\b Description:

Opens an SDS stream for reading or writing timeslot information and data blocks to or from the SDS file. The `buf` parameter specifies
a user-allocated memory region that serves as an internal circular buffer. The buffer must be large enough
to hold at least the largest expected data block plus 8 bytes for header information.

To open a stream in **write mode** (for recording):

- The `name` parameter defines the base name for the SDS output file and is used to construct the full filename in the
  format `name.index.sds`. The `index` is an auto-incrementing value that ensures a unique filename is generated.
  If a file with the generated name already exists, the `index` is incremented until an unused name is found.

To open a stream in **read mode** (for playback):

- The `name` parameter specifies the base name of the SDS input file.
  When SDSIO uses a file system, the function attempts to locate and open the file in the format
  `name.index.sds`, where `index` is an auto-incrementing value. If no matching file is found, the function returns an error.
  When SDSIO uses an SDSIO-Client in conjunction with the SDSIO-Server, the filename is constructed by the SDSIO-Server
  according to the configuration specified in the `sdsio.yml` steering file.

For details, refer to [Filenames section](../theory.md#filenames).

This function returns a handle that uniquely identifies the stream. The handle is used as a reference in
subsequent function calls to perform operations on the stream.
*/

/**
\fn          int32_t sdsClose (sdsId_t id)
\details
\b Description:

Closes an SDS stream and releases any internal resources associated with the stream handle.

For closing a stream used in **write mode**:

- Prior to closing, any remaining data in the internal circular buffer is flushed to the SDS file.
  The function blocks until all data transfers are complete or a timeout occurs.

For closing a stream used in **read mode**:

- The function waits for all pending data transfers to complete or until a timeout occurs.

Upon successful closure, the stream handle becomes invalid.
*/

/**
\fn          int32_t sdsWrite (sdsId_t id, uint32_t timeslot, const void *buf, uint32_t buf_size)
\details
\b Description:

Writes a data block, including a header containing the timeslot information and data block size, to the internal circular buffer.

The `sdsThread` worker thread asynchronously writes the data to the SDS file via the underlying SDSIO interface.
For an explanation of how the SDS system selects and names the target SDS file, refer to [Filenames section](../theory.md#filenames).
This asynchronous design enables efficient, non-blocking data handling and optimized performance.

Before attempting to write, the function verifies that the entire header and the complete data block, provided via the buffer
pointer `buf` and its size `buf_size`, can fit within the available space in the internal SDS circular buffer.
If insufficient space is available, the operation is aborted and the function returns \ref SDS_NO_SPACE.

On success, the function writes the header and data block to the SDS circular buffer and returns the number of data bytes written,
excluding the header.

Thread safety is ensured by allowing only a single thread to write to a given stream at a time.
However, multiple threads can concurrently write to different streams, enabling parallel operations across multiple streams.
*/

/**
\fn          int32_t sdsRead (sdsId_t id, uint32_t *timeslot, void *buf, uint32_t buf_size)
\details
\b Description:

Reads a data block along with its associated timeslot from the internal SDS circular buffer.

The `sdsThread` worker thread asynchronously reads the data from the SDS file using the underlying SDSIO interface.
For details on how the specific SDS file is selected, refer to  [Filenames section](../theory.md#filenames).
The retrieved data is then written to the internal SDS circular buffer. This asynchronous design enables efficient,
non-blocking data handling and ensures optimal performance.

Before attempting to read, the function verifies that the entire header and the complete data block specified by the header
are both present in the SDS circular buffer. If either the header is incomplete or the corresponding data block is not yet fully
available, the function aborts and returns \ref SDS_NO_DATA.

The function verifies that the user-provided buffer `buf`, with size `buf_size`, is large enough to accommodate the entire
data block. If it is too small, the function aborts and returns \ref SDS_ERROR_PARAMETER.

If the end of the stream has been reached and no further data is available, the function returns \ref SDS_EOS.

On success, the function reads the data block from the circular buffer, stores it in the user-provided buffer, and returns
the size of the data block in bytes. The associated timeslot is returned via the output parameter `timeslot`.

Thread safety is ensured by allowing only a single thread to read from a given stream at a time.
However, multiple threads can concurrently read from different streams, enabling parallel operations across multiple streams.
*/

/**
\fn          int32_t sdsGetSize (sdsId_t id)
\details
\b Description:

The function verifies that the entire header and the complete data block specified by the header are both present in the SDS circular buffer.
It returns the size, in bytes, of the next available data block in the stream. If either the header is incomplete or the corresponding
data block is not yet fully available, the function returns \ref  SDS_NO_DATA. If the end of the stream has been reached and no further
data is available, the function returns \ref SDS_EOS.
*/

/**
\fn          int32_t sdsExchange (void)
\details
\b Description:

Exchanges SDS control information with the host.
Updates \ref sdsFlags if requested by the host, and sends the current sdsFlags
value along with \ref sdsIdleRate and optional error information \ref sdsError to the host.
*/

/**
\fn          void sdsFlagsModify (uint32_t set_mask, uint32_t clear_mask)
\details
\b Description:

Atomically sets and clears bits in the global `sdsFlags` control flags.
Bits present in `set_mask` are set and bits present in `clear_mask` are cleared in the update, applied in that order.
*/


/**
@}
*/
// end group SDS_Stream_Interface


/*=======0=========1=========2=========3=========4=========5=========6=========7=========8=========9=========0=========1====*/
/**
\defgroup SDSIO_Interface SDSIO Interface
\brief sdsio.h: Input/Output Interface for SDS data streams.
\details
The SDSIO interface provides a generic mechanism for reading from and writing to `SDS files` using different SDSIO implementations.

An SDSIO can operate over:

- A local file system, such as an SD card, where files are accessed directly.
- A communication channel such as Ethernet, USB, or UART, where access to files is performed remotely via an SDSIO-Server.

When using a communication channel, the embedded device runs an SDSIO-Client, which communicates with the SDSIO-Server
running on the host machine. This interaction is command-based (e.g., `SDSIO_CMD_OPEN`, `SDSIO_CMD_READ`, `SDSIO_CMD_WRITE`) and enables
the embedded system to remotely open, read, write, and close files located on the host. For more details, refer to
[SDSIO-Server Firmware Protocol](../theory.md#sdsio-server-firmware-protocol).

The interface is lightweight and backend-agnostic, making it suitable for embedded data logging, host-interactive tools,
or as a transport layer for higher-level components.

@{
*/

/**
\typedef sdsioId_t
\brief Handle to SDSIO data stream
\details
This *pointer* defines the handle to SDSIO data stream. It is used to identify a data stream across the different functions.
*/

/**
\typedef sdsioMode_t
\brief SDSIO stream open mode
\details
This *enum* identifies the opening mode of an SDSIO stream: read or write.
It is a parameter of the \ref sdsioOpen function.
*/

/**
\fn          int32_t sdsioInit (void)
\details
\b Description:

Initializes the SDSIO interface. The interface may be a local file system, for example an SD card,
or a communication channel such as Ethernet, USB or UART. In the case of a communication channel,
the SDSIO-Client is used to interact with the SDSIO-Server running on a host machine.
The initialization process includes setting up the communication interface and verifying that
the SDSIO-Server is active on the host.
*/

/**
\fn          int32_t sdsioUninit (void)
\details
\b Description:

De-initializes the SDSIO interface. If a communication channel such as Ethernet, USB or USART is used,
the corresponding communication interface is also de-initialized.
*/

/**
\fn          sdsioId_t sdsioOpen (const char *name, sdsioMode_t mode)
\details
\b Description:

Opens an SDSIO stream for reading or writing. If the interface is a local file system, the file is opened directly.
For communication channels such as Ethernet, USB or USART, the SDSIO-Client sends an open command (SDSIO_CMD_OPEN) to the SDSIO-Server to open
the file on the host system. The function returns the handle to the SDSIO stream; if the SDSIO stream could not be opened, it returns NULL.
*/

/**
\fn          int32_t sdsioClose (sdsioId_t id)
\details
\b Description:

Closes an SDSIO stream. If the interface is a local file system, the file is closed directly.
For communication channels such as Ethernet, USB or USART, the SDSIO-Client sends a close command (SDSIO_CMD_CLOSE)
to the SDSIO-Server to close the file on the host system.
*/

/**
\fn          int32_t sdsioWrite (sdsioId_t id, const void *buf, uint32_t buf_size)
\details
\b Description:

Attempts to write up to `buf_size` bytes from the memory pointed to `buf` to the SDSIO stream identified by `id`.
If the interface is a local file system, data is written directly to the file.
For communication channels such as Ethernet, USB or USART, the SDSIO-Client sends a write command (SDSIO_CMD_WRITE) along with the data to
the SDSIO-Server, which then writes the data to a file on the host system.

The function may return before all data has been written, depending on the available interface bandwidth, buffer capacity, or timeout behavior:

- If the write operation is successful, the function returns the number of bytes actually written. This value may be less than \a buf_size in case of partial write.
- If no data could be written before the operation times out, the function returns \ref SDS_ERROR_TIMEOUT.
- If an SDIO interface or protocol error occurs, the function returns \ref SDS_ERROR_IO.
*/

/**
\fn          int32_t sdsioRead (sdsioId_t id, void *buf, uint32_t buf_size)
\details
\b Description:

Attempts to read up to `buf_size` bytes of data from the SDSIO stream identified by `id` into the memory pointed to `buf`.
If the interface is a local file system, data is read directly from the file.
For communication channels such as Ethernet, USB or USART, the SDSIO-Client sends a read command (SDSIO_CMD_READ) to the SDSIO-Server, which reads
the file on the host system and returns the data to the SDSIO-Client.

The function attempts to read data and may block based on the behavior of the underlying interface and data availability. It returns under the following conditions:

- If data is available, the function reads up to `buf_size` bytes and returns the number of bytes actually read. This value may be less than `buf_size`.
- If no data becomes available before the timeout expires, the function returns \ref SDS_ERROR_TIMEOUT.
- If data is partially read but the timeout occurs before the full request is satisfied, the function returns the number of bytes read up to that point.
- If the end of the stream is reached and no more data remains, the function returns \ref SDS_EOS to indicate that the end of file has been reached and no additional data is available.
- If an SDSIO interface or protocol error occurs, the function returns \ref SDS_ERROR_IO.
*/


/**
@}
*/
// end group SDSIO_Client_Interface
