{ "cells": [ { "cell_type": "markdown", "id": "a2173a93", "metadata": {}, "source": [ "# Microwave Spin echo (IQ modulation w/ ADF4351 & ADL5375) \n", "In this example we connect a Red Pitaya 125-14 to an EVAL-CN0285-E1BZ containing a microwave synthesizer (ADF4351) & IQ modulator (ADL5375). We use DigitalIOs for the SPI configuration of the carrier and the RF outputs for fast quadrature modulation.\n", "\n", "Required hardware connection (see [README](https://github.com/RedPitaya/OpenLabCtrl/blob/main/README.md#ios--pin-mapping) for IO Names and Pin Mapping):\n", "* digital_io_2[0] --> CE\n", "* digital_io_2[1] --> PDRF\n", "* digital_io_2[2] <-- MUXOUT\n", "* digital_io_2[3] <-- LD\n", "* digital_io_3[0] --> CLK\n", "* digital_io_3[1] --> LE\n", "* digital_io_3[2] --> DATA\n", "\n", "The generated pulse sequence is a microwave spin echo (pi/2 + pi + pi/2) with variable delay in between.\n", "\n", "**NOTE**: \n", "* The following resistors of the EVAL-CN0285-E1BZ need to be **removed** (if populated): \n", " * Connectivity to on-board controller: R46, R51, R52, R53, R54, R55 R56, R57 \n", " * Pull-ups: R13, R14, R15, R16, R17, R18, R19\n", "* We use two AD8132 mounted on generic EVAL-FDA-1RZ-8 boards to perform the single-ended to differential pair conversion with common mode voltage of 0.5V." ] }, { "cell_type": "markdown", "id": "96f54070", "metadata": {}, "source": [ "### Imports" ] }, { "cell_type": "code", "execution_count": 9, "id": "607b9c7a", "metadata": {}, "outputs": [], "source": [ "import time \n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "from openlabctrl.device import Rp_125_14_Z7010\n", "from openlabctrl.sequence import IoSequence\n", "from openlabctrl.frame import ParamIoSyncFrame\n", "from openlabctrl.io.scope import ScopeSource" ] }, { "cell_type": "markdown", "id": "43fb4f95", "metadata": {}, "source": [ "### Device instances" ] }, { "cell_type": "code", "execution_count": 10, "id": "563af75c", "metadata": {}, "outputs": [], "source": [ "rp_0 = Rp_125_14_Z7010(ip=\"192.168.1.143\", label=\"rp_0\")" ] }, { "cell_type": "markdown", "id": "0436c2e7", "metadata": {}, "source": [ "### IO Sequences & IO Frames instances" ] }, { "cell_type": "code", "execution_count": 11, "id": "6e410a24", "metadata": {}, "outputs": [], "source": [ "seq = IoSequence(device_list=[rp_0])\n", "fr_rf_config = ParamIoSyncFrame(device_type=Rp_125_14_Z7010, trig=None)\n", "fr_mw_config = ParamIoSyncFrame(device_type=Rp_125_14_Z7010, trig=None)\n", "fr_pi_half = ParamIoSyncFrame(device_type=Rp_125_14_Z7010, trig=None)\n", "fr_pi = ParamIoSyncFrame(device_type=Rp_125_14_Z7010, trig=None)\n", "fr_wait = ParamIoSyncFrame(device_type=Rp_125_14_Z7010, trig=None)\n" ] }, { "cell_type": "markdown", "id": "5dbbfaed", "metadata": {}, "source": [ "### Parameter" ] }, { "cell_type": "code", "execution_count": null, "id": "e05c3608", "metadata": {}, "outputs": [], "source": [ "param_dict = {\n", " \"mw_config\" : {\n", " \"frequency_mhz\" : 106.1\n", " },\n", "\n", " \"rf_config\" : {\n", " \"freq_mhz\" : 0,\n", " \"offset_i\" : 0, #compensate for minor deviation of zero point (I modulation)\n", " \"offset_q\" : 0 #compensate for minor deviation of zero point (Q modulation)\n", " },\n", " \n", " \"pi_half\" : {\n", " \"width_samples\" : 20, \n", " \"ampl_i\" : 0.5,\n", " \"ampl_q\" : 0.5\n", " },\n", " \"pi\" : {\n", " \"width_samples\" : 40, \n", " \"ampl_i\" : 0.5,\n", " \"ampl_q\" : 0.5\n", " },\n", " \"wait\" : {\n", " \"wait_time_samples\" : 500\n", " }\n", "}" ] }, { "cell_type": "markdown", "id": "e5930f84", "metadata": {}, "source": [ "### Frame functions \n" ] }, { "cell_type": "code", "execution_count": null, "id": "0406fc31", "metadata": {}, "outputs": [], "source": [ "from devices import ADF4351\n", "\n", "#MW config\n", "def fr_func_mw_config(fr, param):\n", " fr.reset()\n", " mw = ADF4351(fr)\n", " mw.io_config()\n", " mw.rf_disable()\n", " mw.chip_enable()\n", " fr.delay(125000) #1ms\n", " mw.frequency(param[\"frequency_mhz\"] * 1e6) \n", " fr.delay(125000) #1ms\n", "\n", "\n", "#RF config\n", "def fr_func_rf_config(fr, param):\n", " fr.reset()\n", " fr.rf_out_0.frequency(param[\"freq_mhz\"] * 1e6)\n", " fr.rf_out_1.frequency(param[\"freq_mhz\"] * 1e6)\n", " fr.rf_out_0.amplitude(param[\"offset_i\"])\n", " fr.rf_out_1.amplitude(param[\"offset_q\"])\n", " fr.rf_out_0.offset(0)\n", " fr.rf_out_1.amplitude(0)\n", " fr.rf_out_0.phase(0)\n", " fr.rf_out_1.phase(90)\n", " fr.rf_out_0.phase_reset()\n", " fr.rf_out_1.phase_reset()\n", "\n", "\n", "#Triangular Pulse\n", "def fr_func_triangular_pulse(fr, param):\n", " ampl_i_list = np.concatenate(\n", " (np.linspace(0, param[\"ampl_i\"], param[\"width_samples\"]//2),\n", " np.linspace(param[\"ampl_i\"], 0, param[\"width_samples\"]//2)))\n", " \n", " ampl_q_list = np.concatenate(\n", " (np.linspace(0, param[\"ampl_q\"], param[\"width_samples\"]//2),\n", " np.linspace(param[\"ampl_q\"], 0, param[\"width_samples\"]//2)))\n", "\n", " fr.reset()\n", " mw = ADF4351(fr)\n", " mw.rf_enable() \n", " fr.rsync()\n", " for ampl_i, ampl_q in zip(ampl_i_list, ampl_q_list):\n", " fr.rf_out_0.amplitude(ampl_i)\n", " fr.rf_out_1.amplitude(ampl_q)\n", "\n", " fr.delay(10) #80us (compensate for RF out latency) \n", " fr.rsync()\n", " mw.rf_disable()\n", "\n", "\n", "#Wait\n", "def fr_func_wait(fr, param):\n", " fr.reset()\n", " fr.delay(param[\"wait_time_samples\"])" ] }, { "cell_type": "markdown", "id": "d588d3fa", "metadata": {}, "source": [ "### Map frame function and parameters" ] }, { "cell_type": "code", "execution_count": 14, "id": "f08c79cc", "metadata": {}, "outputs": [], "source": [ "fr_mw_config.set_frame_function(fr_func_mw_config)\n", "fr_mw_config.set_frame_parameter(param_dict[\"mw_config\"])\n", "\n", "fr_rf_config.set_frame_function(fr_func_rf_config)\n", "fr_rf_config.set_frame_parameter(param_dict[\"rf_config\"])\n", "\n", "fr_pi_half.set_frame_function(fr_func_triangular_pulse)\n", "fr_pi_half.set_frame_parameter(param_dict[\"pi_half\"])\n", "\n", "fr_pi.set_frame_function(fr_func_triangular_pulse)\n", "fr_pi.set_frame_parameter(param_dict[\"pi\"])\n", "\n", "fr_wait.set_frame_function(fr_func_wait)\n", "fr_wait.set_frame_parameter(param_dict[\"wait\"])" ] }, { "cell_type": "markdown", "id": "7d3c09a3", "metadata": {}, "source": [ "### Sequence definition" ] }, { "cell_type": "code", "execution_count": 15, "id": "1430a2e3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "+--------------------+\n", "| rp_0@192.168.1.143 |\n", "+--------------------+\n", "| mw_config |\n", "| rf_config |\n", "| pi_half (I) |\n", "| wait (I) |\n", "| pi |\n", "| wait (II) |\n", "| pi_half (II) |\n", "+--------------------+\n", "NOTE: Frames with (*) are triggered by external trigger source.\n", "\n" ] } ], "source": [ "seq.reset()\n", "seq.add_frame(frame=fr_mw_config, device=rp_0, label=\"mw_config\")\n", "seq.add_frame(frame=fr_rf_config, device=rp_0, label=\"rf_config\")\n", "seq.add_frame(frame=fr_pi_half, device=rp_0, label=\"pi_half (I)\")\n", "seq.add_frame(frame=fr_wait, device=rp_0, label=\"wait (I)\")\n", "seq.add_frame(frame=fr_pi, device=rp_0, label=\"pi\")\n", "seq.add_frame(frame=fr_wait, device=rp_0, label=\"wait (II)\")\n", "seq.add_frame(frame=fr_pi_half, device=rp_0, label=\"pi_half (II)\")\n", "\n", "print(seq.sequence_description())" ] }, { "cell_type": "markdown", "id": "14044a39", "metadata": {}, "source": [ "### Upload & Run sequence" ] }, { "cell_type": "code", "execution_count": null, "id": "b47594a9", "metadata": {}, "outputs": [], "source": [ "if not seq.is_done():\n", " seq.stop()\n", "\n", "repeat = 5\n", "wait_list = np.arange(0, 50, 2)\n", "\n", "for r in range(repeat):\n", " for w in wait_list: \n", " param_dict[\"wait\"][\"wait_time_samples\"] = w\n", " seq.upload()\n", " seq.start()\n", " seq.wait()\n", " \n", " \n" ] }, { "cell_type": "code", "execution_count": null, "id": "e697bc2a", "metadata": {}, "outputs": [], "source": [ "seq.get_status()" ] }, { "cell_type": "code", "execution_count": null, "id": "7efcbba4", "metadata": {}, "outputs": [], "source": [ "seq.stop()" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.10" } }, "nbformat": 4, "nbformat_minor": 5 }