Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Morse code to ASCII converter using vhdl

Status
Not open for further replies.

gn.times

Junior Member level 1
Junior Member level 1
Joined
Feb 3, 2010
Messages
18
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Location
India
Visit site
Activity points
1,417
I want to implement a Morse code to ASCII converter in vhdl and then to transmit that ASCII character to PC terminal through UART. I have completed the UART part.

But i don't know how to implement the converter part. The problem is with varying symbol rate of input Morse code. I want to detect dot, dash, character space and word space.

Please help me for the following implementation:

1. detection of Morse code symbols with variable symbol rate
2. binary search tree to traverse the Morse code tree to find the corresponding ASCII character.
 

I constructed a project which could translate a morse code broadcast on shortwave radio, into characters onscreen.

There will be a certain amount of milliseconds, to distinguish a dot from a dash. And a longer time period (of silence) which distinguishes the end of a letter.

If you do not get a mix of dots and dashes, then your time limit must be adjusted upward or downward, accordingly. I did this by tapping keys, telling the program to increment or decrement the time limit.

I thought about using a binary search tree. This would keep track of what was the prospective letter-in-progress after every dot or dash. However I found that such a scheme would require an unwieldy table of IF/THEN statements. This would risk consume needed cpu cycles. (My computer was a VIC-20 which runs at 1MHz). I decided such an algorithm would not work.

Instead I decided to create a lookup array called A$(x). I assigned each character a unique binary number, based on the pattern of dots and dashes. I automatically added a '1' prefix to every character. So that:

E = 10. This is decimal 2. So put 'E' in A$(2)
T = 11 (A$(3))
I = 100 (A$(4))
A = 101 (A$(5))
N = 110 (A$(6))
M = 111 (A$(7))
etc.

At the start of every new letter, start with 1 as the running value.
If a dot arrives, multiply the running value by 2.
If a dash arrives, multiply it by 2, and add 1.

If the time limit is exceeded, then you regard that as marking the end of a letter.
Look up the current value in the array. Print the character to screen.

If a long enough time period goes by, then you regard that as marking the end of a word. Print a space.
 

I constructed a project which could translate a morse code broadcast on shortwave radio, into characters onscreen.

There will be a certain amount of milliseconds, to distinguish a dot from a dash. And a longer time period (of silence) which distinguishes the end of a letter.

I'm also using the same approach (adding 0 for dot and 1 for dash to a shift register with an initial value of 00000001).
But the problem is with detecting counts of dash and dots.

Here is the program I have written as of now:

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
------------------------------------------------------------------------------------------------------
-- Morse Detector Entity
------------------------------------------------------------------------------------------------------
entity detection_e is
port(
		clk_i 			: in std_logic; -- clock
		reset_i			: in std_logic; -- reset 
		morse_i 		: in std_logic; -- Morse input
      	        char_o			: out std_logic_vector (7 downto 0); -- shift reg to store the data
		--temp
		high_count_o	        : out integer;
		low_count_o		: out integer;
		sreg_o			: out std_logic_vector (7 downto 0)
	);
end detection_e; 
------------------------------------------------------------------------------------------------------
-- Morse Detector Architecture
------------------------------------------------------------------------------------------------------
architecture detection_a of detection_e is
type state_type_t is (rst_st, wait_st, ccheck_st, scheck_st);

signal state_s, nextstate_s        : state_type_t;
signal sreg_s, sreg_nxt_s           : std_logic_vector (7 downto 0);
signal high_count_s, high_count_nxt_s : integer range 0 to 100000; -- time period count - Morse input is high
signal low_count_s, low_count_nxt_s   : integer range 0 to 100000; -- time period count - Morse input is low
signal dd_space_s, dd_space_nxt_s     : integer range 0 to 65500;  -- one time period low count

begin
-------------------------------------------------------------------------------
-- clock the states
-------------------------------------------------------------------------------
  process(clk_i, reset_i)
  begin
    if (reset_i = '1') then
        state_s <= rst_st;
    elsif (clk_i'event and clk_i = '1') then
        state_s <= nextstate_s;
        sreg_s <= sreg_nxt_s;
	high_count_s <= high_count_nxt_s;
	low_count_s <= low_count_nxt_s;
	dd_space_s <= dd_space_nxt_s;
    end if;
  end process;
-------------------------------------------------------------------------------
--FSM to detect dots and dash
------------------------------------------------------------------------------- 
	process (clk_i, state_s, morse_i, high_count_s, low_count_s, sreg_s, dd_space_s)
		begin
			nextstate_s <= state_s;
			sreg_nxt_s <= sreg_s;
			high_count_nxt_s <= high_count_s;
			low_count_nxt_s <= low_count_s;
			dd_space_nxt_s <= dd_space_s;
			
			case state_s is
			-- reset state
     			         when rst_st  => 	sreg_nxt_s <= "00000001";
							high_count_nxt_s <= 0;
							low_count_nxt_s <=0;
							char_o <= "00000001";
							nextstate_s <= wait_st;
										
				when wait_st  =>	if (morse_i = '1') then  
							    high_count_nxt_s <= high_count_s+ 1;
							    nextstate_s <= ccheck_st;
							elsif (morse_i = '0') then 
								low_count_nxt_s <= low_count_s + 1;
								nextstate_s <= scheck_st;
							end if;
				
				when ccheck_st=>	
							-- condition to check for dot
							if (high_count_s /=0 and high_count_s = low_count_s) then
								high_count_nxt_s <= 0;
								low_count_nxt_s <=0;
								dd_space_nxt_s   <= low_count_s;
								sreg_nxt_s <= sreg_s(6 downto 0) & '0';
								nextstate_s <= wait_st;
							-- condition to check for dash
							elsif (high_count_s /=0 and high_count_s = 3*low_count_s) then
								high_count_nxt_s <= 0;
								low_count_nxt_s <=0;
								dd_space_nxt_s   <= low_count_s;
								sreg_nxt_s <= sreg_s(6 downto 0) & '1';
								nextstate_s <= wait_st;
							
							elsif (morse_i = '1') then  
								high_count_nxt_s <= high_count_s+ 1;
								elsif (morse_i = '0') then 
								low_count_nxt_s <= low_count_s + 1;
							end if;
										
				when scheck_st  =>-- condition to check for character space
							if (low_count_s /=0 and low_count_s = 3*dd_space_s) then
								high_count_nxt_s <= 0;
								low_count_nxt_s <=0;
								dd_space_nxt_s   <= low_count_s;
								char_o <= sreg_s;
								sreg_nxt_s <= x"01";
								nextstate_s <= wait_st;
							 elsif (morse_i = '0') then 
								low_count_nxt_s <= low_count_s + 1;
							elsif (morse_i = '1') then 
								low_count_nxt_s <= 0;
								high_count_nxt_s <= high_count_s + 1;
								nextstate_s <= ccheck_st;
							end if;
										
				when others => nextstate_s <= rst_st;
			end case;				
	end process;
-------------------------------------------------------------------------------
-- output 
-------------------------------------------------------------------------------
	high_count_o <= high_count_nxt_s;
	low_count_o <= low_count_nxt_s;	
	sreg_o <= sreg_s;

end detection_a;

I'm facing the issue that I don't know when to start checking the counts. Because as per above algorithm if highcount = 3*lowcount then I'm considering it as dash. But for a dot when the program is counting lows'(after counting highs) before it completes the count when highcount becomes 3 times of low count then it considers it as dash.

please help
 

Set a quantity of milliseconds (we'll call it X), which distinguishes between a dot and a dash. I seem to remember a reasonable value being 80 mSec.

When a beep begins, start a loop. Count time until the beep ends.
(My VIC-20 automatically reported time with a variable called TI. Each increment was 1/60 of a second.)

See how long was the beep. If it is less than X, you have a dot. Otherwise it's a dash.

Then start an idle loop. When a beep begins, jump to the time-counting loop.
If silence lasts 200 mSec (I think), then process your current character.

(In this testing phase, make the program print out what it is doing. Time counts, dots, dashes, etc.)

If you see mostly dots or mostly dashes, then you must change X, to match the speed of the keyer. You can do this manually, or you can devise an automatic routine.

I did not write an automatic routine. I tapped keys to raise or lower the value of X. If I got all dashes then I had to increment X.
If all dots then I had to decrement it.
 

I did not write an automatic routine. I tapped keys to raise or lower the value of X. If I got all dashes then I had to increment X.
If all dots then I had to decrement it.

I want to design the digital circuit in such a way that it should take value of X automatically which means even if the morse code symbol rate varies, the detector should detect the dot, dash, character space and word space correctly
 

I want to design the digital circuit in such a way that it should take value of X automatically which means even if the morse code symbol rate varies, the detector should detect the dot, dash, character space and word space correctly

you need to generate a clock that changes, so you will need to identify dot spaces, and then load a dds circuit with new rate value.
 

I want to design the digital circuit in such a way that it should take value of X automatically which means even if the morse code symbol rate varies, the detector should detect the dot, dash, character space and word space correctly

X is the average value of beeps. Roughly midway between the length of a dot and a dash.

You can re-calculate it after (a) every beep, or (b) every character, or (c) every 3 or 4 seconds, etc.

Method 'A' is fine if you have cpu cycles to spare. The straightforward way is to use an equation such as:

Xnew = ( 4 * Xprevious + Latest_beep_length ) / 5

Method 'C' may take up less cpu cycles. To calculate X, tally beep lengths for 3 seconds, then divide by quantity of beeps.

My VIC-20 could just about keep pace with the fastest morse speeds. I decided to omit a routine for recalculating X, and changed it manually instead.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top