├── .github
└── workflows
│ ├── docs.yml
│ └── main.yml
├── .gitignore
├── .gitmodules
├── .vscode
├── STM32H750x.svd
├── c_cpp_properties.json
├── launch.json
└── tasks.json
├── Examples
├── Blink
│ ├── Blink.cpp
│ └── Makefile
├── Ringmod
│ ├── Makefile
│ └── Ringmod.cpp
└── Volume
│ ├── Makefile
│ └── Volume.cpp
├── README.md
├── ci
├── build_dist.py
├── build_examples.py
├── build_libs.sh
├── copy_readme.sh
├── local_style_check.sh
└── rm_readme.sh
├── dist
├── Examples
│ ├── Blink.bin
│ ├── Ringmod.bin
│ └── Volume.bin
└── examples.json
├── docs
├── Doxyfile
├── DoxygenLayout.xml
├── extra
│ ├── doxygen-awesome-darkmode-toggle.js
│ ├── doxygen-awesome-sidebar-only-darkmode-toggle.css
│ ├── doxygen-awesome-sidebar-only.css
│ ├── doxygen-awesome.css
│ ├── footer.html
│ └── header.html
├── images
│ └── QB_Logo_Small-55x55.png
└── md
│ └── a1_Building the Examples.md
├── include
└── aurora.h
└── rebuild_all.sh
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: Documentation
2 | # Generates and Deploys doxygen docs
3 | on:
4 | push:
5 | branches: [ main ] # only gen docs for pushes to main
6 | paths:
7 | - 'include/*'
8 | - 'docs/*'
9 | - './README.md'
10 | workflow_dispatch:
11 |
12 | jobs:
13 | # creates a dist/documentation/* folder containing the html documentation
14 | deploy-local:
15 | permissions:
16 | contents: write
17 | checks: write
18 | pull-requests: write
19 | runs-on: ubuntu-latest
20 | steps:
21 | - uses: actions/checkout@v2
22 | - uses: mattnotmitt/doxygen-action@v1
23 | with:
24 | doxyfile-path: docs/Doxyfile
25 | - uses: EndBug/add-and-commit@v9
26 | with:
27 | message: 'Automated: commiting doxygen reference'
28 | add: dist/documentation
29 | env:
30 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
31 | - name: deploy web
32 | uses: peaceiris/actions-gh-pages@v3
33 | with:
34 | github_token: ${{ secrets.GITHUB_TOKEN }}
35 | publish_dir: ./dist/documentation/html
36 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | name: Build All
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 | steps:
13 | - uses: actions/checkout@v2
14 | with:
15 | submodules: 'recursive'
16 | - name: arm-none-eabi-gcc
17 | uses: fiam/arm-none-eabi-gcc@v1
18 | with:
19 | release: '9-2019-q4'
20 | - name: Build Libraries
21 | run: ./ci/build_libs.sh
22 | - name: setup python
23 | uses: actions/setup-python@v2
24 | with:
25 | python-version: 3.8
26 | - name: Build Examples
27 | run: python ./ci/build_examples.py
28 | - name: Create Distributable Binaries
29 | run: python ./ci/build_dist.py -ru
30 | - name: Deploy Dist
31 | uses: EndBug/add-and-commit@v4
32 | with:
33 | message: 'Automated: Committing Dist folder'
34 | env:
35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | build/
2 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "libDaisy"]
2 | path = libs/libDaisy
3 | url = https://github.com/electro-smith/libDaisy
4 | [submodule "DaisySP"]
5 | path = libs/DaisySP
6 | url = https://github.com/electro-smith/DaisySP
7 |
--------------------------------------------------------------------------------
/.vscode/c_cpp_properties.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "name": "Win32",
5 | // Edit to match your development environment if necessary
6 | "compilerPath": "C:/Program Files/DaisyToolchain/bin/arm-none-eabi-gcc.exe",
7 | "includePath": [
8 | "${workspaceFolder}/Examples/**",
9 | "${workspaceFolder}/include/**",
10 | "${workspaceFolder}/libs/libDaisy//**",
11 | "${workspaceFolder}/libs/DaisySP//**"
12 | ],
13 | "intelliSenseMode": "gcc-x64",
14 | "cStandard": "c11",
15 | "cppStandard": "c++17",
16 | "defines": [
17 | "DEBUG=1",
18 | "STM32H750xx"
19 | ],
20 | "windowsSdkVersion": "10.0.17763.0"
21 | },
22 | {
23 | "name": "Mac",
24 | // Edit to match your development environment if necessary
25 | "compilerPath": "/usr/bin/arm-none-eabi-gcc",
26 | "includePath": [
27 | "${workspaceFolder}/Examples/**",
28 | "${workspaceFolder}/include/**",
29 | "${workspaceFolder}/libs/libDaisy//**",
30 | "${workspaceFolder}/libs/DaisySP//**"
31 | ],
32 | "intelliSenseMode": "gcc-x64",
33 | "cStandard": "c11",
34 | "cppStandard": "c++17",
35 | "defines": [
36 | "DEBUG=1",
37 | "STM32H750xx"
38 | ]
39 | }
40 | ],
41 | "version": 4
42 | }
--------------------------------------------------------------------------------
/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | "configurations": [
3 | {
4 | "configFiles": [
5 | "interface/stlink.cfg",
6 | "target/stm32h7x.cfg"
7 | ],
8 | "cwd": "${workspaceFolder}",
9 | "debuggerArgs": [
10 | "-d",
11 | "${workspaceRoot}"
12 | ],
13 | // Here's where you can put the path to the program you want to debug:
14 | "executable": "${workspaceRoot}/Examples/Blink/build/Blink.elf",
15 | "interface": "swd",
16 | "name": "Cortex Debug",
17 | "openOCDLaunchCommands": [
18 | "init",
19 | "reset init",
20 | "gdb_breakpoint_override hard"
21 | ],
22 | //"preLaunchTask": "build_all_debug",
23 | "preRestartCommands": [
24 | "load",
25 | "enable breakpoint",
26 | "monitor reset"
27 | ],
28 | "request": "launch",
29 | "runToMain": true,
30 | "servertype": "openocd",
31 | "showDevDebugOutput": true,
32 | "svdFile": "${workspaceRoot}/.vscode/STM32H750x.svd",
33 | "type": "cortex-debug"
34 | }
35 | ],
36 | "version": "0.2.0"
37 | }
38 |
--------------------------------------------------------------------------------
/.vscode/tasks.json:
--------------------------------------------------------------------------------
1 | {
2 | "tasks": [
3 | {
4 | "label": "Build Libraries",
5 | "command": "./ci/build_libs.sh",
6 | "options": {
7 | "cwd": "${workspaceFolder}"
8 | },
9 | "problemMatcher": [],
10 | "type": "shell"
11 | },
12 | {
13 | "label": "Build Example - Blink",
14 | "command": "make",
15 | "options": {
16 | "cwd": "${workspaceFolder}/Examples/Blink"
17 | },
18 | "problemMatcher": [],
19 | "type": "shell"
20 | },
21 | {
22 | "label": "Build Example - Volume",
23 | "command": "make",
24 | "options": {
25 | "cwd": "${workspaceFolder}/Examples/Volume"
26 | },
27 | "problemMatcher": [],
28 | "type": "shell"
29 | },
30 | {
31 | "label": "Build Example - Ringmod",
32 | "command": "make",
33 | "options": {
34 | "cwd": "${workspaceFolder}/Examples/Ringmod"
35 | },
36 | "problemMatcher": [],
37 | "type": "shell"
38 | },
39 | {
40 | "label": "Build",
41 | "dependsOn": [
42 | "Build Example - Blink",
43 | "Build Example - Volume",
44 | "Build Example - Ringmod"
45 | ],
46 | "problemMatcher": [],
47 | "group": {
48 | "kind": "build",
49 | "isDefault": true
50 | }
51 | },
52 | {
53 | "label": "Clean Example - Blink",
54 | "command": "make clean",
55 | "options": {
56 | "cwd": "${workspaceFolder}/Examples/Blink"
57 | },
58 | "problemMatcher": [],
59 | "type": "shell"
60 | },
61 | {
62 | "label": "Clean Example - Volume",
63 | "command": "make clean",
64 | "options": {
65 | "cwd": "${workspaceFolder}/Examples/Volume"
66 | },
67 | "problemMatcher": [],
68 | "type": "shell"
69 | },
70 | {
71 | "label": "Clean Example - Ringmod",
72 | "command": "make clean",
73 | "options": {
74 | "cwd": "${workspaceFolder}/Examples/Ringmod"
75 | },
76 | "problemMatcher": [],
77 | "type": "shell"
78 | },
79 | {
80 | "label": "Clean",
81 | "dependsOn": [
82 | "Clean Example - Blink",
83 | "Clean Example - Volume",
84 | "Clean Example - Ringmod"
85 | ],
86 | "problemMatcher": [],
87 | }
88 | ],
89 | "version": "2.0.0"
90 | }
--------------------------------------------------------------------------------
/Examples/Blink/Blink.cpp:
--------------------------------------------------------------------------------
1 | /** Blink
2 | *
3 | * Demonstrates blinking of a single LED
4 | *
5 | * In this example, the Freeze LED will blink on/off
6 | * once every second.
7 | */
8 | #include "aurora.h"
9 |
10 | using namespace daisy;
11 | using namespace aurora;
12 |
13 | /** Our global hardware object */
14 | Hardware hw;
15 |
16 | int main(void)
17 | {
18 | /** Initialize the Hardware */
19 | hw.Init();
20 |
21 | /** Create a variable to hold the state of the LED */
22 | bool led_state = true;
23 |
24 | /** Infinite Loop */
25 | while (1)
26 | {
27 | /** Set the State of the LED */
28 | hw.SetLed(LED_FREEZE, 0.f, 0.f, led_state);
29 |
30 | /** Toggle the state */
31 | if (led_state)
32 | led_state = false;
33 | else
34 | led_state = true;
35 |
36 | /** Write all LED states to the hardware */
37 | hw.WriteLeds();
38 |
39 | /** Delay 500ms */
40 | System::Delay(500);
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Examples/Blink/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = Blink
3 |
4 | # Build Project for Daisy Bootloader
5 | APP_TYPE = BOOT_SRAM
6 |
7 | # Sources
8 | CPP_SOURCES = Blink.cpp
9 |
10 | # Path to the root of the Aurora-SDK
11 | # When building custom applications outside of this repo
12 | # update this to point to the Aurora-SDK/ folder
13 | AURORA_SDK_PATH = ../..
14 |
15 | # Location of Hardware Support File within the SDK
16 | C_INCLUDES += -I$(AURORA_SDK_PATH)/include/
17 |
18 | # Library Locations
19 | LIBDAISY_DIR = $(AURORA_SDK_PATH)/libs/libDaisy/
20 | DAISYSP_DIR = $(AURORA_SDK_PATH)/libs/DaisySP/
21 |
22 | # To DEBUG the project with an ST-Link Probe:
23 | # 1. Compile the program with the below lines uncommented
24 | # 2. Load the firmware via the USB drive
25 | # 3. Make sure your .vscode/launch.json points to the
26 | # build/*.elf for the desired program
27 | # 4. Navigate and run the "Cortex Debug" Run and Debug configuration
28 | # or simply press F5 in VS Code.
29 |
30 | # DEBUG = 1
31 | # OPT = -O0
32 |
33 | # Core location, and generic Makefile.
34 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
35 | include $(SYSTEM_FILES_DIR)/Makefile
36 |
--------------------------------------------------------------------------------
/Examples/Ringmod/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = Ringmod
3 |
4 | # Build Project for Daisy Bootloader
5 | APP_TYPE = BOOT_SRAM
6 |
7 | # Sources
8 | CPP_SOURCES = Ringmod.cpp
9 |
10 | # Path to the root of the Aurora-SDK
11 | # When building custom applications outside of this repo
12 | # update this to point to the Aurora-SDK/ folder
13 | AURORA_SDK_PATH = ../..
14 |
15 | # Location of Hardware Support File within the SDK
16 | C_INCLUDES += -I$(AURORA_SDK_PATH)/include/
17 |
18 | # Library Locations
19 | LIBDAISY_DIR = $(AURORA_SDK_PATH)/libs/libDaisy/
20 | DAISYSP_DIR = $(AURORA_SDK_PATH)/libs/DaisySP/
21 |
22 | # To DEBUG the project with an ST-Link Probe:
23 | # 1. Compile the program with the below lines uncommented
24 | # 2. Load the firmware via the USB drive
25 | # 3. Make sure your .vscode/launch.json points to the
26 | # build/*.elf for the desired program
27 | # 4. Navigate and run the "Cortex Debug" Run and Debug configuration
28 | # or simply press F5 in VS Code.
29 |
30 | # DEBUG = 1
31 | # OPT = -O0
32 |
33 | # Core location, and generic Makefile.
34 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
35 | include $(SYSTEM_FILES_DIR)/Makefile
36 |
--------------------------------------------------------------------------------
/Examples/Ringmod/Ringmod.cpp:
--------------------------------------------------------------------------------
1 | /** Ringmode
2 | *
3 | * Demonstrates generating a signal, to create a basic audio effect
4 | * with multiple controls.
5 | *
6 | * A simple sine wave oscillator is used as the modulator, while the audio
7 | * input is used as the carrier.
8 | *
9 | * The following controls are used:
10 | *
11 | * - Warp: adjusts the frequency of modulation
12 | * - Blur: adjusts the depth of modulation
13 | * - Mix: adjusts the blend between the dry signal, and the ring-modulated signal
14 | */
15 | #include "aurora.h"
16 | #include "daisysp.h"
17 |
18 | using namespace daisy;
19 | using namespace aurora;
20 | using namespace daisysp;
21 |
22 | Hardware hw;
23 | Oscillator osc;
24 |
25 | void AudioCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size)
26 | {
27 | /** This filters, and prepares all of the module's controls for us. */
28 | hw.ProcessAllControls();
29 |
30 | /** Assign our knobs to some controls */
31 | /** Modulator frequency in Hz */
32 | float freq = fmap(hw.GetKnobValue(KNOB_WARP), 10.0, 1500.0, Mapping::LOG);
33 | osc.SetFreq(freq);
34 |
35 | /** How much modulation */
36 | float depth = fmap(hw.GetKnobValue(KNOB_BLUR), 0.5, 1.0);
37 |
38 | /** Dry/Wet balance */
39 | float mix = hw.GetKnobValue(KNOB_MIX);
40 |
41 | for (size_t i = 0; i < size; i++)
42 | {
43 | /** Read our inputs */
44 | float dry_left = in[0][i];
45 | float dry_right = in[1][i];
46 |
47 | /** Generate the modulator signal */
48 | float mod_signal = osc.Process() * depth;
49 |
50 | /** Create our ring modulated signals by modulating the two */
51 | float wet_left = dry_left * mod_signal;
52 | float wet_right = dry_right * mod_signal;
53 |
54 | /** Now write the mix of the dry and wet together to the outputs */
55 | /** Left */
56 | out[0][i] = (dry_left * (1.f - mix)) + (wet_left * mix);
57 | /** Right */
58 | out[1][i] = (dry_right * (1.f - mix)) + (wet_right * mix);
59 | }
60 | }
61 |
62 | int main(void)
63 | {
64 | /** Initialize the Hardware */
65 | hw.Init();
66 |
67 | /** Initialize the Oscillator we'll use to modulate our signal */
68 | osc.Init(hw.AudioSampleRate());
69 | osc.SetWaveform(Oscillator::WAVE_SIN);
70 | osc.SetAmp(1.0);
71 |
72 |
73 | /** Start the audio engine calling the function defined above periodically */
74 | hw.StartAudio(AudioCallback);
75 |
76 | /** Infinite Loop */
77 | while (1)
78 | {
79 | }
80 | }
--------------------------------------------------------------------------------
/Examples/Volume/Makefile:
--------------------------------------------------------------------------------
1 | # Project Name
2 | TARGET = Volume
3 |
4 | # Build Project for Daisy Bootloader
5 | APP_TYPE = BOOT_SRAM
6 |
7 | # Sources
8 | CPP_SOURCES = Volume.cpp
9 |
10 | # Path to the root of the Aurora-SDK
11 | # When building custom applications outside of this repo
12 | # update this to point to the Aurora-SDK/ folder
13 | AURORA_SDK_PATH = ../..
14 |
15 | # Location of Hardware Support File within the SDK
16 | C_INCLUDES += -I$(AURORA_SDK_PATH)/include/
17 |
18 | # Library Locations
19 | LIBDAISY_DIR = $(AURORA_SDK_PATH)/libs/libDaisy/
20 | DAISYSP_DIR = $(AURORA_SDK_PATH)/libs/DaisySP/
21 |
22 | # To DEBUG the project with an ST-Link Probe:
23 | # 1. Compile the program with the below lines uncommented
24 | # 2. Load the firmware via the USB drive
25 | # 3. Make sure your .vscode/launch.json points to the
26 | # build/*.elf for the desired program
27 | # 4. Navigate and run the "Cortex Debug" Run and Debug configuration
28 | # or simply press F5 in VS Code.
29 |
30 | # DEBUG = 1
31 | # OPT = -O0
32 |
33 | # Core location, and generic Makefile.
34 | SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
35 | include $(SYSTEM_FILES_DIR)/Makefile
36 |
--------------------------------------------------------------------------------
/Examples/Volume/Volume.cpp:
--------------------------------------------------------------------------------
1 | /** Volume
2 | *
3 | * Demonstrates reading a knob to adjust the level of audio
4 | * passing through the module.
5 | *
6 | * The Mix knob is used to adjust the volume of the signal.
7 | */
8 | #include "aurora.h"
9 |
10 | using namespace daisy;
11 | using namespace aurora;
12 |
13 | /** Our global hardware object */
14 | Hardware hw;
15 |
16 | void AudioCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size)
17 | {
18 | /** This filters, and prepares all of the module's controls for us. */
19 | hw.ProcessAllControls();
20 |
21 | /** Read the Mix knob value into a variable called "volume". */
22 | float volume = hw.GetKnobValue(KNOB_MIX);
23 |
24 | /** Loop through each sample of audio */
25 | for (size_t i = 0; i < size; i++)
26 | {
27 | /** Now for both left and right channels of audio, we'll multiply the input
28 | * by the volume to turn down the output signal.
29 | *
30 | * With Mix all the way down, this will result in silence.
31 | * With Mix all the way up, the audio should pass through at the normal level.
32 | */
33 |
34 | /** Left Channel */
35 | out[0][i] = in[0][i] * volume;
36 |
37 | /** Right Channel */
38 | out[1][i] = in[1][i] * volume;
39 | }
40 | }
41 |
42 | int main(void)
43 | {
44 | /** Initialize the Hardware */
45 | hw.Init();
46 |
47 | /** Start the audio engine calling the function defined above periodically */
48 | hw.StartAudio(AudioCallback);
49 |
50 | /** Infinite Loop */
51 | while (1)
52 | {
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | [](https://github.com/Qu-Bit-Electronix/Aurora-SDK/actions/workflows/main.yml)
4 | [](https://Qu-Bit-Electronix.github.io/Aurora-SDK)
5 |
6 | Everything you need to start writing your own application for the Qu-Bit Aurora Hardware platform!
7 |
8 | Check out the [reference documentation](https://qu-bit-electronix.github.io/Aurora-SDK/) for the project.
9 |
10 | Below we'll cover some basic topics to get started writing your own code to run on the Aurora
11 |
12 | # Table of Contents
13 |
14 | * [Compiling the Examples](#compiling-the-examples)
15 | * [Installing the Toolchain](#installing-the-toolchain)
16 | * [Cloning the SDK](#cloning-the-sdk)
17 | * [Building the Libraries](#building-the-libraries)
18 | * [Building the Examples](#building-the-examples)
19 | * [Reading and Running Examples](#reading-and-running-examples)
20 | * [Blink](#blink)
21 | * [Volume](#volume)
22 | * [Ringmod](#ringmod)
23 | * [Going Further](#going-further)
24 | * [Copying and Modifying an Example](#copying-and-modifying-an-example)
25 | * [Creating Your Own Firmware Project](#creating-your-own-firmware-project)
26 | * [Sharing Firmware With the Community](#sharing-firmware-with-the-community)
27 |
28 | # Compiling the Examples
29 |
30 | To begin, let's get the development environment set up to start working with your Aurora!
31 |
32 | Overall, this process is pretty simple, regardless of what operating system you're using.
33 |
34 | ## Installing the Toolchain
35 |
36 | The "toolchain" is a bundle of tools used to take the source code, and turn it into a binary file that can load onto the Aurora (or any other Daisy) hardware.
37 |
38 | If you've already done some development with Daisy in the past, you should already be good to go, and can skip ahead to the next section.
39 |
40 | On any operating system, our recommended text editor is VS Code, but you can work in any environment you're comfortable with. That said, we will only cover the specifics of working with VS Code in this guide.
41 |
42 | ### Windows
43 |
44 | 1. Download, and run the [Daisy Toolchain for Windows installer](https://media-obsy-dev.fra1.digitaloceanspaces.com/installers/DaisyToolchain-1.0.0-win64.exe) from Qu-bit website.
45 | 2. Download, and run the [Git for Windows installer](https://git-scm.com/download/win).
46 |
47 | This installs the required tools to get up and running with daisy.
48 |
49 | There are some additional helper scripts that require python, but this is optional.
50 |
51 | On Windows, you can install python by downloading the latest from [python.org](https://www.python.org/downloads/).
52 |
53 | **Note**: The windows store version of python will not work.
54 |
55 | ### Mac OS
56 |
57 | 1. Download the [Daisy Toolchain for Mac OS installer](https://media-obsy-dev.fra1.digitaloceanspaces.com/installers/DaisyToolchain-macos-installer-x64-0.1.2.pkg) from the Qu-Bit website.
58 | 2. Unzip, and Double click, the `install.command` file contained within.
59 |
60 | There are some additional helper scripts that require python, but this is optional.
61 |
62 | Mac OS comes with python, but the latest version can be downloaded from [python.org](https://www.python.org/downloads/), or using homebrew.
63 |
64 | If during the steps below, you run into an error similar to the following:
65 |
66 | ```
67 | xcrun: error: invalid active developer path
68 | ```
69 |
70 | then you need to run the following to update, or install the xcode developer tools:
71 |
72 | ```
73 | xcode-select --install
74 | ```
75 |
76 | ## Cloning the SDK
77 |
78 |
79 |
80 | The Aurora-SDK is a github repo, and it uses a few libraries to provide access to the hardware, and bundles the [DaisySP](https://github.com/electro-smith/DaisySP) DSP library.
81 |
82 | To download the entire SDK with all of its libraries:
83 |
84 | First, open a terminal, and navigate to the desired location on your computer. For our purposes here we'll use the `Desktop` folder, but you may wish to use `Documents`, `Developer`, or some other folder of your choice.
85 |
86 | Now, paste the following command into the terminal and press enter:
87 |
88 | ```shell
89 | git clone https://github.com/qu-bit-electronix/Aurora-SDK --recurse-submodules
90 | ```
91 |
92 | Once its done you'll have an Aurora-SDK full of everything you need to start writing your own code.
93 |
94 | ## Building the Libraries
95 |
96 | The Aurora-SDK uses a few libraries to interface with the hardware, and provide a bunch of DSP that can be used within your projects. These need to be compiled before we can build any examples.
97 |
98 | The only time, other than after cloning the repo, that this needs to happen is when updating the libraries to a newer version.
99 |
100 | If you're using VS Code you can open the task menu by clicking: `Terminal->Run Task...` and selecting "Build Libraries" from the menu.
101 |
102 | This is the equivalent of running the following command in a terminal from the Aurora-SDK:
103 |
104 | ```shell
105 | ./ci/build_libs.sh
106 | ```
107 |
108 | ## Building the Examples
109 |
110 |
111 |
112 | Each example is a single C++ file, and a `Makefile`.
113 |
114 | If you're using VS Code, you can build all examples by running the build task by clicking: `Terminal->Run Build Task...`. The shortcut for this is `CTRL+SHIFT+B` on Windows, or `CMD+SHIFT+B` on Mac OS.
115 |
116 | Alternatively, using the same task menu as above, you can build individual examples. For example, the task, `Build Example - Blink` will build the Blink example.
117 |
118 | This is the equivalent of running the following command in a terminal from the specific Example's folder:
119 |
120 | ```shell
121 | make
122 | ```
123 |
124 | # Reading and Running Examples
125 |
126 | One of the best ways to see how stuff works is to try it out!
127 |
128 | In the `dist/Examples` folder is a precompiled version of each of the available examples, and the `Examples/` folder has the corresponding source code.
129 |
130 | Before we get into installing any tools or anything, let's take a moment to look over some of the basic examples, and see how to interact with the module hardware in C++ (it's easier than you might think)!
131 |
132 | To load one of the examples just drag the .bin file of your choice onto your USB drive, and power up the Aurora with it inserted.
133 |
134 | **Note**: In order to ensure that you're loading the desired program, you should have only one `.bin` file in the root directory of the USB drive. (you can keep as many as you want in folders, though!)
135 |
136 | The most up to date, official Aurora firmware can always be downloaded from [the Aurora product page](https://www.qubitelectronix.com/shop/aurora)
137 |
138 | ## Blink
139 |
140 |
141 |
142 | In this example, we're just periodically changing the state of an LED. No audio, no controls.
143 |
144 | Here, we can see a few things that will happen in every program:
145 |
146 | We always have a `Hardware` object, that's our connection to the module itself. Typically, we'll name it `hw` to keep it nice and short.
147 |
148 | We can use that to do things with the Hardware. For example, in this example, we change the state of an LED:
149 |
150 | ```cpp
151 | hw.SetLed(LED_FREEZE, 0.f, 0.f, led_state);
152 | ```
153 |
154 | where the arguments are the LED we want to change followed by values for the red, green, and blue components of the light.
155 |
156 | Next, we toggle that state by changing the variable.
157 |
158 | Then we tell the hardware to write all changes to the LED values to the actual hardware:
159 |
160 | ```cpp
161 | hw.WriteLeds();
162 | ```
163 |
164 | Finally, we tell tell everything to wait 500 milliseconds (or 0.5 seconds) before looping back to the top of the infinite loop:
165 |
166 | ```cpp
167 | System::Delay(500);
168 | ```
169 |
170 | Check out the [full example code here](https://github.com/Qu-Bit-Electronix/Aurora-SDK/blob/main/Examples/Blink/Blink.cpp)
171 |
172 | In more complex projects we'll want to avoid using delays, but we'll get into techniques for doing that later.
173 |
174 | ## Volume
175 |
176 |
177 |
178 | In this example, we're going to add two new things to what our previous example did: audio, and knobs!
179 |
180 | That's right, the most exciting eurorack concept ever invented -- a volume control.
181 |
182 | Just like in our last example, we're still going to create our `Hardware` object, and initialize it.
183 |
184 | However, now we're going to start up a new "callback" for handling audio.
185 |
186 | To define the the audio callback we write a function like this:
187 |
188 | ```cpp
189 | void AudioCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size)
190 | {
191 | }
192 | ```
193 |
194 | The function can have any name, but for clarity we'll simply call it `AudioCallback` within the example.
195 |
196 | The three arguments are:
197 |
198 | * in: real time stereo audio input from the hardware
199 | * out: real time stereo audio output from the hardware
200 | * size: the number of individual samples included in the buffers
201 |
202 | The audio default audio configuration is set up with an array of samples per channel, like this:
203 |
204 | ```cpp
205 | {
206 | { L0, L1, L2, . . ., LN },
207 | { R0, R1, R2, . . ., RN }
208 | }
209 | ```
210 |
211 | So using these arguments, we can loop over each sample of audio, individually.
212 |
213 | For example, just passing the input straight through to the output:
214 |
215 | ```cpp
216 | for (size_t i = 0; i < size; i++)
217 | {
218 | /** Left channel */
219 | out[0][i] = in[0][i];
220 | /** Right channel */
221 | out[1][i] = in[1][i];
222 | }
223 | ```
224 |
225 | We want **control**, through. So what we want to do is use the value of one of the knobs to scale that level.
226 |
227 | Thie is pretty easy to setup. Within the callback, we'll want to process all of our controls, and then we can simply assign one of them to a variable called, "volume".
228 |
229 | Here we'll use the mix knob to get a 0-1 value.
230 |
231 | ```cpp
232 | void AudioCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size)
233 | {
234 | hw.ProcessAllControls();
235 | float volume = hw.GetKnobValue(KNOB_MIX);
236 | }
237 | ```
238 |
239 | Knobs and CVs are handled separately to allow for more complex user interfaces, but there is an equivalent `GetCvValue` function that works in the same way.
240 |
241 | Within the `for` loop, we can scale the input by this amount to control the volume of our signal.
242 |
243 | In total, we now have the following Audio Callback:
244 |
245 | ```cpp
246 | void AudioCallback(AudioHandle::InputBuffer in, AudioHandle::OutputBuffer out, size_t size)
247 | {
248 | hw.ProcessAllControls();
249 | float volume = hw.GetKnobValue(KNOB_MIX);
250 | for (size_t i = 0; i < size; i++)
251 | {
252 | /** Left channel */
253 | out[0][i] = in[0][i] * volume;
254 | /** Right channel */
255 | out[1][i] = in[1][i] * volume;
256 | }
257 | }
258 | ```
259 |
260 | For a bit more detail on how audio works on the Daisy, check out the [Getting Started - Audio](https://electro-smith.github.io/libDaisy/md_doc_md__a3__getting__started__audio.html) guide.
261 |
262 | And check out the [full example code here](https://github.com/Qu-Bit-Electronix/Aurora-SDK/blob/main/Examples/Volume/Volume.cpp)
263 |
264 |
265 | ## Ringmod
266 |
267 |
268 |
269 | In this example, we're going to take what we learned in the Volume example, and make something a bit more exciting happen.
270 |
271 | A ring modulator is a form of bipolar amplitude modulation that can be easily made by multiplying one signal (like our input signal), and another signal.
272 |
273 | In this example we're going to break out a few things from the DaisySP DSP library.
274 |
275 | We'll also be using the `fmap` utility function to help us scale our control's 0-1 values to a more desirable range for our controls.
276 |
277 | For example, when setting our modulator frequency we'll want to have a logarthmic curve, and a frequency range from say, 10Hz to 1.5kHz.
278 | Using `fmap` we can save ourselves from figuring out how to do that with math.
279 |
280 | The fmap function take up to 4 arguments:
281 |
282 | 1. The 0-1 input to be converted (here we use `hw.GetKnobValue(KNOB_WARP)`)
283 | 2. The new minimum
284 | 3. The new maximum
285 | 4. The curve for the mapping function. If this isn't specified, it defaults to a normal, linear curve.
286 |
287 | ```cpp
288 | float freq = fmap(hw.GetKnobValue(KNOB_WARP), 10.0, 1500.0, Mapping::LOG);
289 | ```
290 |
291 | We'll also be using an `Oscillator` to generate a sine wave for our modulator.
292 |
293 | The `Oscillator`, like nearly every other DaisySP object, has two core functions: `Init` and `Process`.
294 |
295 | We want to initialize the oscillator, and set any particular parameters after initializing our Hardware object:
296 |
297 | ```cpp
298 | osc.Init(hw.AudioSampleRate());
299 | osc.SetWaveform(Oscillator::WAVE_SIN);
300 | osc.SetAmp(1.0);
301 | ```
302 |
303 | And then within our per-sample loop of the audio callback, we can render the oscillator's signal by calling it's `Process` function.
304 |
305 | ```cpp
306 | for (size_t i = 0; i < size; i++) {
307 | float signal = osc.Process();
308 | }
309 | ```
310 |
311 | To do the actual ring modulation effect, we'll multiply that signal by our input signal.
312 |
313 | Check out the [full example code here](https://github.com/Qu-Bit-Electronix/Aurora-SDK/blob/main/Examples/Ringmod/Ringmod.cpp)
314 |
315 | # Going Further
316 |
317 | Now that we can compile the provided examples, let's look at where we might want to go from here.
318 |
319 | ## Copying and Modifying an Example
320 |
321 | A great starting point is to copy one of the existing examples, and making modifications.
322 |
323 | For example, a good first modification to any of the existing examples would be to add the corresponding CV input to one of the knob controls.
324 |
325 | Since the examples are only a pair of files each, all you really need to do is Copy/Paste the folder and change the name.
326 |
327 | In the `Makefile` you'll want to:
328 |
329 | * update the `TARGET` name (on line 2)
330 | * and the `CPP_SOURCES` filename (on line 8) if you change the cpp file name.
331 |
332 | To build your new file you'll either need to edit the `.vscode/tasks.json` file (copying the entry for "Build Example - X" to your new folder name), or to run the `make` command directly from the terminal
333 |
334 | ## Creating Your Own Firmware Project
335 |
336 | Once you've dabbled a bit, and want to make your own custom firmware for yourself (or to share with the community), you can set some stuff up to start making your own folders.
337 |
338 | If you're keeping your new project in the `Examples` folder you won't have to change much other than what was mentioned above.
339 |
340 | However, if you want to have a dedicated folder (perhaps a github repo of your own) to keep your project, you may want to have your source files _outside_ of the Aurora-SDK folder.
341 |
342 | In this situation, the only other thing you'll want to update is the `AURORA_SDK` path (line 13) of the Makefile to point to a copy of the Aurora-SDK somewhere on your comptuer. This path can be relative, or absolute.
343 |
344 | If you're making you're making your project a github repo. You can add the SDK to your own repo as a submodule using:
345 |
346 | ```shell
347 | git submodule add https://github.com/qu-bit-electronix/Aurora-SDK
348 | ```
349 |
350 | and initialize it with:
351 |
352 | ```shell
353 | git submodule update --init
354 | ```
355 |
356 | ## Sharing Firmware With the Community
357 |
358 | Once you've got something cool you may want to share the binary, and/or the source code with the community!
359 |
360 | The [Qu-Bit Discord](https://discord.gg/BZmuBxcE) is a great place to share your project along with any details about how it works.
361 |
362 | Another great place to share your project is on [patchstorage](patchstorage.com).
363 |
364 | [
](https://discord.gg/BZmuBxcE)
365 |
--------------------------------------------------------------------------------
/ci/build_dist.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # Scans list of directories provided for examples containing a binary file,
4 | # and compiles a dist/ folder containing a matching hierarchy of binary files
5 | # and some metadata associated with them.
6 | #
7 | # This is primarily for providing easy access to pre-compiled examples for the compiler
8 | # Web Programmer application
9 | #
10 | # Examples must be compiled locally (or in the cloud service running this), otherwise
11 | # there won't be any binary files to grab from, and the script will skip over everything.
12 | #
13 | ##############################
14 | # Script Begin ###############
15 | ##############################
16 | import argparse
17 | import os
18 | import shutil
19 | import json
20 | import glob
21 |
22 |
23 | class Example(object):
24 | def __init__(self, name, ogdir):
25 | self.name = name
26 | self.description = "no desc available yet"
27 | self.url = 'https://raw.githubusercontent.com/electro-smith/'
28 | self.platform = ogdir.replace(os.path.sep, '_')
29 | self.url += 'DaisyExamples/master/' + ogdir.replace(os.path.sep, '/') + '/' + self.name + '/README.md'
30 | self.apath = os.path.abspath('/'.join((ogdir, name)))
31 | flist = glob.glob('{}/build/*.bin'.format(self.apath))
32 | if len(flist) > 0:
33 | self.buildpath = flist[0]
34 | else:
35 | self.buildpath = None
36 | self.destpath = './dist/{}/{}.bin'.format(self.platform, self.name)
37 |
38 | def Valid(self):
39 | if self.buildpath is not None:
40 | return True
41 | else:
42 | return False
43 |
44 | # packs necessary data and returns json object
45 | def DumpObject(self):
46 | myobj = {}
47 | myobj['name'] = self.name
48 | myobj['platform'] = self.platform
49 | myobj['filepath'] = self.destpath
50 | myobj['description'] = self.description
51 | myobj['url'] = self.url
52 | return myobj
53 |
54 | def DumpJson(self, filepointer):
55 | myobj = self.DumpObject()
56 | return json.dump(myobj, filepointer)
57 |
58 | def CopyToDeploy(self):
59 | if not os.path.isdir('./dist'):
60 | os.mkdir('./dist')
61 | if not os.path.isdir(os.path.dirname(self.destpath)):
62 | os.mkdir(os.path.dirname(self.destpath))
63 | if self.buildpath is not None:
64 | shutil.copy(self.buildpath, self.destpath)
65 |
66 |
67 | def run():
68 | # Parse arguments
69 | parser = argparse.ArgumentParser(
70 | description='generates the dist/ directory, containing binaries for all examples, and a json file containing simple metadata for each example.')
71 | parser.add_argument('directory_list', nargs='*',
72 | help='list of directories separated by spaces to use as inputs for the dist folder')
73 | parser.add_argument('-e', '--exclude_list', nargs='*',
74 | help='list of directories separated by spaces to ignore searching')
75 | parser.add_argument('-r', '--rewrite', action='store_true',
76 | help='When set, this will cause the script to completely clear the dist/ directory before executing.')
77 | parser.add_argument('-u', '--human-readable', action='store_true',
78 | help='When set, this will use indentation in the json output. By default the output will be a single line of text.')
79 | args = parser.parse_args()
80 |
81 | if not args.exclude_list:
82 | filter_dirs = ["libDaisy",
83 | "DaisySP",
84 | ".github",
85 | ".vscode",
86 | ".git",
87 | "ci",
88 | "cube",
89 | "dist",
90 | "utils",
91 | "stmlib",
92 | "libdaisy",
93 | "DaisyToolchain",
94 | "MyProjects"]
95 | else:
96 | filter_dirs = args.exclude_list
97 |
98 | # Prior to novemenber 2021 this would be a default-list, and was required.
99 | if not args.directory_list:
100 | # directories = [ 'seed', 'pod', 'patch', 'field', 'petal', 'versio', 'patch_sm' ]
101 | directories = list(
102 | filter(lambda x: x not in filter_dirs and os.path.isdir(x), os.listdir('.')))
103 | else:
104 | directories = list(args.directory_list)
105 |
106 | # navigate directories, and create examples to add to JSON, and dist/
107 | olist = []
108 | for d in directories:
109 | for root, dirs, files in os.walk(d):
110 | if ('Makefile') in files:
111 | ex_name = os.path.basename(root)
112 | ex_path = os.path.normpath(os.path.join(root, '..'))
113 | newobj = Example(ex_name, ex_path)
114 | olist.append(newobj)
115 |
116 | if args.rewrite and os.path.isdir('./dist'):
117 | shutil.rmtree('./dist')
118 |
119 | # Creating New Build Dir
120 | for example in olist:
121 | example.CopyToDeploy()
122 | jsonout = list(example.DumpObject() for example in olist if example.Valid())
123 |
124 | # Creating JSON file
125 | with open('./dist/examples.json', 'w') as f:
126 | if args.human_readable:
127 | json.dump(jsonout, f, indent=4)
128 | else:
129 | json.dump(jsonout, f)
130 |
131 | if __name__ == '__main__':
132 | run()
133 |
134 |
--------------------------------------------------------------------------------
/ci/build_examples.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | # recompiles all Make-based projects within the repository
4 | # excluding any that are located within the specified excluded
5 | # directory list
6 | #
7 | import sys
8 | import os
9 |
10 | filter_dirs = ["libDaisy",
11 | "DaisySP",
12 | ".github",
13 | ".vscode",
14 | ".git",
15 | "ci",
16 | "cube",
17 | "dist",
18 | "utils",
19 | "stmlib",
20 | "libdaisy",
21 | "DaisyToolchain",
22 | "libs",
23 | "MyProjects"]
24 |
25 | dirs_to_search = list(
26 | filter(lambda x: x not in filter_dirs and os.path.isdir(x), os.listdir('.')))
27 |
28 | # recursively go through each directory in dirs_to_search
29 | # and attempt to compile each example
30 | for dir in dirs_to_search:
31 | example_dirs = []
32 | for root, dirs, files in os.walk(dir):
33 | if 'Makefile' in files:
34 | example_dirs.append(root)
35 | cwd = os.path.abspath(os.getcwd())
36 | for ex in example_dirs:
37 | dest = os.path.join(cwd, ex)
38 | os.chdir(dest)
39 | os.system("echo Building: {}".format(ex))
40 | exit_code = os.system('make -s clean')
41 | exit_code = os.system('make -s')
42 | if exit_code != 0:
43 | os.chdir(cwd)
44 | sys.exit(1)
45 | os.chdir(cwd)
46 | # exit successfully
47 | print("done")
48 | sys.exit(0)
49 |
--------------------------------------------------------------------------------
/ci/build_libs.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | START_DIR=$PWD
4 | LIBDAISY_DIR=$PWD/libs/libDaisy
5 | DAISYSP_DIR=$PWD/libs/DaisySP
6 |
7 | echo "building libDaisy . . ."
8 | cd "$LIBDAISY_DIR" ; make -s clean ; make -j -s
9 | if [ $? -ne 0 ]
10 | then
11 | echo "Failed to compile libDaisy"
12 | exit 1
13 | fi
14 | echo "done."
15 |
16 | echo "building DaisySP . . ."
17 | cd "$DAISYSP_DIR" ; make -s clean ; make -j -s
18 | if [ $? -ne 0 ]
19 | then
20 | echo "Failed to compile DaisySP"
21 | exit 1
22 | fi
23 | echo "done."
24 |
25 |
--------------------------------------------------------------------------------
/ci/copy_readme.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | mkdir -p temp_docs
4 | cp README.md temp_docs/
--------------------------------------------------------------------------------
/ci/local_style_check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | # TODO:
4 | # having to do a separate line for each exclude is silly
5 | # and we should be able to run this with wildcards without it
6 | # going crazy.
7 |
8 | python ./utils/run-clang-format.py -r ./ \
9 | -e ./DaisySP -e ./libdaisy -e ./cube -e ./utils -e ./resources \
10 | -e ./seed/experimental -e ./patch/experimental \
11 | --extensions c,cpp,h
12 |
--------------------------------------------------------------------------------
/ci/rm_readme.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | rm -rf ./temp_docs
--------------------------------------------------------------------------------
/dist/Examples/Blink.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Qu-Bit-Electronix/Aurora-SDK/8b0378bd8f54d770a329a57250dcedb1f68fcbaa/dist/Examples/Blink.bin
--------------------------------------------------------------------------------
/dist/Examples/Ringmod.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Qu-Bit-Electronix/Aurora-SDK/8b0378bd8f54d770a329a57250dcedb1f68fcbaa/dist/Examples/Ringmod.bin
--------------------------------------------------------------------------------
/dist/Examples/Volume.bin:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Qu-Bit-Electronix/Aurora-SDK/8b0378bd8f54d770a329a57250dcedb1f68fcbaa/dist/Examples/Volume.bin
--------------------------------------------------------------------------------
/dist/examples.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "Ringmod",
4 | "platform": "Examples",
5 | "filepath": "./dist/Examples/Ringmod.bin",
6 | "description": "no desc available yet",
7 | "url": "https://raw.githubusercontent.com/electro-smith/DaisyExamples/master/Examples/Ringmod/README.md"
8 | },
9 | {
10 | "name": "Blink",
11 | "platform": "Examples",
12 | "filepath": "./dist/Examples/Blink.bin",
13 | "description": "no desc available yet",
14 | "url": "https://raw.githubusercontent.com/electro-smith/DaisyExamples/master/Examples/Blink/README.md"
15 | },
16 | {
17 | "name": "Volume",
18 | "platform": "Examples",
19 | "filepath": "./dist/Examples/Volume.bin",
20 | "description": "no desc available yet",
21 | "url": "https://raw.githubusercontent.com/electro-smith/DaisyExamples/master/Examples/Volume/README.md"
22 | }
23 | ]
--------------------------------------------------------------------------------
/docs/DoxygenLayout.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
222 |
223 |
224 |
225 |
226 |
227 |
228 |
229 |
230 |
--------------------------------------------------------------------------------
/docs/extra/doxygen-awesome-darkmode-toggle.js:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | Doxygen Awesome
4 | https://github.com/jothepro/doxygen-awesome-css
5 |
6 | MIT License
7 |
8 | Copyright (c) 2021 jothepro
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 | */
29 |
30 | class DoxygenAwesomeDarkModeToggle extends HTMLElement {
31 | static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode"
32 | static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode"
33 |
34 | static _staticConstructor = function() {
35 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference
36 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
37 | // Update the color scheme when the browsers preference changes
38 | // without user interaction on the website.
39 | window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => {
40 | DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
41 | })
42 | // Update the color scheme when the tab is made visible again.
43 | // It is possible that the appearance was changed in another tab
44 | // while this tab was in the background.
45 | document.addEventListener("visibilitychange", visibilityState => {
46 | if (document.visibilityState === 'visible') {
47 | DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged()
48 | }
49 | });
50 | }()
51 |
52 | constructor() {
53 | super();
54 | this.onclick=this.toggleDarkMode
55 | }
56 |
57 | /**
58 | * @returns `true` for dark-mode, `false` for light-mode system preference
59 | */
60 | static get systemPreference() {
61 | return window.matchMedia('(prefers-color-scheme: dark)').matches
62 | }
63 |
64 | /**
65 | * @returns `true` for dark-mode, `false` for light-mode user preference
66 | */
67 | static get userPreference() {
68 | return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) ||
69 | (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey))
70 | }
71 |
72 | static set userPreference(userPreference) {
73 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference
74 | if(!userPreference) {
75 | if(DoxygenAwesomeDarkModeToggle.systemPreference) {
76 | localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true)
77 | } else {
78 | localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)
79 | }
80 | } else {
81 | if(!DoxygenAwesomeDarkModeToggle.systemPreference) {
82 | localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true)
83 | } else {
84 | localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)
85 | }
86 | }
87 | DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged()
88 | }
89 |
90 | static enableDarkMode(enable) {
91 | let head = document.getElementsByTagName('head')[0]
92 | if(enable) {
93 | document.documentElement.classList.add("dark-mode")
94 | document.documentElement.classList.remove("light-mode")
95 | } else {
96 | document.documentElement.classList.remove("dark-mode")
97 | document.documentElement.classList.add("light-mode")
98 | }
99 | }
100 |
101 | static onSystemPreferenceChanged() {
102 | DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference
103 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
104 | }
105 |
106 | static onUserPreferenceChanged() {
107 | DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled)
108 | }
109 |
110 | toggleDarkMode() {
111 | DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference
112 | }
113 | }
114 |
115 | customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle);
116 |
--------------------------------------------------------------------------------
/docs/extra/doxygen-awesome-sidebar-only-darkmode-toggle.css:
--------------------------------------------------------------------------------
1 |
2 | /**
3 |
4 | Doxygen Awesome
5 | https://github.com/jothepro/doxygen-awesome-css
6 |
7 | MIT License
8 |
9 | Copyright (c) 2021 jothepro
10 |
11 | Permission is hereby granted, free of charge, to any person obtaining a copy
12 | of this software and associated documentation files (the "Software"), to deal
13 | in the Software without restriction, including without limitation the rights
14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15 | copies of the Software, and to permit persons to whom the Software is
16 | furnished to do so, subject to the following conditions:
17 |
18 | The above copyright notice and this permission notice shall be included in all
19 | copies or substantial portions of the Software.
20 |
21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 | SOFTWARE.
28 |
29 | */
30 |
31 | @media screen and (min-width: 768px) {
32 |
33 | #MSearchBox {
34 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - var(--searchbar-height) - 1px);
35 | }
36 |
37 | #MSearchField {
38 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 66px - var(--searchbar-height));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/docs/extra/doxygen-awesome-sidebar-only.css:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | Doxygen Awesome
4 | https://github.com/jothepro/doxygen-awesome-css
5 |
6 | MIT License
7 |
8 | Copyright (c) 2021 jothepro
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 | */
29 |
30 | html {
31 | /* side nav width. MUST be = `TREEVIEW_WIDTH`.
32 | * Make sure it is wide enought to contain the page title (logo + title + version)
33 | */
34 | --side-nav-fixed-width: 340px;
35 | --menu-display: none;
36 |
37 | --top-height: 120px;
38 | }
39 |
40 |
41 | @media screen and (min-width: 768px) {
42 | html {
43 | --searchbar-background: var(--page-background-color);
44 | }
45 |
46 | #side-nav {
47 | min-width: var(--side-nav-fixed-width);
48 | max-width: var(--side-nav-fixed-width);
49 | top: var(--top-height);
50 | overflow: visible;
51 | }
52 |
53 | #nav-tree, #side-nav {
54 | height: calc(100vh - var(--top-height)) !important;
55 | }
56 |
57 | #nav-tree {
58 | padding: 0;
59 | }
60 |
61 | #top {
62 | display: block;
63 | border-bottom: none;
64 | height: var(--top-height);
65 | margin-bottom: calc(0px - var(--top-height));
66 | max-width: var(--side-nav-fixed-width);
67 | background: var(--side-nav-background);
68 | }
69 | #main-nav {
70 | float: left;
71 | padding-right: 0;
72 | }
73 |
74 | .ui-resizable-handle {
75 | cursor: default;
76 | width: 1px !important;
77 | box-shadow: 0 calc(-2 * var(--top-height)) 0 0 var(--separator-color);
78 | }
79 |
80 | #nav-path {
81 | position: fixed;
82 | right: 0;
83 | left: var(--side-nav-fixed-width);
84 | bottom: 0;
85 | width: auto;
86 | }
87 |
88 | #doc-content {
89 | height: calc(100vh - 31px) !important;
90 | padding-bottom: calc(3 * var(--spacing-large));
91 | padding-top: calc(var(--top-height) - 80px);
92 | box-sizing: border-box;
93 | margin-left: var(--side-nav-fixed-width) !important;
94 | }
95 |
96 | #MSearchBox {
97 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)));
98 | }
99 |
100 | #MSearchField {
101 | width: calc(var(--side-nav-fixed-width) - calc(2 * var(--spacing-medium)) - 65px);
102 | }
103 |
104 | #MSearchResultsWindow {
105 | left: var(--spacing-medium) !important;
106 | right: auto;
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/docs/extra/doxygen-awesome.css:
--------------------------------------------------------------------------------
1 | /**
2 |
3 | Doxygen Awesome
4 | https://github.com/jothepro/doxygen-awesome-css
5 |
6 | MIT License
7 |
8 | Copyright (c) 2021 jothepro
9 |
10 | Permission is hereby granted, free of charge, to any person obtaining a copy
11 | of this software and associated documentation files (the "Software"), to deal
12 | in the Software without restriction, including without limitation the rights
13 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 | copies of the Software, and to permit persons to whom the Software is
15 | furnished to do so, subject to the following conditions:
16 |
17 | The above copyright notice and this permission notice shall be included in all
18 | copies or substantial portions of the Software.
19 |
20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 | SOFTWARE.
27 |
28 | */
29 |
30 | html {
31 | /* primary theme color. This will affect the entire websites color scheme: links, arrows, labels, ... */
32 | --primary-color: #1779c4;
33 | --primary-dark-color: #00559f;
34 | --primary-light-color: #7aabd6;
35 | --primary-lighter-color: #cae1f1;
36 | --primary-lightest-color: #e9f1f8;
37 |
38 | /* page base colors */
39 | --page-background-color: white;
40 | --page-foreground-color: #2c3e50;
41 | --page-secondary-foreground-color: #67727e;
42 |
43 | /* color for all separators on the website: hr, borders, ... */
44 | --separator-color: #dedede;
45 |
46 | /* border radius for all rounded components. Will affect many components, like dropdowns, memitems, codeblocks, ... */
47 | --border-radius-large: 8px;
48 | --border-radius-small: 4px;
49 | --border-radius-medium: 6px;
50 |
51 | /* default spacings. Most compontest reference these values for spacing, to provide uniform spacing on the page. */
52 | --spacing-small: 5px;
53 | --spacing-medium: 10px;
54 | --spacing-large: 16px;
55 |
56 | /* default box shadow used for raising an element above the normal content. Used in dropdowns, Searchresult, ... */
57 | --box-shadow: 0 2px 10px 0 rgba(0,0,0,.1);
58 |
59 | --odd-color: rgba(0,0,0,.03);
60 |
61 | /* font-families. will affect all text on the website
62 | * font-family: the normal font for text, headlines, menus
63 | * font-family-monospace: used for preformatted text in memtitle, code, fragments
64 | */
65 | --font-family: -apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
66 | --font-family-monospace: source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace;
67 |
68 | /* font sizes */
69 | --page-font-size: 15.6px;
70 | --navigation-font-size: 14.4px;
71 | --code-font-size: 14.4px; /* affects code, fragment */
72 | --title-font-size: 22px;
73 |
74 | /* content text properties. These only affect the page content, not the navigation or any other ui elements */
75 | --content-line-height: 27px;
76 | /* The content is centered and constraint in it's width. To make the content fill the whole page, set the variable to auto.*/
77 | --content-maxwidth: 1000px;
78 |
79 | /* colors for various content boxes: @warning, @note, @deprecated @bug */
80 | --warning-color: #fca49b;
81 | --warning-color-dark: #b61825;
82 | --warning-color-darker: #75070f;
83 | --note-color: rgba(255,229,100,.3);
84 | --note-color-dark: #c39900;
85 | --note-color-darker: #8d7400;
86 | --deprecated-color: rgb(214, 216, 224);
87 | --deprecated-color-dark: #5b6269;
88 | --deprecated-color-darker: #43454a;
89 | --bug-color: rgb(246, 208, 178);
90 | --bug-color-dark: #a53a00;
91 | --bug-color-darker: #5b1d00;
92 | --invariant-color: #b7f8d0;
93 | --invariant-color-dark: #00ba44;
94 | --invariant-color-darker: #008622;
95 |
96 | /* blockquote colors */
97 | --blockquote-background: #f5f5f5;
98 | --blockquote-foreground: #727272;
99 |
100 | /* table colors */
101 | --tablehead-background: #f1f1f1;
102 | --tablehead-foreground: var(--page-foreground-color);
103 |
104 | /* menu-display: block | none
105 | * Visibility of the top navigation on screens >= 768px. On smaller screen the menu is always visible.
106 | * `GENERATE_TREEVIEW` MUST be enabled!
107 | */
108 | --menu-display: block;
109 |
110 | --menu-focus-foreground: var(--page-background-color);
111 | --menu-focus-background: var(--primary-color);
112 | --menu-selected-background: rgba(0,0,0,.05);
113 |
114 |
115 | --header-background: var(--page-background-color);
116 | --header-foreground: var(--page-foreground-color);
117 |
118 | /* searchbar colors */
119 | --searchbar-background: var(--side-nav-background);
120 | --searchbar-foreground: var(--page-foreground-color);
121 |
122 | /* searchbar size
123 | * (`searchbar-width` is only applied on screens >= 768px.
124 | * on smaller screens the searchbar will always fill the entire screen width) */
125 | --searchbar-height: 33px;
126 | --searchbar-width: 210px;
127 |
128 | /* code block colors */
129 | --code-background: #f5f5f5;
130 | --code-foreground: var(--page-foreground-color);
131 |
132 | /* fragment colors */
133 | --fragment-background: #282c34;
134 | --fragment-foreground: #ffffff;
135 | --fragment-keyword: #cc99cd;
136 | --fragment-keywordtype: #ab99cd;
137 | --fragment-keywordflow: #e08000;
138 | --fragment-token: #7ec699;
139 | --fragment-comment: #999999;
140 | --fragment-link: #98c0e3;
141 | --fragment-preprocessor: #65cabe;
142 | --fragment-linenumber-color: #cccccc;
143 | --fragment-linenumber-background: #35393c;
144 | --fragment-linenumber-border: #1f1f1f;
145 | --fragment-lineheight: 20px;
146 |
147 | /* sidebar navigation (treeview) colors */
148 | --side-nav-background: #fbfbfb;
149 | --side-nav-foreground: var(--page-foreground-color);
150 | --side-nav-arrow-opacity: 0.6;
151 | --side-nav-arrow-hover-opacity: 0.9;
152 |
153 | /* height of an item in any tree / collapsable table */
154 | --tree-item-height: 30px;
155 |
156 | --darkmode-toggle-button-icon: '☀️'
157 | }
158 |
159 | @media screen and (max-width: 767px) {
160 | html {
161 | --page-font-size: 16px;
162 | --navigation-font-size: 16px;
163 | --code-font-size: 15px; /* affects code, fragment */
164 | --title-font-size: 22px;
165 | }
166 | }
167 |
168 | @media (prefers-color-scheme: dark) {
169 | html:not(.light-mode) {
170 | color-scheme: dark;
171 |
172 | --primary-color: #1982d2;
173 | --primary-dark-color: #5ca8e2;
174 | --primary-light-color: #4779ac;
175 | --primary-lighter-color: #191e21;
176 | --primary-lightest-color: #191a1c;
177 |
178 | --box-shadow: 0 2px 10px 0 rgba(0,0,0,.35);
179 |
180 | --odd-color: rgba(0,0,0,.1);
181 |
182 | --menu-selected-background: rgba(0,0,0,.4);
183 |
184 | --page-background-color: #1C1D1F;
185 | --page-foreground-color: #d2dbde;
186 | --page-secondary-foreground-color: #859399;
187 | --separator-color: #000000;
188 | --side-nav-background: #252628;
189 |
190 | --code-background: #2a2c2f;
191 |
192 | --tablehead-background: #2a2c2f;
193 |
194 | --blockquote-background: #1f2022;
195 | --blockquote-foreground: #77848a;
196 |
197 | --warning-color: #b61825;
198 | --warning-color-dark: #510a02;
199 | --warning-color-darker: #f5b1aa;
200 | --note-color: rgb(255, 183, 0);
201 | --note-color-dark: #9f7300;
202 | --note-color-darker: #645b39;
203 | --deprecated-color: rgb(88, 90, 96);
204 | --deprecated-color-dark: #262e37;
205 | --deprecated-color-darker: #a0a5b0;
206 | --bug-color: rgb(248, 113, 0);
207 | --bug-color-dark: #812a00;
208 | --bug-color-darker: #ffd3be;
209 |
210 | --darkmode-toggle-button-icon: '🌛';
211 | }
212 | }
213 |
214 | /* dark mode variables are defined twice, to support both the dark-mode without and with doxygen-awesome-darkmode-toggle.js */
215 | html.dark-mode {
216 | color-scheme: dark;
217 |
218 | --primary-color: #1982d2;
219 | --primary-dark-color: #5ca8e2;
220 | --primary-light-color: #4779ac;
221 | --primary-lighter-color: #191e21;
222 | --primary-lightest-color: #191a1c;
223 |
224 | --box-shadow: 0 2px 10px 0 rgba(0,0,0,.35);
225 |
226 | --odd-color: rgba(0,0,0,.1);
227 |
228 | --menu-selected-background: rgba(0,0,0,.4);
229 |
230 | --page-background-color: #1C1D1F;
231 | --page-foreground-color: #d2dbde;
232 | --page-secondary-foreground-color: #859399;
233 | --separator-color: #000000;
234 | --side-nav-background: #252628;
235 |
236 | --code-background: #2a2c2f;
237 |
238 | --tablehead-background: #2a2c2f;
239 |
240 | --blockquote-background: #1f2022;
241 | --blockquote-foreground: #77848a;
242 |
243 | --warning-color: #b61825;
244 | --warning-color-dark: #510a02;
245 | --warning-color-darker: #f5b1aa;
246 | --note-color: rgb(255, 183, 0);
247 | --note-color-dark: #9f7300;
248 | --note-color-darker: #645b39;
249 | --deprecated-color: rgb(88, 90, 96);
250 | --deprecated-color-dark: #262e37;
251 | --deprecated-color-darker: #a0a5b0;
252 | --bug-color: rgb(248, 113, 0);
253 | --bug-color-dark: #812a00;
254 | --bug-color-darker: #ffd3be;
255 |
256 | --darkmode-toggle-button-icon: '🌛';
257 | }
258 |
259 | body {
260 | color: var(--page-foreground-color);
261 | background-color: var(--page-background-color);
262 | font-size: var(--page-font-size);
263 | }
264 |
265 | body, table, div, p, dl, #nav-tree .label, .title, .sm-dox a, .sm-dox a:hover, .sm-dox a:focus, #projectname, .SelectItem, #MSearchField, .navpath li.navelem a, .navpath li.navelem a:hover {
266 | font-family: var(--font-family);
267 | }
268 |
269 | h1, h2, h3, h4, h5 {
270 | margin-top: .9em;
271 | font-weight: 600;
272 | line-height: initial;
273 | }
274 |
275 | p, div, table, dl {
276 | font-size: var(--page-font-size);
277 | }
278 |
279 | a:link, a:visited, a:hover, a:focus, a:active {
280 | color: var(--primary-color) !important;
281 | font-weight: 500;
282 | }
283 |
284 | /*
285 | Title and top navigation
286 | */
287 |
288 | #top {
289 | background: var(--header-background);
290 | border-bottom: 1px solid var(--separator-color);
291 | }
292 |
293 | @media screen and (min-width: 768px) {
294 | #top {
295 | display: flex;
296 | flex-wrap: wrap;
297 | justify-content: space-between;
298 | align-items: center;
299 | }
300 | }
301 |
302 | #main-nav {
303 | flex-grow: 5;
304 | padding: var(--spacing-small) var(--spacing-medium);
305 | }
306 |
307 | #titlearea {
308 | width: auto;
309 | padding: var(--spacing-medium) var(--spacing-large);
310 | background: none;
311 | color: var(--header-foreground);
312 | border-bottom: none;
313 | }
314 |
315 | @media screen and (max-width: 767px) {
316 | #titlearea {
317 | padding-bottom: var(--spacing-small);
318 | }
319 | }
320 |
321 | #titlearea table tbody tr {
322 | height: auto !important;
323 | }
324 |
325 | #projectname {
326 | font-size: var(--title-font-size);
327 | font-weight: 600;
328 | }
329 |
330 | #projectnumber {
331 | font-family: inherit;
332 | font-size: 60%;
333 | }
334 |
335 | #projectbrief {
336 | font-family: inherit;
337 | font-size: 80%;
338 | }
339 |
340 | #projectlogo {
341 | vertical-align: middle;
342 | }
343 |
344 | #projectlogo img {
345 | max-height: calc(var(--title-font-size) * 2);
346 | margin-right: var(--spacing-small);
347 | }
348 |
349 | .sm-dox, .tabs, .tabs2, .tabs3 {
350 | background: none;
351 | padding: 0;
352 | }
353 |
354 | .tabs, .tabs2, .tabs3 {
355 | border-bottom: 1px solid var(--separator-color);
356 | margin-bottom: -1px;
357 | }
358 |
359 | @media screen and (max-width: 767px) {
360 | .sm-dox a span.sub-arrow {
361 | background: var(--code-background);
362 | }
363 | }
364 |
365 | @media screen and (min-width: 768px) {
366 | .sm-dox li, .tablist li {
367 | display: var(--menu-display);
368 | }
369 |
370 | .sm-dox a span.sub-arrow {
371 | border-color: var(--header-foreground) transparent transparent transparent;
372 | }
373 |
374 | .sm-dox a:hover span.sub-arrow {
375 | border-color: var(--menu-focus-foreground) transparent transparent transparent;
376 | }
377 |
378 | .sm-dox ul a span.sub-arrow {
379 | border-color: transparent transparent transparent var(--page-foreground-color);
380 | }
381 |
382 | .sm-dox ul a:hover span.sub-arrow {
383 | border-color: transparent transparent transparent var(--menu-focus-foreground);
384 | }
385 | }
386 |
387 | .sm-dox ul {
388 | background: var(--page-background-color);
389 | box-shadow: var(--box-shadow);
390 | border: 1px solid var(--separator-color);
391 | border-radius: var(--border-radius-medium) !important;
392 | padding: var(--spacing-small);
393 | animation: ease-out 150ms slideInMenu;
394 | }
395 |
396 | @keyframes slideInMenu {
397 | from {
398 | opacity: 0;
399 | transform: translate(0px, -2px);
400 | }
401 |
402 | to {
403 | opacity: 1;
404 | transform: translate(0px, 0px);
405 | }
406 | }
407 |
408 | .sm-dox ul a {
409 | color: var(--page-foreground-color) !important;
410 | background: var(--page-background-color);
411 | font-size: var(--navigation-font-size);
412 | }
413 |
414 | .sm-dox>li>ul:after {
415 | border-bottom-color: var(--page-background-color) !important;
416 | }
417 |
418 | .sm-dox>li>ul:before {
419 | border-bottom-color: var(--separator-color) !important;
420 | }
421 |
422 | .sm-dox ul a:hover, .sm-dox ul a:active, .sm-dox ul a:focus {
423 | font-size: var(--navigation-font-size) !important;
424 | color: var(--menu-focus-foreground) !important;
425 | text-shadow: none;
426 | background-color: var(--menu-focus-background);
427 | border-radius: var(--border-radius-small) !important;
428 | }
429 |
430 | .sm-dox a, .sm-dox a:focus, .tablist li, .tablist li a, .tablist li.current a {
431 | text-shadow: none;
432 | background: transparent;
433 | background-image: none !important;
434 | color: var(--header-foreground) !important;
435 | font-weight: normal;
436 | font-size: var(--navigation-font-size);
437 | }
438 |
439 | .sm-dox a:focus {
440 | outline: auto;
441 | }
442 |
443 | .sm-dox a:hover, .sm-dox a:active, .tablist li a:hover {
444 | text-shadow: none;
445 | font-weight: normal;
446 | background: var(--menu-focus-background);
447 | color: var(--menu-focus-foreground) !important;
448 | border-radius: var(--border-radius-small) !important;
449 | font-size: var(--navigation-font-size);
450 | }
451 |
452 | .tablist li.current {
453 | border-radius: var(--border-radius-small);
454 | background: var(--menu-selected-background);
455 | }
456 |
457 | .tablist li {
458 | margin: var(--spacing-small) 0 var(--spacing-small) var(--spacing-small);
459 | }
460 |
461 | .tablist a {
462 | padding: 0 var(--spacing-large);
463 | }
464 |
465 |
466 | /*
467 | Search box
468 | */
469 |
470 | #MSearchBox {
471 | height: var(--searchbar-height);
472 | background: var(--searchbar-background);
473 | border-radius: var(--searchbar-height);
474 | border: 1px solid var(--separator-color);
475 | overflow: hidden;
476 | width: var(--searchbar-width);
477 | position: relative;
478 | box-shadow: none;
479 | display: block;
480 | margin-top: 0;
481 | }
482 |
483 | .left #MSearchSelect {
484 | left: 0;
485 | }
486 |
487 | .tabs .left #MSearchSelect {
488 | padding-left: 0;
489 | }
490 |
491 | .tabs #MSearchBox {
492 | position: absolute;
493 | right: var(--spacing-medium);
494 | }
495 |
496 | @media screen and (max-width: 767px) {
497 | .tabs #MSearchBox {
498 | position: relative;
499 | right: 0;
500 | margin-left: var(--spacing-medium);
501 | margin-top: 0;
502 | }
503 | }
504 |
505 | #MSearchSelectWindow, #MSearchResultsWindow {
506 | z-index: 9999;
507 | }
508 |
509 | #MSearchBox.MSearchBoxActive {
510 | border-color: var(--primary-color);
511 | box-shadow: inset 0 0 0 1px var(--primary-color);
512 | }
513 |
514 | #main-menu > li:last-child {
515 | margin-right: 0;
516 | }
517 |
518 | @media screen and (max-width: 767px) {
519 | #main-menu > li:last-child {
520 | height: 50px;
521 | }
522 | }
523 |
524 | #MSearchField {
525 | font-size: var(--navigation-font-size);
526 | height: calc(var(--searchbar-height) - 2px);
527 | background: transparent;
528 | width: calc(var(--searchbar-width) - 64px);
529 | }
530 |
531 | .MSearchBoxActive #MSearchField {
532 | color: var(--searchbar-foreground);
533 | }
534 |
535 | #MSearchSelect {
536 | top: calc(calc(var(--searchbar-height) / 2) - 11px);
537 | }
538 |
539 | .left #MSearchSelect {
540 | padding-left: 8px;
541 | }
542 |
543 | #MSearchBox span.left, #MSearchBox span.right {
544 | background: none;
545 | }
546 |
547 | #MSearchBox span.right {
548 | padding-top: calc(calc(var(--searchbar-height) / 2) - 12px);
549 | position: absolute;
550 | right: var(--spacing-small);
551 | }
552 |
553 | .tabs #MSearchBox span.right {
554 | top: calc(calc(var(--searchbar-height) / 2) - 12px);
555 | }
556 |
557 | @keyframes slideInSearchResults {
558 | from {
559 | opacity: 0;
560 | transform: translate(0, 15px);
561 | }
562 |
563 | to {
564 | opacity: 1;
565 | transform: translate(0, 20px);
566 | }
567 | }
568 |
569 | #MSearchResultsWindow {
570 | left: auto !important;
571 | right: var(--spacing-medium);
572 | border-radius: var(--border-radius-large);
573 | border: 1px solid var(--separator-color);
574 | transform: translate(0, 20px);
575 | box-shadow: var(--box-shadow);
576 | animation: ease-out 280ms slideInSearchResults;
577 | background: var(--page-background-color);
578 | }
579 |
580 | iframe#MSearchResults {
581 | margin: 4px;
582 | }
583 |
584 | iframe {
585 | color-scheme: normal;
586 | }
587 |
588 | @media (prefers-color-scheme: dark) {
589 | html:not(.light-mode) iframe#MSearchResults {
590 | filter: invert() hue-rotate(180deg);
591 | }
592 | }
593 |
594 | html.dark-mode iframe#MSearchResults {
595 | filter: invert() hue-rotate(180deg);
596 | }
597 |
598 | #MSearchSelectWindow {
599 | border: 1px solid var(--separator-color);
600 | border-radius: var(--border-radius-medium);
601 | box-shadow: var(--box-shadow);
602 | background: var(--page-background-color);
603 | }
604 |
605 | #MSearchSelectWindow a.SelectItem {
606 | font-size: var(--navigation-font-size);
607 | line-height: var(--content-line-height);
608 | margin: 0 var(--spacing-small);
609 | border-radius: var(--border-radius-small);
610 | color: var(--page-foreground-color) !important;
611 | font-weight: normal;
612 | }
613 |
614 | #MSearchSelectWindow a.SelectItem:hover {
615 | background: var(--menu-focus-background);
616 | color: var(--menu-focus-foreground) !important;
617 | }
618 |
619 | @media screen and (max-width: 767px) {
620 | #MSearchBox {
621 | margin-top: var(--spacing-medium);
622 | margin-bottom: var(--spacing-medium);
623 | width: calc(100vw - 30px);
624 | }
625 |
626 | #main-menu > li:last-child {
627 | float: none !important;
628 | }
629 |
630 | #MSearchField {
631 | width: calc(100vw - 110px);
632 | }
633 |
634 | @keyframes slideInSearchResultsMobile {
635 | from {
636 | opacity: 0;
637 | transform: translate(0, 15px);
638 | }
639 |
640 | to {
641 | opacity: 1;
642 | transform: translate(0, 20px);
643 | }
644 | }
645 |
646 | #MSearchResultsWindow {
647 | left: var(--spacing-medium) !important;
648 | right: var(--spacing-medium);
649 | overflow: auto;
650 | transform: translate(0, 20px);
651 | animation: ease-out 280ms slideInSearchResultsMobile;
652 | }
653 |
654 | /*
655 | * Overwrites for fixing the searchbox on mobile in doxygen 1.9.2
656 | */
657 | label.main-menu-btn ~ #searchBoxPos1 {
658 | top: 3px !important;
659 | right: 6px !important;
660 | left: 45px;
661 | display: flex;
662 | }
663 |
664 | label.main-menu-btn ~ #searchBoxPos1 > #MSearchBox {
665 | margin-top: 0;
666 | margin-bottom: 0;
667 | flex-grow: 2;
668 | float: left;
669 | }
670 | }
671 |
672 | /*
673 | Tree view
674 | */
675 |
676 | #side-nav {
677 | padding: 0 !important;
678 | background: var(--side-nav-background);
679 | }
680 |
681 | @media screen and (max-width: 767px) {
682 | #side-nav {
683 | display: none;
684 | }
685 |
686 | #doc-content {
687 | margin-left: 0 !important;
688 | height: auto !important;
689 | padding-bottom: calc(2 * var(--spacing-large));
690 | }
691 | }
692 |
693 | #nav-tree {
694 | background: transparent;
695 | }
696 |
697 | #nav-tree .label {
698 | font-size: var(--navigation-font-size);
699 | }
700 |
701 | #nav-tree .item {
702 | height: var(--tree-item-height);
703 | line-height: var(--tree-item-height);
704 | }
705 |
706 | #nav-sync {
707 | top: 12px !important;
708 | right: 12px;
709 | }
710 |
711 | #nav-tree .selected {
712 | text-shadow: none;
713 | background-image: none;
714 | background-color: transparent;
715 | box-shadow: inset 4px 0 0 0 var(--primary-color);
716 | }
717 |
718 | #nav-tree a {
719 | color: var(--side-nav-foreground) !important;
720 | font-weight: normal;
721 | }
722 |
723 | #nav-tree a:focus {
724 | outline-style: auto;
725 | }
726 |
727 | #nav-tree .arrow {
728 | opacity: var(--side-nav-arrow-opacity);
729 | }
730 |
731 | .arrow {
732 | color: inherit;
733 | cursor: pointer;
734 | font-size: 45%;
735 | vertical-align: middle;
736 | margin-right: 2px;
737 | font-family: serif;
738 | height: auto;
739 | text-align: right;
740 | }
741 |
742 | #nav-tree div.item:hover .arrow, #nav-tree a:focus .arrow {
743 | opacity: var(--side-nav-arrow-hover-opacity);
744 | }
745 |
746 | #nav-tree .selected a {
747 | color: var(--primary-color) !important;
748 | font-weight: bolder;
749 | font-weight: 600;
750 | }
751 |
752 | .ui-resizable-e {
753 | background: var(--separator-color);
754 | width: 1px;
755 | }
756 |
757 | /*
758 | Contents
759 | */
760 |
761 | div.header {
762 | border-bottom: 1px solid var(--separator-color);
763 | background-color: var(--page-background-color);
764 | background-image: none;
765 | }
766 |
767 | div.contents, div.header .title, div.header .summary {
768 | max-width: var(--content-maxwidth);
769 | }
770 |
771 | div.contents, div.header .title {
772 | line-height: initial;
773 | margin: calc(var(--spacing-medium) + .2em) auto var(--spacing-medium) auto;
774 | }
775 |
776 | div.header .summary {
777 | margin: var(--spacing-medium) auto 0 auto;
778 | }
779 |
780 | div.headertitle {
781 | padding: 0;
782 | }
783 |
784 | div.header .title {
785 | font-weight: 600;
786 | font-size: 210%;
787 | padding: var(--spacing-medium) var(--spacing-large);
788 | word-break: break-word;
789 | }
790 |
791 | div.header .summary {
792 | width: auto;
793 | display: block;
794 | float: none;
795 | padding: 0 var(--spacing-large);
796 | }
797 |
798 | td.memSeparator {
799 | border-color: var(--separator-color);
800 | }
801 |
802 | .mdescLeft, .mdescRight, .memItemLeft, .memItemRight, .memTemplItemLeft, .memTemplItemRight, .memTemplParams {
803 | background: var(--code-background);
804 | }
805 |
806 | .mdescRight {
807 | color: var(--page-secondary-foreground-color);
808 | }
809 |
810 | span.mlabel {
811 | background: var(--primary-color);
812 | border: none;
813 | padding: 4px 9px;
814 | border-radius: 12px;
815 | margin-right: var(--spacing-medium);
816 | }
817 |
818 | span.mlabel:last-of-type {
819 | margin-right: 2px;
820 | }
821 |
822 | div.contents {
823 | padding: 0 var(--spacing-large);
824 | }
825 |
826 | div.contents p, div.contents li {
827 | line-height: var(--content-line-height);
828 | }
829 |
830 | div.contents div.dyncontent {
831 | margin: var(--spacing-medium) 0;
832 | }
833 |
834 | @media (prefers-color-scheme: dark) {
835 | html:not(.light-mode) div.contents div.dyncontent img,
836 | html:not(.light-mode) div.contents center img,
837 | html:not(.light-mode) div.contents table img,
838 | html:not(.light-mode) div.contents div.dyncontent iframe,
839 | html:not(.light-mode) div.contents center iframe,
840 | html:not(.light-mode) div.contents table iframe {
841 | filter: hue-rotate(180deg) invert();
842 | }
843 | }
844 |
845 | html.dark-mode div.contents div.dyncontent img,
846 | html.dark-mode div.contents center img,
847 | html.dark-mode div.contents table img,
848 | html.dark-mode div.contents div.dyncontent iframe,
849 | html.dark-mode div.contents center iframe,
850 | html.dark-mode div.contents table iframe {
851 | filter: hue-rotate(180deg) invert();
852 | }
853 |
854 | h2.groupheader {
855 | border-bottom: 1px solid var(--separator-color);
856 | color: var(--page-foreground-color);
857 | }
858 |
859 | blockquote {
860 | padding: var(--spacing-small) var(--spacing-medium);
861 | background: var(--blockquote-background);
862 | color: var(--blockquote-foreground);
863 | border-left: 2px solid var(--blockquote-foreground);
864 | margin: 0;
865 | }
866 |
867 | blockquote p {
868 | margin: var(--spacing-small) 0 var(--spacing-medium) 0;
869 | }
870 | .paramname {
871 | font-weight: 600;
872 | color: var(--primary-dark-color);
873 | }
874 |
875 | .glow {
876 | text-shadow: 0 0 15px var(--primary-light-color) !important;
877 | }
878 |
879 | .alphachar a {
880 | color: var(--page-foreground-color);
881 | }
882 |
883 | /*
884 | Table of Contents
885 | */
886 |
887 | div.toc {
888 | background-color: var(--side-nav-background);
889 | border: 1px solid var(--separator-color);
890 | border-radius: var(--border-radius-medium);
891 | box-shadow: var(--box-shadow);
892 | padding: 0 var(--spacing-large);
893 | margin: 0 0 var(--spacing-medium) var(--spacing-medium);
894 | }
895 |
896 | div.toc h3 {
897 | color: var(--side-nav-foreground);
898 | font-size: var(--navigation-font-size);
899 | margin: var(--spacing-large) 0;
900 | }
901 |
902 | div.toc li {
903 | font-size: var(--navigation-font-size);
904 | padding: 0;
905 | background: none;
906 | }
907 |
908 | div.toc li:before {
909 | content: '↓';
910 | font-weight: 800;
911 | font-family: var(--font-family);
912 | margin-right: var(--spacing-small);
913 | color: var(--side-nav-foreground);
914 | opacity: .4;
915 | }
916 |
917 | div.toc ul li.level1 {
918 | margin: 0;
919 | }
920 |
921 | div.toc ul li.level2, div.toc ul li.level3 {
922 | margin-top: 0;
923 | }
924 |
925 |
926 | @media screen and (max-width: 767px) {
927 | div.toc {
928 | float: none;
929 | width: auto;
930 | margin: 0 0 var(--spacing-medium) 0;
931 | }
932 | }
933 |
934 | /*
935 | Code & Fragments
936 | */
937 |
938 | code, div.fragment, pre.fragment {
939 | border-radius: var(--border-radius-small);
940 | border: none;
941 | overflow: hidden;
942 | }
943 |
944 | code {
945 | display: inline;
946 | background: var(--code-background);
947 | color: var(--code-foreground);
948 | padding: 2px 6px;
949 | word-break: break-word;
950 | }
951 |
952 | div.fragment, pre.fragment {
953 | margin: var(--spacing-medium) 0;
954 | padding: 14px 16px;
955 | background: var(--fragment-background);
956 | color: var(--fragment-foreground);
957 | overflow-x: auto;
958 | }
959 |
960 | @media screen and (max-width: 767px) {
961 | div.fragment, pre.fragment {
962 | border-top-right-radius: 0;
963 | border-bottom-right-radius: 0;
964 | }
965 |
966 | .contents > div.fragment, .textblock > div.fragment, .textblock > pre.fragment {
967 | margin: var(--spacing-medium) calc(0px - var(--spacing-large));
968 | border-radius: 0;
969 | }
970 |
971 | .textblock li > .fragment {
972 | margin: var(--spacing-medium) calc(0px - var(--spacing-large));
973 | }
974 |
975 | .memdoc li > .fragment {
976 | margin: var(--spacing-medium) calc(0px - var(--spacing-medium));
977 | }
978 |
979 | .memdoc > div.fragment, .memdoc > pre.fragment, dl dd > div.fragment, dl dd pre.fragment {
980 | margin: var(--spacing-medium) calc(0px - var(--spacing-medium));
981 | border-radius: 0;
982 | }
983 | }
984 |
985 | code, code a, pre.fragment, div.fragment, div.fragment .line, div.fragment span, div.fragment .line a, div.fragment .line span {
986 | font-family: var(--font-family-monospace);
987 | font-size: var(--code-font-size) !important;
988 | }
989 |
990 | div.line:after {
991 | margin-right: var(--spacing-medium);
992 | }
993 |
994 | div.fragment .line, pre.fragment {
995 | white-space: pre;
996 | word-wrap: initial;
997 | line-height: var(--fragment-lineheight);
998 | }
999 |
1000 | div.fragment span.keyword {
1001 | color: var(--fragment-keyword);
1002 | }
1003 |
1004 | div.fragment span.keywordtype {
1005 | color: var(--fragment-keywordtype);
1006 | }
1007 |
1008 | div.fragment span.keywordflow {
1009 | color: var(--fragment-keywordflow);
1010 | }
1011 |
1012 | div.fragment span.stringliteral {
1013 | color: var(--fragment-token)
1014 | }
1015 |
1016 | div.fragment span.comment {
1017 | color: var(--fragment-comment);
1018 | }
1019 |
1020 | div.fragment a.code {
1021 | color: var(--fragment-link) !important;
1022 | }
1023 |
1024 | div.fragment span.preprocessor {
1025 | color: var(--fragment-preprocessor);
1026 | }
1027 |
1028 | div.fragment span.lineno {
1029 | display: inline-block;
1030 | width: 27px;
1031 | border-right: none;
1032 | background: var(--fragment-linenumber-background);
1033 | color: var(--fragment-linenumber-color);
1034 | }
1035 |
1036 | div.fragment span.lineno a {
1037 | background: none;
1038 | color: var(--fragment-link) !important;
1039 | }
1040 |
1041 | div.fragment .line:first-child .lineno {
1042 | box-shadow: -999999px 0px 0 999999px var(--fragment-linenumber-background), -999998px 0px 0 999999px var(--fragment-linenumber-border);
1043 | }
1044 |
1045 | /*
1046 | dl warning, attention, note, deprecated, bug, ...
1047 | */
1048 |
1049 | dl.warning, dl.attention, dl.note, dl.deprecated, dl.bug, dl.invariant, dl.pre {
1050 | padding: var(--spacing-medium);
1051 | margin: var(--spacing-medium) 0;
1052 | color: var(--page-background-color);
1053 | overflow: hidden;
1054 | margin-left: 0;
1055 | border-radius: var(--border-radius-small);
1056 | }
1057 |
1058 | dl.section dd {
1059 | margin-bottom: 2px;
1060 | }
1061 |
1062 | dl.warning, dl.attention {
1063 | background: var(--warning-color);
1064 | border-left: 8px solid var(--warning-color-dark);
1065 | color: var(--warning-color-darker);
1066 | }
1067 |
1068 | dl.warning dt, dl.attention dt {
1069 | color: var(--warning-color-dark);
1070 | }
1071 |
1072 | dl.note {
1073 | background: var(--note-color);
1074 | border-left: 8px solid var(--note-color-dark);
1075 | color: var(--note-color-darker);
1076 | }
1077 |
1078 | dl.note dt {
1079 | color: var(--note-color-dark);
1080 | }
1081 |
1082 | dl.bug {
1083 | background: var(--bug-color);
1084 | border-left: 8px solid var(--bug-color-dark);
1085 | color: var(--bug-color-darker);
1086 | }
1087 |
1088 | dl.bug dt a {
1089 | color: var(--bug-color-dark) !important;
1090 | }
1091 |
1092 | dl.deprecated {
1093 | background: var(--deprecated-color);
1094 | border-left: 8px solid var(--deprecated-color-dark);
1095 | color: var(--deprecated-color-darker);
1096 | }
1097 |
1098 | dl.deprecated dt a {
1099 | color: var(--deprecated-color-dark) !important;
1100 | }
1101 |
1102 | dl.section dd, dl.bug dd, dl.deprecated dd {
1103 | margin-inline-start: 0px;
1104 | }
1105 |
1106 | dl.invariant, dl.pre {
1107 | background: var(--invariant-color);
1108 | border-left: 8px solid var(--invariant-color-dark);
1109 | color: var(--invariant-color-darker);
1110 | }
1111 |
1112 | /*
1113 | memitem
1114 | */
1115 |
1116 | div.memdoc, div.memproto, h2.memtitle {
1117 | box-shadow: none;
1118 | background-image: none;
1119 | border: none;
1120 | }
1121 |
1122 | div.memdoc {
1123 | padding: 0 var(--spacing-medium);
1124 | background: var(--page-background-color);
1125 | }
1126 |
1127 | h2.memtitle, div.memitem {
1128 | border: 1px solid var(--separator-color);
1129 | }
1130 |
1131 | div.memproto, h2.memtitle {
1132 | background: var(--code-background);
1133 | text-shadow: none;
1134 | }
1135 |
1136 | h2.memtitle {
1137 | font-weight: 500;
1138 | font-family: monospace, fixed;
1139 | border-bottom: none;
1140 | border-top-left-radius: var(--border-radius-medium);
1141 | border-top-right-radius: var(--border-radius-medium);
1142 | word-break: break-all;
1143 | }
1144 |
1145 | a:target + h2.memtitle, a:target + h2.memtitle + div.memitem {
1146 | border-color: var(--primary-light-color);
1147 | }
1148 |
1149 | a:target + h2.memtitle {
1150 | box-shadow: -3px -3px 3px 0 var(--primary-lightest-color), 3px -3px 3px 0 var(--primary-lightest-color);
1151 | }
1152 |
1153 | a:target + h2.memtitle + div.memitem {
1154 | box-shadow: 0 0 10px 0 var(--primary-lighter-color);
1155 | }
1156 |
1157 | div.memitem {
1158 | border-top-right-radius: var(--border-radius-medium);
1159 | border-bottom-right-radius: var(--border-radius-medium);
1160 | border-bottom-left-radius: var(--border-radius-medium);
1161 | overflow: hidden;
1162 | display: block !important;
1163 | }
1164 |
1165 | div.memdoc {
1166 | border-radius: 0;
1167 | }
1168 |
1169 | div.memproto {
1170 | border-radius: 0 var(--border-radius-small) 0 0;
1171 | overflow: auto;
1172 | border-bottom: 1px solid var(--separator-color);
1173 | padding: var(--spacing-medium);
1174 | margin-bottom: -1px;
1175 | }
1176 |
1177 | div.memtitle {
1178 | border-top-right-radius: var(--border-radius-medium);
1179 | border-top-left-radius: var(--border-radius-medium);
1180 | }
1181 |
1182 | div.memproto table.memname {
1183 | font-family: monospace, fixed;
1184 | color: var(--page-foreground-color);
1185 | }
1186 |
1187 | table.mlabels, table.mlabels > tbody {
1188 | display: block;
1189 | }
1190 |
1191 | td.mlabels-left {
1192 | width: auto;
1193 | }
1194 |
1195 | table.mlabels > tbody > tr:first-child {
1196 | display: flex;
1197 | justify-content: space-between;
1198 | flex-wrap: wrap;
1199 | }
1200 |
1201 | .memname, .memitem span.mlabels {
1202 | margin: 0
1203 | }
1204 |
1205 | /*
1206 | reflist
1207 | */
1208 |
1209 | dl.reflist {
1210 | box-shadow: var(--box-shadow);
1211 | border-radius: var(--border-radius-medium);
1212 | border: 1px solid var(--separator-color);
1213 | overflow: hidden;
1214 | padding: 0;
1215 | }
1216 |
1217 |
1218 | dl.reflist dt, dl.reflist dd {
1219 | box-shadow: none;
1220 | text-shadow: none;
1221 | background-image: none;
1222 | border: none;
1223 | padding: 12px;
1224 | }
1225 |
1226 |
1227 | dl.reflist dt {
1228 | font-weight: 500;
1229 | border-radius: 0;
1230 | background: var(--code-background);
1231 | border-bottom: 1px solid var(--separator-color);
1232 | color: var(--page-foreground-color)
1233 | }
1234 |
1235 |
1236 | dl.reflist dd {
1237 | background: none;
1238 | }
1239 |
1240 | /*
1241 | Table
1242 | */
1243 |
1244 | table.markdownTable, table.fieldtable {
1245 | width: 100%;
1246 | border: 1px solid var(--separator-color);
1247 | margin: var(--spacing-medium) 0;
1248 | }
1249 |
1250 | table.fieldtable {
1251 | box-shadow: none;
1252 | border-radius: var(--border-radius-small);
1253 | }
1254 |
1255 | th.markdownTableHeadLeft, th.markdownTableHeadRight, th.markdownTableHeadCenter, th.markdownTableHeadNone {
1256 | background: var(--tablehead-background);
1257 | color: var(--tablehead-foreground);
1258 | font-weight: 600;
1259 | font-size: var(--page-font-size);
1260 | }
1261 |
1262 | table.markdownTable td, table.markdownTable th, table.fieldtable dt {
1263 | border: 1px solid var(--separator-color);
1264 | padding: var(--spacing-small) var(--spacing-medium);
1265 | }
1266 |
1267 | table.fieldtable th {
1268 | font-size: var(--page-font-size);
1269 | font-weight: 600;
1270 | background-image: none;
1271 | background-color: var(--tablehead-background);
1272 | color: var(--tablehead-foreground);
1273 | border-bottom: 1px solid var(--separator-color);
1274 | }
1275 |
1276 | .fieldtable td.fieldtype, .fieldtable td.fieldname {
1277 | border-bottom: 1px solid var(--separator-color);
1278 | border-right: 1px solid var(--separator-color);
1279 | }
1280 |
1281 | .fieldtable td.fielddoc {
1282 | border-bottom: 1px solid var(--separator-color);
1283 | }
1284 |
1285 | .memberdecls td.glow, .fieldtable tr.glow {
1286 | background-color: var(--primary-light-color);
1287 | box-shadow: 0 0 15px var(--primary-lighter-color);
1288 | }
1289 |
1290 | table.memberdecls {
1291 | display: block;
1292 | overflow-x: auto;
1293 | overflow-y: hidden;
1294 | }
1295 |
1296 |
1297 | /*
1298 | Horizontal Rule
1299 | */
1300 |
1301 | hr {
1302 | margin-top: var(--spacing-large);
1303 | margin-bottom: var(--spacing-large);
1304 | border-top:1px solid var(--separator-color);
1305 | }
1306 |
1307 | .contents hr {
1308 | box-shadow: var(--content-maxwidth) 0 0 0 var(--separator-color), calc(0px - var(--content-maxwidth)) 0 0 0 var(--separator-color);
1309 | }
1310 |
1311 | .contents img, .contents .center, .contents center {
1312 | max-width: 100%;
1313 | overflow: scroll;
1314 | }
1315 |
1316 | /*
1317 | Directories
1318 | */
1319 | div.directory {
1320 | border-top: 1px solid var(--separator-color);
1321 | border-bottom: 1px solid var(--separator-color);
1322 | width: auto;
1323 | }
1324 |
1325 | table.directory {
1326 | font-family: var(--font-family);
1327 | font-size: var(--page-font-size);
1328 | font-weight: normal;
1329 | }
1330 |
1331 | .directory td.entry {
1332 | padding: var(--spacing-small);
1333 | display: flex;
1334 | align-items: center;
1335 | }
1336 |
1337 | .directory tr.even {
1338 | background-color: var(--odd-color);
1339 | }
1340 |
1341 | .icona {
1342 | width: auto;
1343 | height: auto;
1344 | margin: 0 var(--spacing-small);
1345 | }
1346 |
1347 | .icon {
1348 | background: var(--primary-color);
1349 | width: 18px;
1350 | height: 18px;
1351 | line-height: 18px;
1352 | }
1353 |
1354 | .iconfopen, .icondoc, .iconfclosed {
1355 | background-position: center;
1356 | margin-bottom: 0;
1357 | }
1358 |
1359 | .icondoc {
1360 | filter: saturate(0.2);
1361 | }
1362 |
1363 | @media screen and (max-width: 767px) {
1364 | div.directory {
1365 | margin-left: calc(0px - var(--spacing-medium));
1366 | margin-right: calc(0px - var(--spacing-medium));
1367 | }
1368 | }
1369 |
1370 | @media (prefers-color-scheme: dark) {
1371 | html:not(.light-mode) .iconfopen, html:not(.light-mode) .iconfclosed {
1372 | filter: hue-rotate(180deg) invert();
1373 | }
1374 | }
1375 |
1376 | html.dark-mode .iconfopen, html.dark-mode .iconfclosed {
1377 | filter: hue-rotate(180deg) invert();
1378 | }
1379 |
1380 | /*
1381 | Class list
1382 | */
1383 |
1384 | .classindex dl.odd {
1385 | background: var(--odd-color);
1386 | border-radius: var(--border-radius-small);
1387 | }
1388 |
1389 | @media screen and (max-width: 767px) {
1390 | .classindex {
1391 | margin: 0 calc(0px - var(--spacing-small));
1392 | }
1393 | }
1394 |
1395 | /*
1396 | Footer and nav-path
1397 | */
1398 |
1399 | #nav-path {
1400 | margin-bottom: -1px;
1401 | width: 100%;
1402 | }
1403 |
1404 | #nav-path ul {
1405 | background-image: none;
1406 | background: var(--page-background-color);
1407 | border: none;
1408 | border-top: 1px solid var(--separator-color);
1409 | border-bottom: 1px solid var(--separator-color);
1410 | font-size: var(--navigation-font-size);
1411 | }
1412 |
1413 | img.footer {
1414 | width: 60px;
1415 | }
1416 |
1417 | .navpath li.footer {
1418 | color: var(--page-secondary-foreground-color);
1419 | }
1420 |
1421 | address.footer {
1422 | margin-bottom: var(--spacing-large);
1423 | }
1424 |
1425 | #nav-path li.navelem {
1426 | background-image: none;
1427 | display: flex;
1428 | align-items: center;
1429 | }
1430 |
1431 | .navpath li.navelem a {
1432 | text-shadow: none;
1433 | display: inline-block;
1434 | color: var(--primary-color) !important;
1435 | }
1436 |
1437 | .navpath li.navelem b {
1438 | color: var(--primary-dark-color);
1439 | font-weight: 500;
1440 | }
1441 |
1442 | li.navelem {
1443 | padding: 0;
1444 | margin-left: -8px;
1445 | }
1446 |
1447 | li.navelem:first-child {
1448 | margin-left: var(--spacing-large);
1449 | }
1450 |
1451 | li.navelem:first-child:before {
1452 | display: none;
1453 | }
1454 |
1455 | #nav-path li.navelem:after {
1456 | content: '';
1457 | border: 5px solid var(--page-background-color);
1458 | border-bottom-color: transparent;
1459 | border-right-color: transparent;
1460 | border-top-color: transparent;
1461 | transform: scaleY(4.2);
1462 | z-index: 10;
1463 | margin-left: 6px;
1464 | }
1465 |
1466 | #nav-path li.navelem:before {
1467 | content: '';
1468 | border: 5px solid var(--separator-color);
1469 | border-bottom-color: transparent;
1470 | border-right-color: transparent;
1471 | border-top-color: transparent;
1472 | transform: scaleY(3.2);
1473 | margin-right: var(--spacing-small);
1474 | }
1475 |
1476 | .navpath li.navelem a:hover {
1477 | color: var(--primary-color);
1478 | }
1479 |
1480 | /*
1481 | Optional Dark mode toggle button
1482 | */
1483 |
1484 | doxygen-awesome-dark-mode-toggle {
1485 | display: inline-block;
1486 | margin: 0 0 0 var(--spacing-small);
1487 | padding: 0;
1488 | width: var(--searchbar-height);
1489 | height: var(--searchbar-height);
1490 | background: none;
1491 | border: none;
1492 | font-size: 23px;
1493 | border-radius: var(--border-radius-medium);
1494 | vertical-align: middle;
1495 | text-align: center;
1496 | line-height: var(--searchbar-height);
1497 | }
1498 |
1499 | doxygen-awesome-dark-mode-toggle:hover {
1500 | background: var(--separator-color);
1501 | }
1502 |
1503 | doxygen-awesome-dark-mode-toggle:after {
1504 | content: var(--darkmode-toggle-button-icon)
1505 | }
1506 |
--------------------------------------------------------------------------------
/docs/extra/footer.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
15 |
16 |
30 |