Index: atari_chips/pokeyv2/audio_signal_detector.vhd
===================================================================
--- atari_chips/pokeyv2/audio_signal_detector.vhd	(nonexistent)
+++ atari_chips/pokeyv2/audio_signal_detector.vhd	(revision 1467)
@@ -0,0 +1,186 @@
+---------------------------------------------------------------------------
+-- (c) 2024 mark watson
+-- I am happy for anyone to use this for non-commercial use.
+-- If my vhdl files are used commercially or otherwise sold,
+-- please contact me for explicit permission at scrameta (gmail).
+-- This applies for source and binary form and derived works.
+---------------------------------------------------------------------------
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all; 
+use ieee.numeric_std.all;
+USE IEEE.STD_LOGIC_UNSIGNED.ALL;
+use IEEE.STD_LOGIC_MISC.all;
+use work.AudioTypes.all;
+
+LIBRARY work;
+
+ENTITY audio_signal_detector IS 
+	PORT
+	(
+		CLK : IN STD_LOGIC;
+		RESET_N : IN STD_LOGIC;
+		AUDIO : IN SIGNED(15 downto 0);
+		SAMPLE : IN STD_LOGIC;
+		VOLUME: IN STD_LOGIC_VECTOR(1 downto 0);
+		
+		DETECT_OUT : OUT STD_LOGIC
+	);
+END audio_signal_detector;		
+		
+ARCHITECTURE vhdl OF audio_signal_detector IS
+	-- find zero
+	signal moving_avg_reg : signed(15 downto 0);
+	signal moving_avg_next : signed(15 downto 0);
+
+	-- amplitude detector
+	signal min_level_reg : signed(11 downto 0);
+	signal min_level_next : signed(11 downto 0);
+
+	signal max_level_reg : signed(11 downto 0);
+	signal max_level_next : signed(11 downto 0);
+
+	signal amplitude_reg  : unsigned(11 downto 0);
+	signal amplitude_next : unsigned(11 downto 0); 
+
+	-- zero crossing	
+	signal zero_crosses_reg : unsigned(10 downto 0);
+	signal zero_crosses_next : unsigned(10 downto 0);
+
+	signal above_zero_reg : std_logic;
+	signal above_zero_next : std_logic;
+
+	-- when to check
+	signal enable_check_pre : std_logic;
+	signal enable_check : std_logic;
+
+	-- how to interpret results
+	signal enabled_reg : unsigned(6 downto 0);
+	signal enabled_next : unsigned(6 downto 0);
+	
+BEGIN
+	 process(CLK,reset_n)
+	 begin
+	   if (reset_n='0') then
+			enabled_reg <= (others=>'0');
+			min_level_reg <= (others=>'1');
+			max_level_reg <= (others=>'0');			
+			amplitude_reg <= (others=>'0');			
+			zero_crosses_reg <= (others=>'0');
+			above_zero_reg <= '0';
+			moving_avg_reg <= (others=>'0');
+		elsif (CLK'event and CLK='1') then
+			enabled_reg <= enabled_next;
+			min_level_reg <= min_level_next;
+			max_level_reg <= max_level_next;
+			amplitude_reg <= amplitude_next;
+			zero_crosses_reg <= zero_crosses_next;
+			above_zero_reg <= above_zero_next;
+			moving_avg_reg <= moving_avg_next;
+		end if;
+	 end process;	
+	 
+enable_div : work.enable_divider
+	generic map (COUNT=>1024)
+	port map(clk=>CLK,reset_n=>reset_n,enable_in=>'1',enable_out=>enable_check_pre);
+
+enable_div2 : work.enable_divider
+	generic map (COUNT=>1024)
+	port map(clk=>CLK,reset_n=>reset_n,enable_in=>enable_check_pre,enable_out=>enable_check);
+
+-- moving avg
+process(moving_avg_reg,sample,audio)
+begin
+	moving_avg_next <= moving_avg_reg;
+	
+	if (sample='1') then
+		--moving_avg_next <= resize(moving_avg_reg(15 downto 1),16) + resize(moving_avg_reg(15 downto 2),16) + resize(moving_avg_reg(15 downto 3),16) + resize(moving_avg_reg(15 downto 4),16)+ resize(moving_avg_reg(15 downto 5),16) + resize(audio(15 downto 5),16);
+		moving_avg_next <= (moving_avg_reg - resize(moving_avg_reg(15 downto 5),16)) + resize(audio(15 downto 5),16);
+	end if;
+end process;	
+	
+-- zero crossing
+process(audio,moving_avg_reg,zero_crosses_reg,above_zero_reg,enable_check)
+	variable audio_nodc : signed(15 downto 0);
+begin
+	above_zero_next <= above_zero_reg;
+	zero_crosses_next <= zero_crosses_reg;
+
+	audio_nodc := audio - moving_avg_reg;
+	
+	above_zero_next <= not(audio_nodc(15));
+
+	if ((above_zero_reg xor not(audio_nodc(15)))='1') then
+		zero_crosses_next <= zero_crosses_reg+1;
+	end if;
+
+	if (enable_check='1') then
+		zero_crosses_next <= (others=>'0');
+	end if;
+end process;
+
+-- amplitude
+process(audio,min_level_reg,max_level_reg,amplitude_reg,enable_check,enabled_reg)
+begin
+	min_level_next <= min_level_reg;
+	max_level_next <= max_level_reg;
+	amplitude_next <= unsigned(max_level_reg-min_level_reg);
+
+	if (audio(15 downto 4)<min_level_reg) then
+		min_level_next <= audio(15 downto 4);
+	end if;
+
+	if (audio(15 downto 4)>max_level_reg) then
+		max_level_next <= audio(15 downto 4);
+	end if;	
+
+	if (enable_check='1') then
+		min_level_next(11) <= '0';
+		min_level_next(10 downto 0) <= (others=>'1');
+		max_level_next(11) <= '1';
+		max_level_next(10 downto 0) <= (others=>'0');
+	end if;
+end process;
+
+process(audio,amplitude_reg,zero_crosses_reg,enable_check,enabled_reg,volume)
+	variable detected : std_logic;
+	variable amplitude_threshold : unsigned(11 downto 0);
+	variable zero_crosses_threshold : unsigned(10 downto 0);
+begin
+	enabled_next <= enabled_reg;
+
+	case volume is
+	when "01" =>
+		amplitude_threshold := to_unsigned(32,12);
+	when "10" =>
+		amplitude_threshold := to_unsigned(64,12);
+	when others =>
+		amplitude_threshold := to_unsigned(128,12);
+	end case;
+
+	zero_crosses_threshold := to_unsigned(256,11);
+	
+	if (enable_check='1') then
+		detected := '0';
+		if (amplitude_reg>amplitude_threshold and zero_crosses_reg<zero_crosses_threshold) then
+			detected := '1';
+		end if;	
+		if (detected='1' and enabled_reg<119) then
+			enabled_next <= enabled_reg+8;
+		end if;
+		if (detected='0' and enabled_reg>0) then
+			enabled_next <= enabled_reg-1;
+		end if;		
+	end if;
+end process;
+
+process(enabled_reg)
+begin
+	detect_out <= '0';
+	if (enabled_reg>=64) then
+		detect_out <= '1';
+	end if;		
+	
+end process;
+
+END vhdl;
Index: atari_chips/pokeyv2/build.sh
===================================================================
--- atari_chips/pokeyv2/build.sh	(revision 1466)
+++ atari_chips/pokeyv2/build.sh	(revision 1467)
@@ -950,6 +950,7 @@
 			`cp -r fir_*vhdl $dir`;
 			`cp -r fir_sample_buffer* $dir`;
 			`cp -r fir_buffer* $dir`;
+			`cp -r audio_sig* $dir`;
 		
 			chdir $dir;
 		
Index: atari_chips/pokeyv2/pokeymax.vhd
===================================================================
--- atari_chips/pokeyv2/pokeymax.vhd	(revision 1466)
+++ atari_chips/pokeyv2/pokeymax.vhd	(revision 1467)
@@ -462,24 +462,16 @@
 	signal adc_use_reg : signed(15 downto 0);
 	signal adc_use_next : signed(15 downto 0);
 
+	signal adc_frozen_reg : signed(15 downto 0);
+	signal adc_frozen_next : signed(15 downto 0);
+	
+	signal sio_noise : signed(15 downto 0);
+
 	signal adc_in_signed : signed(15 downto 0);
 	signal adc_out_signed : signed(15 downto 0);
 	
-	signal adc_min_reg : signed(11 downto 0);
-	signal adc_min_next : signed(11 downto 0);
+	signal adc_enabled : std_logic;
 
-	signal adc_max_reg : signed(11 downto 0);
-	signal adc_max_next : signed(11 downto 0);
-
-	signal adc_diff_reg  : unsigned(11 downto 0);
-	signal adc_diff_next : unsigned(11 downto 0); 
-
-	signal adc_enabled_reg : unsigned(5 downto 0);
-	signal adc_enabled_next : unsigned(5 downto 0);
-
-	signal enable_reset_min_max_pre : std_logic;
-	signal enable_reset_min_max : std_logic;
-	
 	signal adc_valid : std_logic;
 	signal adc_output : std_logic_vector(19 downto 0);
 
@@ -2049,18 +2041,12 @@
 	 begin
 	   if (reset_n='0') then
 			adc_reg <= (others=>'0');
-			adc_enabled_reg <= (others=>'0');
 			adc_use_reg <= (others=>'0');
-			adc_min_reg <= (others=>'1');
-			adc_max_reg <= (others=>'0');			
-			adc_diff_reg <= (others=>'0');			
+			adc_frozen_reg <= (others=>'0');
 		elsif (CLK49152'event and CLK49152='1') then
 			adc_reg <= adc_next;
-			adc_enabled_reg <= adc_enabled_next;
 			adc_use_reg <= adc_use_next;
-			adc_min_reg <= adc_min_next;
-			adc_max_reg <= adc_max_next;
-			adc_diff_reg <= adc_diff_next;
+			adc_frozen_reg <= adc_frozen_next;
 		end if;
 	 end process;	
 	 
@@ -2101,14 +2087,6 @@
 );
 	SIO_AUDIO <= unsigned(not(adc_use_reg(15))&adc_use_reg(14 downto 0));
 
-enable_div : work.enable_divider
-	generic map (COUNT=>128)
-	port map(clk=>CLK49152,reset_n=>reset_n,enable_in=>'1',enable_out=>enable_reset_min_max_pre);
-
-enable_div2 : work.enable_divider
-	generic map (COUNT=>128)
-	port map(clk=>CLK49152,reset_n=>reset_n,enable_in=>enable_reset_min_max_pre,enable_out=>enable_reset_min_max);
-
 process(adc_reg,adc_output,adc_valid,ADC_VOLUME_REG)
 	variable adc_shrunk : signed(19 downto 0);
 begin
@@ -2115,7 +2093,7 @@
 	adc_next <= adc_reg;
 
 	if (adc_valid='1') then
-		adc_shrunk := signed(not(adc_output(19)) & adc_output(18 downto 0));
+		adc_shrunk := (signed(not(adc_output(19)) & adc_output(18 downto 0)));
 		case ADC_VOLUME_REG is
 			when "01" =>
 				adc_next <= adc_shrunk(19 downto (19-16+1)); --*1
@@ -2129,69 +2107,37 @@
 	end if;	
 end process;
 
-process(adc_out_signed,adc_min_reg,adc_max_reg,adc_diff_reg,enable_reset_min_max,adc_enabled_reg,adc_volume_reg)
-	variable detected : std_logic;
-	variable threshold : unsigned(11 downto 0);
-begin
-	adc_min_next <= adc_min_reg;
-	adc_max_next <= adc_max_reg;
-	adc_diff_next <= unsigned(adc_max_reg-adc_min_reg);
-	adc_enabled_next <= adc_enabled_reg;
+audio_signal_detector1 : work.audio_signal_detector
+	port map(clk=>CLK49152,reset_n=>reset_n,audio=>adc_in_signed,sample=>adc_valid,volume=>adc_volume_reg,detect_out=>adc_enabled);
 
-	if (adc_out_signed(15 downto 4)<adc_min_reg) then
-		adc_min_next <= adc_out_signed(15 downto 4);
-	end if;
 
-	if (adc_out_signed(15 downto 4)>adc_max_reg) then
-		adc_max_next <= adc_out_signed(15 downto 4);
-	end if;	
+process(adc_use_reg,adc_frozen_reg,adc_enabled,adc_out_signed,sio_noise)
+begin
+	adc_frozen_next <= adc_frozen_reg;	
 
-	case adc_volume_reg is
-	when "01" =>
-		threshold := to_unsigned(8,12);
-	when "10" =>
-		threshold := to_unsigned(16,12);
-	when others =>
-		threshold := to_unsigned(32,12);
-	end case;
+	adc_use_next <= adc_frozen_reg xor sio_noise;	
+		
+	if (adc_enabled='1') then
+		adc_frozen_next <= adc_out_signed;
+	end if;		
 	
-	if (enable_reset_min_max='1') then
-	   detected := '0';
-		if (adc_diff_reg>threshold) then
-			detected := '1';
-		end if;	
-		if (detected='1' and adc_enabled_reg<63) then
-			adc_enabled_next <= adc_enabled_reg+1;
-		end if;
-		if (detected='0' and adc_enabled_reg>0) then
-			adc_enabled_next <= adc_enabled_reg-1;
-		end if;		
-		adc_min_next(11) <= '0';
-		adc_min_next(10 downto 0) <= (others=>'1');
-		adc_max_next(11) <= '1';
-		adc_max_next(10 downto 0) <= (others=>'0');
-	end if;
 end process;
 
-process(adc_reg,adc_enabled_reg,adc_out_signed,SIO_RXD_SYNC,SIO_DATA_VOLUME_REG)
+process(SIO_RXD_SYNC,SIO_DATA_VOLUME_REG)
 begin
-	adc_use_next <= adc_use_reg;
-	if (adc_enabled_reg>=32) then
-		adc_use_next <= adc_out_signed;
-	else
-		case SIO_DATA_VOLUME_REG is
-			when "01" =>
-				adc_use_next(10) <= SIO_RXD_SYNC;
-			when "10" =>
-				adc_use_next(11) <= SIO_RXD_SYNC;
-			when "11" =>
-				adc_use_next(12) <= SIO_RXD_SYNC;
-			when others =>
-		end case;
-	end if;
+	sio_noise <= (others=>'0');
+	
+	case SIO_DATA_VOLUME_REG is
+		when "01" =>
+			sio_noise(10) <= not(SIO_RXD_SYNC);
+		when "10" =>
+			sio_noise(11) <= not(SIO_RXD_SYNC);
+		when "11" =>
+			sio_noise(12) <= not(SIO_RXD_SYNC);
+		when others =>
+	end case;			
 end process;
 
-
 end generate adc_on;
 
 adc_off : if enable_adc=0 generate 
Index: atari_chips/pokeyv2/pokeymaxv4.qsf
===================================================================
--- atari_chips/pokeyv2/pokeymaxv4.qsf	(revision 1466)
+++ atari_chips/pokeyv2/pokeymaxv4.qsf	(revision 1467)
@@ -263,6 +263,7 @@
 set_instance_assignment -name IO_STANDARD "3.3 V SCHMITT TRIGGER" -to BCLK
 
 set_global_assignment -name OPTIMIZATION_MODE BALANCED
+set_global_assignment -name VHDL_FILE audio_signal_detector.vhd
 set_global_assignment -name VHDL_FILE flash_controller.vhd
 set_global_assignment -name VHDL_FILE stereo_detect.vhd
 set_global_assignment -name VHDL_FILE iox_glue.vhdl
