FM SOS
From Hamsterworks Wiki!
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!
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;
