This commit is contained in:
Steven Dan
2025-12-11 09:43:42 +08:00
commit d8b2974133
1822 changed files with 280037 additions and 0 deletions

View File

@@ -0,0 +1,44 @@
// Copyright 2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef CMD_OFFSETS_H
#define CMD_OFFSETS_H
#include <stages/adsp_module.h>
#include <stddef.h>
#include "cmds.h"
%for name in cmd_map:
#include "${name}_config.h"
%endfor
typedef struct {
uint32_t cmd_id; // CmdID
uint32_t offset; // offset
uint32_t size; //size
}module_config_offsets_t;
%for name, data in cmd_map.items():
// Offset and size of fields in the ${name}_config_t structure
static module_config_offsets_t ${name}_config_offsets[] = {
%for field_name, field_data in data.items():
<% field_data["size"] = field_data["size"] if "size" in field_data else 1 %>\
{.cmd_id=CMD_${name.upper()}_${field_name.upper()}, .offset=offsetof(${name}_config_t, ${field_name}), .size=sizeof(${field_data["type"]}) * ${field_data["size"]}},
%endfor
};
%endfor
static module_config_offsets_t *ptr_module_offsets[] = {
%for name, data in cmd_map.items():
${name}_config_offsets,
%endfor
};
typedef enum
{
%for name in cmd_map:
e_dsp_stage_${name},
%endfor
num_dsp_stages
}all_dsp_stages_t;
#endif

View File

@@ -0,0 +1,17 @@
// Copyright 2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef CMDS_H
#define CMDS_H
%for name, data in cmd_map.items():
// ${name} module commands
<% cmd_id = 1 %>\
%for field_name, field_data in data.items():
#define CMD_${name.upper()}_${field_name.upper()} ${cmd_id}
<% cmd_id = cmd_id + 1 %>\
%endfor
#define NUM_CMDS_${name.upper()} ${len(data)} // Number of commands in the ${name} module
%endfor
#endif

View File

@@ -0,0 +1,47 @@
// Copyright 2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <stdio.h>
%for name in cmd_map:
#include "${name}_config.h"
%endfor
#if OFFSET_GEN
int main(int argc, char* argv[])
{
FILE *fp;
printf("argc = %d\n", argc);
if(argc == 2)
{
printf("argv = %s\n", argv[1]);
fp = fopen(argv[1], "w");
}
else
{
fp = fopen("cmd_offset_size.h", "w");
}
fprintf(fp, "#ifndef CMD_NUM_VALUES_H\n");
fprintf(fp, "#define CMD_NUM_VALUES_H\n\n");
// Number of values read or written as part of the command. Used in the host cmd_map.c file. Needs to be generated by running
// an application since the config yaml files might specified size in terms of #defines (for eg. FILTERS * NUM_COEFFS_PER_BIQUAD)
%for name, data in cmd_map.items():
%for field_name, field_data in data.items():
<%
if "size" in field_data:
size = field_data["size"]
elif field_data["type"] == "float_s32_t":
size = 2
else:
size = 1
%>\
fprintf(fp, "#define NUM_VALUES_${name.upper()}_${field_name.upper()} %u\n", ${size});
fprintf(fp, "\n");
%endfor
%endfor
fprintf(fp, "#endif\n");
fclose(fp);
return 0;
}
#endif

View File

@@ -0,0 +1,18 @@
// Copyright 2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include "cmd_num_values.h"
#include "cmds.h"
static cmd_t commands[] =
{
%for name, data in cmd_map.items():
%for field_name, field_data in data.items():
<%
field_data["size"] = field_data["size"] if "size" in field_data else 1
cmd_type = {'int32_t': 'TYPE_INT32', 'int16_t': 'TYPE_INT16', 'int8_t': 'TYPE_CHAR', 'uint8_t': 'TYPE_UINT8', 'float': 'TYPE_FLOAT', 'int': 'TYPE_INT32', 'uint32_t': 'TYPE_UINT32', 'float_s32_t': 'TYPE_INT32', 'int32_t*': 'TYPE_INT32'}
%>\
{0xff, "${name.upper()}_${field_name.upper()}", ${cmd_type[field_data["type"]]}, CMD_${name.upper()}_${field_name.upper()}, CMD_READ_WRITE, NUM_VALUES_${name.upper()}_${field_name.upper()}, "${field_data["help"].strip()}", false},
%endfor
%endfor
};

View File

@@ -0,0 +1,135 @@
.. _${title}_stages:
${"#"*(len(title) + 7)}
${title} Stages
${"#"*(len(title) + 7)}
${docstring}
% for cl in classes:
.. _${cl}_stage:
${"="*len(cl)}
${cl}
${"="*len(cl)}
.. autoclass:: audio_dsp.stages.${cl}
:noindex:
:members:
:inherited-members: Stage
<%
## Get the parameter type from the stage.set_parameters method
import importlib
import inspect
from typing import get_type_hints
import types
import audio_dsp
# Import the stage class
stages_mod = importlib.import_module('audio_dsp.stages')
stage_cls = getattr(stages_mod, cl)
# Get the set_parameters method
set_params = getattr(stage_cls, 'set_parameters')
# Get the type hints for the method
hints = get_type_hints(set_params)
# Assume the first argument after 'self' is the model class
params = inspect.signature(set_params).parameters
param_names = list(params.keys())
# Skip 'self', get the next parameter
param_name = param_names[1]
model_cls = hints.get(param_name)
if model_cls == audio_dsp.design.stage.StageParameterType:
# generic StageParameterType, so no specific model class
model_cls = []
elif type(model_cls) == types.UnionType:
# If it's a Union, there's multiple types
model_cls = list(model_cls.__args__)
else:
model_cls = [model_cls]
for i, cls in enumerate(model_cls):
# get the full class path
model_cls[i] = f"{cls.__module__}.{cls.__name__}"
%>
% for param_cls in model_cls:
.. autopydantic_model:: ${param_cls}
:noindex:
:members:
:inherited-members: StageParameters
% endfor ## for cls in model_cls
${cl} Control
${"="*len(cl)}========
% if class_data[cl]:
The following runtime command ids are available for the ${cl} Stage. For
details on reading and writing these commands, see the Run-Time Control User Guide.
<%
row_list = []
max_cmd = len("Command ID macro") + 2 # add 2 so the title doesn't ever get split in the PDF
max_pay = len("Payload length")
max_help = len("Description")
for field_name, field_data in class_data[cl].items():
import re
size_str = "*[" + str(field_data['size']) + "]" if "size" in field_data else ""
help_str = f'{field_data["help"].strip()}' if "help" in field_data else ""
if "rw_type" in field_data and field_data["rw_type"] == "CMD_READ_ONLY":
help_str += " This command is read only. When sending a write control command, it will be ignored."
safe_name = cl.replace("RMS", "Rms")
snake_name = re.sub(r'(?<!^)(?=[A-Z])', '_', safe_name).upper()
cmd_str = f"CMD_{snake_name}_{field_name.upper()}"
payload_str = f"``sizeof({field_data['type']}){size_str}``"
this_row = [cmd_str, payload_str, help_str]
row_list.append(this_row)
if len(cmd_str) > max_cmd:
max_cmd = len(cmd_str)
if len(payload_str) > max_pay:
max_pay = len(payload_str)
if len(help_str) > max_help:
max_help = len(help_str)
page_width = 74 # this is a guesstimate of number of chars in a page
cmd_width = int((max_cmd/page_width)*100)
pay_width = int(((max_pay - 5)/page_width)*100) # subtract ` chars and compensate for font (ish)
help_width = 100 - pay_width
%>
## do the printing, use ljust to pad to max size
.. table::
:widths: ${help_width}, ${pay_width}
% if len(row_list) > 6:
:class: longtable
%endif
${"="*max_help} ${"="*max_pay}
${"Control parameter".ljust(max_help)} ${"Payload length".ljust(max_pay)}
${"="*max_help} ${"="*max_pay}
% for row in row_list:
${row[0].ljust(max_help)} ${row[1].ljust(max_pay)}
% if "²" in row[2]: ## ljust in Mako ignores ², no idea why
${row[2].ljust(max_help + 1)} ${'\\'.ljust(max_pay)}
% else:
${row[2].ljust(max_help)} ${'\\'.ljust(max_pay)}
%endif ## "²" in row[2]:
% if row_list.index(row) < len(row_list) - 1:
## don't print a blank row at the end
|
${"-"*max_help}--${"-"*max_pay}
% endif ## row_list.index(row) < len(row_list) - 1
% endfor ## row in row_list
${"="*max_help} ${"="*max_pay}
% else: ## class_data[cl]
The ${cl} Stage has no runtime controllable parameters.
% endif ## class_data[cl]
% endfor ## cl in classes

View File

@@ -0,0 +1,46 @@
// Copyright 2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef ${name.upper()}_CONFIG_H
#define ${name.upper()}_CONFIG_H
%for i in includes:
#include <${i}>
%endfor
%for d in defines:
#define ${d} ${defines[d]}
%endfor
/**
* This structure allows for real time control of the ${name} stage.
* It should be passed to the ${name}_control function.
*/
typedef struct
{
%for field_name, field_data in data.items():
<%
attrib_str = f'{field_data["attribute"]} ' if "attribute" in field_data else ""
size_str = "[" + str(field_data['size']) + "]" if "size" in field_data else ""
help_str = f'{field_data["help"]} ' if "help" in field_data else ""
%>\
<%block filter="wrap_helpstr">
${help_str}
</%block>
${field_data["type"]} ${attrib_str}${field_name}${size_str};
%endfor
}${name}_config_t;
#endif
<%!
# This is a function to wrap long help descriptions
import textwrap
def wrap_helpstr(text):
line_len = 80
max_len = line_len - 4 - 4 - 3
if len(text) > line_len:
return " /**\n * " + '\n'.join(textwrap.wrap(text.strip(), line_len, subsequent_indent=' * ')).strip() + "\n */"
else:
return f" /** {text.strip()} */"
%>