A Tale of Three VR Streaming Apps and Routers

I recently picked-up an Oculus Quest 2, and wanted to get wireless PCVR streaming working optimally to see what the hype was all about. I tried out AMD Relive VR and ALVR for a bit, and eventually purchased Virtual Desktop.

The experience in the beginning with Virtual Desktop was not ideal. I had random latency spikes, even at the lowest bitrate. ALVR and Relive VR were fine though, and at the time, I had assumed it was because of those programs using UDP (Virtual Desktop uses TCP). Switching Relive VR over to TCP further confirmed this (UDP was fine, but TCP resulted in complete cut-outs). The main developer of Virtual Desktop insists on using Discord for support, which seems like a terrible idea when there are multiple people trying to find solutions to issues or optimizations for their set-up (and overall, I’m not a fan of Discord).

So I gave Virtual Desktop a try for about an hour, trying various settings and doing some quick searches, but unfortunately was unable to get it working optimally. I needed to keep the active app time less than 2 hours in order to be within Oculus’s refund policy, so I ended up refunding it that same day. I returned to using AMD Relive VR since it worked the best at the time (ALVR had a bug where it wasn’t reporting IPD changes for levels 1 and 3 on the Quest 2).

I continued to hear about people raving about Virtual Desktop though. I came to the conclusion that I should be able to make Virtual Desktop work well with my set-up, and worst-case, I could pick up a cheap WiFi6 router I hear people recommend. I have 3 AC routers in my house, an Almond+, a Linksys EA6350, and a NETGEAR R6260. Ideally, I would have two of them used in separate rooms with dedicated 5GHz APs for use with Virtual Desktop, and I figure that if I sat down long enough and played with more settings, I could make at least one of the routers work well enough. This started a multi-day task of testing various firmware and settings out.

In the end, I was able to optimize my wireless set-up, and Virtual Desktop works flawlessly on both my Almond+ and NETGEAR R6260 routers. The technical details as to what settings I had to do will be on another blog post.

What I learned buying a Lenovo T500 and hardware

The Lenovo T500 is one of the last Thinkpad models that don’t have reliance on Intel’s Management Engine. This was my main interest in buying this laptop. But buying this laptop required research.

 

Wireless

There are three mPCIe slots available on this laptop. My T500 came with a half-length Intel-based wireless card present in the far-right slot, and had two antenna connection ports.

The objective for me was to find a new card. The important factor in choosing a card was that it supported the ath9k driver in Linux, as this is a completely-free and open-source driver without binary blobs, and is well-supported. Finding a list of cards that met this requirement was tricky, as there is no nicely laid-out list available for this.

I eventually was recommended the Atheros AR5BXB112 card, which uses the Atheros 9380 chipset. It supports both 2.4GHz and 5GHz bands and also 3×3 MIMO (3 antennas). The tricky part was figuring out if full-length mPCIe wireless cards were supported in this laptop, as most guides available on this recommend half-length cards. But the person who recommended me the AR5BXB112 card also mentioned they were using the full-length version, and after I bought it, I can confirm it fits and works nicely.

I’m using Coreboot on my T500, which doesn’t enforce a wireless card whitelist. I’m unsure if the AR5BXB112 card is supported on the stock Lenovo BIOS.

 

RAM

This was probably the most difficult purchase. Coreboot and Libreboot have a different manner on how they initialize RAM (raminit), and thus, have different compatibility with different memory modules that can differ from the manufacturer specifications.

I had no such luck in finding recommended Coreboot-compatible RAM for the T500, but eventually stumbled upon someone recommending the F3-8500CL7D-8GBSQ kit from G.SKILL for another Coreboot laptop. I can confirm this RAM kit works great, and G.SKILL is a memory brand I have good experience with.

I originally purchased a random unnamed memory kit that matched the specifications provided by Lenovo (PC3-8500 DDR3) which did not work.

 

CPU

Nothing inherently tricky with this. I chose the X9100 processor because of the price, and at the time of writing, I’m still waiting for it to arrive from China.

There is apparently a method for allowing quad-core processors to be used in the T500 involving a hardware modification to the CPU socket. I don’t believe I’ll be doing this.

 

SSD

Nothing tricky with this either. This laptop supports standard 2.5″ SATA drives, and I chose a SanDisk 120GB SSD (SDSSDA-120G-G27). Only SATA 3.0Gbps is supported on this motherboard, but that is still plenty fast enough with this SSD.

I have an interesting idea later on involving RAID0 and another SSD in the Ultrabay slot, but this is completely overkill and would only serve as a fun experiment.

Apparently some T500s can also come with a small 32GB Intel SSD in one of the mPCIe slots.

 

Battery

Finding an affordable (cheap) Lenovo OEM battery for a T500 doesn’t seem possible nowadays. There’s a lot of generic batteries available though, and as far as I’m concerned, are decent enough.

There are 6-cell and 9-cell batteries available. The 6-cell batteries fit the T500 perfectly without extending past the rear of the laptop. The 9-cell batteries extend a bit (possibly 2 inches) past the back of the laptop, but also have more capacity than 6-cell batteries.

I went with a 9-cell battery. Took half a month to travel across the US somehow. At max screen brightness, battery life with general web browsing seems to be around 3 hours, which is relatively decent. I will likely purchase a second battery in-case of long commutes.

 

Charger

Opposite of the battery, finding a cheap Lenovo OEM charger for a T500 isn’t too hard at all. There’s also generic chargers available.

90W chargers seem to be the best available for the T500. I ended up going for the OEM 90W (42T5000/92P1105) charger and have had no problems with it so far.

 

TrackPoint

I figure I may as well invest in some nice new TrackPoints. I imagine there’s official OEM TrackPoints available, but I went with the cheapest 3-pack I could find, which look and fit just fine.

As I understand, there are different types of TrackPoints though, and some only fit newer ThinkPad keyboards. I haven’t done too much research into this.

 

Screen

The screens supported and available for a T500 definitely required a bit of research. As I understand, most of the screen choices are backlit with CCFL. But there is one screen officially supported with LED backlighting instead. Most random eBay sellers of the T500 don’t mention detailed specifics about this.

I received a T500 with a LED-backlit WXGA (1280×800) display, which I’m relatively content with.

Undervolting a Helios 300 Laptop in Linux

I have an Acer Predator Helios 300 laptop. It’s thin, and packs pretty decent hardware, notably an Intel i7-770HQ processor, and NVIDIA GTX 1060 6GB dedicated GPU. Unfortunately, and not surprisingly, the cooling system on this laptop can’t quite keep up with the power the hardware offers.

Since I use Linux primarily, I had to figure out a solution to undervolt the processor. A quick search pulled up this descriptive blog post by Matthew Thode named Undervolting your CPU for fun and profit. The important piece of information from this post was the small Python snippet for calculating the offset, which will be useful a bit later:

format(0xFFE00000&( (round(-110*1.024)&0xFFF) <<21), '08x')

So, how to actually undervolt? I eventually found this GitHub repository by Miha Eleršič which provides instructions. I didn’t want to guess voltage offsets to try to find the best values at the time, and since I was going to re-install my Linux environment anyway, I decided to just roll a quick Windows installation to have access to ThrottleStop. After some prime95, BSoDs, and time later, I was able to learn that a -160 (rounded) voltage offset was the lowest I could go.

In ThrottleStop.ini, the undervolt value -160 is reported to be 0xEB800000. I only undervolted the CPU Core and CPU Cache, and their labels in ThrottleStop.ini were FIVRVoltage00 and FIVRVoltage20 respectively. I figured it would be a good idea to get the FIVRVoltage values for the other controls as well. Analog I/O is 40, Intel GPU is 10, ad System Agent is 30. Referring to the GitHub repository above, it mentions that the index of the Voltage Plane can be figured out from the FIVRVoltage values. The second number after FIVRVoltage isn’t useful here, so the end-result is that CPU Core is 0, Intel GPU is 1, CPU Cache is 2, System Agent is 3, Analog I/O is 4, and it’s assumed that Digital I/O is 5, and these numbers are the voltage plane index. This matches perfectly with the notes on the GitHub repository.

Now to find out how to get a usable value. The above GitHub repository gives a one-liner Python snippet that ideally should provide the correct offset, but unfortunately this gives me an error related to the name mv not being defined. Back to Matthew Thode’s Undervolting your CPU for fun and profit blog post. The Python snippet mentioned there and around the top of this post works fine. As to how I plugged in my values to that snippet, I replaced 0xFFE00000 with the voltage offset I obtained from ThrottleStop.ini, which is 0xEB800000. Next, I looked at -110, and replaced it with -160. So my snippet looked like this:

format(0xEB800000&( (round(-160*1.024)&0xFFF) <<21), '08x')

This gives me the value eb800000. Now I begin to work with the next snippet:

0x80000011F1E00000

Going by the information provided in the blog post: 80000 is the constant. The number after that is the voltage plane index, which above is 0, or the CPU Core. Next is another constant, 1, and after that is something to read/write, which is also 1. The values after that are the actual voltage offset. The only parts of that value that need changing are the voltage plane index and the actual voltage offset, which provides me the snippets 0x80000011E1800000 and 0x80000211E1800000 which is setting a -160 voltage offset on the voltage planes 0 and 2, or CPU Core and CPU Cache respectively.

Now the final step is to apply this value. This will be applied through writing a MSR register. This requires the program wrmsr, which is provided by the msr-tools package in popular Linux distributions. In-short, the above calculated values are to be written to the 0x150 MSR register. The following commands do just that, first to the CPU Core:

wrmsr '0x150' '0x80000011EB800000'

… and next to the CPU Cache:

wrmsr '0x150' '0x80000211EB800000'

Changes are applied instantly and can persist through reboots as long as a cold boot doesn't occur. Naturally, I'd like this to apply consistently after reboots, so I created the following systemd script:

[Unit]
Description=CPU Core and CPU Cache Undervolt

[Service]
Type=oneshot
ExecStart='/usr/sbin/wrmsr' '0x150' '0x80000011EB800000'
ExecStart='/usr/sbin/wrmsr' '0x150' '0x80000211EB800000'

[Install]
WantedBy=multi-user.target

... and set it to run on start.

So now I can enjoy a -160 voltage offset undervolt on my CPU while running Linux. This reduces temperatures, and more importantly, allows my processor cores to remain in Turbo Boost significantly longer without being limited by power and thermal limits. prime95 would kick me out of Turbo Boost within a few seconds without the undervolt. Now, I remain in Turbo Boost clocks the entire time I run prime95.