Pynq GPIO simulator

This simulator allows to simulate a Pynq application that uses the GPIO LEDs, RGB LEDs, Buttons and Switches. In order to run an applicatin with the simulator, you need to execute the following code first:

In [29]:
from IPython import display
from ipywidgets import widgets
import threading

MAX_LEDS = 4
MAX_RGBLEDS = 2
MAX_SWITCHES = 2
MAX_BUTTONS = 4

# Reference Color Values for RGB LED
RGB_CLEAR = "#FFFFFF"
RGB_BLUE = "#0000FF"
RGB_GREEN = "#008000"
RGB_CYAN = "#00FFFF"
RGB_RED = "#FF0000"
RGB_MAGENTA = "#FF00FF"
RGB_YELLOW = "#FFFF00"
RGB_WHITE = "#FFFFFF"

colorMap = {0: RGB_CLEAR, 1: RGB_BLUE, 2: RGB_GREEN, 3: RGB_CYAN, 4: RGB_RED, 5: RGB_MAGENTA, 6: RGB_YELLOW, 7: RGB_WHITE}

class mockInterface:
    
    def __init__(self):
        self.leds = []
        self.ledsStatus = []
        self.rgbleds = []
        self.rgbledsStatus = []
        self.switches = []
        self.buttons = []
        
        # Generate leds as white disabled buttons
        for i in range(MAX_LEDS):
            led = widgets.Button(margin = "5px 22px", width = "40px", disabled = True)
            self.leds.append(led)
            self.ledsStatus.append(0)
        ledCont = widgets.HBox(self.leds)
 
        # Generate rgbleds as white disabled buttons
        for i in range(MAX_RGBLEDS):
            led = widgets.Button(margin = "5px 22px", width = "40px", disabled = True)
            self.rgbleds.append(led)
            self.rgbledsStatus.append([0,RGB_CLEAR])
        rgbledCont = widgets.HBox(self.rgbleds)
        
        # Generate buttons
        for i in range(MAX_BUTTONS):
            button = widgets.ToggleButton(description = "b" + str(i), width="40px", margin="5px 22px")
            self.buttons.append(button)
        buttonCont = widgets.HBox(self.buttons)
        
        # Generate switches
        for i in range(MAX_SWITCHES):
            switch = widgets.Select(options=["ON","OFF"], value="OFF", width="60px", height="40px", margin="0px")
            self.switches.append(switch)
        switchesCont = widgets.HBox(self.switches)
        
        display.display(ledCont)
        display.display(rgbledCont)
        display.display(buttonCont) 
        display.display(switchesCont)
    
    def getLed(self, index):
        return self.leds[index]
    
    def getLedStatus(self, index):
        return self.ledsStatus[index]

    def setLedStatus(self, index, status):
        self.ledsStatus[index] = status
    
    def getRGBLed(self, index):
        return self.rgbleds[index]
    
    def getRGBLedStatus(self, index):
        return self.rgbledsStatus[index]

    def setRGBLedStatus(self, index, status, color):
        self.rgbledsStatus[index] = [status, color]
    
    def getButton(self, index):
        return self.buttons[index]

    def getSwitch(self, index):
        return self.switches[index]
    
class LED:

    interface = None
    
    def __init__(self, index):
        if(self.interface == None):
            raise Exception("You need to call initMockInterface() before using a LED")
        self.index = index
    
    def read(self):
        return self.interface.getLed(self.index)
    
    def on(self):
        self.interface.setLedStatus(self.index, True)
        led = self.interface.getLed(self.index)
        led.background_color = "#00FF00"
    
    def off(self):
        self.interface.setLedStatus(self.index, False)
        led = self.interface.getLed(self.index)
        led.background_color = "#FFFFFF"
    
    def toggle(self):
        if(self.interface.getLedStatus(self.index)):
            self.off()
        else:
            self.on()            

class RGBLED:

    interface = None
    
    def __init__(self, index):
        if(self.interface == None):
            raise Exception("You need to call initMockInterface() before using an RGBLED")
        if(index != 4 and index != 5):
            raise Exception("Out of boundaries index for RGBLED: Please use indices 4 or 5")
        self.index = index - MAX_LEDS
    
    def read(self):
        return self.interface.getRGBLed(self.index)
    
    def on(self, color):
        self.interface.setRGBLedStatus(self.index, True, color)
        led = self.interface.getRGBLed(self.index)
        led.background_color = colorMap[color]
    
    def off(self):
        self.interface.setRGBLedStatus(self.index, False, 0)
        led = self.interface.getRGBLed(self.index)
        led.background_color = RGB_CLEAR
            
class Switch:
    
    interface = None
    
    def __init__(self, index):
        if(self.interface == None):
            raise Exception("You need to call initMockInterface() before using a Switch")
        self.index = index
    
    def read(self):
        switch = self.interface.getSwitch(self.index)
        if(switch.value == "OFF"):
            return 0
        return 1
        
class Button:
    
    interface = None
    
    def __init__(self, index):
        if(self.interface == None):
            raise Exception("You need to call initMockInterface() before using a Switch")
        self.index = index
    
    def read(self):
        button = self.interface.getButton(self.index)
        if(button.value):
            return 1
        return 0

def initMockInterface():
    mockInterfaceObj = mockInterface()
    LED.interface = mockInterfaceObj
    RGBLED.interface = mockInterfaceObj
    Switch.interface = mockInterfaceObj
    Button.interface = mockInterfaceObj
    
def startSimulation(program):
    initMockInterface()
    time.sleep(0.5)
    t2 = threading.Thread(target=program)
    t2.start()

After having imported the simulator, you need to wrap your entire application within a "program" function and invoke the method startSimulation(program) at the end of your code. Notice also that you do not have to import the Pynq libraries. The following are simulation examples:

In [30]:
import time

def program():
    leds = [LED(i) for i in range(MAX_LEDS)]

    for i in range(40):
        leds[i % MAX_LEDS].toggle()
        time.sleep(0.1)

startSimulation(program)
In [31]:
def program():

    led = LED(0)
        
    # turn on led
    led.on()
        
    # wait for button 0 to be pressed
    btStart = Button(0)
    while(not btStart.read()):
        time.sleep(0.1)
    while(btStart.read()):
        time.sleep(0.1)
    
    # turn off led
    led.off()

startSimulation(program)
In [35]:
import time

def program():
    led = LED(1)
    for  i in range(40):
        led.toggle()
        time.sleep(0.1)

startSimulation(program)
In [38]:
def program():
    BUTTON_NUM = 4
    RGB_LED_NUM = 2
    RGB_OFFSET = 4
    SWITCH_NUM = 2

    buttons = [Button(i) for i in range(BUTTON_NUM)]
    rgb_leds = [RGBLED(i + RGB_OFFSET) for i in range(RGB_LED_NUM)]
    switches = [Switch(i) for i in range(SWITCH_NUM)]

    exit = 0

    while(not exit):

        time.sleep(0.1)

        button_val = [False] * 3
        value = 0
        for i in range(BUTTON_NUM - 1):
            if buttons[i].read():
                button_val[i] = True
                value += 2 ** i

        for i in range(SWITCH_NUM):
            if switches[i].read():
                rgb_leds[i].on(value)
            else:
                rgb_leds[i].off()

        if buttons[BUTTON_NUM - 1].read():
            exit = 1

startSimulation(program)
In [ ]: