Generating VGA video with Verilog

I’ve started work on an FPGA based Z80 computer. I wanted to generate the video in the FPGA as well, turns out VGA is fairly easy to generate. There’s numerous websites that describe the timing and parameters of the various VGA modes, and how VGA works.

This project is also my Verilog learning experience, so pardon any horrible code.

In a nutshell, for basic VGA you need a total of 5 digital output lines. One for horizontal sync, one for vertical, and one each for the red, green, and blue video signals. The RGB signals are actually analog, but for my purposes implemented as digital, either on or off. That allows a total of eight colors, including white and black. For now the text is only color. To produce additional colors, the RGB lines can be driven with a D/A converter, which could be as simple as a resistor ladder circuit.

These analog voltages need to be limited to under 1 volt. The FPGA I/O outputs are 3.3 volts so a simple resistor and diode circuit was used for each line. Here’s the circuit, as you can see it is quite simple. Virtually any reasonably fast diode can be used:

I decided to use the standard 640 x 480 60 Hz mode, as it would be more than adequate for my goal of displaying 25 lines of 80 characters.

Each character is displayed as a 8 by 16 pixel matrix, resulting in 640 x 400 pixels, the rest of the screen is not used.

The design was implemented on a RioRand EP2C5T144 Altera Cyclone II FPGA Mini Development Board available at Amazon for $19.99. What a deal.

I used the free version of Altera’s Quartus II software package.

Video memory is a 2K byte dual ported RAM, organized in a linear fashion, using 2000 bytes.

The character generator ROM is a 1K ROM, storing 8 rows of 8 pixels for each of the 128 ASCII characters. Each row is displayed twice, for a total of 16 rows. As of now the high bit of the stored ASCII value in video memory is not used, I plan on eventually using it to implement a low-res color graphics mode, a la the Apple ][.

The RioRand-EP2C5T144 FPGA dev board has a 50 MHz oscillator signal as a clock input. I implemented a 4x PLL to produce an internal 200 MHz clock. While the 50 MHz clock is adequate for 640×480 video, the faster clock will allow higher resolution video modes down the road.

A state machine is used to generate the video. A frame of video actually has 525 scan lines, it starts with 10 “front porch” lines (essentially all black video lines), then 2 lines of vertical sync, followed by 33 more “back porch” lines.
Front porch and back porch are old terms from the original NTSC analog TV system developed in the 1940s. You’ll see that totals 45 lines, leaving 480 lines of actual video.

Each video line has 800 pixels (as far as timing is concerned). There’s a front porch of 16 pixels, 96 pixels of horizontal sync, 48 pixels of a back porch, then 640 pixels of actual video content. At a 200 MHz clock, each pixel is 8 clock cycles.

Prior to the display of a pixel, the video RAM is read. The lower 7 bits of the byte, which is the ASCII value of the character to be displayed, is used along with 3 bits of the video line, to form a 10 bit address into the character generator.

Since each line of a character is displayed twice, bits [3:1[ and not [2:0] of the video line are used. If I was willing to dedicate 2K to the character ROM, I could display 16 rows of pixels for each character.

The resulting VGA video, the video RAM was pre-loaded with data using the Altera MegaWizard option to do so from an Intel Hex file.

Verilog Code:

module vga1

// these are placeholders for when we hook up a CPU later
reg [15:0] addressWriteVideoRam=16'b0;
reg [7:0] dataInWriteVideoRam;
wire [7:0] dataOutReadVideoRam;
reg writeEnableWriteVideoRam=1'b0;
reg writeVideoRamClock;

// VGA video generator, undocumented for now. Good luck. 
input clock_in; // 50 MHz input clock

// RGB outputs
output reg red;
output reg green;
output reg blue;

// horizontal and vertical sync outputs
output reg hsync;
output reg vsync;

wire pllClock;
pll my_pll (clock_in, pllClock); // 200 MHz clock from the 50 MHz board clock

reg	[9:0]  char_rom_address;
wire	[7:0]  char_rom_output;
reg char_rom_clock;
reg [7:0] char_rom_data_byte;

reg pixel;
reg [15:0] clockCounter; // 200 MHz clock
reg [15:0] pixelCounter; // 25 MHz pixel clock
reg video_inclock;	// video RAM clock
reg video_wren; // not used yet
reg [7:0] video_data; // not used yet

// 1K x 8 bit video character ROM, 8 lines of 8 pixels for 128 characters, high ASCII bit not used
char_rom my_char_rom(char_rom_address, char_rom_clock, char_rom_output);

// 2K video dual port RAM for 25 lines of 80 characters	
video_ram_dp the_video_ram(.address_a (video_display_address[10:0]), .data_a(video_data), .clock_a(video_inclock), .wren_a(video_wren), .q_a(video_data_byte) ,
	.address_b(addressWriteVideoRam[10:0]), .data_b(dataInWriteVideoRam), .clock_b(writeVideoRamClock), .wren_b(writeEnableWriteVideoRam), .q_b(dataOutReadVideoRam)  );

reg [15:0] video_display_address;
wire [7:0] video_data_byte;

reg [15:0] horzCounter=16'd0;
reg [15:0] lineCounter=16'd0;

// VGA640x480x60_200mhz clock
parameter pixel_rate=8;
parameter horz_front_porch=16*pixel_rate;  
parameter horz_sync=96*pixel_rate;  		
parameter horz_back_porch=48*pixel_rate;
parameter horz_line=800*pixel_rate;
parameter vert_front_porch=10;
parameter vert_sync=2;
parameter vert_back_porch=33;
parameter vert_frame=525;
parameter horz_sync_polarity = 1'b0;
parameter vert_sync_polarity = 1'b0;
parameter first_video_line=49; // first line of video
parameter number_of_video_lines=400; // 25 ASCII lines of 16 pixels each is 400 video lines

always @(negedge pllClock)
always @(posedge pllClock)

	if (clockCounter[2:0]==7) pixelCounter<=pixelCounter+1'b1;

	if (pixelCounter[2:0]==7) begin
		case (clockCounter[2:0])
//		0 : not used
//		1 : not used
		3 : char_rom_address<={video_data_byte[6:0],lineCounter[3:1]}; // high 7 bits of charactor ROM address is the ASCII character, low 3 bits video line counter, we display each line twice
		4 : char_rom_data_byte<=char_rom_output; // latch the character ROM data
//		5 : not used
		6 : video_inclock<=0;	// clock video for next ASCII character
		7 : video_inclock<=1;
	if (horzCounter==0)	begin  // set video to black
	if (horzCounter==horz_front_porch)	hsync<=horz_sync_polarity;
	if (horzCounter==(horz_front_porch+horz_sync))	hsync<=!horz_sync_polarity;

	if ( (lineCounter>=(vert_front_porch+vert_sync+vert_back_porch+first_video_line)) && (lineCounter<=(vert_front_porch+vert_sync+vert_back_porch+first_video_line+number_of_video_lines)) )  begin // video frame time

		if ((pixelCounter[2:0]==6) && (clockCounter[2:0]==7)) video_display_address<=video_display_address+1'b1;

		if (horzCounter==(horz_front_porch+horz_sync+horz_back_porch))	begin
			pixelCounter<=0; // start of video line
		if (horzCounter>=(horz_front_porch+horz_sync+horz_back_porch))	begin // video line
			case (pixelCounter[2:0])
			0 : pixel=char_rom_data_byte[0];
			1 : pixel=char_rom_data_byte[1];
			2 : pixel=char_rom_data_byte[2];
			3 : pixel=char_rom_data_byte[3];
			4 : pixel=char_rom_data_byte[4];
			5 : pixel=char_rom_data_byte[5];
			6 : pixel=char_rom_data_byte[6];
			7 : pixel=char_rom_data_byte[7];
			// set RGB outputs
			end  // video line time
	end // video frame time

	horzCounter <= horzCounter + 16'd1;
	if (horzCounter==horz_line) begin // end of scan line, set video to black

		if (lineCounter>=(vert_front_porch+vert_sync+vert_back_porch)) begin // video frame time
			if (lineCounter[3:0]!=4'd15) video_display_address<=video_display_address-8'd100; else video_display_address<=video_display_address-8'd20;  // 80 chars back to beginning of line
		if (lineCounter==vert_front_porch) vsync<=vert_sync_polarity;
		if (lineCounter==(vert_front_porch+vert_sync)) vsync<=!vert_sync_polarity;
		if (lineCounter==vert_frame) begin	// end of the video frame, start over
			video_display_address<=466;		// offset so we start reading video data at the correct address


Privacy Policy

A. Introduction

The privacy of our website visitors is very important to us, and we are committed to safeguarding it. This policy explains what we will do with your personal information.
Consenting to our use of cookies in accordance with the terms of this policy when you first visit our website permits us to use cookies every time you visit our website.
B. Credit
This document was created using a template from SEQ Legal (
and modified by Website Planet (

C. Collecting personal information

The following types of personal information may be collected, stored, and used:

information about your computer including your IP address, geographical location, browser type and version, and operating system;
information about your visits to and use of this website including the referral source, length of visit, page views, and website navigation paths;
information, such as your email address, that you enter when you register with our website;
information that you enter when you create a profile on our website—for example, your name, profile pictures, gender, birthday, relationship status, interests and hobbies, educational details, and employment details;
information, such as your name and email address, that you enter in order to set up subscriptions to our emails and/or newsletters;
information that you enter while using the services on our website;
information that is generated while using our website, including when, how often, and under what circumstances you use it;
information relating to anything you purchase, services you use, or transactions you make through our website, which includes your name, address, telephone number, email address, and credit card details;
information that you post to our website with the intention of publishing it on the internet, which includes your username, profile pictures, and the content of your posts;
information contained in any communications that you send to us by email or through our website, including its communication content and metadata;
any other personal information that you send to us.
Before you disclose to us the personal information of another person, you must obtain that person’s consent to both the disclosure and the processing of that personal information in accordance with this policy

D. Using your personal information

Personal information submitted to us through our website will be used for the purposes specified in this policy or on the relevant pages of the website. We may use your personal information for the following:

administering our website and business;
personalizing our website for you;
enabling your use of the services available on our website;
sending you goods purchased through our website;
supplying services purchased through our website;
sending statements, invoices, and payment reminders to you, and collecting payments from you;
sending you non-marketing commercial communications;
sending you email notifications that you have specifically requested;
sending you our email newsletter, if you have requested it (you can inform us at any time if you no longer require the newsletter);
sending you marketing communications relating to our business or the businesses of carefully-selected third parties which we think may be of interest to you, by post or, where you have specifically agreed to this, by email or similar technology (you can inform us at any time if you no longer require marketing communications);
providing third parties with statistical information about our users (but those third parties will not be able to identify any individual user from that information);
dealing with inquiries and complaints made by or about you relating to our website;
keeping our website secure and prevent fraud;
verifying compliance with the terms and conditions governing the use of our website (including monitoring private messages sent through our website private messaging service); and
other uses.
If you submit personal information for publication on our website, we will publish and otherwise use that information in accordance with the license you grant to us.

Your privacy settings can be used to limit the publication of your information on our website and can be adjusted using privacy controls on the website.

We will not, without your express consent, supply your personal information to any third party for their or any other third party’s direct marketing.

E. Disclosing personal information

We may disclose your personal information to any of our employees, officers, insurers, professional advisers, agents, suppliers, or subcontractors as reasonably necessary for the purposes set out in this policy.

We may disclose your personal information to any member of our group of companies (this means our subsidiaries, our ultimate holding company and all its subsidiaries) as reasonably necessary for the purposes set out in this policy.

We may disclose your personal information:

to the extent that we are required to do so by law;
in connection with any ongoing or prospective legal proceedings;
in order to establish, exercise, or defend our legal rights (including providing information to others for the purposes of fraud prevention and reducing credit risk);
to the purchaser (or prospective purchaser) of any business or asset that we are (or are contemplating) selling; and
to any person who we reasonably believe may apply to a court or other competent authority for disclosure of that personal information where, in our reasonable opinion, such court or authority would be reasonably likely to order disclosure of that personal information.
Except as provided in this policy, we will not provide your personal information to third parties.

F. International data transfers

Information that we collect may be stored, processed in, and transferred between any of the countries in which we operate in order to enable us to use the information in accordance with this policy.
Information that we collect may be transferred to the following countries which do not have data protection laws equivalent to those in force in the European Economic Area: the United States of America, Russia, Japan, China, and India.
Personal information that you publish on our website or submit for publication on our website may be available, via the internet, around the world. We cannot prevent the use or misuse of such information by others.
You expressly agree to the transfers of personal information described in this Section F.
G. Retaining personal information

This Section G sets out our data retention policies and procedure, which are designed to help ensure that we comply with our legal obligations regarding the retention and deletion of personal information.
Personal information that we process for any purpose or purposes shall not be kept for longer than is necessary for that purpose or those purposes.
Without prejudice to article G-2, we will usually delete personal data falling within the categories set out below at the date/time set out below:
personal data type will be deleted after 24 months.
Notwithstanding the other provisions of this Section G, we will retain documents (including electronic documents) containing personal data:
to the extent that we are required to do so by law;
if we believe that the documents may be relevant to any ongoing or prospective legal proceedings; and
in order to establish, exercise, or defend our legal rights (including providing information to others for the purposes of fraud prevention and reducing credit risk).
H. Security of your personal information

We will take reasonable technical and organizational precautions to prevent the loss, misuse, or alteration of your personal information.
We will store all the personal information you provide on our secure (password- and firewall-protected) servers.
All electronic financial transactions entered into through our website will be protected by encryption technology.
You acknowledge that the transmission of information over the internet is inherently insecure, and we cannot guarantee the security of data sent over the internet.
You are responsible for keeping the password you use for accessing our website confidential; we will not ask you for your password (except when you log in to our website).
I. Amendments

We may update this policy from time to time by publishing a new version on our website. You should check this page occasionally to ensure you understand any changes to this policy. We may notify you of changes to this policy by email or through the private messaging system on our website.

J. Your rights

You may instruct us to provide you with any personal information we hold about you; provision of such information will be subject to the following:

the payment of a fee to be determined based on the cost to provide the data; and
the supply of appropriate evidence of your identity, we will usually accept a photocopy of your passport certified by a notary plus an original copy of a utility bill showing your current address.
We may withhold personal information that you request to the extent permitted by law.

You may instruct us at any time not to process your personal information for marketing purposes.

In practice, you will usually either expressly agree in advance to our use of your personal information for marketing purposes, or we will provide you with an opportunity to opt out of the use of your personal information for marketing purposes.

K. Third party websites

Our website includes hyperlinks to, and details of, third party websites. We have no control over, and are not responsible for, the privacy policies and practices of third parties.

L. Updating information

Please let us know if the personal information that we hold about you needs to be corrected or updated.

M. Cookies

Our website uses cookies. A cookie is a file containing an identifier (a string of letters and numbers) that is sent by a web server to a web browser and is stored by the browser. The identifier is then sent back to the server each time the browser requests a page from the server. Cookies may be either “persistent” cookies or “session” cookies: a persistent cookie will be stored by a web browser and will remain valid until its set expiry date, unless deleted by the user before the expiry date; a session cookie, on the other hand, will expire at the end of the user session, when the web browser is closed. Cookies do not typically contain any information that personally identifies a user, but personal information that we store about you may be linked to the information stored in and obtained from cookies.
We use both session and persistent cookies on our website.

The names of the cookies that we use on our website, and the purposes for which they are used, are set out below:
we use Google Analytics and Adwords on our website to recognize a computer when a user visits the website, track users as they navigate the website, enable the use of a shopping cart on the website,
improve the website’s usability, analyze the use of the website, administer the website, prevent fraud and improve the security of the website, personalize the website for each user,
target advertisements which may be of particular interest to specific users.
Most browsers allow you to refuse to accept cookies—for example:
in Internet Explorer (version 10) you can block cookies using the cookie handling override settings available by clicking “Tools,” “Internet Options,” “Privacy,” and then “Advanced”;
in Firefox (version 24) you can block all cookies by clicking “Tools,” “Options,” “Privacy,” selecting “Use custom settings for history” from the drop-down menu, and unticking “Accept cookies from sites”; and
in Chrome (version 29), you can block all cookies by accessing the “Customize and control” menu, and clicking “Settings,” “Show advanced settings,” and “Content settings,” and then selecting “Block sites from setting any data” under the “Cookies” heading.
Blocking all cookies will have a negative impact upon the usability of many websites. If you block cookies, you will not be able to use all the features on our website.

You can delete cookies already stored on your computer—for example:
in Internet Explorer (version 10), you must manually delete cookie files (you can find instructions for doing so at );
in Firefox (version 24), you can delete cookies by clicking “Tools,” “Options,” and “Privacy”, then selecting “Use custom settings for history”, clicking “Show Cookies,” and then clicking “Remove All Cookies”; and
in Chrome (version 29), you can delete all cookies by accessing the “Customize and control” menu, and clicking “Settings,” “Show advanced settings,” and “Clear browsing data,” and then selecting “Delete cookies and other site and plug-in data” before clicking “Clear browsing data.”
Deleting cookies will have a negative impact on the usability of many websites.

Those Wacky Pescadores

Pescadore is the term used by Pirate DXers to refer to a fishermen operating on the 43 meter band, the plural is pescadores, often abbreviated as peskies. While they can turn up anywhere on the band (or outside it), 6925 LSB seems to be the most common frequency, which can cause QRM to pirates operating on 6925 AM. They also turn up on 6933 LSB fairly often.

Usually you hear them chatting with each other; informal QSOs. Sometimes however they have been known to play music, or engage in other activities fairly close to broadcasting. They can actually be entertaining to listen to.

Here is a recording of them from the other night, starting just before 0000 UTC on 21 September, 2016.

Pescadores have even inspired a pirate radio station named Pesky Party Radio, most recently heard last month. This station plays Spanish language covers of popular songs, and is rather hilarious.

Running an RTL SDR USB Dongle On Your Mac The Easy Way With Cocoa RTL Server

I’ve had a few of the RTL radio tuner dongles for a while. These are USB devices that were originally made for use as TV tuners overseas, but it turns out that you can access the I/Q data stream, and turn them into an SDR (Software Defined Radio). They can be tuned roughly over a range of 25 to 1700 MHz, and sometimes even higher, depending on the tuner IC chip inside the particular dongle.

I previously posted about how to get the RTL dongle working on the Mac here: An SDR for $17 – The R820T USB RTL-SDR DVB-T Dongle and here: An SDR for $17 – The R820T USB RTL-SDR DVB-T Dongle – Part 2. These posts were from 2013, and I did the installation on a Mac running OS X 10.6, using some pre-built libraries.

Fast forward to the present day. I got a new Mac running OS X 10.11 El Capitan, and I wanted to be able to use the RTL dongles with my favorite SDR software on the Mac, SdrDx. Enter Cocoa RTL Server.

Cocoa RTL Server is a stand alone app that interfaces with an RTL dongle. It does not require you to build or install any drivers or libraries. It just works. It’s based off of an open source app called SoftShell, that I heavily extended. Cocoa RTL Server also acts like a networked SDR, following the RF Space protocol. That means it works with SdrDx, as well as any other SDR app on the Mac that supports RF Space SDRs like the netSDR. You can download a copy of the app from the Cocoa RTL Server page. Source code is included, however I am not offering any support for the project or final app.

Here’s a screenshot of the app running:

Getting up and running is easy:

1. Plug in your RTL device
2. Run CocoaRTLServer 2.0
3. Select the device from the popup menu (usually it is already selected)
4. Change the rtl_tcp or tx_tcp port values if needed
5. Click Open
6. Configure your SDR app (set the correct TCP port) and run it

I’ve run it under Mac OS X 10.6, 10.10 and 10.11, It should run under 10.7-10.9 as well. It only works with RTL devices with an E4000 or R820T tuner IC.

Using SdrDx, I can tune a large portion of the FM broadcast band, click to view full size:

In this case I am tuned to 97.9 MHz. To the left of the signal meter, you can see it has decoded the station ID from the RDS data. Yes, SdrDx decodes RDS.

If you look at the lower right corner, you see the scope display of the demodulated FM audio. There are markers for the portions of interest:
You can see the main audio above the green marker to the left.
The stereo pilot at 19 kHz (red marker).
The stereo subcarrier (aquamarine)
The RDS data (orange)
The 67 kHz SCA subcarrier (purple)
The 92 kHz SCA subcarrier (yellow)

Cocoa RTL Server also includes a server that emulates rtl_tcp, so it works with Cocoa1090 which decodes aircraft transponders that transmit on 1090 MHz. It should also work with any other app that gets data from rtl_tcp. Here’s a screenshot of Cocoa1090 running:

Receiving DGPS Stations with MultiMode For Mac OS X

MultiMode for Mac OS X can decode DGPS (Differential Global Positioning System) transmissions. DGPS stations transmit the difference between positions indicated by GPS satellite systems and the known fixed position of the station. This allows higher accuracy. DGPS transmissions are 100 or 200 baud and are transmitted on frequencies from 285 kHz to 325 kHz. They can be interesting DX targets.

A copy of MultiMode can be downloaded here:

To decode the transmission, tune your radio to a DGPS frequency. You can either tune directly to the frequency in CW mode, in which case you set the center frequency in MultiMode to that for your radio’s CW mode, or use USB mode, tune 1 kHz low, and set the center frequency to 1000 Hz.

You can listen to an example DGPS audio recording

Select the baud rate, either 100 or 200 baud, using the button. Also be sure to set your location so that the correct distance and bearing is calculated. Eventually, if you have tuned into a DGPS transmission that is strong enough, you will start seeing decode messages printed:

The Short Demod button can be toggled on, in which case MultiMode will look at a smaller part of the DGPS packet. This often allows decodes of weaker transmissions.

Note that since no error checking is performed on the packet, it is possible to get false decodes. To help determine if you are actually receiving the correct station, compare the printed frequency for that station to what your radio is tuned to, to verify they match. Also look for several decodes from the same station in a row, that indicates that you probably are really receiving that station.

Here’s a list of some stations I have received here with a modest 200 ft random wire antenna:

[15:44:47 11/19/15] 008 804 008 009 286.0 kHz Sandy Hook, NJ United States 40.4747 -74.0197 235.632 km 45.2895 deg
[19:27:49 11/19/15] 198 772 198 199 306.0 kHz Acushnet, MA United States 41.7492 -70.8886 529.571 km 53.1416 deg
[19:28:52 11/19/15] 190 782 190 191 305.0 kHz Dandridge, TN United States 36.0225 -83.3067 723.745 km 245.071 deg
[19:29:12 11/19/15] 156 863 156 157 311.0 kHz Rock Island IL United States 42.0203 -90.2311 1245.06 km 290.156 deg
[19:32:00 11/19/15] 012 806 012 013 289.0 kHz Driver, VA United States 36.9633 -76.5622 231.719 km 192.449 deg
[19:33:00 11/19/15] 184 788 184 185 291.0 kHz Hawk Run, PA United States 40.8889 -78.1889 280.839 km 319.079 deg
[19:33:24 11/19/15] 006 803 006 007 293.0 kHz Moriches, NY United States 40.7944 -72.7564 340.978 km 53.1725 deg
[19:33:37 11/19/15] 196 771 196 197 294.0 kHz New Bern, NC United States 35.1806 -77.0586 434.825 km 192.789 deg
[19:33:50 11/19/15] 092 843 092 093 295.0 kHz St Mary's, WV United States 39.4381 -81.1758 448.281 km 277.867 deg
[19:33:54 11/19/15] 136 792 136 137 297.0 kHz Bobo, MS United States 34.1253 -90.6964 1414.92 km 252.075 deg
[19:33:59 11/19/15] 058 847 058 059 301.0 kHz Annapolis, MD United States 39.0181 -76.61 52.734 km 272.373 deg
[19:36:40 11/19/15] 046 824 046 047 303.0 kHz Greensboro, NC United States 36.0694 -79.7381 463.251 km 226.48 deg
[19:40:01 11/19/15] 218 777 218 219 304.0 kHz Mequon, WI United States 43.2025 -88.0664 1110.64 km 298.697 deg
[19:41:11 11/19/15] 130 834 130 131 307.0 kHz Hagerstown, MD United States 39.5553 -77.7219 160.52 km 293.159 deg
[19:43:59 11/19/15] 312 929 312 313 296.0 kHz St Jean Richelieu, QC Canada 45.3244 -73.3172 736.38 km 16.5642 deg
[19:44:05 11/19/15] 154 862 154 155 322.0 kHz St Louis, MO United States 38.6189 -89.7644 1190.3 km 272.301 deg
[19:55:36 11/19/15] 112 836 112 113 292.0 kHz Cheboygan, MI United States 45.6556 -84.475 1013.8 km 319.521 deg
[20:32:19 11/19/15] 017 808 016 017 314.0 kHz Card Sound, FL United States 25.4417 -80.4525 1560.45 km 196.764 deg
[20:34:44 11/19/15] 340 942 340 341 288.0 kHz Cape Ray, NL Canada 47.6356 -59.2408 1650.3 km 49.1252 deg
[22:10:54 11/19/15] 168 869 168 169 290.0 kHz Louisville, KY United States 38.0175 -85.31 816.337 km 265.238 deg
[22:11:34 11/19/15] 192 778 192 193 292.0 kHz Kensington, SC United States 33.4906 -79.3494 681.801 km 207.126 deg
[22:20:26 11/19/15] 320 925 320 321 313.0 kHz Moise, QC Canada 50.2025 -66.1194 1464.05 km 28.7438 deg
[11:34:56 11/20/15] 262 881 262 263 302.0 kHz Point Loma, CA United States 32.6769 -117.25 3697.45 km 272.2 deg

Poor conditions for some on 43 meters last night, better for others

One measure of the strength of the ionosphere is called foF2. It is the maximum frequency that will be reflected straight back. That is imagine the radio transmitter and receiver are located near each other, the radio waves go straight up, and are reflected straight back down to the receiver. foF2 is continuously varying, based on solar activity, and what part of the Earth the Sun is over. You can find a real time map at this URL:

As the distance between the transmitter and receiver increases, the radio waves are not perpendicular to the ionosphere, but instead strike it at an angle. This allows frequencies higher than foF2 to be reflected. The angle that the radio waves strike the ionosphere depends on the distance between the transmitter and receiver, and the height of the ionosphere, which unfortunately also varies. This is called the hmF2, and there’s a real time map of it also:

The Maximum Usable Frequency (MUF) can be found by:
MUF = foF2 * sqrt( 1+ [D/(2*hmF2)]^2) where D is the distance in km.

Lately, foF2 has been reaching very low values once the Suns sets. This is what causes the 43 meter band to “go long”, making it difficult to impossible to hear stations even many hundreds of miles away. As an example, here is a plot of the measured foF2 value taken over Wallops Island, VA. Consider these values typical for much of the eastern US during this time period:

The blue trace is today’s foF2 values, red is yesterday’s, and the green trace is an average of the last five days.

foF2 was about 5 MHz at 2300z, dropping to 4.5 MHz by 0000z. This was evident in the loggings for The Crystal Ship. Many listeners who normally get a strong signal from this station had poor or no reception (as was my case). This was also the start of a geomagnetic storm, the K index at 0000z was 3, and has since risen to 5 as I type this.

The flip side of a low foF2 value is that listeners at a greater distance from a station can get stronger signals. The geomagnetic storm last night could also have actually enhanced reception for some listeners. Medium wave DXers have referred to geomagnetic storms as “stirring the gumbo”, bringing in a different mix of station than are normally heard.

Update – here is the link to the real time Wallops Island foF2 chart: and the current graph itself:

A Statistical Analysis of A Somewhat Subjective Rating of the Day’s Weather

Below is an analysis of the Capital Weather Gang’s “Daily Digit”, a number from 1 to 10 given each morning to the day’s expected weather. 574 days worth of Daily Digits were analyzed, from March 19, 2013 through October 13, 2014. The starting date was picked as that was the first date where it was easy to get a copy of the CWG’s archived web pages.

The mean daily digit was 6.32.

Below is a trend graph of the Daily Digit, smoothed slightly to make it more readable:

The slope upwards over time could be an artifact of the range of dates chosen, or it could be genuine Daily Digit Inflation.

Below is a histogram of the Daily Digit values:

There were only five days with a Daily Digit of 1; they were:

June 13, 2013 – David Streit (Severe weather)
December 9, 2013 – Jason Samenow (“Sloppy, cloudy and cold”)
December 29, 2013 – Brian Jackson (“40s and soaking rain in December”)
January 3, 2014 – A. Camden Walker (Icy from snow the night before)
January 28, 2014 – Matt Rogers (“Cruel cold slaps us in the face again”)

The mean Daily Digit per month of the year:

The mean Daily Digit per day of the week:

The mean Daily Digit per author:

There is a fairly regular rotation of authors, each generally writing on the same day, hence the strong correlation between the above two graphs. Each author had between 73 to 81 posts.

Not included in the above were the following two authors with a limited number of Daily Digits:
Kathryn Prociv: 10 entries with a mean of 8.3
Rick Grow: 8 entries with a mean of 5.0

There were also a few cases where two authors were credited the same day, also not included above:
Matt Rogers;Jason Samenow: 3 entries with a mean of 3.33
Brian Jackson;Dan Stillman: 2 entries: with a mean of 3.5
A. Camden Walker;Ian Livingston: 1 entry with a mean of 2 (January 10, 2014, Freezing Rain)
Dan Stillman;Ian Livingston: 1 entry with a mean of 4 (February 15, 2014, Snow)
Dan Stillman;Jason Samenow: 1 entry with a mean of 3 (February 26, 2014, “Mother Nature hits the repeat button with light morning snow”)

A big thanks to the Capital Weather Gang for their fabulous posts each day!


Here’s histograms for each author:

Winter 2013-2014 Snowfall

With March ending, I’m hoping we’re done with snow. Here are my measured snowfall totals for the season:

Sunday December 8, 2013: 7 inches snow, some freezing rain
Tuesday December 10, 2013: 6.25 inches snow
Saturday December 14, 2013: 2.5 inches snow
Tuesday December 17, 2013: 0.5 inches snow
Thursday December 26, 2013: 0.75 inches snow

December 2013 total: 17.00 inches snow

Thursday January 2, 2014: 6.00 inches snow
Friday January 10, 2014: 0.25 inches snow
Saturday January 18, 2014: 1.00 inches snow
Tuesday January 21, 2014: 8.00 inches snow
Wednesday January 29, 2014: 0.50 inches snow
Friday January 31, 2014 Graupel

January 2014 total: 15.75 inches snow

Monday February 3, 2014: 7.00 inches snow
Wednesday February 5, 2014: Ice Storm : 1/4 – 1/2 inch freezing rain, 1.00 inch snow / sleet
Sunday February 9, 2014: 1.75 inches snow
Thursday February 13, 2014: 16 inches of snow in the morning, 4 inches at night, 20 inches total
Saturday February 15, 2014: 0.5 inches snow
Monday February 17, 2014: 2.0 inches snow
Tuesday February 25, 2014: 0.25 inches snow
Wednesday February 26, 2014: 0.5 inches snow

February 2014 total: 33.00 inches snow

Monday March 3, 2014: 3.0 inches snow
Monday March 17, 2014: 3.75 inches snow
Tuesday March 25, 2014: 1.50 inches snow
Wednesday March 26, 2014: Dusting of snow
Sunday March 30, 2014: 4.0 inches of snow
March 2014 total: 12.25 inches snow

2014-2013 season total: 78.00 inches snow

Looking for some iPad/iPhone apps? Here are a few that I have written:

Pictures of some snowfall events:

January 31, 2014 Graupel:
January 31, 2014 Graupel

February 5, 2014 Ice Storm:
February 5, 2014 Ice Storm
February 5, 2014 Ice Storm

February 13, 2014 Snow storm, pictures taken on the 14th:
February 13, 2014 snowfall
February 13, 2014 snowfall

March 30, 2014 Surprise snow storm

Looking for some iPad/iPhone apps? Here are a few that I have written:

A Very Busy Christmas Weekend/Eve For Pirates

Here’s what folks have been hearing since Friday night. 41 different North American pirate radio transmissions so far, a total of 163 loggings, and it’s not even Christmas yet!

A big thank you to the operators for their shows, and the listeners for their reports.

All of these loggings can be viewed at the HF Underground

Pirate Radio Boston 6925 AM 1945 UTC December 24, 2012
WBNY 6240 AM 1604 UTC December 24, 2012
Eccentric Shortwave 6930 USB 1529 UTC December 24, 2012
Channel Z 6925 AM 1400 UTC December 24, 2012
UNID 6925 USB 1455 UTC December 24, 2012
Metro Radio International 6975 AM 1323 UTC December 24, 2012
Radio Ronin 6920 AM 1308 UTC December 24, 2012
Northwoods Radio 6925 USB 1200 UTC December 24, 2012
Channel Z 6925 AM 0427 UTC December 24, 2012
UNID 6955 AM 0212 UTC December 24, 2012
Rave On Radio 6925 USB 0200 UTC December 24, 2012
Radio GaGa 6925 USB 0140 UTC December 24, 2012
Radio Appalachia 6935 AM 0125 UTC December 24, 2012
Dit Dah Radio 6925 USB 0025 UTC December 24, 2012
Dit Dah Radio 6935 USB 2156 UTC December 23, 2012
WBNY 6913.34 AM 2150 UTC December 23, 2012
WKND 6924.6 AM 2148 UTC December 23, 2012
Metro Radio International 6925 AM 2008 UTC December 23, 2012
WEDG The Edge 1610 AM 1700 UTC December 23, 2012
Pirate Radio Boston 6925 AM 1612 UCT December 23, 2012
Pirate Radio Boston 6950 AM 1610 UTC December 23, 2012
Pirate Radio Boston 6925 AM 1805 UTC December 23, 2012
Channel Z 6925 AM 1346 UTC 23 December 23, 2012
1720 KHz “The Big Q” 0509 UTC December 23, 2012
Channel Z 6925 AM 0405 UTC December 23, 2012
WPOD 6925 USB 0130 UTC December 23, 2012
Wolverine Radio 6925 USB 0048 UTC December 23, 2012
Toynbee Radio 6925 AM 2258 UTC December 22, 2012
Monkey Mayan Memorial Radio 6925 AM 2222 UTCDecember 22, 2012
UNID 6950 USB 2218 UTC December 22, 2012
UNID 6924.7 Khz AM 2215 UTC December 22, 2012
Toynbee Radio 6925 AM 2131 UTC December 22, 2012
Pirate Radio Boston 6949.39 AM 2015 UTC December 22, 2012
UNID 6935 AM 1902 UTC December 22, 2012
Pirate Radio Boston 6949.39 AM 1355 UTC 2December 22, 2012
Rave On Radio 6925 USB 1241 UTC December 22, 2012
The Big Q 1720 & 1710 AM 0525 UTC December 22, 2012, 2208 UTC
Captain Morgan Shortwave 6950.7 AM 0240 UTC December 22, 2012
UNID 6925 AM 0225 UTC December 21, 2012
UNID 6924 AM 0203 also 6929 AM 0207 December 22, 2012
Insane Radio 6925 AM 0121 UTC December 22, 2012
Insane Radio SSTV 6925 AM 0021 UTC December 22, 2012

What’s All This SDR Stuff, Anyhow?

The Software Defined Radio (SDR) has become very popular in the radio hobby scene over the last few years. Many hobbyists own one, certainly most have heard of them. But what is an SDR, and why might you want one, over a traditional radio?

First, a very brief explanation of how the traditional superhetrodyne radio works. This is the type of radio you have, if you don’t have an SDR (and you don’t have a crystal radio).

Here’s a block diagram of a typical superhetrodyne receiver:

superhetrodyne block diagram

The antenna is connected to a RF amplifier, which amplifies the very weak signals picked up by the antenna. Some high end radios put bandpass filters between the antenna and RF amplifier, to block strong out of band signals which could cause mixing products and images.

Next, the signals are passed to a mixer, which also gets fed a single frequency from the local oscillator. A mixer is a non linear device that causes sum and difference frequencies to be produced. I won’t go into the theory of exactly how it works. The local oscillator frequency is controlled by the tuning knob on the radio. It is offset by a fixed amount from the displayed frequency. That amount is called the IF frequency. For example, the IF of an radio may be 455 kHz. Time for an example…

Say you’re tuned to 6925 kHz. The local oscillator generates a frequency of 6470 kHz, which is 455 kHz below 6925 kHz. The mixer mixes the 6470 kHz signal with the incoming RF from the antenna. So the RF from a station transmitting on 6925 kHz gets mixed with 6470 kHz, producing a sum (6925+6470=13395 kHz) and difference (6925-6470=455 kHz) signal. The IF Filter after the mixer only passes frequencies around 455 kHz, it blocks others. So only the difference frequencies of interest, from the 6925 kHz station, get paseed. This signal is then amplified again, fed to a demodulator to convert the RF into audio frequencies, and fed to an audio amplifier, and then the speaker. The IF filter is what sets the selectivity of the radio, the bandwidth. Some radios have multiple IF filters that can be switched in, say for wide audio (maybe 6 Khz), and narrow (maybe 2.7 kHz). Perhaps even a very narrow (500 Hz) filter for CW.

This is a very basic example. Most higher end HF radios actually have several IF stages, with two or three being most common. The Icom R-71A, a fairly high end radio for its time (the 1980s) had four IF stages. Additional IF stages allow for better filtering of the signal, since it is not possible to build real physical filters with arbitrary capabilities. There’s a limit to how much filtering you can do at each stage.

Now, onto the SDR. I’ll be describing a Direct Digital Sampling (DDS) style SDR. The other style is the Quadrature Sampling Detector (QSD), such as the “SoftRock” SDR. The QSD SDR typically mixes the incoming RF to baseband, where it is then fed to the computer via a sound card interface for processing. The main advantage of the QSD SDR is price, it is a lot cheaper due to fewer components. The sacrifice is performance and features. You can’t get more than about 192 kHz bandwidth with a sound card, and you suffer from signal degradation caused by the sound card hardware. Some try to compensate for this by buying high end sound card interfaces, but at that point you’re approaching the price point of a DDS SDR in total hardware cost anyway.

Here is a block diagram of the SDR-IQ, courtesy of RF Space, you can click on it to see an enlarged image.
sdr-iq block diagram

The RF input (from the antenna) goes in at the left end, much of the front end is the same as a traditional radio. There’s an attenuator, protection against transients/static, and switchable bandpass filters and an amplifier. Finally the RF is fed into an A/D converter clocked at 66.666 MHz. An A/D (Analog to Digital) Converter is a device that continuously measures a voltage, and sends those readings to software for processing. Think of it as a voltmeter. The RF signals are lots of sine waves, all jumbled together. At a very fast rate, over 66 million times per second in this case, the A/D converter is measuring the voltage on the antenna. You’ve got similar A/D converters on the sound card input to your computer. The difference is that a sound card samples at a much lower rate, typically 44.1 kHz. So the A/D in an SDR is sampling about a thousand times faster. It is not too much of a stretch to say that the front end of an SDR is very similar to sticking an antenna into your sound card input. In fact, for many years now, longwave radio enthusiasts have used sound cards, especially those that can sample at higher rates such as 192 kHz, as SDRs, for monitoring VLF signals.

The output of the A/D converter, which at this point is not RF but rather a sequence of voltage readings, is fed to the AD6620, which is where the actual DSP (Digital Signal Processing) is done. The AD6620 is a dedicated chip for this purpose. Other SDRs, such as the netSDR, use a device called a FPGA (Field Programmable Gate Array), which, as the name implies, can be programmed for different uses. It has a huge number of digital logic gates, flip flops, and other devices, which can be interconnected as required. You just need to download new programming instructions. The AD6620 or FPGA does the part of the “software” part of the SDR, the other part being done in your computer.

The DSP portion of the SDR (which is software) does the mixing, filtering, and demodulation that is done in analog hardware in a traditional radio. If you looked at a block diagram of the DSP functions, they would be basically the same as in a traditional radio. The big advantage is that you can change the various parameters on the fly, such as IF filter width and shape, AGC constants, etc. Automatic notch filters become possible, identifying and rejecting interference. You can also realize tight filters that are essentially impossible with actual hardware. With analog circuitry, you introduce noise, distortion, and signal loss with each successive stage. With DSP, once you’ve digitized your input signal, you can perform as many operations as you wish, and they are all “perfect”. You’re only limited by the processing power of your DSP hardware.

Since it is not possible feed a 66 MHz sampled signal into a computer (and the computer may not have the processing power to handle it), the SDR software filters out a portion of the 0-30 MHz that is picked up by the A/D by mixing and filtering, and sends a reduced bandwidth signal to the computer. Often this is in the 50 to 200 kHz range, although more recent SDRs allow wider bandwidths. The netSDR, for example, supports a 1.6 MHz bandwidth.

With a 200 kHz bandwidth, the SDR could send sampled RF to the computer representing 6800 to 7000 kHz. Then additional DSP software in the computer can further process this information, filtering out and demodulating one particular radio station. Some software allows multiple stations to be demodulated at the same time. For example, the Spectravue software by RF Space allows two frequencies to be demodulated at the same time, one fed to the left channel of the sound card, and one to the right. So you could listen to 6925 and 6955 kHz at the same time.

Another obvious benefit of an SDR is that you can view a real time waterfall display of an entire band. Below is a waterfall of 43 meters at 2200 UTC (click on it to enlarge):
43 meter band waterfall

You can see all of the stations operating at one glance. If a station goes on the air, you can spot it within seconds.

Finally, an SDR allows you to record the sampled RF to disk files. You can then play it back. Rather than just recording a single frequency, as you can with a traditional radio, you can record an entire band. You can then go back and demodulate any signals you wish to. I’ll often record 6800 to 7000 kHz overnight, then go back to look for any broadcasts of interest.

For brevity, I avoided going into the details of exactly how the DSP software works, that may be the topic of a future post.

And yes, I borrowed the “What’s All this… Stuff, Anyhow” title from the late great Bob Pease, an engineer at National Semiconductor, who wrote a fabulous series of columns under that title at EDN magazine for many years.