Weekly Report: Week3

So three weeks have already gone by and things seem to be picking up pace now. The midterm evaluation is two weeks from now and one of the thing was to have a clear set of goals for the mid term evaluation.

Opsis Board finally works!

After having spent a lot of time in changing communication modes and toggling power supply I was finally able to get the Opsis working in its default mode. So last week I was stuck at a point, as I was unable to upload the bit stream. I was getting this error at make load-gateware.

$ make load-gateware
..
..
====== Building for: ======
Platform:  opsis
Target:    opsis_hdmi2usb
Subtarget: HDMI2USBSoC
CPU type:  lm32
===========================
Open On-Chip Debugger 0.10.0-dev-00248-gf3b38ff (2016-04-03-07:23)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Warn : Adapter driver 'usb_blaster' did not declare which transports it allows; assuming legacy JTAG-only
Info : only one transport option; autoselect 'jtag'
Warn : incomplete ublast_vid_pid configuration
jtagspi_program
Info : usb blaster interface using libftdi
Error: unable to open ftdi device: device not found

The error says that load-gateware script can’t find the opsis device. This was happening because the Opsis USB was not in the correct mode required for uploading bitstream. I used some of the scripts pointed out by CarlFK for changing the required mode. Following this, I was able to change the mode to “jtag” using this, but I got a different error at  make load-gateware. (see the terminal output). When trying to read the DNA, using the same script, and got an incorrect DNA. This meant that the JTAG connection wasn’t set up correctly.  

DNA = 110000001100000011000000110000001100000011000000110000001 (0x181818181818181)

After talking to my mentor mithro, I tried again with updated HDMI2USB-mode-switch repo. This also included a Makefile to install all the relevant tools and rules for correct JTAG connection. This is the HDMI2USB-mode-switch tool for doing mode-switch. I had a hard time completing the installation of required dependencies, due to having a <space> in path to directory. Lesson learnt: Never create folder names with spaces in them. The installation steps generated a Python file in HDMI2USB-mode-switch/conda/bin/, which was supposed to run with,

$ ./<path>/hdmi2usb-mode-switch --mode=jtag

After this I encountered another error. This happens when udev rules are not installed. These come along with the HDMI2USB-mode-switch installation makefile. I had missed this in the makefile while installing other tools. This was quickly resolved.

$ make load-gateware
..
====== Building for: ======
Platform:  opsis
Target:    opsis_hdmi2usb
Subtarget: HDMI2USBSoC
CPU type:  lm32
===========================
Open On-Chip Debugger 0.10.0-dev-00248-gf3b38ff (2016-04-03-07:23)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Warn : Adapter driver 'usb_blaster' did not declare which transports it allows; assuming legacy JTAG-only
Info : only one transport option; autoselect 'jtag'
Warn : incomplete ublast_vid_pid configuration
jtagspi_program
Info : usb blaster interface using libftdi
Error: unable to open ftdi device: inappropriate permissions on device!

One other common error I encountered was, this.

$ make load-gateware
..
..
====== Building for: ======
Platform:  opsis
Target:    opsis_hdmi2usb
Subtarget: HDMI2USBSoC
CPU type:  lm32
===========================
Open On-Chip Debugger 0.10.0-dev-00248-gf3b38ff (2016-04-03-07:23)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Warn : Adapter driver 'usb_blaster' did not declare which transports it allows; assuming legacy JTAG-only
Info : only one transport option; autoselect 'jtag'
Warn : incomplete ublast_vid_pid configuration
jtagspi_program
Info : usb blaster interface using libftdi
Info : This adapter doesn't support configurable speed
Info : TAP xc6s.tap does not have IDCODE
..
Info : TAP auto19.tap does not have IDCODE
Warn : Unexpected idcode after end of chain: 21 0x00100000
Warn : Unexpected idcode after end of chain: 53 0x14049800
Warn : Unexpected idcode after end of chain: 85 0xfffffa20
Error: double-check your JTAG setup (interface, speed, ...)
Error: Trying to use configured scan chain anyway...
Error: xc6s.tap: IR capture error; saw 0x03 not 0x01
Warn : Bypassing JTAG setup events due to errors
loaded file build/opsis_hdmi2usb-hdmi2usbsoc-opsis.bit to pld device 0 in 31s 968720us

The warning means that the JTAG firmware on the FX2 has gotten confused. Use the mode-switch tool to switch to serial mode and then back to the jtag mode like this.

hdmi2usb-mode-switch --mode=serial
hdmi2usb-mode-switch --mode=jtag

This has to be repeated several times (up to three) to get the USB into correct jtag mode. So you basically have two terminal windows, one to change USB mode and other to do make load-gateware. One important observation was that if I followed certain steps than make load-gateware works without much repetitions.

  1. mode=jtag, make load-gateware, this gives the above warning.
  2. mode=serial, make load-gateware, while this is in progress (this won’t work ideally)
  3. mode=jtag, the make load-gateware will fail as usb mode was changed during process.
  4. Now make load-gateware, this should work.

Important step is to break the make load-gateware process when in serial mode by changing the mode back to jtag. Not sure why this is happening, but now won’t have to repeat a set of commands a lot of times.

After this make load-gateware succeeds, next connected to lm32 softcore using make connect-lm32, tried the bunch of options available to play around with. Added an image here, of the working setup. Still need to figure out how to load gateware and firmware independently.

Run Length Encoding (RLE)

Github Link

A very simple way to understand run length encoding is to follow this wikipedia link. We are trying to do even better that this in the sense that we will have several levels of RLE applied over and over.

For example:

Simple Example
[AABBAABB]->[#2A#2B#2A#2B]->[repeat(2,A), repeat(2,B), repeat(2,A), repeat(2,B)]

Modified RLE for hdmi2usb-mask-gen

[AABBAABB]->[#2A#2B#2A#2B]->[repeat(2,A), repeat(2,B), repeat(2,A), repeat(2,B)] ->  
[repeat( 2, ( repeat(2,A), repeat(2,B) ) ) ]

Last week I had explored the python PIL library to do basically convert an general RGB image to a list of 1s and 0s. This list was then used to  generate the B/W image again. What remained was write a function to encode a list in a run length encoded form and decode it back from the encoded list to generate the image again.

As given in the Hardware Fader Design doc, we should have a repeat class, which can be then used encode multiple levels of run length encoding. In the case of multiple levels of RLE, decoding should be pretty easy, but encoding is not that straightforward.

I am sticking with single level RLE for now, the encoded values are stored in a 2D list, in which first column corresponds to pixel count and second column corresponds to pixel value. The rows are arranged sequentially, with mapping starting from left top to right bottom along horizontal lines.

Using this idea, I was able to do the complete python mask gen setup:
1. RGB–>B/W->Matrix(1s and 0s)->1D list

  1. 1D list –(RLE encoded)–> [2xn] list with specific format
  2. [2xn] list –(RLE Decoded)–>1D list
  3. 1D list –> B/W image

So the basic idea behind RLE is that the relevant masks when copied to and from memory will consume a lot of memory bandwidth which we are already lacking, hence the mask sequences are generated in an run length encoded form by the C firmware. These encoded values are then decoded by an equivalent hardware block, written in migen. All this should be under the timing constraints of a given frame rate.

Once some python functions were done, next step was to write the C firmware.

The idea is to have function like,

struct wipe* generate_wipe(enum wipe_style type, int position, int length)

This should do two things,

  1. Generate a 2D array corresponding the wipe style and current position as compared to length.
  2. Encode the mapped 1D array according to the run length encoding (as implemented in Python) in a suitable struct.

I have done the two things independently, there is still some issues with integrating them together in a function. The problem is mostly regarding passing a 2D array or a struct array in function.

Upcoming Week’s Task

  • Test heartbeat on hardware
  • Complete the C code for generating RLE mask from templates, cleanup hdmi2usb-mask-gen
  • Documentation on 16 bit binary representation
  • Conversion of RGB+YUV to 16bit float and reverse in Migen
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s