.cargo | ||
fpga | ||
gdb_config | ||
openocd | ||
src | ||
.gitignore | ||
.pre-commit-config.yaml | ||
build.rs | ||
Cargo.lock | ||
Cargo.toml | ||
flake.lock | ||
flake.nix | ||
flash.py | ||
itm-cargo-lock.patch | ||
LICENSE | ||
memory.x | ||
README.md | ||
rust-toolchain.toml |
Humpback DDS
MQTT-controlled 4-channel DDS signal generator using Urukul, Humpback and STM32 NUCLEO.
Nix commands
Humpback-DDS firmware is packaged using the Nix 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:
nix develop
python fpga/fpga_config.py [--eem [0,1,2]]
cargo build --release
(For users who had completed the networking setup) Flash firmware onto STM32 NUCLEO-H743ZI2 using OpenOCD.
openocd -f openocd/openocd.cfg -f openocd/main.cfg
(For users who had completed the networking setup) Alternatively, an equivalent Nix command can also do the work.
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.
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
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.
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.
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.
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.
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.
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:
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
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
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
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
publish-mqtt Urukul/Control/Channel0/Attenuator "20 dB"
This sets the attenuation of the channel 0 attenuator to be 20 dB.
Urukul Clock Tree
-
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
publish-mqtt Urukul/Control/Clock/Frequency "100 MHz"
This sets the clock frequency of Urukul to be 100 MHz.
- Topic:
-
Clock Source
- Topic:
Urukul/Control/Clock/Source
- Message:
<clk_src>
- clk_src: Clock source of Urukul. It can only be
OSC
,MMCX
andSMA
.
- clk_src: Clock source of Urukul. It can only be
Example
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.)
- Topic:
-
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
publish-mqtt Urukul/Control/Clock/Division "4"
This divides the clock frequency of Urukul by a factor of 4.
- Topic:
-
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
publish-mqtt Urukul/Control/Clock "source: OSC, frequency: 100 MHz, division: 4"
This is identical to the 3 examples above.
- Topic:
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
publish-mqtt Urukul/Control/Chammel1/SystemClock "1 GHz"
This sets the system clock frequency of channel 1 to 1 GHz.
Single Tone Profile
-
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
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.
- Topic:
-
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
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.
- Topic:
-
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
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.
- Topic:
-
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
publish-mqtt Urukul/Control/Clock "frequency: 3 MHz, phase: 0.0 deg, amplitude: 0.5"
This is identical to the 3 examples above.
- Topic:
Switching DDS Profile
- Topic:
Urukul/Control/Profile
- Message:
<profile>
Example
publish-mqtt Urukul/Control/Profile "5"
This is selects profile 5 for all DDS channels.