MQTT-controlled 4-channel DDS signal generator using Urukul, Humpback and STM32 NUCLEO
Go to file
mwojcik 64b473129b deleted shell.nix as all scripts are ported already 2022-01-24 11:44:55 +08:00
.cargo scpi: add switch ctrl command 2020-09-03 17:41:27 +08:00
fpga fpga_config: fix tab/space 2020-09-25 14:29:33 +08:00
gdb_config scpi: adopt rust standard on result/option handling 2020-09-14 15:36:03 +08:00
openocd openocd: clean cfg 2020-09-25 11:11:08 +08:00
src dds: add ram control 2021-01-29 16:47:28 +08:00
.gitignore gitignore: add result 2022-01-24 11:31:47 +08:00
Cargo.lock cargo: update as SaiTLS 2021-01-29 16:46:07 +08:00
Cargo.toml cargo: set minimq version to 0.1.0 2022-01-19 16:21:31 +08:00
README.md readme: update CI links, build/dev instructions 2022-01-19 16:27:20 +08:00
build.rs rename migen to fpga 2020-09-25 14:26:28 +08:00
flake.lock flakes: add basic flake.nix 2022-01-19 15:00:09 +08:00
flake.nix flake: restore itm and custom openocd scripts 2022-01-24 11:31:31 +08:00
flash.py flash_gen: fix endianness 2020-12-18 17:44:38 +08:00
itm-cargo-lock.patch flake: restore itm and custom openocd scripts 2022-01-24 11:31:31 +08:00
memory.x cargo: update as SaiTLS 2021-01-29 16:46:07 +08:00

README.md

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
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

  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

    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

    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

    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

    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

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

    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

    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

    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

    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

publish-mqtt Urukul/Control/Profile "5"

This is selects profile 5 for all DDS channels.