From 8d735a0b94e977cbcc77ae8060c0bda7a7c726f8 Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Thu, 3 Apr 2025 18:03:07 -0400 Subject: [PATCH 01/11] semi-implemented modified continued fraction alg, debugging currently, saving progress --- dds-sweeper/dds-sweeper.c | 258 ++++++++++++++++++++++++++++++++++---- 1 file changed, 234 insertions(+), 24 deletions(-) diff --git a/dds-sweeper/dds-sweeper.c b/dds-sweeper/dds-sweeper.c index 3cb50c3..1100c97 100644 --- a/dds-sweeper/dds-sweeper.c +++ b/dds-sweeper/dds-sweeper.c @@ -21,6 +21,7 @@ */ #include +#include #include "fast_serial.h" @@ -34,7 +35,6 @@ #include "pico/multicore.h" #include "pico/stdlib.h" #include "trigger_timer.pio.h" - #define VERSION "0.2.1" // Mutex for status @@ -70,7 +70,7 @@ int clk_mode = INTERNAL; // PIO VALUES IT IS LOOKING FOR #define UPDATE 0 -#define MAX_SIZE 245760 +#define MAX_SIZE 245760 // 240 * 1024 #define TIMERS 5000 #define TIMING_OFFSET (MAX_SIZE - TIMERS * 4) @@ -104,6 +104,10 @@ uint stop_ins = 0; // stop/repeat being unset denoted by 0 // order is single step, amp, freq, phase, amp2, freq2, phase2 uint BYTES_PER_INS[] = {8, 7, 13, 7, 13, 17, 13}; +// instruction sizes after backend processing +// order is single step, amp, freq, phase, amp2, freq2, phase2 +uint SIZE_EACH_INS[] = {14, 28, 29, 27, 36, 36, 36}; + // ============================================================================= // Utility Functions // ============================================================================= @@ -207,6 +211,119 @@ void abort_run() { } } +double approx_double_32(double f, uint32_t * numerator, uint * denominator, uint32_t p_max, uint32_t q_max) { + // Approximates a double as a ratio of integers + // using a modified continued fractions algorithm + // input = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult)^2 * 4294967296; + + double eps = 0.00001; // later + + uint32_t a0 = floor(f); + uint32_t r_old = f - a0; + uint32_t q_double_old = 0; + uint32_t p_double_old = 1; + uint32_t p_old = a0; + uint32_t q_old = 1; + + uint32_t a_new, p_new, q_new; + double r_new; + + uint num_iters = 100; + for (uint i = 1; i < num_iters; i++) { + if (fabs(f - ((double)p_old / (double)q_old)) < eps) { + if (DEBUG) { + fast_serial_printf("Ratio close to double within eps %d\n", eps); + } + break; + } + + if (r_old != 0) { + a_new = floor(1/r_old); + } else { + fast_serial_printf("Error: Division by zero encountered in approx_double.\n"); + break; + } + p_new = a_new * p_old + p_double_old; + q_new = a_new * q_old + q_double_old; + + if (p_new > p_max || q_new > q_max){ + if (DEBUG) { + fast_serial_printf("Either delta or rate out of bounds\n"); + } + break; + } + + r_old = 1/r_old - a_new; + + // update all vars + p_double_old = p_old; + p_old = p_new; + q_double_old = q_old; + q_old = q_new; + + } + *numerator = p_old; + *((uint8_t *)denominator) = q_old; + return (double)p_old / (double)q_old; +} + +double approx_double_16(double f, uint16_t * numerator, uint * denominator, uint16_t p_max, uint16_t q_max) { + // Approximates a double as a ratio of integers + // using a modified continued fractions algorithm + + double eps = 0.00001; // later + + uint16_t a0 = floor(f); + uint16_t r_old = f - a0; + uint16_t q_double_old = 0; + uint16_t p_double_old = 1; + uint16_t p_old = a0; + uint16_t q_old = 1; + + uint16_t a_new, p_new, q_new; + double r_new; + + uint num_iters = 100; + for (uint i = 1; i < num_iters; i++) { + if (abs(f - ((double)p_old / (double)q_old)) < eps) { + if (DEBUG) { + fast_serial_printf("Ratio close to double within eps %lf in %u iters\n", eps, i); + } + break; + } + + if (r_old != 0) { + a_new = floor(1/r_old); + } else { + fast_serial_printf("Error: Division by zero encountered in approx_double.\n"); + break; + } + p_new = a_new * p_old + p_double_old; + q_new = a_new * q_old + q_double_old; + + if (p_new > p_max || q_new > q_max){ + if (DEBUG) { + fast_serial_printf("Either delta or rate out of bounds\n"); + } + break; + } + + r_old = 1/r_old - a_new; + + // update all vars + p_double_old = p_old; + p_old = p_new; + q_double_old = q_old; + q_old = q_new; + + } + *numerator = p_old; + // *((uint8_t *)denominator) = q_old; + *denominator = q_old; + return (double)p_old / (double)q_old; + +} + // ============================================================================= // Set Table Instructions // ============================================================================= @@ -483,6 +600,9 @@ void parse_amp_sweep_ins(uint addr, uint channel, uint32_t ftw; uint rate = 1; + uint32_t delta_max = 1023; + uint32_t rate_max = 255; + if (ad9959.sweep_type == AMP2_MODE) { // Convert others into integer values get_ftw(&ad9959, freq, &ftw); @@ -493,28 +613,23 @@ void parse_amp_sweep_ins(uint addr, uint channel, start = get_asf(start, &asf_start); end = get_asf(end, &asf_end); - delta = round(sweep_rate * 1024); - - if (delta < 1) { - if (asf_end > asf_start) { - // If rising, we can use rate to divide down - rate = 255; - delta = round(sweep_rate * 1024 / 255); - if (delta < 1) { - delta = 1; - } - } else { - delta = 1; - } - } else if (delta > 1023) { - delta = 1023; + if (start < end) { + input = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult) * 1024; + sweep_rate = approx_double_16(sweep_rate, &delta, &rate, delta_max, rate_max); + } else { + sweep_rate = get_asf(sweep_rate, &delta); + } + if (delta == 0) { + // enforce minimum sweep rate to not be zero + delta = 1; + sweep_rate = delta / 1023.0; } if (DEBUG) { fast_serial_printf( - "Set ins #%d for channel %d from %3lf%% to %3lf%% with delta %3lf%% " - "and rate of %d\n", - addr, channel, start / 10.23, end / 10.23, delta / 10.23, rate); + "Set ins #%d for channel %d from %3lf%% to %3lf%% with sweep delta %3lf%% " + "and rate of %u\n", + addr, channel, start, end, sweep_rate, rate); } set_amp_sweep_ins(addr, channel, asf_start, asf_end, delta, rate, ftw, pow); @@ -615,6 +730,8 @@ void parse_freq_sweep_ins(uint addr, uint channel, uint32_t ftw_start, ftw_end, delta; uint rate = 1; + uint32_t delta_max = 4294967296 - 1; + uint32_t rate_max = 255; if (ad9959.sweep_type == FREQ2_MODE) { // Convert others into integer values get_asf(amp, &asf); @@ -624,7 +741,16 @@ void parse_freq_sweep_ins(uint addr, uint channel, // Convert percentages to integers, check values in range start = get_ftw(&ad9959, start, &ftw_start); end = get_ftw(&ad9959, end, &ftw_end); - sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); + + if (start < end) { + double bits_per_sync_clk_cycle = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult)^2 * 4294967296; + + sweep_rate = approx_double_32(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); + // sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); + } else { + // here your delta is just sweep_rate / 1 + sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); + } if (DEBUG) { fast_serial_printf( @@ -736,6 +862,9 @@ void parse_phase_sweep_ins(uint addr, uint channel, uint32_t ftw; uint rate = 1; + uint16_t delta_max = 16384; + uint16_t rate_max = 255; + if (ad9959.sweep_type == PHASE2_MODE) { // Convert others into integer values get_ftw(&ad9959, freq, &ftw); @@ -745,7 +874,12 @@ void parse_phase_sweep_ins(uint addr, uint channel, // Convert from degrees to tuning words start = get_pow(start, &pow_start); end = get_pow(end, &pow_end); - sweep_rate = get_pow(sweep_rate, &delta); + + if (start < end) { + sweep_rate = approx_double_16(sweep_rate, &delta, &rate, delta_max, rate_max); + } else { + sweep_rate = get_pow(sweep_rate, &delta); + } if (DEBUG) { fast_serial_printf( @@ -758,6 +892,67 @@ void parse_phase_sweep_ins(uint addr, uint channel, set_phase_sweep_ins(addr, channel, pow_start, pow_end, delta, rate, ftw, asf); } +// void get_continued_fraction(double number, uint32_t *frac_list, uint num_terms) { + +// // Represent a double as a continued fraction +// // Avoids dynamic allocation and lack of array return types by editing a +// // pre-allocated frac_list +// uint32_t a = floor(number); +// frac_list[0] = a; + +// for (uint i = 0; i < num_terms; i++) { +// number = number - frac_list[i]; + +// // Check if number is zero within some tolerance +// // May need to define somewhere else +// if (number < 0.00001){ +// break; +// } + +// number = 1 / number; +// frac_list[i+1] = floor(number); +// } +// } + +// void continued_fraction_as_ratio(uint32_t *frac_list, uint num_terms, uint32_t *numerator, uint32_t *denominator) { + +// // Algorithm to extract the numerator and denominator that estimate the decimal +// // Its other related function may need to be combined + +// if (num_terms == 0) { +// // Divide by zero error? +// *numerator = 0; +// *denominator = 0; +// } else if (num_terms == 1) { +// // If only one term, the fraction is just that term over 1 +// *numerator = frac_list[0]; +// *denominator = 1; // this is fudged +// } else { +// uint32_t p0 = frac_list[0], q0 = 1; +// uint32_t p1 = frac_list[1] * frac_list[0] + 1, q1 = frac_list[1]; +// uint32_t p, q; + +// for (uint k = 3; k < num_terms + 1; k++) { +// p = frac_list[k - 1] * p1 + p0; +// q = frac_list[k - 1] * q1 + q0; +// p0 = p1; +// p1 = p; +// q0 = q1; +// q1 = q; +// } + +// // Assign p to numerator and q to denominator +// // Restrict denominator to be less than 256 +// if (q1 > 256){ +// *numerator = p0; +// *denominator = q0; +// } else { +// *numerator = p1; +// *denominator = q1; +// } +// } +// } + void get_memory_layout(uint sweep_mode) { fast_serial_printf("%d active channels\n", ad9959.channels); @@ -970,6 +1165,22 @@ void loop() { OK(); } else if (strncmp(readstring, "getmode", 7) == 0) { get_memory_layout(ad9959.sweep_type); + // } else if (strncmp(readstring, "getfrac", 7) == 0) { + + // uint num_terms = 4; + // uint16_t frac_container[num_terms]; + // uint16_t some_numerator, some_denominator; + // get_continued_fraction(2.3184, frac_container, num_terms); + // fast_serial_printf("["); + + // for (uint i=0; i < num_terms; i++){ + // fast_serial_printf("%u,", frac_container[i]); + // } + // fast_serial_printf("]\n"); + + // continued_fraction_as_ratio(frac_container, num_terms, &some_numerator, &some_denominator); + // fast_serial_printf("Got %u and %u\n", some_numerator, some_denominator); + } else if (strncmp(readstring, "setchannels", 11) == 0) { uint channels; @@ -1117,8 +1328,7 @@ void loop() { } else if (type > PHASE2_MODE) { fast_serial_printf("Invalid Type - table type must be in range 0-6\n"); } else { - uint8_t sizes[] = {14, 28, 29, 27, 36, 36, 36}; - INS_SIZE = sizes[type]; + INS_SIZE = SIZE_EACH_INS[type]; ad9959.sweep_type = type; timing = _timing; From a8048014c30b13d7a330bdf61ac6d9b9efc682f9 Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Thu, 3 Apr 2025 18:03:40 -0400 Subject: [PATCH 02/11] potentially useful, unsure if it should make it to main --- testing/continued-fractions.ipynb | 112 ++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 testing/continued-fractions.ipynb diff --git a/testing/continued-fractions.ipynb b/testing/continued-fractions.ipynb new file mode 100644 index 0000000..98d0df5 --- /dev/null +++ b/testing/continued-fractions.ipynb @@ -0,0 +1,112 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import math\n", + "math.floor(1/0.016)\n", + "# ## python way\n", + "# def get_continued_fraction(number, num_terms = 3):\n", + "# frac_list = [math.floor(number)]\n", + "# for k in range(num_terms):\n", + "# f = number - frac_list[k]\n", + "# print(f)\n", + "# number = 1/f\n", + "# print(number)\n", + "# frac_list.append(math.floor(number))\n", + "# return(frac_list)\n", + "\n", + "## c like way\n", + "num_terms = 4\n", + "frac_list = [None]*num_terms\n", + "\n", + "def get_continued_fraction_C(number, num_terms=3):\n", + "\n", + " frac_list[0] = math.floor(number)\n", + " for i in range(num_terms):\n", + " diff = number - frac_list[i]\n", + " \n", + " number = 1/diff\n", + " frac_list[i + 1] = math.floor(number)\n", + " \n", + " print(f\"Now frac_list is {frac_list}\")\n", + "\n", + "# print(get_continued_fraction(number = 2.3184))\n", + "\n", + "print(get_continued_fraction_C(number = 2.3184))\n", + "\n", + "def list_to_frac(inputlist):\n", + " n = len(inputlist)\n", + " if n==0:\n", + " return(0, 0)\n", + " elif n==1:\n", + " return(inputlist[0], 0)\n", + " else:\n", + " p0 = inputlist[0]\n", + " q0 = 1\n", + " p1 = inputlist[1] * inputlist[0] + 1\n", + " q1 = inputlist[1]\n", + " for k in range(3, n + 1):\n", + " p = inputlist[k - 1] * p1 + p0\n", + " q = inputlist[k - 1] * q1 + q0\n", + " p0 = p1\n", + " p1 = p\n", + " q0 = q1\n", + " q1 = q\n", + " return(p1, q1, p0, q0)\n", + "print(list_to_frac([2, 3, 1, 4]))\n", + "print(list_to_frac([2, 3, 7, 9]))\n", + "\n", + "def approx_double(f, p_max, q_max, num_iters = 6):\n", + " eps = 0.001\n", + "\n", + " a0 = math.floor(f)\n", + " r_old = f - a0\n", + " q_double_old = 0\n", + " p_double_old = 1\n", + " p_old = a0\n", + " q_old = 1\n", + "\n", + " a_new, p_new, q_new = None, None, None\n", + " r_new = None, None\n", + "\n", + " for i in range(1, num_iters):\n", + " print(i)\n", + " check = f - (p_old / q_old)\n", + " if (abs(check) < eps):\n", + " print('number close within eps')\n", + " break\n", + "\n", + " a_new = math.floor(1/r_old)\n", + " p_new = a_new * p_old + p_double_old\n", + " q_new = a_new * q_old + q_double_old\n", + "\n", + " if (p_new > p_max or q_new > q_max):\n", + " print('either num or denom too big')\n", + " break\n", + " r_old = 1/r_old - a_new\n", + "\n", + " p_double_old = p_old\n", + " p_old = p_new\n", + " q_double_old = q_old\n", + " q_old = q_new\n", + "\n", + " return(p_old, q_old, i)\n", + "\n", + "x = approx_double(2.314075007934069, 2**32 - 1, 256, num_iters=100)\n", + "print(x)\n", + "print(x[0] / x[1])" + ] + } + ], + "metadata": { + "language_info": { + "name": "python" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} From 3d5e2a8ba93c61df4af18310a39d24fdaf8af921 Mon Sep 17 00:00:00 2001 From: Json-To-String Date: Fri, 4 Apr 2025 00:38:50 -0400 Subject: [PATCH 03/11] adding the scaling factors before I forget them, will test tomorrow --- dds-sweeper/dds-sweeper.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/dds-sweeper/dds-sweeper.c b/dds-sweeper/dds-sweeper.c index 1100c97..f903757 100644 --- a/dds-sweeper/dds-sweeper.c +++ b/dds-sweeper/dds-sweeper.c @@ -219,7 +219,7 @@ double approx_double_32(double f, uint32_t * numerator, uint * denominator, uint double eps = 0.00001; // later uint32_t a0 = floor(f); - uint32_t r_old = f - a0; + double r_old = f - a0; uint32_t q_double_old = 0; uint32_t p_double_old = 1; uint32_t p_old = a0; @@ -240,7 +240,7 @@ double approx_double_32(double f, uint32_t * numerator, uint * denominator, uint if (r_old != 0) { a_new = floor(1/r_old); } else { - fast_serial_printf("Error: Division by zero encountered in approx_double.\n"); + fast_serial_printf("Error: Division by zero.\n"); break; } p_new = a_new * p_old + p_double_old; @@ -263,7 +263,7 @@ double approx_double_32(double f, uint32_t * numerator, uint * denominator, uint } *numerator = p_old; - *((uint8_t *)denominator) = q_old; + *denominator) = q_old; return (double)p_old / (double)q_old; } @@ -274,7 +274,7 @@ double approx_double_16(double f, uint16_t * numerator, uint * denominator, uint double eps = 0.00001; // later uint16_t a0 = floor(f); - uint16_t r_old = f - a0; + double r_old = f - a0; uint16_t q_double_old = 0; uint16_t p_double_old = 1; uint16_t p_old = a0; @@ -285,7 +285,7 @@ double approx_double_16(double f, uint16_t * numerator, uint * denominator, uint uint num_iters = 100; for (uint i = 1; i < num_iters; i++) { - if (abs(f - ((double)p_old / (double)q_old)) < eps) { + if (fabs(f - ((double)p_old / (double)q_old)) < eps) { if (DEBUG) { fast_serial_printf("Ratio close to double within eps %lf in %u iters\n", eps, i); } @@ -318,7 +318,6 @@ double approx_double_16(double f, uint16_t * numerator, uint * denominator, uint } *numerator = p_old; - // *((uint8_t *)denominator) = q_old; *denominator = q_old; return (double)p_old / (double)q_old; @@ -614,8 +613,12 @@ void parse_amp_sweep_ins(uint addr, uint channel, end = get_asf(end, &asf_end); if (start < end) { - input = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult) * 1024; - sweep_rate = approx_double_16(sweep_rate, &delta, &rate, delta_max, rate_max); + bits_per_sync_clk_cycle = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult) * 1024; + sweep_rate = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); + + // reversing scaling to see what sweep rate was actually set + sweep_rate = sweep_rate * (ad9959->ref_clk * ad9959->pll_mult) / (4 * 1024); + } else { sweep_rate = get_asf(sweep_rate, &delta); } @@ -744,9 +747,9 @@ void parse_freq_sweep_ins(uint addr, uint channel, if (start < end) { double bits_per_sync_clk_cycle = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult)^2 * 4294967296; - sweep_rate = approx_double_32(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); - // sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); + sweep_rate = sweep_rate * (ad9959.ref_clk * ad9959.pll_mult) / (4 * 4294967296); + } else { // here your delta is just sweep_rate / 1 sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); @@ -876,7 +879,10 @@ void parse_phase_sweep_ins(uint addr, uint channel, end = get_pow(end, &pow_end); if (start < end) { - sweep_rate = approx_double_16(sweep_rate, &delta, &rate, delta_max, rate_max); + double bits_per_sync_clk_cycle = sweep_rate * 4 / (ad9959.ref_clk * ad9959.pll_mult) * 16384; + sweep_rate = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); + sweep_rate = sweep_rate * (ad9959.ref_clk * ad9959.pll_mult) / (4 * 16384); + } else { sweep_rate = get_pow(sweep_rate, &delta); } From 44d1e8fbefc8e69c420d90e85f00caa659ece288 Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Fri, 4 Apr 2025 16:14:28 -0400 Subject: [PATCH 04/11] upwards sweeps calculate correctly, but are now in different units than the downwards, need to fix --- dds-sweeper/ad9959.c | 114 +++++++++++++++++ dds-sweeper/ad9959.h | 4 + dds-sweeper/dds-sweeper.c | 254 +++++++------------------------------- 3 files changed, 160 insertions(+), 212 deletions(-) diff --git a/dds-sweeper/ad9959.c b/dds-sweeper/ad9959.c index 3248a7e..8855091 100644 --- a/dds-sweeper/ad9959.c +++ b/dds-sweeper/ad9959.c @@ -167,3 +167,117 @@ void clear() { spi_write_blocking(SPI, clear, sizeof clear); } + +// ============================================================================= +// Sweep rate algorithms +// ============================================================================= + +double approx_double_32(double f, uint32_t * numerator, uint * denominator, uint32_t p_max, uint32_t q_max) { + // Approximates a double as a ratio of integers + // using a modified continued fractions algorithm + + double eps = 0.000000001; // later + + uint32_t a0 = floor(f); + double r_old = f - a0; + uint32_t q_double_old = 0; + uint32_t p_double_old = 1; + uint32_t p_old = a0; + uint32_t q_old = 1; + + uint32_t a_new, p_new, q_new; + double r_new; + + if (p_old == 0) { + // Returns slowest possible ramp rate + *numerator = 1; + *denominator = 255; + return 1.0/255.0; + } + + uint num_iters = 100; + for (uint i = 1; i < num_iters; i++) { + + if (fabs(f - ((double)p_old / (double)q_old)) < eps) { + // Ratio close to double within eps + break; + } + + a_new = floor(1/r_old); + p_new = a_new * p_old + p_double_old; + q_new = a_new * q_old + q_double_old; + + if (p_new > p_max || q_new > q_max){ + // Either delta or rate out of bounds + break; + } + + r_old = 1/r_old - a_new; + + // update all vars + p_double_old = p_old; + p_old = p_new; + q_double_old = q_old; + q_old = q_new; + + } + + *numerator = p_old; + *denominator = q_old; + return (double)p_old / (double)q_old; +} + +double approx_double_16(double f, uint16_t * numerator, uint * denominator, uint16_t p_max, uint16_t q_max) { + // Approximates a double as a ratio of integers + // using a modified continued fractions algorithm + + double eps = 0.000000001; // later + + uint16_t a0 = floor(f); + double r_old = f - a0; + uint16_t q_double_old = 0; + uint16_t p_double_old = 1; + uint16_t p_old = a0; + uint16_t q_old = 1; + + uint16_t a_new, p_new, q_new; + double r_new; + + if (p_old == 0) { + // Returns slowest possible ramp rate + *numerator = 1; + *denominator = 255; + return 1.0/255.0; + } + + uint num_iters = 100; + for (uint i = 1; i < num_iters; i++) { + if (fabs(f - ((double)p_old / (double)q_old)) < eps) { + // Ratio close to double within eps + break; + } + + a_new = floor(1/r_old); + p_new = a_new * p_old + p_double_old; + q_new = a_new * q_old + q_double_old; + + if (p_new > p_max || q_new > q_max){ + // Either delta or rate out of bounds + break; + } + + r_old = 1/r_old - a_new; + + // update all vars + p_double_old = p_old; + p_old = p_new; + q_double_old = q_old; + q_old = q_new; + + } + + *numerator = p_old; + *denominator = q_old; + return (double)p_old / (double)q_old; + +} \ No newline at end of file diff --git a/dds-sweeper/ad9959.h b/dds-sweeper/ad9959.h index 3f70500..775f2b5 100644 --- a/dds-sweeper/ad9959.h +++ b/dds-sweeper/ad9959.h @@ -113,4 +113,8 @@ void set_ref_clk(ad9959_config* c, uint64_t freq); void single_step_mode(); void clear(); +// Sweep rate algorithm +double approx_double_32(double f, uint32_t * numerator, uint * denominator, uint32_t p_max, uint32_t q_max); +double approx_double_16(double f, uint16_t * numerator, uint * denominator, uint16_t p_max, uint16_t q_max); + #endif diff --git a/dds-sweeper/dds-sweeper.c b/dds-sweeper/dds-sweeper.c index f903757..622b717 100644 --- a/dds-sweeper/dds-sweeper.c +++ b/dds-sweeper/dds-sweeper.c @@ -211,118 +211,6 @@ void abort_run() { } } -double approx_double_32(double f, uint32_t * numerator, uint * denominator, uint32_t p_max, uint32_t q_max) { - // Approximates a double as a ratio of integers - // using a modified continued fractions algorithm - // input = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult)^2 * 4294967296; - - double eps = 0.00001; // later - - uint32_t a0 = floor(f); - double r_old = f - a0; - uint32_t q_double_old = 0; - uint32_t p_double_old = 1; - uint32_t p_old = a0; - uint32_t q_old = 1; - - uint32_t a_new, p_new, q_new; - double r_new; - - uint num_iters = 100; - for (uint i = 1; i < num_iters; i++) { - if (fabs(f - ((double)p_old / (double)q_old)) < eps) { - if (DEBUG) { - fast_serial_printf("Ratio close to double within eps %d\n", eps); - } - break; - } - - if (r_old != 0) { - a_new = floor(1/r_old); - } else { - fast_serial_printf("Error: Division by zero.\n"); - break; - } - p_new = a_new * p_old + p_double_old; - q_new = a_new * q_old + q_double_old; - - if (p_new > p_max || q_new > q_max){ - if (DEBUG) { - fast_serial_printf("Either delta or rate out of bounds\n"); - } - break; - } - - r_old = 1/r_old - a_new; - - // update all vars - p_double_old = p_old; - p_old = p_new; - q_double_old = q_old; - q_old = q_new; - - } - *numerator = p_old; - *denominator) = q_old; - return (double)p_old / (double)q_old; -} - -double approx_double_16(double f, uint16_t * numerator, uint * denominator, uint16_t p_max, uint16_t q_max) { - // Approximates a double as a ratio of integers - // using a modified continued fractions algorithm - - double eps = 0.00001; // later - - uint16_t a0 = floor(f); - double r_old = f - a0; - uint16_t q_double_old = 0; - uint16_t p_double_old = 1; - uint16_t p_old = a0; - uint16_t q_old = 1; - - uint16_t a_new, p_new, q_new; - double r_new; - - uint num_iters = 100; - for (uint i = 1; i < num_iters; i++) { - if (fabs(f - ((double)p_old / (double)q_old)) < eps) { - if (DEBUG) { - fast_serial_printf("Ratio close to double within eps %lf in %u iters\n", eps, i); - } - break; - } - - if (r_old != 0) { - a_new = floor(1/r_old); - } else { - fast_serial_printf("Error: Division by zero encountered in approx_double.\n"); - break; - } - p_new = a_new * p_old + p_double_old; - q_new = a_new * q_old + q_double_old; - - if (p_new > p_max || q_new > q_max){ - if (DEBUG) { - fast_serial_printf("Either delta or rate out of bounds\n"); - } - break; - } - - r_old = 1/r_old - a_new; - - // update all vars - p_double_old = p_old; - p_old = p_new; - q_double_old = q_old; - q_old = q_new; - - } - *numerator = p_old; - *denominator = q_old; - return (double)p_old / (double)q_old; - -} - // ============================================================================= // Set Table Instructions // ============================================================================= @@ -612,14 +500,15 @@ void parse_amp_sweep_ins(uint addr, uint channel, start = get_asf(start, &asf_start); end = get_asf(end, &asf_end); + double t_sync = 4 / (ad9959.ref_clk * ad9959.pll_mult); + double bits_per_arb = 1024; if (start < end) { - bits_per_sync_clk_cycle = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult) * 1024; - sweep_rate = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); - - // reversing scaling to see what sweep rate was actually set - sweep_rate = sweep_rate * (ad9959->ref_clk * ad9959->pll_mult) / (4 * 1024); - + double arb_per_sync = sweep_rate * t_sync; + double bits_per_sync_clk_cycle = bits_per_arb * arb_per_sync; + double approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); + sweep_rate = approx_bits_per_sync / bits_per_arb / t_sync; } else { + // sweep_rate = sweep_rate / t_sync; sweep_rate = get_asf(sweep_rate, &delta); } if (delta == 0) { @@ -630,9 +519,8 @@ void parse_amp_sweep_ins(uint addr, uint channel, if (DEBUG) { fast_serial_printf( - "Set ins #%d for channel %d from %3lf%% to %3lf%% with sweep delta %3lf%% " - "and rate of %u\n", - addr, channel, start, end, sweep_rate, rate); + "Set ins #%d for channel %d from %3lf%% to %3lf%% with sweep rate %3lf%% arb/s\n", + addr, channel, start, end, sweep_rate); } set_amp_sweep_ins(addr, channel, asf_start, asf_end, delta, rate, ftw, pow); @@ -746,20 +634,30 @@ void parse_freq_sweep_ins(uint addr, uint channel, end = get_ftw(&ad9959, end, &ftw_end); if (start < end) { - double bits_per_sync_clk_cycle = sweep_rate * 4 / (ad9959->ref_clk * ad9959->pll_mult)^2 * 4294967296; - sweep_rate = approx_double_32(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); - sweep_rate = sweep_rate * (ad9959.ref_clk * ad9959.pll_mult) / (4 * 4294967296); + double sys_clk = ad9959.ref_clk * ad9959.pll_mult; + double t_sync = 4 / sys_clk; + double bits_per_hz = 4294967296 / sys_clk; + double hz_per_sync = sweep_rate * t_sync; + double approx_bits_per_sync; + double bits_per_sync_clk_cycle = bits_per_hz * hz_per_sync; + + approx_bits_per_sync = approx_double_32(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); + + sweep_rate = approx_bits_per_sync / bits_per_hz / t_sync; } else { // here your delta is just sweep_rate / 1 sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); } - + if (delta == 0) { + // enforce minimum sweep rate to not be zero + delta = 1; + sweep_rate = delta * (ad9959.ref_clk * ad9959.pll_mult) / (4 * 4294967296); + } if (DEBUG) { fast_serial_printf( - "Set ins #%d for channel %d from %4lf Hz to %4lf Hz with delta %4lf " - "Hz and rate of %d\n", - addr, channel, start, end, sweep_rate, rate); + "Set ins #%d for channel %d from %4lf Hz to %4lf Hz with sweep rate %lf Hz/s\n", + addr, channel, start, end, sweep_rate); } set_freq_sweep_ins(addr, channel, ftw_start, ftw_end, delta, rate, asf, pow); @@ -879,86 +777,25 @@ void parse_phase_sweep_ins(uint addr, uint channel, end = get_pow(end, &pow_end); if (start < end) { - double bits_per_sync_clk_cycle = sweep_rate * 4 / (ad9959.ref_clk * ad9959.pll_mult) * 16384; - sweep_rate = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); - sweep_rate = sweep_rate * (ad9959.ref_clk * ad9959.pll_mult) / (4 * 16384); - + double bits_per_deg = 16384; + double t_sync = 4 / (ad9959.ref_clk * ad9959.pll_mult); + double deg_per_sync = sweep_rate * t_sync; + double bits_per_sync_clk_cycle = bits_per_deg * deg_per_sync; + double approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); + sweep_rate = approx_bits_per_sync / bits_per_deg / t_sync; } else { sweep_rate = get_pow(sweep_rate, &delta); } if (DEBUG) { fast_serial_printf( - "Set ins #%d for channel %d from %4lf deg to %4lf deg with delta " - "%4lf deg and rate of %d\n", - addr, channel, pow_start / 16384.0 * 360, pow_end / 16384.0 * 360, delta / 16384.0 * 360, - rate); + "Set ins #%d for channel %d from %4lf deg to %4lf deg with sweep rate %4lf deg/s\n", + addr, channel, start, end, sweep_rate); } set_phase_sweep_ins(addr, channel, pow_start, pow_end, delta, rate, ftw, asf); } -// void get_continued_fraction(double number, uint32_t *frac_list, uint num_terms) { - -// // Represent a double as a continued fraction -// // Avoids dynamic allocation and lack of array return types by editing a -// // pre-allocated frac_list -// uint32_t a = floor(number); -// frac_list[0] = a; - -// for (uint i = 0; i < num_terms; i++) { -// number = number - frac_list[i]; - -// // Check if number is zero within some tolerance -// // May need to define somewhere else -// if (number < 0.00001){ -// break; -// } - -// number = 1 / number; -// frac_list[i+1] = floor(number); -// } -// } - -// void continued_fraction_as_ratio(uint32_t *frac_list, uint num_terms, uint32_t *numerator, uint32_t *denominator) { - -// // Algorithm to extract the numerator and denominator that estimate the decimal -// // Its other related function may need to be combined - -// if (num_terms == 0) { -// // Divide by zero error? -// *numerator = 0; -// *denominator = 0; -// } else if (num_terms == 1) { -// // If only one term, the fraction is just that term over 1 -// *numerator = frac_list[0]; -// *denominator = 1; // this is fudged -// } else { -// uint32_t p0 = frac_list[0], q0 = 1; -// uint32_t p1 = frac_list[1] * frac_list[0] + 1, q1 = frac_list[1]; -// uint32_t p, q; - -// for (uint k = 3; k < num_terms + 1; k++) { -// p = frac_list[k - 1] * p1 + p0; -// q = frac_list[k - 1] * q1 + q0; -// p0 = p1; -// p1 = p; -// q0 = q1; -// q1 = q; -// } - -// // Assign p to numerator and q to denominator -// // Restrict denominator to be less than 256 -// if (q1 > 256){ -// *numerator = p0; -// *denominator = q0; -// } else { -// *numerator = p1; -// *denominator = q1; -// } -// } -// } - void get_memory_layout(uint sweep_mode) { fast_serial_printf("%d active channels\n", ad9959.channels); @@ -1138,6 +975,14 @@ void loop() { } else if (strncmp(readstring, "abort", 5) == 0) { abort_run(); OK(); + } else if (strncmp(readstring, "approx", 6) == 0) { + double f, f_approx; + int parsed = sscanf(readstring, "%*s %lf", &f); + uint rate; + uint32_t delta; + + f_approx = approx_double_32(f, &delta, &rate, 4e6, 255); + fast_serial_printf("%lf (%lf)=[%u/%u]\n", f, f_approx, delta, rate); } // ==================================================== // Stuff that cannot be done while the table is running @@ -1171,21 +1016,6 @@ void loop() { OK(); } else if (strncmp(readstring, "getmode", 7) == 0) { get_memory_layout(ad9959.sweep_type); - // } else if (strncmp(readstring, "getfrac", 7) == 0) { - - // uint num_terms = 4; - // uint16_t frac_container[num_terms]; - // uint16_t some_numerator, some_denominator; - // get_continued_fraction(2.3184, frac_container, num_terms); - // fast_serial_printf("["); - - // for (uint i=0; i < num_terms; i++){ - // fast_serial_printf("%u,", frac_container[i]); - // } - // fast_serial_printf("]\n"); - - // continued_fraction_as_ratio(frac_container, num_terms, &some_numerator, &some_denominator); - // fast_serial_printf("Got %u and %u\n", some_numerator, some_denominator); } else if (strncmp(readstring, "setchannels", 11) == 0) { uint channels; From 47b5584e722d411922b009be6f8a296df9cc519f Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Fri, 4 Apr 2025 18:22:16 -0400 Subject: [PATCH 05/11] an idea, why not have the falling case just use the same function but enforce the denominator to be 1? I believe thats the same as before, but outskirts the bounds on get_asf() --- dds-sweeper/dds-sweeper.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/dds-sweeper/dds-sweeper.c b/dds-sweeper/dds-sweeper.c index 622b717..e7f78a2 100644 --- a/dds-sweeper/dds-sweeper.c +++ b/dds-sweeper/dds-sweeper.c @@ -502,20 +502,25 @@ void parse_amp_sweep_ins(uint addr, uint channel, double t_sync = 4 / (ad9959.ref_clk * ad9959.pll_mult); double bits_per_arb = 1024; + double arb_per_sync = sweep_rate * t_sync; + double bits_per_sync_clk_cycle = bits_per_arb * arb_per_sync; + double approx_bits_per_sync; + if (start < end) { - double arb_per_sync = sweep_rate * t_sync; - double bits_per_sync_clk_cycle = bits_per_arb * arb_per_sync; - double approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); - sweep_rate = approx_bits_per_sync / bits_per_arb / t_sync; + approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); } else { - // sweep_rate = sweep_rate / t_sync; - sweep_rate = get_asf(sweep_rate, &delta); + // sweep_rate = sweep_rate * bits_per_arb / t_sync; + // sweep_rate = get_asf(sweep_rate, &delta); + approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, 1); + } + sweep_rate = approx_bits_per_sync / bits_per_arb / t_sync; if (delta == 0) { // enforce minimum sweep rate to not be zero delta = 1; sweep_rate = delta / 1023.0; } + if (DEBUG) { fast_serial_printf( @@ -975,7 +980,7 @@ void loop() { } else if (strncmp(readstring, "abort", 5) == 0) { abort_run(); OK(); - } else if (strncmp(readstring, "approx", 6) == 0) { + } else if (strncmp(readstring, "approx32", 8) == 0) { double f, f_approx; int parsed = sscanf(readstring, "%*s %lf", &f); uint rate; @@ -983,6 +988,14 @@ void loop() { f_approx = approx_double_32(f, &delta, &rate, 4e6, 255); fast_serial_printf("%lf (%lf)=[%u/%u]\n", f, f_approx, delta, rate); + } else if (strncmp(readstring, "approx16", 8) == 0) { + double f, f_approx; + int parsed = sscanf(readstring, "%*s %lf", &f); + uint rate; + uint16_t delta; + + f_approx = approx_double_16(f, &delta, &rate, 16300, 255); + fast_serial_printf("%lf (%lf)=[%u/%u]\n", f, f_approx, delta, rate); } // ==================================================== // Stuff that cannot be done while the table is running From 352861849f9aa74e95ade553365534bb41ba3cdd Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:23:56 -0400 Subject: [PATCH 06/11] Polished ramp logic and returned test notebook to working condition --- dds-sweeper/ad9959.c | 1 - dds-sweeper/dds-sweeper.c | 55 ++- testing/tests.ipynb | 779 +++++++++++++++++--------------------- 3 files changed, 389 insertions(+), 446 deletions(-) diff --git a/dds-sweeper/ad9959.c b/dds-sweeper/ad9959.c index 8855091..390c261 100644 --- a/dds-sweeper/ad9959.c +++ b/dds-sweeper/ad9959.c @@ -197,7 +197,6 @@ double approx_double_32(double f, uint32_t * numerator, uint * denominator, uint uint num_iters = 100; for (uint i = 1; i < num_iters; i++) { - if (fabs(f - ((double)p_old / (double)q_old)) < eps) { // Ratio close to double within eps break; diff --git a/dds-sweeper/dds-sweeper.c b/dds-sweeper/dds-sweeper.c index e7f78a2..6458ced 100644 --- a/dds-sweeper/dds-sweeper.c +++ b/dds-sweeper/dds-sweeper.c @@ -509,12 +509,14 @@ void parse_amp_sweep_ins(uint addr, uint channel, if (start < end) { approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); } else { - // sweep_rate = sweep_rate * bits_per_arb / t_sync; // sweep_rate = get_asf(sweep_rate, &delta); approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, 1); } + + // back to human readable units sweep_rate = approx_bits_per_sync / bits_per_arb / t_sync; + if (delta == 0) { // enforce minimum sweep rate to not be zero delta = 1; @@ -637,28 +639,32 @@ void parse_freq_sweep_ins(uint addr, uint channel, // Convert percentages to integers, check values in range start = get_ftw(&ad9959, start, &ftw_start); end = get_ftw(&ad9959, end, &ftw_end); + + double sys_clk = ad9959.ref_clk * ad9959.pll_mult; + double t_sync = 4 / sys_clk; + double bits_per_hz = 4294967296 / sys_clk; + double hz_per_sync = sweep_rate * t_sync; + double bits_per_sync_clk_cycle = bits_per_hz * hz_per_sync; + double approx_bits_per_sync; if (start < end) { - double sys_clk = ad9959.ref_clk * ad9959.pll_mult; - double t_sync = 4 / sys_clk; - double bits_per_hz = 4294967296 / sys_clk; - double hz_per_sync = sweep_rate * t_sync; - double approx_bits_per_sync; - double bits_per_sync_clk_cycle = bits_per_hz * hz_per_sync; - approx_bits_per_sync = approx_double_32(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); - - sweep_rate = approx_bits_per_sync / bits_per_hz / t_sync; - + } else { // here your delta is just sweep_rate / 1 - sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); + approx_bits_per_sync = approx_double_32(bits_per_sync_clk_cycle, &delta, &rate, delta_max, 1); + // sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); } + + // back to human readable units + sweep_rate = approx_bits_per_sync / bits_per_hz / t_sync; + if (delta == 0) { // enforce minimum sweep rate to not be zero delta = 1; sweep_rate = delta * (ad9959.ref_clk * ad9959.pll_mult) / (4 * 4294967296); } + if (DEBUG) { fast_serial_printf( "Set ins #%d for channel %d from %4lf Hz to %4lf Hz with sweep rate %lf Hz/s\n", @@ -781,15 +787,26 @@ void parse_phase_sweep_ins(uint addr, uint channel, start = get_pow(start, &pow_start); end = get_pow(end, &pow_end); + double bits_per_deg = 16384; + double t_sync = 4 / (ad9959.ref_clk * ad9959.pll_mult); + double deg_per_sync = sweep_rate * t_sync; + double bits_per_sync_clk_cycle = bits_per_deg * deg_per_sync; + double approx_bits_per_sync; + if (start < end) { - double bits_per_deg = 16384; - double t_sync = 4 / (ad9959.ref_clk * ad9959.pll_mult); - double deg_per_sync = sweep_rate * t_sync; - double bits_per_sync_clk_cycle = bits_per_deg * deg_per_sync; - double approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); - sweep_rate = approx_bits_per_sync / bits_per_deg / t_sync; + approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); } else { - sweep_rate = get_pow(sweep_rate, &delta); + // sweep_rate = get_pow(sweep_rate, &delta); + approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, 1); + } + + // back to human readable units + sweep_rate = approx_bits_per_sync / bits_per_deg / t_sync; + + if (delta == 0) { + // enforce minimum sweep rate to not be zero + delta = 1; + sweep_rate = delta / 16383.0; } if (DEBUG) { diff --git a/testing/tests.ipynb b/testing/tests.ipynb index 13982f8..778b9f0 100644 --- a/testing/tests.ipynb +++ b/testing/tests.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -26,6 +26,10 @@ "# the pico will show up as 'USB Serial Device'\n", "PICO_PORT = 'COM3'\n", "\n", + "# Including a PRAWN_PORT to be used if you are externally triggering \n", + "# (pass into send function)\n", + "PRAWN_PORT = 'COM7'\n", + "\n", "MHZ = 1000000\n", "\n", "# without images, entire notebook takes ~40s\n", @@ -35,16 +39,7 @@ }, { "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "# send('program')" - ] - }, - { - "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -53,7 +48,7 @@ "# if echo is set to false, that means not to worry about the response from the\n", "# pico it signifigantly reduces communication time when sending many\n", "# instructions, but you lose out on the debugging info from the pico\n", - "def send(command: str, echo = True) -> str:\n", + "def send(command: str, echo = True, PORT = PICO_PORT) -> str:\n", " # pico is expecting a newline to end every command\n", " if command[-1] != '\\n':\n", " command += '\\n'\n", @@ -85,17 +80,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Serial Communication Successful\n" - ] - } - ], + "outputs": [], "source": [ "assert send('reset') == 'ok\\n'\n", "assert send('status') == '0\\n'\n", @@ -112,24 +99,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'pll_mult': 4,\n", - " 0: {'freq': 0.0, 'phase': 0.0, 'amp': 1},\n", - " 1: {'freq': 0.0, 'phase': 0.0, 'amp': 1},\n", - " 2: {'freq': 0.0, 'phase': 0.0, 'amp': 1},\n", - " 3: {'freq': 0.0, 'phase': 0.0, 'amp': 1}}" - ] - }, - "execution_count": 5, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# Helper for reading register values and putting them in a dictionary\n", "# takes in the frequency of the reference clock, assuming default of 125 MHz\n", @@ -177,33 +149,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "PLL Multiplier: 4\n", - "Channel 0:\n", - " Frequency: 0.0 Hz\n", - " Phase: 0.0 degrees\n", - " Amplitude: 1\n", - "Channel 1:\n", - " Frequency: 0.0 Hz\n", - " Phase: 0.0 degrees\n", - " Amplitude: 1\n", - "Channel 2:\n", - " Frequency: 0.0 Hz\n", - " Phase: 0.0 degrees\n", - " Amplitude: 1\n", - "Channel 3:\n", - " Frequency: 0.0 Hz\n", - " Phase: 0.0 degrees\n", - " Amplitude: 1\n" - ] - } - ], + "outputs": [], "source": [ "def format_regs(ad9959: dict) -> str:\n", " formatted_str = []\n", @@ -223,17 +171,9 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Register Readback Successful\n" - ] - } - ], + "outputs": [], "source": [ "assert send('reset') == 'ok\\n', 'Could not run \"reset\" command'\n", "ad9959 = readregs()\n", @@ -264,33 +204,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "PLL Multiplier: 4\n", - "Channel 0:\n", - " Frequency: 99999999.97671694 Hz\n", - " Phase: 0.0 degrees\n", - " Amplitude: 1\n", - "Channel 1:\n", - " Frequency: 0.0 Hz\n", - " Phase: 270.0 degrees\n", - " Amplitude: 1\n", - "Channel 2:\n", - " Frequency: 0.0 Hz\n", - " Phase: 0.0 degrees\n", - " Amplitude: 0.5004887585532747\n", - "Channel 3:\n", - " Frequency: 0.0 Hz\n", - " Phase: 0.0 degrees\n", - " Amplitude: 1\n" - ] - } - ], + "outputs": [], "source": [ "def format_regs(ad9959: dict) -> str:\n", " formatted_str = []\n", @@ -310,7 +226,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -326,20 +242,9 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "27" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# my_instrument.query('*LRN?')\n", "# my_instrument.query('TIMebase:MODE?')\n", @@ -379,7 +284,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -420,20 +325,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'ok\\n'" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "## source\n", "freq0 = 125 * MHZ # source freq > ref freq\n", @@ -463,20 +357,9 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'ok\\n'" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "# send(f\"\"\"\n", "# abort\n", @@ -511,34 +394,9 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 125000000.000000 4\n", - "\n", - "ok\n", - "\n", - "0 120000000.000000 1\n", - "\n", - "ok\n", - "\n", - "pll_sys = 110000kHz\n", - "pll_usb = 48000kHz\n", - "rosc = 5458kHz\n", - "clk_sys = 110000kHz\n", - "clk_peri = 110001kHz\n", - "clk_usb = 48000kHz\n", - "clk_adc = 48000kHz\n", - "clk_rtc = 47kHz\n", - "ok\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "print(send('clkstatus'))\n", "print(send(f'setclock 0 {120 * MHZ} 1'))\n", @@ -549,50 +407,18 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'ok\\n'" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "send('reset')" ] }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "0 110000000.000000 1\n", - "\n", - "ok\n", - "\n", - "pll_sys = 125000kHz\n", - "pll_usb = 48000kHz\n", - "rosc = 5460kHz\n", - "clk_sys = 125000kHz\n", - "clk_peri = 125000kHz\n", - "clk_usb = 48000kHz\n", - "clk_adc = 48000kHz\n", - "clk_rtc = 47kHz\n", - "ok\n", - "\n" - ] - } - ], + "outputs": [], "source": [ "print(send('clkstatus'))\n", "print(send(f'setclock 0 {125 * MHZ} 4')) ## return back to default value\n", @@ -619,18 +445,9 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Table Programmed, Executing\n", - "Table Executed successfully\n" - ] - } - ], + "outputs": [], "source": [ "my_instrument.set_time_delay(20e-6)\n", "my_instrument.set_time_scale(10e-9)\n", @@ -677,18 +494,9 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Table Programmed, Executing\n", - "Table Executed successfully\n" - ] - } - ], + "outputs": [], "source": [ "my_instrument.annotate_screen(\"Testing Mode 0b: Single Stepping Amplitude\")\n", "\n", @@ -734,18 +542,9 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Table Programmed, Executing\n", - "Table Executed successfully\n" - ] - } - ], + "outputs": [], "source": [ "my_instrument.annotate_screen(\"Testing Mode 0c: Single Stepping Phase\")\n", "\n", @@ -792,17 +591,9 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Table run from non-volatile memory successfully\n" - ] - } - ], + "outputs": [], "source": [ "my_instrument.annotate_screen(\"Testing Table Save and Load\")\n", "\n", @@ -846,53 +637,39 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Success\n" - ] - } - ], + "outputs": [], "source": [ "my_instrument.annotate_screen(\"Testing Mode 1: Amplitude Sweep\")\n", - "my_instrument.set_time_delay(50e-6)\n", - "my_instrument.set_time_scale(20e-6)\n", + "# my_instrument.set_time_delay(50e-6)\n", + "# my_instrument.set_time_scale(20e-6)\n", "\n", "# send('reset')\n", "\n", "filename = 'mode1-picostart-ampsweep-test.png'\n", - "t = 2000 / (125e6)\n", + "t = 200 / (125e6)\n", + "sweep_rate = .1225e6 # arb / s\n", "\n", - "send('debug off')\n", - "send(f\"\"\"mode 1 1\n", + "print(send(f\"\"\"mode 1 1\n", + "debug off\n", "setchannels 1\n", "setfreq 0 100000000\n", "setfreq 1 100000000\n", "setfreq 2 100000000\n", "setfreq 3 100000000\n", - "set 0 0 1.0 0.0 0.001 {t}\n", - "set 0 1 0.0 0.5 0.001 {t}\n", - "set 0 2 0.5 1.0 0.001 {t}\n", - "set 0 3 1.0 0.0 0.001 {t}\n", - "set 0 4 0.0 1.0 0.001 {t}\n", - "set 0 5 1.0 0.5 0.001 {t}\n", - "set 0 6 0.5 0.0 0.001 {t}\n", - "set 0 7 0.0 1.0 0.001 {t}\n", - "set 0 0 1.0 0.0 0.001 {t}\n", - "set 0 1 0.0 0.5 0.001 {t}\n", - "set 0 2 0.5 1.0 0.001 {t}\n", - "set 0 3 1.0 0.0 0.001 {t}\n", - "set 0 4 0.0 1.0 0.001 {t}\n", - "set 0 5 1.0 0.5 0.001 {t}\n", - "set 0 6 0.5 0.0 0.001 {t}\n", - "set 0 7 0.0 1.0 0.001 {t}\n", + "debug on\n", + "set 0 0 1.0 0.0 {sweep_rate} {t}\n", + "set 0 1 0.0 0.5 {sweep_rate} {t}\n", + "set 0 2 0.5 1.0 {sweep_rate} {t}\n", + "set 0 3 1.0 0.0 {sweep_rate} {t}\n", + "set 0 4 0.0 1.0 {sweep_rate} {t}\n", + "set 0 5 1.0 0.5 {sweep_rate} {t}\n", + "set 0 6 0.5 0.0 {sweep_rate} {t}\n", + "set 0 7 0.0 1.0 {sweep_rate} {t}\n", "set 4 8\n", "start\n", - "\"\"\")\n", + "\"\"\"))\n", "\n", "assert send('numtriggers') == '8\\n'\n", "print('Success')\n", @@ -903,6 +680,91 @@ " display(Image(filename))" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "x = 1/255\n", + "print(send(f'approx16 {x}'))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + ".1" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "1/1023" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "send('reset')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# send('program')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "my_instrument.annotate_screen(\"Testing Mode 1: Amplitude Sweep\")\n", + "# my_instrument.set_time_delay(50e-6)\n", + "# my_instrument.set_time_scale(20e-6)\n", + "\n", + "# send('reset')\n", + "\n", + "# filename = 'mode1-picostart-ampsweep-test.png'\n", + "t = 2000 / (125e6)\n", + "sweep_rate = .1225e6 # arb per sec\n", + "send('debug on')\n", + "print(send(f\"\"\"mode 1 1\n", + "setchannels 1\n", + "setfreq 0 100000000\n", + "setfreq 1 100000000\n", + "setfreq 2 100000000\n", + "setfreq 3 100000000\n", + "set 0 0 0.0 0.5 {sweep_rate} {t}\n", + "set 0 1 0.5 1.0 {sweep_rate} {t}\n", + "set 0 2 1.0 0.5 {sweep_rate} {t}\n", + "set 0 3 0.5 0.0 {sweep_rate} {t}\n", + "set 4 4\n", + "start\n", + "\"\"\"))\n", + "\n", + "# assert send('numtriggers') == '8\\n'\n", + "print('Success')\n", + "if SAVE_IMAGES == True:\n", + " my_instrument.save_screenshot(filename)\n", + "\n", + "if SHOW_IMAGES == True:\n", + " display(Image(filename))" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -912,7 +774,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -945,6 +807,18 @@ " display(Image(filename))" ] }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# send('status\\r\\n', PORT=PRAWN_PORT)\n", + "# send(f'set 0 0 4000 100\\r\\n', PORT=PRAWN_PORT)\n", + "# print(send('start\\r\\n', PORT=PRAWN_PORT, echo=True))\n", + "# print(send('abort\\r\\n', PORT=PRAWN_PORT, echo=True))\n" + ] + }, { "attachments": {}, "cell_type": "markdown", @@ -973,7 +847,7 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 413, "metadata": {}, "outputs": [ { @@ -986,8 +860,8 @@ ], "source": [ "my_instrument.annotate_screen(\"Testing Mode 2: Frequency Sweep\")\n", - "my_instrument.set_time_delay(40e-6)\n", - "my_instrument.set_time_scale(100e-6)\n", + "# my_instrument.set_time_delay(40e-6)\n", + "# my_instrument.set_time_scale(100e-6)\n", "\n", "# send('reset')\n", "\n", @@ -1001,29 +875,42 @@ "# f2 = 90e6\n", "# f3 = 130e6\n", "\n", - "d = 2000\n", + "d = 17e6\n", "t = 2000 / (125e6)\n", "\n", "send(\n", "f\"\"\"abort\n", "mode 2 1\n", "setchannels 1\n", - "set 0 0 {f1} {f3} {d * 1} {t * 1}\n", - "set 0 1 {f3} {f2} {d / 4} {t * 2}\n", - "set 0 2 {f2} {f1} {d * 1} {t / 2}\n", - "set 0 3 {f1} {f1} {d * 0} {t * 1}\n", - "set 0 4 {f2} {f2} {d * 0} {t * 1}\n", - "set 0 5 {f3} {f3} {d * 0} {t * 1}\n", - "set 0 6 {f3} {f1} {d * 0} {t * 1}\n", - "set 0 7 {f1} {f2} {d / 4} {t * 2}\n", - "set 0 8 {f2} {f3} {d * 0} {t * 10}\n", - "set 0 9 {f1} {f1} {d * 0} 1\n", + "set 0 0 {f1} {f3} {d} {t * 1}\n", + "set 0 1 {f3} {f2} {d} {t * 2}\n", + "set 0 2 {f2} {f1} {d} {t / 2}\n", + "set 0 3 {f1} {f1} {d} {t * 1}\n", + "set 0 4 {f2} {f2} {d} {t * 1}\n", + "set 0 5 {f3} {f3} {d} {t * 1}\n", + "set 0 6 {f3} {f1} {d} {t * 1}\n", + "set 0 7 {f1} {f2} {d} {t * 2}\n", + "set 0 8 {f2} {f3} {d} {t * 10}\n", + "set 0 9 {f1} {f1} {d} 1\n", "set 4 10\n", "start\n", "\"\"\"\n", ")\n", "\n", - "assert send('numtriggers') == '10\\n'\n", + "\n", + "# ## set chan addr start end ramprate (time)\n", + "# print(send(\n", + "# f\"\"\"abort\n", + "# debug on\n", + "# mode 2 1\n", + "# setchannels 1\n", + "# set 0 0 {f1} {f3} {d} {t * 1}\n", + "# set 0 1 {f3} 0 {d} {t * 2}\n", + "# set 4 2\n", + "# start\n", + "# \"\"\"\n", + "# ))\n", + "# assert send('numtriggers') == '10\\n'\n", "print('Success')\n", "\n", "if SAVE_IMAGES == True:\n", @@ -1052,20 +939,9 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'ok\\nok\\nok\\nok\\nok\\nok\\nok\\nok\\nok\\nok\\nok\\n'" - ] - }, - "execution_count": 47, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "send(\n", "f\"\"\"abort\n", @@ -1099,13 +975,92 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 436, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'ok\\n'" + ] + }, + "execution_count": 436, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "send('reset')" + ] + }, + { + "cell_type": "code", + "execution_count": 448, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ + "ok\n", + "ok\n", + "set freq: 99999999.976717\n", + "ok\n", + "set freq: 99999999.976717\n", + "ok\n", + "set freq: 99999999.976717\n", + "ok\n", + "set freq: 99999999.976717\n", + "ok\n", + "Phase: 0.000000\n", + "ok\n", + "Phase: 0.000000\n", + "ok\n", + "Phase: 0.000000\n", + "ok\n", + "Phase: 0.000000\n", + "ok\n", + "ok\n", + "ok\n", + "Set ins #0 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #1 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #2 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #3 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #4 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #5 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #0 for channel 1 from 0.000000 deg to 180.010987 deg with sweep rate 49999.782017 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #1 for channel 1 from 180.010987 deg to 90.005493 deg with sweep rate 53405.761719 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #2 for channel 1 from 90.005493 deg to 0.000000 deg with sweep rate 53405.761719 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #3 for channel 1 from 0.000000 deg to 90.005493 deg with sweep rate 49999.782017 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #4 for channel 1 from 90.005493 deg to 180.010987 deg with sweep rate 49999.782017 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #5 for channel 1 from 180.010987 deg to 0.000000 deg with sweep rate 53405.761719 deg/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "ok\n", + "ok\n", + "\n", "Success\n" ] } @@ -1124,10 +1079,10 @@ "filename = 'mode3-phasesweep-test.png'\n", "\n", "t = 2000 / (125e6) # set time in seconds\n", - "d = 0.2\n", + "sweep_rate = 0.5e5 # degrees per second\n", "\n", - "send(f\"\"\"abort\n", - "debug off\n", + "print(send(f\"\"\"abort\n", + "debug on\n", "setfreq 0 100000000\n", "setfreq 1 100000000\n", "setfreq 2 100000000\n", @@ -1144,15 +1099,15 @@ "set 0 3 0 0 0 {t}\n", "set 0 4 0 0 0 {t}\n", "set 0 5 0 0 0 {t}\n", - "set 1 0 0 180 {d} {t}\n", - "set 1 1 180 90 {d} {t}\n", - "set 1 2 90 0 {d} {t}\n", - "set 1 3 0 90 {d} {t}\n", - "set 1 4 90 180 {d} {t}\n", - "set 1 5 180 0 {d} {t}\n", + "set 1 0 0 180 {sweep_rate} {t}\n", + "set 1 1 180 90 {sweep_rate} {t}\n", + "set 1 2 90 0 {sweep_rate} {t}\n", + "set 1 3 0 90 {sweep_rate} {t}\n", + "set 1 4 90 180 {sweep_rate} {t}\n", + "set 1 5 180 0 {sweep_rate} {t}\n", "set 4 6\n", "start\n", - "\"\"\")\n", + "\"\"\"))\n", "\n", "assert send('numtriggers') == '6\\n'\n", "print('Success')\n", @@ -1174,7 +1129,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 451, "metadata": {}, "outputs": [], "source": [ @@ -1260,7 +1215,7 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 454, "metadata": {}, "outputs": [ { @@ -1280,8 +1235,9 @@ "\n", "f0 = 120 * MHZ\n", "\n", - "d = 0.001\n", + "# d = 0.001\n", "t = 2000 / (125e6)\n", + "sweep_rate = .1225e6 # arb / s\n", "\n", "filename = 'mode4-ampsweep2-test.png'\n", "\n", @@ -1290,24 +1246,24 @@ "f\"\"\"abort\n", "mode 4 1\n", "setchannels 2\n", - "set 0 0 1.0 0.0 {d} {f0} 0 {t}\n", - "set 0 1 0.0 0.5 {d} {f0} 0 {t}\n", - "set 0 2 0.5 1.0 {d} {f0} 0 {t}\n", - "set 0 3 1.0 0.0 {d} {f0} 0 {t}\n", - "set 0 4 0.0 1.0 {d} {f0} 0 {t}\n", - "set 0 5 1.0 0.5 {d} {f0} 0 {t}\n", - "set 0 6 0.5 0.0 {d} {f0} 0 {t}\n", - "set 0 7 0.0 1.0 {d} {f0} 0 {t}\n", - "set 0 8 1.0 0.0 {d} {f0} 0 {t}\n", + "set 0 0 1.0 0.0 {sweep_rate} {f0} 0 {t}\n", + "set 0 1 0.0 0.5 {sweep_rate} {f0} 0 {t}\n", + "set 0 2 0.5 1.0 {sweep_rate} {f0} 0 {t}\n", + "set 0 3 1.0 0.0 {sweep_rate} {f0} 0 {t}\n", + "set 0 4 0.0 1.0 {sweep_rate} {f0} 0 {t}\n", + "set 0 5 1.0 0.5 {sweep_rate} {f0} 0 {t}\n", + "set 0 6 0.5 0.0 {sweep_rate} {f0} 0 {t}\n", + "set 0 7 0.0 1.0 {sweep_rate} {f0} 0 {t}\n", + "set 0 8 1.0 0.0 {sweep_rate} {f0} 0 {t}\n", "set 0 9 1.0 1.0 {0} {f0} 0 {t}\n", "set 1 0 1.0 0.0 {0} {f0} 0 {t}\n", "set 1 1 0.0 0.5 {0} {f0} 0 {t}\n", - "set 1 2 0.5 1.0 {d} {f0} 0 {t}\n", - "set 1 3 1.0 0.0 {d} {f0} 0 {t}\n", - "set 1 4 0.0 1.0 {d} {f0} 0 {t}\n", - "set 1 5 1.0 0.5 {d} {f0} 0 {t}\n", - "set 1 6 0.5 0.0 {d} {f0} 0 {t}\n", - "set 1 7 0.0 1.0 {d} {f0} 0 {t}\n", + "set 1 2 0.5 1.0 {sweep_rate} {f0} 0 {t}\n", + "set 1 3 1.0 0.0 {sweep_rate} {f0} 0 {t}\n", + "set 1 4 0.0 1.0 {sweep_rate} {f0} 0 {t}\n", + "set 1 5 1.0 0.5 {sweep_rate} {f0} 0 {t}\n", + "set 1 6 0.5 0.0 {sweep_rate} {f0} 0 {t}\n", + "set 1 7 0.0 1.0 {sweep_rate} {f0} 0 {t}\n", "set 1 8 1.0 1.0 {0} {f0} 0 {t}\n", "set 1 9 1.0 1.0 {0} {f0} 0 {t}\n", "set 4 10\n", @@ -1336,7 +1292,7 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1353,7 +1309,7 @@ "p1 = get_pow(phase = 90)\n", "p2 = get_pow(phase = 270)\n", "\n", - "d = 1\n", + "sweep_rate = 1\n", "t = 2000 # seti in cycles\n", "\n", "filename = 'mode4-seti-ampsweep2-test.png'\n", @@ -1362,14 +1318,14 @@ "f\"\"\"abort\n", "mode 4 1\n", "setchannels 2\n", - "seti 0 0 700 1023 {d} 1 {f2} {p1} {t}\n", - "seti 0 1 1023 700 {d} 1 {f2} {p2} {t}\n", + "seti 0 0 700 1023 {sweep_rate} 1 {f2} {p1} {t}\n", + "seti 0 1 1023 700 {sweep_rate} 1 {f2} {p2} {t}\n", "seti 0 2 1023 1023 {0} 1 {f2} {p1} {t}\n", - "seti 0 3 1023 700 {d} 1 {f2} {p2} {t}\n", - "seti 1 0 1023 1023 {d} 1 {f2} {p2} {t}\n", - "seti 1 1 1023 1023 {d} 1 {f2} {p2} {t}\n", + "seti 0 3 1023 700 {sweep_rate} 1 {f2} {p2} {t}\n", + "seti 1 0 1023 1023 {sweep_rate} 1 {f2} {p2} {t}\n", + "seti 1 1 1023 1023 {sweep_rate} 1 {f2} {p2} {t}\n", "seti 1 2 1023 1023 {0} 1 {f2} {p2} {t}\n", - "seti 1 3 1023 1023 {d} 1 {f2} {p2} {t}\n", + "seti 1 3 1023 1023 {sweep_rate} 1 {f2} {p2} {t}\n", "seti 4 4\n", "start\n", "\"\"\"\n", @@ -1400,7 +1356,7 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 461, "metadata": {}, "outputs": [ { @@ -1409,7 +1365,7 @@ "'ok\\n'" ] }, - "execution_count": 64, + "execution_count": 461, "metadata": {}, "output_type": "execute_result" } @@ -1420,7 +1376,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 463, "metadata": {}, "outputs": [ { @@ -1442,9 +1398,9 @@ "f2 = 90e6\n", "f3 = 130e6\n", "\n", - "d = .001\n", + "# d = .001\n", "t = 2000 / (125e6)\n", - "\n", + "sweep_rate = 17e6\n", "filename = 'mode5-freqsweep2-test.png'\n", "\n", "# set Chan Addr Start Stop Delta Amp Phase Time\n", @@ -1453,26 +1409,26 @@ "f\"\"\"abort\n", "mode 5 1\n", "setchannels 2\n", - "set 0 0 {f1} {f3} {d} 0.75 90 {t}\n", - "set 0 1 {f3} {f2} {d/4} 0.5 180 {t*2}\n", - "set 0 2 {f2} {f1} {d} 0.9 90 {t/2}\n", - "set 0 3 {f1} {f1} {0} 1.0 00 {t}\n", - "set 0 4 {f2} {f2} {0} 0.9 90 {t}\n", - "set 0 5 {f3} {f3} {0} 0.8 180 {t}\n", - "set 0 6 {f3} {f1} {d} 0.9 90 {t}\n", - "set 0 7 {f1} {f2} {d/4} 1.0 00 {t*2}\n", - "set 0 8 {f2} {f3} {d} 0.9 90 {t*10}\n", - "set 0 9 {f1} {f1} 0 1.0 90 1\n", - "set 1 0 {f1} {f3} {d} 1 0 {t}\n", - "set 1 1 {f3} {f2} {d/4} 1 0 {t*2}\n", - "set 1 2 {f2} {f1} {d} 1 0 {t/2}\n", - "set 1 3 {f1} {f1} {0} 1 0 {t}\n", - "set 1 4 {f2} {f2} {0} 1 0 {t}\n", - "set 1 5 {f3} {f3} {0} 1 0 {t}\n", - "set 1 6 {f3} {f1} {d} 1 0 {t}\n", - "set 1 7 {f1} {f2} {d/4} 1 0 {t*2}\n", - "set 1 8 {f2} {f3} {d} 1 0 {t*10}\n", - "set 1 9 {f1} {f1} 0 1 0 1\n", + "set 0 0 {f1} {f3} {sweep_rate * 1} 0.75 90 {t}\n", + "set 0 1 {f3} {f2} {sweep_rate / 4} 0.5 180 {t*2}\n", + "set 0 2 {f2} {f1} {sweep_rate * 1} 0.9 90 {t/2}\n", + "set 0 3 {f1} {f1} {sweep_rate * 0} 1.0 00 {t}\n", + "set 0 4 {f2} {f2} {sweep_rate * 0} 0.9 90 {t}\n", + "set 0 5 {f3} {f3} {sweep_rate * 0} 0.8 180 {t}\n", + "set 0 6 {f3} {f1} {sweep_rate * 1} 0.9 90 {t}\n", + "set 0 7 {f1} {f2} {sweep_rate / 4} 1.0 00 {t*2}\n", + "set 0 8 {f2} {f3} {sweep_rate * 1} 0.9 90 {t*10}\n", + "set 0 9 {f1} {f1} {sweep_rate * 0} 1.0 90 1\n", + "set 1 0 {f1} {f3} {sweep_rate * 1} 1.0 0 {t}\n", + "set 1 1 {f3} {f2} {sweep_rate / 4} 1.0 0 {t*2}\n", + "set 1 2 {f2} {f1} {sweep_rate * 1} 1.0 0 {t/2}\n", + "set 1 3 {f1} {f1} {sweep_rate * 0} 1.0 0 {t}\n", + "set 1 4 {f2} {f2} {sweep_rate * 0} 1.0 0 {t}\n", + "set 1 5 {f3} {f3} {sweep_rate * 0} 1.0 0 {t}\n", + "set 1 6 {f3} {f1} {sweep_rate * 1} 1.0 0 {t}\n", + "set 1 7 {f1} {f2} {sweep_rate / 4} 1.0 0 {t*2}\n", + "set 1 8 {f2} {f3} {sweep_rate * 1} 1.0 0 {t*10}\n", + "set 1 9 {f1} {f1} {sweep_rate * 0} 1.0 0 1\n", "set 4 10\n", "start\n", "\"\"\"\n", @@ -1498,7 +1454,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1585,7 +1541,7 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1594,7 +1550,7 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1609,8 +1565,9 @@ "f115 = 115e6\n", "f118 = 118e6\n", "f125 = 125 * MHZ\n", - "d = 0.1\n", + "# d = 0.1\n", "t = 2000 / 125e6\n", + "sweep_rate = 0.5e5 # degrees per second\n", "\n", "filename = 'mode6-phasesweep2-test.png'\n", "\n", @@ -1619,61 +1576,31 @@ "f\"\"\"abort\n", "mode 6 1\n", "setchannels 2\n", - "set 0 0 0 0 {d} {f125} 0.80 {t * 2}\n", - "set 0 1 0 0 {d} {f125} 0.90 {t * 2}\n", - "set 0 2 0 0 {d} {f125} 0.75 {t * 2}\n", - "set 0 3 0 0 {d} {f125} 1.00 {t * 2}\n", - "set 0 4 0 0 {d} {f125} 1.00 {t * 2}\n", - "set 0 5 0 0 {d} {f125} 0.80 {t * 2}\n", - "set 0 6 0 0 {d} {f125} 1.00 {t * 2}\n", - "set 0 7 0 0 {d} {f125} 0.90 {t * 2}\n", - "set 0 8 0 0 {d} {f125} 1.00 {t * 2}\n", - "set 0 9 0 0 {d} {f125} 1.00 {t * 10}\n", - "set 1 0 90 {d} {f125} 1.00 {t * 2}\n", - "set 1 1 90 180 {d} {f125} 1.00 {t * 2}\n", - "set 1 2 180 270 {d} {f125} 1.00 {t * 2}\n", - "set 1 3 270 360 {d} {f125} 1.00 {t * 2}\n", - "set 1 4 360 270 {d} {f125} 1.00 {t * 2}\n", - "set 1 5 270 180 {d} {f125} 1.00 {t * 2}\n", - "set 1 6 180 270 {d} {f125} 1.00 {t * 2}\n", - "set 1 7 270 180 {d} {f125} 1.00 {t * 2}\n", - "set 1 8 180 90 {d} {f125} 1.00 {t * 2}\n", - "set 1 9 90 0 {d} {f125} 1.00 {t * 10}\n", + "set 0 0 0 0 {sweep_rate} {f125} 0.80 {t * 2}\n", + "set 0 1 0 0 {sweep_rate} {f125} 0.90 {t * 2}\n", + "set 0 2 0 0 {sweep_rate} {f125} 0.75 {t * 2}\n", + "set 0 3 0 0 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 0 4 0 0 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 0 5 0 0 {sweep_rate} {f125} 0.80 {t * 2}\n", + "set 0 6 0 0 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 0 7 0 0 {sweep_rate} {f125} 0.90 {t * 2}\n", + "set 0 8 0 0 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 0 9 0 0 {sweep_rate} {f125} 1.00 {t * 10}\n", + "set 1 0 90 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 1 90 180 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 2 180 270 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 3 270 360 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 4 360 270 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 5 270 180 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 6 180 270 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 7 270 180 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 8 180 90 {sweep_rate} {f125} 1.00 {t * 2}\n", + "set 1 9 90 0 {sweep_rate} {f125} 1.00 {t * 10}\n", "set 4 10\n", "start\n", "\"\"\"\n", ")\n", "\n", - "# ## set Channel Address Start Stop Delta Amp Freq Time\n", - "# send(\n", - "# f\"\"\"abort\n", - "# mode 6 1\n", - "# setchannels 2\n", - "# set 0 0 90 {d} {f125} 1.00 {t * 2}\n", - "# set 0 1 90 180 {d} {f125} 1.00 {t * 2}\n", - "# set 0 2 180 270 {d} {f125} 1.00 {t * 2}\n", - "# set 0 3 270 360 {d} {f125} 1.00 {t * 2}\n", - "# set 0 4 360 270 {d} {f125} 1.00 {t * 2}\n", - "# set 0 5 270 180 {d} {f125} 1.00 {t * 2}\n", - "# set 0 6 180 270 {d} {f125} 1.00 {t * 2}\n", - "# set 0 7 270 180 {d} {f125} 1.00 {t * 2}\n", - "# set 0 8 180 90 {d} {f125} 1.00 {t * 2}\n", - "# set 0 9 90 0 {d} {f125} 1.00 {t * 10}\n", - "# set 1 0 90 {d} {f125} 1.00 {t * 2}\n", - "# set 1 1 90 180 {d} {f125} 1.00 {t * 2}\n", - "# set 1 2 180 270 {d} {f125} 1.00 {t * 2}\n", - "# set 1 3 270 360 {d} {f125} 1.00 {t * 2}\n", - "# set 1 4 360 270 {d} {f125} 1.00 {t * 2}\n", - "# set 1 5 270 180 {d} {f125} 1.00 {t * 2}\n", - "# set 1 6 180 270 {d} {f125} 1.00 {t * 2}\n", - "# set 1 7 270 180 {d} {f125} 1.00 {t * 2}\n", - "# set 1 8 180 90 {d} {f125} 1.00 {t * 2}\n", - "# set 1 9 90 0 {d} {f125} 1.00 {t * 10}\n", - "# set 4 10\n", - "# start\n", - "# \"\"\"\n", - "# )\n", - "\n", "\n", "SAVE_IMAGES = False\n", "\n", @@ -1694,7 +1621,7 @@ }, { "cell_type": "code", - "execution_count": 80, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ From 552365493ad0e9eddb6b76df334f8af052ac0876 Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:44:53 -0400 Subject: [PATCH 07/11] fixed asymmetry in amp sweeps (needed a slightly longer time) and cleanup on comments in dds-sweeper.c --- dds-sweeper/dds-sweeper.c | 9 +------ testing/tests.ipynb | 49 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/dds-sweeper/dds-sweeper.c b/dds-sweeper/dds-sweeper.c index 6458ced..e1ac211 100644 --- a/dds-sweeper/dds-sweeper.c +++ b/dds-sweeper/dds-sweeper.c @@ -509,7 +509,6 @@ void parse_amp_sweep_ins(uint addr, uint channel, if (start < end) { approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); } else { - // sweep_rate = get_asf(sweep_rate, &delta); approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, 1); } @@ -649,11 +648,8 @@ void parse_freq_sweep_ins(uint addr, uint channel, if (start < end) { approx_bits_per_sync = approx_double_32(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); - } else { - // here your delta is just sweep_rate / 1 approx_bits_per_sync = approx_double_32(bits_per_sync_clk_cycle, &delta, &rate, delta_max, 1); - // sweep_rate = get_ftw(&ad9959, sweep_rate, &delta); } // back to human readable units @@ -664,7 +660,7 @@ void parse_freq_sweep_ins(uint addr, uint channel, delta = 1; sweep_rate = delta * (ad9959.ref_clk * ad9959.pll_mult) / (4 * 4294967296); } - + if (DEBUG) { fast_serial_printf( "Set ins #%d for channel %d from %4lf Hz to %4lf Hz with sweep rate %lf Hz/s\n", @@ -796,7 +792,6 @@ void parse_phase_sweep_ins(uint addr, uint channel, if (start < end) { approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, rate_max); } else { - // sweep_rate = get_pow(sweep_rate, &delta); approx_bits_per_sync = approx_double_16(bits_per_sync_clk_cycle, &delta, &rate, delta_max, 1); } @@ -1002,7 +997,6 @@ void loop() { int parsed = sscanf(readstring, "%*s %lf", &f); uint rate; uint32_t delta; - f_approx = approx_double_32(f, &delta, &rate, 4e6, 255); fast_serial_printf("%lf (%lf)=[%u/%u]\n", f, f_approx, delta, rate); } else if (strncmp(readstring, "approx16", 8) == 0) { @@ -1010,7 +1004,6 @@ void loop() { int parsed = sscanf(readstring, "%*s %lf", &f); uint rate; uint16_t delta; - f_approx = approx_double_16(f, &delta, &rate, 16300, 255); fast_serial_printf("%lf (%lf)=[%u/%u]\n", f, f_approx, delta, rate); } diff --git a/testing/tests.ipynb b/testing/tests.ipynb index 778b9f0..7e92404 100644 --- a/testing/tests.ipynb +++ b/testing/tests.ipynb @@ -637,9 +637,52 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 476, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ok\n", + "ok\n", + "ok\n", + "ok\n", + "ok\n", + "ok\n", + "ok\n", + "ok\n", + "Set ins #0 for channel 0 from 1.000000% to 0.000000% with sweep rate 122070.312500% arb/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #1 for channel 0 from 0.000000% to 0.500489% with sweep rate 122070.312500% arb/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #2 for channel 0 from 0.500489% to 1.000000% with sweep rate 122070.312500% arb/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #3 for channel 0 from 1.000000% to 0.000000% with sweep rate 122070.312500% arb/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #4 for channel 0 from 0.000000% to 1.000000% with sweep rate 122070.312500% arb/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #5 for channel 0 from 1.000000% to 0.500489% with sweep rate 122070.312500% arb/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #6 for channel 0 from 0.500489% to 0.000000% with sweep rate 122070.312500% arb/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "Set ins #7 for channel 0 from 0.000000% to 1.000000% with sweep rate 122070.312500% arb/s\n", + "\ttime: 1.60e-05 s\n", + "ok\n", + "ok\n", + "ok\n", + "\n", + "Success\n" + ] + } + ], "source": [ "my_instrument.annotate_screen(\"Testing Mode 1: Amplitude Sweep\")\n", "# my_instrument.set_time_delay(50e-6)\n", @@ -648,7 +691,7 @@ "# send('reset')\n", "\n", "filename = 'mode1-picostart-ampsweep-test.png'\n", - "t = 200 / (125e6)\n", + "t = 2000 / (125e6)\n", "sweep_rate = .1225e6 # arb / s\n", "\n", "print(send(f\"\"\"mode 1 1\n", From f33e597bae5766cd6057e8e5ed2b9618236f5cd3 Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Tue, 8 Apr 2025 09:24:29 -0400 Subject: [PATCH 08/11] implementing changes --- dds-sweeper/ad9959.c | 1 + dds-sweeper/dds-sweeper.c | 34 ---------------------------------- 2 files changed, 1 insertion(+), 34 deletions(-) diff --git a/dds-sweeper/ad9959.c b/dds-sweeper/ad9959.c index 390c261..bf295c8 100644 --- a/dds-sweeper/ad9959.c +++ b/dds-sweeper/ad9959.c @@ -1,5 +1,6 @@ #include "ad9959.h" #include "fast_serial.h" +#include // ============================================================================= // calculate tuning words diff --git a/dds-sweeper/dds-sweeper.c b/dds-sweeper/dds-sweeper.c index e1ac211..1a33112 100644 --- a/dds-sweeper/dds-sweeper.c +++ b/dds-sweeper/dds-sweeper.c @@ -21,7 +21,6 @@ */ #include -#include #include "fast_serial.h" @@ -516,13 +515,6 @@ void parse_amp_sweep_ins(uint addr, uint channel, // back to human readable units sweep_rate = approx_bits_per_sync / bits_per_arb / t_sync; - if (delta == 0) { - // enforce minimum sweep rate to not be zero - delta = 1; - sweep_rate = delta / 1023.0; - } - - if (DEBUG) { fast_serial_printf( "Set ins #%d for channel %d from %3lf%% to %3lf%% with sweep rate %3lf%% arb/s\n", @@ -655,12 +647,6 @@ void parse_freq_sweep_ins(uint addr, uint channel, // back to human readable units sweep_rate = approx_bits_per_sync / bits_per_hz / t_sync; - if (delta == 0) { - // enforce minimum sweep rate to not be zero - delta = 1; - sweep_rate = delta * (ad9959.ref_clk * ad9959.pll_mult) / (4 * 4294967296); - } - if (DEBUG) { fast_serial_printf( "Set ins #%d for channel %d from %4lf Hz to %4lf Hz with sweep rate %lf Hz/s\n", @@ -798,12 +784,6 @@ void parse_phase_sweep_ins(uint addr, uint channel, // back to human readable units sweep_rate = approx_bits_per_sync / bits_per_deg / t_sync; - if (delta == 0) { - // enforce minimum sweep rate to not be zero - delta = 1; - sweep_rate = delta / 16383.0; - } - if (DEBUG) { fast_serial_printf( "Set ins #%d for channel %d from %4lf deg to %4lf deg with sweep rate %4lf deg/s\n", @@ -992,20 +972,6 @@ void loop() { } else if (strncmp(readstring, "abort", 5) == 0) { abort_run(); OK(); - } else if (strncmp(readstring, "approx32", 8) == 0) { - double f, f_approx; - int parsed = sscanf(readstring, "%*s %lf", &f); - uint rate; - uint32_t delta; - f_approx = approx_double_32(f, &delta, &rate, 4e6, 255); - fast_serial_printf("%lf (%lf)=[%u/%u]\n", f, f_approx, delta, rate); - } else if (strncmp(readstring, "approx16", 8) == 0) { - double f, f_approx; - int parsed = sscanf(readstring, "%*s %lf", &f); - uint rate; - uint16_t delta; - f_approx = approx_double_16(f, &delta, &rate, 16300, 255); - fast_serial_printf("%lf (%lf)=[%u/%u]\n", f, f_approx, delta, rate); } // ==================================================== // Stuff that cannot be done while the table is running From e81bbda4f0b4f866bcfefe684d558af86ea81138 Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Wed, 9 Apr 2025 15:59:58 -0400 Subject: [PATCH 09/11] ensuring phase is within bounds --- dds-sweeper/dds-sweeper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dds-sweeper/dds-sweeper.c b/dds-sweeper/dds-sweeper.c index 1a33112..a488bbb 100644 --- a/dds-sweeper/dds-sweeper.c +++ b/dds-sweeper/dds-sweeper.c @@ -756,7 +756,7 @@ void parse_phase_sweep_ins(uint addr, uint channel, uint32_t ftw; uint rate = 1; - uint16_t delta_max = 16384; + uint16_t delta_max = 16384 - 1; uint16_t rate_max = 255; if (ad9959.sweep_type == PHASE2_MODE) { From f6c61e07ad35c79c3c759ff4e9a1f355a301d102 Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:01:42 -0400 Subject: [PATCH 10/11] updated set description - delta and rate now sweep_rate, checked and seti and setb should be correct, + describe conversion process in SWEEP_DETAILS.md --- README.md | 12 ++++++------ SWEEP_DETAILS.md | 20 +++++++++++++++++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 02fe71f..e183e1b 100644 --- a/README.md +++ b/README.md @@ -168,17 +168,17 @@ Manually set the amplitude scale factor of a specified channel. Channels are 0-3 - `set`: Sets the value of instruction number `addr` for channel `channel` (zero indexed). `addr` starts at 0. It looks different depending on what mode the sweeper is in. If `Debug` is set to `on` it will respond with the actual values set for that instruction. - Single Stepping (mode 0): `set ()` - - Sweep Mode (modes 1-3): `set ()` + - Sweep Mode (modes 1-3): `set ()` - `start_point` is the value the sweep should start from, and `end_point` is where it will stop. `delta` is the amount that the output should change by every cycle of the sweep clock. In the AD9959, the sweep clock runs at one quarter the system clock. The types of values expected for `start_point`, `end_point`, and `delta` different depending on the type of sweep + `start_point` is the value the sweep should start from, and `end_point` is where it will stop. `sweep_rate` is the amount that the output should change in each quantity's units per second (further info below). In the AD9959, the sweep clock runs at one quarter the system clock. The types of values expected for `start_point`, `end_point`, and `sweep_rate` are different depending on the type of sweep: - Amplitude Sweeps (mode 1) - `start_point` and `end_point` should be decimals between 0 and 1 that represent the desired proportion of the maximum output amplitude. `delta` is the desired change in that proportion. For all three of those values there is a resolution of $\frac{1}{1024} \approx 0.09766\$ + `start_point` and `end_point` should be decimals between 0 and 1 that represent the desired proportion of the maximum output amplitude. `sweep_rate` is then that proportion per second. The resolution of the start and end values is $\frac{1}{1024} \approx 0.09766$. - Frequency Sweeps (mode 2) - `start_point`, `end_point`, and `delta` are frequencies in Hz. They can have decimal values, but they will be rounded to the nearest multiple of the frequency resolution. + `start_point` and `end_point` are frequencies in Hz, with `sweep_rate` in Hz per second. The start and end points can have decimal values, but they will be rounded to the nearest multiple of the frequency resolution ($\frac{f_{sysclk}}{2^{32}}$). - Phase Sweeps (mode 3) - `start_point`, `end_point`, and `delta` are in degrees. They can have decimal values, but they will be rounded to the nearest multiple of the phase resolution (always $= 360^\circ / 2^{14} \approx 0.02197^\circ$). + `start_point`, `end_point` are in degrees, with `sweep_rate` in degrees per second. The start and end points can have decimal values, but they will be rounded to the nearest multiple of the phase resolution ($\frac{360^\circ}{2^{14}} \approx 0.02197^\circ$). - - Sweep and Single Stepping Mode (modes 4-6): `set ()` + - Sweep and Single Stepping Mode (modes 4-6): `set ()` These modes perform a linear sweep on one of the parameters, while simultaneously single stepping on the other two parameters. - Amplitude Sweeps (mode 4) diff --git a/SWEEP_DETAILS.md b/SWEEP_DETAILS.md index 71d2481..7f83848 100644 --- a/SWEEP_DETAILS.md +++ b/SWEEP_DETAILS.md @@ -3,7 +3,7 @@ - Setting up a sweep: ![Sweep Setup Figure](img/sweep-setup.png) Sweeps are defined by two parameters, sweep delta and ramp rate. -- Sweep Delta defines the change in output amplitude/frequency/phase on each sweep step +- Sweep Delta defines the change in output amplitude/frequency/phase on each sweep step. - Ramp rate defines how often a sweep step is taken. It is based off of the AD9959's sync clock signal which will be one quarter of the AD9959's system clock. The ramp rate parameter specifies the number of sync clock cycles per sweep step. A ramp rate of 1 will cause the sweep delta to be applied every 1 sync clock cycle. For upward sweeps, the ramp rate parameter can have a value of 1-255. For downward sweeps the ramp rate can only be 1. The time between sweep steps can be calculated with: @@ -11,14 +11,28 @@ $ t = \frac{\textrm{Ramp Rate}}{\textrm{Sync Clock}} $ Using the Pico's 125 Mhz with a 4 times PLL Multiplier gives the AD9959 a system clock of 500 MHz and therefore a sync clock of 125 MHz. For upward sweeps the time between sweeps can range from $\frac{1}{125 MHz} = 8 ns$ to $\frac{255}{125 MHz} = 2.04 \mu s$. Downward sweeps will apply the sweep delta every $\frac{1}{125 MHz} = 8 ns$. -Given the frequency resolution of $\frac{f_{sys clk}}{2^{32}}$, the smallest sweep delta is $= \frac{1}{2^{32}} = 0.1164$ Hz. With the maximum ramp rates, the DDS-sweeper has a minimum sweeping rate of $\approx 47871$ Hz/sec when sweeping upwards or $\approx 12207031.25$ Hz/sec when sweeping downward. +Given the frequency resolution of $\frac{f_{sys clk}}{2^{32}}$, the smallest sweep delta is $\frac{1}{2^{32}} = 0.1164$ Hz. With the maximum ramp rates, the DDS-sweeper has a minimum sweeping rate of $\approx 47871$ Hz/sec when sweeping upwards or $\approx 12207031.25$ Hz/sec when sweeping downward. + +## Finer Sweep Rate Resolution in `set` + +The `set` command will internally calculate the sweep delta and ramp rate by given the user provided `sweep_rate` using the continued fraction algorithm. Given a conversion factor $B$ that allows us to convert a sweep rate $R$ to bits per sync clock cycle, + +$$B_{freq} = \frac{2^{32}}{f_{sysclk}} [\frac{\text{bits}}{\text{Hz}}], B_{amp} = 2^{10} [\frac{\text{bits}}{\text{Arb.}}], B_{phase} = 2^{14}[\frac{\text{bits}}{\text{degree}}],$$ + +the ratio of sweep delta $d$ and ramp rate $r$ can be equated to the following: + +$$ +\frac{d}{r} = B\frac{4R}{f_{sysclk}} +$$. + +The continued fraction algorithm then returns the integer ratio approximation of the desired `sweep_rate` float and therefore set an integer sweep delta and ramp rate. The algorithm will respect the limits of each sweep mode, so the frequency tuning word sweep deltas can be between $0$ and $2^{32}-1$, amplitude scale factor sweep deltas can be between $0$ and $2^{10}$, and phase offset word sweep deltas can be between $0$ and $2^{14}$. The ramp rates for each mode are constrained to be between $1$ and $255$ for upward sweeps, and held to $1$ for downward sweeps. ## Downward Sweeps Downward sweeps are not well supported by the AD9959, but they can still be done. The best method I have found for doing a downward sweep is to send the instructions via serial first, with the sweep autoclear bit set to active and the rising sweep tuning word set to the maximum. Then issue the IO_UPDATE signal while keeping the profile pin for that channel high. -I belive this clears the sweep accumulator then quickly refills it with a max rate sweep before beginning the downward sweep. +I believe this clears the sweep accumulator then quickly refills it with a max rate sweep before beginning the downward sweep. Other combinations of autoclear bit active or not and timing of the profile pins seem to cause even more issues with downward sweeps. The biggest downside of this method is that you cannot slow down the downward sweep ramp rate as much as the upward sweep ramp rate. From d491613f719a92ccaf91b50ed420cdfdca21643d Mon Sep 17 00:00:00 2001 From: Jason Pruitt <55477390+Json-To-String@users.noreply.github.com> Date: Wed, 9 Apr 2025 16:02:59 -0400 Subject: [PATCH 11/11] forgot to delete those old helper function cells here too, deleted now. --- testing/tests.ipynb | 195 ++++---------------------------------------- 1 file changed, 18 insertions(+), 177 deletions(-) diff --git a/testing/tests.ipynb b/testing/tests.ipynb index 7e92404..3493318 100644 --- a/testing/tests.ipynb +++ b/testing/tests.ipynb @@ -637,7 +637,7 @@ }, { "cell_type": "code", - "execution_count": 476, + "execution_count": null, "metadata": {}, "outputs": [ { @@ -655,16 +655,16 @@ "Set ins #0 for channel 0 from 1.000000% to 0.000000% with sweep rate 122070.312500% arb/s\n", "\ttime: 1.60e-05 s\n", "ok\n", - "Set ins #1 for channel 0 from 0.000000% to 0.500489% with sweep rate 122070.312500% arb/s\n", + "Set ins #1 for channel 0 from 0.000000% to 0.500489% with sweep rate 150001.655191% arb/s\n", "\ttime: 1.60e-05 s\n", "ok\n", - "Set ins #2 for channel 0 from 0.500489% to 1.000000% with sweep rate 122070.312500% arb/s\n", + "Set ins #2 for channel 0 from 0.500489% to 1.000000% with sweep rate 150001.655191% arb/s\n", "\ttime: 1.60e-05 s\n", "ok\n", "Set ins #3 for channel 0 from 1.000000% to 0.000000% with sweep rate 122070.312500% arb/s\n", "\ttime: 1.60e-05 s\n", "ok\n", - "Set ins #4 for channel 0 from 0.000000% to 1.000000% with sweep rate 122070.312500% arb/s\n", + "Set ins #4 for channel 0 from 0.000000% to 1.000000% with sweep rate 150001.655191% arb/s\n", "\ttime: 1.60e-05 s\n", "ok\n", "Set ins #5 for channel 0 from 1.000000% to 0.500489% with sweep rate 122070.312500% arb/s\n", @@ -673,7 +673,7 @@ "Set ins #6 for channel 0 from 0.500489% to 0.000000% with sweep rate 122070.312500% arb/s\n", "\ttime: 1.60e-05 s\n", "ok\n", - "Set ins #7 for channel 0 from 0.000000% to 1.000000% with sweep rate 122070.312500% arb/s\n", + "Set ins #7 for channel 0 from 0.000000% to 1.000000% with sweep rate 150001.655191% arb/s\n", "\ttime: 1.60e-05 s\n", "ok\n", "ok\n", @@ -723,52 +723,6 @@ " display(Image(filename))" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "x = 1/255\n", - "print(send(f'approx16 {x}'))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - ".1" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "1/1023" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "send('reset')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "# send('program')" - ] - }, { "cell_type": "code", "execution_count": null, @@ -890,17 +844,9 @@ }, { "cell_type": "code", - "execution_count": 413, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Success\n" - ] - } - ], + "outputs": [], "source": [ "my_instrument.annotate_screen(\"Testing Mode 2: Frequency Sweep\")\n", "# my_instrument.set_time_delay(40e-6)\n", @@ -1018,96 +964,18 @@ }, { "cell_type": "code", - "execution_count": 436, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'ok\\n'" - ] - }, - "execution_count": 436, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "send('reset')" ] }, { "cell_type": "code", - "execution_count": 448, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ok\n", - "ok\n", - "set freq: 99999999.976717\n", - "ok\n", - "set freq: 99999999.976717\n", - "ok\n", - "set freq: 99999999.976717\n", - "ok\n", - "set freq: 99999999.976717\n", - "ok\n", - "Phase: 0.000000\n", - "ok\n", - "Phase: 0.000000\n", - "ok\n", - "Phase: 0.000000\n", - "ok\n", - "Phase: 0.000000\n", - "ok\n", - "ok\n", - "ok\n", - "Set ins #0 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #1 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #2 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #3 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #4 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #5 for channel 0 from 0.000000 deg to 0.000000 deg with sweep rate 29.919194 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #0 for channel 1 from 0.000000 deg to 180.010987 deg with sweep rate 49999.782017 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #1 for channel 1 from 180.010987 deg to 90.005493 deg with sweep rate 53405.761719 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #2 for channel 1 from 90.005493 deg to 0.000000 deg with sweep rate 53405.761719 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #3 for channel 1 from 0.000000 deg to 90.005493 deg with sweep rate 49999.782017 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #4 for channel 1 from 90.005493 deg to 180.010987 deg with sweep rate 49999.782017 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "Set ins #5 for channel 1 from 180.010987 deg to 0.000000 deg with sweep rate 53405.761719 deg/s\n", - "\ttime: 1.60e-05 s\n", - "ok\n", - "ok\n", - "ok\n", - "\n", - "Success\n" - ] - } - ], + "outputs": [], "source": [ "\n", "my_instrument.annotate_screen(\"Testing Mode 3: Phase Sweep\")\n", @@ -1172,7 +1040,7 @@ }, { "cell_type": "code", - "execution_count": 451, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -1258,17 +1126,9 @@ }, { "cell_type": "code", - "execution_count": 454, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Success\n" - ] - } - ], + "outputs": [], "source": [ "my_instrument.annotate_screen(\"Testing set Mode 4: Amplitude Sweep, Single Step Freq, Phase\")\n", "my_instrument.set_time_delay(70e-6)\n", @@ -1399,37 +1259,18 @@ }, { "cell_type": "code", - "execution_count": 461, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "'ok\\n'" - ] - }, - "execution_count": 461, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "send('reset')" ] }, { "cell_type": "code", - "execution_count": 463, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Success\n" - ] - } - ], + "outputs": [], "source": [ "my_instrument.annotate_screen(\"Testing Mode 5: Frequency Sweep, Single Step Amp, Phase\")\n", "my_instrument.set_time_delay(200e-6)\n",