This commit is contained in:
Dan-guanghua
2025-12-15 12:05:06 +08:00
parent 749e9926e5
commit 90c69ea943
18 changed files with 9373 additions and 866 deletions

View File

@@ -1,175 +1,175 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "ccc61334-38ac-4c86-a86a-bd2975d5a60d",
"metadata": {},
"source": [
"# lib_audio_dsp pipeline designer\n",
"\n",
"In this file you can generate the DSP pipeline of your choice.\n",
"\n",
"Below you will find 3 cells which can be modified and executed to configure, tune and run the desired pipeline.\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "0acbc09d",
"metadata": {},
"source": [
"1. This is the pipeline design cell. Here you must break the DSP pipeline down into threads and use the provided DSP stages to create a pipeline. Running this cell will produce a diagram showing your pipeline. Make sure to capture each stage in your pipeline as a variable, as it will be needed in the next step.\n",
"Note that every time the pipeline cell is changed, the app must be regenerated before the tuning stage can work correctly as the stage indices used for communication may have changed."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3806bd0-99e0-42b6-a084-e9a2f17ba7dc",
"metadata": {},
"outputs": [],
"source": [
"# Pipeline design stage\n",
"\n",
"from audio_dsp.design.pipeline import Pipeline\n",
"from audio_dsp.stages import *\n",
"\n",
"p, inputs = Pipeline.begin(2, fs=48000)\n",
"\n",
"# inputs is a list of pipeline inputs. \"input gain\" is a label for this instance of VolumeControl.\n",
"# The new variable x is the output of the input gain VolumeContro and has two elements.\n",
"x = p.stage(VolumeControl, inputs, \"input_gain\")\n",
"\n",
"# Pass the output of the input gain stage to a low-pass filter.\n",
"# The variable x is reassigned as the outputs of this filter.\n",
"x = p.stage(Biquad, x, \"low_pass\")\n",
"\n",
"# Pass the output of the low-pass filter to a high pass filter.\n",
"# The variable x is reassigned as the outputs of this filter.\n",
"x = p.stage(Biquad, x, \"high_pass\")\n",
"\n",
"# Pass the output of the high-pass filter to a notch filter.\n",
"# The variable x is reassigned as the outputs of this filter.\n",
"x = p.stage(Biquad, x, \"notch\")\n",
"\n",
"# Pass the output of the notch filter to a low-shelf filter.\n",
"# The variable x is reassigned as the outputs of this filter.\n",
"x = p.stage(Biquad, x, \"low_shelf\")\n",
"\n",
"# Fork the output of the low-shelf filter.\n",
"# The variable x, which now contains four elements, is reassigned as the outputs of the fork stage.\n",
"x = p.stage(Fork, x, \"fork\")\n",
"\n",
"# Pass one pair of the outputs from the fork to a mixer.\n",
"# The new variable y holds the outputs from the new mixer.\n",
"y = p.stage(Mixer, x[0,2], \"mixer_1\")\n",
"\n",
"# Pass the other pair of the outputs from the fork to another mixer.\n",
"# The new variable z holds the outputs from the new mixer.\n",
"z = p.stage(Mixer, x[1,3], \"mixer_2\")\n",
"\n",
"# Pass the output of mixer 1 and mixer 2 to an output gain stage.\n",
"# The variable y is reassigned to the output of this gain stage.\n",
"y = p.stage(VolumeControl, y+z, \"output_gain\")\n",
"\n",
"# Connect output gain to the clipper.\n",
"y = p.stage(Clipper, y)\n",
"\n",
"# Finally connect to the output of the pipeline.\n",
"p.set_outputs(y)\n",
"\n",
"p.draw()\n"
]
},
{
"cell_type": "markdown",
"id": "27e9d385",
"metadata": {},
"source": [
"2. This is the tuning cell. First time through this can be ignored, but once your pipeline is running on a connected device, this cell can be updated and executed to update each pipeline stage live."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "89d245d6-b908-4815-ae22-fa10e40d65dc",
"metadata": {},
"outputs": [],
"source": [
"from audio_dsp.tuning import send_config_to_device, profile_pipeline\n",
"from audio_dsp.tuning.transport import XScopeTransport\n",
"from time import sleep\n",
"\n",
"# Make a low pass filter with a cut-off frequency of 20000 Hz and q of 0.707\n",
"p[\"low_pass\"].make_lowpass(20000, 0.707)\n",
"p[\"low_pass\"].plot_frequency_response(16000)\n",
"\n",
"# Make a high pass filter with a cut-off frequency of 20 Hz and q of 0.177\n",
"p[\"high_pass\"].make_highpass(20, 0.707)\n",
"p[\"high_pass\"].plot_frequency_response(16000)\n",
"\n",
"# Make a notch filter with a center frequency of 50 Hz and q of 0.707\n",
"p[\"notch\"].make_notch(50, 0.707)\n",
"p[\"notch\"].plot_frequency_response(16000)\n",
"\n",
"# Make a low-shelf filter with a center frequency of 130 Hz, a q of 0.707, and a boost of 6 dB\n",
"p[\"low_shelf\"].make_lowshelf(130, 0.707, 6.0)\n",
"p[\"low_shelf\"].plot_frequency_response(16000)"
]
},
{
"cell_type": "markdown",
"id": "2113ddc3",
"metadata": {},
"source": [
"3. This is the build and run cell. This stage generates an application which uses your pipeline. The tuning parameters set in the previous cell are baked in the application."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "32492495-d82a-45ba-87e3-80b01de38981",
"metadata": {},
"outputs": [],
"source": [
"# Build and run\n",
"from audio_dsp.design.pipeline import generate_dsp_main\n",
"from audio_dsp.design.build_utils import XCommonCMakeHelper\n",
"\n",
"b = XCommonCMakeHelper()\n",
"generate_dsp_main(p)\n",
"\n",
"b.configure_build_run()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a31cc9af-d81d-4862-bcc0-5f692ae38c44",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
{
"cells": [
{
"cell_type": "markdown",
"id": "ccc61334-38ac-4c86-a86a-bd2975d5a60d",
"metadata": {},
"source": [
"# lib_audio_dsp pipeline designer\n",
"\n",
"In this file you can generate the DSP pipeline of your choice.\n",
"\n",
"Below you will find 3 cells which can be modified and executed to configure, tune and run the desired pipeline.\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "0acbc09d",
"metadata": {},
"source": [
"1. This is the pipeline design cell. Here you must break the DSP pipeline down into threads and use the provided DSP stages to create a pipeline. Running this cell will produce a diagram showing your pipeline. Make sure to capture each stage in your pipeline as a variable, as it will be needed in the next step.\n",
"Note that every time the pipeline cell is changed, the app must be regenerated before the tuning stage can work correctly as the stage indices used for communication may have changed."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3806bd0-99e0-42b6-a084-e9a2f17ba7dc",
"metadata": {},
"outputs": [],
"source": [
"# Pipeline design stage\n",
"\n",
"from audio_dsp.design.pipeline import Pipeline\n",
"from audio_dsp.stages import *\n",
"\n",
"p, inputs = Pipeline.begin(2, fs=48000)\n",
"\n",
"# inputs is a list of pipeline inputs. \"input gain\" is a label for this instance of VolumeControl.\n",
"# The new variable x is the output of the input gain VolumeContro and has two elements.\n",
"x = p.stage(VolumeControl, inputs, \"input_gain\")\n",
"\n",
"# Pass the output of the input gain stage to a low-pass filter.\n",
"# The variable x is reassigned as the outputs of this filter.\n",
"x = p.stage(Biquad, x, \"low_pass\")\n",
"\n",
"# Pass the output of the low-pass filter to a high pass filter.\n",
"# The variable x is reassigned as the outputs of this filter.\n",
"x = p.stage(Biquad, x, \"high_pass\")\n",
"\n",
"# Pass the output of the high-pass filter to a notch filter.\n",
"# The variable x is reassigned as the outputs of this filter.\n",
"x = p.stage(Biquad, x, \"notch\")\n",
"\n",
"# Pass the output of the notch filter to a low-shelf filter.\n",
"# The variable x is reassigned as the outputs of this filter.\n",
"x = p.stage(Biquad, x, \"low_shelf\")\n",
"\n",
"# Fork the output of the low-shelf filter.\n",
"# The variable x, which now contains four elements, is reassigned as the outputs of the fork stage.\n",
"x = p.stage(Fork, x, \"fork\")\n",
"\n",
"# Pass one pair of the outputs from the fork to a mixer.\n",
"# The new variable y holds the outputs from the new mixer.\n",
"y = p.stage(Mixer, x[0,2], \"mixer_1\")\n",
"\n",
"# Pass the other pair of the outputs from the fork to another mixer.\n",
"# The new variable z holds the outputs from the new mixer.\n",
"z = p.stage(Mixer, x[1,3], \"mixer_2\")\n",
"\n",
"# Pass the output of mixer 1 and mixer 2 to an output gain stage.\n",
"# The variable y is reassigned to the output of this gain stage.\n",
"y = p.stage(VolumeControl, y+z, \"output_gain\")\n",
"\n",
"# Connect output gain to the clipper.\n",
"y = p.stage(Clipper, y)\n",
"\n",
"# Finally connect to the output of the pipeline.\n",
"p.set_outputs(y)\n",
"\n",
"p.draw()\n"
]
},
{
"cell_type": "markdown",
"id": "27e9d385",
"metadata": {},
"source": [
"2. This is the tuning cell. First time through this can be ignored, but once your pipeline is running on a connected device, this cell can be updated and executed to update each pipeline stage live."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "89d245d6-b908-4815-ae22-fa10e40d65dc",
"metadata": {},
"outputs": [],
"source": [
"from audio_dsp.tuning import send_config_to_device, profile_pipeline\n",
"from audio_dsp.tuning.transport import XScopeTransport\n",
"from time import sleep\n",
"\n",
"# Make a low pass filter with a cut-off frequency of 20000 Hz and q of 0.707\n",
"p[\"low_pass\"].make_lowpass(20000, 0.707)\n",
"p[\"low_pass\"].plot_frequency_response(16000)\n",
"\n",
"# Make a high pass filter with a cut-off frequency of 20 Hz and q of 0.177\n",
"p[\"high_pass\"].make_highpass(20, 0.707)\n",
"p[\"high_pass\"].plot_frequency_response(16000)\n",
"\n",
"# Make a notch filter with a center frequency of 50 Hz and q of 0.707\n",
"p[\"notch\"].make_notch(50, 0.707)\n",
"p[\"notch\"].plot_frequency_response(16000)\n",
"\n",
"# Make a low-shelf filter with a center frequency of 130 Hz, a q of 0.707, and a boost of 6 dB\n",
"p[\"low_shelf\"].make_lowshelf(130, 0.707, 6.0)\n",
"p[\"low_shelf\"].plot_frequency_response(16000)"
]
},
{
"cell_type": "markdown",
"id": "2113ddc3",
"metadata": {},
"source": [
"3. This is the build and run cell. This stage generates an application which uses your pipeline. The tuning parameters set in the previous cell are baked in the application."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "32492495-d82a-45ba-87e3-80b01de38981",
"metadata": {},
"outputs": [],
"source": [
"# Build and run\n",
"from audio_dsp.design.pipeline import generate_dsp_main\n",
"from audio_dsp.design.build_utils import XCommonCMakeHelper\n",
"\n",
"b = XCommonCMakeHelper()\n",
"generate_dsp_main(p)\n",
"\n",
"b.configure_build_run()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a31cc9af-d81d-4862-bcc0-5f692ae38c44",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,139 +1,139 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "ccc61334-38ac-4c86-a86a-bd2975d5a60d",
"metadata": {},
"source": [
"# lib_audio_dsp pipeline designer\n",
"\n",
"In this file you can generate the DSP pipeline of your choice.\n",
"\n",
"Below you will find 3 cells which can be modified and executed to configure, tune and run the desired pipeline.\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "0acbc09d",
"metadata": {},
"source": [
"1. This is the pipeline design cell. Here you must break the DSP pipeline down into threads and use the provided DSP stages to create a pipeline. Running this cell will produce a diagram showing your pipeline. Make sure to capture each stage in your pipeline as a variable, as it will be needed in the next step.\n",
"Note that every time the pipeline cell is changed, the app must be regenerated before the tuning stage can work correctly as the stage indices used for communication may have changed."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3806bd0-99e0-42b6-a084-e9a2f17ba7dc",
"metadata": {},
"outputs": [],
"source": [
"# Pipeline design stage\n",
"\n",
"from audio_dsp.design.pipeline import Pipeline\n",
"from audio_dsp.stages import *\n",
"\n",
"p, inputs = Pipeline.begin(2, fs=48000)\n",
"\n",
"# inputs is a list of pipeline inputs. \"input gain\" is a label for this instance of VolumeControl.\n",
"# The new variable x is the output of the input gain VolumeContro and has two elements.\n",
"x = p.stage(VolumeControl, inputs, \"input_gain\")\n",
"\n",
"# Fork the output of the input gain stage.\n",
"# The variable x, which now contains four elements, is reassigned as the outputs of the fork stage.\n",
"x = p.stage(Fork, x, \"fork\")\n",
"\n",
"# Pass one pair of the outputs from the fork to a mixer.\n",
"# The new variable y holds the outputs from the new mixer.\n",
"y = p.stage(Mixer, x[0,2], \"mixer_1\")\n",
"\n",
"# Pass the other pair of the outputs from the fork to another mixer.\n",
"# The new variable z holds the outputs from the new mixer.\n",
"z = p.stage(Mixer, x[1,3], \"mixer_2\")\n",
"\n",
"# Pass the output of mixer 1 and mixer 2 to an output gain stage.\n",
"# The variable y is reassigned to the output of this gain stage.\n",
"y = p.stage(VolumeControl, y+z, \"output_gain\")\n",
"\n",
"# Connect output gain to the clipper.\n",
"y = p.stage(Clipper, y)\n",
"\n",
"# Finally connect to the output of the pipeline.\n",
"p.set_outputs(y)\n",
"\n",
"p.draw()\n"
]
},
{
"cell_type": "markdown",
"id": "27e9d385",
"metadata": {},
"source": [
"2. This is the tuning cell. First time through this can be ignored, but once your pipeline is running on a connected device, this cell can be updated and executed to update each pipeline stage live."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "89d245d6-b908-4815-ae22-fa10e40d65dc",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "2113ddc3",
"metadata": {},
"source": [
"3. This is the build and run cell. This stage generates an application which uses your pipeline. The tuning parameters set in the previous cell are baked in the application."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "32492495-d82a-45ba-87e3-80b01de38981",
"metadata": {},
"outputs": [],
"source": [
"# Build and run\n",
"from audio_dsp.design.pipeline import generate_dsp_main\n",
"from audio_dsp.design.build_utils import XCommonCMakeHelper\n",
"\n",
"b = XCommonCMakeHelper()\n",
"generate_dsp_main(p)\n",
"\n",
"b.configure_build_run()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a31cc9af-d81d-4862-bcc0-5f692ae38c44",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
{
"cells": [
{
"cell_type": "markdown",
"id": "ccc61334-38ac-4c86-a86a-bd2975d5a60d",
"metadata": {},
"source": [
"# lib_audio_dsp pipeline designer\n",
"\n",
"In this file you can generate the DSP pipeline of your choice.\n",
"\n",
"Below you will find 3 cells which can be modified and executed to configure, tune and run the desired pipeline.\n",
"\n"
]
},
{
"cell_type": "markdown",
"id": "0acbc09d",
"metadata": {},
"source": [
"1. This is the pipeline design cell. Here you must break the DSP pipeline down into threads and use the provided DSP stages to create a pipeline. Running this cell will produce a diagram showing your pipeline. Make sure to capture each stage in your pipeline as a variable, as it will be needed in the next step.\n",
"Note that every time the pipeline cell is changed, the app must be regenerated before the tuning stage can work correctly as the stage indices used for communication may have changed."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f3806bd0-99e0-42b6-a084-e9a2f17ba7dc",
"metadata": {},
"outputs": [],
"source": [
"# Pipeline design stage\n",
"\n",
"from audio_dsp.design.pipeline import Pipeline\n",
"from audio_dsp.stages import *\n",
"\n",
"p, inputs = Pipeline.begin(2, fs=48000)\n",
"\n",
"# inputs is a list of pipeline inputs. \"input gain\" is a label for this instance of VolumeControl.\n",
"# The new variable x is the output of the input gain VolumeContro and has two elements.\n",
"x = p.stage(VolumeControl, inputs, \"input_gain\")\n",
"\n",
"# Fork the output of the input gain stage.\n",
"# The variable x, which now contains four elements, is reassigned as the outputs of the fork stage.\n",
"x = p.stage(Fork, x, \"fork\")\n",
"\n",
"# Pass one pair of the outputs from the fork to a mixer.\n",
"# The new variable y holds the outputs from the new mixer.\n",
"y = p.stage(Mixer, x[0,2], \"mixer_1\")\n",
"\n",
"# Pass the other pair of the outputs from the fork to another mixer.\n",
"# The new variable z holds the outputs from the new mixer.\n",
"z = p.stage(Mixer, x[1,3], \"mixer_2\")\n",
"\n",
"# Pass the output of mixer 1 and mixer 2 to an output gain stage.\n",
"# The variable y is reassigned to the output of this gain stage.\n",
"y = p.stage(VolumeControl, y+z, \"output_gain\")\n",
"\n",
"# Connect output gain to the clipper.\n",
"y = p.stage(Clipper, y)\n",
"\n",
"# Finally connect to the output of the pipeline.\n",
"p.set_outputs(y)\n",
"\n",
"p.draw()\n"
]
},
{
"cell_type": "markdown",
"id": "27e9d385",
"metadata": {},
"source": [
"2. This is the tuning cell. First time through this can be ignored, but once your pipeline is running on a connected device, this cell can be updated and executed to update each pipeline stage live."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "89d245d6-b908-4815-ae22-fa10e40d65dc",
"metadata": {},
"outputs": [],
"source": []
},
{
"cell_type": "markdown",
"id": "2113ddc3",
"metadata": {},
"source": [
"3. This is the build and run cell. This stage generates an application which uses your pipeline. The tuning parameters set in the previous cell are baked in the application."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "32492495-d82a-45ba-87e3-80b01de38981",
"metadata": {},
"outputs": [],
"source": [
"# Build and run\n",
"from audio_dsp.design.pipeline import generate_dsp_main\n",
"from audio_dsp.design.build_utils import XCommonCMakeHelper\n",
"\n",
"b = XCommonCMakeHelper()\n",
"generate_dsp_main(p)\n",
"\n",
"b.configure_build_run()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a31cc9af-d81d-4862-bcc0-5f692ae38c44",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.4"
}
},
"nbformat": 4,
"nbformat_minor": 5
}

View File

@@ -1,98 +1,98 @@
<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xmos.com http://www.xmos.com" ManuallySpecifiedRouting="true">
<Type>Board</Type>
<Name>XS2 MC Audio</Name>
<Declarations>
<Declaration>tileref tile[2]</Declaration>
<Declaration>tileref usb_tile</Declaration>
</Declarations>
<Packages>
<Package id="0" Type="XS2-UnA-512-FB236">
<Nodes>
<Node Id="0" InPackageId="0" Type="XS2-L16A-512" Oscillator="24MHz" SystemFrequency="500MHz" referencefrequency="100MHz">
<Boot>
<Source Location="SPI:bootFlash"/>
</Boot>
<Tile Number="0" Reference="tile[0]">
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
<!-- Audio Ports -->
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
<Port Location="XS1_PORT_1F" Name="PORT_MCLK_IN"/>
<Port Location="XS1_PORT_1G" Name="PORT_I2S_LRCLK"/>
<Port Location="XS1_PORT_1H" Name="PORT_I2S_BCLK"/>
<Port Location="XS1_PORT_1M" Name="PORT_I2S_DAC0"/>
<port Location="XS1_PORT_1N" Name="PORT_I2S_DAC1"/>
<port Location="XS1_PORT_1O" Name="PORT_I2S_DAC2"/>
<port Location="XS1_PORT_1P" Name="PORT_I2S_DAC3"/>
<Port Location="XS1_PORT_1I" Name="PORT_I2S_ADC0"/>
<Port Location="XS1_PORT_1J" Name="PORT_I2S_ADC1"/>
<Port Location="XS1_PORT_1K" Name="PORT_I2S_ADC2"/>
<Port Location="XS1_PORT_1L" Name="PORT_I2S_ADC3"/>
<Port Location="XS1_PORT_4A" Name="PORT_I2C"/>
<Port Location="XS1_PORT_1M" Name="PORT_DSD_DAC0"/>
<port Location="XS1_PORT_1N" Name="PORT_DSD_DAC1"/>
<Port Location="XS1_PORT_1G" Name="PORT_DSD_CLK"/>
<Port Location="XS1_PORT_1E" Name="PORT_ADAT_OUT"/>--> <!-- D: COAX E: OPT -->
<Port Location="XS1_PORT_1D" Name="PORT_SPDIF_OUT"/>--> <!-- D: COAX E: OPT -->
</Tile>
<Tile Number="1" Reference="tile[1]">
<Port Location="XS1_PORT_1H" Name="PORT_USB_TX_READYIN"/>
<Port Location="XS1_PORT_1J" Name="PORT_USB_CLK"/>
<Port Location="XS1_PORT_1K" Name="PORT_USB_TX_READYOUT"/>
<Port Location="XS1_PORT_1I" Name="PORT_USB_RX_READY"/>
<Port Location="XS1_PORT_1E" Name="PORT_USB_FLAG0"/>
<Port Location="XS1_PORT_1F" Name="PORT_USB_FLAG1"/>
<Port Location="XS1_PORT_1G" Name="PORT_USB_FLAG2"/>
<Port Location="XS1_PORT_8A" Name="PORT_USB_TXD"/>
<Port Location="XS1_PORT_8B" Name="PORT_USB_RXD"/>
<!-- Audio Ports -->
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
<Port Location="XS1_PORT_1L" Name="PORT_MCLK_IN2"/>
<Port Location="XS1_PORT_1M" Name="PORT_MIDI_IN"/>
<Port Location="XS1_PORT_1N" Name="PORT_MIDI_OUT"/>
<Port Location="XS1_PORT_1O" Name="PORT_ADAT_IN"/>--> <!-- P: COAX O: OPT -->
<Port Location="XS1_PORT_1P" Name="PORT_SPDIF_IN"/>--> <!-- P: COAX O: OPT -->
</Tile>
</Node>
<Node Id="1" InPackageId="1" Type="periph:XS1-SU" Reference="usb_tile" Oscillator="24MHz">
</Node>
</Nodes>
<Links>
<Link Encoding="5wire">
<LinkEndpoint NodeId="0" Link="8" Delays="52clk,52clk"/>
<LinkEndpoint NodeId="1" Link="XL0" Delays="1clk,1clk"/>
</Link>
</Links>
</Package>
</Packages>
<Nodes>
<Node Id="2" Type="device:" RoutingId="0x8000">
<Service Id="0" Proto="xscope_host_data(chanend c);">
<Chanend Identifier="c" end="3"/>
</Service>
</Node>
</Nodes>
<Links>
<Link Encoding="2wire" Delays="4,4" Flags="XSCOPE">
<LinkEndpoint NodeId="0" Link="XL0"/>
<LinkEndpoint NodeId="2" Chanend="1"/>
</Link>
</Links>
<ExternalDevices>
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="8192">
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
<Attribute Name="QE_REGISTER" Value="flash_qe_location_status_reg_1"/>
<Attribute Name="QE_BIT" Value="flash_qe_bit_1"/>
</Device>
</ExternalDevices>
<JTAGChain>
<JTAGDevice NodeId="0"/>
<JTAGDevice NodeId="1"/>
</JTAGChain>
</Network>
<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xmos.com http://www.xmos.com" ManuallySpecifiedRouting="true">
<Type>Board</Type>
<Name>XS2 MC Audio</Name>
<Declarations>
<Declaration>tileref tile[2]</Declaration>
<Declaration>tileref usb_tile</Declaration>
</Declarations>
<Packages>
<Package id="0" Type="XS2-UnA-512-FB236">
<Nodes>
<Node Id="0" InPackageId="0" Type="XS2-L16A-512" Oscillator="24MHz" SystemFrequency="500MHz" referencefrequency="100MHz">
<Boot>
<Source Location="SPI:bootFlash"/>
</Boot>
<Tile Number="0" Reference="tile[0]">
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
<!-- Audio Ports -->
<Port Location="XS1_PORT_1A" Name="PORT_PLL_REF"/>
<Port Location="XS1_PORT_1F" Name="PORT_MCLK_IN"/>
<Port Location="XS1_PORT_1G" Name="PORT_I2S_LRCLK"/>
<Port Location="XS1_PORT_1H" Name="PORT_I2S_BCLK"/>
<Port Location="XS1_PORT_1M" Name="PORT_I2S_DAC0"/>
<port Location="XS1_PORT_1N" Name="PORT_I2S_DAC1"/>
<port Location="XS1_PORT_1O" Name="PORT_I2S_DAC2"/>
<port Location="XS1_PORT_1P" Name="PORT_I2S_DAC3"/>
<Port Location="XS1_PORT_1I" Name="PORT_I2S_ADC0"/>
<Port Location="XS1_PORT_1J" Name="PORT_I2S_ADC1"/>
<Port Location="XS1_PORT_1K" Name="PORT_I2S_ADC2"/>
<Port Location="XS1_PORT_1L" Name="PORT_I2S_ADC3"/>
<Port Location="XS1_PORT_4A" Name="PORT_I2C"/>
<Port Location="XS1_PORT_1M" Name="PORT_DSD_DAC0"/>
<port Location="XS1_PORT_1N" Name="PORT_DSD_DAC1"/>
<Port Location="XS1_PORT_1G" Name="PORT_DSD_CLK"/>
<Port Location="XS1_PORT_1E" Name="PORT_ADAT_OUT"/>--> <!-- D: COAX E: OPT -->
<Port Location="XS1_PORT_1D" Name="PORT_SPDIF_OUT"/>--> <!-- D: COAX E: OPT -->
</Tile>
<Tile Number="1" Reference="tile[1]">
<Port Location="XS1_PORT_1H" Name="PORT_USB_TX_READYIN"/>
<Port Location="XS1_PORT_1J" Name="PORT_USB_CLK"/>
<Port Location="XS1_PORT_1K" Name="PORT_USB_TX_READYOUT"/>
<Port Location="XS1_PORT_1I" Name="PORT_USB_RX_READY"/>
<Port Location="XS1_PORT_1E" Name="PORT_USB_FLAG0"/>
<Port Location="XS1_PORT_1F" Name="PORT_USB_FLAG1"/>
<Port Location="XS1_PORT_1G" Name="PORT_USB_FLAG2"/>
<Port Location="XS1_PORT_8A" Name="PORT_USB_TXD"/>
<Port Location="XS1_PORT_8B" Name="PORT_USB_RXD"/>
<!-- Audio Ports -->
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
<Port Location="XS1_PORT_1L" Name="PORT_MCLK_IN2"/>
<Port Location="XS1_PORT_1M" Name="PORT_MIDI_IN"/>
<Port Location="XS1_PORT_1N" Name="PORT_MIDI_OUT"/>
<Port Location="XS1_PORT_1O" Name="PORT_ADAT_IN"/>--> <!-- P: COAX O: OPT -->
<Port Location="XS1_PORT_1P" Name="PORT_SPDIF_IN"/>--> <!-- P: COAX O: OPT -->
</Tile>
</Node>
<Node Id="1" InPackageId="1" Type="periph:XS1-SU" Reference="usb_tile" Oscillator="24MHz">
</Node>
</Nodes>
<Links>
<Link Encoding="5wire">
<LinkEndpoint NodeId="0" Link="8" Delays="52clk,52clk"/>
<LinkEndpoint NodeId="1" Link="XL0" Delays="1clk,1clk"/>
</Link>
</Links>
</Package>
</Packages>
<Nodes>
<Node Id="2" Type="device:" RoutingId="0x8000">
<Service Id="0" Proto="xscope_host_data(chanend c);">
<Chanend Identifier="c" end="3"/>
</Service>
</Node>
</Nodes>
<Links>
<Link Encoding="2wire" Delays="4,4" Flags="XSCOPE">
<LinkEndpoint NodeId="0" Link="XL0"/>
<LinkEndpoint NodeId="2" Chanend="1"/>
</Link>
</Links>
<ExternalDevices>
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="8192">
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
<Attribute Name="QE_REGISTER" Value="flash_qe_location_status_reg_1"/>
<Attribute Name="QE_BIT" Value="flash_qe_bit_1"/>
</Device>
</ExternalDevices>
<JTAGChain>
<JTAGDevice NodeId="0"/>
<JTAGDevice NodeId="1"/>
</JTAGChain>
</Network>

View File

@@ -1,120 +1,120 @@
// Copyright 2016-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
.section .dp.data,"awd",@progbits
.text
#if (defined(__XS2A__) || defined (__XS3A__))
.cc_top dsp_sqrt30_xs2.function
.globl dsp_sqrt30_xs2
.type dsp_sqrt30_xs2,@function
#define NSTACKWORDS 2
// void dsp_sqrt30_xs2(uint32_t x)
.align 16
.globl sqrt_as
.issue_mode dual
dsp_sqrt30_xs2:
dualentsp 0 //TODO remove this - it's here to allow call from SI
{ bf r0, zero_sqrt ; clz r11, r0 }
{ dualentsp NSTACKWORDS ; shr r3, r11, 1 }
{ shl r2, r3, 1 ; ldc r11, 25 }
{ shl r0, r0, r2 ; stw r5, sp[0] }
{ shr r1, r0, 2 ; ldc r5, 2 }
{ shr r2, r1, r11 ; ldap r11, firstbitslookup - 8 }
{ ld8u r2, r11[r2] ; shl r1, r1, 4 }
{ mul r11, r2, r2 }
{ shl r11, r11, 24 ; stw r4, sp[1] }
{ shl r2, r2, 6 ; shl r0, r2, 24 }
{ sub r1, r1, r11 ; ldap r11, jumptable-16*64}
{ add r2, r2, r11 ; ldc r4, 26 }
{ shr r11, r1, r4 ; shl r5, r5, 24 }
next:
{ ld8u r11, r2[r11] ; shr r5, r5, 2 }
{ bru r11 ; shl r1, r1, 2 }
//bp
{ bt r5, next ; shr r11, r1, r4 }
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
//nobp_sh_ne
{ bf r5, lastbit_sh_ne ; sub r11, r0, r5 }
{ sub r0, r0, r5 ; shl r11, r11, 3 }
{ sub r0, r0, r5 ; add r1, r1, r11 }
{ shr r11, r1, r4 ; bu next }
//nobp_sh_none
{ bf r5, lastbit_sh_none ; add r11, r0, r5 }
{ add r0, r0, r5 ; shl r11, r11, 3 }
{ add r0, r0, r5 ; sub r1, r1, r11 }
{ shr r11, r1, r4 ; bu next }
//nobp_nosh_ne
{ shl r11, r5, 1 ; bf r5, lastbit_nosh_ne }
{ shl r11, r0, 2 ; sub r1, r1, r11 }
{ add r1, r1, r11 ; sub r0, r0, r5 }
{ shr r11, r1, r4 ; bu next }
//nobp_nosh_none
{ shl r11, r5, 1 ; bf r5, lastbit_nosh_none }
{ shl r11, r0, 2 ; sub r1, r1, r11 }
{ sub r1, r1, r11 ; add r0, r0, r5 }
{ shr r11, r1, r4 ; bu next }
.align 16
lastbit_sh_ne:
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; sub r0, r0, 2 }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
.align 16
lastbit_sh_none:
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; add r0, r0, 2 }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
.align 16
lastbit_nosh_ne:
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; sub r0, r0, 1 }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
.align 16
lastbit_nosh_none:
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; add r0, r0, 1 }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
zero_sqrt:
{ retsp 0 ; }
firstbitslookup:
.byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f
jumptable:
.byte 0,0,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,0,0
.byte 0,0,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,0,0
.byte 0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0
.byte 0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0
.byte 0,0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12,0,0,0
.tmp_dsp_sqrt30_xs2:
.size dsp_sqrt30_xs2, .tmp_dsp_sqrt30_xs2-dsp_sqrt30_xs2
.align 4
.cc_bottom dsp_sqrt30_xs2.function
.set dsp_sqrt30_xs2.nstackwords,NSTACKWORDS
.globl dsp_sqrt30_xs2.nstackwords
.set dsp_sqrt30_xs2.maxcores,1
.globl dsp_sqrt30_xs2.maxcores
.set dsp_sqrt30_xs2.maxtimers,0
.globl dsp_sqrt30_xs2.maxtimers
.set dsp_sqrt30_xs2.maxchanends,0
.globl dsp_sqrt30_xs2.maxchanends
#endif
// Copyright 2016-2021 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
.section .dp.data,"awd",@progbits
.text
#if (defined(__XS2A__) || defined (__XS3A__))
.cc_top dsp_sqrt30_xs2.function
.globl dsp_sqrt30_xs2
.type dsp_sqrt30_xs2,@function
#define NSTACKWORDS 2
// void dsp_sqrt30_xs2(uint32_t x)
.align 16
.globl sqrt_as
.issue_mode dual
dsp_sqrt30_xs2:
dualentsp 0 //TODO remove this - it's here to allow call from SI
{ bf r0, zero_sqrt ; clz r11, r0 }
{ dualentsp NSTACKWORDS ; shr r3, r11, 1 }
{ shl r2, r3, 1 ; ldc r11, 25 }
{ shl r0, r0, r2 ; stw r5, sp[0] }
{ shr r1, r0, 2 ; ldc r5, 2 }
{ shr r2, r1, r11 ; ldap r11, firstbitslookup - 8 }
{ ld8u r2, r11[r2] ; shl r1, r1, 4 }
{ mul r11, r2, r2 }
{ shl r11, r11, 24 ; stw r4, sp[1] }
{ shl r2, r2, 6 ; shl r0, r2, 24 }
{ sub r1, r1, r11 ; ldap r11, jumptable-16*64}
{ add r2, r2, r11 ; ldc r4, 26 }
{ shr r11, r1, r4 ; shl r5, r5, 24 }
next:
{ ld8u r11, r2[r11] ; shr r5, r5, 2 }
{ bru r11 ; shl r1, r1, 2 }
//bp
{ bt r5, next ; shr r11, r1, r4 }
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
//nobp_sh_ne
{ bf r5, lastbit_sh_ne ; sub r11, r0, r5 }
{ sub r0, r0, r5 ; shl r11, r11, 3 }
{ sub r0, r0, r5 ; add r1, r1, r11 }
{ shr r11, r1, r4 ; bu next }
//nobp_sh_none
{ bf r5, lastbit_sh_none ; add r11, r0, r5 }
{ add r0, r0, r5 ; shl r11, r11, 3 }
{ add r0, r0, r5 ; sub r1, r1, r11 }
{ shr r11, r1, r4 ; bu next }
//nobp_nosh_ne
{ shl r11, r5, 1 ; bf r5, lastbit_nosh_ne }
{ shl r11, r0, 2 ; sub r1, r1, r11 }
{ add r1, r1, r11 ; sub r0, r0, r5 }
{ shr r11, r1, r4 ; bu next }
//nobp_nosh_none
{ shl r11, r5, 1 ; bf r5, lastbit_nosh_none }
{ shl r11, r0, 2 ; sub r1, r1, r11 }
{ sub r1, r1, r11 ; add r0, r0, r5 }
{ shr r11, r1, r4 ; bu next }
.align 16
lastbit_sh_ne:
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; sub r0, r0, 2 }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
.align 16
lastbit_sh_none:
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; add r0, r0, 2 }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
.align 16
lastbit_nosh_ne:
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; sub r0, r0, 1 }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
.align 16
lastbit_nosh_none:
{ ldw r4, sp[1] ; shl r0, r0, 1 }
{ ldw r5, sp[0] ; add r0, r0, 1 }
{ retsp NSTACKWORDS ; shr r0, r0, r3 }
zero_sqrt:
{ retsp 0 ; }
firstbitslookup:
.byte 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, 0x15, 0x16, 0x17, 0x17, 0x18, 0x19, 0x19, 0x1a, 0x1b, 0x1b, 0x1c, 0x1c, 0x1d, 0x1d, 0x1e, 0x1e, 0x1f, 0x1f
jumptable:
.byte 0,0,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,0,0
.byte 0,0,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,0,0
.byte 0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0
.byte 0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0
.byte 0,0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12,0,0,0
.byte 0,0,0,16,16,16,16,16,16,16,16,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,0,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,12,12,12,12,12,12,12,12,0,0,0
.tmp_dsp_sqrt30_xs2:
.size dsp_sqrt30_xs2, .tmp_dsp_sqrt30_xs2-dsp_sqrt30_xs2
.align 4
.cc_bottom dsp_sqrt30_xs2.function
.set dsp_sqrt30_xs2.nstackwords,NSTACKWORDS
.globl dsp_sqrt30_xs2.nstackwords
.set dsp_sqrt30_xs2.maxcores,1
.globl dsp_sqrt30_xs2.maxcores
.set dsp_sqrt30_xs2.maxtimers,0
.globl dsp_sqrt30_xs2.maxtimers
.set dsp_sqrt30_xs2.maxchanends,0
.globl dsp_sqrt30_xs2.maxchanends
#endif

View File

@@ -1,51 +1,51 @@
#ifndef __DS_BUILD_H__
#define __DS_BUILD_H__
//#define _DEBUG
#define XMOS_SDK
#define USE_OS // Thread, Event, Lock 등의 외부 OS API 사용
#define USE_FIXED_POINT // 내부 연산 고정소수점 사용
#define USE_PLANAR_ARRAY_INPUT // Audio Input Data Planar 배열 사용
#if (NUM_USB_CHAN_OUT > 5)
#define USE_LFE_UNIT // LFE 채널 Convolution 사용
#endif
// #define USE_UPMIX // Upmix 기능 사용
#if (NUM_USB_CHAN_OUT <= 8)
#if (NUM_USB_CHAN_OUT == 2)
#define USE_ONLY_STEREO
#endif
#define USE_ONLY_HORIZONTALITY // 수평 방향(Vertical 90도)만 사용
#elif (NUM_USB_CHAN_OUT == 12)
#define USE_7_1_4_IR_ARRARY // top: 1st~4th (45/135/225/315 ==> TFL/TFR/TBL/TBR)
// middle: 5th~12th (0/45/90/135/180/225/270/315 ==> FL/FR/C/LFE/BL/BR/SL/SR)
#elif (NUM_USB_CHAN_OUT == 16)
#define USE_7_1_4_4_IR_ARRARY // top: 1st~4th (45/135/225/315 ==> TFL/TFR/TBL/TBR)
// middle: 5th~12th (0/45/90/135/180/225/270/315 ==> FL/FR/C/LFE/BL/BR/SL/SR)
// bottom: 13th~16th (45/135/225/315 ==> BFL/BFR/BBL/BBR)
#elif (NUM_USB_CHAN_OUT == 24)
#define USE_7_1_8_8_IR_ARRARY // top: 1st~4th (0/45/90/135/180/225/270/315 ==> TFL/TFR/TFC/TBC/TBL/TBR/TSL/TSR)
// middle: 5th~12th (0/45/90/135/180/225/270/315 ==> FL/FR/C/LFE/BL/BR/SL/SR)
// bottom: 13th~16th (0/45/90/135/180/225/270/315 ==> BFL/BFR/BFC/BBC/BBL/BBR/BSL/BSR)
#endif
#if NUM_USB_CHAN_OUT == 8
//#define SHOOTING_GAME
#define DSP_WORKER_COUNT 4//3 //the count of workers
#define DSP_WORKER_DATA_CH_COUNT 2 //3 //the number of channels each one handles
#define DSP_WORKER_FILTER_PER_DATA_CH 2 //the number of channels each one handles
// #define IR_AUDIO
// #define IR_VIDEO
#else
#define IR_PS5
#define DSP_WORKER_COUNT 4 //the count of workers
#define DSP_WORKER_DATA_CH_COUNT 1 //the number of channels each one handles
#define DSP_WORKER_FILTER_PER_DATA_CH 2 //the number of channels each one handles
#endif
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#endif //__DS_BUILD_H__
#ifndef __DS_BUILD_H__
#define __DS_BUILD_H__
//#define _DEBUG
#define XMOS_SDK
#define USE_OS // Thread, Event, Lock 등의 외부 OS API 사용
#define USE_FIXED_POINT // 내부 연산 고정소수점 사용
#define USE_PLANAR_ARRAY_INPUT // Audio Input Data Planar 배열 사용
#if (NUM_USB_CHAN_OUT > 5)
#define USE_LFE_UNIT // LFE 채널 Convolution 사용
#endif
// #define USE_UPMIX // Upmix 기능 사용
#if (NUM_USB_CHAN_OUT <= 8)
#if (NUM_USB_CHAN_OUT == 2)
#define USE_ONLY_STEREO
#endif
#define USE_ONLY_HORIZONTALITY // 수평 방향(Vertical 90도)만 사용
#elif (NUM_USB_CHAN_OUT == 12)
#define USE_7_1_4_IR_ARRARY // top: 1st~4th (45/135/225/315 ==> TFL/TFR/TBL/TBR)
// middle: 5th~12th (0/45/90/135/180/225/270/315 ==> FL/FR/C/LFE/BL/BR/SL/SR)
#elif (NUM_USB_CHAN_OUT == 16)
#define USE_7_1_4_4_IR_ARRARY // top: 1st~4th (45/135/225/315 ==> TFL/TFR/TBL/TBR)
// middle: 5th~12th (0/45/90/135/180/225/270/315 ==> FL/FR/C/LFE/BL/BR/SL/SR)
// bottom: 13th~16th (45/135/225/315 ==> BFL/BFR/BBL/BBR)
#elif (NUM_USB_CHAN_OUT == 24)
#define USE_7_1_8_8_IR_ARRARY // top: 1st~4th (0/45/90/135/180/225/270/315 ==> TFL/TFR/TFC/TBC/TBL/TBR/TSL/TSR)
// middle: 5th~12th (0/45/90/135/180/225/270/315 ==> FL/FR/C/LFE/BL/BR/SL/SR)
// bottom: 13th~16th (0/45/90/135/180/225/270/315 ==> BFL/BFR/BFC/BBC/BBL/BBR/BSL/BSR)
#endif
#if NUM_USB_CHAN_OUT == 8
//#define SHOOTING_GAME
#define DSP_WORKER_COUNT 4//3 //the count of workers
#define DSP_WORKER_DATA_CH_COUNT 2 //3 //the number of channels each one handles
#define DSP_WORKER_FILTER_PER_DATA_CH 2 //the number of channels each one handles
// #define IR_AUDIO
// #define IR_VIDEO
#else
#define IR_PS5
#define DSP_WORKER_COUNT 4 //the count of workers
#define DSP_WORKER_DATA_CH_COUNT 1 //the number of channels each one handles
#define DSP_WORKER_FILTER_PER_DATA_CH 2 //the number of channels each one handles
#endif
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
#endif //__DS_BUILD_H__

View File

@@ -1,72 +1,72 @@
#if defined(EXTERN)
#undef EXTERN
#endif
#if defined(_AUDIO_EX3D_CONTROL_C_)
#define EXTERN
#else
#define EXTERN extern
#endif
#define NO_ERR 0
#ifndef TRUE
#define TRUE 1
#endif
#ifndef true
#define true 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef false
#define false 0
#endif
#ifndef DS_BOOL
typedef int DS_BOOL;
#endif
#define EX3D_SET_CH_NUM NUM_USB_CHAN_OUT
#define EX3D_SF_NUM 1
EXTERN void audio_ex3d_load_key(chanend_t c);
EXTERN int audio_ex3d_activate_key(chanend_t c);
EXTERN int audio_ex3d_init(uint32_t dwChannels, uint32_t dwSampleSize, uint32_t dwSRHz, uint32_t dwAudioDataSize);
EXTERN int audio_ex3d_conv_init(uint32_t dwTileNum, uint32_t dwChannels);
EXTERN int audio_ex3d_deinit(void);
EXTERN int audio_ex3d_change_parameter(uint32_t dwChannels, uint32_t dwSampleSize, uint32_t dwSRHz, uint32_t dwAudioDataSize);
EXTERN void audio_ex3d_set_onoff(DS_BOOL onoff);
EXTERN void audio_ex3d_set_sf(uint32_t SF_Idx);
#if 1
EXTERN void audio_ex3d_set_angle(uint32_t dwCh1Angle, uint32_t dwCh2Angle);
#else
EXTERN void audio_ex3d_set_angle(uint32_t dwCh1Angle, uint32_t dwCh2Angle,
uint32_t dwCh3Angle, uint32_t dwCh4Angle,
uint32_t dwCh5Angle, uint32_t dwCh6Angle,
uint32_t dwCh7Angle, uint32_t dwCh8Angle);
#endif
EXTERN void audio_ex3d_set_upmix(DS_BOOL onoff);
EXTERN void audio_ex3d_upmix_toggle(void);
EXTERN void audio_ex3d_toggle(void);
EXTERN void audio_ex3d_task(void);
EXTERN uint32_t EX3D_HAngle[EX3D_SET_CH_NUM]; // EX3D Channel 수평각
EXTERN uint32_t EX3D_VAngle[EX3D_SET_CH_NUM]; // EX3D Channel 수직각
EXTERN DS_BOOL EX3D_Mute[EX3D_SET_CH_NUM]; // EX3D Channel Mute
EXTERN uint8_t bEX3D_Open; // EX3D Open 유무 저장
EXTERN uint8_t bEX3D_On; // EX3D On 유무 저장
EXTERN int32_t Ex3dOnGain; // EX3D On Gain 값
EXTERN int32_t Ex3dOffGain; // EX3D Off Gain 값
EXTERN int32_t Ex3dLfeGain; // EX3D Lfe Gain 값
EXTERN uint8_t bEX3D_Upmix; // EX3D Upmix 유무 저장
EXTERN float Ex3dLimiterThreshold; // EX3D Limiter threshold 값
EXTERN int32_t Ex3dLimiterAttackTime; // EX3D Limiter Attack Time 값
EXTERN int32_t Ex3dLimiterReleaseTime; // EX3D Limiter Release Time 값
#if defined(EXTERN)
#undef EXTERN
#endif
#if defined(_AUDIO_EX3D_CONTROL_C_)
#define EXTERN
#else
#define EXTERN extern
#endif
#define NO_ERR 0
#ifndef TRUE
#define TRUE 1
#endif
#ifndef true
#define true 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
#ifndef false
#define false 0
#endif
#ifndef DS_BOOL
typedef int DS_BOOL;
#endif
#define EX3D_SET_CH_NUM NUM_USB_CHAN_OUT
#define EX3D_SF_NUM 1
EXTERN void audio_ex3d_load_key(chanend_t c);
EXTERN int audio_ex3d_activate_key(chanend_t c);
EXTERN int audio_ex3d_init(uint32_t dwChannels, uint32_t dwSampleSize, uint32_t dwSRHz, uint32_t dwAudioDataSize);
EXTERN int audio_ex3d_conv_init(uint32_t dwTileNum, uint32_t dwChannels);
EXTERN int audio_ex3d_deinit(void);
EXTERN int audio_ex3d_change_parameter(uint32_t dwChannels, uint32_t dwSampleSize, uint32_t dwSRHz, uint32_t dwAudioDataSize);
EXTERN void audio_ex3d_set_onoff(DS_BOOL onoff);
EXTERN void audio_ex3d_set_sf(uint32_t SF_Idx);
#if 1
EXTERN void audio_ex3d_set_angle(uint32_t dwCh1Angle, uint32_t dwCh2Angle);
#else
EXTERN void audio_ex3d_set_angle(uint32_t dwCh1Angle, uint32_t dwCh2Angle,
uint32_t dwCh3Angle, uint32_t dwCh4Angle,
uint32_t dwCh5Angle, uint32_t dwCh6Angle,
uint32_t dwCh7Angle, uint32_t dwCh8Angle);
#endif
EXTERN void audio_ex3d_set_upmix(DS_BOOL onoff);
EXTERN void audio_ex3d_upmix_toggle(void);
EXTERN void audio_ex3d_toggle(void);
EXTERN void audio_ex3d_task(void);
EXTERN uint32_t EX3D_HAngle[EX3D_SET_CH_NUM]; // EX3D Channel 수평각
EXTERN uint32_t EX3D_VAngle[EX3D_SET_CH_NUM]; // EX3D Channel 수직각
EXTERN DS_BOOL EX3D_Mute[EX3D_SET_CH_NUM]; // EX3D Channel Mute
EXTERN uint8_t bEX3D_Open; // EX3D Open 유무 저장
EXTERN uint8_t bEX3D_On; // EX3D On 유무 저장
EXTERN int32_t Ex3dOnGain; // EX3D On Gain 값
EXTERN int32_t Ex3dOffGain; // EX3D Off Gain 값
EXTERN int32_t Ex3dLfeGain; // EX3D Lfe Gain 값
EXTERN uint8_t bEX3D_Upmix; // EX3D Upmix 유무 저장
EXTERN float Ex3dLimiterThreshold; // EX3D Limiter threshold 값
EXTERN int32_t Ex3dLimiterAttackTime; // EX3D Limiter Attack Time 값
EXTERN int32_t Ex3dLimiterReleaseTime; // EX3D Limiter Release Time 값

View File

@@ -0,0 +1,797 @@
/*
* The little filesystem
*
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef LFS_H
#define LFS_H
#include "lfs_util.h"
#ifdef __cplusplus
extern "C"
{
#endif
/// Version info ///
// Software library version
// Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions
#define LFS_VERSION 0x0002000a
#define LFS_VERSION_MAJOR (0xffff & (LFS_VERSION >> 16))
#define LFS_VERSION_MINOR (0xffff & (LFS_VERSION >> 0))
// Version of On-disk data structures
// Major (top-nibble), incremented on backwards incompatible changes
// Minor (bottom-nibble), incremented on feature additions
#define LFS_DISK_VERSION 0x00020001
#define LFS_DISK_VERSION_MAJOR (0xffff & (LFS_DISK_VERSION >> 16))
#define LFS_DISK_VERSION_MINOR (0xffff & (LFS_DISK_VERSION >> 0))
/// Definitions ///
// Type definitions
typedef uint32_t lfs_size_t;
typedef uint32_t lfs_off_t;
typedef int32_t lfs_ssize_t;
typedef int32_t lfs_soff_t;
typedef uint32_t lfs_block_t;
// Maximum name size in bytes, may be redefined to reduce the size of the
// info struct. Limited to <= 1022. Stored in superblock and must be
// respected by other littlefs drivers.
#ifndef LFS_NAME_MAX
#define LFS_NAME_MAX 255
#endif
// Maximum size of a file in bytes, may be redefined to limit to support other
// drivers. Limited on disk to <= 2147483647. Stored in superblock and must be
// respected by other littlefs drivers.
#ifndef LFS_FILE_MAX
#define LFS_FILE_MAX 2147483647
#endif
// Maximum size of custom attributes in bytes, may be redefined, but there is
// no real benefit to using a smaller LFS_ATTR_MAX. Limited to <= 1022. Stored
// in superblock and must be respected by other littlefs drivers.
#ifndef LFS_ATTR_MAX
#define LFS_ATTR_MAX 1022
#endif
// Possible error codes, these are negative to allow
// valid positive return values
enum lfs_error {
LFS_ERR_OK = 0, // No error
LFS_ERR_IO = -5, // Error during device operation
LFS_ERR_CORRUPT = -84, // Corrupted
LFS_ERR_NOENT = -2, // No directory entry
LFS_ERR_EXIST = -17, // Entry already exists
LFS_ERR_NOTDIR = -20, // Entry is not a dir
LFS_ERR_ISDIR = -21, // Entry is a dir
LFS_ERR_NOTEMPTY = -39, // Dir is not empty
LFS_ERR_BADF = -9, // Bad file number
LFS_ERR_FBIG = -27, // File too large
LFS_ERR_INVAL = -22, // Invalid parameter
LFS_ERR_NOSPC = -28, // No space left on device
LFS_ERR_NOMEM = -12, // No more memory available
LFS_ERR_NOATTR = -61, // No data/attr available
LFS_ERR_NAMETOOLONG = -36, // File name too long
};
// File types
enum lfs_type {
// file types
LFS_TYPE_REG = 0x001,
LFS_TYPE_DIR = 0x002,
// internally used types
LFS_TYPE_SPLICE = 0x400,
LFS_TYPE_NAME = 0x000,
LFS_TYPE_STRUCT = 0x200,
LFS_TYPE_USERATTR = 0x300,
LFS_TYPE_FROM = 0x100,
LFS_TYPE_TAIL = 0x600,
LFS_TYPE_GLOBALS = 0x700,
LFS_TYPE_CRC = 0x500,
// internally used type specializations
LFS_TYPE_CREATE = 0x401,
LFS_TYPE_DELETE = 0x4ff,
LFS_TYPE_SUPERBLOCK = 0x0ff,
LFS_TYPE_DIRSTRUCT = 0x200,
LFS_TYPE_CTZSTRUCT = 0x202,
LFS_TYPE_INLINESTRUCT = 0x201,
LFS_TYPE_SOFTTAIL = 0x600,
LFS_TYPE_HARDTAIL = 0x601,
LFS_TYPE_MOVESTATE = 0x7ff,
LFS_TYPE_CCRC = 0x500,
LFS_TYPE_FCRC = 0x5ff,
// internal chip sources
LFS_FROM_NOOP = 0x000,
LFS_FROM_MOVE = 0x101,
LFS_FROM_USERATTRS = 0x102,
};
// File open flags
enum lfs_open_flags {
// open flags
LFS_O_RDONLY = 1, // Open a file as read only
#ifndef LFS_READONLY
LFS_O_WRONLY = 2, // Open a file as write only
LFS_O_RDWR = 3, // Open a file as read and write
LFS_O_CREAT = 0x0100, // Create a file if it does not exist
LFS_O_EXCL = 0x0200, // Fail if a file already exists
LFS_O_TRUNC = 0x0400, // Truncate the existing file to zero size
LFS_O_APPEND = 0x0800, // Move to end of file on every write
#endif
// internally used flags
#ifndef LFS_READONLY
LFS_F_DIRTY = 0x010000, // File does not match storage
LFS_F_WRITING = 0x020000, // File has been written since last flush
#endif
LFS_F_READING = 0x040000, // File has been read since last flush
#ifndef LFS_READONLY
LFS_F_ERRED = 0x080000, // An error occurred during write
#endif
LFS_F_INLINE = 0x100000, // Currently inlined in directory entry
};
// File seek flags
enum lfs_whence_flags {
LFS_SEEK_SET = 0, // Seek relative to an absolute position
LFS_SEEK_CUR = 1, // Seek relative to the current file position
LFS_SEEK_END = 2, // Seek relative to the end of the file
};
// Configuration provided during initialization of the littlefs
struct lfs_config {
// Opaque user provided context that can be used to pass
// information to the block device operations
void *context;
// Read a region in a block. Negative error codes are propagated
// to the user.
int (*read)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size);
// Program a region in a block. The block must have previously
// been erased. Negative error codes are propagated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*prog)(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size);
// Erase a block. A block must be erased before being programmed.
// The state of an erased block is undefined. Negative error codes
// are propagated to the user.
// May return LFS_ERR_CORRUPT if the block should be considered bad.
int (*erase)(const struct lfs_config *c, lfs_block_t block);
// Sync the state of the underlying block device. Negative error codes
// are propagated to the user.
int (*sync)(const struct lfs_config *c);
#ifdef LFS_THREADSAFE
// Lock the underlying block device. Negative error codes
// are propagated to the user.
int (*lock)(const struct lfs_config *c);
// Unlock the underlying block device. Negative error codes
// are propagated to the user.
int (*unlock)(const struct lfs_config *c);
#endif
// Minimum size of a block read in bytes. All read operations will be a
// multiple of this value.
lfs_size_t read_size;
// Minimum size of a block program in bytes. All program operations will be
// a multiple of this value.
lfs_size_t prog_size;
// Size of an erasable block in bytes. This does not impact ram consumption
// and may be larger than the physical erase size. However, non-inlined
// files take up at minimum one block. Must be a multiple of the read and
// program sizes.
lfs_size_t block_size;
// Number of erasable blocks on the device. Defaults to block_count stored
// on disk when zero.
lfs_size_t block_count;
// Number of erase cycles before littlefs evicts metadata logs and moves
// the metadata to another block. Suggested values are in the
// range 100-1000, with large values having better performance at the cost
// of less consistent wear distribution.
//
// Set to -1 to disable block-level wear-leveling.
int32_t block_cycles;
// Size of block caches in bytes. Each cache buffers a portion of a block in
// RAM. The littlefs needs a read cache, a program cache, and one additional
// cache per file. Larger caches can improve performance by storing more
// data and reducing the number of disk accesses. Must be a multiple of the
// read and program sizes, and a factor of the block size.
lfs_size_t cache_size;
// Size of the lookahead buffer in bytes. A larger lookahead buffer
// increases the number of blocks found during an allocation pass. The
// lookahead buffer is stored as a compact bitmap, so each byte of RAM
// can track 8 blocks.
lfs_size_t lookahead_size;
// Threshold for metadata compaction during lfs_fs_gc in bytes. Metadata
// pairs that exceed this threshold will be compacted during lfs_fs_gc.
// Defaults to ~88% block_size when zero, though the default may change
// in the future.
//
// Note this only affects lfs_fs_gc. Normal compactions still only occur
// when full.
//
// Set to -1 to disable metadata compaction during lfs_fs_gc.
lfs_size_t compact_thresh;
// Optional statically allocated read buffer. Must be cache_size.
// By default lfs_malloc is used to allocate this buffer.
void *read_buffer;
// Optional statically allocated program buffer. Must be cache_size.
// By default lfs_malloc is used to allocate this buffer.
void *prog_buffer;
// Optional statically allocated lookahead buffer. Must be lookahead_size.
// By default lfs_malloc is used to allocate this buffer.
void *lookahead_buffer;
// Optional upper limit on length of file names in bytes. No downside for
// larger names except the size of the info struct which is controlled by
// the LFS_NAME_MAX define. Defaults to LFS_NAME_MAX or name_max stored on
// disk when zero.
lfs_size_t name_max;
// Optional upper limit on files in bytes. No downside for larger files
// but must be <= LFS_FILE_MAX. Defaults to LFS_FILE_MAX or file_max stored
// on disk when zero.
lfs_size_t file_max;
// Optional upper limit on custom attributes in bytes. No downside for
// larger attributes size but must be <= LFS_ATTR_MAX. Defaults to
// LFS_ATTR_MAX or attr_max stored on disk when zero.
lfs_size_t attr_max;
// Optional upper limit on total space given to metadata pairs in bytes. On
// devices with large blocks (e.g. 128kB) setting this to a low size (2-8kB)
// can help bound the metadata compaction time. Must be <= block_size.
// Defaults to block_size when zero.
lfs_size_t metadata_max;
// Optional upper limit on inlined files in bytes. Inlined files live in
// metadata and decrease storage requirements, but may be limited to
// improve metadata-related performance. Must be <= cache_size, <=
// attr_max, and <= block_size/8. Defaults to the largest possible
// inline_max when zero.
//
// Set to -1 to disable inlined files.
lfs_size_t inline_max;
#ifdef LFS_MULTIVERSION
// On-disk version to use when writing in the form of 16-bit major version
// + 16-bit minor version. This limiting metadata to what is supported by
// older minor versions. Note that some features will be lost. Defaults to
// to the most recent minor version when zero.
uint32_t disk_version;
#endif
};
// File info structure
struct lfs_info {
// Type of the file, either LFS_TYPE_REG or LFS_TYPE_DIR
uint8_t type;
// Size of the file, only valid for REG files. Limited to 32-bits.
lfs_size_t size;
// Name of the file stored as a null-terminated string. Limited to
// LFS_NAME_MAX+1, which can be changed by redefining LFS_NAME_MAX to
// reduce RAM. LFS_NAME_MAX is stored in superblock and must be
// respected by other littlefs drivers.
char name[LFS_NAME_MAX+1];
};
// Filesystem info structure
struct lfs_fsinfo {
// On-disk version.
uint32_t disk_version;
// Size of a logical block in bytes.
lfs_size_t block_size;
// Number of logical blocks in filesystem.
lfs_size_t block_count;
// Upper limit on the length of file names in bytes.
lfs_size_t name_max;
// Upper limit on the size of files in bytes.
lfs_size_t file_max;
// Upper limit on the size of custom attributes in bytes.
lfs_size_t attr_max;
};
// Custom attribute structure, used to describe custom attributes
// committed atomically during file writes.
struct lfs_attr {
// 8-bit type of attribute, provided by user and used to
// identify the attribute
uint8_t type;
// Pointer to buffer containing the attribute
void *buffer;
// Size of attribute in bytes, limited to LFS_ATTR_MAX
lfs_size_t size;
};
// Optional configuration provided during lfs_file_opencfg
struct lfs_file_config {
// Optional statically allocated file buffer. Must be cache_size.
// By default lfs_malloc is used to allocate this buffer.
void *buffer;
// Optional list of custom attributes related to the file. If the file
// is opened with read access, these attributes will be read from disk
// during the open call. If the file is opened with write access, the
// attributes will be written to disk every file sync or close. This
// write occurs atomically with update to the file's contents.
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller
// than the buffer, it will be padded with zeros. If the stored attribute
// is larger, then it will be silently truncated. If the attribute is not
// found, it will be created implicitly.
struct lfs_attr *attrs;
// Number of custom attributes in the list
lfs_size_t attr_count;
};
/// internal littlefs data structures ///
typedef struct lfs_cache {
lfs_block_t block;
lfs_off_t off;
lfs_size_t size;
uint8_t *buffer;
} lfs_cache_t;
typedef struct lfs_mdir {
lfs_block_t pair[2];
uint32_t rev;
lfs_off_t off;
uint32_t etag;
uint16_t count;
bool erased;
bool split;
lfs_block_t tail[2];
} lfs_mdir_t;
// littlefs directory type
typedef struct lfs_dir {
struct lfs_dir *next;
uint16_t id;
uint8_t type;
lfs_mdir_t m;
lfs_off_t pos;
lfs_block_t head[2];
} lfs_dir_t;
// littlefs file type
typedef struct lfs_file {
struct lfs_file *next;
uint16_t id;
uint8_t type;
lfs_mdir_t m;
struct lfs_ctz {
lfs_block_t head;
lfs_size_t size;
} ctz;
uint32_t flags;
lfs_off_t pos;
lfs_block_t block;
lfs_off_t off;
lfs_cache_t cache;
const struct lfs_file_config *cfg;
} lfs_file_t;
typedef struct lfs_superblock {
uint32_t version;
lfs_size_t block_size;
lfs_size_t block_count;
lfs_size_t name_max;
lfs_size_t file_max;
lfs_size_t attr_max;
} lfs_superblock_t;
typedef struct lfs_gstate {
uint32_t tag;
lfs_block_t pair[2];
} lfs_gstate_t;
// The littlefs filesystem type
typedef struct lfs {
lfs_cache_t rcache;
lfs_cache_t pcache;
lfs_block_t root[2];
struct lfs_mlist {
struct lfs_mlist *next;
uint16_t id;
uint8_t type;
lfs_mdir_t m;
} *mlist;
uint32_t seed;
lfs_gstate_t gstate;
lfs_gstate_t gdisk;
lfs_gstate_t gdelta;
struct lfs_lookahead {
lfs_block_t start;
lfs_block_t size;
lfs_block_t next;
lfs_block_t ckpoint;
uint8_t *buffer;
} lookahead;
const struct lfs_config *cfg;
lfs_size_t block_count;
lfs_size_t name_max;
lfs_size_t file_max;
lfs_size_t attr_max;
lfs_size_t inline_max;
#ifdef LFS_MIGRATE
struct lfs1 *lfs1;
#endif
} lfs_t;
/// Filesystem functions ///
#ifndef LFS_READONLY
// Format a block device with the littlefs
//
// Requires a littlefs object and config struct. This clobbers the littlefs
// object, and does not leave the filesystem mounted. The config struct must
// be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_format(lfs_t *lfs, const struct lfs_config *config);
#endif
// Mounts a littlefs
//
// Requires a littlefs object and config struct. Multiple filesystems
// may be mounted simultaneously with multiple littlefs objects. Both
// lfs and config must be allocated while mounted. The config struct must
// be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_mount(lfs_t *lfs, const struct lfs_config *config);
// Unmounts a littlefs
//
// Does nothing besides releasing any allocated resources.
// Returns a negative error code on failure.
int lfs_unmount(lfs_t *lfs);
/// General operations ///
#ifndef LFS_READONLY
// Removes a file or directory
//
// If removing a directory, the directory must be empty.
// Returns a negative error code on failure.
int lfs_remove(lfs_t *lfs, const char *path);
#endif
#ifndef LFS_READONLY
// Rename or move a file or directory
//
// If the destination exists, it must match the source in type.
// If the destination is a directory, the directory must be empty.
//
// Returns a negative error code on failure.
int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath);
#endif
// Find info about a file or directory
//
// Fills out the info structure, based on the specified file or directory.
// Returns a negative error code on failure.
int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info);
// Get a custom attribute
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. When read, if the stored attribute is smaller than
// the buffer, it will be padded with zeros. If the stored attribute is larger,
// then it will be silently truncated. If no attribute is found, the error
// LFS_ERR_NOATTR is returned and the buffer is filled with zeros.
//
// Returns the size of the attribute, or a negative error code on failure.
// Note, the returned size is the size of the attribute on disk, irrespective
// of the size of the buffer. This can be used to dynamically allocate a buffer
// or check for existence.
lfs_ssize_t lfs_getattr(lfs_t *lfs, const char *path,
uint8_t type, void *buffer, lfs_size_t size);
#ifndef LFS_READONLY
// Set custom attributes
//
// Custom attributes are uniquely identified by an 8-bit type and limited
// to LFS_ATTR_MAX bytes. If an attribute is not found, it will be
// implicitly created.
//
// Returns a negative error code on failure.
int lfs_setattr(lfs_t *lfs, const char *path,
uint8_t type, const void *buffer, lfs_size_t size);
#endif
#ifndef LFS_READONLY
// Removes a custom attribute
//
// If an attribute is not found, nothing happens.
//
// Returns a negative error code on failure.
int lfs_removeattr(lfs_t *lfs, const char *path, uint8_t type);
#endif
/// File operations ///
#ifndef LFS_NO_MALLOC
// Open a file
//
// The mode that the file is opened in is determined by the flags, which
// are values from the enum lfs_open_flags that are bitwise-ored together.
//
// Returns a negative error code on failure.
int lfs_file_open(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags);
// if LFS_NO_MALLOC is defined, lfs_file_open() will fail with LFS_ERR_NOMEM
// thus use lfs_file_opencfg() with config.buffer set.
#endif
// Open a file with extra configuration
//
// The mode that the file is opened in is determined by the flags, which
// are values from the enum lfs_open_flags that are bitwise-ored together.
//
// The config struct provides additional config options per file as described
// above. The config struct must remain allocated while the file is open, and
// the config struct must be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file,
const char *path, int flags,
const struct lfs_file_config *config);
// Close a file
//
// Any pending writes are written out to storage as though
// sync had been called and releases any allocated resources.
//
// Returns a negative error code on failure.
int lfs_file_close(lfs_t *lfs, lfs_file_t *file);
// Synchronize a file on storage
//
// Any pending writes are written out to storage.
// Returns a negative error code on failure.
int lfs_file_sync(lfs_t *lfs, lfs_file_t *file);
// Read data from file
//
// Takes a buffer and size indicating where to store the read data.
// Returns the number of bytes read, or a negative error code on failure.
lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file,
void *buffer, lfs_size_t size);
#ifndef LFS_READONLY
// Write data to file
//
// Takes a buffer and size indicating the data to write. The file will not
// actually be updated on the storage until either sync or close is called.
//
// Returns the number of bytes written, or a negative error code on failure.
lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
const void *buffer, lfs_size_t size);
#endif
// Change the position of the file
//
// The change in position is determined by the offset and whence flag.
// Returns the new position of the file, or a negative error code on failure.
lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file,
lfs_soff_t off, int whence);
#ifndef LFS_READONLY
// Truncates the size of the file to the specified size
//
// Returns a negative error code on failure.
int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size);
#endif
// Return the position of the file
//
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_CUR)
// Returns the position of the file, or a negative error code on failure.
lfs_soff_t lfs_file_tell(lfs_t *lfs, lfs_file_t *file);
// Change the position of the file to the beginning of the file
//
// Equivalent to lfs_file_seek(lfs, file, 0, LFS_SEEK_SET)
// Returns a negative error code on failure.
int lfs_file_rewind(lfs_t *lfs, lfs_file_t *file);
// Return the size of the file
//
// Similar to lfs_file_seek(lfs, file, 0, LFS_SEEK_END)
// Returns the size of the file, or a negative error code on failure.
lfs_soff_t lfs_file_size(lfs_t *lfs, lfs_file_t *file);
/// Directory operations ///
#ifndef LFS_READONLY
// Create a directory
//
// Returns a negative error code on failure.
int lfs_mkdir(lfs_t *lfs, const char *path);
#endif
// Open a directory
//
// Once open a directory can be used with read to iterate over files.
// Returns a negative error code on failure.
int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path);
// Close a directory
//
// Releases any allocated resources.
// Returns a negative error code on failure.
int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir);
// Read an entry in the directory
//
// Fills out the info structure, based on the specified file or directory.
// Returns a positive value on success, 0 at the end of directory,
// or a negative error code on failure.
int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info);
// Change the position of the directory
//
// The new off must be a value previous returned from tell and specifies
// an absolute offset in the directory seek.
//
// Returns a negative error code on failure.
int lfs_dir_seek(lfs_t *lfs, lfs_dir_t *dir, lfs_off_t off);
// Return the position of the directory
//
// The returned offset is only meant to be consumed by seek and may not make
// sense, but does indicate the current position in the directory iteration.
//
// Returns the position of the directory, or a negative error code on failure.
lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir);
// Change the position of the directory to the beginning of the directory
//
// Returns a negative error code on failure.
int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir);
/// Filesystem-level filesystem operations
// Find on-disk info about the filesystem
//
// Fills out the fsinfo structure based on the filesystem found on-disk.
// Returns a negative error code on failure.
int lfs_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo);
// Finds the current size of the filesystem
//
// Note: Result is best effort. If files share COW structures, the returned
// size may be larger than the filesystem actually is.
//
// Returns the number of allocated blocks, or a negative error code on failure.
lfs_ssize_t lfs_fs_size(lfs_t *lfs);
// Traverse through all blocks in use by the filesystem
//
// The provided callback will be called with each block address that is
// currently in use by the filesystem. This can be used to determine which
// blocks are in use or how much of the storage is available.
//
// Returns a negative error code on failure.
int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data);
#ifndef LFS_READONLY
// Attempt to make the filesystem consistent and ready for writing
//
// Calling this function is not required, consistency will be implicitly
// enforced on the first operation that writes to the filesystem, but this
// function allows the work to be performed earlier and without other
// filesystem changes.
//
// Returns a negative error code on failure.
int lfs_fs_mkconsistent(lfs_t *lfs);
#endif
#ifndef LFS_READONLY
// Attempt any janitorial work
//
// This currently:
// 1. Calls mkconsistent if not already consistent
// 2. Compacts metadata > compact_thresh
// 3. Populates the block allocator
//
// Though additional janitorial work may be added in the future.
//
// Calling this function is not required, but may allow the offloading of
// expensive janitorial work to a less time-critical code path.
//
// Returns a negative error code on failure. Accomplishing nothing is not
// an error.
int lfs_fs_gc(lfs_t *lfs);
#endif
#ifndef LFS_READONLY
// Grows the filesystem to a new size, updating the superblock with the new
// block count.
//
// Note: This is irreversible.
//
// Returns a negative error code on failure.
int lfs_fs_grow(lfs_t *lfs, lfs_size_t block_count);
#endif
#ifndef LFS_READONLY
#ifdef LFS_MIGRATE
// Attempts to migrate a previous version of littlefs
//
// Behaves similarly to the lfs_format function. Attempts to mount
// the previous version of littlefs and update the filesystem so it can be
// mounted with the current version of littlefs.
//
// Requires a littlefs object and config struct. This clobbers the littlefs
// object, and does not leave the filesystem mounted. The config struct must
// be zeroed for defaults and backwards compatibility.
//
// Returns a negative error code on failure.
int lfs_migrate(lfs_t *lfs, const struct lfs_config *cfg);
#endif
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif

View File

@@ -0,0 +1,275 @@
/*
* lfs utility functions
*
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef LFS_UTIL_H
#define LFS_UTIL_H
#define LFS_STRINGIZE(x) LFS_STRINGIZE2(x)
#define LFS_STRINGIZE2(x) #x
// Users can override lfs_util.h with their own configuration by defining
// LFS_CONFIG as a header file to include (-DLFS_CONFIG=lfs_config.h).
//
// If LFS_CONFIG is used, none of the default utils will be emitted and must be
// provided by the config file. To start, I would suggest copying lfs_util.h
// and modifying as needed.
#ifdef LFS_CONFIG
#include LFS_STRINGIZE(LFS_CONFIG)
#else
// Alternatively, users can provide a header file which defines
// macros and other things consumed by littlefs.
//
// For example, provide my_defines.h, which contains
// something like:
//
// #include <stddef.h>
// extern void *my_malloc(size_t sz);
// #define LFS_MALLOC(sz) my_malloc(sz)
//
// And build littlefs with the header by defining LFS_DEFINES.
// (-DLFS_DEFINES=my_defines.h)
#ifdef LFS_DEFINES
#include LFS_STRINGIZE(LFS_DEFINES)
#endif
// System includes
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <inttypes.h>
#ifndef LFS_NO_MALLOC
#include <stdlib.h>
#endif
#ifndef LFS_NO_ASSERT
#include <assert.h>
#endif
#if !defined(LFS_NO_DEBUG) || \
!defined(LFS_NO_WARN) || \
!defined(LFS_NO_ERROR) || \
defined(LFS_YES_TRACE)
#include <stdio.h>
#endif
#ifdef __cplusplus
extern "C"
{
#endif
// Macros, may be replaced by system specific wrappers. Arguments to these
// macros must not have side-effects as the macros can be removed for a smaller
// code footprint
// Logging functions
#ifndef LFS_TRACE
#ifdef LFS_YES_TRACE
#define LFS_TRACE_(fmt, ...) \
printf("%s:%d:trace: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_TRACE(...) LFS_TRACE_(__VA_ARGS__, "")
#else
#define LFS_TRACE(...)
#endif
#endif
#ifndef LFS_DEBUG
#ifndef LFS_NO_DEBUG
#define LFS_DEBUG_(fmt, ...) \
printf("%s:%d:debug: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_DEBUG(...) LFS_DEBUG_(__VA_ARGS__, "")
#else
#define LFS_DEBUG(...)
#endif
#endif
#ifndef LFS_WARN
#ifndef LFS_NO_WARN
#define LFS_WARN_(fmt, ...) \
printf("%s:%d:warn: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_WARN(...) LFS_WARN_(__VA_ARGS__, "")
#else
#define LFS_WARN(...)
#endif
#endif
#ifndef LFS_ERROR
#ifndef LFS_NO_ERROR
#define LFS_ERROR_(fmt, ...) \
printf("%s:%d:error: " fmt "%s\n", __FILE__, __LINE__, __VA_ARGS__)
#define LFS_ERROR(...) LFS_ERROR_(__VA_ARGS__, "")
#else
#define LFS_ERROR(...)
#endif
#endif
// Runtime assertions
#ifndef LFS_ASSERT
#ifndef LFS_NO_ASSERT
#define LFS_ASSERT(test) assert(test)
#else
#define LFS_ASSERT(test)
#endif
#endif
// Builtin functions, these may be replaced by more efficient
// toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more
// expensive basic C implementation for debugging purposes
// Min/max functions for unsigned 32-bit numbers
static inline uint32_t lfs_max(uint32_t a, uint32_t b) {
return (a > b) ? a : b;
}
static inline uint32_t lfs_min(uint32_t a, uint32_t b) {
return (a < b) ? a : b;
}
// Align to nearest multiple of a size
static inline uint32_t lfs_aligndown(uint32_t a, uint32_t alignment) {
return a - (a % alignment);
}
static inline uint32_t lfs_alignup(uint32_t a, uint32_t alignment) {
return lfs_aligndown(a + alignment-1, alignment);
}
// Find the smallest power of 2 greater than or equal to a
static inline uint32_t lfs_npw2(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return 32 - __builtin_clz(a-1);
#else
uint32_t r = 0;
uint32_t s;
a -= 1;
s = (a > 0xffff) << 4; a >>= s; r |= s;
s = (a > 0xff ) << 3; a >>= s; r |= s;
s = (a > 0xf ) << 2; a >>= s; r |= s;
s = (a > 0x3 ) << 1; a >>= s; r |= s;
return (r | (a >> 1)) + 1;
#endif
}
// Count the number of trailing binary zeros in a
// lfs_ctz(0) may be undefined
static inline uint32_t lfs_ctz(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && defined(__GNUC__)
return __builtin_ctz(a);
#else
return lfs_npw2((a & -a) + 1) - 1;
#endif
}
// Count the number of binary ones in a
static inline uint32_t lfs_popc(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && (defined(__GNUC__) || defined(__CC_ARM))
return __builtin_popcount(a);
#else
a = a - ((a >> 1) & 0x55555555);
a = (a & 0x33333333) + ((a >> 2) & 0x33333333);
return (((a + (a >> 4)) & 0xf0f0f0f) * 0x1010101) >> 24;
#endif
}
// Find the sequence comparison of a and b, this is the distance
// between a and b ignoring overflow
static inline int lfs_scmp(uint32_t a, uint32_t b) {
return (int)(unsigned)(a - b);
}
// Convert between 32-bit little-endian and native order
static inline uint32_t lfs_fromle32(uint32_t a) {
#if (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
return a;
#elif !defined(LFS_NO_INTRINSICS) && ( \
(defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))
return __builtin_bswap32(a);
#else
return (((uint8_t*)&a)[0] << 0) |
(((uint8_t*)&a)[1] << 8) |
(((uint8_t*)&a)[2] << 16) |
(((uint8_t*)&a)[3] << 24);
#endif
}
static inline uint32_t lfs_tole32(uint32_t a) {
return lfs_fromle32(a);
}
// Convert between 32-bit big-endian and native order
static inline uint32_t lfs_frombe32(uint32_t a) {
#if !defined(LFS_NO_INTRINSICS) && ( \
(defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \
(defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__))
return __builtin_bswap32(a);
#elif (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \
(defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \
(defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
return a;
#else
return (((uint8_t*)&a)[0] << 24) |
(((uint8_t*)&a)[1] << 16) |
(((uint8_t*)&a)[2] << 8) |
(((uint8_t*)&a)[3] << 0);
#endif
}
static inline uint32_t lfs_tobe32(uint32_t a) {
return lfs_frombe32(a);
}
// Calculate CRC-32 with polynomial = 0x04c11db7
#ifdef LFS_CRC
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
return LFS_CRC(crc, buffer, size)
}
#else
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size);
#endif
// Allocate memory, only used if buffers are not provided to littlefs
//
// littlefs current has no alignment requirements, as it only allocates
// byte-level buffers.
static inline void *lfs_malloc(size_t size) {
#if defined(LFS_MALLOC)
return LFS_MALLOC(size);
#elif !defined(LFS_NO_MALLOC)
return malloc(size);
#else
(void)size;
return NULL;
#endif
}
// Deallocate memory, only used if buffers are not provided to littlefs
static inline void lfs_free(void *p) {
#if defined(LFS_FREE)
LFS_FREE(p);
#elif !defined(LFS_NO_MALLOC)
if (!p) {
free(p);
}
#else
(void)p;
#endif
}
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif
#endif

View File

@@ -0,0 +1,10 @@
set(LIB_NAME lib_littlefs)
set(LIB_VERSION 0.0.1)
set(LIB_INCLUDES api)
set(LIB_DEPENDENT_MODULES "lib_logging(3.2.0)")
set(LIB_COMPILER_FLAGS -O3 -DREF_CLK_FREQ=100 -fasm-linenum -fcomment-asm)
list(APPEND LIB_COMPILER_FLAGS -DXASSERT_ENABLE_ASSERTIONS=0
-DXASSERT_ENABLE_DEBUG=0
-DXASSERT_ENABLE_LINE_NUMBERS=0)
XMOS_REGISTER_MODULE()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,37 @@
/*
* lfs util functions
*
* Copyright (c) 2022, The littlefs authors.
* Copyright (c) 2017, Arm Limited. All rights reserved.
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "lfs_util.h"
// Only compile if user does not provide custom config
#ifndef LFS_CONFIG
// If user provides their own CRC impl we don't need this
#ifndef LFS_CRC
// Software CRC implementation with small lookup table
uint32_t lfs_crc(uint32_t crc, const void *buffer, size_t size) {
static const uint32_t rtable[16] = {
0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c,
};
const uint8_t *data = buffer;
for (size_t i = 0; i < size; i++) {
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 0)) & 0xf];
crc = (crc >> 4) ^ rtable[(crc ^ (data[i] >> 4)) & 0xf];
}
return crc;
}
#endif
#endif

View File

@@ -0,0 +1,30 @@
if((${CMAKE_SYSTEM_NAME} STREQUAL XCORE_XS3A) OR (${CMAKE_SYSTEM_NAME} STREQUAL XCORE_XS2A))
## Create library target
add_library(framework_rtos_drivers_qspi_io INTERFACE)
target_sources(framework_rtos_drivers_qspi_io
INTERFACE
src/rtos_qspi_flash.c
src/rtos_qspi_flash_rpc.c
)
target_include_directories(framework_rtos_drivers_qspi_io
INTERFACE
api
)
target_link_libraries(framework_rtos_drivers_qspi_io
INTERFACE
lib_qspi_fast_read
rtos::osal
)
target_compile_options(framework_rtos_drivers_qspi_io
INTERFACE
-lquadflash
)
target_link_options(framework_rtos_drivers_qspi_io
INTERFACE
-lquadflash
)
## Create an alias
add_library(rtos::drivers::qspi_io ALIAS framework_rtos_drivers_qspi_io)
endif()

View File

@@ -0,0 +1,394 @@
// Copyright 2020-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#ifndef RTOS_QSPI_FLASH_H_
#define RTOS_QSPI_FLASH_H_
/**
* \addtogroup rtos_qspi_flash_driver rtos_qspi_flash_driver
*
* The public API for using the RTOS QSPI flash driver.
* @{
*/
#include <quadflash.h>
#include <quadflashlib.h>
#include "xs1.h"
#include "xcore/clock.h"
#include "xcore/port.h"
#define RTOS_QSPI_FLASH_READ_CHUNK_SIZE (24*1024)
/**
* Typedef to the RTOS QSPI flash driver instance struct.
*/
typedef struct rtos_qspi_flash_struct rtos_qspi_flash_t;
/**
* Struct representing an RTOS QSPI flash driver instance.
*
* The members in this struct should not be accessed directly.
*/
struct rtos_qspi_flash_struct {
__attribute__((fptrgroup("rtos_qspi_flash_read_fptr_grp")))
void (*read)(rtos_qspi_flash_t *, uint8_t *, unsigned, size_t);
__attribute__((fptrgroup("rtos_qspi_flash_read_mode_fptr_grp")))
void (*read_mode)(rtos_qspi_flash_t *, uint8_t *, unsigned, size_t, qspi_fast_flash_read_transfer_mode_t);
__attribute__((fptrgroup("rtos_qspi_flash_write_fptr_grp")))
void (*write)(rtos_qspi_flash_t *, const uint8_t *, unsigned, size_t);
__attribute__((fptrgroup("rtos_qspi_flash_erase_fptr_grp")))
void (*erase)(rtos_qspi_flash_t *, unsigned, size_t);
__attribute__((fptrgroup("rtos_qspi_flash_lock_fptr_grp")))
void (*lock)(rtos_qspi_flash_t *);
__attribute__((fptrgroup("rtos_qspi_flash_unlock_fptr_grp")))
void (*unlock)(rtos_qspi_flash_t *);
fl_QSPIPorts qspi_ports;
fl_QuadDeviceSpec qspi_spec;
size_t flash_size;
unsigned calibration_valid;
unsigned last_op;
volatile int spinlock;
volatile int ll_req_flag;
};
/**
* \addtogroup rtos_qspi_flash_driver_core rtos_qspi_flash_driver_core
*
* The core functions for using an RTOS QSPI flash driver instance after
* it has been initialized and started. These functions may be used
* by both the host and any client tiles that RPC has been enabled for.
* @{
*/
/**
* Obtains a lock for exclusive access to the QSPI flash. This allows
* a thread to perform a sequence of operations (such as read, modify, erase,
* write) without the risk of another thread issuing a command in the middle of
* the sequence and corrupting the data in the flash.
*
* If only a single atomic operation needs to be performed, such as a read, it
* is not necessary to call this to obtain the lock first. Each individual operation
* obtains and releases the lock automatically so that they cannot run while another
* thread has the lock.
*
* The lock MUST be released when it is no longer needed by calling
* rtos_qspi_flash_unlock().
*
* \param ctx A pointer to the QSPI flash driver instance to lock.
*/
inline void rtos_qspi_flash_lock(
rtos_qspi_flash_t *ctx)
{
ctx->lock(ctx);
}
/**
* Releases a lock for exclusive access to the QSPI flash. The lock
* must have already been obtained by calling rtos_qspi_flash_lock().
*
* \param ctx A pointer to the QSPI flash driver instance to unlock.
*/
inline void rtos_qspi_flash_unlock(
rtos_qspi_flash_t *ctx)
{
ctx->unlock(ctx);
}
/**
* This reads data from the flash in quad I/O mode. All four lines are
* used to send the address and to read the data.
*
* \param ctx A pointer to the QSPI flash driver instance to use.
* \param data Pointer to the buffer to save the read data to.
* \param address The byte address in the flash to begin reading at.
* Only bits 23:0 contain the address. Bits 31:24 are
* ignored.
* \param len The number of bytes to read and save to \p data.
*/
inline void rtos_qspi_flash_read(
rtos_qspi_flash_t *ctx,
uint8_t *data,
unsigned address,
size_t len)
{
ctx->read(ctx, data, address, len);
}
/**
* This is a lower level version of rtos_qspi_flash_read() that is safe
* to call from within ISRs. If a task currently own the flash lock, or
* if another core is actively doing a read with this function, then the
* read will not be performed and an error returned. It is up to the
* application to determine what it should do in this situation and to
* avoid a potential deadlock.
*
* This function may only be called on the same tile as the underlying
* peripheral.
*
* This function uses the lib_quadflash API to perform the read. It is up
* to the application to ensure that XCORE resources are properly configured.
*
* \note It is not possible to call this from a task that currently owns
* the flash lock taken with rtos_qspi_flash_lock(). In general it is not
* advisable to call this from an RTOS task unless the small amount of
* overhead time that is introduced by rtos_qspi_flash_read() is unacceptable.
*
* \param ctx A pointer to the QSPI flash driver instance to use.
* \param data Pointer to the buffer to save the read data to.
* \param address The byte address in the flash to begin reading at.
* Only bits 23:0 contain the address. Bits 31:24 are
* ignored.
* \param len The number of bytes to read and save to \p data.
*
* \retval 0 if the flash was available and the read operation was performed.
* \retval -1 if the flash was unavailable and the read could not be performed.
*/
int rtos_qspi_flash_read_ll(
rtos_qspi_flash_t *ctx,
uint8_t *data,
unsigned address,
size_t len);
/**
* This writes data to the QSPI flash. The standard page program command
* is sent and only SIO0 (MOSI) is used to send the address and data.
*
* The driver handles sending the write enable command, as well as waiting for
* the write to complete.
*
* This function may return before the write operation is complete, as the actual
* write operation is queued and executed by a thread created by the driver.
*
* \note this function does NOT erase the flash first. Erase operations must be
* explicitly requested by the application.
*
* \param ctx A pointer to the QSPI flash driver instance to use.
* \param data Pointer to the data to write to the flash.
* \param address The byte address in the flash to begin writing at.
* Only bits 23:0 contain the address. The byte in bits 31:24 is
* not sent.
* \param len The number of bytes to write to the flash.
*/
inline void rtos_qspi_flash_write(
rtos_qspi_flash_t *ctx,
const uint8_t *data,
unsigned address,
size_t len)
{
ctx->write(ctx, data, address, len);
}
/**
* This erases data from the QSPI flash. If the address range to erase
* spans multiple sectors, then all of these sectors will be erased by issuing
* multiple erase commands.
*
* The driver handles sending the write enable command, as well as waiting for
* the write to complete.
*
* This function may return before the write operation is complete, as the actual
* erase operation is queued and executed by a thread created by the driver.
*
* \note The smallest amount of data that can be erased is a 4k sector.
* This means that data outside the address range specified by \p address
* and \p len will be erased if the address range does not both begin and
* end at 4k sector boundaries.
*
* \param ctx A pointer to the QSPI flash driver instance to use.
* \param address The byte address to begin erasing. This does not need to begin
* at a sector boundary, but if it does not, note that the entire
* sector that contains this address will still be erased.
* \param len The minimum number of bytes to erase. If \p address + \p len - 1
* does not correspond to the last address within a sector, note that
* the entire sector that contains this address will still be erased.
*/
inline void rtos_qspi_flash_erase(
rtos_qspi_flash_t *ctx,
unsigned address,
size_t len)
{
ctx->erase(ctx, address, len);
}
/**
* This gets the size in bytes of the flash chip.
*
* \param A pointer to the QSPI flash driver instance to query.
*
* \returns the size in bytes of the flash chip.
*/
inline size_t rtos_qspi_flash_size_get(
rtos_qspi_flash_t *qspi_flash_ctx)
{
return qspi_flash_ctx->flash_size;
}
/**
* This gets the size in bytes of each page in the flash chip.
*
* \param A pointer to the QSPI flash driver instance to query.
*
* \returns the size in bytes of the flash page.
*/
inline size_t rtos_qspi_flash_page_size_get(
rtos_qspi_flash_t *qspi_flash_ctx)
{
return qspi_flash_ctx->qspi_spec.pageSize;
}
/**
* This gets the number of pages in the flash chip.
*
* \param A pointer to the QSPI flash driver instance to query.
*
* \returns the number of pages in the flash chip.
*/
inline size_t rtos_qspi_flash_page_count_get(
rtos_qspi_flash_t *qspi_flash_ctx)
{
return qspi_flash_ctx->qspi_spec.numPages;
}
/**
* This gets the sector size of the flash chip
*
* \param A pointer to the QSPI flash driver instance to query.
*
* \returns the size in bytes of the smallest sector
*/
inline size_t rtos_qspi_flash_sector_size_get(
rtos_qspi_flash_t *qspi_flash_ctx)
{
return qspi_flash_ctx->qspi_spec.sectorEraseSize;
}
/**
* Gets the value of the calibration valid.
*
* \param A pointer to the QSPI flash driver instance to query.
*
* \returns 1 if calibration was successful
* 0 otherwise
*/
inline unsigned rtos_qspi_flash_calibration_valid_get(
rtos_qspi_flash_t *qspi_flash_ctx)
{
return qspi_flash_ctx->calibration_valid;
}
/**@}*/
/**
* Starts an RTOS QSPI flash driver instance. This must only be called by the tile that
* owns the driver instance. It may be called either before or after starting
* the RTOS, but must be called before any of the core QSPI flash driver functions are
* called with this instance.
*
* rtos_qspi_flash_init() must be called on this QSPI flash driver instance prior to calling this.
*
* \param ctx A pointer to the QSPI flash driver instance to start.
* \param priority The priority of the task that gets created by the driver to
* handle the QSPI flash interface.
*/
void rtos_qspi_flash_start(
rtos_qspi_flash_t *ctx,
unsigned priority);
/**
* Sets the core affinity for a RTOS QSPI flash driver instance.
* This must only be called by the tile that owns the driver instance.
* It may be called either before or after starting the RTOS, and should
* be called before any of the core QSPI flash driver functions are
* called with this instance.
*
* Since interrupts are disabled during the QSPI transaction on the op thread, a
* core mask is provided to allow users to avoid collisions with application ISRs.
*
* rtos_qspi_flash_start() must be called on this QSPI flash driver instance prior to calling this.
*
* \param ctx A pointer to the QSPI flash driver instance to start.
* \param op_core_mask A bitmask representing the cores on which the QSPI I/O thread
* created by the driver is allowed to run. Bit 0 is core 0, bit 1 is core 1,
* etc.
*/
void rtos_qspi_flash_op_core_affinity_set(
rtos_qspi_flash_t *ctx,
uint32_t op_core_mask);
/**
* Initializes an RTOS QSPI flash driver instance.
* This must only be called by the tile that owns the driver instance. It may be
* called either before or after starting the RTOS, but must be called before calling
* rtos_qspi_flash_start() or any of the core QSPI flash driver functions with this instance.
*
* This function will initialize a flash driver using lib_quadflash for
* all operations.
*
* \param ctx A pointer to the QSPI flash driver instance to initialize.
* \param clock_block The clock block to use for the qspi_io interface.
* \param cs_port The chip select port. MUST be a 1-bit port.
* \param sclk_port The SCLK port. MUST be a 1-bit port.
* \param sio_port The SIO port. MUST be a 4-bit port.
* \param spec A pointer to the flash part specification.
* This may be set to NULL to use the XTC default
*/
void rtos_qspi_flash_init(
rtos_qspi_flash_t *ctx,
xclock_t clock_block,
port_t cs_port,
port_t sclk_port,
port_t sio_port,
fl_QuadDeviceSpec *spec);
/**
* Initializes an RTOS QSPI flash driver instance.
* This must only be called by the tile that owns the driver instance. It may be
* called either before or after starting the RTOS, but must be called before calling
* rtos_qspi_flash_start() or any of the core QSPI flash driver functions with this instance.
*
* This function will initialize a flash driver using lib_quadflash for
* erase and writes, and lib_qspi_fast_read for reads. If calibration
* fails the driver will enable lib_quadflash for reads and allow the
* application to decide what to do about the failed calibration. The
* status of the calibration can be checked at runtime by calling
* rtos_qspi_flash_calibration_valid_get().
*
* \param ctx A pointer to the QSPI flash driver instance to initialize.
* \param clock_block The clock block to use for the qspi_io interface.
* \param cs_port The chip select port. MUST be a 1-bit port.
* \param sclk_port The SCLK port. MUST be a 1-bit port.
* \param sio_port The SIO port. MUST be a 4-bit port.
* \param spec A pointer to the flash part specification.
* This may be set to NULL to use the XTC default
* \param read_mode The transfer mode to use for port reads.
* Invalid values will default to qspi_fast_flash_read_transfer_raw
* \param read_divide The divisor to use for QSPI SCLK.
* \param calibration_pattern_addr The address of the default calibration pattern.
* This driver requires the default calibration pattern
* supplied with lib_qspi_fast_read and does not support
* custom patterns.
*/
void rtos_qspi_flash_fast_read_init(
rtos_qspi_flash_t *ctx,
xclock_t clock_block,
port_t cs_port,
port_t sclk_port,
port_t sio_port,
fl_QuadDeviceSpec *spec,
uint8_t read_divide,
uint32_t calibration_pattern_addr);
/**@}*/
#endif /* RTOS_QSPI_FLASH_H_ */

View File

@@ -0,0 +1,10 @@
set(LIB_NAME lib_qspi_flash)
set(LIB_VERSION 0.0.1)
set(LIB_INCLUDES api)
set(LIB_DEPENDENT_MODULES "lib_logging(3.2.0)")
set(LIB_COMPILER_FLAGS -O3 -DREF_CLK_FREQ=100 -fasm-linenum -fcomment-asm)
list(APPEND LIB_COMPILER_FLAGS -DXASSERT_ENABLE_ASSERTIONS=0
-DXASSERT_ENABLE_DEBUG=0
-DXASSERT_ENABLE_LINE_NUMBERS=0)
XMOS_REGISTER_MODULE()

View File

@@ -0,0 +1,399 @@
// Copyright 2020-2023 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#define DEBUG_UNIT RTOS_QSPI_FLASH
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <xcore/assert.h>
#include <xcore/lock.h>
#include "rtos_qspi_flash.h"
#ifndef QSPI_FL_RETRY_DELAY_TICKS
#define QSPI_FL_RETRY_DELAY_TICKS 1000
#endif
#ifndef QSPI_FL_RETRY_ATTEMPT_CNT
#define QSPI_FL_RETRY_ATTEMPT_CNT 5
#endif
/* TODO, these will be removed once moved to the public API */
#define ERASE_CHIP 0xC7
extern void fl_int_read(
unsigned char cmd,
unsigned int address,
unsigned char * destination,
unsigned int num_bytes);
extern void fl_int_write(
unsigned char cmd,
unsigned int pageAddress,
const unsigned char data[],
unsigned int num_bytes);
extern void fl_int_sendSingleByteCommand(unsigned char cmd);
extern void fl_int_eraseSector(
unsigned char cmd,
unsigned int sectorAddress);
/* end TODO */
/* Library only supports 4096 sector size*/
#define QSPI_ERASE_TYPE_SIZE_LOG2 12
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define FLASH_OP_NONE 0
#define FLASH_OP_READ 1
#define FLASH_OP_WRITE 2
#define FLASH_OP_ERASE 3
#define FLASH_OP_READ_FAST_RAW 4
#define FLASH_OP_READ_FAST_NIBBLE_SWAP 5
#define FLASH_OP_LL_SETUP 6
extern unsigned __libc_hwlock;
typedef struct {
int op;
uint8_t *data;
unsigned address;
size_t len;
unsigned priority;
} qspi_flash_op_req_t;
/*
* Returns true if the spinlock is
* acquired, false if not available.
* NOT recursive.
*/
static bool spinlock_get(volatile int *lock)
{
bool ret;
lock_acquire(__libc_hwlock);
{
if (*lock == 0) {
*lock = 1;
ret = true;
} else {
ret = false;
}
}
lock_release(__libc_hwlock);
return ret;
}
/*
* Releases the lock. It MUST be owned
* by the caller.
*/
static void spinlock_release(volatile int *lock)
{
*lock = 0;
}
static void rtos_qspi_flash_fl_connect_with_retry(
rtos_qspi_flash_t *ctx)
{
if (fl_connectToDevice(&ctx->qspi_ports, &ctx->qspi_spec, 1) == 0) {
return;
} else {
int cnt = 0;
while (fl_connectToDevice(&ctx->qspi_ports, &ctx->qspi_spec, 1) != 0) {
delay_ticks(QSPI_FL_RETRY_DELAY_TICKS);
if (cnt++ >= QSPI_FL_RETRY_ATTEMPT_CNT) {
xassert(0); /* fl_connectToDevice failed too many times */
}
}
}
}
int rtos_qspi_flash_read_ll(
rtos_qspi_flash_t *ctx,
uint8_t *data,
unsigned address,
size_t len)
{
uint32_t irq_mask;
bool lock_acquired;
// printf("Asked to ll read %d bytes at address 0x%08x\n", len, address);
lock_acquired = spinlock_get(&ctx->spinlock);
while (lock_acquired && len > 0) {
size_t read_len = MIN(len, RTOS_QSPI_FLASH_READ_CHUNK_SIZE);
/*
* Cap the address at the size of the flash.
* This ensures the correction below will work if
* address is outside the flash's address space.
*/
if (address >= ctx->flash_size) {
address = ctx->flash_size;
}
if (address + read_len > ctx->flash_size) {
int original_len = read_len;
/* Don't read past the end of the flash */
read_len = ctx->flash_size - address;
/* Return all 0xFF bytes for addresses beyond the end of the flash */
memset(&data[read_len], 0xFF, original_len - read_len);
}
// printf("Read %d bytes from flash at address 0x%x\n", read_len, address);
fl_int_read(ctx->qspi_spec.readCommand, address, data, read_len);
len -= read_len;
data += read_len;
address += read_len;
}
if (lock_acquired) {
spinlock_release(&ctx->spinlock);
}
return lock_acquired ? 0 : -1;
}
static void read_op(
rtos_qspi_flash_t *ctx,
uint8_t *data,
unsigned address,
size_t len)
{
// printf("Asked to read %d bytes at address 0x%08x\n", len, address);
while (len > 0) {
size_t read_len = MIN(len, RTOS_QSPI_FLASH_READ_CHUNK_SIZE);
/*
* Cap the address at the size of the flash.
* This ensures the correction below will work if
* address is outside the flash's address space.
*/
if (address >= ctx->flash_size) {
address = ctx->flash_size;
}
if (address + read_len > ctx->flash_size) {
int original_len = read_len;
/* Don't read past the end of the flash */
read_len = ctx->flash_size - address;
/* Return all 0xFF bytes for addresses beyond the end of the flash */
memset(&data[read_len], 0xFF, original_len - read_len);
}
// printf("Read %d bytes from flash at address 0x%x\n", read_len, address);
fl_int_read(ctx->qspi_spec.readCommand, address, data, read_len);
len -= read_len;
data += read_len;
address += read_len;
}
}
static void while_busy(void)
{
bool busy;
do {
busy = fl_getBusyStatus();
} while (busy);
}
static void write_op(
rtos_qspi_flash_t *ctx,
const uint8_t *data,
unsigned address,
size_t len)
{
size_t bytes_left_to_write = len;
unsigned address_to_write = address;
const uint8_t *write_buf = data;
// printf("Asked to write %d bytes at address 0x%08x\n", bytes_left_to_write, address_to_write);
while (bytes_left_to_write > 0) {
/* compute the maximum number of bytes that can be written to the current page. */
size_t max_bytes_to_write = fl_getPageSize() - (address_to_write & (fl_getPageSize() - 1));
size_t bytes_to_write = bytes_left_to_write <= max_bytes_to_write ? bytes_left_to_write : max_bytes_to_write;
if (address_to_write >= ctx->flash_size) {
break; /* do not write past the end of the flash */
}
// printf("Write %d bytes from flash at address 0x%x\n", bytes_to_write, address_to_write);
fl_int_sendSingleByteCommand(ctx->qspi_spec.writeEnableCommand);
fl_int_write(ctx->qspi_spec.programPageCommand, address_to_write, write_buf, bytes_to_write);
while_busy();
fl_int_sendSingleByteCommand(ctx->qspi_spec.writeDisableCommand);
bytes_left_to_write -= bytes_to_write;
write_buf += bytes_to_write;
address_to_write += bytes_to_write;
}
}
#define SECTORS_TO_BYTES(s, ss_log2) ((s) << (ss_log2))
#define BYTES_TO_SECTORS(b, ss_log2) (((b) + (1 << ss_log2) - 1) >> (ss_log2))
#define SECTOR_TO_BYTE_ADDRESS(s, ss_log2) SECTORS_TO_BYTES(s, ss_log2)
#define BYTE_TO_SECTOR_ADDRESS(b, ss_log2) ((b) >> (ss_log2))
static void erase_op(
rtos_qspi_flash_t *ctx,
unsigned address,
size_t len)
{
size_t bytes_left_to_erase = len;
unsigned address_to_erase = address;
// printf("Asked to erase %d bytes at address 0x%08x\n", bytes_left_to_erase, address_to_erase);
if (address_to_erase == 0 && bytes_left_to_erase >= ctx->flash_size) {
/* Use chip erase when being asked to erase the entire address range */
// printf("Erasing entire chip\n");
fl_int_sendSingleByteCommand(ctx->qspi_spec.writeEnableCommand);
fl_int_sendSingleByteCommand(ERASE_CHIP);
while_busy();
fl_int_sendSingleByteCommand(ctx->qspi_spec.writeDisableCommand);
} else {
if (SECTOR_TO_BYTE_ADDRESS(BYTE_TO_SECTOR_ADDRESS(address_to_erase, QSPI_ERASE_TYPE_SIZE_LOG2), QSPI_ERASE_TYPE_SIZE_LOG2) != address_to_erase) {
/*
* If the provided starting erase address does not begin on the smallest
* sector boundary, then update the starting address and number of bytes
* to erase so that it does.
*/
unsigned sector_address;
sector_address = BYTE_TO_SECTOR_ADDRESS(address_to_erase, QSPI_ERASE_TYPE_SIZE_LOG2);
bytes_left_to_erase += address_to_erase - SECTOR_TO_BYTE_ADDRESS(sector_address, QSPI_ERASE_TYPE_SIZE_LOG2);
address_to_erase = SECTOR_TO_BYTE_ADDRESS(sector_address, QSPI_ERASE_TYPE_SIZE_LOG2);
// printf("adjusted starting erase address to %d\n", address_to_erase);
}
while (bytes_left_to_erase > 0) {
int erase_length;
int erase_length_log2 = QSPI_ERASE_TYPE_SIZE_LOG2;
if (address_to_erase >= ctx->flash_size) {
break; /* do not erase past the end of the flash */
}
erase_length = 1 << erase_length_log2;
xassert(address_to_erase == SECTOR_TO_BYTE_ADDRESS(BYTE_TO_SECTOR_ADDRESS(address_to_erase, erase_length_log2), erase_length_log2));
// printf("Erasing %d bytes (%d) at byte address %d, sector %d\n", erase_length, bytes_left_to_erase, address_to_erase, BYTE_TO_SECTOR_ADDRESS(address_to_erase, erase_length_log2));
fl_int_sendSingleByteCommand(ctx->qspi_spec.writeEnableCommand);
fl_int_eraseSector(ctx->qspi_spec.sectorEraseCommand, address_to_erase);
while_busy();
fl_int_sendSingleByteCommand(ctx->qspi_spec.writeDisableCommand);
address_to_erase += erase_length;
bytes_left_to_erase -= erase_length < bytes_left_to_erase ? erase_length : bytes_left_to_erase;
}
}
// printf("Erasing complete\n");
}
__attribute__((fptrgroup("rtos_qspi_flash_read_fptr_grp")))
static void qspi_flash_local_read(
rtos_qspi_flash_t *ctx,
uint8_t *data,
unsigned address,
size_t len)
{
qspi_flash_op_req_t op = {
.op = FLASH_OP_READ,
.data = data,
.address = address,
.len = len
};
read_op(ctx, op.data, op.address, op.len);
}
__attribute__((fptrgroup("rtos_qspi_flash_write_fptr_grp")))
static void qspi_flash_local_write(
rtos_qspi_flash_t *ctx,
const uint8_t *data,
unsigned address,
size_t len)
{
qspi_flash_op_req_t op = {
.op = FLASH_OP_WRITE,
.address = address,
.len = len
};
write_op(ctx, data, op.address, op.len);
}
__attribute__((fptrgroup("rtos_qspi_flash_erase_fptr_grp")))
static void qspi_flash_local_erase(
rtos_qspi_flash_t *ctx,
unsigned address,
size_t len)
{
qspi_flash_op_req_t op = {
.op = FLASH_OP_ERASE,
.address = address,
.len = len
};
erase_op(ctx, op.address, op.len);
}
void rtos_qspi_flash_init(
rtos_qspi_flash_t *ctx,
xclock_t clock_block,
port_t cs_port,
port_t sclk_port,
port_t sio_port,
fl_QuadDeviceSpec *spec)
{
ctx->qspi_ports.qspiCS = cs_port;
ctx->qspi_ports.qspiSCLK = sclk_port;
ctx->qspi_ports.qspiSIO = sio_port;
ctx->qspi_ports.qspiClkblk = clock_block;
fl_QuadDeviceSpec default_spec = FL_QUADDEVICE_DEFAULT;
if (spec == NULL) {
memcpy(&ctx->qspi_spec, &default_spec, sizeof(fl_QuadDeviceSpec));
} else {
memcpy(&ctx->qspi_spec, spec, sizeof(fl_QuadDeviceSpec));
}
xassert(fl_connectToDevice(&ctx->qspi_ports, &ctx->qspi_spec, 1) == 0);
/* Copy the spec back in case one was provided which has params populated by sfdp */
xassert(fl_copySpec(&ctx->qspi_spec) == 0);
ctx->flash_size = fl_getFlashSize();
/* Driver currently only supports 4096 sector size */
xassert(rtos_qspi_flash_sector_size_get(ctx) == (1 << QSPI_ERASE_TYPE_SIZE_LOG2));
/* Enable quad flash */
xassert(fl_quadEnable() == 0);
ctx->calibration_valid = 0;
ctx->last_op = FLASH_OP_NONE;
ctx->read = qspi_flash_local_read;
ctx->write = qspi_flash_local_write;
ctx->erase = qspi_flash_local_erase;
}

View File

@@ -1,177 +1,177 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{84eacf4f-e405-4909-b440-a04a84a3f8c8}</ProjectGuid>
<RootNamespace>
</RootNamespace>
<SDKPath Condition="'$(SDKPath)' == ''">C:\Program Files\XMOS\tusbaudiosdk</SDKPath>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
<Import Project="$(SDKPath)\source\tusbaudioapi_inc\tusbaudioapi_inc_vs2022.vcxitems" Label="Shared" />
<Import Project="$(SDKPath)\source\libwn_min\_libwn_min_vs2022.vcxitems" Label="Shared" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>.\bin\$(Configuration)\$(PlatformName)\</OutDir>
<IntDir>$(Configuration)\$(PlatformName)_$(PlatformToolset)</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\bin\$(Configuration)\$(PlatformName)\</OutDir>
<IntDir>$(Configuration)\$(PlatformName)_$(PlatformToolset)</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>
</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_AMD64;_CONSOLE;_UNICODE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>.;.\Win;$(SDKPath)\source\shared;$(SDKPath)\source\inc;$(SDKPath)\source\libwn_min;$(SDKPath)\source\libwtl;$(SDKPath)\source\tusbaudioapi_inc</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>Async</ExceptionHandling>
<PrecompiledHeaderFile />
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<EnableUAC>false</EnableUAC>
<UACExecutionLevel />
<UACUIAccess />
<GenerateMapFile>true</GenerateMapFile>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>
</SDLCheck>
<PreprocessorDefinitions>_AMD64;_CONSOLE;_UNICODE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>.;.\Win;$(SDKPath)\source\shared;$(SDKPath)\source\inc;$(SDKPath)\source\libwn_min;$(SDKPath)\source\libwtl;$(SDKPath)\source\tusbaudioapi_inc</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>Async</ExceptionHandling>
<PrecompiledHeaderFile />
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<EnableUAC>false</EnableUAC>
<UACExecutionLevel />
<UACUIAccess />
<GenerateMapFile>true</GenerateMapFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="usb_mixer.h" />
<ClInclude Include="Win\global.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="mixer_app.cpp" />
<ClCompile Include="usb_mixer.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{84eacf4f-e405-4909-b440-a04a84a3f8c8}</ProjectGuid>
<RootNamespace>
</RootNamespace>
<SDKPath Condition="'$(SDKPath)' == ''">C:\Program Files\XMOS\tusbaudiosdk</SDKPath>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
<Import Project="$(SDKPath)\source\tusbaudioapi_inc\tusbaudioapi_inc_vs2022.vcxitems" Label="Shared" />
<Import Project="$(SDKPath)\source\libwn_min\_libwn_min_vs2022.vcxitems" Label="Shared" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>.\bin\$(Configuration)\$(PlatformName)\</OutDir>
<IntDir>$(Configuration)\$(PlatformName)_$(PlatformToolset)</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>.\bin\$(Configuration)\$(PlatformName)\</OutDir>
<IntDir>$(Configuration)\$(PlatformName)_$(PlatformToolset)</IntDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<SDLCheck>
</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_AMD64;_CONSOLE;_UNICODE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>.;.\Win;$(SDKPath)\source\shared;$(SDKPath)\source\inc;$(SDKPath)\source\libwn_min;$(SDKPath)\source\libwtl;$(SDKPath)\source\tusbaudioapi_inc</AdditionalIncludeDirectories>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>Async</ExceptionHandling>
<PrecompiledHeaderFile />
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<EnableUAC>false</EnableUAC>
<UACExecutionLevel />
<UACUIAccess />
<GenerateMapFile>true</GenerateMapFile>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>
</SDLCheck>
<PreprocessorDefinitions>_AMD64;_CONSOLE;_UNICODE;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<AdditionalIncludeDirectories>.;.\Win;$(SDKPath)\source\shared;$(SDKPath)\source\inc;$(SDKPath)\source\libwn_min;$(SDKPath)\source\libwtl;$(SDKPath)\source\tusbaudioapi_inc</AdditionalIncludeDirectories>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<ExceptionHandling>Async</ExceptionHandling>
<PrecompiledHeaderFile />
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>%(AdditionalDependencies)</AdditionalDependencies>
<EnableUAC>false</EnableUAC>
<UACExecutionLevel />
<UACUIAccess />
<GenerateMapFile>true</GenerateMapFile>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="usb_mixer.h" />
<ClInclude Include="Win\global.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="mixer_app.cpp" />
<ClCompile Include="usb_mixer.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@@ -1,33 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="usb_mixer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Win\global.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="mixer_app.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Win\usb_mixer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="usb_mixer.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Win\global.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="mixer_app.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Win\usb_mixer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup />
</Project>