From 5ff15cc9e36b661b2d5a1e2b4883e79b02153f63 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Thu, 5 Nov 2026 15:45:42 +0000 Subject: [PATCH 1/4] Adding Source Waveform example in NI-Digital --- CHANGELOG.md | 1 + docs/nidigital/examples.rst | 9 ++ .../examples/source_waveform/Pattern.digipat | Bin 0 -> 5413 bytes .../source_waveform/PinLevels.digilevels | 15 +++ .../examples/source_waveform/PinMap.pinmap | 51 +++++++++ .../source_waveform/SourceWaveform.tdms | Bin 0 -> 1619 bytes .../source_waveform/Specifications.specs | 9 ++ .../source_waveform/Timing.digitiming | 23 ++++ .../nidigital_source_waveform.py | 100 ++++++++++++++++++ .../source_waveform/source_waveform.digiproj | 39 +++++++ 10 files changed, 247 insertions(+) create mode 100644 src/nidigital/examples/source_waveform/Pattern.digipat create mode 100644 src/nidigital/examples/source_waveform/PinLevels.digilevels create mode 100644 src/nidigital/examples/source_waveform/PinMap.pinmap create mode 100644 src/nidigital/examples/source_waveform/SourceWaveform.tdms create mode 100644 src/nidigital/examples/source_waveform/Specifications.specs create mode 100644 src/nidigital/examples/source_waveform/Timing.digitiming create mode 100644 src/nidigital/examples/source_waveform/nidigital_source_waveform.py create mode 100644 src/nidigital/examples/source_waveform/source_waveform.digiproj diff --git a/CHANGELOG.md b/CHANGELOG.md index 83d1d3267b..7fefe411b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -558,6 +558,7 @@ #### [nidigital] Unreleased - Added - (Common) Added `nitlsconfig[grpc]>=1.0.0a2` to the optional gRPC dependencies. + - Added the `nidigital_source_waveform.py` example. - Changed - Removed diff --git a/docs/nidigital/examples.rst b/docs/nidigital/examples.rst index b8c8cc689a..303dcff661 100644 --- a/docs/nidigital/examples.rst +++ b/docs/nidigital/examples.rst @@ -30,3 +30,12 @@ nidigital_ppmu_source_and_measure.py :encoding: utf8 :caption: `(nidigital_ppmu_source_and_measure.py) `_ +nidigital_source_waveform.py +---------------------------- + +.. literalinclude:: ../../src/nidigital/examples/source_waveform/nidigital_source_waveform.py + :language: python + :linenos: + :encoding: utf8 + :caption: `(nidigital_source_waveform.py) `_ + diff --git a/src/nidigital/examples/source_waveform/Pattern.digipat b/src/nidigital/examples/source_waveform/Pattern.digipat new file mode 100644 index 0000000000000000000000000000000000000000..0ee9d4fef983edd6c923bfa0c4eeb74e1a9f9bf2 GIT binary patch literal 5413 zcmcgwTXP#V6y9(x<&uWN3^Ux6;bDhPr*2vb<=zk%aGTOh?KV7-S=(}~va2<+T(@uG zjTv6~A^Zz|Ryp79IgXsz9dCj;6XjdW(sw>dM@L$>>dow>D2mLRQPd`c39isHO6@7x z3-o|ulT0hZm#OR|-fL%HrN^!wcAOb_lUsZXdy$GaJ}sJ~0)CQ_@8?e8BUvl(ezB~I z1gE^?L+BkYtsd_UN(CX$W#$n)#&ez;Y~|U&q`JFneE)%VLz0aFk)02@J}&Db!DC#n zQ3LLOCwZ7Vkf70tNsOIM@+B(~Jf`FWYH-I`lZ`SAF7c+F>bf(Jw3{B_N~lff1Q(;d z*)=|Y7VQ_TR`3|@`_!PGkL|uox_UQp*4X{KwwXNAQ)17pg<@qz1;P3Xm0J9xCK?wb zPEk20Ai?zpeT`T*gfKyLLtsp}YB5b?rmc_PqiRJ3O^(`gR58aJsz=uNy`gtBI>lYX z0c~)dAUvF#WM!|4N-< zf*^aFN-Y+$;^_yMj|NLzf7wiekn!#u8QgzNqil2*<_1R-R7u8@1Wr=7MP-7Tb`Av%bi?lf^sBM4?Bk8ny$MWHb^x-Ll+cnk_~!SJ*cqWL4A< zB4HePrIcMNUcTk#=w5MSh(~6aN=0&Q-VEs1={bzC!+kd=+@~CbiLS}4^?0mN4~yOrNCCy;L=|GfAp; z>2$5_Xu569jj7lfZ8$X`T;4H&@wBjS+4Zh-z*f zVFQPBSNMzY0H@$ literal 0 HcmV?d00001 diff --git a/src/nidigital/examples/source_waveform/PinLevels.digilevels b/src/nidigital/examples/source_waveform/PinLevels.digilevels new file mode 100644 index 0000000000..1908b117fa --- /dev/null +++ b/src/nidigital/examples/source_waveform/PinLevels.digilevels @@ -0,0 +1,15 @@ + + + + + + 0 + 3.3 + 0.8 + 2 + 0 + HighZ + + + + \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/PinMap.pinmap b/src/nidigital/examples/source_waveform/PinMap.pinmap new file mode 100644 index 0000000000..46d985a9f9 --- /dev/null +++ b/src/nidigital/examples/source_waveform/PinMap.pinmap @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/SourceWaveform.tdms b/src/nidigital/examples/source_waveform/SourceWaveform.tdms new file mode 100644 index 0000000000000000000000000000000000000000..4f85ffcdff1deaa6c969a39131b2c23dc77153ea GIT binary patch literal 1619 zcmeHHO-sW-5RD&IL{L!CYi_yq<6_T-C{~CTQtdG;$=VJyA8fYv>Oa>vX%^N(iQ=^b z!`sg8yf?ee%p{1iBgb**0uE#|xQ8`+?+bQ_1$!pH-QL$8soQexlM{)z>w2n!!^{*zbxRh zN!h{f1?(=lZ=Sg4*rKsxin46R#R-UfRfseZm9|wzwT9yuY*E>`$@-ZdFqnmQ!BqdzGNJ6} bRs2T8V2cRmsr_7UQdP~Y?_g)p?RWd%nF`^h literal 0 HcmV?d00001 diff --git a/src/nidigital/examples/source_waveform/Specifications.specs b/src/nidigital/examples/source_waveform/Specifications.specs new file mode 100644 index 0000000000..65c615cfd6 --- /dev/null +++ b/src/nidigital/examples/source_waveform/Specifications.specs @@ -0,0 +1,9 @@ + + +
+ + 1 µs + +
+ +
\ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/Timing.digitiming b/src/nidigital/examples/source_waveform/Timing.digitiming new file mode 100644 index 0000000000..b5908eabfb --- /dev/null +++ b/src/nidigital/examples/source_waveform/Timing.digitiming @@ -0,0 +1,23 @@ + + + + + + timing.period + + + + 0 ns + timing.period / 2 + timing.period + + + (3 * timing.period) / 4 + + Pattern + + + + + + \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/nidigital_source_waveform.py b/src/nidigital/examples/source_waveform/nidigital_source_waveform.py new file mode 100644 index 0000000000..266d731ca5 --- /dev/null +++ b/src/nidigital/examples/source_waveform/nidigital_source_waveform.py @@ -0,0 +1,100 @@ +#!/usr/bin/python + +import argparse +import nidigital +import os +import sys + + +def example(resource_name, options, source_waveform_type='PARALLEL', data_mapping='BROADCAST', waveform_name='new_waveform', start_label='new_pattern', + parallel_channel_list='PinGroup1', serial_channel_list='DUTPin1', sample_width=32, bit_order='MSB', waveform_file=None, write_waveform_data=True): + + with nidigital.Session(resource_name=resource_name, options=options) as session: + + dir = os.path.join(os.path.dirname(__file__)) + if waveform_file is None: + waveform_file = os.path.join(dir, 'SourceWaveform.tdms') + + session.load_pin_map(os.path.join(dir, 'PinMap.pinmap')) + + spec_filename = os.path.join(dir, 'Specifications.specs') + levels_filename = os.path.join(dir, 'PinLevels.digilevels') + timing_filename = os.path.join(dir, 'Timing.digitiming') + session.load_specifications_levels_and_timing(spec_filename, levels_filename, timing_filename) + + session.apply_levels_and_timing(levels_filename, timing_filename) + + session.load_pattern(os.path.join(dir, 'Pattern.digipat')) + + mapping = nidigital.SourceDataMapping[data_mapping] + + # Configure the source waveform type + if source_waveform_type == 'PARALLEL': + session.pins[parallel_channel_list].create_source_waveform_parallel(waveform_name, mapping) + elif source_waveform_type == 'SERIAL': + session.pins[serial_channel_list].create_source_waveform_serial(waveform_name, mapping, sample_width, nidigital.BitOrder[bit_order]) + elif source_waveform_type == 'TDMS': + # Waveform configuration and data are read from the TDMS file + session.create_source_waveform_from_file_tdms(waveform_name, waveform_file, write_waveform_data) + + # Write the source waveform data + if source_waveform_type != 'TDMS': + # Placeholder ramp data for illustration; replace with your own waveform samples + sample_count = 2 ** min(sample_width, 8) if source_waveform_type == 'SERIAL' else 256 + samples = [i % sample_count for i in range(sample_count)] + if mapping == nidigital.SourceDataMapping.BROADCAST: + session.write_source_waveform_broadcast(waveform_name, samples) + else: + # Site-unique data is a dict of site number to samples; both sites use the same placeholder data here + session.write_source_waveform_site_unique(waveform_name, {0: samples, 1: samples}) + + print('Start bursting pattern') + session.burst_pattern(start_label=start_label) + + session.selected_function = nidigital.SelectedFunction.DISCONNECT + print('Done bursting pattern') + + +def _main(argsv): + parser = argparse.ArgumentParser(description='Demonstrates how to configure, write, and burst a source waveform using NI-Digital source memory.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-n', '--resource-name', default='PXI1Slot2,PXI1Slot3', help='The specified resource name shown in Measurement & Automation Explorer (MAX) for a digital pattern instrument, for example, PXI1Slot3, where PXI1Slot3 is an instrument resource name.') + parser.add_argument('-s', '--simulate', default='True', choices=['True', 'False'], help='Whether to run on simulated hardware or real hardware') + parser.add_argument('-w', '--waveform-name', default='new_waveform', help='The name to assign to the waveform. Use the waveform_name with source_start opcode in your pattern.') + parser.add_argument('-l', '--start-label', default='new_pattern', help='Pattern name or exported pattern label from which to start bursting the pattern.') + parser.add_argument('-d', '--data-mapping', default='BROADCAST', choices=nidigital.SourceDataMapping.__members__.keys(), type=str.upper, help='Parameter that specifies how to map data on multiple sites.') + parser.add_argument('-t', '--source-waveform-type', default='PARALLEL', choices=['PARALLEL', 'SERIAL', 'TDMS'], type=str.upper, help='Type of source waveform to configure.') + parser.add_argument('--parallel-channel-list', default='PinGroup1', help='Pins that source data for a parallel waveform.') + parser.add_argument('--serial-channel-list', default='DUTPin1', help='Pins that source data for a serial waveform.') + parser.add_argument('--sample-width', default=32, type=int, help='Width in bits of each serial sample. Valid values are between 1 and 32.') + parser.add_argument('--bit-order', default='MSB', choices=nidigital.BitOrder.__members__.keys(), type=str.upper, help='Order in which to shift the bits.') + parser.add_argument('--waveform-file', default=None, help='Absolute file path to the load source waveform file (.tdms). Defaults to SourceWaveform.tdms next to this example.') + parser.add_argument('--write-waveform-data', default='True', choices=['True', 'False'], help='A Boolean that writes waveform data to source memory if True and the waveform data is in the file.') + args = parser.parse_args(argsv) + + example(args.resource_name, + 'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '', + args.source_waveform_type, args.data_mapping, args.waveform_name, args.start_label, + args.parallel_channel_list, args.serial_channel_list, args.sample_width, args.bit_order, + args.waveform_file, args.write_waveform_data == 'True') + + +def main(): + _main(sys.argv[1:]) + + +def test_main(): + _main([]) + _main(['--source-waveform-type', 'SERIAL', '--data-mapping', 'SITE_UNIQUE']) + _main(['--source-waveform-type', 'TDMS']) + + +def test_example(): + resource_name = 'PXI1Slot2,PXI1Slot3' + options = {'simulate': True, 'driver_setup': {'Model': '6571'}, } + example(resource_name, options) + example(resource_name, options, 'SERIAL', 'SITE_UNIQUE') + example(resource_name, options, 'TDMS') + + +if __name__ == '__main__': + main() diff --git a/src/nidigital/examples/source_waveform/source_waveform.digiproj b/src/nidigital/examples/source_waveform/source_waveform.digiproj new file mode 100644 index 0000000000..971b8ff9b9 --- /dev/null +++ b/src/nidigital/examples/source_waveform/source_waveform.digiproj @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From b151b5e8b7604a4af3dfd2d50237b939146de0b8 Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Thu, 5 Nov 2026 15:46:25 +0000 Subject: [PATCH 2/4] Revert "Adding Source Waveform example in NI-Digital" This reverts commit 5ff15cc9e36b661b2d5a1e2b4883e79b02153f63. --- CHANGELOG.md | 1 - docs/nidigital/examples.rst | 9 -- .../examples/source_waveform/Pattern.digipat | Bin 5413 -> 0 bytes .../source_waveform/PinLevels.digilevels | 15 --- .../examples/source_waveform/PinMap.pinmap | 51 --------- .../source_waveform/SourceWaveform.tdms | Bin 1619 -> 0 bytes .../source_waveform/Specifications.specs | 9 -- .../source_waveform/Timing.digitiming | 23 ---- .../nidigital_source_waveform.py | 100 ------------------ .../source_waveform/source_waveform.digiproj | 39 ------- 10 files changed, 247 deletions(-) delete mode 100644 src/nidigital/examples/source_waveform/Pattern.digipat delete mode 100644 src/nidigital/examples/source_waveform/PinLevels.digilevels delete mode 100644 src/nidigital/examples/source_waveform/PinMap.pinmap delete mode 100644 src/nidigital/examples/source_waveform/SourceWaveform.tdms delete mode 100644 src/nidigital/examples/source_waveform/Specifications.specs delete mode 100644 src/nidigital/examples/source_waveform/Timing.digitiming delete mode 100644 src/nidigital/examples/source_waveform/nidigital_source_waveform.py delete mode 100644 src/nidigital/examples/source_waveform/source_waveform.digiproj diff --git a/CHANGELOG.md b/CHANGELOG.md index 7fefe411b8..83d1d3267b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -558,7 +558,6 @@ #### [nidigital] Unreleased - Added - (Common) Added `nitlsconfig[grpc]>=1.0.0a2` to the optional gRPC dependencies. - - Added the `nidigital_source_waveform.py` example. - Changed - Removed diff --git a/docs/nidigital/examples.rst b/docs/nidigital/examples.rst index 303dcff661..b8c8cc689a 100644 --- a/docs/nidigital/examples.rst +++ b/docs/nidigital/examples.rst @@ -30,12 +30,3 @@ nidigital_ppmu_source_and_measure.py :encoding: utf8 :caption: `(nidigital_ppmu_source_and_measure.py) `_ -nidigital_source_waveform.py ----------------------------- - -.. literalinclude:: ../../src/nidigital/examples/source_waveform/nidigital_source_waveform.py - :language: python - :linenos: - :encoding: utf8 - :caption: `(nidigital_source_waveform.py) `_ - diff --git a/src/nidigital/examples/source_waveform/Pattern.digipat b/src/nidigital/examples/source_waveform/Pattern.digipat deleted file mode 100644 index 0ee9d4fef983edd6c923bfa0c4eeb74e1a9f9bf2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5413 zcmcgwTXP#V6y9(x<&uWN3^Ux6;bDhPr*2vb<=zk%aGTOh?KV7-S=(}~va2<+T(@uG zjTv6~A^Zz|Ryp79IgXsz9dCj;6XjdW(sw>dM@L$>>dow>D2mLRQPd`c39isHO6@7x z3-o|ulT0hZm#OR|-fL%HrN^!wcAOb_lUsZXdy$GaJ}sJ~0)CQ_@8?e8BUvl(ezB~I z1gE^?L+BkYtsd_UN(CX$W#$n)#&ez;Y~|U&q`JFneE)%VLz0aFk)02@J}&Db!DC#n zQ3LLOCwZ7Vkf70tNsOIM@+B(~Jf`FWYH-I`lZ`SAF7c+F>bf(Jw3{B_N~lff1Q(;d z*)=|Y7VQ_TR`3|@`_!PGkL|uox_UQp*4X{KwwXNAQ)17pg<@qz1;P3Xm0J9xCK?wb zPEk20Ai?zpeT`T*gfKyLLtsp}YB5b?rmc_PqiRJ3O^(`gR58aJsz=uNy`gtBI>lYX z0c~)dAUvF#WM!|4N-< zf*^aFN-Y+$;^_yMj|NLzf7wiekn!#u8QgzNqil2*<_1R-R7u8@1Wr=7MP-7Tb`Av%bi?lf^sBM4?Bk8ny$MWHb^x-Ll+cnk_~!SJ*cqWL4A< zB4HePrIcMNUcTk#=w5MSh(~6aN=0&Q-VEs1={bzC!+kd=+@~CbiLS}4^?0mN4~yOrNCCy;L=|GfAp; z>2$5_Xu569jj7lfZ8$X`T;4H&@wBjS+4Zh-z*f zVFQPBSNMzY0H@$ diff --git a/src/nidigital/examples/source_waveform/PinLevels.digilevels b/src/nidigital/examples/source_waveform/PinLevels.digilevels deleted file mode 100644 index 1908b117fa..0000000000 --- a/src/nidigital/examples/source_waveform/PinLevels.digilevels +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - 0 - 3.3 - 0.8 - 2 - 0 - HighZ - - - - \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/PinMap.pinmap b/src/nidigital/examples/source_waveform/PinMap.pinmap deleted file mode 100644 index 46d985a9f9..0000000000 --- a/src/nidigital/examples/source_waveform/PinMap.pinmap +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/SourceWaveform.tdms b/src/nidigital/examples/source_waveform/SourceWaveform.tdms deleted file mode 100644 index 4f85ffcdff1deaa6c969a39131b2c23dc77153ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1619 zcmeHHO-sW-5RD&IL{L!CYi_yq<6_T-C{~CTQtdG;$=VJyA8fYv>Oa>vX%^N(iQ=^b z!`sg8yf?ee%p{1iBgb**0uE#|xQ8`+?+bQ_1$!pH-QL$8soQexlM{)z>w2n!!^{*zbxRh zN!h{f1?(=lZ=Sg4*rKsxin46R#R-UfRfseZm9|wzwT9yuY*E>`$@-ZdFqnmQ!BqdzGNJ6} bRs2T8V2cRmsr_7UQdP~Y?_g)p?RWd%nF`^h diff --git a/src/nidigital/examples/source_waveform/Specifications.specs b/src/nidigital/examples/source_waveform/Specifications.specs deleted file mode 100644 index 65c615cfd6..0000000000 --- a/src/nidigital/examples/source_waveform/Specifications.specs +++ /dev/null @@ -1,9 +0,0 @@ - - -
- - 1 µs - -
- -
\ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/Timing.digitiming b/src/nidigital/examples/source_waveform/Timing.digitiming deleted file mode 100644 index b5908eabfb..0000000000 --- a/src/nidigital/examples/source_waveform/Timing.digitiming +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - timing.period - - - - 0 ns - timing.period / 2 - timing.period - - - (3 * timing.period) / 4 - - Pattern - - - - - - \ No newline at end of file diff --git a/src/nidigital/examples/source_waveform/nidigital_source_waveform.py b/src/nidigital/examples/source_waveform/nidigital_source_waveform.py deleted file mode 100644 index 266d731ca5..0000000000 --- a/src/nidigital/examples/source_waveform/nidigital_source_waveform.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/python - -import argparse -import nidigital -import os -import sys - - -def example(resource_name, options, source_waveform_type='PARALLEL', data_mapping='BROADCAST', waveform_name='new_waveform', start_label='new_pattern', - parallel_channel_list='PinGroup1', serial_channel_list='DUTPin1', sample_width=32, bit_order='MSB', waveform_file=None, write_waveform_data=True): - - with nidigital.Session(resource_name=resource_name, options=options) as session: - - dir = os.path.join(os.path.dirname(__file__)) - if waveform_file is None: - waveform_file = os.path.join(dir, 'SourceWaveform.tdms') - - session.load_pin_map(os.path.join(dir, 'PinMap.pinmap')) - - spec_filename = os.path.join(dir, 'Specifications.specs') - levels_filename = os.path.join(dir, 'PinLevels.digilevels') - timing_filename = os.path.join(dir, 'Timing.digitiming') - session.load_specifications_levels_and_timing(spec_filename, levels_filename, timing_filename) - - session.apply_levels_and_timing(levels_filename, timing_filename) - - session.load_pattern(os.path.join(dir, 'Pattern.digipat')) - - mapping = nidigital.SourceDataMapping[data_mapping] - - # Configure the source waveform type - if source_waveform_type == 'PARALLEL': - session.pins[parallel_channel_list].create_source_waveform_parallel(waveform_name, mapping) - elif source_waveform_type == 'SERIAL': - session.pins[serial_channel_list].create_source_waveform_serial(waveform_name, mapping, sample_width, nidigital.BitOrder[bit_order]) - elif source_waveform_type == 'TDMS': - # Waveform configuration and data are read from the TDMS file - session.create_source_waveform_from_file_tdms(waveform_name, waveform_file, write_waveform_data) - - # Write the source waveform data - if source_waveform_type != 'TDMS': - # Placeholder ramp data for illustration; replace with your own waveform samples - sample_count = 2 ** min(sample_width, 8) if source_waveform_type == 'SERIAL' else 256 - samples = [i % sample_count for i in range(sample_count)] - if mapping == nidigital.SourceDataMapping.BROADCAST: - session.write_source_waveform_broadcast(waveform_name, samples) - else: - # Site-unique data is a dict of site number to samples; both sites use the same placeholder data here - session.write_source_waveform_site_unique(waveform_name, {0: samples, 1: samples}) - - print('Start bursting pattern') - session.burst_pattern(start_label=start_label) - - session.selected_function = nidigital.SelectedFunction.DISCONNECT - print('Done bursting pattern') - - -def _main(argsv): - parser = argparse.ArgumentParser(description='Demonstrates how to configure, write, and burst a source waveform using NI-Digital source memory.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) - parser.add_argument('-n', '--resource-name', default='PXI1Slot2,PXI1Slot3', help='The specified resource name shown in Measurement & Automation Explorer (MAX) for a digital pattern instrument, for example, PXI1Slot3, where PXI1Slot3 is an instrument resource name.') - parser.add_argument('-s', '--simulate', default='True', choices=['True', 'False'], help='Whether to run on simulated hardware or real hardware') - parser.add_argument('-w', '--waveform-name', default='new_waveform', help='The name to assign to the waveform. Use the waveform_name with source_start opcode in your pattern.') - parser.add_argument('-l', '--start-label', default='new_pattern', help='Pattern name or exported pattern label from which to start bursting the pattern.') - parser.add_argument('-d', '--data-mapping', default='BROADCAST', choices=nidigital.SourceDataMapping.__members__.keys(), type=str.upper, help='Parameter that specifies how to map data on multiple sites.') - parser.add_argument('-t', '--source-waveform-type', default='PARALLEL', choices=['PARALLEL', 'SERIAL', 'TDMS'], type=str.upper, help='Type of source waveform to configure.') - parser.add_argument('--parallel-channel-list', default='PinGroup1', help='Pins that source data for a parallel waveform.') - parser.add_argument('--serial-channel-list', default='DUTPin1', help='Pins that source data for a serial waveform.') - parser.add_argument('--sample-width', default=32, type=int, help='Width in bits of each serial sample. Valid values are between 1 and 32.') - parser.add_argument('--bit-order', default='MSB', choices=nidigital.BitOrder.__members__.keys(), type=str.upper, help='Order in which to shift the bits.') - parser.add_argument('--waveform-file', default=None, help='Absolute file path to the load source waveform file (.tdms). Defaults to SourceWaveform.tdms next to this example.') - parser.add_argument('--write-waveform-data', default='True', choices=['True', 'False'], help='A Boolean that writes waveform data to source memory if True and the waveform data is in the file.') - args = parser.parse_args(argsv) - - example(args.resource_name, - 'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '', - args.source_waveform_type, args.data_mapping, args.waveform_name, args.start_label, - args.parallel_channel_list, args.serial_channel_list, args.sample_width, args.bit_order, - args.waveform_file, args.write_waveform_data == 'True') - - -def main(): - _main(sys.argv[1:]) - - -def test_main(): - _main([]) - _main(['--source-waveform-type', 'SERIAL', '--data-mapping', 'SITE_UNIQUE']) - _main(['--source-waveform-type', 'TDMS']) - - -def test_example(): - resource_name = 'PXI1Slot2,PXI1Slot3' - options = {'simulate': True, 'driver_setup': {'Model': '6571'}, } - example(resource_name, options) - example(resource_name, options, 'SERIAL', 'SITE_UNIQUE') - example(resource_name, options, 'TDMS') - - -if __name__ == '__main__': - main() diff --git a/src/nidigital/examples/source_waveform/source_waveform.digiproj b/src/nidigital/examples/source_waveform/source_waveform.digiproj deleted file mode 100644 index 971b8ff9b9..0000000000 --- a/src/nidigital/examples/source_waveform/source_waveform.digiproj +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 7cd4a8385bb5fcd8b367bfc09949b3512c37980b Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Thu, 12 Nov 2026 10:16:47 +0000 Subject: [PATCH 3/4] Adding Unload and Reload Specification File example in NI_Digital --- CHANGELOG.md | 1 + docs/nidigital/examples.rst | 9 ++ .../PinLevels.digilevels | 14 ++ .../PinMap.pinmap | 30 +++++ .../Shmoo.digishmoo | 14 ++ .../Specifications.specs | 25 ++++ .../Timing.digitiming | 41 ++++++ .../demo_pattern_no_hw.digipat | Bin 0 -> 5464 bytes .../demo_src_wfm.tdms | Bin 0 -> 1231 bytes .../demo_waveform.digicapture | Bin 0 -> 797 bytes ...l_unload_and_reload_specifications_file.py | 127 ++++++++++++++++++ ...ad_and_reload_specifications_file.digiproj | 41 ++++++ 12 files changed, 302 insertions(+) create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/PinLevels.digilevels create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/PinMap.pinmap create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/Shmoo.digishmoo create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/Specifications.specs create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/Timing.digitiming create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/demo_pattern_no_hw.digipat create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/demo_src_wfm.tdms create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/demo_waveform.digicapture create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py create mode 100644 src/nidigital/examples/unload_and_reload_specifications_file/unload_and_reload_specifications_file.digiproj diff --git a/CHANGELOG.md b/CHANGELOG.md index 743a0d082c..eb81047ee5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -558,6 +558,7 @@ #### [nidigital] Unreleased - Added - (Common) Added `nitlsconfig[grpc]>=1.0.0a2` to the optional gRPC dependencies. + - Added the `nidigital_unload_and_reload_specifications_file.py` example. - Changed - Removed diff --git a/docs/nidigital/examples.rst b/docs/nidigital/examples.rst index b8c8cc689a..916896d3c3 100644 --- a/docs/nidigital/examples.rst +++ b/docs/nidigital/examples.rst @@ -30,3 +30,12 @@ nidigital_ppmu_source_and_measure.py :encoding: utf8 :caption: `(nidigital_ppmu_source_and_measure.py) `_ +nidigital_unload_and_reload_specifications_file.py +-------------------------------------------------- + +.. literalinclude:: ../../src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py + :language: python + :linenos: + :encoding: utf8 + :caption: `(nidigital_unload_and_reload_specifications_file.py) `_ + diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/PinLevels.digilevels b/src/nidigital/examples/unload_and_reload_specifications_file/PinLevels.digilevels new file mode 100644 index 0000000000..cb4f7c3fe7 --- /dev/null +++ b/src/nidigital/examples/unload_and_reload_specifications_file/PinLevels.digilevels @@ -0,0 +1,14 @@ + + + + + + 0 + DC.Vdd + DC.Vol + DC.Voh + HighZ + + + + \ No newline at end of file diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/PinMap.pinmap b/src/nidigital/examples/unload_and_reload_specifications_file/PinMap.pinmap new file mode 100644 index 0000000000..b7f4156dde --- /dev/null +++ b/src/nidigital/examples/unload_and_reload_specifications_file/PinMap.pinmap @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/Shmoo.digishmoo b/src/nidigital/examples/unload_and_reload_specifications_file/Shmoo.digishmoo new file mode 100644 index 0000000000..e026b0ea38 --- /dev/null +++ b/src/nidigital/examples/unload_and_reload_specifications_file/Shmoo.digishmoo @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/Specifications.specs b/src/nidigital/examples/unload_and_reload_specifications_file/Specifications.specs new file mode 100644 index 0000000000..2a23605d5a --- /dev/null +++ b/src/nidigital/examples/unload_and_reload_specifications_file/Specifications.specs @@ -0,0 +1,25 @@ + + +
+ + 5.250000E+0 + + + DC.Vdd - 1 + + + 0.4 + +
+
+ + 100 M + + + 1 / AC.Frequency + + + 0.4*AC.Period + +
+
\ No newline at end of file diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/Timing.digitiming b/src/nidigital/examples/unload_and_reload_specifications_file/Timing.digitiming new file mode 100644 index 0000000000..283940d591 --- /dev/null +++ b/src/nidigital/examples/unload_and_reload_specifications_file/Timing.digitiming @@ -0,0 +1,41 @@ + + + + + + AC.Period + + + + AC.Period + 1.25*AC.Period + 1.75*AC.Period + 2*AC.Period + + + AC.Strobe + + Pattern + we are sourcing and capturing on the same pin, so we move the drive edges into the subsequent vector period + + + + + 3 µs + + + + 0 + 0 + AC.Period + + + AC.Strobe + + Pattern + + + + + + \ No newline at end of file diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/demo_pattern_no_hw.digipat b/src/nidigital/examples/unload_and_reload_specifications_file/demo_pattern_no_hw.digipat new file mode 100644 index 0000000000000000000000000000000000000000..456d171a1ef5e50773f10da4d577435596ce66e9 GIT binary patch literal 5464 zcmcgw-EJF26yCO&^52F60`WJwS|L?6Tp;l$h>1h7Xwy<#DO_2b-Elna?u;3a!4=6e*q#&gFQ6>x1A0^I7tNYsYhtucFx8u~RkyA#aBCJ8hDVLWm@d7TBi5nU# z@Rh6=2zkGH6*0~U!Iv9UwoNfoxy&9aH{6qUOzy5$?QVoz?|Cl9Gh8oF1>gQ|^2k__ zpwhWXlwM5osaL{yM#(!=;jYrEm=x$-;?#aF+g2S)JKw=ep*E&tT#a@oQ_lPo?I&I> z;~CnwsY2UK^?^+?`7p6s>4ST^n;gnHvDY_3u{@%TV11TKGyYl(V$8UjF@>>^+Qo0tYe5B7PTOUAvBVo*PqcFVv9r`W;hTmX`oO=I0YEtsY-=TF*0_ozzs^5QN#$Y>r|St=c+AkSjdo!JpPPOQ02jWr8`a*>*T>> zY7Aop8DiUvnXG)eZOvpxmUpm6!xrDN=}R(>o}D{1&M zp|o&ADdbU7jOe1e*SRUilo%=%bpOKbQjFUyqb=`Rh6*A-+942YKY7lDT4fjg$HkJ@i=&scR#bcG&57u=l-WyzeA^2*B_(zo7k+asd3&U(lBhcK}rY_pJsePJhCz9t$A zDq+S4i|fMWj2(K4xma*V(+`sH2}{dDbe^m9Kt zIr-ySbTW6kWIv4P$p)2X+%*%M(w`KEazOW#RSucl2j0XOpG5H#XKgo3R&t+u0^2G- zt8uEL`R_`2OmQb>!=bqR18;28{&Y|vcW^MqZI*BUjA)OohfbT-vUZ+O@A literal 0 HcmV?d00001 diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/demo_src_wfm.tdms b/src/nidigital/examples/unload_and_reload_specifications_file/demo_src_wfm.tdms new file mode 100644 index 0000000000000000000000000000000000000000..a68d55da8b82f73ed706a7089fcce8ea168552c9 GIT binary patch literal 1231 zcmWG>3C?9>U|`4;Vqi!I(jWk%8G&pN*8dL#EIKGD~v6dO!jo%MwdVGV+TQKwKaQL2`l_M2G=KgRJKV zVtsXFyVOAr0!iVp6l5YFP#WZ^R3HrkFdC#y9Ej0O)K@RgEJ-y`7XeDK12IS$3@`y1 zIBWt5m*!=b#21$oW#*+TK(!z{U^`UI97>bm0GM$goyYIDIF{|ar%<&=He}1k=~@OU zFZ0e8WL|pS)pPXN?ugQmCr<@WJeVwSIR4Or;J4O)!_U`WGT-FqvBjg&ai&hmLP5dM zl~YVve!Fb>dU8hN6P?9dr)=M|RXXC@qoVSNQS8M0v5Dz4MlOedIB? zu)2Iz literal 0 HcmV?d00001 diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/demo_waveform.digicapture b/src/nidigital/examples/unload_and_reload_specifications_file/demo_waveform.digicapture new file mode 100644 index 0000000000000000000000000000000000000000..4aa8a001645d751aad208049b1596186bdf48d3d GIT binary patch literal 797 zcmbtSO-sZu5RLeC5J435n%mxX*OTY1L8!30(Bd9T*hV|hv`ZTG=j)qp1KER=#RtPn zCh2=Ko#ZOBXF>?N7NP<(0v}<`G5Y~du;6I4H4=P@D2;84Z~bN7TW2r&M7MFY_0%?e zhjEJV(;POzK)^i}I5Z-G3j;bE5&f!Y5GF`Mj}O}HdJ`@=PsRD)#TG07X;e@P2P zAGFfGSW%ODV>^j7HtXiGw(RH2v(1bnUB@QR>;MEl&}7%b6P}p%5;EL}G8?k{ bE{{kv0*|@i!N;w<8P^TZmZy9_olob#QI4yg literal 0 HcmV?d00001 diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py b/src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py new file mode 100644 index 0000000000..d8652023e1 --- /dev/null +++ b/src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py @@ -0,0 +1,127 @@ +#!/usr/bin/python + +import argparse +import nidigital +import os +import random +import shutil +import sys +import tempfile +from xml.etree import ElementTree + +SPECS_NAMESPACE = 'http://www.ni.com/schemas/Semiconductor/Specifications.xsd' +FORMULA_NAMESPACE = 'http://www.ni.com/schemas/Semiconductor/Formula.xsd' +NAMESPACES = {'s': SPECS_NAMESPACE, 'f': FORMULA_NAMESPACE} +ElementTree.register_namespace('', SPECS_NAMESPACE) +ElementTree.register_namespace('f', FORMULA_NAMESPACE) + +SOURCE_WAVEFORM_NAME = 'demo_src_wfm' +CAPTURE_WAVEFORM_NAME = 'demo_waveform' +SOURCE_PIN = 'SDATA' +SAMPLE_WIDTH = 32 +NUMBER_OF_SAMPLES = 32 + + +def _sweep_values(start, stop, steps): + if steps == 1: + return [start] + return [start + i * (stop - start) / (steps - 1) for i in range(steps)] + + +def _update_specification_values(specs_file_path, new_values): + # new_values maps '
.' to the new definition for that specification + tree = ElementTree.parse(specs_file_path) + for spec_name, value in new_values.items(): + section_name, symbol = spec_name.split('.') + definition = tree.find("s:Section[@name='{}']/f:Formula[@symbol='{}']/f:Definition".format(section_name, symbol), NAMESPACES) + definition.text = repr(value) + tree.write(specs_file_path, encoding='utf-8', xml_declaration=True) + + +def _count_mismatched_bits(expected, actual): + return sum(bin(e ^ a).count('1') for e, a in zip(expected, actual)) + + +def example(resource_name, options, x_spec_name, x_start, x_stop, x_steps, y_spec_name, y_start, y_stop, y_steps): + dir = os.path.join(os.path.dirname(__file__)) + + pin_map_filename = os.path.join(dir, 'PinMap.pinmap') + pattern_filename = os.path.join(dir, 'demo_pattern_no_hw.digipat') + capture_waveform_filename = os.path.join(dir, 'demo_waveform.digicapture') + original_spec_filename = os.path.join(dir, 'Specifications.specs') + levels_filename = os.path.join(dir, 'PinLevels.digilevels') + timing_filename = os.path.join(dir, 'Timing.digitiming') + + # Work on a temporary copy so the specifications file shipped with the example is never modified + with tempfile.TemporaryDirectory() as temp_dir, \ + nidigital.Session(resource_name=resource_name, options=options) as session: + spec_filename = os.path.join(temp_dir, 'Specifications.specs') + shutil.copy(original_spec_filename, spec_filename) + + session.load_pin_map(pin_map_filename) + session.load_pattern(pattern_filename) + + # Source random data; reg0 sets the number of source and capture loops used by the pattern + source_data = [random.getrandbits(SAMPLE_WIDTH) for _ in range(NUMBER_OF_SAMPLES)] + session.write_sequencer_register(nidigital.SequencerRegister.REGISTER0, len(source_data) * SAMPLE_WIDTH) + session.pins[SOURCE_PIN].create_source_waveform_serial(SOURCE_WAVEFORM_NAME, nidigital.SourceDataMapping.BROADCAST, SAMPLE_WIDTH, nidigital.BitOrder.MSB) + session.write_source_waveform_broadcast(SOURCE_WAVEFORM_NAME, source_data) + + session.create_capture_waveform_from_file_digicapture(CAPTURE_WAVEFORM_NAME, capture_waveform_filename) + + session.load_specifications_levels_and_timing(spec_filename, levels_filename, timing_filename) + session.apply_levels_and_timing(levels_filename, timing_filename) + + total_bits = len(source_data) * SAMPLE_WIDTH + print('Fraction of mismatched capture bits for each ({}, {}) pair:'.format(x_spec_name, y_spec_name)) + for y_value in _sweep_values(y_start, y_stop, y_steps): + for x_value in _sweep_values(x_start, x_stop, x_steps): + # Only the specifications are unloaded, so reload only them; the levels and timing sheets are still loaded + session.unload_specifications(spec_filename) + _update_specification_values(spec_filename, {x_spec_name: x_value, y_spec_name: y_value}) + session.load_specifications_levels_and_timing(specifications_file_paths=spec_filename) + session.apply_levels_and_timing(levels_filename, timing_filename) + + session.burst_pattern(start_label='startdemo') + captured = next(iter(session.fetch_capture_waveform(CAPTURE_WAVEFORM_NAME, len(source_data)).values())) + mismatch = _count_mismatched_bits(source_data, captured) / total_bits + print('{}={:g}, {}={:g}: {:.4f}'.format(x_spec_name, x_value, y_spec_name, y_value, mismatch)) + + session.selected_function = nidigital.SelectedFunction.DISCONNECT + + +def _main(argsv): + parser = argparse.ArgumentParser(description='Demonstrates how to unload and reload a specifications file while sweeping two specification values and measuring the capture waveform bit errors at each point.', formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser.add_argument('-n', '--resource-name', default='PXI1Slot2,PXI1Slot3', help='Resource name of a NI digital pattern instrument. Ensure the resource name matches the instrument name in the pinmap file.') + parser.add_argument('-s', '--simulate', default='True', choices=['True', 'False'], help='Whether to run on simulated hardware or real hardware') + parser.add_argument('-xn', '--x-spec-name', default='AC.Strobe', help='Specification to sweep along the X axis, as
..') + parser.add_argument('-xs', '--x-start', default=0.0, type=float, help='First value of the X axis sweep.') + parser.add_argument('-xe', '--x-stop', default=1e-8, type=float, help='Last value of the X axis sweep.') + parser.add_argument('-xc', '--x-steps', default=50, type=int, help='Number of values in the X axis sweep.') + parser.add_argument('-yn', '--y-spec-name', default='DC.Voh', help='Specification to sweep along the Y axis, as
..') + parser.add_argument('-ys', '--y-start', default=0.0, type=float, help='First value of the Y axis sweep.') + parser.add_argument('-ye', '--y-stop', default=5.0, type=float, help='Last value of the Y axis sweep.') + parser.add_argument('-yc', '--y-steps', default=100, type=int, help='Number of values in the Y axis sweep.') + args = parser.parse_args(argsv) + + example(args.resource_name, + 'Simulate=1, DriverSetup=Model:6571' if args.simulate == 'True' else '', + args.x_spec_name, args.x_start, args.x_stop, args.x_steps, + args.y_spec_name, args.y_start, args.y_stop, args.y_steps) + + +def main(): + _main(sys.argv[1:]) + + +def test_example(): + options = {'simulate': True, 'driver_setup': {'Model': '6571'}, } + example('PXI1Slot2,PXI1Slot3', options, 'AC.Strobe', 0.0, 1e-8, 2, 'DC.Voh', 0.0, 5.0, 2) + + +def test_main(): + _main(['--x-steps', '2', '--y-steps', '2']) + + +if __name__ == '__main__': + main() diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/unload_and_reload_specifications_file.digiproj b/src/nidigital/examples/unload_and_reload_specifications_file/unload_and_reload_specifications_file.digiproj new file mode 100644 index 0000000000..36c3f4fe49 --- /dev/null +++ b/src/nidigital/examples/unload_and_reload_specifications_file/unload_and_reload_specifications_file.digiproj @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From f18524c5367c1c3de817f1582e8d524b7453c5ca Mon Sep 17 00:00:00 2001 From: NI-velmurugan Date: Thu, 12 Nov 2026 13:05:24 +0000 Subject: [PATCH 4/4] Improving on the console printing --- ...l_unload_and_reload_specifications_file.py | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py b/src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py index d8652023e1..83ddb75114 100644 --- a/src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py +++ b/src/nidigital/examples/unload_and_reload_specifications_file/nidigital_unload_and_reload_specifications_file.py @@ -30,62 +30,65 @@ def _sweep_values(start, stop, steps): def _update_specification_values(specs_file_path, new_values): # new_values maps '
.' to the new definition for that specification - tree = ElementTree.parse(specs_file_path) + specs_tree = ElementTree.parse(specs_file_path) for spec_name, value in new_values.items(): - section_name, symbol = spec_name.split('.') - definition = tree.find("s:Section[@name='{}']/f:Formula[@symbol='{}']/f:Definition".format(section_name, symbol), NAMESPACES) - definition.text = repr(value) - tree.write(specs_file_path, encoding='utf-8', xml_declaration=True) + section_name, formula_symbol = spec_name.split('.') + definition_element = specs_tree.find("s:Section[@name='{}']/f:Formula[@symbol='{}']/f:Definition".format(section_name, formula_symbol), NAMESPACES) + definition_element.text = repr(value) + specs_tree.write(specs_file_path, encoding='utf-8', xml_declaration=True) -def _count_mismatched_bits(expected, actual): - return sum(bin(e ^ a).count('1') for e, a in zip(expected, actual)) +def _count_mismatched_bits(expected_words, actual_words): + return sum(bin(expected_word ^ actual_word).count('1') for expected_word, actual_word in zip(expected_words, actual_words)) def example(resource_name, options, x_spec_name, x_start, x_stop, x_steps, y_spec_name, y_start, y_stop, y_steps): - dir = os.path.join(os.path.dirname(__file__)) + example_dir = os.path.join(os.path.dirname(__file__)) - pin_map_filename = os.path.join(dir, 'PinMap.pinmap') - pattern_filename = os.path.join(dir, 'demo_pattern_no_hw.digipat') - capture_waveform_filename = os.path.join(dir, 'demo_waveform.digicapture') - original_spec_filename = os.path.join(dir, 'Specifications.specs') - levels_filename = os.path.join(dir, 'PinLevels.digilevels') - timing_filename = os.path.join(dir, 'Timing.digitiming') + pin_map_filename = os.path.join(example_dir, 'PinMap.pinmap') + pattern_filename = os.path.join(example_dir, 'demo_pattern_no_hw.digipat') + capture_waveform_filename = os.path.join(example_dir, 'demo_waveform.digicapture') + original_spec_filename = os.path.join(example_dir, 'Specifications.specs') + levels_filename = os.path.join(example_dir, 'PinLevels.digilevels') + timing_filename = os.path.join(example_dir, 'Timing.digitiming') # Work on a temporary copy so the specifications file shipped with the example is never modified with tempfile.TemporaryDirectory() as temp_dir, \ nidigital.Session(resource_name=resource_name, options=options) as session: - spec_filename = os.path.join(temp_dir, 'Specifications.specs') - shutil.copy(original_spec_filename, spec_filename) + temp_spec_filename = os.path.join(temp_dir, 'Specifications.specs') + shutil.copy(original_spec_filename, temp_spec_filename) session.load_pin_map(pin_map_filename) session.load_pattern(pattern_filename) # Source random data; reg0 sets the number of source and capture loops used by the pattern - source_data = [random.getrandbits(SAMPLE_WIDTH) for _ in range(NUMBER_OF_SAMPLES)] - session.write_sequencer_register(nidigital.SequencerRegister.REGISTER0, len(source_data) * SAMPLE_WIDTH) + source_waveform_data = [random.getrandbits(SAMPLE_WIDTH) for _ in range(NUMBER_OF_SAMPLES)] + session.write_sequencer_register(nidigital.SequencerRegister.REGISTER0, len(source_waveform_data) * SAMPLE_WIDTH) session.pins[SOURCE_PIN].create_source_waveform_serial(SOURCE_WAVEFORM_NAME, nidigital.SourceDataMapping.BROADCAST, SAMPLE_WIDTH, nidigital.BitOrder.MSB) - session.write_source_waveform_broadcast(SOURCE_WAVEFORM_NAME, source_data) + session.write_source_waveform_broadcast(SOURCE_WAVEFORM_NAME, source_waveform_data) session.create_capture_waveform_from_file_digicapture(CAPTURE_WAVEFORM_NAME, capture_waveform_filename) - session.load_specifications_levels_and_timing(spec_filename, levels_filename, timing_filename) + session.load_specifications_levels_and_timing(temp_spec_filename, levels_filename, timing_filename) session.apply_levels_and_timing(levels_filename, timing_filename) - total_bits = len(source_data) * SAMPLE_WIDTH + total_bits = len(source_waveform_data) * SAMPLE_WIDTH + print('Start sweeping specifications') print('Fraction of mismatched capture bits for each ({}, {}) pair:'.format(x_spec_name, y_spec_name)) for y_value in _sweep_values(y_start, y_stop, y_steps): for x_value in _sweep_values(x_start, x_stop, x_steps): # Only the specifications are unloaded, so reload only them; the levels and timing sheets are still loaded - session.unload_specifications(spec_filename) - _update_specification_values(spec_filename, {x_spec_name: x_value, y_spec_name: y_value}) - session.load_specifications_levels_and_timing(specifications_file_paths=spec_filename) + session.unload_specifications(temp_spec_filename) + _update_specification_values(temp_spec_filename, {x_spec_name: x_value, y_spec_name: y_value}) + session.load_specifications_levels_and_timing(specifications_file_paths=temp_spec_filename) session.apply_levels_and_timing(levels_filename, timing_filename) session.burst_pattern(start_label='startdemo') - captured = next(iter(session.fetch_capture_waveform(CAPTURE_WAVEFORM_NAME, len(source_data)).values())) - mismatch = _count_mismatched_bits(source_data, captured) / total_bits - print('{}={:g}, {}={:g}: {:.4f}'.format(x_spec_name, x_value, y_spec_name, y_value, mismatch)) + site_number, captured_waveform = next(iter(session.fetch_capture_waveform(CAPTURE_WAVEFORM_NAME, len(source_waveform_data)).items())) + mismatch_fraction = _count_mismatched_bits(source_waveform_data, captured_waveform) / total_bits + print('Site {}: {}={:g}, {}={:g}: {:.4f}'.format(site_number, x_spec_name, x_value, y_spec_name, y_value, mismatch_fraction)) + + print('Done sweeping specifications') session.selected_function = nidigital.SelectedFunction.DISCONNECT @@ -97,11 +100,11 @@ def _main(argsv): parser.add_argument('-xn', '--x-spec-name', default='AC.Strobe', help='Specification to sweep along the X axis, as
..') parser.add_argument('-xs', '--x-start', default=0.0, type=float, help='First value of the X axis sweep.') parser.add_argument('-xe', '--x-stop', default=1e-8, type=float, help='Last value of the X axis sweep.') - parser.add_argument('-xc', '--x-steps', default=50, type=int, help='Number of values in the X axis sweep.') + parser.add_argument('-xc', '--x-steps', default=5, type=int, help='Number of values in the X axis sweep.') parser.add_argument('-yn', '--y-spec-name', default='DC.Voh', help='Specification to sweep along the Y axis, as
..') parser.add_argument('-ys', '--y-start', default=0.0, type=float, help='First value of the Y axis sweep.') parser.add_argument('-ye', '--y-stop', default=5.0, type=float, help='Last value of the Y axis sweep.') - parser.add_argument('-yc', '--y-steps', default=100, type=int, help='Number of values in the Y axis sweep.') + parser.add_argument('-yc', '--y-steps', default=5, type=int, help='Number of values in the Y axis sweep.') args = parser.parse_args(argsv) example(args.resource_name,