├── LICENSE
├── README.rst
├── docs
├── conf.py
└── requirements.txt
├── examples
├── acquisition
│ ├── acq_ext_trig.ipynb
│ ├── acq_instant.ipynb
│ └── acq_trigger_level.ipynb
├── acquisition_generation
│ └── acq_gen_synced_pulse.ipynb
├── analog
│ ├── analog_input.ipynb
│ ├── analog_output.ipynb
│ └── img
│ │ └── analogLoopBack.png
├── click_shield_examples
│ └── click_board_examples
│ │ ├── basic
│ │ ├── buttonG.ipynb
│ │ ├── cap_touch.ipynb
│ │ └── relay.ipynb
│ │ ├── click_board_examples.ipynb
│ │ ├── motor
│ │ ├── dc_motor2.ipynb
│ │ └── vibro_motor.ipynb
│ │ └── sensor
│ │ ├── current.ipynb
│ │ ├── light.ipynb
│ │ ├── motion.ipynb
│ │ └── thermo16.ipynb
├── digital
│ ├── gpio.ipynb
│ └── led.ipynb
├── dma
│ └── dma.ipynb
├── generation
│ ├── gen_arbitrary_signal.ipynb
│ ├── gen_burst_async_signals.ipynb
│ ├── gen_bursts.ipynb
│ ├── gen_continuous_signal.ipynb
│ ├── gen_ext_trigger.ipynb
│ └── gen_sync_two_channel.ipynb
├── hardware
│ ├── calibration.ipynb
│ └── hwid.ipynb
├── img
│ ├── FastIOLoopBack.png
│ ├── LED-blink.gif
│ ├── RedPitaya_pinout.jpg
│ ├── generate_continous_signal_on_fast_analog_output.png
│ └── on_given_trigger_acquire_signal_on_fast_analog_input.png
├── multiboard_sync
│ ├── click_shield_1.ipynb
│ └── daisy_chain_1.ipynb
└── outdated
│ ├── cable_length.ipynb
│ ├── exam_temp.ipynb
│ ├── home_automation.ipynb
│ ├── img
│ ├── cable_length.jpg
│ ├── nest.jpeg
│ ├── on_off_control.png
│ ├── temp_reg_setup.jpg
│ ├── temp_sensor.jpg
│ └── temp_sensor_sch.png
│ ├── la_trigger.ipynb
│ └── lg_counter.ipynb
├── experiments
├── axi4lite_gpio.ipynb
├── monitor_classic_fpga.ipynb
├── scope_filter.ipynb
└── xadc.ipynb
├── redpitaya
├── __init__.py
├── app
│ ├── __init__.py
│ ├── generator.py
│ └── oscilloscope.py
├── drv
│ ├── __init__.py
│ ├── acq.py
│ ├── asg_bst.py
│ ├── asg_per.py
│ ├── clb.py
│ ├── evn.py
│ ├── fixp.py
│ ├── gen.py
│ ├── gen_out.py
│ ├── hwid.py
│ ├── la.py
│ ├── la_msk.py
│ ├── la_rle.py
│ ├── la_trg.py
│ ├── lg.py
│ ├── lg_out.py
│ ├── mgmt.py
│ ├── osc.py
│ ├── osc_fil.py
│ ├── osc_trg.py
│ ├── overlay.py
│ ├── pdm.py
│ ├── uio.py
│ └── wave.py
└── overlay
│ ├── __init__.py
│ └── mercury.py
├── setup.py
└── welcome.ipynb
/README.rst:
--------------------------------------------------------------------------------
1 | ==============================
2 | Red Pitaya JupyterLab
3 | ==============================
4 |
5 | Here you can find examples on how to control Red Pitaya through the on-board JupyerLab application.
6 |
7 | - OS versions including and up to 2.00-18 use a modified FPGA image reffered to as Mercury.
8 | - OS versions above 2.00-23 use a standard Red Pitaya FPGA image and the JupyterLab commands have been changed, so that they are now the same as C and Python API commands. The new Jupyter commands run corresponding C API functions in the background.
9 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | numpy
2 | scipy
3 | bokeh
4 | ipywidgets
5 | IPython
6 | pyudev
7 | python-periphery
8 | # support for http://wavedrom.com
9 | sphinxcontrib-wavedrom
10 |
--------------------------------------------------------------------------------
/examples/acquisition/acq_ext_trig.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Triggering on external trigger\n",
8 | "In the third example, we will learn how to configure the acquisition to capture data on an external trigger\n",
9 | "\n",
10 | "**Note:** \n",
11 | "The voltage range of fast analog inputs on the Red Pitaya depends on the input jumper position. HV sets the input range to ±20 V, while LV sets the input range to ±1 V. For more information, please read the following [chapter](https://redpitaya.readthedocs.io/en/latest/developerGuide/hardware/125-14/fastIO.html#analog-inputs).\n",
12 | "\n",
13 | "Create a loop-back from fast analog outputs to fast analog inputs, as shown in the picture below. \n",
14 | "Please make sure the jumpers are set to ±1 V (LV).\n",
15 | "\n",
16 | ""
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "metadata": {},
22 | "source": [
23 | "## Libraries and FPGA image\n",
24 | "\n",
25 | "We need the additional functionality of *numpy* and *matplotlib* for data plotting and faster array operations."
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": null,
31 | "metadata": {},
32 | "outputs": [],
33 | "source": [
34 | "import numpy as np\n",
35 | "from matplotlib import pyplot as plt\n",
36 | "from rp_overlay import overlay\n",
37 | "import rp\n",
38 | "\n",
39 | "fpga = overlay()\n",
40 | "rp.rp_Init()"
41 | ]
42 | },
43 | {
44 | "cell_type": "markdown",
45 | "metadata": {},
46 | "source": [
47 | "## Macros\n",
48 | "Throughout this tutorial we will mention macros multiple times. Here is a complete list of macros that will come in handy when customising this notebook. The marcos are a part of the **rp** library.\n",
49 | "\n",
50 | "- **Decimation** - RP_DEC_1, RP_DEC_2, RP_DEC_4, RP_DEC_8, RP_DEC_16, RP_DEC_32, RP_DEC_64, RP_DEC_128, RP_DEC_256, RP_DEC_512, RP_DEC_1024, RP_DEC_2048, RP_DEC_4096, RP_DEC_8192, RP_DEC_16384, RP_DEC_32768, RP_DEC_65536 \n",
51 | "- **Acquisition trigger** - RP_TRIG_SRC_DISABLED, RP_TRIG_SRC_NOW, RP_TRIG_SRC_CHA_PE, RP_TRIG_SRC_CHA_NE, RP_TRIG_SRC_CHB_PE, RP_TRIG_SRC_CHB_NE, RP_TRIG_SRC_EXT_PE, RP_TRIG_SRC_EXT_NE, RP_TRIG_SRC_AWG_PE, RP_TRIG_SRC_AWG_NE\n",
52 | "- **Acquisition trigger state** - RP_TRIG_STATE_TRIGGERED, RP_TRIG_STATE_WAITING\n",
53 | "- **Buffer size** - ADC_BUFFER_SIZE, DAC_BUFFER_SIZE\n",
54 | "- **Fast analog channels** - RP_CH_1, RP_CH_2\n",
55 | "\n",
56 | "SIGNALlab 250-12 only:\n",
57 | "- **Input coupling** - RP_DC, RP_AC\n",
58 | "\n",
59 | "STEMlab 125-14 4-Input only:\n",
60 | "- **Fast analog channels** - RP_CH_3, RP_CH_4\n",
61 | "- **Acquisition trigger** - RP_TRIG_SRC_CHC_PE, RP_TRIG_SRC_CHC_NE, RP_TRIG_SRC_CHD_PE, RP_TRIG_SRC_CHD_NE\n"
62 | ]
63 | },
64 | {
65 | "cell_type": "markdown",
66 | "metadata": {},
67 | "source": [
68 | "## External trigger\n",
69 | "The external trigger is located on the DIO0_P pin on the extension connector E1. It is recommended that the applied source meets the 3V3 CMOS signal conditions. For this simple experiment, we can use a simple jumper wire to touch the pin or connect it to the pin, which acts as an antenna and picks up environmental signals to trigger the acquisition.\n",
70 | "\n",
71 | "Now that we are already familiar with the process, let's jump right in.\n",
72 | "\n",
73 | "Parameters:"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": null,
79 | "metadata": {},
80 | "outputs": [],
81 | "source": [
82 | "# Generator parameters\n",
83 | "channel = rp.RP_CH_1\n",
84 | "channel2 = rp.RP_CH_2\n",
85 | "waveform = rp.RP_WAVEFORM_SINE\n",
86 | "freq = 100000\n",
87 | "ampl = 1.0\n",
88 | "\n",
89 | "# Acquisition paramters\n",
90 | "dec = rp.RP_DEC_1\n",
91 | "\n",
92 | "trig_lvl = 0.5\n",
93 | "trig_dly = 0\n",
94 | "\n",
95 | "acq_trig_sour = rp.RP_TRIG_SRC_EXT_PE\n",
96 | "N = 16384\n",
97 | "\n",
98 | "rp.rp_GenReset()\n",
99 | "rp.rp_AcqReset()"
100 | ]
101 | },
102 | {
103 | "cell_type": "markdown",
104 | "metadata": {},
105 | "source": [
106 | "Generator code (if needed):"
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "metadata": {},
113 | "outputs": [],
114 | "source": [
115 | "print(\"Gen_start\")\n",
116 | "rp.rp_GenWaveform(channel, waveform)\n",
117 | "rp.rp_GenFreqDirect(channel, freq)\n",
118 | "rp.rp_GenAmp(channel, ampl)\n",
119 | "\n",
120 | "rp.rp_GenWaveform(channel2, waveform)\n",
121 | "rp.rp_GenFreqDirect(channel2, freq)\n",
122 | "rp.rp_GenAmp(channel2, ampl)\n",
123 | "\n",
124 | "rp.rp_GenTriggerSource(channel, rp.RP_GEN_TRIG_SRC_INTERNAL)\n",
125 | "\n",
126 | "rp.rp_GenOutEnableSync(True)\n",
127 | "rp.rp_GenSynchronise()"
128 | ]
129 | },
130 | {
131 | "cell_type": "markdown",
132 | "metadata": {},
133 | "source": [
134 | "Acquisition code:"
135 | ]
136 | },
137 | {
138 | "cell_type": "code",
139 | "execution_count": null,
140 | "metadata": {},
141 | "outputs": [],
142 | "source": [
143 | "# Set Decimation\n",
144 | "rp.rp_AcqSetDecimation(dec)\n",
145 | "\n",
146 | "# Set trigger level and delay\n",
147 | "rp.rp_AcqSetTriggerLevel(rp.RP_T_CH_1, trig_lvl)\n",
148 | "rp.rp_AcqSetTriggerDelay(trig_dly)\n",
149 | "\n",
150 | "# Start Acquisition\n",
151 | "print(\"Acq_start\")\n",
152 | "rp.rp_AcqStart()\n",
153 | "\n",
154 | "# Specify trigger - immediately\n",
155 | "rp.rp_AcqSetTriggerSrc(acq_trig_sour)\n",
156 | "\n",
157 | "# Trigger state\n",
158 | "while 1:\n",
159 | " trig_state = rp.rp_AcqGetTriggerState()[1]\n",
160 | " if trig_state == rp.RP_TRIG_STATE_TRIGGERED:\n",
161 | " break\n",
162 | "\n",
163 | "# Fill state\n",
164 | "while 1:\n",
165 | " if rp.rp_AcqGetBufferFillState()[1]:\n",
166 | " break\n",
167 | "\n",
168 | "\n",
169 | "### Get data ###\n",
170 | "# RAW\n",
171 | "ibuff = rp.i16Buffer(N)\n",
172 | "res = rp.rp_AcqGetOldestDataRaw(rp.RP_CH_1, N, ibuff.cast())[1]\n",
173 | "\n",
174 | "# Volts\n",
175 | "fbuff = rp.fBuffer(N)\n",
176 | "res = rp.rp_AcqGetOldestDataV(rp.RP_CH_1, N, fbuff)[1]\n",
177 | "\n",
178 | "data_V = np.zeros(N, dtype = float)\n",
179 | "data_raw = np.zeros(N, dtype = int)\n",
180 | "X = np.arange(0, N, 1)\n",
181 | "\n",
182 | "for i in range(0, N, 1):\n",
183 | " data_V[i] = fbuff[i]\n",
184 | " data_raw[i] = ibuff[i]\n",
185 | "\n",
186 | "figure, axis = plt.subplots(1, 2) \n",
187 | "\n",
188 | "axis[0].plot(X, data_V) \n",
189 | "axis[0].set_title(\"Volts\")\n",
190 | "\n",
191 | "axis[1].plot(X, data_raw) \n",
192 | "axis[1].set_title(\"RAW\") \n",
193 | "\n",
194 | "plt.show()"
195 | ]
196 | },
197 | {
198 | "cell_type": "code",
199 | "execution_count": null,
200 | "metadata": {},
201 | "outputs": [],
202 | "source": [
203 | "# Release resources\n",
204 | "rp.rp_Release()"
205 | ]
206 | },
207 | {
208 | "cell_type": "markdown",
209 | "metadata": {},
210 | "source": [
211 | "### Note\n",
212 | "There are a lot of different commands for the Acquisition. The list of available functions is quite an achievement to read through, so from now on, please refer to the *C and Python API section* of the [SCPI & API command list](https://redpitaya.readthedocs.io/en/latest/appsFeatures/remoteControl/command_list.html#list-of-supported-scpi-api-commands) for all available commands.\n"
213 | ]
214 | }
215 | ],
216 | "metadata": {
217 | "language_info": {
218 | "name": "python"
219 | }
220 | },
221 | "nbformat": 4,
222 | "nbformat_minor": 2
223 | }
224 |
--------------------------------------------------------------------------------
/examples/acquisition/acq_instant.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Instant signal acquisition\n",
8 | "\n",
9 | "In the second example, we will learn how to force an acquisition to trigger in the specified moment.\n",
10 | "\n",
11 | "**Note:** \n",
12 | "The voltage range of fast analog inputs on the Red Pitaya depends on the input jumper position. HV sets the input range to ±20 V, while LV sets the input range to ±1 V. For more information, please read the following [chapter](https://redpitaya.readthedocs.io/en/latest/developerGuide/hardware/125-14/fastIO.html#analog-inputs).\n",
13 | "\n",
14 | "Create a loop-back from fast analog outputs to fast analog inputs, as shown in the picture below. \n",
15 | "Please make sure the jumpers are set to ±1 V (LV).\n",
16 | "\n",
17 | ""
18 | ]
19 | },
20 | {
21 | "cell_type": "markdown",
22 | "metadata": {},
23 | "source": [
24 | "## Libraries and FPGA image\n",
25 | "\n",
26 | "We need the additional functionality of *numpy* and *matplotlib* for data plotting and faster array operations."
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": null,
32 | "metadata": {
33 | "scrolled": false
34 | },
35 | "outputs": [],
36 | "source": [
37 | "import time\n",
38 | "import numpy as np\n",
39 | "from matplotlib import pyplot as plt\n",
40 | "from rp_overlay import overlay\n",
41 | "import rp\n",
42 | "\n",
43 | "fpga = overlay()\n",
44 | "rp.rp_Init()"
45 | ]
46 | },
47 | {
48 | "cell_type": "markdown",
49 | "metadata": {},
50 | "source": [
51 | "## Macros\n",
52 | "Throughout this tutorial we will mention macros multiple times. Here is a complete list of macros that will come in handy when customising this notebook. The marcos are a part of the **rp** library.\n",
53 | "\n",
54 | "- **Decimation** - RP_DEC_1, RP_DEC_2, RP_DEC_4, RP_DEC_8, RP_DEC_16, RP_DEC_32, RP_DEC_64, RP_DEC_128, RP_DEC_256, RP_DEC_512, RP_DEC_1024, RP_DEC_2048, RP_DEC_4096, RP_DEC_8192, RP_DEC_16384, RP_DEC_32768, RP_DEC_65536 \n",
55 | "- **Acquisition trigger** - RP_TRIG_SRC_DISABLED, RP_TRIG_SRC_NOW, RP_TRIG_SRC_CHA_PE, RP_TRIG_SRC_CHA_NE, RP_TRIG_SRC_CHB_PE, RP_TRIG_SRC_CHB_NE, RP_TRIG_SRC_EXT_PE, RP_TRIG_SRC_EXT_NE, RP_TRIG_SRC_AWG_PE, RP_TRIG_SRC_AWG_NE\n",
56 | "- **Acquisition trigger state** - RP_TRIG_STATE_TRIGGERED, RP_TRIG_STATE_WAITING\n",
57 | "- **Buffer size** - ADC_BUFFER_SIZE, DAC_BUFFER_SIZE\n",
58 | "- **Fast analog channels** - RP_CH_1, RP_CH_2\n",
59 | "\n",
60 | "SIGNALlab 250-12 only:\n",
61 | "- **Input coupling** - RP_DC, RP_AC\n",
62 | "\n",
63 | "STEMlab 125-14 4-Input only:\n",
64 | "- **Fast analog channels** - RP_CH_3, RP_CH_4\n",
65 | "- **Acquisition trigger** - RP_TRIG_SRC_CHC_PE, RP_TRIG_SRC_CHC_NE, RP_TRIG_SRC_CHD_PE, RP_TRIG_SRC_CHD_NE\n"
66 | ]
67 | },
68 | {
69 | "cell_type": "markdown",
70 | "metadata": {},
71 | "source": [
72 | "## Instant acquisition\n",
73 | "The only change from the previous example is that we will specify the acquisition trigger as **RP_TRIG_SRC_NOW**, which immediately forces a trigger condition.\n",
74 | "\n",
75 | "Here are the Generation and Acquisition parameters:"
76 | ]
77 | },
78 | {
79 | "cell_type": "code",
80 | "execution_count": null,
81 | "metadata": {
82 | "collapsed": true
83 | },
84 | "outputs": [],
85 | "source": [
86 | "# Generator parameters\n",
87 | "channel = rp.RP_CH_1\n",
88 | "channel2 = rp.RP_CH_2\n",
89 | "waveform = rp.RP_WAVEFORM_SINE\n",
90 | "freq = 100000\n",
91 | "ampl = 1.0\n",
92 | "\n",
93 | "# Acquisition paramters\n",
94 | "dec = rp.RP_DEC_1\n",
95 | "\n",
96 | "trig_lvl = 0.5\n",
97 | "trig_dly = 0\n",
98 | "\n",
99 | "acq_trig_sour = rp.RP_TRIG_SRC_NOW\n",
100 | "N = 16384\n",
101 | "\n",
102 | "rp.rp_GenReset()\n",
103 | "rp.rp_AcqReset()"
104 | ]
105 | },
106 | {
107 | "cell_type": "markdown",
108 | "metadata": {},
109 | "source": [
110 | "Generator code (if needed):"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": null,
116 | "metadata": {},
117 | "outputs": [],
118 | "source": [
119 | "print(\"Gen_start\")\n",
120 | "rp.rp_GenWaveform(channel, waveform)\n",
121 | "rp.rp_GenFreqDirect(channel, freq)\n",
122 | "rp.rp_GenAmp(channel, ampl)\n",
123 | "\n",
124 | "rp.rp_GenWaveform(channel2, waveform)\n",
125 | "rp.rp_GenFreqDirect(channel2, freq)\n",
126 | "rp.rp_GenAmp(channel2, ampl)\n",
127 | "\n",
128 | "rp.rp_GenTriggerSource(channel, rp.RP_GEN_TRIG_SRC_INTERNAL)\n",
129 | "\n",
130 | "rp.rp_GenOutEnableSync(True)\n",
131 | "rp.rp_GenSynchronise()"
132 | ]
133 | },
134 | {
135 | "cell_type": "markdown",
136 | "metadata": {},
137 | "source": [
138 | "Here is the acquisition code. It is recommended to leave some time between the **rp_AcqStart** and **rp_AcqSetTriggerSrc** so Red Pitaya has enough time to capture the data. Otherwise, we can find inconsistencies in the captured data (especially at higher decimations)."
139 | ]
140 | },
141 | {
142 | "cell_type": "code",
143 | "execution_count": null,
144 | "metadata": {},
145 | "outputs": [],
146 | "source": [
147 | "# Set Decimation\n",
148 | "rp.rp_AcqSetDecimation(dec)\n",
149 | "\n",
150 | "# Set trigger level and delay\n",
151 | "rp.rp_AcqSetTriggerLevel(rp.RP_T_CH_1, trig_lvl)\n",
152 | "rp.rp_AcqSetTriggerDelay(trig_dly)\n",
153 | "\n",
154 | "# Start Acquisition\n",
155 | "print(\"Acq_start\")\n",
156 | "rp.rp_AcqStart()\n",
157 | "\n",
158 | "time.sleep(0.1)\n",
159 | "\n",
160 | "# Specify trigger - immediately\n",
161 | "rp.rp_AcqSetTriggerSrc(acq_trig_sour)\n",
162 | "\n",
163 | "# Trigger state\n",
164 | "while 1:\n",
165 | " trig_state = rp.rp_AcqGetTriggerState()[1]\n",
166 | " if trig_state == rp.RP_TRIG_STATE_TRIGGERED:\n",
167 | " break\n",
168 | "\n",
169 | "# Fill state\n",
170 | "while 1:\n",
171 | " if rp.rp_AcqGetBufferFillState()[1]:\n",
172 | " break\n",
173 | "\n",
174 | "\n",
175 | "### Get data ###\n",
176 | "# RAW\n",
177 | "ibuff = rp.i16Buffer(N)\n",
178 | "res = rp.rp_AcqGetOldestDataRaw(rp.RP_CH_1, N, ibuff.cast())[1]\n",
179 | "\n",
180 | "# Volts\n",
181 | "fbuff = rp.fBuffer(N)\n",
182 | "res = rp.rp_AcqGetOldestDataV(rp.RP_CH_1, N, fbuff)[1]\n",
183 | "\n",
184 | "data_V = np.zeros(N, dtype = float)\n",
185 | "data_raw = np.zeros(N, dtype = int)\n",
186 | "X = np.arange(0, N, 1)\n",
187 | "\n",
188 | "for i in range(0, N, 1):\n",
189 | " data_V[i] = fbuff[i]\n",
190 | " data_raw[i] = ibuff[i]\n",
191 | "\n",
192 | "figure, axis = plt.subplots(1, 2) \n",
193 | "\n",
194 | "axis[0].plot(X, data_V) \n",
195 | "axis[0].set_title(\"Volts\")\n",
196 | "\n",
197 | "axis[1].plot(X, data_raw) \n",
198 | "axis[1].set_title(\"RAW\") \n",
199 | "\n",
200 | "plt.show()"
201 | ]
202 | },
203 | {
204 | "cell_type": "code",
205 | "execution_count": null,
206 | "metadata": {},
207 | "outputs": [],
208 | "source": [
209 | "# Release resources\n",
210 | "rp.rp_Release()"
211 | ]
212 | },
213 | {
214 | "cell_type": "markdown",
215 | "metadata": {},
216 | "source": [
217 | "### Note\n",
218 | "There are a lot of different commands for the Acquisition. The list of available functions is quite an achievement to read through, so from now on, please refer to the *C and Python API section* of the [SCPI & API command list](https://redpitaya.readthedocs.io/en/latest/appsFeatures/remoteControl/command_list.html#list-of-supported-scpi-api-commands) for all available commands.\n"
219 | ]
220 | }
221 | ],
222 | "metadata": {
223 | "kernelspec": {
224 | "display_name": "Python 3",
225 | "language": "python",
226 | "name": "python3"
227 | },
228 | "language_info": {
229 | "codemirror_mode": {
230 | "name": "ipython",
231 | "version": 3
232 | },
233 | "file_extension": ".py",
234 | "mimetype": "text/x-python",
235 | "name": "python",
236 | "nbconvert_exporter": "python",
237 | "pygments_lexer": "ipython3",
238 | "version": "3.5.2"
239 | }
240 | },
241 | "nbformat": 4,
242 | "nbformat_minor": 2
243 | }
244 |
--------------------------------------------------------------------------------
/examples/analog/analog_output.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Slow Analog Outputs \n",
8 | "\n",
9 | "Slow analog outputs provide a convenient way to generate output voltage from 0 to 1.8 V.\n",
10 | "\n",
11 | "There are four analog outputs on the E2 connector depicted in the picture below.\n",
12 | "\n",
13 | ""
14 | ]
15 | },
16 | {
17 | "cell_type": "markdown",
18 | "metadata": {},
19 | "source": [
20 | "## Libraries and FPGA image\n",
21 | "\n",
22 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
23 | ]
24 | },
25 | {
26 | "cell_type": "code",
27 | "execution_count": null,
28 | "metadata": {
29 | "collapsed": true
30 | },
31 | "outputs": [],
32 | "source": [
33 | "from rp_overlay import overlay\n",
34 | "import rp\n",
35 | "\n",
36 | "fpga = overlay()\n",
37 | "rp.rp_Init()"
38 | ]
39 | },
40 | {
41 | "cell_type": "markdown",
42 | "metadata": {},
43 | "source": [
44 | "## Macros\n",
45 | "Throughout this tutorial we will mention macros multiple times. Here is a complete list of analog macros that will come in handy when customising this notebook. The marcos are a part of the **rp** library.\n",
46 | "\n",
47 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
48 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3"
49 | ]
50 | },
51 | {
52 | "cell_type": "markdown",
53 | "metadata": {},
54 | "source": [
55 | "## Controling Analog Outputs\n",
56 | "The analog outputs can be contolled in two different ways; either specify the value in Volts or the RAW DAC value directly. Analog output numbers range from 0 to 3.\n",
57 | "\n",
58 | "### Setting value in Volts\n",
59 | "- **rp_AOpinSetValue(analog_output_number, value)**\n",
60 | "- **rp_ApinSetValue(analog_output_macro, value)**\n",
61 | "\n",
62 | "### Setting RAW value\n",
63 | "- **rp_AOpinSetValueRaw(analog_output_number, raw_value)**\n",
64 | "- **rp_ApinSetValueRaw(analog_input_macro, raw_value)**\n",
65 | "\n",
66 | "### Getting current output value in Volts\n",
67 | "- **rp_AOpinGetValue(analog_output_number)**\n",
68 | "- **rp_ApinGetValue(analog_output_macro)**\n",
69 | "\n",
70 | "### Getting current output RAW value\n",
71 | "- **rp_AOpinGetValueRaw(analog_output_number)**\n",
72 | "- **rp_ApinGetValueRaw(analog_input_macro)**\n",
73 | "\n",
74 | "### Reading analog output range\n",
75 | "To get the analog output range use the following function:\n",
76 | "- **rp_AOpinGetRange(analog_out_number)**\n",
77 | "- **rp_ApinGetRange(analog_pin_macro)**\n",
78 | "\n",
79 | "### Reseting analog pins\n",
80 | "To reset all analog pins to their default state (output 0 V) use:\n",
81 | "- **rp_AOpinReset()**\n",
82 | "- **rp_ApinReset()**"
83 | ]
84 | },
85 | {
86 | "cell_type": "markdown",
87 | "metadata": {},
88 | "source": [
89 | "First we will reset all analog pins."
90 | ]
91 | },
92 | {
93 | "cell_type": "code",
94 | "execution_count": null,
95 | "metadata": {},
96 | "outputs": [],
97 | "source": [
98 | "rp.rp_ApinReset()"
99 | ]
100 | },
101 | {
102 | "cell_type": "markdown",
103 | "metadata": {},
104 | "source": [
105 | "Next, lets set *Analog output 0* and *AOUT1* to 1 V and 1.5 V respectively."
106 | ]
107 | },
108 | {
109 | "cell_type": "code",
110 | "execution_count": null,
111 | "metadata": {},
112 | "outputs": [],
113 | "source": [
114 | "rp.rp_ApinSetValue(rp.RP_AOUT0, 1)\n",
115 | "rp.rp_AOpinSetValue(1, 1.5)"
116 | ]
117 | },
118 | {
119 | "cell_type": "markdown",
120 | "metadata": {},
121 | "source": [
122 | "Releasing resources:"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "execution_count": null,
128 | "metadata": {},
129 | "outputs": [],
130 | "source": [
131 | "rp.rp_Release()"
132 | ]
133 | },
134 | {
135 | "cell_type": "markdown",
136 | "metadata": {},
137 | "source": [
138 | "## Analog Signal Generator\n",
139 | "This example is the analog signal generator for the [analog input](analog_input.ipynb) live data plotting.\n",
140 | "\n",
141 | "The measurements on the slow analog inputs are taken every 10 milliseconds. Hence, we need to generate new data samples at the same rate. We will use the *time* module to delay the data generation and import *numpy* to generate a sine wave.\n"
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "execution_count": null,
147 | "metadata": {},
148 | "outputs": [],
149 | "source": [
150 | "import time\n",
151 | "import numpy as np\n",
152 | "import rp\n",
153 | "\n",
154 | "rp.rp_Init()"
155 | ]
156 | },
157 | {
158 | "cell_type": "markdown",
159 | "metadata": {},
160 | "source": [
161 | "Here, we will configure the number of channels (4) and define the amplitudes. Note that the analog outputs only accept values from 0 to 1.8V, so we have to offset our signals to $\\frac{1.8V} { 2 } = 0.9V $.\n",
162 | "\n",
163 | "Then, we will start an infinite loop that will generate sinuses on the analog outputs. \n",
164 | "To stop execution:\n",
165 | "- Press the (∎) button above or \n",
166 | "- Click outside, to the left of the cell, but inside of the green rectangle, so it turns green, which will invoke Jupyter's command mode and press the *I* key twice."
167 | ]
168 | },
169 | {
170 | "cell_type": "code",
171 | "execution_count": null,
172 | "metadata": {},
173 | "outputs": [],
174 | "source": [
175 | "chn = 4\n",
176 | "amp = (0.25, 0.35, 0.4, 0.8)\n",
177 | "\n",
178 | "while True:\n",
179 | " for i in range(40):\n",
180 | " for ch in range(0, chn):\n",
181 | " rp.rp_AOpinSetValue(ch, 0.9 + amp[ch] * np.sin(i * np.pi / 20) )\n",
182 | " time.sleep(0.01)"
183 | ]
184 | },
185 | {
186 | "cell_type": "markdown",
187 | "metadata": {},
188 | "source": [
189 | "Releasing resources:"
190 | ]
191 | },
192 | {
193 | "cell_type": "code",
194 | "execution_count": null,
195 | "metadata": {},
196 | "outputs": [],
197 | "source": [
198 | "rp.rp_Release()"
199 | ]
200 | }
201 | ],
202 | "metadata": {
203 | "kernelspec": {
204 | "display_name": "Python 3",
205 | "language": "python",
206 | "name": "python3"
207 | },
208 | "language_info": {
209 | "codemirror_mode": {
210 | "name": "ipython",
211 | "version": 3
212 | },
213 | "file_extension": ".py",
214 | "mimetype": "text/x-python",
215 | "name": "python",
216 | "nbconvert_exporter": "python",
217 | "pygments_lexer": "ipython3",
218 | "version": "3.5.2"
219 | }
220 | },
221 | "nbformat": 4,
222 | "nbformat_minor": 2
223 | }
224 |
--------------------------------------------------------------------------------
/examples/analog/img/analogLoopBack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/analog/img/analogLoopBack.png
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/basic/buttonG.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# BUTTON G CLICK \n",
8 | "\n",
9 | "## Libraries and FPGA image\n",
10 | "\n",
11 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "import time\n",
21 | "from rp_overlay import overlay\n",
22 | "import rp\n",
23 | "\n",
24 | "# Initialize the FPGA overlay\n",
25 | "fpga = overlay()\n",
26 | "rp.rp_Init()"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "## Macros\n",
34 | "Here is a complete list of macros that will come in handy when customising this notebook and operating the click shields.\n",
35 | "\n",
36 | "- **States** - RP_LOW, RP_HIGH\n",
37 | "- **Directions** - RP_IN, RP_OUT\n",
38 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7\n",
39 | "- **DIOx_P** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
40 | "- **DIOx_N** - RP_DIO0_N, RP_DIO1_N, ..., RP_DIO7_N *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
41 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
42 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3\n",
43 | "\n",
44 | "### Click shield macros\n",
45 | "For easier work with the click shields, here are some macro rewrites. Marcos ending in \"1\" are on MicroBus1, and macros ending in \"2\" are on MicroBus2.\n",
46 | "\n",
47 | "- **AN1, AIN2** - RP_AIN0, RP_AIN1\n",
48 | "- **RST1, RST2** - RP_DIO2_N, RP_DIO4_N\n",
49 | "- **PWM1, PWM2** - RP_DIO1_P, RP_DIO3_P\n",
50 | "- **INT1, INT2** - RP_DIO2_P, RP_DIO4_P\n",
51 | "- **UART_SW** - RP_DIO5_N\n",
52 | "- **SPI_CS1, SPI_CS2** - RP_DIO1_N, RP_DIO3_N\n",
53 | "- **Logic analyser** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P\n",
54 | "\n",
55 | "Setting up click shield macros:"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "AN1 = rp.RP_AIN0\n",
65 | "AN2 = rp.RP_AIN1\n",
66 | "RST1 = rp.RP_DIO2_N\n",
67 | "RST2 = rp.RP_DIO4_N\n",
68 | "PWM1 = rp.RP_DIO1_P\n",
69 | "PWM2 = rp.RP_DIO3_P\n",
70 | "INT1 = rp.RP_DIO2_P\n",
71 | "INT2 = rp.RP_DIO4_P\n",
72 | "UART_SW = rp.RP_DIO5_N\n",
73 | "SPI_CS1 = rp.RP_DIO1_N\n",
74 | "SPI_CS2 = rp.RP_DIO3_N"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": null,
80 | "metadata": {},
81 | "outputs": [],
82 | "source": [
83 | "# Set the direction of mikrobus pins\n",
84 | "rp.rp_DpinSetDirection(PWM1, rp.RP_OUT)\n",
85 | "rp.rp_DpinSetDirection(PWM2, rp.RP_OUT)\n",
86 | "rp.rp_DpinSetDirection(INT1, rp.RP_IN)\n",
87 | "rp.rp_DpinSetDirection(INT2, rp.RP_IN)"
88 | ]
89 | },
90 | {
91 | "cell_type": "markdown",
92 | "metadata": {},
93 | "source": [
94 | "If the G button is pressed on the click board, an LED on the Red Pitaya and the LED inside the G button are turned ON."
95 | ]
96 | },
97 | {
98 | "cell_type": "code",
99 | "execution_count": null,
100 | "metadata": {},
101 | "outputs": [],
102 | "source": [
103 | "while True:\n",
104 | " state = int(rp.rp_DpinGetState(INT1)[1])\n",
105 | " if state:\n",
106 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_HIGH)\n",
107 | " rp.rp_DpinSetState(PWM1, rp.RP_HIGH)\n",
108 | " else:\n",
109 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_LOW)\n",
110 | " rp.rp_DpinSetState(PWM1, rp.RP_LOW)"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": null,
116 | "metadata": {},
117 | "outputs": [],
118 | "source": [
119 | "# Release resources\n",
120 | "rp.rp_Release()"
121 | ]
122 | }
123 | ],
124 | "metadata": {
125 | "language_info": {
126 | "name": "python"
127 | },
128 | "orig_nbformat": 4
129 | },
130 | "nbformat": 4,
131 | "nbformat_minor": 2
132 | }
133 |
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/basic/cap_touch.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# CAPACITIVE TOUCH CLICK \n",
8 | "\n",
9 | "## Libraries and FPGA image\n",
10 | "\n",
11 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "import time\n",
21 | "from rp_overlay import overlay\n",
22 | "import rp\n",
23 | "\n",
24 | "# Initialize the FPGA overlay\n",
25 | "fpga = overlay()\n",
26 | "rp.rp_Init()"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "## Macros\n",
34 | "Here is a complete list of macros that will come in handy when customising this notebook and operating the click shields.\n",
35 | "\n",
36 | "- **States** - RP_LOW, RP_HIGH\n",
37 | "- **Directions** - RP_IN, RP_OUT\n",
38 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7\n",
39 | "- **DIOx_P** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
40 | "- **DIOx_N** - RP_DIO0_N, RP_DIO1_N, ..., RP_DIO7_N *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
41 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
42 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3\n",
43 | "\n",
44 | "### Click shield macros\n",
45 | "For easier work with the click shields, here are some macro rewrites. Marcos ending in \"1\" are on MicroBus1, and macros ending in \"2\" are on MicroBus2.\n",
46 | "\n",
47 | "- **AN1, AIN2** - RP_AIN0, RP_AIN1\n",
48 | "- **RST1, RST2** - RP_DIO2_N, RP_DIO4_N\n",
49 | "- **PWM1, PWM2** - RP_DIO1_P, RP_DIO3_P\n",
50 | "- **INT1, INT2** - RP_DIO2_P, RP_DIO4_P\n",
51 | "- **UART_SW** - RP_DIO5_N\n",
52 | "- **SPI_CS1, SPI_CS2** - RP_DIO1_N, RP_DIO3_N\n",
53 | "- **Logic analyser** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P\n",
54 | "\n",
55 | "Setting up click shield macros:"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "AN1 = rp.RP_AIN0\n",
65 | "AN2 = rp.RP_AIN1\n",
66 | "RST1 = rp.RP_DIO2_N\n",
67 | "RST2 = rp.RP_DIO4_N\n",
68 | "PWM1 = rp.RP_DIO1_P\n",
69 | "PWM2 = rp.RP_DIO3_P\n",
70 | "INT1 = rp.RP_DIO2_P\n",
71 | "INT2 = rp.RP_DIO4_P\n",
72 | "UART_SW = rp.RP_DIO5_N\n",
73 | "SPI_CS1 = rp.RP_DIO1_N\n",
74 | "SPI_CS2 = rp.RP_DIO3_N\n",
75 | "\n",
76 | "# Set the direction of mikrobus pins\n",
77 | "rp.rp_DpinSetDirection(INT1, rp.RP_IN)\n",
78 | "rp.rp_DpinSetDirection(INT2, rp.RP_IN)"
79 | ]
80 | },
81 | {
82 | "cell_type": "markdown",
83 | "metadata": {},
84 | "source": [
85 | "If the capacitor button is pressed on the click board, an LED is turned ON on the Red Pitaya."
86 | ]
87 | },
88 | {
89 | "cell_type": "code",
90 | "execution_count": null,
91 | "metadata": {},
92 | "outputs": [],
93 | "source": [
94 | "while True:\n",
95 | " state = int(rp.rp_DpinGetState(INT1)[1])\n",
96 | " if state:\n",
97 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_HIGH)\n",
98 | " else:\n",
99 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_LOW)"
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "execution_count": null,
105 | "metadata": {},
106 | "outputs": [],
107 | "source": [
108 | "# Release resources\n",
109 | "rp.rp_Release()"
110 | ]
111 | }
112 | ],
113 | "metadata": {
114 | "language_info": {
115 | "name": "python"
116 | },
117 | "orig_nbformat": 4
118 | },
119 | "nbformat": 4,
120 | "nbformat_minor": 2
121 | }
122 |
123 |
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/basic/relay.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# RELAY CLICK \n",
8 | "\n",
9 | "## Libraries and FPGA image\n",
10 | "\n",
11 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {
18 | "collapsed": true
19 | },
20 | "outputs": [],
21 | "source": [
22 | "import time\n",
23 | "from rp_overlay import overlay\n",
24 | "import rp\n",
25 | "\n",
26 | "# Initialize the FPGA overlay\n",
27 | "fpga = overlay()\n",
28 | "rp.rp_Init()"
29 | ]
30 | },
31 | {
32 | "cell_type": "markdown",
33 | "metadata": {},
34 | "source": [
35 | "## Macros\n",
36 | "Here is a complete list of macros that will come in handy when customising this notebook and operating the click shields.\n",
37 | "\n",
38 | "- **States** - RP_LOW, RP_HIGH\n",
39 | "- **Directions** - RP_IN, RP_OUT\n",
40 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7\n",
41 | "- **DIOx_P** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
42 | "- **DIOx_N** - RP_DIO0_N, RP_DIO1_N, ..., RP_DIO7_N *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
43 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
44 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3\n",
45 | "\n",
46 | "### Click shield macros\n",
47 | "For easier work with the click shields, here are some macro rewrites. Marcos ending in \"1\" are on MicroBus1, and macros ending in \"2\" are on MicroBus2.\n",
48 | "\n",
49 | "- **AN1, AIN2** - RP_AIN0, RP_AIN1\n",
50 | "- **RST1, RST2** - RP_DIO2_N, RP_DIO4_N\n",
51 | "- **PWM1, PWM2** - RP_DIO1_P, RP_DIO3_P\n",
52 | "- **INT1, INT2** - RP_DIO2_P, RP_DIO4_P\n",
53 | "- **UART_SW** - RP_DIO5_N\n",
54 | "- **SPI_CS1, SPI_CS2** - RP_DIO1_N, RP_DIO3_N\n",
55 | "- **Logic analyser** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P\n",
56 | "\n",
57 | "Setting up click shield macros:"
58 | ]
59 | },
60 | {
61 | "cell_type": "code",
62 | "execution_count": null,
63 | "metadata": {},
64 | "outputs": [],
65 | "source": [
66 | "AN1 = rp.RP_AIN0\n",
67 | "AN2 = rp.RP_AIN1\n",
68 | "RST1 = rp.RP_DIO2_N\n",
69 | "RST2 = rp.RP_DIO4_N\n",
70 | "PWM1 = rp.RP_DIO1_P\n",
71 | "PWM2 = rp.RP_DIO3_P\n",
72 | "INT1 = rp.RP_DIO2_P\n",
73 | "INT2 = rp.RP_DIO4_P\n",
74 | "UART_SW = rp.RP_DIO5_N\n",
75 | "SPI_CS1 = rp.RP_DIO1_N\n",
76 | "SPI_CS2 = rp.RP_DIO3_N\n",
77 | "\n",
78 | "# Set the direction of mikrobus pins\n",
79 | "RL1 = SPI_CS1\n",
80 | "RL2 = PWM1\n",
81 | "\n",
82 | "rp.rp_DpinSetDirection(RL1, rp.RP_OUT)\n",
83 | "rp.rp_DpinSetDirection(RL2, rp.RP_OUT)"
84 | ]
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {},
89 | "source": [
90 | "The two relays on the click board can be closed on command. Consequently, the LEDs are turned ON on the Red Pitaya."
91 | ]
92 | },
93 | {
94 | "cell_type": "code",
95 | "execution_count": null,
96 | "metadata": {
97 | "collapsed": true
98 | },
99 | "outputs": [],
100 | "source": [
101 | "while True:\n",
102 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_HIGH)\n",
103 | " rp.rp_DpinSetState(RL1, rp.RP_HIGH)\n",
104 | " rp.rp_DpinSetState(RL2, rp.RP_HIGH)\n",
105 | " time.sleep(1)\n",
106 | " \n",
107 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_LOW)\n",
108 | " rp.rp_DpinSetState(RL1, rp.RP_LOW)\n",
109 | " rp.rp_DpinSetState(RL2, rp.RP_LOW)\n",
110 | " time.sleep(1)"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": null,
116 | "metadata": {},
117 | "outputs": [],
118 | "source": [
119 | "# Release resources\n",
120 | "rp.rp_Release()"
121 | ]
122 | }
123 | ],
124 | "metadata": {
125 | "kernelspec": {
126 | "display_name": "Python 3",
127 | "language": "python",
128 | "name": "python3"
129 | },
130 | "language_info": {
131 | "codemirror_mode": {
132 | "name": "ipython",
133 | "version": 3
134 | },
135 | "file_extension": ".py",
136 | "mimetype": "text/x-python",
137 | "name": "python",
138 | "nbconvert_exporter": "python",
139 | "pygments_lexer": "ipython3",
140 | "version": "3.5.2"
141 | }
142 | },
143 | "nbformat": 4,
144 | "nbformat_minor": 2
145 | }
146 |
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/click_board_examples.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "0595ebb4-5223-4f51-9da4-41d443f626d7",
6 | "metadata": {},
7 | "source": [
8 | "## JupyterLab Click Board examples for Red Pitaya\n",
9 | "\n",
10 | "Below you can find a few examples of how to control [MirkoE Click Boards](https://www.mikroe.com/) through your Red Pitaya with the [Click Shield](https://redpitaya.readthedocs.io/en/latest/developerGuide/hardware/ext_modules/click_shield.html#click-shield).\n",
11 | "\n",
12 | "To execute a cell click on it to change focus, and press the run button (⏵) above or press the key combination `Shift+Enter`."
13 | ]
14 | },
15 | {
16 | "cell_type": "markdown",
17 | "id": "f462a81a-b397-4976-9340-192770719809",
18 | "metadata": {},
19 | "source": [
20 | "1. **Basic:**\n",
21 | " 1. [Button G Click](basic/buttonG.ipynb)\n",
22 | " 0. [Capacitive Touch Click](basic/cap_touch.ipynb)\n",
23 | " 0. [Relay Click](basic/relay.ipynb)\n",
24 | "0. **Sensors:**\n",
25 | " 1. [Current Click](sensor/current.ipynb)\n",
26 | " 0. [Light Click](sensor/light.ipynb)\n",
27 | " 0. [Motion Click](sensor/motion.ipynb)\n",
28 | " 0. [Thermo 16 Click](sensor/thermo16.ipynb)\n",
29 | "0. **Motors:**\n",
30 | " 1. [DC Motor 2 Click](motor/dc_motor2.ipynb)\n",
31 | " 0. [Vibro Motor Click](motor/vibro_motor.ipynb)\n",
32 | "0. **Data:**\n",
33 | " 1. *Under construction...*\n"
34 | ]
35 | }
36 | ],
37 | "metadata": {
38 | "kernelspec": {
39 | "display_name": "Python 3 (ipykernel)",
40 | "language": "python",
41 | "name": "python3"
42 | },
43 | "language_info": {
44 | "codemirror_mode": {
45 | "name": "ipython",
46 | "version": 3
47 | },
48 | "file_extension": ".py",
49 | "mimetype": "text/x-python",
50 | "name": "python",
51 | "nbconvert_exporter": "python",
52 | "pygments_lexer": "ipython3",
53 | "version": "3.10.12"
54 | }
55 | },
56 | "nbformat": 4,
57 | "nbformat_minor": 5
58 | }
59 |
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/motor/vibro_motor.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# VIBRO MOTOR CLICK \n",
8 | "\n",
9 | "## Libraries and FPGA image\n",
10 | "\n",
11 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "import time\n",
21 | "from rp_overlay import overlay\n",
22 | "import rp\n",
23 | "\n",
24 | "# Initialize the FPGA overlay\n",
25 | "fpga = overlay()\n",
26 | "rp.rp_Init()"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "## Macros\n",
34 | "Here is a complete list of macros that will come in handy when customising this notebook and operating the click shields.\n",
35 | "\n",
36 | "- **States** - RP_LOW, RP_HIGH\n",
37 | "- **Directions** - RP_IN, RP_OUT\n",
38 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7\n",
39 | "- **DIOx_P** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
40 | "- **DIOx_N** - RP_DIO0_N, RP_DIO1_N, ..., RP_DIO7_N *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
41 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
42 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3\n",
43 | "\n",
44 | "### Click shield macros\n",
45 | "For easier work with the click shields, here are some macro rewrites. Marcos ending in \"1\" are on MicroBus1, and macros ending in \"2\" are on MicroBus2.\n",
46 | "\n",
47 | "- **AN1, AIN2** - RP_AIN0, RP_AIN1\n",
48 | "- **RST1, RST2** - RP_DIO2_N, RP_DIO4_N\n",
49 | "- **PWM1, PWM2** - RP_DIO1_P, RP_DIO3_P\n",
50 | "- **INT1, INT2** - RP_DIO2_P, RP_DIO4_P\n",
51 | "- **UART_SW** - RP_DIO5_N\n",
52 | "- **SPI_CS1, SPI_CS2** - RP_DIO1_N, RP_DIO3_N\n",
53 | "- **Logic analyser** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P\n",
54 | "\n",
55 | "Setting up click shield macros:"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "AN1 = rp.RP_AIN0\n",
65 | "AN2 = rp.RP_AIN1\n",
66 | "RST1 = rp.RP_DIO2_N\n",
67 | "RST2 = rp.RP_DIO4_N\n",
68 | "PWM1 = rp.RP_DIO1_P\n",
69 | "PWM2 = rp.RP_DIO3_P\n",
70 | "INT1 = rp.RP_DIO2_P\n",
71 | "INT2 = rp.RP_DIO4_P\n",
72 | "UART_SW = rp.RP_DIO5_N\n",
73 | "SPI_CS1 = rp.RP_DIO1_N\n",
74 | "SPI_CS2 = rp.RP_DIO3_N"
75 | ]
76 | },
77 | {
78 | "cell_type": "code",
79 | "execution_count": null,
80 | "metadata": {},
81 | "outputs": [],
82 | "source": [
83 | "# Define pin directions\n",
84 | "rp.rp_DpinSetDirection(PWM1, rp.RP_OUT)\n",
85 | "rp.rp_DpinSetDirection(PWM2, rp.RP_OUT)\n",
86 | "\n",
87 | "def pwm(pin, duty_cycle, num_seconds):\n",
88 | " period_us = 875\n",
89 | " pulse_us = (duty_cycle * period_us) / 100\n",
90 | " num_periods = 0\n",
91 | " \n",
92 | " while True:\n",
93 | " if num_periods == num_seconds * 1000:\n",
94 | " break\n",
95 | " rp.rp_DpinSetState(pin, rp.RP_HIGH)\n",
96 | " time.sleep(pulse_us / 1000000)\n",
97 | " rp.rp_DpinSetState(pin, rp.RP_HIGH)\n",
98 | " time.sleep((period_us - pulse_us) / 1000000)\n",
99 | " num_periods += 1"
100 | ]
101 | },
102 | {
103 | "cell_type": "markdown",
104 | "metadata": {},
105 | "source": [
106 | "The example turns on an LED for 3 seconds, then runs the motor connected to the PWM pin at 50% power for 3 seconds."
107 | ]
108 | },
109 | {
110 | "cell_type": "code",
111 | "execution_count": null,
112 | "metadata": {},
113 | "outputs": [],
114 | "source": [
115 | "# turn on\n",
116 | "rp.rp_DpinSetState(rp.RP_LED0, rp.RP_HIGH)\n",
117 | "\n",
118 | "# run motor at 50% duty cycle for 3 seconds\n",
119 | "pwm(PWM1, 50, 3)\n",
120 | "# the motor doesn't run at less than 30% power\n",
121 | "\n",
122 | "# turn off\n",
123 | "rp.rp_DpinSetState(rp.RP_LED0, rp.RP_LOW)"
124 | ]
125 | },
126 | {
127 | "cell_type": "code",
128 | "execution_count": null,
129 | "metadata": {},
130 | "outputs": [],
131 | "source": [
132 | "# Release resources\n",
133 | "rp.rp_Release()"
134 | ]
135 | }
136 | ],
137 | "metadata": {
138 | "kernelspec": {
139 | "display_name": "Python 3",
140 | "language": "python",
141 | "name": "python3"
142 | },
143 | "language_info": {
144 | "codemirror_mode": {
145 | "name": "ipython",
146 | "version": 3
147 | },
148 | "file_extension": ".py",
149 | "mimetype": "text/x-python",
150 | "name": "python",
151 | "nbconvert_exporter": "python",
152 | "pygments_lexer": "ipython3",
153 | "version": "3.5.2"
154 | }
155 | },
156 | "nbformat": 4,
157 | "nbformat_minor": 2
158 | }
159 |
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/sensor/current.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# CURRENT CLICK \n",
8 | "\n",
9 | "## Libraries and FPGA image\n",
10 | "\n",
11 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "import time\n",
21 | "from rp_overlay import overlay\n",
22 | "import rp\n",
23 | "\n",
24 | "# Initialize the FPGA overlay\n",
25 | "fpga = overlay()\n",
26 | "rp.rp_Init()"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "## Macros\n",
34 | "Here is a complete list of macros that will come in handy when customising this notebook and operating the click shields.\n",
35 | "\n",
36 | "- **States** - RP_LOW, RP_HIGH\n",
37 | "- **Directions** - RP_IN, RP_OUT\n",
38 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7\n",
39 | "- **DIOx_P** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
40 | "- **DIOx_N** - RP_DIO0_N, RP_DIO1_N, ..., RP_DIO7_N *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
41 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
42 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3\n",
43 | "\n",
44 | "### Click shield macros\n",
45 | "For easier work with the click shields, here are some macro rewrites. Marcos ending in \"1\" are on MicroBus1, and macros ending in \"2\" are on MicroBus2.\n",
46 | "\n",
47 | "- **AN1, AIN2** - RP_AIN0, RP_AIN1\n",
48 | "- **RST1, RST2** - RP_DIO2_N, RP_DIO4_N\n",
49 | "- **PWM1, PWM2** - RP_DIO1_P, RP_DIO3_P\n",
50 | "- **INT1, INT2** - RP_DIO2_P, RP_DIO4_P\n",
51 | "- **UART_SW** - RP_DIO5_N\n",
52 | "- **SPI_CS1, SPI_CS2** - RP_DIO1_N, RP_DIO3_N\n",
53 | "- **Logic analyser** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P\n",
54 | "\n",
55 | "Setting up click shield macros:"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "AN1 = rp.RP_AIN0\n",
65 | "AN2 = rp.RP_AIN1\n",
66 | "RST1 = rp.RP_DIO2_N\n",
67 | "RST2 = rp.RP_DIO4_N\n",
68 | "PWM1 = rp.RP_DIO1_P\n",
69 | "PWM2 = rp.RP_DIO3_P\n",
70 | "INT1 = rp.RP_DIO2_P\n",
71 | "INT2 = rp.RP_DIO4_P\n",
72 | "UART_SW = rp.RP_DIO5_N\n",
73 | "SPI_CS1 = rp.RP_DIO1_N\n",
74 | "SPI_CS2 = rp.RP_DIO3_N\n",
75 | "\n",
76 | "# Reset analog pins\n",
77 | "rp.rp_ApinReset()\n",
78 | "\n",
79 | "AIN = AN1"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": null,
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "def convert_to_engineering_unit(number, units):\n",
89 | " magnitude = number\n",
90 | " unit_index = 0\n",
91 | "\n",
92 | " while magnitude <= 1.0 and unit_index < len(units) - 1:\n",
93 | " magnitude *= 1000.0\n",
94 | " unit_index += 1\n",
95 | "\n",
96 | " print(\"Value: {:.4f} {} \\n\".format(magnitude, units[unit_index]))\n",
97 | "\n",
98 | "def get_current(pin, resistor_value):\n",
99 | " # Get ADC value from the specified pin\n",
100 | " value = rp.rp_ApinGetValue(pin)[1]\n",
101 | " max_current = 3.3 / (20.0 * resistor_value)\n",
102 | " print(\"Minimum current is 2mA, maximum is:\")\n",
103 | " convert_to_engineering_unit(max_current, [\"A\", \"mA\", \"μA\", \"nA\"])\n",
104 | "\n",
105 | " # Calculate current\n",
106 | " voltage = value / 20.0\n",
107 | " # gain of circuit is 20\n",
108 | " current = voltage / resistor_value\n",
109 | "\n",
110 | " return current\n",
111 | "\n",
112 | "def recommend_resistor(current):\n",
113 | " if current != 0:\n",
114 | " resistor = 0.075 / current\n",
115 | " print(\"The recommended resistor value for best measurement (R) is {:.4f} ohms.\\n\".format(resistor))\n",
116 | " return resistor\n",
117 | " else:\n",
118 | " print(\"Error: Current (I) cannot be zero.\\n\")\n",
119 | " return -1\n",
120 | " # Return -1 to indicate an error"
121 | ]
122 | },
123 | {
124 | "cell_type": "markdown",
125 | "metadata": {},
126 | "source": [
127 | "The example shows how to read the current through a shunt resistor. The program, however, does not know how many ohms your shunt resistor has. That is why the shunt resistor value must be input when prompted by the program. Also, the shunt resistor should be accurate to at least three decimals (for example, with a multimeter). That way, the current measurement will be most accurate.\n",
128 | "\n",
129 | "Refrain from going above or below the minimum and maximum current measurement.\n",
130 | "\n",
131 | "For best measurements, please use the recommended resistor."
132 | ]
133 | },
134 | {
135 | "cell_type": "code",
136 | "execution_count": null,
137 | "metadata": {},
138 | "outputs": [],
139 | "source": [
140 | "while True:\n",
141 | " print(\"Enter shunt resistor value in Ohms: \")\n",
142 | " # circuit 5 ohms\n",
143 | " resistor_value = float(input())\n",
144 | " current = get_current(AIN, resistor_value)\n",
145 | "\n",
146 | " convert_to_engineering_unit(current, [\"A\", \"mA\", \"μA\", \"nA\"])\n",
147 | " recommend_resistor(current)\n",
148 | " time.sleep(1)"
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "execution_count": null,
154 | "metadata": {},
155 | "outputs": [],
156 | "source": [
157 | "# Release resources\n",
158 | "rp.rp_Release()"
159 | ]
160 | }
161 | ],
162 | "metadata": {
163 | "language_info": {
164 | "name": "python"
165 | },
166 | "orig_nbformat": 4
167 | },
168 | "nbformat": 4,
169 | "nbformat_minor": 2
170 | }
171 |
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/sensor/light.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# LIGHT CLICK \n",
8 | "\n",
9 | "## Libraries and FPGA image\n",
10 | "\n",
11 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "import time\n",
21 | "from rp_overlay import overlay\n",
22 | "import rp\n",
23 | "\n",
24 | "# Initialize the FPGA overlay\n",
25 | "fpga = overlay()\n",
26 | "rp.rp_Init()"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "## Macros\n",
34 | "Here is a complete list of macros that will come in handy when customising this notebook and operating the click shields.\n",
35 | "\n",
36 | "- **States** - RP_LOW, RP_HIGH\n",
37 | "- **Directions** - RP_IN, RP_OUT\n",
38 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7\n",
39 | "- **DIOx_P** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
40 | "- **DIOx_N** - RP_DIO0_N, RP_DIO1_N, ..., RP_DIO7_N *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
41 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
42 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3\n",
43 | "\n",
44 | "### Click shield macros\n",
45 | "For easier work with the click shields, here are some macro rewrites. Marcos ending in \"1\" are on MicroBus1, and macros ending in \"2\" are on MicroBus2.\n",
46 | "\n",
47 | "- **AN1, AIN2** - RP_AIN0, RP_AIN1\n",
48 | "- **RST1, RST2** - RP_DIO2_N, RP_DIO4_N\n",
49 | "- **PWM1, PWM2** - RP_DIO1_P, RP_DIO3_P\n",
50 | "- **INT1, INT2** - RP_DIO2_P, RP_DIO4_P\n",
51 | "- **UART_SW** - RP_DIO5_N\n",
52 | "- **SPI_CS1, SPI_CS2** - RP_DIO1_N, RP_DIO3_N\n",
53 | "- **Logic analyser** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P\n",
54 | "\n",
55 | "Setting up click shield macros:"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "AN1 = rp.RP_AIN0\n",
65 | "AN2 = rp.RP_AIN1\n",
66 | "RST1 = rp.RP_DIO2_N\n",
67 | "RST2 = rp.RP_DIO4_N\n",
68 | "PWM1 = rp.RP_DIO1_P\n",
69 | "PWM2 = rp.RP_DIO3_P\n",
70 | "INT1 = rp.RP_DIO2_P\n",
71 | "INT2 = rp.RP_DIO4_P\n",
72 | "UART_SW = rp.RP_DIO5_N\n",
73 | "SPI_CS1 = rp.RP_DIO1_N\n",
74 | "SPI_CS2 = rp.RP_DIO3_N\n",
75 | "\n",
76 | "# Reset analog pins\n",
77 | "rp.rp_ApinReset()\n",
78 | "\n",
79 | "AIN = AN1"
80 | ]
81 | },
82 | {
83 | "cell_type": "markdown",
84 | "metadata": {},
85 | "source": [
86 | "The example measures light intensity by reading the analog value and displays whether it is light or dark. If the sensor is covered or the light intensity is below the threshold, the program prints that it is dark."
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": null,
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "while True:\n",
96 | " # Get light value\n",
97 | " value = rp.rp_ApinGetValue(AIN)[1]\n",
98 | " print(\"Measured voltage on AI[{}] = {}V\\n\".format(0, value))\n",
99 | " if value >= 2.0:\n",
100 | " # Turn on light based on read value\n",
101 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_HIGH)\n",
102 | " print(\"It is light\\n\")\n",
103 | " elif value <= 0.5:\n",
104 | " # Turn off light based on read value\n",
105 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_LOW)\n",
106 | " print(\"It is dark\\n\")\n",
107 | " else:\n",
108 | " print(\"It is gloomy\\n\")\n",
109 | "\n",
110 | " time.sleep(1)"
111 | ]
112 | },
113 | {
114 | "cell_type": "code",
115 | "execution_count": null,
116 | "metadata": {},
117 | "outputs": [],
118 | "source": [
119 | "# Release resources\n",
120 | "rp.rp_Release()"
121 | ]
122 | }
123 | ],
124 | "metadata": {
125 | "language_info": {
126 | "name": "python"
127 | },
128 | "orig_nbformat": 4
129 | },
130 | "nbformat": 4,
131 | "nbformat_minor": 2
132 | }
133 |
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/sensor/motion.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# MOTION CLICK \n",
8 | "\n",
9 | "## Libraries and FPGA image\n",
10 | "\n",
11 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "import time\n",
21 | "from rp_overlay import overlay\n",
22 | "import rp\n",
23 | "\n",
24 | "# Initialize the FPGA overlay\n",
25 | "fpga = overlay()\n",
26 | "rp.rp_Init()"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "## Macros\n",
34 | "Here is a complete list of macros that will come in handy when customising this notebook and operating the click shields.\n",
35 | "\n",
36 | "- **States** - RP_LOW, RP_HIGH\n",
37 | "- **Directions** - RP_IN, RP_OUT\n",
38 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7\n",
39 | "- **DIOx_P** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
40 | "- **DIOx_N** - RP_DIO0_N, RP_DIO1_N, ..., RP_DIO7_N *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
41 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
42 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3\n",
43 | "\n",
44 | "### Click shield macros\n",
45 | "For easier work with the click shields, here are some macro rewrites. Marcos ending in \"1\" are on MicroBus1, and macros ending in \"2\" are on MicroBus2.\n",
46 | "\n",
47 | "- **AN1, AIN2** - RP_AIN0, RP_AIN1\n",
48 | "- **RST1, RST2** - RP_DIO2_N, RP_DIO4_N\n",
49 | "- **PWM1, PWM2** - RP_DIO1_P, RP_DIO3_P\n",
50 | "- **INT1, INT2** - RP_DIO2_P, RP_DIO4_P\n",
51 | "- **UART_SW** - RP_DIO5_N\n",
52 | "- **SPI_CS1, SPI_CS2** - RP_DIO1_N, RP_DIO3_N\n",
53 | "- **Logic analyser** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P\n",
54 | "\n",
55 | "Setting up click shield macros:"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "AN1 = rp.RP_AIN0\n",
65 | "AN2 = rp.RP_AIN1\n",
66 | "RST1 = rp.RP_DIO2_N\n",
67 | "RST2 = rp.RP_DIO4_N\n",
68 | "PWM1 = rp.RP_DIO1_P\n",
69 | "PWM2 = rp.RP_DIO3_P\n",
70 | "INT1 = rp.RP_DIO2_P\n",
71 | "INT2 = rp.RP_DIO4_P\n",
72 | "UART_SW = rp.RP_DIO5_N\n",
73 | "SPI_CS1 = rp.RP_DIO1_N\n",
74 | "SPI_CS2 = rp.RP_DIO3_N\n",
75 | "\n",
76 | "\n",
77 | "# Define pin directions\n",
78 | "rp.rp_DpinSetDirection(INT1, rp.RP_IN)\n",
79 | "rp.rp_DpinSetDirection(INT2, rp.RP_IN)"
80 | ]
81 | },
82 | {
83 | "cell_type": "markdown",
84 | "metadata": {},
85 | "source": [
86 | "Every second, the example program checks if any motion was detected."
87 | ]
88 | },
89 | {
90 | "cell_type": "code",
91 | "execution_count": null,
92 | "metadata": {},
93 | "outputs": [],
94 | "source": [
95 | "while True:\n",
96 | " # Get the state of the button\n",
97 | " state = rp.rp_DpinSetState(INT1, rp.RP_HIGH)\n",
98 | "\n",
99 | " # Turn on the LED based on the button state\n",
100 | " if state:\n",
101 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_HIGH) # Turn on LED0\n",
102 | " print(\"Must have been the wind...\\n\")\n",
103 | " else:\n",
104 | " rp.rp_DpinSetState(rp.RP_LED0, rp.RP_LOW) # Turn off LED0\n",
105 | " print(\"Everything is quiet\\n\")\n",
106 | "\n",
107 | " time.sleep(1)"
108 | ]
109 | },
110 | {
111 | "cell_type": "code",
112 | "execution_count": null,
113 | "metadata": {},
114 | "outputs": [],
115 | "source": [
116 | "# Release resources\n",
117 | "rp.rp_Release()"
118 | ]
119 | }
120 | ],
121 | "metadata": {
122 | "kernelspec": {
123 | "display_name": "Python 3",
124 | "language": "python",
125 | "name": "python3"
126 | },
127 | "language_info": {
128 | "codemirror_mode": {
129 | "name": "ipython",
130 | "version": 3
131 | },
132 | "file_extension": ".py",
133 | "mimetype": "text/x-python",
134 | "name": "python",
135 | "nbconvert_exporter": "python",
136 | "pygments_lexer": "ipython3",
137 | "version": "3.5.2"
138 | }
139 | },
140 | "nbformat": 4,
141 | "nbformat_minor": 2
142 | }
143 |
--------------------------------------------------------------------------------
/examples/click_shield_examples/click_board_examples/sensor/thermo16.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# THERMO 16 CLICK \n",
8 | "\n",
9 | "## Libraries and FPGA image\n",
10 | "\n",
11 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
12 | ]
13 | },
14 | {
15 | "cell_type": "code",
16 | "execution_count": null,
17 | "metadata": {},
18 | "outputs": [],
19 | "source": [
20 | "import time\n",
21 | "from rp_overlay import overlay\n",
22 | "import rp\n",
23 | "\n",
24 | "# Initialize the FPGA overlay\n",
25 | "fpga = overlay()\n",
26 | "rp.rp_Init()"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "## Macros\n",
34 | "Here is a complete list of macros that will come in handy when customising this notebook and operating the click shields.\n",
35 | "\n",
36 | "- **States** - RP_LOW, RP_HIGH\n",
37 | "- **Directions** - RP_IN, RP_OUT\n",
38 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7\n",
39 | "- **DIOx_P** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
40 | "- **DIOx_N** - RP_DIO0_N, RP_DIO1_N, ..., RP_DIO7_N *# Goes up to 9 on SDRlab and STEMlab 4-Input*\n",
41 | "- **Analog outputs** - RP_AOUT0, RP_AOUT1, ..., RP_AOUT3\n",
42 | "- **Analog inputs** - RP_AIN0, RP_AIN1, ..., RP_AIN3\n",
43 | "\n",
44 | "### Click shield macros\n",
45 | "For easier work with the click shields, here are some macro rewrites. Marcos ending in \"1\" are on MicroBus1, and macros ending in \"2\" are on MicroBus2.\n",
46 | "\n",
47 | "- **AN1, AIN2** - RP_AIN0, RP_AIN1\n",
48 | "- **RST1, RST2** - RP_DIO2_N, RP_DIO4_N\n",
49 | "- **PWM1, PWM2** - RP_DIO1_P, RP_DIO3_P\n",
50 | "- **INT1, INT2** - RP_DIO2_P, RP_DIO4_P\n",
51 | "- **UART_SW** - RP_DIO5_N\n",
52 | "- **SPI_CS1, SPI_CS2** - RP_DIO1_N, RP_DIO3_N\n",
53 | "- **Logic analyser** - RP_DIO0_P, RP_DIO1_P, ..., RP_DIO7_P\n",
54 | "\n",
55 | "Setting up click shield macros:"
56 | ]
57 | },
58 | {
59 | "cell_type": "code",
60 | "execution_count": null,
61 | "metadata": {},
62 | "outputs": [],
63 | "source": [
64 | "AN1 = rp.RP_AIN0\n",
65 | "AN2 = rp.RP_AIN1\n",
66 | "RST1 = rp.RP_DIO2_N\n",
67 | "RST2 = rp.RP_DIO4_N\n",
68 | "PWM1 = rp.RP_DIO1_P\n",
69 | "PWM2 = rp.RP_DIO3_P\n",
70 | "INT1 = rp.RP_DIO2_P\n",
71 | "INT2 = rp.RP_DIO4_P\n",
72 | "UART_SW = rp.RP_DIO5_N\n",
73 | "SPI_CS1 = rp.RP_DIO1_N\n",
74 | "SPI_CS2 = rp.RP_DIO3_N\n",
75 | "\n",
76 | "# Reset analog pins\n",
77 | "rp.rp_ApinReset()\n",
78 | "\n",
79 | "AIN = AN1"
80 | ]
81 | },
82 | {
83 | "cell_type": "code",
84 | "execution_count": null,
85 | "metadata": {},
86 | "outputs": [],
87 | "source": [
88 | "print(f\"Measured voltage on Analog pin is {rp.rp_ApinGetValue(AIN)[1]:.2f} V\\n\")\n",
89 | "\n",
90 | "def get_average_temperature():\n",
91 | " values = []\n",
92 | " sum = 0.0\n",
93 | " for i in range(0, 30):\n",
94 | " # read analog input value from Red Pitaya\n",
95 | " values.append(rp.rp_ApinGetValue(AIN)[1])\n",
96 | " sum += values[i]\n",
97 | " time.sleep(0.05)\n",
98 | " average = sum / 30.0\n",
99 | " return (average -0.53) * 100.0\n",
100 | "\n",
101 | " # TEMP_IN_CELSIUS;\n",
102 | " # standard deviation = ABSOLUTE MISTAKE / Sqrt(3) = 1,25 °C / Sqrt(3) = 0.72 °C\n",
103 | " # with 68% certainty\n",
104 | " # uncertainty due to repeated measurements can be disregarded"
105 | ]
106 | },
107 | {
108 | "cell_type": "markdown",
109 | "metadata": {},
110 | "source": [
111 | "The example shows how to measure temperature. If the Thermo16 Click Board is too close to the Red Pitaya (directly mounted on the Click Shield), the temperature measurements can be affected by the Red Pitaya's heating."
112 | ]
113 | },
114 | {
115 | "cell_type": "code",
116 | "execution_count": null,
117 | "metadata": {},
118 | "outputs": [],
119 | "source": [
120 | "temperature = get_average_temperature()\n",
121 | "correction= -9.0 \n",
122 | "# ADD A DIFFRENT CORRECTION IF NECESSARY;\n",
123 | "temperature = temperature + correction\n",
124 | "\n",
125 | "print(f\"Measured TEMP_IN_KELVIN = {temperature + 273.15:.4f}°C +- 0.72°C \\n\")\n",
126 | "print(f\"Measured TEMP_IN_FARENHEIT = {(temperature * 9.0/5.0) + 32.0:.4f}°F +- 1.3°F \\n\")\n",
127 | "print(f\"Measured TEMP_IN_CELSIUS = {temperature:.4f}°C +- 0.72°C\\n\")"
128 | ]
129 | },
130 | {
131 | "cell_type": "code",
132 | "execution_count": null,
133 | "metadata": {},
134 | "outputs": [],
135 | "source": [
136 | "# Release resources\n",
137 | "rp.rp_Release()"
138 | ]
139 | }
140 | ],
141 | "metadata": {
142 | "language_info": {
143 | "name": "python"
144 | },
145 | "orig_nbformat": 4
146 | },
147 | "nbformat": 4,
148 | "nbformat_minor": 2
149 | }
150 |
--------------------------------------------------------------------------------
/examples/digital/led.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Drive LEDs\n",
8 | "\n",
9 | "This example shows how to control LEDs on a Red Pitaya board."
10 | ]
11 | },
12 | {
13 | "cell_type": "markdown",
14 | "metadata": {},
15 | "source": [
16 | ""
17 | ]
18 | },
19 | {
20 | "cell_type": "markdown",
21 | "metadata": {},
22 | "source": [
23 | "## Libraries and FPGA image\n",
24 | "\n",
25 | "The first thing we need to do is import the *time*, *rp* (Red Pitaya), and *rp_overlay* libraries.\n",
26 | "Then, we load the *v0.94* FPGA image into the Xilinx Zynq 7010 SoC and finally initialize the Red Pitaya.\n",
27 | "\n",
28 | "We will do this by clicking on the following cell to select it and pressing the run button (⏵) above or the key combination *Shift+Enter*."
29 | ]
30 | },
31 | {
32 | "cell_type": "code",
33 | "execution_count": null,
34 | "metadata": {},
35 | "outputs": [],
36 | "source": [
37 | "import time\n",
38 | "from rp_overlay import overlay\n",
39 | "import rp\n",
40 | "\n",
41 | "fpga = overlay()\n",
42 | "rp.rp_Init()"
43 | ]
44 | },
45 | {
46 | "cell_type": "markdown",
47 | "metadata": {},
48 | "source": [
49 | "## Macros\n",
50 | "Throughout this tutorial we will mention macros multiple times. Here is a complete list of digital macros that will come in handy when customising this notebook. The marcos are a part of the **rp** library.\n",
51 | "\n",
52 | "- **States** - RP_LOW, RP_HIGH\n",
53 | "- **LEDs** - RP_LED0, RP_LED1, ..., RP_LED7"
54 | ]
55 | },
56 | {
57 | "cell_type": "markdown",
58 | "metadata": {},
59 | "source": [
60 | "## LEDs"
61 | ]
62 | },
63 | {
64 | "cell_type": "markdown",
65 | "metadata": {},
66 | "source": [
67 | "There are eight orange LEDs on the Red Pitaya board. We need to tell Python which LED we want to control. Each bit corresponds to an LED; 1st bit (*LSB*) to *LED0*, 2nd bit to *LED1*, ..., and 8th (*MSB*) to *LED7*. If a specific bit is set to 1 (*HIGH*), the LED is turned *on*. Otherwise (the bit is 0 (*LOW*)), the LED is turned *off*. To configure the LED, we can use one of the following functions:\n",
68 | "- **rp_LEDSetState(8-bit_state)**\n",
69 | "\n",
70 | "Alternatively, use LED macros to turn *on*/*off* a specific LED:\n",
71 | "- **rp_DpinSetState(led_macro, led_state)**\n",
72 | "\n",
73 | "Here are examples of how to turn *on LED1*."
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": null,
79 | "metadata": {
80 | "collapsed": true,
81 | "jupyter": {
82 | "outputs_hidden": true
83 | }
84 | },
85 | "outputs": [],
86 | "source": [
87 | "led1 = 0b00000010\n",
88 | "rp.rp_LEDSetState(led1)"
89 | ]
90 | },
91 | {
92 | "cell_type": "markdown",
93 | "metadata": {},
94 | "source": [
95 | "Using macros:"
96 | ]
97 | },
98 | {
99 | "cell_type": "code",
100 | "execution_count": null,
101 | "metadata": {},
102 | "outputs": [],
103 | "source": [
104 | "rp.rp_DpinSetState(rp.RP_LED1, rp.RP_HIGH)"
105 | ]
106 | },
107 | {
108 | "cell_type": "markdown",
109 | "metadata": {},
110 | "source": [
111 | "To read the LED states use the following functions:\n",
112 | "- **rp_LEDGetState()**\n",
113 | "- **rp_DpinGetState(led_macro)**\n",
114 | "\n",
115 | "When reading the LED states with the first function, we must extract a specific bit. When checking if the LED is *on* we are searching for a result greater than 0 (or comparing it to power of 2). Here is an example:"
116 | ]
117 | },
118 | {
119 | "cell_type": "code",
120 | "execution_count": null,
121 | "metadata": {},
122 | "outputs": [],
123 | "source": [
124 | "led_values = rp.rp_LEDGetState()[1] # Reading state of all LEDs\n",
125 | "print(f\"LED states: {led_values}\")\n",
126 | "\n",
127 | "led1_state = led_values & led1 # Extracting the 2nd bit\n",
128 | "print(f\"LED1 state: {led1_state}\")\n",
129 | "\n",
130 | "if led1_state > 0: # or led1_state == pow(2,1)\n",
131 | " print(\"LED1 ON\")\n",
132 | "else:\n",
133 | " print(\"LED1 OFF\")"
134 | ]
135 | },
136 | {
137 | "cell_type": "markdown",
138 | "metadata": {},
139 | "source": [
140 | "Using macros:"
141 | ]
142 | },
143 | {
144 | "cell_type": "code",
145 | "execution_count": null,
146 | "metadata": {},
147 | "outputs": [],
148 | "source": [
149 | "led1_state = rp.rp_DpinGetState(rp.RP_LED1)[1]\n",
150 | "print(f\"LED1 state: {led1_state}\")"
151 | ]
152 | },
153 | {
154 | "cell_type": "markdown",
155 | "metadata": {},
156 | "source": [
157 | "To turn all LEDs *off* execute the following cell."
158 | ]
159 | },
160 | {
161 | "cell_type": "code",
162 | "execution_count": null,
163 | "metadata": {
164 | "collapsed": true,
165 | "jupyter": {
166 | "outputs_hidden": true
167 | }
168 | },
169 | "outputs": [],
170 | "source": [
171 | "rp.rp_LEDSetState(0)"
172 | ]
173 | },
174 | {
175 | "cell_type": "markdown",
176 | "metadata": {},
177 | "source": [
178 | "Alternatively, all LEDs can be turned *off* one by one using macros."
179 | ]
180 | },
181 | {
182 | "cell_type": "markdown",
183 | "metadata": {},
184 | "source": [
185 | "## Blink LED\n",
186 | "\n",
187 | "To make an LED blink, we need to write a loop turning the LED *on* and *off*. We will use the *time* library so we can slow down the execution of the cell so we can see the LED blinking."
188 | ]
189 | },
190 | {
191 | "cell_type": "markdown",
192 | "metadata": {},
193 | "source": [
194 | " 1. Turn the LED *on* and *off* 10 times every half a second."
195 | ]
196 | },
197 | {
198 | "cell_type": "code",
199 | "execution_count": null,
200 | "metadata": {
201 | "collapsed": true,
202 | "jupyter": {
203 | "outputs_hidden": true
204 | }
205 | },
206 | "outputs": [],
207 | "source": [
208 | "for i in range(10):\n",
209 | " rp.rp_LEDSetState(led1)\n",
210 | " time.sleep(0.5)\n",
211 | " rp.rp_LEDSetState(0)\n",
212 | " time.sleep(0.5)"
213 | ]
214 | },
215 | {
216 | "cell_type": "code",
217 | "execution_count": null,
218 | "metadata": {},
219 | "outputs": [],
220 | "source": [
221 | "for i in range(10):\n",
222 | " rp.rp_DpinSetState(rp.RP_LED1, rp.RP_HIGH)\n",
223 | " time.sleep(0.5)\n",
224 | " rp.rp_DpinSetState(rp.RP_LED1, rp.RP_LOW)\n",
225 | " time.sleep(0.5)"
226 | ]
227 | },
228 | {
229 | "cell_type": "markdown",
230 | "metadata": {},
231 | "source": [
232 | "Finaly, at the end of the program, we should always release the used resources. Execute the following cell."
233 | ]
234 | },
235 | {
236 | "cell_type": "code",
237 | "execution_count": null,
238 | "metadata": {
239 | "collapsed": true,
240 | "jupyter": {
241 | "outputs_hidden": true
242 | }
243 | },
244 | "outputs": [],
245 | "source": [
246 | "rp.rp_Release()"
247 | ]
248 | },
249 | {
250 | "cell_type": "markdown",
251 | "metadata": {},
252 | "source": [
253 | "### Note\n",
254 | "All Python API functions internally call corresponding C functions. Therefore, they always return an integer value depending on their successful execution (**0 - success**, **!=0 - error**). "
255 | ]
256 | }
257 | ],
258 | "metadata": {
259 | "kernelspec": {
260 | "display_name": "Python 3 (ipykernel)",
261 | "language": "python",
262 | "name": "python3"
263 | },
264 | "language_info": {
265 | "codemirror_mode": {
266 | "name": "ipython",
267 | "version": 3
268 | },
269 | "file_extension": ".py",
270 | "mimetype": "text/x-python",
271 | "name": "python",
272 | "nbconvert_exporter": "python",
273 | "pygments_lexer": "ipython3",
274 | "version": "3.10.12"
275 | }
276 | },
277 | "nbformat": 4,
278 | "nbformat_minor": 4
279 | }
280 |
--------------------------------------------------------------------------------
/examples/generation/gen_burst_async_signals.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Generate two burst asynced signals\n",
8 | "This example shows how to generate two asynced analog burst signals."
9 | ]
10 | },
11 | {
12 | "cell_type": "markdown",
13 | "metadata": {},
14 | "source": [
15 | "## Libraries and FPGA image"
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": null,
21 | "metadata": {},
22 | "outputs": [],
23 | "source": [
24 | "import time\n",
25 | "from rp_overlay import overlay\n",
26 | "import rp\n",
27 | "\n",
28 | "fpga = overlay()\n",
29 | "rp.rp_Init()"
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {},
35 | "source": [
36 | "## Macros\n",
37 | "Throughout this tutorial we will mention macros multiple times. Here is a complete list of macros that will come in handy when customising this notebook. The marcos are a part of the **rp** library.\n",
38 | "\n",
39 | "- **Waveforms** - RP_WAVEFORM_SINE, RP_WAVEFORM_SQUARE, RP_WAVEFORM_TRIANGLE, RP_WAVEFORM_RAMP_UP, RP_WAVEFORM_RAMP_DOWN, RP_WAVEFORM_DC, RP_WAVEFORM_PWM, RP_WAVEFORM_ARBITRARY, RP_WAVEFORM_DC_NEG, RP_WAVEFORM_SWEEP\n",
40 | "- **Generator modes** - RP_GEN_MODE_CONTINUOUS, RP_GEN_MODE_BURST\n",
41 | "- **Sweep direction** - RP_GEN_SWEEP_DIR_NORMAL, RP_GEN_SWEEP_DIR_UP_DOWN\n",
42 | "- **Sweep mode** - RP_GEN_SWEEP_MODE_LINEAR, RP_GEN_SWEEP_MODE_LOG\n",
43 | "- **Generator trigger source** - RP_GEN_TRIG_SRC_INTERNAL, RP_GEN_TRIG_SRC_EXT_PE, RP_GEN_TRIG_SRC_EXT_NE\n",
44 | "- **Fast analog channels** - RP_CH_1, RP_CH_2\n",
45 | "- **Fast analog triggers** - RP_T_CH_1, RP_T_CH_2, RP_T_CH_EXT\n",
46 | "- **Rise and fall times** - RISE_FALL_MIN_RATIO, RISE_FALL_MAX_RATIO\n",
47 | "\n",
48 | "SIGNALlab 250-12 only:\n",
49 | "- **Generator gain** - RP_GAIN_1X, RP_GAIN_5X\n",
50 | "\n",
51 | "STEMlab 125-14 4-Input only:\n",
52 | "- **Fast analog channels** - RP_CH_3, RP_CH_4\n",
53 | "- **Fast analog triggers** - RP_T_CH_3, RP_T_CH_4\n"
54 | ]
55 | },
56 | {
57 | "cell_type": "markdown",
58 | "metadata": {},
59 | "source": [
60 | "## Asynchronised signals\n",
61 | "Here is a quick reference guide to the functions used:\n",
62 | "- **rp_GenOutEnable(output_channel)** - supplies voltage on the specified output (voltage set with **rp_GenSetInitGenValue** appears on the output), but does not generate a signal\n",
63 | "- **rp_GenOutEnableSync()** - supplies voltage on both outputs (voltage set with **rp_GenSetInitGenValue** appears on the outputs), but does not generate a signal.\n",
64 | "- **rp_GenTriggerOnly(output_channel)** - triggers signal generation on the specified output\n",
65 | "- **rp_GenSynchronise()** - triggers both signal generators at the same time (sychronised)"
66 | ]
67 | },
68 | {
69 | "cell_type": "code",
70 | "execution_count": null,
71 | "metadata": {},
72 | "outputs": [],
73 | "source": [
74 | "channel = rp.RP_CH_1 # rp.RP_CH_2\n",
75 | "channel2 = rp.RP_CH_2\n",
76 | "waveform = rp.RP_WAVEFORM_SINE\n",
77 | "freq = 10000\n",
78 | "ampl = 1\n",
79 | "\n",
80 | "ncyc = 2\n",
81 | "nor = 1\n",
82 | "period = 50\n",
83 | "\n",
84 | "\n",
85 | "# Reset generator\n",
86 | "rp.rp_GenReset()\n",
87 | "\n",
88 | "###### Generation #####\n",
89 | "# OUT1\n",
90 | "rp.rp_GenWaveform(channel, waveform)\n",
91 | "rp.rp_GenFreqDirect(channel, freq)\n",
92 | "rp.rp_GenAmp(channel, ampl)\n",
93 | "\n",
94 | "# Change to burst mode\n",
95 | "rp.rp_GenMode(channel, rp.RP_GEN_MODE_BURST)\n",
96 | "rp.rp_GenBurstCount(channel, ncyc) # Ncyc\n",
97 | "rp.rp_GenBurstRepetitions(channel, nor) # Nor\n",
98 | "rp.rp_GenBurstPeriod(channel, period) # Period\n",
99 | "\n",
100 | "# OUT2\n",
101 | "rp.rp_GenWaveform(channel2, waveform)\n",
102 | "rp.rp_GenFreqDirect(channel2, freq)\n",
103 | "rp.rp_GenAmp(channel2, ampl)\n",
104 | "\n",
105 | "# Change to burst mode\n",
106 | "rp.rp_GenMode(channel2, rp.RP_GEN_MODE_BURST)\n",
107 | "rp.rp_GenBurstCount(channel2, ncyc) # Ncyc\n",
108 | "rp.rp_GenBurstRepetitions(channel2, nor) # Nor\n",
109 | "rp.rp_GenBurstPeriod(channel2, period) # Period\n",
110 | "\n",
111 | "\n",
112 | "# Specify generator trigger source\n",
113 | "rp.rp_GenTriggerSource(channel, rp.RP_GEN_TRIG_SRC_INTERNAL)\n",
114 | "\n",
115 | "# Enable output synchronisation\n",
116 | "rp.rp_GenOutEnableSync(True)\n",
117 | "time.sleep(0.1)\n",
118 | "\n",
119 | "# Syncronise output channels\n",
120 | "rp.rp_GenTriggerOnly(channel)\n",
121 | "rp.rp_GenTriggerOnly(channel2)\n",
122 | "rp.rp_GenSynchronise()"
123 | ]
124 | },
125 | {
126 | "cell_type": "code",
127 | "execution_count": null,
128 | "metadata": {},
129 | "outputs": [],
130 | "source": [
131 | "# Release resources\n",
132 | "rp.rp_Release()"
133 | ]
134 | },
135 | {
136 | "cell_type": "markdown",
137 | "metadata": {},
138 | "source": [
139 | "### Note\n",
140 | "There are a lot of different commands for the Generation. The list of available functions is quite an achievement to read through, so from now on, please refer to the *C and Python API section* of the [SCPI & API command list](https://redpitaya.readthedocs.io/en/latest/appsFeatures/remoteControl/command_list.html#list-of-supported-scpi-api-commands) for all available commands.\n"
141 | ]
142 | }
143 | ],
144 | "metadata": {
145 | "language_info": {
146 | "name": "python"
147 | }
148 | },
149 | "nbformat": 4,
150 | "nbformat_minor": 2
151 | }
152 |
--------------------------------------------------------------------------------
/examples/generation/gen_bursts.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Generate signal pulses\n",
8 | "In this example we will learn how to create burst pulses on the fast analog outputs."
9 | ]
10 | },
11 | {
12 | "cell_type": "markdown",
13 | "metadata": {},
14 | "source": [
15 | "## Libraries and FPGA image"
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": null,
21 | "metadata": {
22 | "collapsed": true
23 | },
24 | "outputs": [],
25 | "source": [
26 | "from rp_overlay import overlay\n",
27 | "import rp\n",
28 | "\n",
29 | "fpga = overlay()\n",
30 | "rp.rp_Init()"
31 | ]
32 | },
33 | {
34 | "cell_type": "markdown",
35 | "metadata": {},
36 | "source": [
37 | "## Macros\n",
38 | "Throughout this tutorial we will mention macros multiple times. Here is a complete list of macros that will come in handy when customising this notebook. The marcos are a part of the **rp** library.\n",
39 | "\n",
40 | "- **Waveforms** - RP_WAVEFORM_SINE, RP_WAVEFORM_SQUARE, RP_WAVEFORM_TRIANGLE, RP_WAVEFORM_RAMP_UP, RP_WAVEFORM_RAMP_DOWN, RP_WAVEFORM_DC, RP_WAVEFORM_PWM, RP_WAVEFORM_ARBITRARY, RP_WAVEFORM_DC_NEG, RP_WAVEFORM_SWEEP\n",
41 | "- **Generator modes** - RP_GEN_MODE_CONTINUOUS, RP_GEN_MODE_BURST\n",
42 | "- **Sweep direction** - RP_GEN_SWEEP_DIR_NORMAL, RP_GEN_SWEEP_DIR_UP_DOWN\n",
43 | "- **Sweep mode** - RP_GEN_SWEEP_MODE_LINEAR, RP_GEN_SWEEP_MODE_LOG\n",
44 | "- **Generator trigger source** - RP_GEN_TRIG_SRC_INTERNAL, RP_GEN_TRIG_SRC_EXT_PE, RP_GEN_TRIG_SRC_EXT_NE\n",
45 | "- **Fast analog channels** - RP_CH_1, RP_CH_2\n",
46 | "- **Fast analog triggers** - RP_T_CH_1, RP_T_CH_2, RP_T_CH_EXT\n",
47 | "- **Rise and fall times** - RISE_FALL_MIN_RATIO, RISE_FALL_MAX_RATIO\n",
48 | "\n",
49 | "SIGNALlab 250-12 only:\n",
50 | "- **Generator gain** - RP_GAIN_1X, RP_GAIN_5X\n",
51 | "\n",
52 | "STEMlab 125-14 4-Input only:\n",
53 | "- **Fast analog channels** - RP_CH_3, RP_CH_4\n",
54 | "- **Fast analog triggers** - RP_T_CH_3, RP_T_CH_4"
55 | ]
56 | },
57 | {
58 | "cell_type": "markdown",
59 | "metadata": {},
60 | "source": [
61 | "## Burst signals\n",
62 | "\n",
63 | "Burst signals differ from continuous signals. They are only generated in a short amount of time and do not necessarily repeat. Here are the new parameters that come into play (in addition to the continuous signal parameters):\n",
64 | "\n",
65 | "- **Number of Cycles (NCYC)** - How many periods of our signal are there in a single burst?\n",
66 | "- **Number of Repetitions (NOR)** - How many bursts are there overall (each burst includes NCYC signal periods)?\n",
67 | "- **Burst period (PERIOD)** - The time between the start of one and the start of the next burst (in microseconds). The minimal period is 1 microsecond.\n",
68 | "\n",
69 | "Now that we know the basics, let's start programming."
70 | ]
71 | },
72 | {
73 | "cell_type": "code",
74 | "execution_count": null,
75 | "metadata": {
76 | "collapsed": true
77 | },
78 | "outputs": [],
79 | "source": [
80 | "channel = rp.RP_CH_1 # rp.RP_CH_2\n",
81 | "waveform = rp.RP_WAVEFORM_SINE\n",
82 | "freq = 1000\n",
83 | "ampl = 1\n",
84 | "\n",
85 | "# Burst paramteres\n",
86 | "ncyc = 1 # Number of waveform periods in one burst\n",
87 | "nor = 1000 # Number of repeated bursts\n",
88 | "period = 5000 # Delay between start of first burst and start of second burst\n",
89 | " # in mircoseconds"
90 | ]
91 | },
92 | {
93 | "cell_type": "markdown",
94 | "metadata": {},
95 | "source": [
96 | "By default, Red Pitaya operates generates continuous signals, so we need to change the generation mode to burst."
97 | ]
98 | },
99 | {
100 | "cell_type": "code",
101 | "execution_count": null,
102 | "metadata": {},
103 | "outputs": [],
104 | "source": [
105 | "mode = rp.RP_GEN_MODE_BURST\n",
106 | "\n",
107 | "# Reset generator\n",
108 | "rp.rp_GenReset()\n",
109 | "\n",
110 | "#### Generation ####\n",
111 | "rp.rp_GenWaveform(channel, waveform)\n",
112 | "rp.rp_GenFreqDirect(channel, freq)\n",
113 | "rp.rp_GenAmp(channel, ampl)\n",
114 | "\n",
115 | "# Change to burst mode\n",
116 | "rp.rp_GenMode(channel, mode)\n",
117 | "rp.rp_GenBurstCount(channel, ncyc) # Ncyc\n",
118 | "rp.rp_GenBurstRepetitions(channel, nor) # Nor\n",
119 | "rp.rp_GenBurstPeriod(channel, period) # Period"
120 | ]
121 | },
122 | {
123 | "cell_type": "markdown",
124 | "metadata": {},
125 | "source": [
126 | "One major difference between continuous and burst signals is that you can retrigger burst signals to generate them again. Retriggering a continuous signal does not achieve much beyond resetting the phase."
127 | ]
128 | },
129 | {
130 | "cell_type": "code",
131 | "execution_count": null,
132 | "metadata": {},
133 | "outputs": [],
134 | "source": [
135 | "rp.rp_GenOutEnable(channel)\n",
136 | "rp.rp_GenTriggerOnly(channel)"
137 | ]
138 | },
139 | {
140 | "cell_type": "markdown",
141 | "metadata": {},
142 | "source": [
143 | "To repeat a burst signal, trigger the generator again."
144 | ]
145 | },
146 | {
147 | "cell_type": "code",
148 | "execution_count": null,
149 | "metadata": {
150 | "collapsed": true
151 | },
152 | "outputs": [],
153 | "source": [
154 | "rp.rp_GenTriggerOnly(channel)"
155 | ]
156 | },
157 | {
158 | "cell_type": "markdown",
159 | "metadata": {},
160 | "source": [
161 | "Finally, release the resources."
162 | ]
163 | },
164 | {
165 | "cell_type": "code",
166 | "execution_count": null,
167 | "metadata": {},
168 | "outputs": [],
169 | "source": [
170 | "rp.rp_Release()"
171 | ]
172 | },
173 | {
174 | "cell_type": "markdown",
175 | "metadata": {},
176 | "source": [
177 | "### Note\n",
178 | "There are a lot of different commands for the Generation. The list of available functions is quite an achievement to read through, so from now on, please refer to the *C and Python API section* of the [SCPI & API command list](https://redpitaya.readthedocs.io/en/latest/appsFeatures/remoteControl/command_list.html#list-of-supported-scpi-api-commands) for all available commands.\n"
179 | ]
180 | }
181 | ],
182 | "metadata": {
183 | "kernelspec": {
184 | "display_name": "Python 3",
185 | "language": "python",
186 | "name": "python3"
187 | },
188 | "language_info": {
189 | "codemirror_mode": {
190 | "name": "ipython",
191 | "version": 3
192 | },
193 | "file_extension": ".py",
194 | "mimetype": "text/x-python",
195 | "name": "python",
196 | "nbconvert_exporter": "python",
197 | "pygments_lexer": "ipython3",
198 | "version": "3.5.2"
199 | }
200 | },
201 | "nbformat": 4,
202 | "nbformat_minor": 2
203 | }
204 |
--------------------------------------------------------------------------------
/examples/generation/gen_continuous_signal.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Generate Continuous Signal\n",
8 | "\n",
9 | "This example will show how to generate a continuous 2 kHz 1 V sine wave on fast analog outputs."
10 | ]
11 | },
12 | {
13 | "cell_type": "markdown",
14 | "metadata": {},
15 | "source": [
16 | "## Libraries and FPGA image\n",
17 | "\n",
18 | "We will start by importing the *rp* (Red Pitaya) and *rp_overlay* libraries, loading the *v0.94* FPGA image, and initializing the Red Pitaya."
19 | ]
20 | },
21 | {
22 | "cell_type": "code",
23 | "execution_count": null,
24 | "metadata": {
25 | "scrolled": true
26 | },
27 | "outputs": [],
28 | "source": [
29 | "from rp_overlay import overlay\n",
30 | "import rp\n",
31 | "\n",
32 | "fpga = overlay()\n",
33 | "rp.rp_Init()"
34 | ]
35 | },
36 | {
37 | "cell_type": "markdown",
38 | "metadata": {},
39 | "source": [
40 | "## Macros\n",
41 | "Throughout this tutorial we will mention macros multiple times. Here is a complete list of macros that will come in handy when customising this notebook. The marcos are a part of the **rp** library.\n",
42 | "\n",
43 | "- **Waveforms** - RP_WAVEFORM_SINE, RP_WAVEFORM_SQUARE, RP_WAVEFORM_TRIANGLE, RP_WAVEFORM_RAMP_UP, RP_WAVEFORM_RAMP_DOWN, RP_WAVEFORM_DC, RP_WAVEFORM_PWM, RP_WAVEFORM_ARBITRARY, RP_WAVEFORM_DC_NEG, RP_WAVEFORM_SWEEP\n",
44 | "- **Generator modes** - RP_GEN_MODE_CONTINUOUS, RP_GEN_MODE_BURST\n",
45 | "- **Sweep direction** - RP_GEN_SWEEP_DIR_NORMAL, RP_GEN_SWEEP_DIR_UP_DOWN\n",
46 | "- **Sweep mode** - RP_GEN_SWEEP_MODE_LINEAR, RP_GEN_SWEEP_MODE_LOG\n",
47 | "- **Generator trigger source** - RP_GEN_TRIG_SRC_INTERNAL, RP_GEN_TRIG_SRC_EXT_PE, RP_GEN_TRIG_SRC_EXT_NE\n",
48 | "- **Fast analog channels** - RP_CH_1, RP_CH_2\n",
49 | "- **Fast analog triggers** - RP_T_CH_1, RP_T_CH_2, RP_T_CH_EXT\n",
50 | "- **Rise and fall times** - RISE_FALL_MIN_RATIO, RISE_FALL_MAX_RATIO\n",
51 | "\n",
52 | "SIGNALlab 250-12 only:\n",
53 | "- **Generator gain** - RP_GAIN_1X, RP_GAIN_5X\n",
54 | "\n",
55 | "STEMlab 125-14 4-Input only:\n",
56 | "- **Fast analog channels** - RP_CH_3, RP_CH_4\n",
57 | "- **Fast analog triggers** - RP_T_CH_3, RP_T_CH_4"
58 | ]
59 | },
60 | {
61 | "cell_type": "markdown",
62 | "metadata": {},
63 | "source": [
64 | "## Generation\n",
65 | "\n",
66 | "When generating signals, there are a number of important parameters that we need to define.\n",
67 | "\n",
68 | "- **Channel** - on which of the two output channels do we want to generate a signal\n",
69 | "- **Waveform** - te basic shape of our signal. Some most common examples are sine, square, triangle, etc.\n",
70 | "- **Frequency** - how fast will our signal periods be generated/how much time it takes for one period of our signal to generate. $f = \\frac{1}{T}$, where T is signal period.\n",
71 | "- **Amplitude** - what is the maximum voltage of our output signal. There are multiple different ways to define this, but Red Pitaya uses one-way amplitude referenced towards GND (and not peak-to-peak).\n",
72 | "\n",
73 | "In this example, we will generate a 1 V, 2 kHz sine wave. So, let's define the parameters."
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": null,
79 | "metadata": {},
80 | "outputs": [],
81 | "source": [
82 | "channel = rp.RP_CH_1 # rp.RP_CH_2\n",
83 | "waveform = rp.RP_WAVEFORM_SINE\n",
84 | "freq = 2000\n",
85 | "ampl = 1 # One way amplitude (reference to GND)"
86 | ]
87 | },
88 | {
89 | "cell_type": "markdown",
90 | "metadata": {},
91 | "source": [
92 | "Next, we will reset the generator to default parameters (1 kHz sine wave with amplitude 1 V), as we have no idea what the output was generating before."
93 | ]
94 | },
95 | {
96 | "cell_type": "code",
97 | "execution_count": null,
98 | "metadata": {},
99 | "outputs": [],
100 | "source": [
101 | "rp.rp_GenReset()"
102 | ]
103 | },
104 | {
105 | "cell_type": "markdown",
106 | "metadata": {},
107 | "source": [
108 | "Now that the generator is reset, let us specify our 2 kHz sine signal."
109 | ]
110 | },
111 | {
112 | "cell_type": "code",
113 | "execution_count": null,
114 | "metadata": {
115 | "collapsed": true,
116 | "scrolled": true
117 | },
118 | "outputs": [],
119 | "source": [
120 | "rp.rp_GenWaveform(channel, waveform)\n",
121 | "rp.rp_GenFreqDirect(channel, freq)\n",
122 | "rp.rp_GenAmp(channel, ampl)"
123 | ]
124 | },
125 | {
126 | "cell_type": "markdown",
127 | "metadata": {},
128 | "source": [
129 | "To enable the output and trigger the generation execute the following cell."
130 | ]
131 | },
132 | {
133 | "cell_type": "code",
134 | "execution_count": null,
135 | "metadata": {},
136 | "outputs": [],
137 | "source": [
138 | "rp.rp_GenOutEnable(channel)\n",
139 | "rp.rp_GenTriggerOnly(channel)"
140 | ]
141 | },
142 | {
143 | "cell_type": "markdown",
144 | "metadata": {},
145 | "source": [
146 | "It is a bit hard to know without using an oscilloscope or external insturument, but OUT1 of our Red Pitaya is now generating a continuous sine wave with the specified parameters.\n",
147 | "\n",
148 | "Once finished, do not forget to release the resources."
149 | ]
150 | },
151 | {
152 | "cell_type": "code",
153 | "execution_count": null,
154 | "metadata": {
155 | "scrolled": true
156 | },
157 | "outputs": [],
158 | "source": [
159 | "rp.rp_Release()"
160 | ]
161 | },
162 | {
163 | "cell_type": "markdown",
164 | "metadata": {},
165 | "source": [
166 | "### Note\n",
167 | "There are a lot of different commands for the Generation. The list of available functions is quite an achievement to read through, so from now on, please refer to the *C and Python API section* of the [SCPI & API command list](https://redpitaya.readthedocs.io/en/latest/appsFeatures/remoteControl/command_list.html#list-of-supported-scpi-api-commands) for all available commands.\n"
168 | ]
169 | }
170 | ],
171 | "metadata": {
172 | "kernelspec": {
173 | "display_name": "Python 3",
174 | "language": "python",
175 | "name": "python3"
176 | },
177 | "language_info": {
178 | "codemirror_mode": {
179 | "name": "ipython",
180 | "version": 3
181 | },
182 | "file_extension": ".py",
183 | "mimetype": "text/x-python",
184 | "name": "python",
185 | "nbconvert_exporter": "python",
186 | "pygments_lexer": "ipython3",
187 | "version": "3.5.2"
188 | }
189 | },
190 | "nbformat": 4,
191 | "nbformat_minor": 2
192 | }
193 |
--------------------------------------------------------------------------------
/examples/generation/gen_sync_two_channel.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Generate two synchronous signals\n",
8 | "Here we will learn how to generate two synchronous signals on both fast analog outputs."
9 | ]
10 | },
11 | {
12 | "cell_type": "markdown",
13 | "metadata": {},
14 | "source": [
15 | "## Libraries and FPGA image"
16 | ]
17 | },
18 | {
19 | "cell_type": "code",
20 | "execution_count": null,
21 | "metadata": {
22 | "scrolled": true
23 | },
24 | "outputs": [],
25 | "source": [
26 | "from rp_overlay import overlay\n",
27 | "import rp\n",
28 | "\n",
29 | "fpga = overlay()\n",
30 | "rp.rp_Init()"
31 | ]
32 | },
33 | {
34 | "cell_type": "markdown",
35 | "metadata": {},
36 | "source": [
37 | "## Macros\n",
38 | "Throughout this tutorial we will mention macros multiple times. Here is a complete list of macros that will come in handy when customising this notebook. The marcos are a part of the **rp** library.\n",
39 | "\n",
40 | "- **Waveforms** - RP_WAVEFORM_SINE, RP_WAVEFORM_SQUARE, RP_WAVEFORM_TRIANGLE, RP_WAVEFORM_RAMP_UP, RP_WAVEFORM_RAMP_DOWN, RP_WAVEFORM_DC, RP_WAVEFORM_PWM, RP_WAVEFORM_ARBITRARY, RP_WAVEFORM_DC_NEG, RP_WAVEFORM_SWEEP\n",
41 | "- **Generator modes** - RP_GEN_MODE_CONTINUOUS, RP_GEN_MODE_BURST\n",
42 | "- **Sweep direction** - RP_GEN_SWEEP_DIR_NORMAL, RP_GEN_SWEEP_DIR_UP_DOWN\n",
43 | "- **Sweep mode** - RP_GEN_SWEEP_MODE_LINEAR, RP_GEN_SWEEP_MODE_LOG\n",
44 | "- **Generator trigger source** - RP_GEN_TRIG_SRC_INTERNAL, RP_GEN_TRIG_SRC_EXT_PE, RP_GEN_TRIG_SRC_EXT_NE\n",
45 | "- **Fast analog channels** - RP_CH_1, RP_CH_2\n",
46 | "- **Fast analog triggers** - RP_T_CH_1, RP_T_CH_2, RP_T_CH_EXT\n",
47 | "- **Rise and fall times** - RISE_FALL_MIN_RATIO, RISE_FALL_MAX_RATIO\n",
48 | "\n",
49 | "SIGNALlab 250-12 only:\n",
50 | "- **Generator gain** - RP_GAIN_1X, RP_GAIN_5X\n",
51 | "\n",
52 | "STEMlab 125-14 4-Input only:\n",
53 | "- **Fast analog channels** - RP_CH_3, RP_CH_4\n",
54 | "- **Fast analog triggers** - RP_T_CH_3, RP_T_CH_4"
55 | ]
56 | },
57 | {
58 | "cell_type": "markdown",
59 | "metadata": {},
60 | "source": [
61 | "## Synchronising both outputs\n",
62 | "\n",
63 | "Here is a quick reference guide to the functions used:\n",
64 | "- **rp_GenOutEnable(output_channel)** - supplies voltage on the specified output (voltage set with **rp_GenSetInitGenValue** appears on the output), but does not generate a signal\n",
65 | "- **rp_GenOutEnableSync()** - supplies voltage on both outputs (voltage set with **rp_GenSetInitGenValue** appears on the outputs), but does not generate a signal.\n",
66 | "- **rp_GenTriggerOnly(output_channel)** - triggers signal generation on the specified output\n",
67 | "- **rp_GenSynchronise()** - triggers both signal generators at the same time (sychronised)"
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": null,
73 | "metadata": {
74 | "scrolled": true
75 | },
76 | "outputs": [],
77 | "source": [
78 | "channel = rp.RP_CH_1\n",
79 | "channel2 = rp.RP_CH_2\n",
80 | "waveform = rp.RP_WAVEFORM_SINE\n",
81 | "freq = 10000\n",
82 | "ampl = 1\n",
83 | "\n",
84 | "gen_trig_sour = rp.RP_GEN_TRIG_SRC_INTERNAL\n",
85 | "\n",
86 | "\n",
87 | "# Reset generator\n",
88 | "rp.rp_GenReset()\n",
89 | "\n",
90 | "###### Generation #####\n",
91 | "# OUT1\n",
92 | "rp.rp_GenWaveform(channel, waveform)\n",
93 | "rp.rp_GenFreqDirect(channel, freq)\n",
94 | "rp.rp_GenAmp(channel, ampl)\n",
95 | "\n",
96 | "# OUT2\n",
97 | "rp.rp_GenWaveform(channel2, waveform)\n",
98 | "rp.rp_GenFreqDirect(channel2, freq)\n",
99 | "rp.rp_GenAmp(channel2, ampl)\n",
100 | "\n",
101 | "# Specify generator trigger source\n",
102 | "rp.rp_GenTriggerSource(channel, gen_trig_sour)\n",
103 | "\n",
104 | "# Enable outputs on both channels synchronuously\n",
105 | "rp.rp_GenOutEnableSync(True)\n",
106 | "\n",
107 | "# Syncronise and trigger output channels\n",
108 | "rp.rp_GenSynchronise()\n"
109 | ]
110 | },
111 | {
112 | "cell_type": "code",
113 | "execution_count": null,
114 | "metadata": {},
115 | "outputs": [],
116 | "source": [
117 | "# Release resources\n",
118 | "rp.rp_Release()"
119 | ]
120 | },
121 | {
122 | "cell_type": "markdown",
123 | "metadata": {},
124 | "source": [
125 | "### Note\n",
126 | "There are a lot of different commands for the Generation. The list of available functions is quite an achievement to read through, so from now on, please refer to the *C and Python API section* of the [SCPI & API command list](https://redpitaya.readthedocs.io/en/latest/appsFeatures/remoteControl/command_list.html#list-of-supported-scpi-api-commands) for all available commands.\n"
127 | ]
128 | }
129 | ],
130 | "metadata": {
131 | "kernelspec": {
132 | "display_name": "Python 3",
133 | "language": "python",
134 | "name": "python3"
135 | },
136 | "language_info": {
137 | "codemirror_mode": {
138 | "name": "ipython",
139 | "version": 3
140 | },
141 | "file_extension": ".py",
142 | "mimetype": "text/x-python",
143 | "name": "python",
144 | "nbconvert_exporter": "python",
145 | "pygments_lexer": "ipython3",
146 | "version": "3.5.2"
147 | }
148 | },
149 | "nbformat": 4,
150 | "nbformat_minor": 2
151 | }
152 |
--------------------------------------------------------------------------------
/examples/hardware/hwid.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Hardware identification"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "Import Red Pitaya library."
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {},
21 | "outputs": [],
22 | "source": [
23 | "import time\n",
24 | "from rp_overlay import overlay\n",
25 | "import rp"
26 | ]
27 | },
28 | {
29 | "cell_type": "markdown",
30 | "metadata": {},
31 | "source": [
32 | "Load the *v0.94* FPGA image into the Xilinx Zynq SoC."
33 | ]
34 | },
35 | {
36 | "cell_type": "code",
37 | "execution_count": null,
38 | "metadata": {},
39 | "outputs": [],
40 | "source": [
41 | "fpga = overlay()"
42 | ]
43 | },
44 | {
45 | "cell_type": "markdown",
46 | "metadata": {},
47 | "source": [
48 | "Initialize the interface."
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": null,
54 | "metadata": {},
55 | "outputs": [],
56 | "source": [
57 | "rp.rp_Init()"
58 | ]
59 | },
60 | {
61 | "cell_type": "markdown",
62 | "metadata": {},
63 | "source": [
64 | "Display the Red Pitaya Version and the Hardware ID. The *hardware identification* register is not very useful, since the number never changes. Red Pitaya *Version* might be relevant to some board-model-specific applications."
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": null,
70 | "metadata": {},
71 | "outputs": [],
72 | "source": [
73 | "print(f'My Red Pitaya version: {rp.rp_GetVersion()}')\n",
74 | "print(f'My Red Pitaya HWID: {rp.rp_IdGetID()[1]}')"
75 | ]
76 | },
77 | {
78 | "cell_type": "markdown",
79 | "metadata": {},
80 | "source": [
81 | "Print *Zynq FPGA* **DNA** number."
82 | ]
83 | },
84 | {
85 | "cell_type": "code",
86 | "execution_count": null,
87 | "metadata": {},
88 | "outputs": [],
89 | "source": [
90 | "print(f'DNA number: {rp.rp_IdGetDNA()[1]}')"
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {
96 | "collapsed": true,
97 | "jupyter": {
98 | "outputs_hidden": true
99 | }
100 | },
101 | "source": [
102 | "Release resources."
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "execution_count": null,
108 | "metadata": {},
109 | "outputs": [],
110 | "source": [
111 | "rp.rp_Release()"
112 | ]
113 | }
114 | ],
115 | "metadata": {
116 | "kernelspec": {
117 | "display_name": "Python 3 (ipykernel)",
118 | "language": "python",
119 | "name": "python3"
120 | },
121 | "language_info": {
122 | "codemirror_mode": {
123 | "name": "ipython",
124 | "version": 3
125 | },
126 | "file_extension": ".py",
127 | "mimetype": "text/x-python",
128 | "name": "python",
129 | "nbconvert_exporter": "python",
130 | "pygments_lexer": "ipython3",
131 | "version": "3.10.12"
132 | }
133 | },
134 | "nbformat": 4,
135 | "nbformat_minor": 4
136 | }
137 |
--------------------------------------------------------------------------------
/examples/img/FastIOLoopBack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/img/FastIOLoopBack.png
--------------------------------------------------------------------------------
/examples/img/LED-blink.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/img/LED-blink.gif
--------------------------------------------------------------------------------
/examples/img/RedPitaya_pinout.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/img/RedPitaya_pinout.jpg
--------------------------------------------------------------------------------
/examples/img/generate_continous_signal_on_fast_analog_output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/img/generate_continous_signal_on_fast_analog_output.png
--------------------------------------------------------------------------------
/examples/img/on_given_trigger_acquire_signal_on_fast_analog_input.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/img/on_given_trigger_acquire_signal_on_fast_analog_input.png
--------------------------------------------------------------------------------
/examples/outdated/exam_temp.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "## Setup\n",
8 | "- Red Pitaya STEMlab board + sensor shield\n",
9 | "- Grove temperature sensor"
10 | ]
11 | },
12 | {
13 | "cell_type": "markdown",
14 | "metadata": {},
15 | "source": [
16 | "## Temperature sensor\n",
17 | "The Grove - Temperature Sensor uses a Thermistor to detect the ambient temperature. The resistance of a thermistor will increase when the ambient temperature decreases. It's this characteristic that we use to calculate the ambient temperature. The detectable range of this sensor is -40 - 125ºC, and the accuracy is ±1.5ºC\n",
18 | "Datasheet: [NCP18WF104F03RC](http://wiki.seeed.cc/Grove-Temperature_Sensor_V1.2/) \n",
19 | "\n",
20 | ""
21 | ]
22 | },
23 | {
24 | "cell_type": "code",
25 | "execution_count": null,
26 | "metadata": {},
27 | "outputs": [],
28 | "source": [
29 | "from redpitaya.overlay.mercury import mercury as FPGA\n",
30 | "overlay = FPGA()\n",
31 | "ANALOG = FPGA.analog_in(0) # define which pin will be used for temperature sensor"
32 | ]
33 | },
34 | {
35 | "cell_type": "code",
36 | "execution_count": null,
37 | "metadata": {},
38 | "outputs": [],
39 | "source": [
40 | "# Temperature vs. NTC resistance \n",
41 | "import math\n",
42 | "import matplotlib.pyplot as plt\n",
43 | "import time\n",
44 | "from redpitaya.overlay.mercury import mercury as FPGA\n",
45 | "overlay = FPGA()\n",
46 | "ANALOG = FPGA.analog_in(0) # define which pin will be used for temperature sensor\n",
47 | "\n",
48 | "def res_to_temp(Rntc):\n",
49 | " B = 4275; # B value of the thermistor\n",
50 | " return (1.0/(math.log10(Rntc/100000.0)/B+1/298.15)-273.15) #convert to temperature via datasheet \n",
51 | "temp = [ res_to_temp(R) for R in range(10000,300000,100)]\n",
52 | "plt.plot(range(10000,300000,100), temp)\n",
53 | "plt.xlabel('Rntc[ohm]')\n",
54 | "plt.ylabel('Temperature[*C]')\n",
55 | "plt.show()"
56 | ]
57 | },
58 | {
59 | "cell_type": "markdown",
60 | "metadata": {},
61 | "source": [
62 | "## Reading temperature sensor\n",
63 | "\n",
64 | "To read the temperature we need to read the voltage value and convert it to temperature."
65 | ]
66 | },
67 | {
68 | "cell_type": "code",
69 | "execution_count": null,
70 | "metadata": {},
71 | "outputs": [],
72 | "source": [
73 | "def temp():\n",
74 | " Va0=ANALOG.read() # read voltage of sensor\n",
75 | " R0 = 100000; # R0 = 100k\n",
76 | " Rntc = 3.3/(Va0)-1.0 \n",
77 | " Rntc = 100000.0*Rntc # thermistor resistance\n",
78 | " return (res_to_temp(Rntc),Va0);\n",
79 | "r=temp()\n",
80 | "\n",
81 | "print(\"voltage={:.2f}V temp {:.2f}℃\".format(r[1],r[0]) )"
82 | ]
83 | }
84 | ],
85 | "metadata": {
86 | "kernelspec": {
87 | "display_name": "Python 3",
88 | "language": "python",
89 | "name": "python3"
90 | },
91 | "language_info": {
92 | "codemirror_mode": {
93 | "name": "ipython",
94 | "version": 3
95 | },
96 | "file_extension": ".py",
97 | "mimetype": "text/x-python",
98 | "name": "python",
99 | "nbconvert_exporter": "python",
100 | "pygments_lexer": "ipython3",
101 | "version": "3.5.2"
102 | }
103 | },
104 | "nbformat": 4,
105 | "nbformat_minor": 2
106 | }
107 |
--------------------------------------------------------------------------------
/examples/outdated/home_automation.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Home heating system / temperature regulator\n",
8 | "In this experiment we will present basic heating on/off system regulator with a hysteresis.\n",
9 | "Even very modern thermostats like NEST are still primarly based on old ON/OFF regulaton method. \n",
10 | ""
11 | ]
12 | },
13 | {
14 | "cell_type": "markdown",
15 | "metadata": {},
16 | "source": [
17 | "## Basic principle\n",
18 | "User sets a desired temperature that is compared to measured temperature. If the measured temperature is < set temperature, we turn heater on, but if measured tempreature > set temperature we turn it off.\n",
19 | ""
20 | ]
21 | },
22 | {
23 | "cell_type": "markdown",
24 | "metadata": {},
25 | "source": [
26 | "## Setup\n",
27 | "- Red Pitaya STEMlab board + sensor shield\n",
28 | "- Grove temperature sensor & LED diode for heater states indicator (optional relay that drives heater)\n",
29 | ""
30 | ]
31 | },
32 | {
33 | "cell_type": "markdown",
34 | "metadata": {},
35 | "source": [
36 | "## Temperature sensor\n",
37 | "The Grove - Temperature Sensor uses a Thermistor to detect the ambient temperature. The resistance of a thermistor will increase when the ambient temperature decreases. It's this characteristic that we use to calculate the ambient temperature. The detectable range of this sensor is -40 - 125ºC, and the accuracy is ±1.5ºC\n",
38 | "Datasheet: [NCP18WF104F03RC](http://wiki.seeed.cc/Grove-Temperature_Sensor_V1.2/) \n",
39 | "\n",
40 | ""
41 | ]
42 | },
43 | {
44 | "cell_type": "code",
45 | "execution_count": null,
46 | "metadata": {},
47 | "outputs": [],
48 | "source": [
49 | "# Temperature vs. NTC resistance \n",
50 | "import math\n",
51 | "import matplotlib.pyplot as plt\n",
52 | "import time\n",
53 | "from redpitaya.overlay.mercury import mercury as FPGA\n",
54 | "overlay = FPGA()\n",
55 | "ANALOG = FPGA.analog_in(0) # define which pin will be used for temperature sensor\n",
56 | "\n",
57 | "def res_to_temp(Rntc):\n",
58 | " B = 4275; # B value of the thermistor\n",
59 | " return (1.0/(math.log10(Rntc/100000.0)/B+1/298.15)-273.15) #convert to temperature via datasheet \n",
60 | "temp = [ res_to_temp(R) for R in range(10000,300000,100)]\n",
61 | "plt.plot(range(10000,300000,100), temp)\n",
62 | "plt.xlabel('Rntc[ohm]')\n",
63 | "plt.ylabel('Temperature[*C]')\n",
64 | "plt.show()"
65 | ]
66 | },
67 | {
68 | "cell_type": "markdown",
69 | "metadata": {},
70 | "source": [
71 | "## Reading temperature sensor\n",
72 | "\n",
73 | "To read the temperature we need to read the voltage value and convert it to temperature."
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": null,
79 | "metadata": {},
80 | "outputs": [],
81 | "source": [
82 | "def temp():\n",
83 | " Va0=ANALOG.read() # read voltage of sensor\n",
84 | " R0 = 100000; # R0 = 100k\n",
85 | " Rntc = 3.3/(Va0)-1.0 \n",
86 | " Rntc = 100000.0*Rntc # thermistor resistance\n",
87 | " return (res_to_temp(Rntc),Va0);\n",
88 | "r=temp()\n",
89 | "\n",
90 | "print(\"voltage={:.2f}V temp {:.2f}℃\".format(r[1],r[0]) )"
91 | ]
92 | },
93 | {
94 | "cell_type": "markdown",
95 | "metadata": {},
96 | "source": [
97 | "## Simple controll of LED\n",
98 | "\n",
99 | "LEDs are controlled with GPIOs."
100 | ]
101 | },
102 | {
103 | "cell_type": "code",
104 | "execution_count": null,
105 | "metadata": {
106 | "collapsed": true
107 | },
108 | "outputs": [],
109 | "source": [
110 | "GPIO = FPGA.gpio\n",
111 | "import time"
112 | ]
113 | },
114 | {
115 | "cell_type": "code",
116 | "execution_count": null,
117 | "metadata": {},
118 | "outputs": [],
119 | "source": [
120 | "gpio_o = GPIO('p', 0, \"out\")\n",
121 | "gpio_o.write(True)\n",
122 | "time.sleep(1)\n",
123 | "gpio_o.write(False)"
124 | ]
125 | },
126 | {
127 | "cell_type": "markdown",
128 | "metadata": {},
129 | "source": [
130 | "# Simple Home Heating"
131 | ]
132 | },
133 | {
134 | "cell_type": "code",
135 | "execution_count": null,
136 | "metadata": {
137 | "scrolled": true
138 | },
139 | "outputs": [],
140 | "source": [
141 | "import time\n",
142 | "\n",
143 | "from bokeh.io import push_notebook, show, output_notebook\n",
144 | "from bokeh.models import HoverTool, Range1d\n",
145 | "from bokeh.plotting import figure\n",
146 | "from bokeh.resources import INLINE \n",
147 | "output_notebook(resources=INLINE)"
148 | ]
149 | },
150 | {
151 | "cell_type": "code",
152 | "execution_count": null,
153 | "metadata": {
154 | "scrolled": false
155 | },
156 | "outputs": [],
157 | "source": [
158 | "colors = ('red', 'blue', 'green', 'orange')\n",
159 | "legends = ('temperature', 'setTemp+hysteresis','setTemp-hysteresis', 'heater State')\n",
160 | "hover = HoverTool(mode = 'vline', tooltips=[(\"T\", \"@y\")])\n",
161 | "tools = \"pan,wheel_zoom,box_zoom,reset,crosshair\"\n",
162 | "p = figure(plot_height=400, plot_width=900, title=\"Home heating system\", toolbar_location=\"above\", tools=(tools, hover))\n",
163 | "p.xaxis.axis_label='time [s]'\n",
164 | "p.y_range=Range1d(20, 35)\n",
165 | "p.yaxis.axis_label='temperature [℃]'\n",
166 | "\n",
167 | "# get and explicit handle to update the next show cell with\n",
168 | "# a simple ON/OFF regulator with hysteresis\n",
169 | "target = show(p, notebook_handle=True)"
170 | ]
171 | },
172 | {
173 | "cell_type": "code",
174 | "execution_count": null,
175 | "metadata": {},
176 | "outputs": [],
177 | "source": [
178 | "# a simple ON/OFF regulator with hysteresis\n",
179 | "HYSTERESIS=0.5\n",
180 | "setTemp=28\n",
181 | "heaterState=0\n",
182 | "chn=4\n",
183 | "\n",
184 | "T = 1 # sampling period\n",
185 | "HYST_HI=setTemp+HYSTERESIS\n",
186 | "HYST_LO=setTemp-HYSTERESIS\n",
187 | "\n",
188 | "x=[0]\n",
189 | "y=[ [temp()[0]], [HYST_HI], [HYST_LO], [heaterState] ]\n",
190 | "r = [p.line(x, y[ch], line_width=1, line_alpha=0.7, color=colors[ch],legend=legends[ch]) for ch in range(chn)]\n",
191 | "\n",
192 | "# take 30 samples while simultaneously plotting the plot\n",
193 | "for i in range(30):\n",
194 | " x.append(0) if i == 0 else x.append(x[-1]+T)\n",
195 | " temperature=temp()[0]\n",
196 | " \n",
197 | " # Hysteresis\n",
198 | " if (temperature < HYST_LO): #turn heating ON (LED)\n",
199 | " gpio_o.write(True)\n",
200 | " heaterState=1\n",
201 | " elif (temperature > HYST_HI): #turn heating OFF (LED)\n",
202 | " heaterState=0\n",
203 | " gpio_o.write(False) \n",
204 | " \n",
205 | " r[0].data_source.data['y'].append(temperature) # store temperature\n",
206 | " r[1].data_source.data['y'].append(HYST_HI) # store set temperature + hysteresis\n",
207 | " r[2].data_source.data['y'].append(HYST_LO) # store set temperature - hysteresis\n",
208 | " r[3].data_source.data['y'].append(heaterState*22) # store heater state\n",
209 | " \n",
210 | " # push updates to the plot continuously using the handle (intererrupt the notebook kernel to stop)\n",
211 | " push_notebook(handle=target)\n",
212 | " time.sleep(T)"
213 | ]
214 | }
215 | ],
216 | "metadata": {
217 | "kernelspec": {
218 | "display_name": "Python 3",
219 | "language": "python",
220 | "name": "python3"
221 | },
222 | "language_info": {
223 | "codemirror_mode": {
224 | "name": "ipython",
225 | "version": 3
226 | },
227 | "file_extension": ".py",
228 | "mimetype": "text/x-python",
229 | "name": "python",
230 | "nbconvert_exporter": "python",
231 | "pygments_lexer": "ipython3",
232 | "version": "3.5.2"
233 | }
234 | },
235 | "nbformat": 4,
236 | "nbformat_minor": 2
237 | }
238 |
--------------------------------------------------------------------------------
/examples/outdated/img/cable_length.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/outdated/img/cable_length.jpg
--------------------------------------------------------------------------------
/examples/outdated/img/nest.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/outdated/img/nest.jpeg
--------------------------------------------------------------------------------
/examples/outdated/img/on_off_control.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/outdated/img/on_off_control.png
--------------------------------------------------------------------------------
/examples/outdated/img/temp_reg_setup.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/outdated/img/temp_reg_setup.jpg
--------------------------------------------------------------------------------
/examples/outdated/img/temp_sensor.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/outdated/img/temp_sensor.jpg
--------------------------------------------------------------------------------
/examples/outdated/img/temp_sensor_sch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/RedPitaya/jupyter/cfc9051d7a3518b2cb987337bc1fc068cd5b6c67/examples/outdated/img/temp_sensor_sch.png
--------------------------------------------------------------------------------
/examples/outdated/la_trigger.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Logic analyzer trigger"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "An FPGA overlay must be loaded first."
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "collapsed": true,
22 | "scrolled": false
23 | },
24 | "outputs": [],
25 | "source": [
26 | "from redpitaya.overlay.mercury import mercury as overlay\n",
27 | "fpga = overlay()"
28 | ]
29 | },
30 | {
31 | "cell_type": "code",
32 | "execution_count": null,
33 | "metadata": {
34 | "collapsed": true
35 | },
36 | "outputs": [],
37 | "source": [
38 | "la = fpga.la()"
39 | ]
40 | },
41 | {
42 | "cell_type": "markdown",
43 | "metadata": {},
44 | "source": [
45 | "Logic analyzer is configured in a similar way as the oscilloscope,\n",
46 | "except for trigger settings, which can check for masked values on the bus,\n",
47 | "and or posedge/negedge triggers."
48 | ]
49 | },
50 | {
51 | "cell_type": "code",
52 | "execution_count": null,
53 | "metadata": {
54 | "collapsed": true
55 | },
56 | "outputs": [],
57 | "source": [
58 | "# input mask and polarity\n",
59 | "la.input_mask = 0xffff\n",
60 | "la.input_polarity = 0x0000\n",
61 | "\n",
62 | "# data rate decimation\n",
63 | "la.decimation = 1\n",
64 | "\n",
65 | "# trigger timing [sample periods]\n",
66 | "N = la.buffer_size\n",
67 | "la.trigger_pre = N//4 * 1\n",
68 | "la.trigger_post = N//4 * 3\n",
69 | "\n",
70 | "# trigger bit mask, bit values and edges ['neg', 'pos']\n",
71 | "la.trigger_mask = 0x0000\n",
72 | "la.trigger_value = 0x0000\n",
73 | "la.trigger_edge = [0x0100, 0x0000] # enable trigger on edge [pos, neg]\n",
74 | "\n",
75 | "# trigger source is the level trigger from the same input\n",
76 | "la.trig_src = fpga.trig_src[\"la\"]"
77 | ]
78 | },
79 | {
80 | "cell_type": "code",
81 | "execution_count": null,
82 | "metadata": {
83 | "collapsed": true
84 | },
85 | "outputs": [],
86 | "source": [
87 | "# reset and start\n",
88 | "la.reset()\n",
89 | "la.start()\n",
90 | "# wait for data\n",
91 | "while (la.status_run()): pass\n",
92 | "\n",
93 | "# show only the part of the buffer requested by pre/post trigger timing\n",
94 | "data = la.data(N)"
95 | ]
96 | },
97 | {
98 | "cell_type": "markdown",
99 | "metadata": {},
100 | "source": [
101 | "In contrast to oscilloscope, the data is not converted to float signals,\n",
102 | "instead integer values are returned."
103 | ]
104 | },
105 | {
106 | "cell_type": "code",
107 | "execution_count": null,
108 | "metadata": {
109 | "collapsed": true
110 | },
111 | "outputs": [],
112 | "source": [
113 | "for i in range(20):\n",
114 | " print(\"{0:4d} = {0:016b}\".format(data[i]))"
115 | ]
116 | }
117 | ],
118 | "metadata": {
119 | "kernelspec": {
120 | "display_name": "Python 3",
121 | "language": "python",
122 | "name": "python3"
123 | },
124 | "language_info": {
125 | "codemirror_mode": {
126 | "name": "ipython",
127 | "version": 3
128 | },
129 | "file_extension": ".py",
130 | "mimetype": "text/x-python",
131 | "name": "python",
132 | "nbconvert_exporter": "python",
133 | "pygments_lexer": "ipython3",
134 | "version": "3.5.2"
135 | }
136 | },
137 | "nbformat": 4,
138 | "nbformat_minor": 2
139 | }
140 |
--------------------------------------------------------------------------------
/examples/outdated/lg_counter.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Logic generator (counter signal)"
8 | ]
9 | },
10 | {
11 | "cell_type": "markdown",
12 | "metadata": {},
13 | "source": [
14 | "An FPGA overlay must be loaded first."
15 | ]
16 | },
17 | {
18 | "cell_type": "code",
19 | "execution_count": null,
20 | "metadata": {
21 | "collapsed": true
22 | },
23 | "outputs": [],
24 | "source": [
25 | "from redpitaya.overlay.mercury import mercury as overlay\n",
26 | "fpga = overlay()"
27 | ]
28 | },
29 | {
30 | "cell_type": "markdown",
31 | "metadata": {},
32 | "source": [
33 | "Fpga management is used to configure GPIO pins into logic generator mode, instead of the default PS GPIO mode.\n",
34 | "\n",
35 | "Each bit in `gpio_mode` coresponds to one of the 16 GPIO pins.\n",
36 | "* 0 - PS GPIO mode\n",
37 | "* 1 - Logic generator mode"
38 | ]
39 | },
40 | {
41 | "cell_type": "code",
42 | "execution_count": null,
43 | "metadata": {
44 | "collapsed": true
45 | },
46 | "outputs": [],
47 | "source": [
48 | "mgmt = fpga.mgmt()"
49 | ]
50 | },
51 | {
52 | "cell_type": "code",
53 | "execution_count": null,
54 | "metadata": {
55 | "collapsed": true
56 | },
57 | "outputs": [],
58 | "source": [
59 | "mgmt.gpio_mode = 0xffff"
60 | ]
61 | },
62 | {
63 | "cell_type": "markdown",
64 | "metadata": {},
65 | "source": [
66 | "Compared to the arbitrary signal generator, the logic generator only supports burst mode.\n",
67 | "The given example creates a binary counter, which can be used for debugging."
68 | ]
69 | },
70 | {
71 | "cell_type": "code",
72 | "execution_count": null,
73 | "metadata": {
74 | "collapsed": true
75 | },
76 | "outputs": [],
77 | "source": [
78 | "lg = fpga.lg()"
79 | ]
80 | },
81 | {
82 | "cell_type": "code",
83 | "execution_count": null,
84 | "metadata": {
85 | "collapsed": true
86 | },
87 | "outputs": [],
88 | "source": [
89 | "# buffer waveform and sample timing\n",
90 | "lg.waveform = range(lg.buffer_size)\n",
91 | "\n",
92 | "# repeat the entire buffere indefinitely\n",
93 | "lg.burst_data_repetitions = 1\n",
94 | "lg.burst_data_length = lg.buffer_size\n",
95 | "lg.burst_period_length = lg.buffer_size\n",
96 | "lg.burst_period_number = 0\n",
97 | "\n",
98 | "# set output amplitude, offset and enable it\n",
99 | "lg.enable = 0xffff # all pins have outputs enabled (for both output values 0/1)\n",
100 | "lg.mask = 0x0000 # all bits come from ASG, none are constants\n",
101 | "lg.value = 0x0000 # the constant pin values are irrelevant since they are not used\n",
102 | "\n",
103 | "# reset, start and trigger generator to get the first burst\n",
104 | "lg.reset()\n",
105 | "lg.start()\n",
106 | "lg.trigger()"
107 | ]
108 | }
109 | ],
110 | "metadata": {
111 | "kernelspec": {
112 | "display_name": "Python 3",
113 | "language": "python",
114 | "name": "python3"
115 | },
116 | "language_info": {
117 | "codemirror_mode": {
118 | "name": "ipython",
119 | "version": 3
120 | },
121 | "file_extension": ".py",
122 | "mimetype": "text/x-python",
123 | "name": "python",
124 | "nbconvert_exporter": "python",
125 | "pygments_lexer": "ipython3",
126 | "version": "3.5.2"
127 | }
128 | },
129 | "nbformat": 4,
130 | "nbformat_minor": 2
131 | }
132 |
--------------------------------------------------------------------------------
/experiments/axi4lite_gpio.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "**NOTE: This is experimental code, not intended as an example.**\n",
8 | "\n",
9 | "Verilog RTL code and some block diagram code (AXI3 to AXI4-lite conversion) are in the `fpga/prj/axi4lite` directory.\n",
10 | "\n",
11 | "The FPGA image contains a single slave device connected to GPIO and LED pins.\n",
12 | "The slave system bus was recoded from the previous undocumented bus to a standard *AXI4-Lite* interface.\n",
13 | "The clock for the system bus is derived from the ADC reference oscilator,\n",
14 | "as it should be with hardware synchronous to 125 MHz ADC/DAC.\n",
15 | "\n",
16 | "The Example provides raw Python code for mapping registers, without and C code.\n",
17 | "And would allow developers to write drivers for FPGA HW entirely in Python."
18 | ]
19 | },
20 | {
21 | "cell_type": "markdown",
22 | "metadata": {},
23 | "source": [
24 | "The first code segment provides register set definition and memory mapping.\n",
25 | "Output, output enable and input registers are all 32bit.\n",
26 | "GPIOs are mapped to bits `[15:0]`and LEDs are mapped to bits `[23:16]`."
27 | ]
28 | },
29 | {
30 | "cell_type": "code",
31 | "execution_count": null,
32 | "metadata": {
33 | "collapsed": false
34 | },
35 | "outputs": [],
36 | "source": [
37 | "import os\n",
38 | "import mmap\n",
39 | "import numpy as np\n",
40 | "\n",
41 | "regset_gpio = np.dtype([\n",
42 | " ('o', 'uint32'),\n",
43 | " ('t', 'uint32'),\n",
44 | " ('i', 'uint32')\n",
45 | "])\n",
46 | "\n",
47 | "os.system('cat /opt/redpitaya/fpga/axi4lite/fpga.bit > /dev/xdevcfg')\n",
48 | "\n",
49 | "fd = os.open('/dev/uio/api', os.O_RDWR)\n",
50 | "m = mmap.mmap(fileno=fd, length=mmap.PAGESIZE, offset=0x0)\n",
51 | "gpio_array = np.recarray(1, regset_gpio, buf=m)\n",
52 | "gpio = gpio_array[0]"
53 | ]
54 | },
55 | {
56 | "cell_type": "markdown",
57 | "metadata": {},
58 | "source": [
59 | "GPIO T signal is inverted output enable, a native notation for Xilinx IOBUF Verilog primitives.\n",
60 | "So to enable an output, the relevant bit in this register should be set to `0`.\n",
61 | "\n",
62 | "The example then alternatively lights up `LED[3:0]` and `LED[7:4]` with a 0.2s delay between them."
63 | ]
64 | },
65 | {
66 | "cell_type": "code",
67 | "execution_count": null,
68 | "metadata": {
69 | "collapsed": true
70 | },
71 | "outputs": [],
72 | "source": [
73 | "import time\n",
74 | "\n",
75 | "# enable output\n",
76 | "gpio.t = 0xffff00\n",
77 | "\n",
78 | "# blink\n",
79 | "for i in range(10):\n",
80 | " gpio.o = 0x0000f0\n",
81 | " time.sleep(0.2)\n",
82 | " gpio.o = 0x00000f\n",
83 | " time.sleep(0.2)"
84 | ]
85 | },
86 | {
87 | "cell_type": "markdown",
88 | "metadata": {},
89 | "source": [
90 | "Reading from the input register should return the value on the pins."
91 | ]
92 | },
93 | {
94 | "cell_type": "code",
95 | "execution_count": null,
96 | "metadata": {
97 | "collapsed": false
98 | },
99 | "outputs": [],
100 | "source": [
101 | "hex(gpio.i)"
102 | ]
103 | },
104 | {
105 | "cell_type": "markdown",
106 | "metadata": {},
107 | "source": [
108 | "The next example provides an alternative mapping of the registers.\n",
109 | "It is intended for testing 64 bit read access to registers.\n",
110 | "Although the actual register is 32 bit the AXI interconnect\n",
111 | "should split 64 bit transfers into two 32bit transfers.\n",
112 | "This is usefull for example for 64 bit values like the Zynq DNA code.\n",
113 | "Since the bus is little endian the high part of 64 bit data\n",
114 | "is stored at address `0x0`, while the low part at address `0x4`."
115 | ]
116 | },
117 | {
118 | "cell_type": "code",
119 | "execution_count": null,
120 | "metadata": {
121 | "collapsed": false
122 | },
123 | "outputs": [],
124 | "source": [
125 | "regset_test64 = np.dtype([\n",
126 | " ('ot', 'uint64'),\n",
127 | " ('i', 'uint32')\n",
128 | "])\n",
129 | "\n",
130 | "test64_array = np.recarray(1, regset_test64, buf=m)\n",
131 | "test64 = test64_array[0]\n",
132 | "gpio.t = 0x01234567\n",
133 | "gpio.o = 0x89abcdef\n",
134 | "hex(test64.ot)"
135 | ]
136 | },
137 | {
138 | "cell_type": "markdown",
139 | "metadata": {},
140 | "source": [
141 | "Writing 64 bit data and reading it as two 32 bit registers should also work."
142 | ]
143 | },
144 | {
145 | "cell_type": "code",
146 | "execution_count": null,
147 | "metadata": {
148 | "collapsed": false
149 | },
150 | "outputs": [],
151 | "source": [
152 | "test64.ot = 0xfedcba9876543210\n",
153 | "hex(gpio.t), hex(gpio.o)"
154 | ]
155 | }
156 | ],
157 | "metadata": {
158 | "kernelspec": {
159 | "display_name": "Python 3",
160 | "language": "python",
161 | "name": "python3"
162 | },
163 | "language_info": {
164 | "codemirror_mode": {
165 | "name": "ipython",
166 | "version": 3
167 | },
168 | "file_extension": ".py",
169 | "mimetype": "text/x-python",
170 | "name": "python",
171 | "nbconvert_exporter": "python",
172 | "pygments_lexer": "ipython3",
173 | "version": "3.5.2"
174 | }
175 | },
176 | "nbformat": 4,
177 | "nbformat_minor": 2
178 | }
179 |
--------------------------------------------------------------------------------
/experiments/monitor_classic_fpga.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {
7 | "collapsed": false,
8 | "deletable": true,
9 | "editable": true
10 | },
11 | "outputs": [],
12 | "source": [
13 | "from periphery import MMIO\n",
14 | "\n",
15 | "# Open am335x real-time clock subsystem page\n",
16 | "regset_gen = MMIO(0x40200000, 0x30000)\n",
17 | "\n",
18 | "# read control/status registers\n",
19 | "for adr in range(0, 0x44, 0x4):\n",
20 | " print(\"@{adr:08x} = 0x{dat:08x} = {dat:10d} = {dat:032b}\".format(adr=adr, dat=regset_gen.read32(adr)))\n",
21 | "# read the buffer\n",
22 | "for adr in range(0x10000, 0x10040, 0x4):\n",
23 | " print(\"@{adr:08x} = 0x{dat:08x} = {dat:10d} = {dat:032b}\".format(adr=adr, dat=regset_gen.read32(adr)))\n",
24 | "\n",
25 | "regset_gen.close()"
26 | ]
27 | },
28 | {
29 | "cell_type": "code",
30 | "execution_count": null,
31 | "metadata": {
32 | "collapsed": true,
33 | "deletable": true,
34 | "editable": true
35 | },
36 | "outputs": [],
37 | "source": [
38 | "# just an example on how to write\n",
39 | "#regset_gen.write32(0x0, 0x0080)"
40 | ]
41 | },
42 | {
43 | "cell_type": "code",
44 | "execution_count": null,
45 | "metadata": {
46 | "collapsed": false,
47 | "deletable": true,
48 | "editable": true
49 | },
50 | "outputs": [],
51 | "source": [
52 | "from periphery import MMIO\n",
53 | "\n",
54 | "# Open am335x real-time clock subsystem page\n",
55 | "regset_acq = MMIO(0x40100000, 0x30000)\n",
56 | "\n",
57 | "# read control/status registers\n",
58 | "for adr in range(0, 0x100, 0x4):\n",
59 | " print(\"@{adr:08x} = 0x{dat:08x} = {dat:10d} = {dat:032b}\".format(adr=adr, dat=regset_acq.read32(adr)))\n",
60 | "# read the buffer\n",
61 | "for adr in range(0x10000, 0x10040, 0x4):\n",
62 | " print(\"@{adr:08x} = 0x{dat:08x} = {dat:10d} = {dat:032b}\".format(adr=adr, dat=regset_acq.read32(adr)))\n",
63 | "\n",
64 | "regset_acq.close()"
65 | ]
66 | }
67 | ],
68 | "metadata": {
69 | "kernelspec": {
70 | "display_name": "Python 3",
71 | "language": "python",
72 | "name": "python3"
73 | },
74 | "language_info": {
75 | "codemirror_mode": {
76 | "name": "ipython",
77 | "version": 3
78 | },
79 | "file_extension": ".py",
80 | "mimetype": "text/x-python",
81 | "name": "python",
82 | "nbconvert_exporter": "python",
83 | "pygments_lexer": "ipython3",
84 | "version": "3.5.2"
85 | }
86 | },
87 | "nbformat": 4,
88 | "nbformat_minor": 2
89 | }
90 |
--------------------------------------------------------------------------------
/experiments/scope_filter.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "metadata": {},
6 | "source": [
7 | "# Scope filter\n",
8 | "\n",
9 | "```\n",
10 | "Legend:\n",
11 | "R01, R02, R1, R2, R3, R4, R5 registers\n",
12 | "SHR n - right shift for n bits\n",
13 | "SHL n - left shift for n bits\n",
14 | "BB - zero for FIR part of equalization filter\n",
15 | "AA - pole for IIR part of equalization filter\n",
16 | "PP - pole for IIR part of shaping filter\n",
17 | "KK - gain\n",
18 | "Transfer function:\n",
19 | "H[z]=K*(z-B) / (z^4*(z-P) * (z-A))\n",
20 | "where:\n",
21 | "K=KK/2^24\n",
22 | "B=1-(BB/2^28)\n",
23 | "P=PP/2^16\n",
24 | "A=1-(AA/2^25)\n",
25 | "```\n",
26 | "\n",
27 | "$$ H[z] = \\frac {z K - B K} {z^4*(z^2 - z (P+A) + P A)} $$\n",
28 | "\n",
29 | "$$ H[z] = \\frac {z K - B K} {z^6 - z^5 (P+A) + z^4 P A} $$"
30 | ]
31 | },
32 | {
33 | "cell_type": "code",
34 | "execution_count": null,
35 | "metadata": {
36 | "collapsed": false
37 | },
38 | "outputs": [],
39 | "source": [
40 | "from scipy import signal\n",
41 | "import matplotlib.pyplot as plt\n",
42 | "\n",
43 | "AA = 0x7D93\n",
44 | "BB = 0x437C7\n",
45 | "PP = 0x2666\n",
46 | "KK = 0xd9999a\n",
47 | "\n",
48 | "K=KK/2**24\n",
49 | "B=1-(BB/2**28)\n",
50 | "P=PP/2**16\n",
51 | "A=1-(AA/2**25)\n",
52 | "\n",
53 | "num = [K, -K*B]\n",
54 | "den = [1, -(P+A), P*A, 0, 0, 0, 0]\n",
55 | "\n",
56 | "scope_filter = signal.TransferFunction(num, den, dt=0.000000008)"
57 | ]
58 | },
59 | {
60 | "cell_type": "code",
61 | "execution_count": null,
62 | "metadata": {
63 | "collapsed": false
64 | },
65 | "outputs": [],
66 | "source": [
67 | "w, mag, phase = signal.dbode(scope_filter)\n",
68 | "\n",
69 | "plt.figure()\n",
70 | "plt.semilogx(w, mag) # Bode magnitude plot\n",
71 | "plt.figure()\n",
72 | "plt.semilogx(w, phase) # Bode phase plot\n",
73 | "plt.show()"
74 | ]
75 | },
76 | {
77 | "cell_type": "code",
78 | "execution_count": null,
79 | "metadata": {
80 | "collapsed": false
81 | },
82 | "outputs": [],
83 | "source": [
84 | "from scipy import __version__\n",
85 | "__version__"
86 | ]
87 | }
88 | ],
89 | "metadata": {
90 | "kernelspec": {
91 | "display_name": "Python 3",
92 | "language": "python",
93 | "name": "python3"
94 | },
95 | "language_info": {
96 | "codemirror_mode": {
97 | "name": "ipython",
98 | "version": 3
99 | },
100 | "file_extension": ".py",
101 | "mimetype": "text/x-python",
102 | "name": "python",
103 | "nbconvert_exporter": "python",
104 | "pygments_lexer": "ipython3",
105 | "version": "3.5.2"
106 | }
107 | },
108 | "nbformat": 4,
109 | "nbformat_minor": 2
110 | }
111 |
--------------------------------------------------------------------------------
/redpitaya/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ['overlay', 'drv', 'app']
2 |
--------------------------------------------------------------------------------
/redpitaya/app/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ['generator', 'oscilloscope']
2 |
--------------------------------------------------------------------------------
/redpitaya/app/generator.py:
--------------------------------------------------------------------------------
1 | # FPGA configuration and API
2 | from redpitaya.overlay.mercury import mercury as overlay
3 |
4 | # system and mathematics libraries
5 | import time
6 | import math
7 | import numpy as np
8 |
9 | # visualization
10 | from bokeh.io import push_notebook, show, output_notebook
11 | from bokeh.models import HoverTool, Range1d
12 | from bokeh.plotting import figure
13 | from bokeh.layouts import widgetbox
14 | from bokeh.resources import INLINE
15 |
16 | # widgets
17 | from IPython.display import display
18 | import ipywidgets as ipw
19 |
20 | class generator (object):
21 | def __init__ (self, channels = [0, 1]):
22 | """Generator application"""
23 |
24 | # instantiate both generators
25 | self.channels = channels
26 |
27 | # this will load the FPGA
28 | try:
29 | self.ovl = overlay()
30 | except ResourceWarning:
31 | print ("FPGA bitstream is already loaded")
32 | # wait a bit for the overlay to be properly applied
33 | # TODO it should be automated in the library
34 | time.sleep(0.5)
35 |
36 | # generators
37 | self.gen = [self.channel(ch) for ch in self.channels]
38 |
39 | # display widgets
40 | for ch in self.channels:
41 | self.gen[ch].display()
42 |
43 | def __del__ (self):
44 | # close widgets
45 | for ch in self.channels:
46 | self.gen[ch].close()
47 | # delete generator and overlay objects
48 | del (self.gen)
49 | # TODO: overlay should not be removed if a different app added it
50 | del (self.ovl)
51 |
52 | class channel (overlay.gen):
53 | # waveform defaults
54 | form = 'sin'
55 | duty = 0.5
56 |
57 | def set_waveform (self):
58 | if self.form == 'sin':
59 | self.waveform = self.sin()
60 | elif self.form == 'square':
61 | self.waveform = self.square(self.duty)
62 | elif self.form == 'sawtooth':
63 | self.waveform = self.sawtooth(self.duty)
64 |
65 | def __init__ (self, ch):
66 |
67 | super().__init__(ch)
68 |
69 | self.reset()
70 | self.sync_src = overlay.sync_src['gen'+str(ch)]
71 | self.trig_src = 0
72 | self.mode = 'PERIODIC'
73 | self.amplitude = 0
74 | self.offset = 0
75 | self.set_waveform()
76 | self.frequency = self._f_one
77 | self.phase = 0
78 | self.start()
79 | self.trigger()
80 |
81 | fl_min = math.log10(self._f_min)
82 | fl_max = math.log10(self._f_max)
83 | fl_one = math.log10(self._f_one)
84 |
85 | # create widgets
86 | self.w_enable = ipw.ToggleButton (value=False, description='output enable')
87 | self.w_waveform = ipw.ToggleButtons(value='sin', options=['sin', 'square', 'sawtooth'], description='waveform')
88 | self.w_duty = ipw.FloatSlider (value=0.5, min=0.0, max=1.0, step=0.01, description='duty')
89 | self.w_amplitude = ipw.FloatSlider (value=0, min=-1.0, max=+1.0, step=0.02, description='amplitude')
90 | self.w_offset = ipw.FloatSlider (value=0, min=-1.0, max=+1.0, step=0.02, description='offset')
91 | self.w_frequency = ipw.FloatSlider (value=fl_one, min=fl_min, max=fl_max, step=0.02, description='frequency')
92 | self.w_phase = ipw.FloatSlider (value=0, min=0, max=360, step=1, description='phase')
93 |
94 | # style widgets
95 | self.w_enable.layout = ipw.Layout(width='100%')
96 | self.w_duty.layout = ipw.Layout(width='100%')
97 | self.w_amplitude.layout = ipw.Layout(width='100%')
98 | self.w_offset.layout = ipw.Layout(width='100%')
99 | self.w_frequency.layout = ipw.Layout(width='100%')
100 | self.w_phase.layout = ipw.Layout(width='100%')
101 |
102 | self.w_enable.observe (self.clb_enable , names='value')
103 | self.w_waveform.observe (self.clb_waveform , names='value')
104 | self.w_duty.observe (self.clb_duty , names='value')
105 | self.w_amplitude.observe(self.clb_amplitude, names='value')
106 | self.w_offset.observe (self.clb_offset , names='value')
107 | self.w_frequency.observe(self.clb_frequency, names='value')
108 | self.w_phase.observe (self.clb_phase , names='value')
109 |
110 | def clb_enable (self, change):
111 | self.enable = change['new']
112 |
113 | def clb_waveform (self, change):
114 | self.form = change['new']
115 | self.set_waveform()
116 |
117 | def clb_duty (self, change):
118 | self.duty = change['new']
119 | self.set_waveform()
120 |
121 | def clb_amplitude (self, change):
122 | self.amplitude = change['new']
123 |
124 | def clb_offset (self, change):
125 | self.offset = change['new']
126 |
127 | def clb_frequency (self, change):
128 | self.frequency = math.pow(10, change['new'])
129 |
130 | def clb_phase (self, change):
131 | self.phase = change['new']
132 |
133 | def display (self):
134 | layout = ipw.Layout(border='solid 2px', margin='2px 2px 2px 2px')
135 | # labels
136 | self.lbl_waveform = ipw.Label(value="waveform shapes" , layout = ipw.Layout(width='100%'))
137 | self.lbl_output = ipw.Label(value="amplitude [V] and offset [V]" , layout = ipw.Layout(width='100%'))
138 | self.lbl_frequency = ipw.Label(value="frequency [Hz] and phase [DEG]", layout = ipw.Layout(width='100%'))
139 | self.lbl_channel = ipw.Label(value="generator" , layout = ipw.Layout(width='100%'))
140 | # boxes
141 | self.box_enable = ipw.VBox([self.w_enable], layout = ipw.Layout(margin='2px 2px 2px 2px'))
142 | self.box_waveform = ipw.VBox([self.lbl_waveform, self.w_waveform, self.w_duty] , layout = layout)
143 | self.box_output = ipw.VBox([self.lbl_output, self.w_amplitude, self.w_offset], layout = layout)
144 | self.box_frequency = ipw.VBox([self.lbl_frequency, self.w_frequency, self.w_phase] , layout = layout)
145 | self.box_channel = ipw.VBox([self.lbl_channel,
146 | self.box_enable,
147 | self.box_waveform,
148 | self.box_output,
149 | self.box_frequency],
150 | layout = ipw.Layout(border='solid 2px',
151 | padding='2px 2px 2px 2px',
152 | margin='4px 0px 4px 0px') )
153 | display (self.box_channel)
154 |
155 | def close(self):
156 | # boxes
157 | self.box_channel.close()
158 | self.box_enable.close()
159 | self.box_waveform.close()
160 | self.box_output.close()
161 | self.box_frequency.close()
162 | # labels
163 | self.lbl_waveform.close()
164 | self.lbl_output.close()
165 | self.lbl_frequency.close()
166 | self.lbl_channel.close()
167 | # widgets
168 | self.w_enable.close()
169 | self.w_waveform.close()
170 | self.w_duty.close()
171 | self.w_amplitude.close()
172 | self.w_offset.close()
173 | self.w_frequency.close()
174 | self.w_phase.close()
175 |
176 | def __del__ (self):
177 | # widgets
178 | del(w_enable)
179 | del(w_waveform)
180 | del(w_duty)
181 | del(w_amplitude)
182 | del(w_offset)
183 | del(w_frequency)
184 | del(w_phase)
185 | # calling super class
186 | super().__del__()
187 |
--------------------------------------------------------------------------------
/redpitaya/drv/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ['overlay', 'uio', 'evn', 'hwid', 'mgmt', 'pdm', 'clb', 'wave', 'gen', 'osc', 'lg', 'la']
--------------------------------------------------------------------------------
/redpitaya/drv/acq.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 | import numpy as np
3 | import math
4 |
5 |
6 | class acq(object):
7 | CW = 31 #: counter size
8 | _CWr = 2**CW
9 |
10 | class _regset_t(Structure):
11 | _fields_ = [('cfg_pre', c_uint32), # configuration pre trigger
12 | ('cfg_pst', c_uint32), # configuration post trigger
13 | ('sts_pre', c_uint32), # status pre trigger
14 | ('sts_pst', c_uint32)] # status post trigger
15 |
16 | def show_regset(self):
17 | """Print FPGA module register set for debugging purposes."""
18 | print(
19 | "cfg_pre = 0x{reg:08x} = {reg:10d} # delay pre trigger \n".format(reg=self.regset.acq.cfg_pre) +
20 | "cfg_pst = 0x{reg:08x} = {reg:10d} # delay post trigger \n".format(reg=self.regset.acq.cfg_pst) +
21 | "sts_pre = 0x{reg:08x} = {reg:10d} # status pre trigger \n".format(reg=self.regset.acq.sts_pre) +
22 | "sts_pst = 0x{reg:08x} = {reg:10d} # status post trigger \n".format(reg=self.regset.acq.sts_pst)
23 | )
24 |
25 | def default(self):
26 | """Set registers into default (power-up) state."""
27 | self.regset.acq.cfg_pre = 0
28 | self.regset.acq.cfg_pst = 0
29 |
30 | @property
31 | def trigger_pre(self) -> int:
32 | """Pre trigger delay.
33 |
34 | Number of samples stored into the buffer
35 | after start() before a trigger event is accepted.
36 | It makes sense for this number to be up to buffer size.
37 | """
38 | return self.regset.acq.cfg_pre
39 |
40 | @trigger_pre.setter
41 | def trigger_pre(self, value: int):
42 | if (0 <= value < self._CWr):
43 | self.regset.acq.cfg_pre = value
44 | else:
45 | raise ValueError("Pre trigger delay should be positive and less or equal to {}.".format(self._CWr))
46 |
47 | @property
48 | def trigger_post(self) -> int:
49 | """Post trigger delay.
50 |
51 | Number of samples stored into the buffer
52 | after a trigger, before writing stops automatically.
53 | It makes sense for this number to be up to buffer size.
54 | """
55 | return self.regset.acq.cfg_pst
56 |
57 | @trigger_post.setter
58 | def trigger_post(self, value: int):
59 | if (0 <= value < self._CWr):
60 | self.regset.acq.cfg_pst = value
61 | else:
62 | raise ValueError("Post trigger delay should be positive and less or equal to {}.".format(self._CWr))
63 | # TODO check range
64 |
65 | @property
66 | def trigger_pre_status(self) -> int:
67 | """Pre trigger sample counter status."""
68 | return (self.regset.acq.sts_pre & 0x7fffffff)
69 |
70 | @property
71 | def trigger_post_status(self) -> int:
72 | """Post trigger sample counter status."""
73 | return (self.regset.acq.sts_pst & 0x7fffffff)
74 |
--------------------------------------------------------------------------------
/redpitaya/drv/asg_bst.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 |
4 | class asg_bst (object):
5 | """
6 | Generator FPGA module driver.
7 | """
8 |
9 | # burst counter parameters
10 | CWR = 14 #: counter width - burst data repetition
11 | CWL = 32 #: counter width - burst period length
12 | CWN = 16 #: counter width - burst period number
13 | _CWRr = 2**CWR
14 | _CWLr = 2**CWL
15 | _CWNr = 2**CWN
16 |
17 | class _regset_t(Structure):
18 | _fields_ = [('cfg_bdr', c_uint32), # burst data repetitions
19 | ('cfg_bdl', c_uint32), # burst data length
20 | ('cfg_bpl', c_uint32), # burst period length (data+pause)
21 | ('cfg_bpn', c_uint32), # burst period number
22 | ('sts_bln', c_uint32), # length (current position inside burst length)
23 | ('sts_bnm', c_uint32)] # number (current burst counter)
24 |
25 | def default(self):
26 | """Set registers into default (power-up) state."""
27 | self.regset.bst.cfg_bdr = 0
28 | self.regset.bst.cfg_bdl = 0
29 | self.regset.bst.cfg_bpl = 0
30 | self.regset.bst.cfg_bpn = 0
31 |
32 | def show_regset(self):
33 | """Print FPGA module register set for debugging purposes."""
34 | print(
35 | "cfg_bdr = 0x{reg:08x} = {reg:10d} # burst data repetition \n".format(reg=self.regset.bst.cfg_bdr) +
36 | "cfg_bdl = 0x{reg:08x} = {reg:10d} # burst data length \n".format(reg=self.regset.bst.cfg_bdl) +
37 | "cfg_bpl = 0x{reg:08x} = {reg:10d} # burst period length \n".format(reg=self.regset.bst.cfg_bpl) +
38 | "cfg_bpn = 0x{reg:08x} = {reg:10d} # burst period number \n".format(reg=self.regset.bst.cfg_bpn) +
39 | "sts_bln = 0x{reg:08x} = {reg:10d} # burst length (current position)\n".format(reg=self.regset.bst.sts_bln) +
40 | "sts_bnm = 0x{reg:08x} = {reg:10d} # burst number (current counter) \n".format(reg=self.regset.bst.sts_bnm)
41 | )
42 |
43 | @property
44 | def burst_data_repetitions(self) -> int:
45 | """Burst data repetitions, up to 2**`CWR`."""
46 | return (self.regset.bst.cfg_bdr + 1)
47 |
48 | @burst_data_repetitions.setter
49 | def burst_data_repetitions(self, value: int):
50 | if (0 < value <= self._CWRr):
51 | self.regset.bst.cfg_bdr = value - 1
52 | else:
53 | raise ValueError("Burst data repetitions should be in range from 1 to {}.".format(self._CWRr))
54 |
55 | @property
56 | def burst_data_length(self) -> int:
57 | """Burst data length, up to waveform array size."""
58 | return (self.regset.bst.cfg_bdl + 1)
59 |
60 | @burst_data_length.setter
61 | def burst_data_length(self, value: int):
62 | if (0 < value <= self.buffer_size):
63 | self.regset.bst.cfg_bdl = value - 1
64 | else:
65 | raise ValueError("Burst data length should be in range from 1 to {}.".format(self.buffer_size))
66 |
67 | @property
68 | def burst_period_length(self) -> int:
69 | """Burst period length (data+pause), up to 2**`CWL`."""
70 | return (self.regset.bst.cfg_bpl + 1)
71 |
72 | @burst_period_length.setter
73 | def burst_period_length(self, value: int):
74 | if (0 < value <= self._CWLr):
75 | self.regset.bst.cfg_bpl = value - 1
76 | else:
77 | raise ValueError("Burst period length should be in range from 1 to {}.".format(self._CWLr))
78 |
79 | @property
80 | def burst_period_number(self) -> int:
81 | """Number of burst period reperitions, up to 2**`CWN`, value `0` produces infinite repetition."""
82 | value = self.regset.bst.cfg_bpn
83 | if (value & 0x80000000):
84 | return (0)
85 | else:
86 | return (value + 1)
87 |
88 | @burst_period_number.setter
89 | def burst_period_number(self, value: int):
90 | if (value == 0):
91 | self.regset.bst.cfg_bpn = 0x80000000
92 | elif (0 < value <= self._CWNr):
93 | self.regset.bst.cfg_bpn = value - 1
94 | else:
95 | raise ValueError("Burst period number should be in range from 1 to {}, or 0 for inifinite bursts.".format(self._CWNr))
96 |
--------------------------------------------------------------------------------
/redpitaya/drv/asg_per.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 |
4 | class asg_per(object):
5 | """
6 | Generator FPGA module driver.
7 | """
8 |
9 | # buffer parameters (fixed point number uM.F)
10 | CWM = 14 #: counter width - magnitude (fixed point integer)
11 | CWF = 16 #: counter width - fraction (fixed point fraction)
12 | CW = CWM + CWF
13 | # buffer counter ranges
14 | _CWMr = 2**CWM
15 | _CWFr = 2**CWF
16 |
17 | class _regset_t(Structure):
18 | _fields_ = [('cfg_siz', c_uint32), # size
19 | ('cfg_off', c_uint32), # offset
20 | ('cfg_ste', c_uint32)] # step
21 |
22 | def default(self):
23 | """Set registers into default (power-up) state."""
24 | self.regset.per.cfg_siz = 0
25 | self.regset.per.cfg_ste = 0
26 | self.regset.per.cfg_off = 0
27 |
28 | def show_regset(self):
29 | """Print FPGA module register set for debugging purposes."""
30 | print(
31 | "cfg_siz = 0x{reg:08x} = {reg:10d} # waveform size \n".format(reg=self.regset.per.cfg_siz) +
32 | "cfg_off = 0x{reg:08x} = {reg:10d} # waveform offset\n".format(reg=self.regset.per.cfg_off) +
33 | "cfg_ste = 0x{reg:08x} = {reg:10d} # waveform step \n".format(reg=self.regset.per.cfg_ste)
34 | )
35 |
36 | @property
37 | def waveform_size(self) -> int:
38 | """Waveform size."""
39 | return ((self.regset.per.cfg_siz + 1) >> self.CWF)
40 |
41 | @waveform_size.setter
42 | def waveform_size(self, value: int):
43 | if (0 < value <= self.buffer_size):
44 | self.regset.per.cfg_siz = (value << self.CWF) - 1
45 | else:
46 | raise ValueError("Waveform size should in range from 1 to buffer size. buffer_size = {}".format(self.buffer_size))
47 |
48 | @property
49 | def frequency(self) -> float:
50 | """Periodic signal frequency up to FS/2"""
51 | siz = self.regset.per.cfg_siz + 1
52 | ste = self.regset.per.cfg_ste + 1
53 | return (ste / siz * self.FS)
54 |
55 | @frequency.setter
56 | def frequency(self, value: float):
57 | if (value < self.FS/2):
58 | siz = self.regset.per.cfg_siz + 1
59 | self.regset.per.cfg_ste = int(siz * (value / self.FS)) - 1
60 | else:
61 | raise ValueError("Frequency should be less then half the sample rate. f < FS/2 = {} Hz".format(self.FS/2))
62 |
63 | @property
64 | def phase(self) -> float:
65 | """Periodic signal phase in angular degrees"""
66 | siz = self.regset.per.cfg_siz + 1
67 | off = self.regset.per.cfg_off
68 | return (off / siz * 360)
69 |
70 | @phase.setter
71 | def phase(self, value: float):
72 | siz = self.regset.per.cfg_siz + 1
73 | self.regset.per.cfg_off = int(siz * (value % 360) / 360)
74 |
--------------------------------------------------------------------------------
/redpitaya/drv/evn.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 |
4 | class evn():
5 | # control register masks
6 | _CTL_TRG_MASK = 1<<3 # sw trigger bit (sw trigger must be enabled)
7 | _CTL_STP_MASK = 1<<2 # stop/abort; returns 1 when stopped
8 | _CTL_STR_MASK = 1<<1 # start
9 | _CTL_RST_MASK = 1<<0 # reset state machine so that it is in known state
10 |
11 | class _regset_t (Structure):
12 | _fields_ = [('ctl_sts', c_uint32), # control/status register
13 | ('cfg_evn', c_uint32), # software event source select
14 | ('cfg_trg', c_uint32)] # hardware trigger mask
15 |
16 | def default(self):
17 | """Set registers into default (power-up) state."""
18 | self.regset.evn.cfg_evn = 0 # TODO: it should probably be pointing to itself
19 | self.regset.evn.cfg_trg = 0
20 |
21 | def show_regset(self):
22 | """Print FPGA module register set for debugging purposes."""
23 | print(
24 | "ctl_sts = 0x{reg:08x} = {reg:10d} # control/status \n".format(reg=self.regset.evn.ctl_sts) +
25 | "cfg_evn = 0x{reg:08x} = {reg:10d} # SW event source select\n".format(reg=self.regset.evn.cfg_evn) +
26 | "cfg_trg = 0x{reg:08x} = {reg:10d} # HW trigger mask \n".format(reg=self.regset.evn.cfg_trg)
27 | )
28 |
29 | def reset(self):
30 | """Reset state machine, is used to synchronize alwways running streams."""
31 | self.regset.evn.ctl_sts = self._CTL_RST_MASK
32 |
33 | def start(self):
34 | """Start starte machine."""
35 | self.regset.evn.ctl_sts = self._CTL_STR_MASK
36 |
37 | def stop(self):
38 | """Stop state machine."""
39 | self.regset.evn.ctl_sts = self._CTL_STP_MASK
40 |
41 | def trigger(self):
42 | """Activate SW trigger."""
43 | self.regset.evn.ctl_sts = self._CTL_TRG_MASK
44 |
45 | def start_trigger(self):
46 | """Start state machine and activate SW trigger."""
47 | self.regset.evn.ctl_sts = self._CTL_TRG_MASK | self._CTL_STR_MASK
48 |
49 | def status_run(self) -> bool:
50 | """Run status."""
51 | return bool(self.regset.evn.ctl_sts & self._CTL_STR_MASK)
52 |
53 | def status_trigger(self) -> bool:
54 | """Trigger status."""
55 | return bool(self.regset.evn.ctl_sts & self._CTL_TRG_MASK)
56 |
57 | @property
58 | def sync_src(self) -> int:
59 | """Select for software event sources."""
60 | return self.regset.evn.cfg_evn
61 |
62 | @sync_src.setter
63 | def sync_src(self, value: int):
64 | self.regset.evn.cfg_evn = value
65 |
66 | @property
67 | def trig_src(self) -> int:
68 | """Enable mask for hardware trigger sources."""
69 | return self.regset.evn.cfg_trg
70 |
71 | @trig_src.setter
72 | def trig_src(self, value: int):
73 | self.regset.evn.cfg_trg = value
74 |
--------------------------------------------------------------------------------
/redpitaya/drv/fixp.py:
--------------------------------------------------------------------------------
1 | class fixp (object):
2 | """Fixed point basic class."""
3 | __init__(self, s: bool, m: int, f: int):
4 | self.s = s
5 | self.m = m
6 | self.f = f
7 |
8 | @property
9 | def num(self) -> int:
10 | """Number of possible values."""
11 | return ( (1<<(v.s+v.m+v.f)) )
12 |
13 | @property
14 | def max(self) -> int:
15 | """Maximum value (positive)."""
16 | return ( (+(1<<( v.m+v.f))-1) )
17 |
18 | @property
19 | def min(self) -> int:
20 | """Minimum value (nagetive or zero for unsigned)."""
21 | return ((v.s ? (-(1<<( v.m+v.f)) ) : 0))
22 |
23 | @property
24 | def unit(self) -> int:
25 | """Unit (1) value."""
26 | return ( (1<<( v.f)) )
27 |
28 | @property
29 | def bits(self) -> int:
30 | """Number of used bits."""
31 | return ( (v.s+v.m+v.f) )
32 |
33 | def float2fixp(self, value: float) -> int:
34 | """Conversion from ``float`` fixed point."""
35 | if ((not self.s) and (value < 0)):
36 | raise ValueError("This fixed point number is unsigned, so negative values are not supported.")
37 | else:
38 | return int(value*self.unit)
39 |
40 | def fixp2float(self, value: int) -> float:
41 | """Conversion from ``float`` fixed point."""
42 | return (float(value)/float(self.unit))
43 |
--------------------------------------------------------------------------------
/redpitaya/drv/gen.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 | import numpy as np
3 |
4 | from enum import Enum
5 |
6 | import mmap
7 |
8 | from .evn import evn
9 | from .asg_per import asg_per
10 | from .asg_bst import asg_bst
11 | from .gen_out import gen_out
12 | from .wave import wave
13 | from .uio import uio
14 |
15 |
16 | class gen(evn, asg_per, asg_bst, gen_out, wave, uio):
17 | """
18 | Generator FPGA module driver.
19 | """
20 |
21 | #: sampling frequency
22 | FS = 125000000.0
23 | # linear addition multiplication register width
24 | DW = 14 #: data width - streaming sample
25 | DWM = 14 #: data width - linear gain multiplier
26 | DWS = 14 #: data width - linear offset summand
27 | # fixed point range
28 | _DWr = (1 << (DW -1)) - 1
29 | _DWMr = (1 << (DWM-2))
30 | _DWSr = (1 << (DWS-1)) - 1
31 |
32 | class _regset_t(Structure):
33 | _fields_ = [('evn', evn._regset_t),
34 | ('rsv_000', c_uint32),
35 | ('cfg_mod', c_uint32), # mode
36 | ('per', asg_per._regset_t),
37 | ('bst', asg_bst._regset_t),
38 | ('rsv_001', c_uint32 * 2),
39 | ('out', gen_out._regset_t)]
40 |
41 | class _buffer_t(Array):
42 | _length_ = 2**14
43 | _type_ = c_int32
44 |
45 | def __init__(self, index: int, uio: str = '/dev/uio/gen'):
46 | """Module instance index should be provided"""
47 |
48 | # use index
49 | uio = uio+str(index)
50 |
51 | # call parent class init to open UIO device and mmap maps
52 | super().__init__(uio)
53 |
54 | # map regset
55 | self.regset = self._regset_t.from_buffer(self.uio_mmaps[0])
56 | # map buffer
57 | self.buffer = self._buffer_t.from_buffer(self.uio_mmaps[1])
58 |
59 | # calculate constants
60 | self.buffer_size = 2**self.CWM #: buffer size
61 |
62 | # logaritmic scale from 0.116Hz to 62.5Mhz
63 | self._f_min = self.FS / 2**self.CW
64 | self._f_max = self.FS / 2
65 | self._f_one = self.FS / 2**self.CWM
66 |
67 | def __del__(self):
68 | # disable output
69 | self.enable = False
70 | # make sure state machine is not running
71 | self.reset()
72 | # call parent class init to unmap maps and close UIO device
73 | super().__del__()
74 |
75 | def default(self):
76 | """Set registers into default (power-up) state."""
77 | evn.default(self)
78 | self.regset.cfg_mod = 0
79 | asg_per.default(self)
80 | asg_bst.default(self)
81 | gen_out.default(self)
82 |
83 | def show_regset(self):
84 | """Print FPGA module register set for debugging purposes."""
85 | evn.show_regset(self)
86 | print(
87 | "cfg_mod = 0x{reg:08x} = {reg:10d} # burst mode\n".format(reg=self.regset.cfg_mod)
88 | )
89 | asg_per.show_regset(self)
90 | asg_bst.show_regset(self)
91 | gen_out.show_regset(self)
92 |
93 | @property
94 | def waveform(self):
95 | """Waveworm array containing normalized values in the range [-1,1].
96 |
97 | Array can be up to `buffer_size` samples in length.
98 | """
99 | scale = float(self._DWr)
100 | # TODO: nparray
101 | return [self.buffer[i] / scale for i in range(self.waveform_size)]
102 |
103 | @waveform.setter
104 | def waveform(self, value):
105 | siz = len(value)
106 | if (siz <= self.buffer_size):
107 | for i in range(siz):
108 | # TODO add saturation
109 | scale = float(self._DWr)
110 | self.buffer[i] = int(value[i] * scale)
111 | self.waveform_size = siz
112 | else:
113 | raise ValueError("Waveform buffer size should not excede buffer size. buffer_size = {}".format(self.buffer_size))
114 |
115 | class modes(Enum):
116 | PERIODIC = 0x0
117 | BURST = 0x1
118 |
119 | @property
120 | def mode(self) -> str:
121 | """Generator mode:
122 |
123 | * 'PERIODIC' - continuous/periodic signals
124 | * 'BURST' - finite/infinite bursts
125 | """
126 | return self.modes(self.regset.cfg_mod)
127 |
128 | @mode.setter
129 | def mode(self, value: str):
130 | if isinstance(value, str):
131 | self.regset.cfg_mod = self.modes[value].value
132 | else:
133 | raise ValueError("Generator supports modes ['PERIODIC', 'BURST'].")
134 |
--------------------------------------------------------------------------------
/redpitaya/drv/gen_out.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 | import numpy as np
3 |
4 |
5 | class gen_out(object):
6 | # linear addition multiplication register width
7 | DWM = 14 #: data width - linear gain multiplier
8 | DWS = 14 #: data width - linear offset summand
9 | # fixed point range
10 | _DWMr = (1 << (DWM-2))
11 | _DWSr = (1 << (DWS-1)) - 1
12 |
13 | class _regset_t(Structure):
14 | _fields_ = [('cfg_mul', c_int32), # multiplier (amplitude)
15 | ('cfg_sum', c_int32), # adder (offset)
16 | ('cfg_ena', c_uint32)] # output enable
17 |
18 | def default(self):
19 | """Set registers into default (power-up) state."""
20 | self.regset.out.cfg_mul = int(1 * self._DWMr)
21 | self.regset.out.cfg_sum = 0
22 | self.regset.out.cfg_ena = 0
23 |
24 | def show_regset(self):
25 | """Print FPGA module register set for debugging purposes."""
26 | print(
27 | "cfg_mul = 0x{reg:08x} = {reg:10d} # multiplier (amplitude)\n".format(reg=self.regset.out.cfg_mul) +
28 | "cfg_sum = 0x{reg:08x} = {reg:10d} # adder (offset) \n".format(reg=self.regset.out.cfg_sum) +
29 | "cfg_ena = 0x{reg:08x} = {reg:10d} # output enable \n".format(reg=self.regset.out.cfg_ena)
30 | )
31 |
32 | @property
33 | def amplitude(self) -> float:
34 | """Output amplitude in range [-1,1] vols."""
35 | return (self.regset.out.cfg_mul / self._DWMr)
36 |
37 | @amplitude.setter
38 | def amplitude(self, value: float):
39 | if (-1.0 <= value <= 1.0):
40 | self.regset.out.cfg_mul = int(value * self._DWMr)
41 | else:
42 | raise ValueError("Output amplitude should be inside [-1,1] volts.")
43 |
44 | @property
45 | def offset(self) -> float:
46 | """Output offset in range [-1,1] vols."""
47 | return (self.regset.out.cfg_sum / self._DWSr)
48 |
49 | @offset.setter
50 | def offset(self, value: float):
51 | if (-1.0 <= value <= 1.0):
52 | self.regset.out.cfg_sum = int(value * self._DWSr)
53 | else:
54 | raise ValueError("Output offset should be inside [-1,1] volts.")
55 |
56 | @property
57 | def enable(self) -> bool:
58 | """Output enable boolean value."""
59 | return bool(self.regset.out.cfg_ena)
60 |
61 | @enable.setter
62 | def enable(self, value: bool):
63 | self.regset.out.cfg_ena = int(value)
64 |
--------------------------------------------------------------------------------
/redpitaya/drv/hwid.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 | from .uio import uio
4 |
5 |
6 | class hwid(uio):
7 | """Driver for hardware identification module.
8 |
9 | Attributes
10 | ----------
11 | hwid : int
12 | Red Pitaya FPGA identification number (32bit).
13 | efuse : int
14 | Zynq FPGA efuse (57bit).
15 | dna : int
16 | Zynq FPGA DNA number (57bit).
17 | gith : str
18 | Git hash (160 bits, 40 hex characters)
19 |
20 | .. note::
21 |
22 | Future releases might provide access to other Zynq FPGA features.
23 | """
24 | class _regset_t(Structure):
25 | _fields_ = [('hwid' , c_uint32 ),
26 | ('rsv0' , c_uint32 ), # reserved
27 | ('efuse', c_uint32 ),
28 | ('rsv1' , c_uint32 ), # reserved
29 | ('dna' , c_uint32 * 2),
30 | ('rsv3' , c_uint32 * 2), # reserved
31 | ('gith' , c_uint32 * 5)]
32 |
33 | def __init__(self, uio: str = '/dev/uio/hwid'):
34 | super().__init__(uio)
35 | self.regset = self._regset_t.from_buffer(self.uio_mmaps[0])
36 |
37 | def __del__(self):
38 | super().__del__()
39 |
40 | @property
41 | def hwid(self) -> int:
42 | """Red Pitaya FPGA identification number.
43 |
44 | A 32bit read only register defined at FPGA compile time.
45 | """
46 | return self.regset.hwid
47 |
48 | @property
49 | def efuse(self) -> int:
50 | """Zynq FPGA efuse.
51 |
52 | A 32bit value, read only for now, future versions might provide a convoluted write access scheme.
53 | """
54 | return self.regset.efuse
55 |
56 | @property
57 | def dna(self) -> int:
58 | """Zynq FPGA DNA number.
59 |
60 | A 57bit read-only value defined in manufacturing.
61 | Can be used as an almost unique device identification.
62 | """
63 | return ((self.regset.dna[1] << 32) | self.regset.dna[0])
64 |
65 | @property
66 | def gith(self) -> str:
67 | """Git hash.
68 |
69 | A full SHA-1 hash (160 bits, 40 hex characters)
70 | for the repository from which the FPGA was built.
71 | """
72 | return (''.join(["{:08x}".format(self.regset.gith[i]) for i in range(5)]))
73 |
--------------------------------------------------------------------------------
/redpitaya/drv/la.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 | import numpy as np
3 | import math
4 |
5 | import mmap
6 |
7 | from .evn import evn
8 | from .acq import acq
9 | from .la_trg import la_trg
10 | from .la_rle import la_rle
11 | from .la_msk import la_msk
12 | from .uio import uio
13 |
14 |
15 | class la(evn, acq, la_trg, la_rle, la_msk, uio):
16 | #: sampling frequency
17 | FS = 125000000.0
18 | #: register width - linear addition multiplication
19 | DW = 16
20 | # fixed point range
21 | _DWr = (1 << (DW-1)) - 1
22 | # buffer parameters
23 | buffer_size = 2**14 #: buffer size
24 | CW = 31 #: counter size
25 | _CWr = 2**CW
26 |
27 | class _regset_t (Structure):
28 | _fields_ = [('evn', evn._regset_t),
29 | ('rsv_000', c_uint32),
30 | ('acq', acq._regset_t), # pre/post trigger counters
31 | ('trg', la_trg._regset_t), # trigger (value, edge) detection
32 | ('rle', la_rle._regset_t), # RLE
33 | ('rsv_001', c_uint32),
34 | ('msk', la_msk._regset_t)] # mask/polarity
35 |
36 | class _buffer_t(Array):
37 | _length_ = 2**14
38 | _type_ = c_int16
39 |
40 | def __init__(self, uio: str = '/dev/uio/la'):
41 | # call parent class init to open UIO device and map regset
42 | super().__init__(uio)
43 |
44 | # map regset
45 | self.regset = self._regset_t.from_buffer(self.uio_mmaps[0])
46 | # map buffer
47 | self.buffer = self._buffer_t.from_buffer(self.uio_mmaps[1])
48 |
49 | def __del__(self):
50 | # call parent class init to unmap maps and close UIO device
51 | super().__del__()
52 |
53 | def default(self):
54 | """Set registers into default (power-up) state."""
55 | evn.default(self)
56 | acq.default(self)
57 | la_trg.default(self)
58 | la_rle.default(self)
59 | la_msk.default(self)
60 |
61 | def show_regset(self):
62 | """Print FPGA module register set for debugging purposes."""
63 | evn.show_regset(self)
64 | acq.show_regset(self)
65 | la_trg.show_regset(self)
66 | la_rle.show_regset(self)
67 | la_msk.show_regset(self)
68 |
69 | @property
70 | def sample_rate(self) -> float:
71 | """Sample rate depending on decimation factor."""
72 | return (self.FS / self.decimation)
73 |
74 | @property
75 | def sample_period(self) -> float:
76 | """Sample period depending on decimation factor."""
77 | return (1 / self.sample_rate)
78 |
79 | @property
80 | def pointer(self):
81 | # mask out overflow bit and sum pre and post trigger counters
82 | cnt = self.trigger_pre_status + self.trigger_post_status
83 | adr = cnt % self.buffer_size
84 | return adr
85 |
86 | def data(self, siz: int = buffer_size, ptr: int = None) -> np.array:
87 | """Data.
88 |
89 | Parameters
90 | ----------
91 | siz : int, optional
92 | Number of data samples to be read from the FPGA buffer.
93 | ptr : int, optional
94 | End of data pointer, only use if you understand
95 | the source code.
96 |
97 | Returns
98 | -------
99 | array
100 | Array containing binary samples.
101 | The data is alligned at the end to the last sample
102 | stored into the buffer.
103 | """
104 | if ptr is None:
105 | ptr = int(self.pointer)
106 | adr = (self.buffer_size + ptr - siz) % self.buffer_size
107 | ret = []
108 | for i in range(siz):
109 | ret.append(self.buffer[(i + ptr) % self.buffer_size])
110 | return ret
111 |
--------------------------------------------------------------------------------
/redpitaya/drv/la_msk.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 |
4 | class la_msk(object):
5 | class _regset_t(Structure):
6 | _fields_ = [('cfg_msk', c_uint32), # input mask
7 | ('cfg_pol', c_uint32), # input polarity
8 | ('cfg_dec', c_uint32)] # decimation factor
9 |
10 | def default(self):
11 | """Set registers into default (power-up) state."""
12 | self.regset.msk.cfg_msk = 0
13 | self.regset.msk.cfg_pol = 0
14 | self.regset.msk.cfg_dec = 0
15 |
16 | def show_regset(self):
17 | """Print FPGA module register set for debugging purposes."""
18 | print(
19 | "cfg_msk = 0x{reg:08x} = {reg:10d} # input mask \n".format(reg=self.regset.msk.cfg_msk) +
20 | "cfg_pol = 0x{reg:08x} = {reg:10d} # input polarity \n".format(reg=self.regset.msk.cfg_pol) +
21 | "cfg_dec = 0x{reg:08x} = {reg:10d} # decimation factor\n".format(reg=self.regset.msk.cfg_dec)
22 | )
23 |
24 | @property
25 | def input_mask(self) -> int:
26 | """Input signal bit mask (can be used to reduce power consumption)."""
27 | return self.regset.msk.cfg_msk
28 |
29 | @input_mask.setter
30 | def input_mask(self, value: int):
31 | self.regset.msk.cfg_msk = value
32 |
33 | @property
34 | def input_polarity(self) -> int:
35 | """Input signal bit polarity."""
36 | return self.regset.msk.cfg_pol
37 |
38 | @input_polarity.setter
39 | def input_polarity(self, value: int):
40 | self.regset.msk.cfg_pol = value
41 |
42 | @property
43 | def decimation(self) -> int:
44 | """Decimation factor."""
45 | return (self.regset.cfg_dec + 1)
46 |
47 | @decimation.setter
48 | def decimation(self, value: int):
49 | # TODO check range
50 | self.regset.cfg_dec = value - 1
51 |
--------------------------------------------------------------------------------
/redpitaya/drv/la_rle.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 |
4 | class la_rle(object):
5 | class _regset_t(Structure):
6 | _fields_ = [('cfg_rle', c_uint32), # RLE mode
7 | ('sts_cur', c_uint32), # current counter
8 | ('sts_lst', c_uint32)] # last counter
9 |
10 | def default(self):
11 | """Set registers into default (power-up) state."""
12 | self.regset.rle.cfg_rle = 0
13 |
14 | def show_regset(self):
15 | """Print FPGA module register set for debugging purposes."""
16 | print(
17 | "cfg_rle = 0x{reg:08x} = {reg:10d} # RLE mode \n".format(reg=self.regset.rle.cfg_rle) +
18 | "sts_cur = 0x{reg:08x} = {reg:10d} # current counter\n".format(reg=self.regset.rle.sts_cur) +
19 | "sts_lst = 0x{reg:08x} = {reg:10d} # last counter\n".format(reg=self.regset.rle.sts_lst)
20 | )
21 |
22 | @property
23 | def rle(self) -> bool:
24 | """RLE mode enable."""
25 | return bool(self.regset.rle.cfg_rle)
26 |
27 | @rle.setter
28 | def rle(self, value: bool):
29 | self.regset.rle.cfg_rle = int(value)
30 |
31 | @property
32 | def counter_current(self) -> int:
33 | """Current data stream length counter."""
34 | return self.regset.rle.sts_cur
35 |
36 | @property
37 | def counter_last(self) -> int:
38 | """Last data stream length counter."""
39 | return self.regset.rle.sts_lst
40 |
--------------------------------------------------------------------------------
/redpitaya/drv/la_trg.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 |
4 | class la_trg(object):
5 | class _regset_t(Structure):
6 | _fields_ = [('cfg_cmp_msk', c_uint32), # comparator mask
7 | ('cfg_cmp_val', c_uint32), # comparator value
8 | ('cfg_edg_pos', c_uint32), # edge positive
9 | ('cfg_edg_neg', c_uint32)] # edge negative
10 |
11 | def show_regset(self):
12 | """Print FPGA module register set for debugging purposes."""
13 | print(
14 | "cfg_cmp_msk = 0x{reg:08x} = {reg:10d} # comparator mask \n".format(reg=self.regset.trg.cfg_cmp_msk) +
15 | "cfg_cmp_val = 0x{reg:08x} = {reg:10d} # comparator value\n".format(reg=self.regset.trg.cfg_cmp_val) +
16 | "cfg_edg_pos = 0x{reg:08x} = {reg:10d} # edge positive \n".format(reg=self.regset.trg.cfg_edg_pos) +
17 | "cfg_edg_neg = 0x{reg:08x} = {reg:10d} # edge negative \n".format(reg=self.regset.trg.cfg_edg_neg)
18 | )
19 |
20 | def default(self):
21 | """Set registers into default (power-up) state."""
22 | self.regset.trg.cfg_cmp_msk = 0
23 | self.regset.trg.cfg_cmp_val = 0
24 | self.regset.trg.cfg_edg_pos = 0
25 | self.regset.trg.cfg_edg_neg = 0
26 |
27 | @property
28 | def trigger_mask(self) -> int:
29 | """Trigger comparator mask."""
30 | return self.regset.trg.cfg_cmp_msk
31 |
32 | @trigger_mask.setter
33 | def trigger_mask(self, value: tuple):
34 | self.regset.trg.cfg_cmp_msk = value
35 |
36 | @property
37 | def trigger_value(self) -> int:
38 | """Trigger comparator value."""
39 | return self.regset.trg.cfg_cmp_val
40 |
41 | @trigger_value.setter
42 | def trigger_value(self, value: tuple):
43 | self.regset.trg.cfg_cmp_val = value
44 |
45 | @property
46 | def trigger_edge(self) -> tuple:
47 | """Trigger edge detection mask [pos, neg]."""
48 | return [self.regset.trg.cfg_edg_pos, self.regset.trg.cfg_edg_neg]
49 |
50 | @trigger_edge.setter
51 | def trigger_edge(self, value: tuple):
52 | [self.regset.trg.cfg_edg_pos, self.regset.trg.cfg_edg_neg] = value
53 |
--------------------------------------------------------------------------------
/redpitaya/drv/lg.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 | import numpy as np
3 |
4 | from enum import Enum
5 |
6 | import mmap
7 |
8 | from .evn import evn
9 | from .asg_bst import asg_bst
10 | from .lg_out import lg_out
11 | from .uio import uio
12 |
13 |
14 | class lg(evn, asg_bst, lg_out, uio):
15 | """
16 | Generator FPGA module driver.
17 | """
18 |
19 | #: sampling frequency
20 | FS = 125000000.0
21 | # linear addition multiplication register width
22 | DW = 16 #: data width - streaming sample
23 |
24 | CWM = 14
25 |
26 | class _regset_t(Structure):
27 | _fields_ = [('evn', evn._regset_t),
28 | ('rsv_000', c_uint32),
29 | ('cfg_bmd', c_uint32), # mode
30 | ('rsv_001', c_uint32 * 3),
31 | ('bst', asg_bst._regset_t),
32 | ('rsv_002', c_uint32 * 2),
33 | ('out', lg_out._regset_t)]
34 |
35 | class _buffer_t(Array):
36 | _length_ = 2**14
37 | _type_ = c_int32
38 |
39 | def __init__(self, uio: str = '/dev/uio/lg'):
40 | # call parent class init to open UIO device and mmap maps
41 | super().__init__(uio)
42 |
43 | # map regset
44 | self.regset = self._regset_t.from_buffer(self.uio_mmaps[0])
45 | # map buffer
46 | self.buffer = self._buffer_t.from_buffer(self.uio_mmaps[1])
47 |
48 | # calculate constants
49 | self.buffer_size = 2**self.CWM #: buffer size
50 |
51 | def __del__(self):
52 | # disable output
53 | self.enable = False
54 | # make sure state machine is not running
55 | self.reset()
56 | # call parent class init to unmap maps and close UIO device
57 | super().__del__()
58 |
59 | def default(self):
60 | """Set registers into default (power-up) state."""
61 | evn.default(self)
62 | asg_bst.default(self)
63 | lg_out.default(self)
64 |
65 | def show_regset(self):
66 | """Print FPGA module register set for debugging purposes."""
67 | evn.show_regset(self)
68 | asg_bst.show_regset(self)
69 | lg_out.show_regset(self)
70 |
71 | @property
72 | def waveform(self):
73 | """Waveworm array containing normalized values in the range [-1,1].
74 |
75 | Array can be up to `buffer_size` samples in length.
76 | """
77 | # TODO: nparray
78 | return [self.buffer[i] for i in range(self.waveform_size)]
79 |
80 | @waveform.setter
81 | def waveform(self, value):
82 | siz = len(value)
83 | if (siz <= self.buffer_size):
84 | for i in range(siz):
85 | self.buffer[i] = value[i]
86 | self.waveform_size = siz
87 | else:
88 | raise ValueError("Waveform table size should not excede buffer size. buffer_size = {}".format(self.buffer_size))
89 |
--------------------------------------------------------------------------------
/redpitaya/drv/lg_out.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 | import numpy as np
3 |
4 |
5 | class lg_out (object):
6 | """Logic generator output control.
7 |
8 | +----------------+----------------+-------------+----------------+-------------+-------------------------------+
9 | | ``cfg_oen[0]`` | ``cfg_oen[1]`` | ``cfg_msk`` | ``cfg_val`` | **output** | **output** |
10 | | out enable 0 | out enable 1 | out mask | value/polarity | **enable** | **equation** |
11 | +================+================+=============+================+=============+===============================+
12 | | 0 | 0 | x | x | Hi-Z | ``z`` |
13 | +----------------+----------------+-------------+----------------+-------------+-------------------------------+
14 | | 0 | 1 | 0 | | open drain | `` cfg_val ? 1 : z`` |
15 | +----------------+----------------+-------------+----------------+-------------+-------------------------------+
16 | | 0 | 1 | 1 | | open drain | ``asg_val ^ cfg_val ? 1 : z`` |
17 | +----------------+----------------+-------------+----------------+-------------+-------------------------------+
18 | | 1 | 0 | 0 | | open source | `` cfg_val ? z : 0`` |
19 | +----------------+----------------+-------------+----------------+-------------+-------------------------------+
20 | | 1 | 0 | 1 | | open source | ``asg_val ^ cfg_val ? z : 0`` |
21 | +----------------+----------------+-------------+----------------+-------------+-------------------------------+
22 | | 1 | 1 | 0 | | push-pull | `` cfg_val`` |
23 | +----------------+----------------+-------------+----------------+-------------+-------------------------------+
24 | | 1 | 1 | 1 | | push-pull | ``asg_val ^ cfg_val`` |
25 | +----------------+----------------+-------------+----------------+-------------+-------------------------------+
26 | """
27 |
28 | class _regset_t (Structure):
29 | _fields_ = [('cfg_oen', c_uint32 *2), # output enable [0,1]
30 | ('cfg_msk', c_uint32 ), # mask
31 | ('cfg_val', c_uint32 )] # value/polarity
32 |
33 | def default(self):
34 | """Set registers into default (power-up) state."""
35 | self.regset.out.cfg_oen[0] = 0
36 | self.regset.out.cfg_oen[1] = 0
37 | self.regset.out.cfg_msk = 0
38 | self.regset.out.cfg_val = 0
39 |
40 | def show_regset(self):
41 | """Print FPGA module register set for debugging purposes."""
42 | print(
43 | "cfg_oen[0] = 0x{reg:08x} = {reg:10d} # output enable 0\n".format(reg=self.regset.out.cfg_oen[0]) +
44 | "cfg_oen[1] = 0x{reg:08x} = {reg:10d} # output enable 1\n".format(reg=self.regset.out.cfg_oen[1]) +
45 | "cfg_msk = 0x{reg:08x} = {reg:10d} # output mask \n".format(reg=self.regset.out.cfg_msk) +
46 | "cfg_val = 0x{reg:08x} = {reg:10d} # value/polarity \n".format(reg=self.regset.out.cfg_val)
47 | )
48 |
49 | @property
50 | def enable(self) -> _regset_t.cfg_oen:
51 | """Output enable [oe0, oe1]."""
52 | return self.regset.out.cfg_oen
53 |
54 | @enable.setter
55 | def enable(self, value: tuple):
56 | if isinstance(value, int):
57 | value = [value]*2
58 | self.regset.out.cfg_oen[0] = value[0]
59 | self.regset.out.cfg_oen[1] = value[1]
60 |
61 | @property
62 | def mask(self) -> int:
63 | """Output mask."""
64 | return self.regset.out.cfg_msk
65 |
66 | @mask.setter
67 | def mask(self, value: int):
68 | self.regset.out.cfg_msk = value
69 |
70 | @property
71 | def value(self) -> int:
72 | """Output value."""
73 | return self.regset.out.cfg_val
74 |
75 | @value.setter
76 | def value(self, value: int):
77 | self.regset.out.cfg_val = value
78 |
--------------------------------------------------------------------------------
/redpitaya/drv/mgmt.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 | from .uio import uio
4 |
5 |
6 | class mgmt(uio):
7 | """Driver for hardware identification module"""
8 | class _regset_t(Structure):
9 | _fields_ = [('cfg_iom' , c_uint32), # GPIO mode (0 - PS GPIO, 1 - Logic generator)
10 | ('cfg_loop', c_uint32)] # enable internal digital loop from gen to osc
11 |
12 | def __init__(self, uio: str = '/dev/uio/mgmt'):
13 | super().__init__(uio)
14 | self.regset = self._regset_t.from_buffer(self.uio_mmaps[0])
15 |
16 | def __del__(self):
17 | super().__del__()
18 |
19 | def default(self):
20 | """Set registers into default (power-up) state."""
21 | self.regset.cfg_iom = 0x0
22 | self.regset.cfg_loop = 0x0
23 |
24 | def show_regset(self):
25 | """Print FPGA module register set for debugging purposes."""
26 | print(
27 | "cfg_iom = 0x{reg:08x} = {reg:10d} # GPIO mode \n".format(reg=self.regset.cfg_iom) +
28 | "cfg_loop = 0x{reg:08x} = {reg:10d} # gen->osc loop\n".format(reg=self.regset.cfg_loop)
29 | )
30 |
31 | @property
32 | def gpio_mode(self) -> int:
33 | """GPIO mode
34 |
35 | Each bit coresponds to one of {exp_n_io[7:0], exp_p_io[7:0]} GPIO pins.
36 | 0 - pin is connected to PS GPIO controller
37 | 1 - pin is connected to Logic generator.
38 | """
39 | return self.regset.cfg_iom
40 |
41 | @gpio_mode.setter
42 | def gpio_mode(self, value: int):
43 | self.regset.cfg_iom = value
44 |
45 | @property
46 | def loop(self) -> int:
47 | """Digital loopback (for debugging purposes)
48 |
49 | Each bit controls one of the loop paths:
50 | 0 - enable loop: gen0 -> osc0,
51 | 1 - enable loop: gen1 -> osc1.
52 | """
53 | return self.regset.cfg_loop
54 |
55 | @loop.setter
56 | def loop(self, value: int):
57 | self.regset.cfg_loop = value
58 |
--------------------------------------------------------------------------------
/redpitaya/drv/osc.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 | import numpy as np
3 | import math
4 |
5 | import mmap
6 |
7 | from .evn import evn
8 | from .acq import acq
9 | from .osc_trg import osc_trg
10 | from .osc_fil import osc_fil
11 | from .uio import uio
12 |
13 |
14 | class osc(evn, acq, osc_trg, osc_fil, uio):
15 | #: sampling frequency
16 | FS = 125000000.0
17 | #: register width - linear addition multiplication
18 | DW = 16
19 | # fixed point range
20 | _DWr = (1 << (DW-1)) - 1
21 | # buffer parameters
22 | buffer_size = 2**14 #: buffer size
23 | CW = 31 #: counter size
24 | _CWr = 2**CW
25 |
26 | #: analog stage range voltages
27 | ranges = (1.0, 20.0)
28 |
29 | class _regset_t(Structure):
30 | _fields_ = [('evn', evn._regset_t),
31 | ('rsv_000', c_uint32),
32 | ('acq', acq._regset_t), # pre/post trigger counters
33 | # edge detection
34 | ('trg', osc_trg._regset_t),
35 | ('rsv_001', c_uint32),
36 | # filter
37 | ('fil', osc_fil._regset_t)]
38 |
39 | class _buffer_t(Array):
40 | _length_ = 2**14
41 | _type_ = c_int16
42 |
43 | def __init__(self, index: int, input_range: float, uio: str = '/dev/uio/osc'):
44 | """Module instance index should be provided"""
45 |
46 | # use index
47 | uio = uio+str(index)
48 |
49 | # call parent class init to open UIO device and map regset
50 | super().__init__(uio)
51 |
52 | # map regset
53 | self.regset = self._regset_t.from_buffer(self.uio_mmaps[0])
54 | # map buffer
55 | self.buffer = self._buffer_t.from_buffer(self.uio_mmaps[1])
56 |
57 | # set input range (there is no default)
58 | self.input_range = input_range
59 |
60 | def __del__(self):
61 | # call parent class init to unmap maps and close UIO device
62 | super().__del__()
63 |
64 | def default(self):
65 | """Set registers into default (power-up) state."""
66 | evn.default(self)
67 | acq.default(self)
68 | osc_trg.default(self)
69 | osc_fil.default(self)
70 | self.input_range = self.input_range
71 |
72 | def show_regset(self):
73 | """Print FPGA module register set for debugging purposes."""
74 | evn.show_regset(self)
75 | acq.show_regset(self)
76 | osc_trg.show_regset(self)
77 | osc_fil.show_regset(self)
78 |
79 | @property
80 | def input_range(self) -> float:
81 | """Input range can be one of the supporte ranges.
82 |
83 | See HW board documentation for details.
84 | """
85 | return self.__input_range
86 |
87 | @input_range.setter
88 | def input_range(self, value: float):
89 | if value in self.ranges:
90 | self.__input_range = value
91 | self.filter_coeficients = self._filters[value]
92 | else:
93 | raise ValueError("Input range can be one of {} volts.".format(self.ranges))
94 |
95 | @property
96 | def sample_rate(self) -> float:
97 | """Sample rate depending on decimation factor."""
98 | return (self.FS / self.decimation)
99 |
100 | @property
101 | def sample_period(self) -> float:
102 | """Sample period depending on decimation factor."""
103 | return (1 / self.sample_rate)
104 |
105 | @property
106 | def pointer(self):
107 | # mask out overflow bit and sum pre and post trigger counters
108 | cnt = self.trigger_pre_status + self.trigger_post_status
109 | adr = cnt % self.buffer_size
110 | return adr
111 |
112 |
113 | def data(self, siz: int = buffer_size, ptr: int = None) -> np.array:
114 | """Data.
115 |
116 | Parameters
117 | ----------
118 | siz : int, optional
119 | Number of data samples to be read from the FPGA buffer.
120 | ptr : int, optional
121 | End of data pointer, only use if you understand
122 | the source code.
123 |
124 | Returns
125 | -------
126 | array
127 | Array containing float samples scaled
128 | to the selected analog range.
129 | The data is alligned at the end to the last sample
130 | stored into the buffer.
131 | """
132 | if ptr is None:
133 | ptr = int(self.pointer)
134 | scale = self.__input_range / float(self._DWr)
135 |
136 | buffer_np = np.ctypeslib.as_array(self.buffer)
137 | buffer_size = len(self.buffer)
138 |
139 | # get `siz`-segment by start and exlusive-end pointers
140 | start = ptr
141 | end = (ptr + siz) % buffer_size
142 | if start < end:
143 | return scale * buffer_np[start:end]
144 | else: # wrap around
145 | head_length = buffer_size - start
146 | segment = np.empty(head_length + end)
147 | segment[:head_length] = buffer_np[start:]
148 | segment[head_length:] = buffer_np[:end]
149 | return scale * segment
150 |
--------------------------------------------------------------------------------
/redpitaya/drv/osc_fil.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 |
4 | class osc_fil(object):
5 | # filter coeficients
6 | _filters = { 1.0: (0x7D93, 0x437C7, 0xd9999a, 0x2666),
7 | 20.0: (0x4C5F, 0x2F38B, 0xd9999a, 0x2666)}
8 |
9 | class _regset_t(Structure):
10 | _fields_ = [('cfg_dec', c_uint32), # decimation factor
11 | ('cfg_shr', c_uint32), # shift right
12 | ('cfg_avg', c_uint32), # average enable
13 | ('cfg_byp', c_uint32), # bypass
14 | ('cfg_faa', c_int32), # AA coeficient
15 | ('cfg_fbb', c_int32), # BB coeficient
16 | ('cfg_fkk', c_int32), # KK coeficient
17 | ('cfg_fpp', c_int32)] # PP coeficient
18 |
19 | def default(self):
20 | self.regset.fil.cfg_dec = 0
21 | self.regset.fil.cfg_shr = 0
22 | self.regset.fil.cfg_avg = 0
23 |
24 | def show_regset(self):
25 | """Print FPGA module register set for debugging purposes."""
26 | print(
27 | "cfg_dec = 0x{reg:08x} = {reg:10d} # decimation factor\n".format(reg=self.regset.fil.cfg_dec) +
28 | "cfg_shr = 0x{reg:08x} = {reg:10d} # shift right \n".format(reg=self.regset.fil.cfg_shr) +
29 | "cfg_avg = 0x{reg:08x} = {reg:10d} # average enable \n".format(reg=self.regset.fil.cfg_avg) +
30 | "cfg_byp = 0x{reg:08x} = {reg:10d} # bypass \n".format(reg=self.regset.fil.cfg_byp) +
31 | "cfg_faa = 0x{reg:08x} = {reg:10d} # AA coeficient \n".format(reg=self.regset.fil.cfg_faa) +
32 | "cfg_fbb = 0x{reg:08x} = {reg:10d} # BB coeficient \n".format(reg=self.regset.fil.cfg_fbb) +
33 | "cfg_fkk = 0x{reg:08x} = {reg:10d} # KK coeficient \n".format(reg=self.regset.fil.cfg_fkk) +
34 | "cfg_fpp = 0x{reg:08x} = {reg:10d} # PP coeficient \n".format(reg=self.regset.fil.cfg_fpp)
35 | )
36 |
37 | @property
38 | def decimation(self) -> int:
39 | """Decimation factor."""
40 | return (self.regset.fil.cfg_dec + 1)
41 |
42 | @decimation.setter
43 | def decimation(self, value: int):
44 | # TODO check range
45 | self.regset.fil.cfg_dec = value - 1
46 |
47 | @property
48 | def average(self) -> bool:
49 | return bool(self.regset.fil.cfg_avg)
50 |
51 | @average.setter
52 | def average(self, value: bool):
53 | # TODO check range, for non 2**n decimation factors,
54 | # scaling should be applied in addition to shift
55 | self.regset.fil.cfg_avg = int(value)
56 | self.regset.fil.cfg_shr = math.ceil(math.log2(self.decimation))
57 |
58 | @property
59 | def filter_bypass(self) -> bool:
60 | """Bypass digital input filter.
61 |
62 | True filter is not used
63 | False filter is used
64 | """
65 | return bool(self.regset.fil.cfg_byp)
66 |
67 | @filter_bypass.setter
68 | def filter_bypass(self, value: bool):
69 | self.regset.fil.cfg_byp = int(value)
70 |
71 | @property
72 | def filter_coeficients(self) -> tuple:
73 | return (self.regset.fil.cfg_faa,
74 | self.regset.fil.cfg_fbb,
75 | self.regset.fil.cfg_fkk,
76 | self.regset.fil.cfg_fpp)
77 |
78 | @filter_coeficients.setter
79 | def filter_coeficients(self, value: tuple):
80 | # TODO check range
81 | self.regset.fil.cfg_faa = value[0]
82 | self.regset.fil.cfg_fbb = value[1]
83 | self.regset.fil.cfg_fkk = value[2]
84 | self.regset.fil.cfg_fpp = value[3]
85 |
--------------------------------------------------------------------------------
/redpitaya/drv/osc_trg.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 |
4 | class osc_trg(object):
5 | # trigger edge dictionary
6 | _edges = {'pos': 0, 'neg': 1}
7 |
8 | class _regset_t(Structure):
9 | _fields_ = [('cfg_neg', c_int32), # negative level
10 | ('cfg_pos', c_int32), # positive level
11 | ('cfg_edg', c_uint32)] # edge (0-pos, 1-neg)
12 |
13 | def default(self):
14 | """Set registers into default (power-up) state."""
15 | self.regset.trg.cfg_neg = 0
16 | self.regset.trg.cfg_pos = 0
17 | self.regset.trg.cfg_edg = 0
18 |
19 | def show_regset(self):
20 | """Print FPGA module register set for debugging purposes."""
21 | print(
22 | "cfg_neg = 0x{reg:08x} = {reg:10d} # negative level \n".format(reg=self.regset.trg.cfg_neg) +
23 | "cfg_pos = 0x{reg:08x} = {reg:10d} # positive level \n".format(reg=self.regset.trg.cfg_pos) +
24 | "cfg_edg = 0x{reg:08x} = {reg:10d} # edge (0-pos, 1-neg)\n".format(reg=self.regset.trg.cfg_edg)
25 | )
26 |
27 | @property
28 | def level(self) -> float:
29 | """Trigger level in vols, or a pair of values [neg, pos] if a hysteresis is desired."""
30 | scale = self.input_range / self._DWr
31 | return [self.regset.trg.cfg_neg * scale, self.regset.trg.cfg_pos * scale]
32 |
33 | @level.setter
34 | def level(self, value: tuple):
35 | scale = self._DWr / self.input_range
36 | if isinstance(value, float):
37 | value = [value]*2
38 | if (-1.0 <= value[0] <= 1.0):
39 | self.regset.trg.cfg_neg = int(value[0] * scale)
40 | else:
41 | raise ValueError("Trigger negative level should be inside [{},{}]".format(self.input_range))
42 | if (-1.0 <= value[1] <= 1.0):
43 | self.regset.trg.cfg_pos = int(value[1] * scale)
44 | else:
45 | raise ValueError("Trigger positive level should be inside [{},{}]".format(self.input_range))
46 |
47 | @property
48 | def edge(self) -> str:
49 | """Trigger edge as a string 'pos'/'neg'"""
50 | return ('pos', 'neg')[self.regset.trg.cfg_edg]
51 |
52 | @edge.setter
53 | def edge(self, value: str):
54 | if (value in self._edges):
55 | self.regset.trg.cfg_edg = self._edges[value]
56 | else:
57 | raise ValueError("Trigger edge should be one of {}".format(list(self._edges.keys())))
58 |
--------------------------------------------------------------------------------
/redpitaya/drv/overlay.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 |
4 |
5 | class overlay(object):
6 | """Class handling device tree overlays and FPGA bitstreams."""
7 | overlays = "/sys/kernel/config/device-tree/overlays"
8 | fpgapath = "/opt/redpitaya/fpga"
9 | overlaysh = "/opt/redpitaya/sbin/overlay.sh"
10 |
11 | def __init__(self, overlay: str):
12 | if not isinstance(overlay, str):
13 | raise TypeError("Bitstream name has to be a string.")
14 |
15 | if os.path.isfile(self.overlaysh):
16 | self.overlay = overlay
17 | self.syspath = "{}/{}".format(self.overlays, self.overlay)
18 |
19 | if self.status():
20 | print('Check FPGA [OK].')
21 | return
22 |
23 | os.system("{} {}".format(self.overlaysh,overlay))
24 | # this delay makes sure all devices are created before continuing
25 | time.sleep(0.5)
26 | if self.status():
27 | print('Load overlay [OK].')
28 | else:
29 | print('Load overlay [FAIL].')
30 |
31 | def __del__(self):
32 | print('Overlay __del__ was activated.')
33 | print('But since there are garbage collection ordering issues, this code is commented out.')
34 | # os.system("rmdir {}".format(self.syspath))
35 | # del(self.syspath)
36 | # del(self.overlay)
37 |
38 | def status(self) -> bool:
39 | """Checking device tree overlay status.
40 |
41 | :returns: device tree overlay 'applied' status
42 | :rtype: bool
43 | """
44 | if not os.path.isfile('/tmp/loaded_fpga.inf'):
45 | return False
46 | else:
47 | with open('/tmp/loaded_fpga.inf', 'r') as status_file:
48 | status_string = status_file.read()
49 | if (status_string != self.overlay): return False
50 |
51 | if not os.path.isfile('{}/Full/status'.format(self.overlays)):
52 | return False
53 | else:
54 | with open('{}/Full/status'.format(self.overlays), 'r') as status_file:
55 | status_string = status_file.read()
56 | if (status_string == "applied\n"): return True
57 | else: return False
58 |
--------------------------------------------------------------------------------
/redpitaya/drv/pdm.py:
--------------------------------------------------------------------------------
1 | from ctypes import *
2 |
3 | from .uio import uio
4 |
5 |
6 | class pdm(uio):
7 |
8 | DN = 4
9 | DW = 8
10 | _DWr = 2**DW - 1
11 |
12 | class _regset_t(Structure):
13 | DN = 4 # TODO: the DN value from the 'pdm' class should be used
14 | _fields_ = [('pdm', c_uint32 * DN)]
15 |
16 | def __init__(self, uio: str = '/dev/uio/pdm'):
17 | super().__init__(uio)
18 | self.regset = self._regset_t.from_buffer(self.uio_mmaps[0])
19 |
20 | def __del__(self):
21 | super().__del__()
22 |
23 | def default(self):
24 | """Set registers into default (power-up) state."""
25 | for channel in range(self.DN):
26 | self.regset.pdm[channel] = 0
27 |
28 | def read(self, channel: int) -> int:
29 | return self.regset.pdm[channel]
30 |
31 | def write(self, channel: int, value: int):
32 | if (0 <= value <= self._DWr):
33 | self.regset.pdm[channel] = value
34 | else:
35 | raise ValueError("PDM output value should be in range [0,{}]".format(self._DWr))
36 |
--------------------------------------------------------------------------------
/redpitaya/drv/uio.py:
--------------------------------------------------------------------------------
1 | import os
2 | import fcntl
3 | import mmap
4 | import pyudev
5 | from ctypes import c_uint32
6 |
7 |
8 | class _uio_map(object):
9 | def __init__(self, device, index: int):
10 | self.index = index
11 | self.name = device.attributes.asstring('maps/map'+str(index)+'/name')
12 | self.addr = int(device.attributes.asstring('maps/map'+str(index)+'/addr'), 16)
13 | self.offset = int(device.attributes.asstring('maps/map'+str(index)+'/offset'), 16)
14 | self.size = int(device.attributes.asstring('maps/map'+str(index)+'/size'), 16)
15 |
16 |
17 | class uio(object):
18 | """UIO class provides user space access to UIO devices.
19 |
20 | When instantiating this class the next steps are performed:
21 |
22 | 1. The provided UIO device file is first opened.
23 | 2. An attempt is made to exclusively lock the device file.
24 | If another process has already locked this file
25 | an error will be rised. This prevents multiple
26 | applications from accessing the same HW module.
27 | 3. If locking is sucessfull sysfs arguments will be read
28 | to determine the maps listed in the device tree.
29 | All maps will be `mmap`ed into memory and provided
30 | as a tuple.
31 |
32 | When an instance of :class:`uio` is deleted the next steps are performed:
33 |
34 | 1. Close all memory mappings.
35 | 2. Close the UIO device file, which also releases the exclusive lock.
36 |
37 | Parameters
38 | ----------
39 | uio : :obj:`str`
40 | device node path
41 |
42 | Attributes
43 | ----------
44 | uio_maps : :obj:`touple` of :class:`mmap` objects
45 | List of all memory maps derived from device tree node for the UIO device.
46 | uio_mmaps : :obj:`touple` of :class:`mmap` objects
47 | List of all mmap-ed memory maps derived from device tree node for the UIO device.
48 | """
49 |
50 | def __init__(self, uio: str):
51 | # store UIO device node path
52 | self.uio_path = uio
53 |
54 | # open device file
55 | try:
56 | self.uio_dev = open(self.uio_path, 'r+b')
57 | except OSError as e:
58 | raise IOError(e.errno, "Opening {}: {}".format(self.uio_path, e.strerror))
59 |
60 | # exclusive lock
61 | try:
62 | fcntl.flock(self.uio_dev, fcntl.LOCK_EX | fcntl.LOCK_NB)
63 | except IOError as e:
64 | raise IOError(e.errno, "Locking {}: {}".format(self.uio_path, e.strerror))
65 |
66 | # UDEV device
67 | device = pyudev.Devices.from_device_file(pyudev.Context(), self.uio_path)
68 |
69 | # create list of UIO maps
70 | self.uio_maps = [_uio_map(device, int(uio_map[3:])) for uio_map in os.listdir(os.path.join(device.sys_path, 'maps'))]
71 |
72 | # mmap all maps listed in device tree
73 | self.uio_mmaps = [self._uio_mmap(uio_map) for uio_map in self.uio_maps]
74 |
75 | def _uio_mmap(self, uio_map: _uio_map):
76 | try:
77 | uio_mmap = mmap.mmap(fileno = self.uio_dev.fileno(),
78 | length = uio_map.size,
79 | offset = uio_map.index * mmap.PAGESIZE,
80 | flags = mmap.MAP_SHARED,
81 | prot = mmap.PROT_READ | mmap.PROT_WRITE)
82 | except OSError as e:
83 | raise IOError(e.errno, "Mapping {} map {} size {}: {}".format(self.uio_path, uio_map.name, uio_map.size, e.strerror))
84 | return uio_mmap
85 |
86 | def __del__(self):
87 | # print('UIO __del__ was activated.')
88 | # close memory mappings
89 | for uio_mmap in self.uio_mmaps:
90 | uio_mmap.close()
91 | # close uio device (also releases exclusive lock)
92 | try:
93 | self.uio_dev.close()
94 | except OSError as e:
95 | raise IOError(e.errno, "Closing {}: {}".format(self.uio_path, e.strerror))
96 |
97 | def irq_enable(self):
98 | """Enable interrupt."""
99 | cnt = c_uint32(1);
100 | try:
101 | self.uio_dev.write(bytearray(cnt))
102 | except OSError as e:
103 | raise IOError(e.errno, "Enable IRQ {}: {}".format(self.uio_path, e.strerror));
104 |
105 | def irq_disable(self):
106 | """Disable interrupt."""
107 | cnt = c_uint32(0);
108 | try:
109 | self.uio_dev.write(bytearray(cnt))
110 | except OSError as e:
111 | raise IOError(e.errno, "Disable IRQ {}: {}".format(self.uio_path, e.strerror));
112 |
113 | def irq_wait(self):
114 | """Wait for interrupt."""
115 | try:
116 | status = self.uio_dev.read(4)
117 | except OSError as e:
118 | raise IOError(e.errno, "Wait for IRQ {}: {}".format(self.uio_path, e.strerror));
119 | # import sys
120 | # cnt = int.from_bytes(status, byteorder=sys.byteorder)
121 |
122 | def pool(self):
123 | """TODO: implement interrupt support
124 | """
125 | pass
126 |
--------------------------------------------------------------------------------
/redpitaya/drv/wave.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from scipy import signal
3 |
4 |
5 | class wave():
6 | """Common waveform creation.
7 |
8 | This class provides methods for creating common waveform shapes.
9 | """
10 |
11 | def _wavetime(self):
12 | return np.linspace(0, 2*np.pi, self.buffer_size, endpoint=False)
13 |
14 | def sin(self, t: np.array = None) -> np.array:
15 | """Sinus waveform.
16 |
17 | Parameters
18 | ----------
19 | t : array_like, optional
20 | If not time array is provided, a default buffer sized array
21 | with a 2*PI period will be used.
22 |
23 | Returns
24 | -------
25 | waveform : ndarray
26 | Sinusoidal waveform with samples in the normalized range [-1,+1].
27 |
28 | References
29 | ----------
30 | https://docs.scipy.org/doc/numpy/reference/generated/numpy.sin.html
31 |
32 | See Also
33 | --------
34 | square
35 | sawtooth
36 | """
37 | if t is None:
38 | t = self._wavetime()
39 | return np.sin(t)
40 |
41 | def square(self, duty: float = 0.5, t: np.array = None) -> np.array:
42 | """Square waveform.
43 |
44 | Parameters
45 | ----------
46 | duty : float, optional
47 | Duty cycle.
48 | t : array_like, optional
49 | If not time array is provided, a default buffer sized array
50 | with a 2*PI period will be used.
51 |
52 | Returns
53 | -------
54 | waveform : ndarray
55 | Square waveform with samples in the normalized range [-1,+1]
56 | and given duty cycle.
57 |
58 | References
59 | ----------
60 | http://scipy.github.io/devdocs/generated/scipy.signal.square.html
61 |
62 | See Also
63 | --------
64 | sin
65 | sawtooth
66 | """
67 | if t is None:
68 | t = self._wavetime()
69 | return signal.square(t, duty)
70 |
71 | def sawtooth(self, width: float = 0.5, t: np.array = None) -> np.array:
72 | """Sawtooth waveform.
73 |
74 | Parameters
75 | ----------
76 | width : float, optional
77 | Width of rising versus the falling sawtooth edge.
78 | t : array_like, optional
79 | If not time array is provided, a default buffer sized array
80 | with a 2*PI period will be used.
81 |
82 | Returns
83 | -------
84 | waveform : ndarray
85 | Sawtooth waveform with samples in the normalized range [-1,+1]
86 | and given width.
87 |
88 | References
89 | ----------
90 | http://scipy.github.io/devdocs/generated/scipy.signal.square.html
91 |
92 | See Also
93 | --------
94 | sin
95 | square
96 | """
97 | if t is None:
98 | t = self._wavetime()
99 | return signal.sawtooth(t, width)
100 |
--------------------------------------------------------------------------------
/redpitaya/overlay/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ['mercury']
2 |
--------------------------------------------------------------------------------
/redpitaya/overlay/mercury.py:
--------------------------------------------------------------------------------
1 | from redpitaya.drv.overlay import overlay
2 |
3 | from periphery import LED
4 | from periphery import GPIO
5 |
6 | from redpitaya.drv.hwid import hwid
7 | from redpitaya.drv.mgmt import mgmt
8 | from redpitaya.drv.pdm import pdm
9 | from redpitaya.drv.clb import clb
10 | from redpitaya.drv.gen import gen
11 | from redpitaya.drv.osc import osc
12 | from redpitaya.drv.lg import lg
13 | from redpitaya.drv.la import la
14 |
15 | import iio
16 |
17 |
18 | class mercury(overlay):
19 |
20 | def __init__(self):
21 | super().__init__(overlay='mercury')
22 |
23 | def __del__(self):
24 | super().__del__()
25 |
26 | # module number constants
27 | _MNG = 2 # generators
28 | _MNO = 2 # oscilloscopes
29 |
30 | _modules = tuple(['gen'+str(ch) for ch in range(_MNG)] + ['osc'+str(ch) for ch in range(_MNO)] + ['lg', 'la'])
31 | # TODO: it is unclear why the next line fails
32 | # sync_src = {event_sources[i]: i for i in range(len(_modules))}
33 | # trig_src = {event_sources[i]: 1 << i for i in range(len(_modules))}
34 | sync_src = {'gen0': 0,
35 | 'gen1': 1,
36 | 'osc0': 2,
37 | 'osc1': 3,
38 | 'lg' : 4,
39 | 'la' : 5}
40 | trig_src = {'gen0': 1 << 0,
41 | 'gen1': 1 << 1,
42 | 'osc0': 1 << 2,
43 | 'osc1': 1 << 3,
44 | 'lg' : 1 << 4,
45 | 'la' : 1 << 5}
46 |
47 | class led(LED):
48 | leds = range(8)
49 |
50 | def __init__(self, index, brightness=None):
51 | if index not in self.leds:
52 | raise ValueError("LED index should be one of: {}".format(self.leds))
53 | else:
54 | super().__init__(name="led"+str(index), brightness=brightness)
55 |
56 | class gpio():
57 |
58 | def __new__(cls, port, pin, direction="preserve"):
59 | ports = {'p': 968, 'n': 976}
60 | gpios = range(8)
61 |
62 | if port not in ports:
63 | raise ValueError("GPIO port should be one of: {}".format(ports))
64 | if pin not in gpios:
65 | raise ValueError("GPIO pin should be one of: {}".format(gpios))
66 | else:
67 | return GPIO(ports[port] + pin,direction)
68 |
69 | class analog_in():
70 | channels = {0: 'voltage9', 1: 'voltage11', 2: 'voltage10', 3: 'voltage8'}
71 | ctx = iio.Context()
72 | dev = ctx.devices[1]
73 | # resistor divider
74 | resdiv = 4.99 / (30.0 + 4.99)
75 |
76 | def __init__(self, channel):
77 | if channel in range(4):
78 | channel = self.channels[channel]
79 | self.chn = self.dev.find_channel(channel)
80 | self.scale = self.chn.attrs['scale'].value
81 |
82 | def read(self):
83 | raw = self.chn.attrs['raw'].value
84 | return (int(raw)*float(self.scale)/1000 / self.resdiv)
85 |
86 | class hwid(hwid):
87 | pass
88 |
89 | class mgmt(mgmt):
90 | pass
91 |
92 | class analog_out(pdm):
93 | V = 1.8 # voltage
94 |
95 | def read(self, ch: int) -> float:
96 | return (super().read(ch) / super().DWr * self.V)
97 |
98 | def write(self, ch: int, value: float):
99 | if (0 <= value <= self.V):
100 | super().write(ch, int(value / self.V * super()._DWr))
101 | else:
102 | raise ValueError("Output amplitude should be inside [0,{}] volts.".format(self.V))
103 |
104 | class clb(clb):
105 | # TODO, add checks
106 | pass
107 |
108 | class gen(gen):
109 | def __init__(self, index: int):
110 | self.calib = clb()
111 | self.eeprom_user = self.calib.eeprom_read()
112 | self.calib_user = self.calib.eeprom_parse(self.eeprom_user)
113 | self.calib.calib_dac_apply(self.calib_user)
114 | del(self.calib)
115 | if index in range(mercury._MNG):
116 | super().__init__(index=index)
117 | self.sync_src = mercury.sync_src['gen'+str(index)]
118 | else:
119 | raise ValueError("Generator index should be one of {}".format(range(mercury._MNG)))
120 |
121 | class osc(osc):
122 | def __init__(self, index: int, input_range: float):
123 | self.calib = clb()
124 | self.eeprom_user = self.calib.eeprom_read()
125 | self.calib_user = self.calib.eeprom_parse(self.eeprom_user)
126 | self.calib.calib_adc_apply(self.calib_user,index,input_range)
127 | #self.calib.calib_show(self.calib_user)
128 | del(self.calib)
129 | if index in range(mercury._MNO):
130 | super().__init__(index=index, input_range=input_range)
131 | self.sync_src = mercury.sync_src['osc'+str(index)]
132 | self.trig_src = mercury.trig_src['osc'+str(index)]
133 | if (input_range == 1.0):
134 | fil_cof = self.calib_user.adc[index].lo
135 | self.filter_coeficients = (fil_cof.fil_aa,fil_cof.fil_bb,fil_cof.fil_kk,fil_cof.fil_pp)
136 | else:
137 | fil_cof = self.calib_user.adc[index].hi
138 | self.filter_coeficients = (fil_cof.fil_aa,fil_cof.fil_bb,fil_cof.fil_kk,fil_cof.fil_pp)
139 | # self.show_regset()
140 | else:
141 | raise ValueError("Oscilloscope index should be one of {}".format(range(mercury._MNO)))
142 |
143 | class lg(lg):
144 | def __init__(self):
145 | super().__init__()
146 | self.sync_src = mercury.sync_src['lg']
147 |
148 | class la(la):
149 | def __init__(self):
150 | super().__init__()
151 | self.sync_src = mercury.sync_src['la']
152 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | # Always prefer setuptools over distutils
2 | from setuptools import setup, find_packages
3 | # To use a consistent encoding
4 | from codecs import open
5 | from os import path
6 |
7 | here = path.abspath(path.dirname(__file__))
8 |
9 | # Get the long description from the README file
10 | with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
11 | long_description = f.read()
12 |
13 | setup(
14 | name='redpitaya',
15 |
16 | # Versions should comply with PEP440. For a discussion on single-sourcing
17 | # the version across setup.py and the project code, see
18 | # https://packaging.python.org/en/latest/single_source_version.html
19 | version='2.00',
20 |
21 | description='Red Pitaya Python drivers and Jupyter applications',
22 | long_description=long_description,
23 |
24 | # The project's main homepage.
25 | url='https://github.com/RedPitaya/RedPitaya',
26 |
27 | # Author details
28 | author='Red Pitaya',
29 | author_email='info@redpitaya.com',
30 |
31 | # Choose your license
32 | license='BSD',
33 |
34 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
35 | classifiers=[
36 | # 3 - Alpha
37 | # 4 - Beta
38 | # 5 - Production/Stable
39 | 'Development Status :: 5 - Stable',
40 |
41 | 'Intended Audience :: Developers',
42 | 'Topic :: Software Development :: Drivers',
43 |
44 | 'License :: OSI Approved :: MIT License',
45 |
46 | 'Programming Language :: Python :: 3.10',
47 | ],
48 |
49 | keywords='signal generation acquisition GPIO control',
50 | packages=['redpitaya'],
51 | install_requires=['numpy', 'scipy', 'bokeh', 'IPython', 'ipywidgets'],
52 | )
53 |
--------------------------------------------------------------------------------
/welcome.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "markdown",
5 | "id": "de4c4d1c-d010-4f1e-b32c-8fdc1f3da56d",
6 | "metadata": {
7 | "collapsed": true,
8 | "jupyter": {
9 | "outputs_hidden": true
10 | }
11 | },
12 | "source": [
13 | "## Welcome to the Red Pitaya JupyterLab tutorial\n",
14 | "\n",
15 | "JupyterLab is the latest web-based interactive development environment for notebooks, code, and data. Its flexible interface allows users to configure and arrange workflows in data science, scientific computing, computational journalism, and machine learning. A modular design invites extensions to expand and enrich functionality. Read more about [JupyterLab](https://jupyter.org/).\n",
16 | "\n",
17 | "JupyterLab is available on Red Pitaya with 2.00-23 OS version or higher.\n",
18 | "\n",
19 | "With the upgrade from Jupyter Notebook to JupyterLab, we at Red Pitaya also made a big change: No more obscure documentation and spending hours searching for resources - from now on, JupyterLab uses the Python API commands. Since we now have *One OS to rule all Red Pitaya boards*, the decision has fallen to use the same commands that control your Red Pitaya board across all platforms. \n",
20 | "SCPI commands, once received by the Red Pitaya, are interpreted, and an appropriate C API function is executed. Python API commands, and by extension JupyterLab commands, are also just a mask for C API functions. This means the following:\n",
21 | "- All commands across all platforms are the same\n",
22 | "- The functionality of C API commands is expanded to all other programming languages and platforms.\n",
23 | "\n",
24 | "Enough of the chit-chat! Let's go straight to the fun part!\n",
25 | "\n",
26 | "In case you are new to Python, here is the [Official Python 3 tutorial](https://docs.python.org/3/tutorial/index.html).\n",
27 | "You also can check out the [Whirlwind Python tutorial by Jake Vanderplas on GitHub](https://github.com/jakevdp/WhirlwindTourOfPython), but please note that the Python syntax is outdated.\n",
28 | "\n",
29 | "To execute a cell in JupyterLab, click on it to change focus, and press the run button (⏵) above or press the key combination `Shift+Enter`.\n",
30 | "\n",
31 | "### Note \n",
32 | "We do not recommend running more than 10 JupyterLab kernels simultaneously, as the board can run out of memory and force the shutdown of the JupyterLab application.\n",
33 | "Red Pitaya remembers which Notebooks were opened the last time JupyterLab was used, so exiting the application without closing most of the Notebooks can lead to very long JupyterLab loading times. Therefore, it is inadvisable to exit JupyterLab with more than 5 tabs (Notebooks) open.\n",
34 | "\n"
35 | ]
36 | },
37 | {
38 | "cell_type": "markdown",
39 | "id": "9d0a837a-18e9-4ddd-89af-1be4b46d2160",
40 | "metadata": {},
41 | "source": [
42 | "### Jupyter API Examples:\n",
43 | "\n",
44 | "1. **Digital:**\n",
45 | " 1. [LED Blink](examples/digital/led.ipynb)\n",
46 | " 2. [Control GPIOs](examples/digital/gpio.ipynb)\n",
47 | "2. **Analog:**\n",
48 | " 1. [Read slow analog I/Os](examples/analog/analog_input.ipynb)\n",
49 | " 2. [Set slow analog I/Os](examples/analog/analog_output.ipynb)\n",
50 | "3. **Generating signals at RF outputs:**\n",
51 | " 1. [Generate continuous signal](examples/generation/gen_continuous_signal.ipynb)\n",
52 | " 2. [Generate signal pulses](examples/generation/gen_bursts.ipynb)\n",
53 | " 3. [Generate a signal on external trigger](examples/generation/gen_ext_trigger.ipynb)\n",
54 | " 4. [Custom waveform signal generation](examples/generation/gen_arbitrary_signal.ipynb)\n",
55 | " 5. [Generate two synchronous signals](examples/generation/gen_sync_two_channel.ipynb)\n",
56 | " 6. [Generate two burst asynced signals](examples/generation/gen_burst_async_signals.ipynb)\n",
57 | "4. **Acquiring signals at RF inputs:**\n",
58 | " 1. [Triggering with a threshold on channel](examples/acquisition/acq_trigger_level.ipynb)\n",
59 | " 2. [Instant signal acquisition](examples/acquisition/acq_instant.ipynb)\n",
60 | " 3. [Triggering on external trigger](examples/acquisition/acq_ext_trig.ipynb)\n",
61 | "5. **Generating and Acquiring signals at RF inputs/outputs:**\n",
62 | " 1. [Synchronised one-pulse signal generation and acquisition](examples/acquisition_generation/acq_gen_synced_pulse.ipynb)\n",
63 | "6. **Multi-board signal acquisition and generation:**\n",
64 | " 1. [Daisy chain generation and acquisition](examples/multiboard_sync/daisy_chain_1.ipynb)\n",
65 | " 2. [Synchronised Click Shield generation and acquisition](examples/multiboard_sync/click_shield_1.ipynb)\n",
66 | "7. **Deep Memory Acquisition:**\n",
67 | " 1. [Deep Memory Acquisition](examples/dma/dma.ipynb)\n",
68 | "8. **Digital communication interfaces (Under construction):**\n",
69 | " 1. *I2C:*\n",
70 | "\n",
71 | " 2. *SPI:*\n",
72 | "\n",
73 | " 3. *UART:*\n",
74 | "\n",
75 | "### System Tools:\n",
76 | "1. [Hardware ID](examples/hardware/hwid.ipynb)\n",
77 | "2. [Calibration](examples/hardware/calibration.ipynb)\n",
78 | "\n",
79 | "### Click Shield Examples\n",
80 | "1. [Click Board Examples](examples/click_shield_examples/click_board_examples/click_board_examples.ipynb)\n",
81 | "\n",
82 | "\n",
83 | "## Outdated\n",
84 | "The code here is outdated and must be updated to work with the Red Pitaya JupyterLab. The examples here will be brought up-to-date in the future.\n",
85 | "\n",
86 | "1. **Sensor:**\n",
87 | " 1. [Home heating automation](examples/outdated/home_automation.ipynb)\n",
88 | " 2. [Temperature sensor (GROVE sensors)](examples/outdated/exam_temp.ipynb)\n",
89 | "2. **Other:**\n",
90 | " 1. [Cable Length measurement using TDR](examples/outdated/cable_length.ipynb)"
91 | ]
92 | }
93 | ],
94 | "metadata": {
95 | "kernelspec": {
96 | "display_name": "Python 3 (ipykernel)",
97 | "language": "python",
98 | "name": "python3"
99 | },
100 | "language_info": {
101 | "codemirror_mode": {
102 | "name": "ipython",
103 | "version": 3
104 | },
105 | "file_extension": ".py",
106 | "mimetype": "text/x-python",
107 | "name": "python",
108 | "nbconvert_exporter": "python",
109 | "pygments_lexer": "ipython3",
110 | "version": "3.10.12"
111 | }
112 | },
113 | "nbformat": 4,
114 | "nbformat_minor": 5
115 | }
116 |
--------------------------------------------------------------------------------