---------------------------------------------------------------------------
-- (c) 2013 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_MISC.all;

ENTITY pokey_mixer IS
PORT 
( 
	CLK : IN STD_LOGIC;

	SUM : IN STD_LOGIC_VECTOR(6 downto 0); -- unsigned
	
	VOLUME_OUT_NEXT : OUT STD_LOGIC_vector(15 downto 0)
);
END pokey_mixer;

ARCHITECTURE vhdl OF pokey_mixer IS
	signal volume_next : std_logic_vector(15 downto 0);

	signal y1 : signed(15 downto 0);
	signal y1_reg : signed(15 downto 0);
	signal y2 : signed(15 downto 0);
	signal ych : signed(15 downto 0);
	signal yadj_next : signed(31 downto 0);
	signal yadj_reg : signed(31 downto 0);

	signal b_in : signed(15 downto 0);
BEGIN
process(clk)
begin
	if (clk'event and clk='1') then
		YADJ_REG <= YADJ_NEXT;
		Y1_REG <= Y1;
	END IF;
END PROCESS;

	-- next state
 	process (sum, y1, y2, y1_reg, yadj_reg)
		type LOOKUP_TYPE is array (0 to 32) of signed(15 downto 0);
		variable lookup : LOOKUP_TYPE;
	begin
		-- replace with piecewise interp. Takes a mul unit but saves lookup space.

		lookup := (x"86E8" ,x"9E40" ,x"B3E3" ,x"C7E3" ,x"DA52" ,x"EB42" ,x"FAC5" ,x"08ED" ,x"15CB" ,x"2172" ,x"2BF4" ,x"3562" ,x"3DCE" ,x"454B" ,x"4BEA" ,x"51BD" ,x"56D6" ,x"5B47" ,x"5F22" ,x"6278" ,x"655C" ,x"67E0" ,x"6A15" ,x"6C0D" ,x"6DDB" ,x"6F90" ,x"713E" ,x"72F7" ,x"74CD" ,x"76D2" ,x"7918" ,x"7BB0" ,x"7EAD");

		y1 <= lookup(to_integer(unsigned(sum(5 downto 1))));
		y2 <= lookup(to_integer(unsigned(sum(5 downto 1)))+1);

		ych <= y2-y1;

		volume_next <= std_logic_vector(yadj_reg(20 downto 5) + y1_reg);

		--case volume_sum(9 downto 0) is 
		--end case;
        end process;

	B_in <= signed("00000000000"&sum(0 downto 0)&"0000");
	linterp_mult : entity work.mult_infer
	PORT MAP( A => signed(ych),
		  B => b_in,
		  RESULT => yadj_next);
	
	-- output
	volume_out_next <= volume_next;
		
END vhdl;
