273 lines
12 KiB
Markdown
273 lines
12 KiB
Markdown
# Humpback DDS
|
|
|
|
MQTT-controlled 4-channel DDS signal generator using Urukul, Humpback and STM32 NUCLEO.
|
|
|
|
- [Continuous Integration](https://nixbld.m-labs.hk/job/mcu/humpback-dds/humpback-dds)
|
|
- [Download latest firmware build](https://nixbld.m-labs.hk/job/mcu/humpback-dds/humpback-dds/latest/download-by-type/file/binary-dist)
|
|
|
|
## Nix commands
|
|
|
|
Humpback-DDS firmware is packaged using the [Nix](https://nixos.org) Flakes system. Install Nix 2.4+ and enable flakes by adding ``experimental-features = nix-command flakes`` to ``nix.conf`` (e.g. ``~/.config/nix/nix.conf``).
|
|
|
|
Once you have Flakes enabled, you can use ``nix build`` to build the firmware.
|
|
|
|
Alternatively, you can develop and build it within Nix shell:
|
|
```shell
|
|
nix develop
|
|
python fpga/fpga_config.py
|
|
cargo build --release
|
|
```
|
|
|
|
**(For users who had completed the [networking setup](##networking-setup-for-first-time-user))** Flash firmware onto STM32 NUCLEO-H743ZI2 using OpenOCD.
|
|
```shell
|
|
openocd -f openocd/openocd.cfg -f openocd/main.cfg
|
|
```
|
|
|
|
**(For users who had completed the [networking setup](##networking-setup-for-first-time-user))** Alternatively, an equivalent Nix command can also do the work.
|
|
```shell
|
|
openocd-flash
|
|
```
|
|
|
|
## Networking Setup for First-time User
|
|
Provide them to setup Humpback-DDS:
|
|
- IP Address of Humpback-DDS
|
|
- Bit length of the LAN prefix
|
|
- MAC Address of Humpback-DDS
|
|
- IP Address of MQTT broker
|
|
- Device name of Humpback-DDS
|
|
|
|
Note:
|
|
- IP/MAC address of Humpback-DDS should be unique inside a local area network.
|
|
- Device name should be unique among all Humpback-DDS connected to the same MQTT broker.
|
|
- The MQTT broker must accept TCP connection at port `1883`.
|
|
|
|
Use the following Nix command.
|
|
```shell
|
|
openocd-flash-customised <client_cidr_ip_addr> <mac_addr> <broker_addr> "<name>"
|
|
```
|
|
Parameters:
|
|
- client_cidr_ip_addr: IP address for the Humpback-DDS device, in CIDR notation
|
|
- mac_addr: MAC address for the Humpback-DDS device
|
|
- broker_addr: IP address for the MQTT broker
|
|
- name: Device name of the Humpback-DDS
|
|
|
|
### Example
|
|
```shell
|
|
openocd-flash-customised 192.168.1.200/24 AC:6F:7A:DE:D6:C8 192.168.1.125 "Urukul"
|
|
```
|
|
The device will be named `Urukul`.
|
|
It has `192.168.1.200` as IPv4 Address, inside a `/24` network, with `AC:6F:7A:DE:D6:C8` as MAC address.
|
|
It will connect to a MQTT broker at `192.168.1.125:1883`.
|
|
|
|
|
|
## MQTT Broker
|
|
Mosquitto is within the Nix package.
|
|
Starting a Mosquitto MQTT broker can be as simple as the following line.
|
|
```shell
|
|
mosquitto
|
|
```
|
|
The MQTT broker will be started locally, at port 1883.
|
|
|
|
To enable feedback from the device, subscribe to all subtopics under `Urukul/Feedback` on a separate terminal.
|
|
```shell
|
|
mosquitto_sub -h <broker ip address> -t Urukul/Feedback/#
|
|
```
|
|
Note that subscription to the feedback topic is completely optional.
|
|
|
|
|
|
## Publishing MQTT messages through Mosquitto
|
|
Controlling Humpback-DDS can be achieved by sending specific MQTT commands through Mosquitto. The device will listen to all publishes that are under the `Urukul/Control` or `/Urukul/Control` topic. A MQTT message can be published by the following command.
|
|
```shell
|
|
mosquitto_pub -h <broker ip address> -t <topic> -m <message>
|
|
```
|
|
For example, to publish a local MQTT broker, with the topic of `Foo/Bar` and `Baz` as the message, enter this command.
|
|
```shell
|
|
mosquitto_pub -h localhost -t Foo/Bar -m "Baz"
|
|
```
|
|
Note that MQTT topics are case-sensitive.
|
|
Alternatively, the following nix command provided by the shell simplify the syntax.
|
|
```shell
|
|
publish-mqtt <topic> <message>
|
|
```
|
|
This will send the MQTT message to a local MQTT broker at port 1883, with specified topic and message. The example above can be simplified into:
|
|
```shell
|
|
publish-mqtt Foo/Bar "baz"
|
|
```
|
|
|
|
## List of Commands
|
|
All currently supported commands are listed below.
|
|
**Note: The following table only lists the subtopic. To make a full topic, add `Urukul/Control/` in front of all subtopics.**
|
|
### Example: Full topic of Reset command
|
|
```shell
|
|
Urukul/Control/Reset
|
|
```
|
|
|
|
| Subtopic | Message | Functionality|
|
|
| --------------------------------------- | ------------------------------------------------------------------ | ---|
|
|
| `Reset` | | Reset the device|
|
|
| `ChannelX/Switch` | `<off/on>` | Turn off/on the RF switch at channel X.|
|
|
| `ChannelX/Attenuation` | `<atten> [dB]` | Set attenuation of channel X.|
|
|
| `Clock/Source` | `<clk_src>` | Select the clock source of Urukul.|
|
|
| `Clock/Frequency` | `<f_clk> [unit]` | Set the clock frequency of the clock source of Urukul.|
|
|
| `Clock/Source` | `<clk_div>` | Set the clock division of Urukul.|
|
|
| `Clock` | `frequency: <f_clk> [unit], source: <clk_src>, division: <clk_div>`| Setup the clock tree for Urukul.|
|
|
| `ChannelX/SystemClock` | `<f_sys_clk> [unit]` | Set the system clock frequency of channel X.|
|
|
| `ChannelX/ProfileY/Singletone/Frequency`| `<freq> [unit]` | Setup a single tone profile at channel X, profile Y, with frequency `<freq> [unit]`.|
|
|
| `ChannelX/ProfileY/Singletone/Amplitude`| `<ampl>` | Setup a single tone profile at channel X, profile Y, with amplitude factor `<ampl>`.|
|
|
| `ChannelX/ProfileY/Singletone/Phase` | `<phase> [deg]` | Setup a single tone profile at channel X, profile Y, with phase `<phase> [deg]`.|
|
|
| `ChannelX/ProfileY/Singletone` | `frequency: <freq> [unit], amplitude: <ampl>, phase: <phase>` | Setup a compelte single tone profile at channel X, profile Y.|
|
|
| `Profile` | `<pr_num>` | Switch to a DDS profile across all channels.|
|
|
|
|
## Reset the device
|
|
- Topic: `Urukul/Control/Reset`
|
|
- Message: (Don't care)
|
|
|
|
The `Reset` command resets the device. The effects are:
|
|
- Turn off all RF switches.
|
|
- Set attenuations to be 31.5 dB for all attenuators.
|
|
- Set Urukul clock source to be the internal oscillator, with 100MHz.
|
|
- Set Urukul clock divider to 4.
|
|
- Reset all 4 DDS chips.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Reset
|
|
```
|
|
This resets the device.
|
|
|
|
## RF Switch
|
|
- Topic: `Urukul/Control/Channel<ch_num>/Switch`
|
|
- ch_num: The channel number, from 0 to 3.
|
|
- Message: `<off/on>`
|
|
|
|
This command turns off/on an RF switch of a channel.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Channel0/Switch "on"
|
|
```
|
|
This turns on the channel 0 RF switch.
|
|
|
|
## Attenuator
|
|
- Topic: `Urukul/Control/Channel<ch_num>/Attenuator`
|
|
- ch_num: The channel number, from 0 to 3.
|
|
- Message: `<atten> [dB]`
|
|
- atten: Attenuation of the attenuator of the specified channel. The unit dB is optional. Valid attenuation is within [0, 31.5] (inclusive) in decibel.
|
|
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Channel0/Attenuator "20 dB"
|
|
```
|
|
This sets the attenuation of the channel 0 attenuator to be 20 dB.
|
|
|
|
## Urukul Clock Tree
|
|
1. Clock Frequency
|
|
- Topic: `Urukul/Control/Clock/Frequency`
|
|
- Message: `<f_clk> [unit]`
|
|
- f_clk: Clock frequency of the Urukul clock source.
|
|
- unit: **(Optional)** Unit of f_clk, supports `Hz`, `kHz`, `MHz`, `GHz`. `Hz` if unspecified.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Clock/Frequency "100 MHz"
|
|
```
|
|
This sets the clock frequency of Urukul to be 100 MHz.
|
|
|
|
2. Clock Source
|
|
- Topic: `Urukul/Control/Clock/Source`
|
|
- Message: `<clk_src>`
|
|
- clk_src: Clock source of Urukul. It can only be `OSC`, `MMCX` and `SMA`.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Clock/Source "OSC"
|
|
```
|
|
This sets the clock source of Urukul to be the internal oscillator.
|
|
(Note: The internal oscillator should have a frequency of 100MHz, though this command does not setup the clock frequency.)
|
|
|
|
3. Clock Frequency Division
|
|
- Topic: `Urukul/Control/Clock/Division`
|
|
- Message: `<clk_div>`
|
|
- clk_div: Clock frequency division of Urukul. It can only be 1, 2, or 4.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Clock/Division "4"
|
|
```
|
|
This divides the clock frequency of Urukul by a factor of 4.
|
|
|
|
4. Clock Overall Setup
|
|
- Topic: `Urukul/Control/Clock`
|
|
- Message: `frequency: <f_clk> [unit], source: <clk_src>, division: <clk_div>`
|
|
- f_clk, unit, clk_src, clk_div: Same as above.
|
|
- Argument can be permutated.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Clock "source: OSC, frequency: 100 MHz, division: 4"
|
|
```
|
|
This is identical to the 3 examples above.
|
|
|
|
## DDS System Clock Frequency
|
|
- Topic: `Channel<ch_num>/SystemClock`
|
|
- Message: `<f_sys_clk> [unit]`
|
|
- f_sys_clk: DDS System Clock frequency a channel.
|
|
- unit: **(Optional)** Unit of f_clk, supports `Hz`, `kHz`, `MHz`, `GHz`. `Hz` if unspecified.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Chammel1/SystemClock "1 GHz"
|
|
```
|
|
This sets the system clock frequency of channel 1 to 1 GHz.
|
|
|
|
## Single Tone Profile
|
|
1. Single Tone Frequency
|
|
- Topic: `Urukul/Control/Channel<ch_num>/Profile<pr_num>/Singletone/Frequency`
|
|
- ch_num: Channel number.
|
|
- pr_num: Profile number.
|
|
- Message: `<freq> [unit]`
|
|
- freq: Output frequency of the DDS single tone profile.
|
|
- unit: **(Optional)** Unit of freq, supports `Hz`, `kHz`, `MHz`, `GHz`. `Hz` if unspecified.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Channel1/Profile2/Singletone/Frequency "3 MHz"
|
|
```
|
|
This sets the output frequency of the single tone profile at channel 1, profile 2 to be 3 MHz.
|
|
|
|
2. Single Tone Amplitude
|
|
- Topic: `Urukul/Control/Channel<ch_num>/Profile<pr_num>/Singletone/Amplitude`
|
|
- ch_num: Channel number.
|
|
- pr_num: Profile number.
|
|
- Message: `<ampl>`
|
|
- ampl: Amplitude factor of the single tone profile. It ranges from 0 to 1 inclusive.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Channel1/Profile2/Singletone/Amplitude "0.5"
|
|
```
|
|
This sets the output amplitude factor of the single tone profile at channel 1, profile 2 to be 0.5.
|
|
|
|
3. Single Tone Phase
|
|
- Topic: `Urukul/Control/Channel<ch_num>/Profile<pr_num>/Singletone/Phase`
|
|
- ch_num: Channel number.
|
|
- pr_num: Profile number.
|
|
- Message: `<phase>`
|
|
- phase: Phase of the single tone profile. The unit is in degree.
|
|
- deg: **Optional** Specifies the unit of phase to be degree.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Channel1/Profile2/Singletone/Degree "0.0 deg"
|
|
```
|
|
This sets the phase of the single tone profile at channel 1, profile 2 to be 0 degree.
|
|
|
|
4. Single Tone Overall Setup
|
|
- Topic: `Urukul/Control/Channel<ch_num>/Profile<pr_num>/Singletone`
|
|
- Message: `frequency: <freq> [unit], amplitude: <ampl>, phase: <phase>`
|
|
- All parameters are the same as above commands.
|
|
- Argument can be permutated.
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Clock "frequency: 3 MHz, phase: 0.0 deg, amplitude: 0.5"
|
|
```
|
|
This is identical to the 3 examples above.
|
|
|
|
## Switching DDS Profile
|
|
- Topic: `Urukul/Control/Profile`
|
|
- Message: `<profile>`
|
|
### Example
|
|
```shell
|
|
publish-mqtt Urukul/Control/Profile "5"
|
|
```
|
|
This is selects profile 5 for all DDS channels. |