FM SOS

From Hamsterworks Wiki!

Jump to: navigation, search

After a bit of thinking, this FPGA Project was completed in an hour in November 2012.

Here is a simple FM transmitter that is surprisingly good, and very, very simple. The spectral qualities of the RF output will be pretty awful - this is not supposed to be a production design for anything, it is just a hack!

Fm xmit.png

A full explanation would most probably be longer than the actual code, but here goes. It is a cross between a one-bit DAC and a phase accumulator. The output is a jittery pulse train with a frequency that is 91.0MHz +/- 75kHz of modulation, plus a whole lot of nasty harmonics.

The project uses a DCM to generate a high frequency (320MHz), that runs a 32 bit accumulator.

  • Every clock cycle it adds (desired freq)/320,000,000 * 2^32 to the accumulator.
  • The upper bit then flips on and off at the desired frequency (however with around 3ns of jitter) - just plug in a wire and you are done.
  • For 91.0Mhz at either side of the FM band gives constants of 1222387958 and 1220374692, with a centre frequency constant of 1221381325.

My simple demo makes a square wave, but you if you were to use 1221381325 +/- 1,000,000 (e.g, a 16 bit signed sample plus five zeros) you can transmit high quality mono audio.

Just poke a wire into the antenna socket, configure your FPGA and you are away. There is a video of me testing the range at http://youtu.be/4YbDjc3Xb1E

This code is running on a Spartan 6 LX9, and you also need to add a DCM to give you a nice fast clock - the faster the clock the better the signal. You can also need to adjust the timing constants to put the signal on any channel you want.

Once again - this is just a demo, it is not supposed to be used for anything. And you most probably shouldn't be broadcasting SOS unless you want your neighbors to call out search and rescue.

fm_xmit

------------------------------------
- Simple FM transmitter
-
- Mike Field <hamster@snap.net.nz 
- 
------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity fm_xmit is
    Port ( clk32 : in  STD_LOGIC;
           antenna : out  STD_LOGIC);
end fm_xmit;

architecture Behavioral of fm_xmit is
   component clocking
   port ( CLK32  : in  std_logic;
          CLK320 : out std_logic
   );
   end component;
   
   signal clk320            : std_logic;
   signal shift_ctr         : unsigned (4 downto 0) := (others => '0');
   signal phase_accumulator : unsigned (31 downto 0) := (others => '0');
   signal beep_counter      : unsigned (19 downto 0):= (others => '0'); -- gives a 305Hz beep signal
   signal message           : std_logic_vector(33 downto 0) := "1010100011101110111000101010000000";
begin
   antenna <= std_logic(phase_accumulator(31));

fast_clock : clocking port map (
      CLK32 => CLK32,
      CLK320 => CLK320
   );
   
   process(clk320)
   begin
      if rising_edge(clk320) then
         if beep_counter = x"FFFFF" then
            if shift_ctr = "00000" then
               message <= message(0) & message(33 downto 1);
            end if;
            shift_ctr <= shift_ctr + 1;
         end if;      
         
         -- The constants are calculated as (desired freq)/320Mhz*2^32
         if message(0) = '1' then
            if beep_counter(19) = '1' then
               phase_accumulator <= phase_accumulator + 1222387958; -- gives a 91075kHz signal               
            else
               phase_accumulator <= phase_accumulator + 1220374692; -- gives 90925kHz signal
            end if;
         else 
            phase_accumulator <= phase_accumulator + 1221381325; -- gives 91000kHz signal
         end if;
         
         beep_counter <= beep_counter+1;
      end if;
   end process;
end Behavioral;

Personal tools