# K230 FFT API Reference

## Overview

The current user-mode access interface to FFT hardware in the SDK has been adjusted to RT-Smart HAL encapsulation, and the public header file is `drv_fft.h`.

The characteristics of the current interface are as follows:

- Open the `/dev/fft` device via `drv_fft_open()` and get the instance handle.
- `drv_fft_open()` will apply for an input/output MMZ buffer in advance, which can cover a maximum of 4096 point scenes by default.
- Perform FFT calculation via `drv_fft_run()` or `drv_fft_fft()` / `drv_fft_ifft()`.
- HAL is internally responsible for MMZ buffer application, cache synchronization and ioctl calls. The application layer only needs to provide input and output arrays.
- Support querying and adjusting HAL internal DMA/MMZ buffer size.
- Supports 64, 128, 256, 512, 1024, 2048, 4096 points.
- The input and output data are all in `short` (`int16_t`) format.
- Supports three input formats `RIRI`, `RRRR`, and `RR_II`, and two output formats `RIRI_OUT` and `RR_II_OUT`.

## Header files and links

- Header File: `drv_fft.h`
- The FFT HAL library is usually introduced through `librtsmart_hal.mk` in the sample project

## API list

- [drv_fft_open](#drv_fft_open)
- [drv_fft_close](#drv_fft_close)
- [drv_fft_set_input_alloc_size](#drv_fft_set_input_alloc_size)
- [drv_fft_set_output_alloc_size](#drv_fft_set_output_alloc_size)
- [drv_fft_get_input_alloc_size](#drv_fft_get_input_alloc_size)
- [drv_fft_get_output_alloc_size](#drv_fft_get_output_alloc_size)
- [drv_fft_run](#drv_fft_run)
- [drv_fft_fft](#drv_fft_fft)
- [drv_fft_ifft](#drv_fft_ifft)

## Function description

### drv_fft_open

Description

Open the FFT device and create a HAL instance.

Syntax

```c
int drv_fft_open(drv_fft_inst_t **inst);
```

Parameters

| Parameter Name | Description | Input/Output |
| -------- | ---- | --------- |
| inst | Returns FFT instance handle | Output |

Return Value

| Return Value | Description |
| ------ | ---- |
| 0 | Success |
| negative number | On failure, a negative errno style error code is returned. |

Notes

- After success, the pairing must be called `drv_fft_close()` to release.
- If `/dev/fft` does not exist or the driver is not initialized, the opening will fail.
- The current implementation will pre-apply for input/output MMZ buffers during the opening phase, and the default sizes are the capacity required for the largest FFT scenario.

### drv_fft_close

Description

Close the FFT device and release the instance.

Syntax

```c
void drv_fft_close(drv_fft_inst_t **inst);
```

Parameters

| Parameter Name | Description | Input/Output |
| -------- | ---- | --------- |
| inst | Address of the FFT instance handle to close | Input/Output |

Notes

- When `NULL` or `*inst == NULL` is passed in, the function returns directly.
- After the call is successful, `*inst` will be set to `NULL`.
- `drv_fft_close()` also releases the internal MMZ input/output buffer.

### drv_fft_set_input_alloc_size

Description

Adjust FFT HAL internal input MMZ buffer size.

Syntax

```c
int drv_fft_set_input_alloc_size(drv_fft_inst_t *inst, uint32_t size);
```

Parameters

| Parameter Name | Description | Input/Output |
| -------- | ---- | --------- |
| inst | FFT instance handle | Input |
| size | New number of input buffer bytes | Input |

Return Value

| Return Value | Description |
| ------ | ---- |
| 0 | Success |
| negative number | On failure, a negative errno style error code is returned. |

Notes

- If the current size is already equal to `size`, the function will directly return success.
- If the adjustment is successful, the old MMZ buffer is released and replaced with the new buffer.

### drv_fft_set_output_alloc_size

Description

Adjust FFT HAL internal output MMZ buffer size.

Syntax

```c
int drv_fft_set_output_alloc_size(drv_fft_inst_t *inst, uint32_t size);
```

Parameters

| Parameter Name | Description | Input/Output |
| -------- | ---- | --------- |
| inst | FFT instance handle | Input |
| size | New output buffer bytes | Input |

Return Value

| Return Value | Description |
| ------ | ---- |
| 0 | Success |
| negative number | On failure, a negative errno style error code is returned. |

### drv_fft_get_input_alloc_size

Description

Get the current input MMZ buffer size.

Syntax

```c
uint32_t drv_fft_get_input_alloc_size(const drv_fft_inst_t *inst);
```

### drv_fft_get_output_alloc_size

Description

Get the current output MMZ buffer size.

Syntax

```c
uint32_t drv_fft_get_output_alloc_size(const drv_fft_inst_t *inst);
```

Description

- When `inst == NULL`, the above query interface returns `0`.
- When turned on by default, both input and output buffers are pre-allocated.

### drv_fft_run

Description

Directly perform an FFT or IFFT in the mode specified in `drv_fft_cfg_t`.

Syntax

```c
int drv_fft_run(drv_fft_inst_t *inst, const drv_fft_cfg_t *cfg,
                const short *in_real, const short *in_imag,
                short *out_real, short *out_imag);
```

Parameters

| Parameter Name | Description | Input/Output |
| -------- | ---- | --------- |
| inst | FFT instance handle | Input |
| cfg | FFT configuration structure, see [drv_fft_cfg_t](#drv_fft_cfg_t) | Input |
| in_real | Input real part array with length `cfg->point` | Input |
| in_imag | Input the imaginary part array, the length is `cfg->point`; when `input_mode == RRRR`, it can be `NULL` | Input |
| out_real | Output the real part array with length `cfg->point` | Output |
| out_imag | Output the imaginary part array with length `cfg->point` | Output |

Return Value

| Return Value | Description |
| ------ | ---- |
| 0 | Success |
| negative number | On failure, a negative errno style error code is returned. |

Notes

- `cfg->point` only supports `64/128/256/512/1024/2048/4096`.
- `cfg->mode` determines whether to perform FFT or IFFT.
- `timeout_ms` Writing `0` means disabling FFT timeout reporting; the current example uses `0` by default.
- If the number of input/output bytes required for this run exceeds the current internal buffer size, `-ENOMEM` will be returned.
- In `RRRR` input mode, `in_imag` can be `NULL`.

### drv_fft_fft

Description

Perform FFT. This interface will ignore the `cfg->mode` passed by the caller and is forced to set to `FFT_MODE` internally.

Syntax

```c
int drv_fft_fft(drv_fft_inst_t *inst, const drv_fft_cfg_t *cfg,
                const short *in_real, const short *in_imag,
                short *out_real, short *out_imag);
```

Parameters

Same as [drv_fft_run](#drv_fft_run).

### drv_fft_ifft

Description

Perform IFFT. This interface will ignore the `cfg->mode` passed by the caller and is forced to set to `IFFT_MODE` internally.

Syntax

```c
int drv_fft_ifft(drv_fft_inst_t *inst, const drv_fft_cfg_t *cfg,
                 const short *in_real, const short *in_imag,
                 short *out_real, short *out_imag);
```

Parameters

Same as [drv_fft_run](#drv_fft_run).

## data type

### drv_fft_inst_t

Description

FFT HAL handle type, opaque structure, only used through pointers.

### drv_fft_cfg_t

Description

FFT run configuration.

definition

```c
typedef struct {
    uint32_t           point;
    k_fft_mode_e       mode;
    k_fft_input_mode_e input_mode;
    k_fft_out_mode_e   output_mode;
    uint16_t           shift;
    uint32_t           timeout_ms;
} drv_fft_cfg_t;
```

member

| member name | Description |
| -------- | ---- |
| point | FFT/IFFT points, supports the power of 2 of `64 ~ 4096` |
| mode | Operation mode, see [k_fft_mode_e](#k_fft_mode_e) |
| input_mode | Input format, see [k_fft_input_mode_e](#k_fft_input_mode_e) |
| output_mode | Output format, see [k_fft_out_mode_e](#k_fft_out_mode_e) |
| shift | Each level scaling control bit |
| timeout_ms | Timeout configuration, `0` means disabling timeout reporting |

### k_fft_mode_e

definition

```c
typedef enum {
    FFT_MODE = 0,
    IFFT_MODE,
} k_fft_mode_e;
```

### k_fft_input_mode_e

definition

```c
typedef enum {
    RIRI = 0,
    RRRR,
    RR_II,
} k_fft_input_mode_e;
```

Description

- `RIRI`: Inputs are sorted by `real0, imag0, real1, imag1...`
- `RRRR`: pure real input, only use `in_real`
- `RR_II`: All real parts first, then all imaginary parts

### k_fft_out_mode_e

definition

```c
typedef enum {
    RIRI_OUT = 0,
    RR_II_OUT,
} k_fft_out_mode_e;
```

Description

- `RIRI_OUT`: Output is returned in interleaved format
- `RR_II_OUT`: output split into `out_real[]` and `out_imag[]`

## Usage example

```c
#include <stdio.h>
#include <string.h>

#include "drv_fft.h"

int main(void)
{
    drv_fft_inst_t *inst = NULL;
    short in_real[512] = {0};
    short in_imag[512] = {0};
    short out_real[512] = {0};
    short out_imag[512] = {0};
    drv_fft_cfg_t cfg = {
        .point = 512,
        .mode = FFT_MODE,
        .input_mode = RIRI,
        .output_mode = RR_II_OUT,
        .shift = 0x555,
        .timeout_ms = 0,
    };

    if (drv_fft_open(&inst) != 0)
        return -1;

    printf("fft in alloc = %u, out alloc = %u\n",
           drv_fft_get_input_alloc_size(inst),
           drv_fft_get_output_alloc_size(inst));

    if (drv_fft_fft(inst, &cfg, in_real, in_imag, out_real, out_imag) != 0) {
        drv_fft_close(&inst);
        return -1;
    }

    drv_fft_close(&inst);
    return 0;
}
```

## Examples and related documentation

- FFT HAL regression example: `src/rtsmart/examples/peripheral/fft/test_fft.c`
- Audio spectrum display example: `src/rtsmart/examples/mpp/sample_fft_display/main.c`
- Peripheral sample document: [FFT Peripheral Example](../../app_develop_guide/peripheral/fft.md)
- Media sample document: [FFT spectrum display example](../../app_develop_guide/media/fft.md)

## Buffer size recommendations

- The default `drv_fft_open()` has pre-allocated buffers for a maximum 4096-point scene and usually does not require manual adjustment.
- If the subsequent HAL needs to run fixed-point FFT in a smaller memory usage scenario, the internal buffer can be reduced through `drv_fft_set_input_alloc_size()` / `drv_fft_set_output_alloc_size()`.
- If the buffer is manually reduced and an FFT is performed with a larger number of points or a larger input layout, `drv_fft_run()` will return `-ENOMEM`.
