sgm0_done = sgm0_done or sgm_optim_0.register_map.CTRL.AP_DONE sgm1_done = sgm1_done or sgm_optim_1.register_map.CTRL.AP_DONE #print(count) #count = count + 1 pass print("--- %s seconds ---" % (time.time() - start_time)) raw_iml_buffer = np.zeros((IMG_HEIGHT,IMG_WIDTH),dtype=np.ubyte) raw_imr_buffer = np.zeros((IMG_HEIGHT,IMG_WIDTH),dtype=np.ubyte) rec_iml_buffer = np.zeros((IMG_HEIGHT,IMG_WIDTH),dtype=np.ubyte) rec_imr_buffer = np.zeros((IMG_HEIGHT,IMG_WIDTH),dtype=np.ubyte) disp_im_buffer = np.zeros((IMG_HEIGHT,IMG_WIDTH),dtype=np.ubyte) for i in range(IMG_HEIGHT): for j in range(IMG_WIDTH): disp_im_buffer[i][j] = Image_buf[12*image_size+i*IMG_WIDTH+j] raw_imr_buffer[i][j] = Image_buf[1*image_size+i*IMG_WIDTH+j] raw_iml_buffer[i][j] = Image_buf[0*image_size+i*IMG_WIDTH+j] rec_imr_buffer[i][j] = Image_buf[11*image_size+i*IMG_WIDTH+j] rec_iml_buffer[i][j] = Image_buf[10*image_size+i*IMG_WIDTH+j] cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/raw_iml_buffer.png',raw_iml_buffer) cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/raw_imr_buffer.png',raw_imr_buffer) cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/rec_iml_buffer.png',rec_iml_buffer) cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/rec_imr_buffer.png',rec_imr_buffer) cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/disp_im_buffer.png',disp_im_buffer) Xlnk.cma_free(Image_buf)
# while(count < 5000): # print(count) # count = count +1 # for i in range(IMG_HEIGHT): # for j in range(IMG_WIDTH): # disp_im_buffer[i][j] = Image_buf[12*image_size+i*IMG_WIDTH+j] # cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/disp_im_buffer.png',disp_im_buffer) # Image_buf[0:image_size] = test1[0:image_size] #left raw image # Image_buf[image_size:image_size*2] = test2[0:image_size] #right raw image for i in range(IMG_HEIGHT): for j in range(IMG_WIDTH): disp_im_buffer[i][j] = Image_buf[12 * image_size + i * IMG_WIDTH + j] raw_imr_buffer[i][j] = Image_buf[1 * image_size + i * IMG_WIDTH + j] raw_iml_buffer[i][j] = Image_buf[0 * image_size + i * IMG_WIDTH + j] rec_imr_buffer[i][j] = Image_buf[11 * image_size + i * IMG_WIDTH + j] rec_iml_buffer[i][j] = Image_buf[10 * image_size + i * IMG_WIDTH + j] cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/raw_iml_buffer.png', raw_iml_buffer) cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/raw_imr_buffer.png', raw_imr_buffer) cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/rec_iml_buffer.png', rec_iml_buffer) cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/rec_imr_buffer.png', rec_imr_buffer) cv2.imwrite('/home/xilinx/sgm_pynq_ver/output_images/disp_im_buffer.png', disp_im_buffer) xlnk.cma_free(Image_buf)
class Arduino_LCD18(object): """This class controls the Adafruit 1.8" LCD shield from AdaFruit. The LCD panel consists of ST7735 LCD controller, a joystick, and a microSD socket. This class uses the LCD panel (128x160 pixels) and the joystick. The joystick uses A3 analog channel. https://www.adafruit.com/product/802. Attributes ---------- microblaze : Arduino Microblaze processor instance used by this module. buf_manager : Xlnk DDR management unit that provides the physical address of the image. """ def __init__(self, mb_info): """Return a new instance of an Arduino_LCD18 object. Parameters ---------- mb_info : dict A dictionary storing Microblaze information, such as the IP name and the reset name. """ self.microblaze = Arduino(mb_info, ARDUINO_LCD18_PROGRAM) self.buf_manager = Xlnk() def clear(self): """Clear the screen. Returns ------- None """ self.microblaze.write_blocking_command(CLEAR_SCREEN) def display(self, img_path, x_pos=0, y_pos=127, orientation=3, background=None, frames=1): """Animate the image at the desired location for multiple frames. The maximum screen resolution is 160x128. Users can specify the position to display the image. For example, to display the image in the center, `x_pos` can be (160-`width`/2), `y_pos` can be (128/2)+(`height`/2). A typical orientation is 3. The origin of orientation 0, 1, 2, and 3 corresponds to upper right corner, lower right corner, lower left corner, and upper left corner, respectively. Currently, only 1 and 3 are valid orientations. If users choose orientation 1, the picture will be shown upside-down. If users choose orientation 3, the picture will be shown consistently with the LCD screen orientation. Parameter `background` specifies the color of the background; it is a list of 3 elements: R, G, and B, each with 8 bits for color level. Parameters ---------- img_path : str The file path to the image stored in the file system. x_pos : int x position of a pixel where the image starts. y_pos : int y position of a pixel where the image starts. background : list A list of [R, G, B] components for background, each of 8 bits. orientation : int orientation of the image; valid values are 1 and 3. frames : int Number of frames the image is moved, must be less than 65536. Returns ------- None """ task = asyncio.ensure_future( self.display_async(img_path, x_pos, y_pos, orientation, background, frames)) loop = asyncio.get_event_loop() loop.run_until_complete(task) @asyncio.coroutine def display_async(self, img_path, x_pos=0, y_pos=127, orientation=3, background=None, frames=1): """Animate the image at the desired location for multiple frames. The maximum screen resolution is 160x128. Users can specify the position to display the image. For example, to display the image in the center, `x_pos` can be (160-`width`/2), `y_pos` can be (128/2)+(`height`/2). A typical orientation is 3. The origin of orientation 0, 1, 2, and 3 corresponds to upper right corner, lower right corner, lower left corner, and upper left corner, respectively. Currently, only 1 and 3 are valid orientations. If users choose orientation 1, the picture will be shown upside-down. If users choose orientation 3, the picture will be shown consistently with the LCD screen orientation. Parameter `background` specifies the color of the background; it is a list of 3 elements: R, G, and B, each with 8 bits for color level. Parameters ---------- img_path : str The file path to the image stored in the file system. x_pos : int x position of a pixel where the image starts. y_pos : int y position of a pixel where the image starts. background : list A list of [R, G, B] components for background, each of 8 bits. orientation : int orientation of the image; valid values are 1 and 3. frames : int Number of frames the image is moved, must be less than 65536. Returns ------- None """ if x_pos not in range(160): raise ValueError("Valid x_pos is 0 - 159.") if y_pos not in range(128): raise ValueError("Valid y_pos is 0 - 127.") if orientation not in [1, 3]: raise ValueError("Valid orientation is 1 or 3.") if frames not in range(1, 65536): raise ValueError("Valid number of frames is 1 - 65535.") if not os.path.isfile(img_path): raise ValueError("Specified image file does not exist.") if background is None: background = [0, 0, 0] background16 = _convert_color(background) image_file = Image.open(img_path) width, height = image_file.size if width not in range(161) or height not in range(129): raise ValueError("Picture too large to be fit in 160x128 screen.") image_file.resize((width, height), Image.ANTIALIAS) image_array = array(image_file) image_file.close() file_size = width * height * 2 buf0 = self.buf_manager.cma_alloc(file_size, data_type="uint8_t") buf1 = self.buf_manager.cma_get_buffer(buf0, file_size) phy_addr = self.buf_manager.cma_get_phy_addr(buf0) try: for j in range(width): for i in range(height): red, green, blue = image_array[i][j] temp = ((blue & 0xF8) << 8) | ((green & 0xFC) << 3) | \ ((red & 0xF8) >> 3) index = 2 * ((height - i - 1) * width + j) buf1[index] = bytes([temp & 0xFF]) buf1[index + 1] = bytes([(temp & 0xFF00) >> 8]) data = [ x_pos, y_pos, width, height, phy_addr, background16, orientation, frames ] self.microblaze.write_mailbox(0, data) # Ensure interrupt is reset before issuing command if self.microblaze.interrupt: self.microblaze.interrupt.clear() self.microblaze.write_non_blocking_command(DISPLAY) while self.microblaze.read(MAILBOX_OFFSET + MAILBOX_PY2IOP_CMD_OFFSET) != 0: if self.microblaze.interrupt: yield from self.microblaze.interrupt.wait() finally: if self.microblaze.interrupt: self.microblaze.interrupt.clear() self.buf_manager.cma_free(buf0) def draw_line(self, x_start_pos, y_start_pos, x_end_pos, y_end_pos, color=None, background=None, orientation=3): """Draw a line from starting point to ending point. The maximum screen resolution is 160x128. Parameter `color` specifies the color of the line; it is a list of 3 elements: R, G, and B, each with 8 bits for color level. Parameter `background` is similar to parameter `color`, except that it specifies the background color. A typical orientation is 3. The origin of orientation 0, 1, 2, and 3 corresponds to upper right corner, lower right corner, lower left corner, and upper left corner, respectively. Currently, only 1 and 3 are valid orientations. If users choose orientation 1, the picture will be shown upside-down. If users choose orientation 3, the picture will be shown consistently with the LCD screen orientation. Parameters ---------- x_start_pos : int x position (in pixels) where the line starts. y_start_pos : int y position (in pixels) where the line starts. x_end_pos : int x position (in pixels ) where the line ends. y_end_pos : int y position (in pixels) where the line ends. color : list A list of [R, G, B] components for line color, each of 8 bits. background : list A list of [R, G, B] components for background, each of 8 bits. orientation : int orientation of the image; valid values are 1 and 3. Returns ------- None """ if x_start_pos not in range(160): raise ValueError("Valid x start position is 0 - 159.") if y_start_pos not in range(128): raise ValueError("Valid y start position is 0 - 127.") if x_end_pos not in range(160): raise ValueError("Valid x end position is 0 - 159.") if y_end_pos not in range(128): raise ValueError("Valid y end position is 0 - 127.") if orientation not in [1, 3]: raise ValueError("Valid orientation is 1 or 3.") if color is None: color = [255, 255, 255] color16 = _convert_color(color) if background is None: background = [0, 0, 0] background16 = _convert_color(background) data = [ x_start_pos, y_start_pos, x_end_pos, y_end_pos, color16, background16, orientation ] self.microblaze.write_mailbox(0, data) self.microblaze.write_blocking_command(DRAW_LINE) def print_string(self, x_start_pos, y_start_pos, text, color=None, background=None, orientation=3): """Draw a character with a specific color. The maximum screen resolution is 160x128. Parameter `color` specifies the color of the text; it is a list of 3 elements: R, G, and B, each with 8 bits for color level. Parameter `background` is similar to parameter `color`, except that it specifies the background color. A typical orientation is 3. The origin of orientation 0, 1, 2, and 3 corresponds to upper right corner, lower right corner, lower left corner, and upper left corner, respectively. Currently, only 1 and 3 are valid orientations. If users choose orientation 1, the picture will be shown upside-down. If users choose orientation 3, the picture will be shown consistently with the LCD screen orientation. Parameters ---------- x_start_pos : int x position (in pixels) where the line starts. y_start_pos : int y position (in pixels) where the line starts. text : str printable ASCII characters. color : list A list of [R, G, B] components for line color, each of 8 bits. background : list A list of [R, G, B] components for background, each of 8 bits. orientation : int orientation of the image; valid values are 1 and 3. Returns ------- None """ if x_start_pos not in range(160): raise ValueError("Valid x start position is 0 - 159.") if y_start_pos not in range(128): raise ValueError("Valid y start position is 0 - 127.") if type(text) is not str: raise ValueError("Character has to be of string type.") if orientation not in [1, 3]: raise ValueError("Valid orientation is 1 or 3.") if color is None: color = [255, 255, 255] color16 = _convert_color(color) if background is None: background = [0, 0, 0] background16 = _convert_color(background) temp_txt = text count = len(text) for _ in range(count % 4): temp_txt = temp_txt + str('\0') data = [x_start_pos, y_start_pos, color16, background16, orientation] temp = 0 for i in range(len(temp_txt)): temp = temp | (ord(temp_txt[i]) << 8 * (i % 4)) if i % 4 == 3: data.append(temp) temp = 0 self.microblaze.write_mailbox(0, data) self.microblaze.write_blocking_command(PRINT_STRING) def draw_filled_rectangle(self, x_start_pos, y_start_pos, width, height, color=None, background=None, orientation=3): """Draw a filled rectangle. Parameter `color` specifies the color of the text; it is a list of 3 elements: R, G, and B, each with 8 bits for color level. Parameter `background` is similar to parameter `color`, except that it specifies the background color. A typical orientation is 3. The origin of orientation 0, 1, 2, and 3 corresponds to upper right corner, lower right corner, lower left corner, and upper left corner, respectively. Currently, only 1 and 3 are valid orientations. If users choose orientation 1, the picture will be shown upside-down. If users choose orientation 3, the picture will be shown consistently with the LCD screen orientation. Parameters ---------- x_start_pos : int x position (in pixels) where the rectangle starts. y_start_pos : int y position (in pixels) where the rectangle starts. width : int Width of the rectangle (in pixels). height : int Height of the rectangle (in pixels). color : list A list of [R, G, B] components for line color, each of 8 bits. background : list A list of [R, G, B] components for background, each of 8 bits. orientation : int orientation of the image; valid values are 1 and 3. Returns ------- None """ if x_start_pos not in range(160): raise ValueError("Valid x start position is 0 - 159.") if y_start_pos not in range(128): raise ValueError("Valid y start position is 0 - 127.") if width not in range(160): raise ValueError("Valid x end position is 0 - 159.") if height not in range(128): raise ValueError("Valid y end position is 0 - 127.") if orientation not in [1, 3]: raise ValueError("Valid orientation is 1 or 3.") if color is None: color = [255, 255, 255] color16 = _convert_color(color) if background is None: background = [0, 0, 0] background16 = _convert_color(background) data = [ x_start_pos, y_start_pos, width, height, color16, background16, orientation ] self.microblaze.write_mailbox(0, data) self.microblaze.write_blocking_command(FILL_RECTANGLE) def read_joystick(self): """Read the joystick values. The joystick values can be read when user is pressing the button toward a specific direction. The returned values can be: 1: left; 2: down; 3: center; 4: right; 5: up; 0: no button pressed. Returns ------- int Indicating the direction towards which the button is pushed. """ self.microblaze.write_blocking_command(READ_BUTTON) value = self.microblaze.read_mailbox(0) return value
class LogicToolsController(PynqMicroblaze): """This class controls all the logic generators. This class uses the PynqMicroblaze class. It extends PynqMicroblaze with capability to control boolean generators, pattern generators, and Finite State Machine (FSM) generators. Attributes ---------- ip_name : str The name of the IP corresponding to the Microblaze. rst_name : str The name of the reset pin for the Microblaze. mb_program : str The absolute path of the Microblaze program. state : str The status (IDLE, RUNNING, or STOPPED) of the Microblaze. reset : GPIO The reset pin associated with the Microblaze. mmio : MMIO The MMIO instance associated with the Microblaze. interrupt : Event An asyncio.Event-like class for waiting on and clearing interrupts. clk : Clocks The instance to control PL clocks. buf_manager : Xlnk The Xlnk memory manager used for contiguous memory allocation. buffers : dict A dictionary of cffi.FFI.CData buffer, each can be accessed similarly as arrays. intf_spec : dict The interface specification, e.g., PYNQZ1_LOGICTOOLS_SPECIFICATION. pin_map : dict A dictionary of pins available from the interface specification. status : dict A dictionary keeping track of the generator status. steps : int The number of steps during `step()` method. Equals `num_analyzer_samples` when `run()` is called. """ __instance = None __initialized = False __time_stamp = None def __new__(cls, mb_info, intf_spec_name='PYNQZ1_LOGICTOOLS_SPECIFICATION'): """Create a new Microblaze object. This method overwrites the default `new()` method so that the same instance can be reused by many modules. The internal variable `__instance` is private and used as a singleton. Parameters ---------- mb_info : dict A dictionary storing Microblaze information, such as the IP name and the reset name. intf_spec_name : str The name of the interface specification. Examples -------- The `mb_info` is a dictionary storing Microblaze information: >>> mb_info = {'ip_name': 'mb_bram_ctrl_3', 'rst_name': 'mb_reset_3', 'intr_pin_name': 'iop3/dff_en_reset_0/q', 'intr_ack_name': 'mb_3_intr_ack'} """ if cls.__instance is None or cls.__time_stamp != PL.timestamp: cls.__instance = PynqMicroblaze.__new__(cls) cls.__time_stamp = PL.timestamp cls.__initialized = False return cls.__instance def __init__(self, mb_info, intf_spec_name='PYNQZ1_LOGICTOOLS_SPECIFICATION', logictools_microblaze_bin=LOGICTOOLS_ARDUINO_BIN): """Initialize the created Microblaze object. This method leverages the initialization method of its parent. It also deals with relative / absolute path of the program. Parameters ---------- mb_info : dict A dictionary storing Microblaze information, such as the IP name and the reset name. intf_spec_name : str The name of the interface specification. logictools_microblaze_bin : str The name of the microblaze program to be loaded. Examples -------- The `mb_info` is a dictionary storing Microblaze information: >>> mb_info = {'ip_name': 'mb_bram_ctrl_3', 'rst_name': 'mb_reset_3', 'intr_pin_name': 'iop3/dff_en_reset_0/q', 'intr_ack_name': 'mb_3_intr_ack'} """ if not os.path.isabs(logictools_microblaze_bin): mb_program = os.path.join(BIN_LOCATION, logictools_microblaze_bin) else: mb_program = logictools_microblaze_bin if not self.__initialized: super().__init__(mb_info, mb_program) self.clk = Clocks self.buf_manager = Xlnk() self.buffers = dict() self.status = {k: 'RESET' for k in GENERATOR_ENGINE_DICT.keys()} self.intf_spec = eval(intf_spec_name) pin_list = list( set(self.intf_spec['traceable_io_pins'].keys()) | set(self.intf_spec['non_traceable_outputs'].keys()) | set(self.intf_spec['non_traceable_inputs'].keys())) self.pin_map = {k: 'UNUSED' for k in pin_list} self.steps = 0 self.__class__.__initialized = True def program(self): """This method programs the Microblaze. This method is called in `__init__()`; it can also be called after that. It overwrites the `program()` method defined in the parent class. """ super().reset() PL.load_ip_data(self.ip_name, self.mb_program) if self.interrupt: self.interrupt.clear() super().run() def write_control(self, ctrl_parameters): """This method writes control parameters to the Microblaze. Parameters ---------- ctrl_parameters : list A list of control parameters, each being an int. Returns ------- None """ self.write(MAILBOX_OFFSET, ctrl_parameters) def read_results(self, num_words): """This method reads results from the Microblaze. Parameters ---------- num_words : int Number of 32b words to read from Microblaze mailbox. Returns ------- list list of results read from mailbox """ return self.read(MAILBOX_OFFSET, num_words) def write_command(self, command): """This method writes the commands to the Microblaze. The program waits in the loop until the command is cleared by the Microblaze. Parameters ---------- command : int The command to write to the Microblaze. Returns ------- None """ self.write(MAILBOX_OFFSET + MAILBOX_PY2DIF_CMD_OFFSET, command) while self.read(MAILBOX_OFFSET + MAILBOX_PY2DIF_CMD_OFFSET) != 0: pass def check_status(self): """Check the status of all the generators. This method will send the command to the Microblaze, and wait for the Microblaze to return the status for all the generator. """ self.write_command(CMD_CHECK_STATUS) one_hot_status_list = self.read_results(len(GENERATOR_ENGINE_DICT)) generator_name_list = GENERATOR_ENGINE_DICT.keys() for generator_name, one_hot_status in zip(generator_name_list, one_hot_status_list): for state_name, state_code in GENERATOR_STATE.items(): if one_hot_status == state_code: self.status[generator_name] = state_name break def reset(self, generator_list): """Reset the specified generators. After reset, the corresponding generators will have to be setup again before it can be run or step. During reset, each generator will be stopped first. Parameters ---------- generator_list : list A list of generators in any state, each being a generator object. """ self.stop(generator_list) cmd_reset = CMD_RESET for generator in generator_list: generator_type = generator.__class__.__name__ cmd_reset |= GENERATOR_ENGINE_DICT[generator_type] if generator.analyzer is not None: analyzer_type = generator.analyzer.__class__.__name__ cmd_reset |= GENERATOR_ENGINE_DICT[analyzer_type] self.write_command(cmd_reset) for generator in generator_list: generator.reset() self.steps = 0 self.check_status() def run(self, generator_list): """Send the command `RUN` to the Microblaze. Send the command to the Microblaze, and wait for the Microblaze to return control. Valid generators must be objects of BooleanGenerator, PatternGenerator, FSMGenerator, or TraceAnalyzer. Parameters ---------- generator_list : list A list of READY generators, each being a generator object. """ for generator in generator_list: generator_type = generator.__class__.__name__ if self.status[generator_type] == 'RESET': raise ValueError( "{} must be at least READY before RUNNING.".format( generator_type)) cmd_run = CMD_RUN for generator in generator_list: generator_type = generator.__class__.__name__ generator.connect() cmd_run |= GENERATOR_ENGINE_DICT[generator_type] if generator.analyzer is not None: analyzer_type = generator.analyzer.__class__.__name__ cmd_run |= GENERATOR_ENGINE_DICT[analyzer_type] self.write_command(cmd_run) for generator in generator_list: generator.analyze() self.check_status() def step(self, generator_list): """Send the command `STEP` to the Microblaze. Send the command to the Microblaze, and wait for the Microblaze to return control. Valid generators must be objects of BooleanGenerator, PatternGenerator, FSMGenerator, or TraceAnalyzer. Parameters ---------- generator_list : list A list of READY generators, each being a generator object. """ for generator in generator_list: generator_type = generator.__class__.__name__ if self.status[generator_type] == 'RESET': raise ValueError( "{} must be at least READY before RUNNING.".format( generator_type)) cmd_step = CMD_STEP for generator in generator_list: generator_type = generator.__class__.__name__ cmd_step |= GENERATOR_ENGINE_DICT[generator_type] if generator.analyzer is not None: analyzer_type = generator.analyzer.__class__.__name__ cmd_step |= GENERATOR_ENGINE_DICT[analyzer_type] if self.steps == 0: for generator in generator_list: generator.connect() self.write_command(cmd_step) self.steps += 1 self.write_command(cmd_step) for generator in generator_list: generator.analyze() self.check_status() def stop(self, generator_list): """Send the command `STOP` to the Microblaze. Send the command to the Microblaze, and wait for the Microblaze to return control. Valid generators must be objects of BooleanGenerator, PatternGenerator, FSMGenerator, or TraceAnalyzer. Parameters ---------- generator_list : list A list of RUNNING generators, each being a generator object. """ cmd_stop = CMD_STOP for generator in generator_list: generator_type = generator.__class__.__name__ cmd_stop |= GENERATOR_ENGINE_DICT[generator_type] if generator.analyzer is not None: analyzer_type = generator.analyzer.__class__.__name__ cmd_stop |= GENERATOR_ENGINE_DICT[analyzer_type] self.write_command(cmd_stop) for generator in generator_list: generator.disconnect() generator.clear_wave() self.steps = 0 self.check_status() def __del__(self): """Clean up the object when it is no longer used. Contiguous memory buffers have to be freed. """ self.reset_buffers() def allocate_buffer(self, name, num_samples, data_type="unsigned int"): """This method allocates the source or the destination buffers. Usually, the source buffer stores 32-bit samples, while the destination buffer stores 64-bit samples. Note that the numpy array has to be deep-copied before users can free the buffer. Parameters ---------- name : str The name of the string, used for indexing the buffers. num_samples : int The number of samples that needs to be generated or captured. data_type : str The type of the data. Returns ------- int The address of the source or destination buffer. """ buf = self.buf_manager.cma_alloc(num_samples, data_type=data_type) self.buffers[name] = buf return self.buf_manager.cma_get_phy_addr(buf) def ndarray_from_buffer(self, name, num_bytes, dtype=np.uint32): """This method returns a numpy array from the buffer. If not data type is specified, the returned numpy array will have data type as `numpy.uint32`. The numpy array is copied. Hence even if the underlying buffer is freed, the returned numpy array is still usable. Parameters ---------- name : str The name of the buffer where the numpy array can be constructed. num_bytes : int The length of the buffer, in bytes. dtype : str Data type of the numpy array. Returns ------- numpy.ndarray The numpy array constructed from the buffer. """ if name not in self.buffers: raise ValueError( "No such buffer {} allocated previously.".format(name)) buffer = self.buffers[name] buf_temp = self.buf_manager.cma_get_buffer(buffer, num_bytes) return np.frombuffer(buf_temp, dtype=dtype).copy() def free_buffer(self, name): """This method frees the buffer. Note that the numpy array built on top of the buffer should be deep-copied before users can free the buffer. Parameters ---------- name : str The name of the buffer to be freed. """ if name in self.buffers: self.buf_manager.cma_free(self.buffers[name]) del (self.buffers[name]) def phy_addr_from_buffer(self, name): """Get the physical address from the buffer. The method takes the name of the buffer as input, and returns the physical address. Parameters ---------- name : str The name of the buffer. Returns ------- int The physical address of the buffer. """ if name not in self.buffers: raise ValueError( "No such buffer {} allocated previously.".format(name)) return self.buf_manager.cma_get_phy_addr(self.buffers[name]) def reset_buffers(self): """This method resets all the buffers. Note that the numpy array built on top of the buffer should be deep-copied before users can free the buffer. """ if self.buffers: for name in self.buffers: self.buf_manager.cma_free(self.buffers[name]) self.buffers = dict() def config_ioswitch(self, ioswitch_pins, ioswitch_select_value): """Configure the IO switch. This method configures the IO switch based on the input parameters. Parameters ---------- ioswitch_pins : list List of pins to be configured. ioswitch_select_value : int Function selection parameter. """ # Read switch config self.write_command(CMD_READ_INTF_SWITCH_CONFIG) mailbox_addr = self.mmio.base_addr + MAILBOX_OFFSET ioswitch_config = [ Register(addr) for addr in [mailbox_addr, mailbox_addr + 4] ] # Modify switch for requested entries for ix in ioswitch_pins: if ix < 10: lsb = ix * 2 msb = ix * 2 + 1 ioswitch_config[0][msb:lsb] = ioswitch_select_value else: lsb = (ix - 10) * 2 msb = (ix - 10) * 2 + 1 ioswitch_config[1][msb:lsb] = ioswitch_select_value # Write switch config self.write_command(CMD_INTF_SWITCH_CONFIG)