from pynq.overlays.logictools import LogicToolsOverlay


logictools_olay = LogicToolsOverlay('logictools.bit')


"""
Explanation: Single Stepping logictools Generators
This notebook will show how to use single stepping mode in logictools generators. In this example the pattern generator is used to implement a simple 4-bit up-counter, we will be able to single step the clock and verify the counter operation. The output is verifired using the waveforms captured by the trace analyzer as well as the patterns on the on-board LEDs.   
We use the boolean generator to transfer the pattern generator signals to the on-board LEDs. It implements 4 buffer functions that pass the input values received from the pattern generator to the on-board LEDs. we observe the patterns on the on-board LEDs by single stepping the clock at desired intervals.    
Single stepping is supported in all the logictools generators.
Step 1: Download the logictools overlay
End of explanation
"""


from pynq.lib.logictools import Waveform

up_counter = {'signal': [
    ['stimulus',
        {'name': 'bit0', 'pin': 'D0', 'wave': 'lh' * 8},
        {'name': 'bit1', 'pin': 'D1', 'wave': 'l.h.' * 4},
        {'name': 'bit2', 'pin': 'D2', 'wave': 'l...h...' * 2},
        {'name': 'bit3', 'pin': 'D3', 'wave': 'l.......h.......'}],
        {},
    ['analysis',
        {'name': 'bit0_loopback', 'pin': 'D0'},
        {'name': 'bit1_loopback', 'pin': 'D1'},
        {'name': 'bit2_loopback', 'pin': 'D2'},
        {'name': 'bit3_loopback', 'pin': 'D3'}]], 

    'foot': {'tock': 1},
    'head': {'text': 'up_counter'}}

waveform = Waveform(up_counter)
waveform.display()

"""
Explanation: Step 2: Create WaveJSON waveform
The pattern to be generated is specified in the waveJSON format   
The pattern is applied to the Arduino interface, pins D0, D1, D2 and D3 are set to generate a 4-bit count. 
The Waveform class is used to display the specified waveform.
End of explanation
"""


pattern_generator = logictools_olay.pattern_generator
pattern_generator.trace(num_analyzer_samples=16)
pattern_generator.setup(up_counter,
                        stimulus_group_name='stimulus',
                        analysis_group_name='analysis')

"""
Explanation: Note: Since there are no captured samples at this moment, the analysis group will be empty.
Step 3: Instantiate and setup the pattern generator and trace analyzer objects
Users can choose whether to use the trace analyzer by calling the trace() method.  
The analyzer can be set to trace a specific number of samples using, num_analyzer_samples argument.
End of explanation
"""


boolean_generator = logictools_olay.boolean_generator

functions = {'Buffer 1': 'LD3 = D16',
             'Buffer 2': 'LD2 = D17',
             'Buffer 3': 'LD1 = D18',
             'Buffer 4': 'LD0 = D19'}

boolean_generator.setup(functions)
boolean_generator.expressions

"""
Explanation: Step 4: Setup the boolean generator
End of explanation
"""


logictools_controller = logictools_olay.logictools_controller

"""
Explanation: Step 5: Instantiate logictools controller to run both the instantiated generators simultaneously
End of explanation
"""


from time import sleep

for _ in range(4):
    logictools_controller.step([boolean_generator, pattern_generator])
    sleep(1)

pattern_generator.show_waveform()

"""
Explanation: Set the loopback connections using jumper wires on the Arduino Interface


Output pins D0, D1, D2 and D3 are connected to pins D19, D18, D17 and D16 respectively
Internal Loopback pins D0, D1, D2 and D3 are observed using the trace analyzer as shown below
After setup, the pattern generator should be ready to run     
Patterns on pins D19, D18, D17 and D16 are observed on the on-board LEDs

Note: Make sure all other pins are disconnected.
Step 6: Step and display waveform
The step() method is used to single step the pattern, show_waveform() method is used to display the waveforms.  
Step 4 cycles using a 1 second delay loop. Observe the pattern on the on-board LEDs
End of explanation
"""


from time import sleep

for _ in range(11):
    logictools_controller.step([boolean_generator, pattern_generator])
    sleep(1)
pattern_generator.show_waveform()

"""
Explanation: Step an additional 11 cycles using a 1 second delay loop. Observe the pattern on the on-board LEDs
End of explanation
"""


logictools_controller.step([boolean_generator, pattern_generator])
pattern_generator.show_waveform()

"""
Explanation: Step 1 additional cycle to reach the maximum count value. Observe the pattern on the on-board LEDs
End of explanation
"""


pattern_generator.stop()
boolean_generator.stop()

"""
Explanation: Step 7: Stop the  generators
Calling stop() will clear the logic values on output pins; however, the waveform will be recorded locally in the pattern generator instance.
End of explanation
"""


pattern_generator.reset()
boolean_generator.reset()

"""
Explanation: Step 8: Reset the  generators
Calling reset() will reset generator instances.
End of explanation
"""


