-
Notifications
You must be signed in to change notification settings - Fork 24
feat(example): Generic synchronization example #242
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| Generic Synchronization Example | ||
| =============================== | ||
|
|
||
| This example demonstrates how to synchronize two :any:`nixnet.session.FrameInStreamSession` | ||
| session types on different interfaces. | ||
|
|
||
| These principles can be extended to any session type and quantity. | ||
| Sessions are created, configured, and started for each interface sequentially. | ||
|
|
||
| The interfaces that will listen for a clock should be created and configured first. | ||
| Interface properties need only be set once per interface. The connect_terminals function | ||
| acts like an interface property and needs to be set only once per interface. Listening | ||
| sessions can then be started with the "Session Only" scope. The last session to be started | ||
| on a particul interface can be started with the normal scope which will cause it to start | ||
| listening for a start trigger. | ||
|
|
||
| The interface that will drive the master timebase clock should be created and configured | ||
| last. The master timebase is configured to be output via connect_terminals and then the | ||
| interface can be started with normal scope. | ||
|
|
||
| Generic Synchronization | ||
| ----------------------- | ||
|
|
||
| .. literalinclude:: ../../nixnet_examples/generic_synchronization.py | ||
| :pyobject: main | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2029,3 +2029,27 @@ class FrameType(enum.Enum): | |
| SPECIAL_DELAY = _cconsts.NX_FRAME_TYPE_SPECIAL_DELAY | ||
| SPECIAL_LOG_TRIGGER = _cconsts.NX_FRAME_TYPE_SPECIAL_LOG_TRIGGER | ||
| SPECIAL_START_TRIGGER = _cconsts.NX_FRAME_TYPE_SPECIAL_START_TRIGGER | ||
|
|
||
|
|
||
| class Terminal(enum.Enum): | ||
| "Terminals to import/export from the XNET device" | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use triple quotes for docstrings. https://www.python.org/dev/peps/pep-0257/#one-line-docstrings |
||
| FRONTPANEL_0 = _cconsts.NX_TERM_FRONT_PANEL0 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should FRONTPANEL_0 and FRONTPANEL_1 be removed? They are duplicates of FRONT_PANEL_0 and FRONT_PANEL_1 below. |
||
| FRONTPANEL_1 = _cconsts.NX_TERM_FRONT_PANEL1 | ||
| PXI_TRIG_0 = _cconsts.NX_TERM_PXI_TRIG0 | ||
| PXI_TRIG_1 = _cconsts.NX_TERM_PXI_TRIG1 | ||
| PXI_TRIG_2 = _cconsts.NX_TERM_PXI_TRIG2 | ||
| PXI_TRIG_3 = _cconsts.NX_TERM_PXI_TRIG3 | ||
| PXI_TRIG_4 = _cconsts.NX_TERM_PXI_TRIG4 | ||
| PXI_TRIG_5 = _cconsts.NX_TERM_PXI_TRIG5 | ||
| PXI_TRIG_6 = _cconsts.NX_TERM_PXI_TRIG6 | ||
| PXI_TRIG_7 = _cconsts.NX_TERM_PXI_TRIG7 | ||
| FRONT_PANEL_0 = _cconsts.NX_TERM_FRONT_PANEL0 | ||
| FRONT_PANEL_1 = _cconsts.NX_TERM_FRONT_PANEL1 | ||
| PXI_STAR = _cconsts.NX_TERM_PXI_STAR | ||
| PXI_CLK_10 = _cconsts.NX_TERM_PXI_CLK10 | ||
| TIMEBASE_10_MHZ = _cconsts.NX_TERM_10_M_HZ_TIMEBASE | ||
| TIMEBASE_1_MHZ = _cconsts.NX_TERM_1_M_HZ_TIMEBASE | ||
| TIMEBASE_MASTER = _cconsts.NX_TERM_MASTER_TIMEBASE | ||
| COMM_TRIGGER = _cconsts.NX_TERM_COMM_TRIGGER | ||
| START_TRIGGER = _cconsts.NX_TERM_START_TRIGGER | ||
| LOG_TRIGGER = _cconsts.NX_TERM_LOG_TRIGGER | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,99 @@ | ||
| from __future__ import absolute_import | ||
| from __future__ import division | ||
| from __future__ import print_function | ||
|
|
||
| import six | ||
| import time | ||
|
|
||
|
|
||
| import nixnet | ||
| from nixnet import constants | ||
| from nixnet import types | ||
|
|
||
|
|
||
| def main(): | ||
| interface1 = 'CAN1' | ||
| interface2 = 'CAN2' | ||
|
|
||
| # Create the sessions. ExitStack() can be used for high session counts | ||
| with nixnet.FrameInStreamSession(interface1) as interface1_input: | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. More of a suggestion here; would this naming be a little more descriptive? |
||
| with nixnet.FrameInStreamSession(interface2) as interface2_input: | ||
| with nixnet.FrameOutStreamSession(interface2) as interface2_output: | ||
| # Set session and interface properties such as termination | ||
| # Note that interface properties only need to be set once per interface | ||
| interface1_input.intf.baud_rate = 125000 | ||
| interface1_input.intf.can_term = constants.CanTerm.ON | ||
|
|
||
| # Connect the start trigger terminals for the listening interface | ||
| interface1_input.connect_terminals(constants.Terminal.PXI_TRIG_0, constants.Terminal.START_TRIGGER) | ||
|
|
||
| # Start the listening interface sessions | ||
| interface1_input.start() | ||
|
|
||
| # Set session and interface properties such as termination | ||
| # Note that interface properties only need to be set once per interface | ||
| interface2_input.intf.baud_rate = 125000 | ||
| interface2_input.intf.can_term = constants.CanTerm.ON | ||
| interface2_input.intf.echo_tx = True | ||
|
|
||
| # Connect the start trigger terminals for the interface driving the start trigger | ||
| interface2_input.connect_terminals(constants.Terminal.START_TRIGGER, constants.Terminal.PXI_TRIG_0) | ||
|
|
||
| # Starting the sessions on the driving interface will trigger the start of the listening sessions | ||
| interface2_input.start(constants.StartStopScope.SESSION_ONLY) | ||
| interface2_output.start() | ||
|
|
||
| # Request values to transmit from user | ||
| user_value = six.moves.input('Enter payload [int, int, ...]: ') | ||
| try: | ||
| payload_list = [int(x.strip()) for x in user_value.split(",")] | ||
| except ValueError: | ||
| payload_list = [2, 4, 8, 16] | ||
| print('Unrecognized input ({}). Setting data buffer to {}'.format(user_value, payload_list)) | ||
|
|
||
| id = types.CanIdentifier(1) | ||
| payload = bytearray(payload_list) | ||
| frame = types.CanFrame(id, constants.FrameType.CAN_DATA, payload) | ||
|
|
||
| print('The same values should be received. Press q to quit') | ||
| i = 0 | ||
| while True: | ||
| # Apply the user input to the frame payload | ||
| for index, byte in enumerate(payload): | ||
| payload[index] = byte + i | ||
|
|
||
| frame.payload = payload | ||
| # Write the specified frame to the bus | ||
| interface2_output.frames.write([frame]) | ||
| print('Sent frame with ID {} payload: {}'.format(id, payload)) | ||
|
|
||
| time.sleep(0.2) | ||
|
|
||
| # Read frames back from both input sessions | ||
| frames_to_read = 1 | ||
| received_frames = interface1_input.frames.read(frames_to_read) | ||
| echoed_frames = interface2_input.frames.read(frames_to_read) | ||
| rx_frame_list = list(received_frames) | ||
| echo_frame_list = list(echoed_frames) | ||
| for frame in rx_frame_list: | ||
| print('Received frame: {}'.format(rx_frame_list[0])) | ||
| print(' payload={}'.format(list(six.iterbytes(rx_frame_list[0].payload)))) | ||
| print('Echoed frame: {}'.format(echo_frame_list[0])) | ||
| print(' payload={}'.format(list(six.iterbytes(echo_frame_list[0].payload)))) | ||
|
|
||
| # Subtract the timestamp from first frame in each list to obtain delta | ||
| delta_t = rx_frame_list[0].timestamp - echo_frame_list[0].timestamp | ||
| print('The delta between received timestamp and echo is: {}', delta_t) | ||
|
|
||
| i += 1 | ||
| if max(payload) + i > 0xFF: | ||
| i = 0 | ||
| inp = six.moves.input('Hit enter to continue (q to quit): ') | ||
| if inp.lower() == 'q': | ||
| break | ||
|
|
||
| print('Data acquisition stopped.') | ||
|
|
||
|
|
||
| if __name__ == '__main__': | ||
| main() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
particular*
Might be nice to actually link to docstrings for things like "connect_terminals", "SESSION_ONLY", and any other relevant properties.
If possible, it's a good idea to get input from techcomms on docstrings.