aboutsummaryrefslogtreecommitdiff
path: root/eindopdracht-progh2-vivado/eindopdracht-progh2-vivado.srcs/sources_1/pixeldata.vhd
blob: 28ef3191dd12b9e3df3431594f4d808c129d74af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.numeric_std.all;

entity pixeldata is
	generic(
		NOTE_HEAD_OFFSET : integer := 300; -- y coordinate of center of note head
		NOTE_WIDTH : integer := 110; -- note image width
		NOTE_HEIGHT : integer := 345; -- note image height
		STAFF_SPACING : integer := 50; -- pitch between staff lines
		STAFF_TOP_Y : integer := 220); -- y position of first staff line
	port(
		CLK: in std_logic; -- system clock
		RESET: in std_logic; -- async reset
		X, Y: in std_logic_vector(9 downto 0); -- pixel x/y
		NOTE_IDX: in std_logic_vector(3 downto 0);
		NOTE_WRONG: in std_logic;
		RGB: out std_logic_vector(11 downto 0)); -- RGB output color
end pixeldata;

architecture Behavioral of pixeldata is
	component half_note_rom is port (
		clka : in std_logic;
		addra : in std_logic_vector(15 downto 0);
		douta : out std_logic_vector(0 downto 0));
	end component;

	signal iX, iY: unsigned (9 downto 0); -- pixel x/y
	signal address : unsigned (15 downto 0);
	signal data : std_logic_vector (0 downto 0);
	signal NOTE_INDEX : integer;
begin
	iX <= unsigned(X);
	iY <= unsigned(Y); 
	NOTE_INDEX <= to_integer(unsigned(NOTE_IDX));

	rom: component half_note_rom port map ( 
		clka => CLK,
		addra => std_logic_vector (address),
		douta => data
	);

	process (CLK)
		variable note_x : integer;
		variable note_y : integer;
		variable note_upright : std_logic;
		variable pixel_index : integer;
	begin
		if RESET = '1' then
			RGB <= (others => '0');
			address <= (others => '0');
			note_x := 0;
			note_y := 0;
			note_upright := '1';

		elsif rising_edge(CLK) then
			-- calculate which notes are displayed upright
			case NOTE_IDX is
				-- f,g,a upright note
				when "0000" | "0001" | "0010" => note_upright := '1';
				-- b,c,d,e,f hanging note
				when others => note_upright := '0';
			end case;

			-- base note x position
			note_x := 100;
			-- base note y position (bottom staff y position, f)
			note_y := STAFF_TOP_Y + 4 * STAFF_SPACING;
			-- shift note y up by half a staff space for each increment of note_index
			note_y := note_y - NOTE_INDEX * (STAFF_SPACING / 2);

			-- shift up note depending on if displayed upside down or not
			case note_upright is
				when '0' => note_y := note_y - NOTE_HEIGHT + NOTE_HEAD_OFFSET;
				when '1' => note_y := note_y - NOTE_HEAD_OFFSET;
			end case;

			pixel_index := to_integer(iX) - note_x + (to_integer(iY) - note_y) * NOTE_WIDTH;
			if note_upright = '0' then
				-- invert coordinates
				pixel_index := NOTE_WIDTH * NOTE_HEIGHT - pixel_index;
			end if;
			address <= to_unsigned(pixel_index, address'length);

			-- white background by default
			RGB <= x"fff";

			-- black staff lines
			if Y = STAFF_TOP_Y + 0 * STAFF_SPACING then RGB <= x"000"; end if;
			if Y = STAFF_TOP_Y + 1 * STAFF_SPACING then RGB <= x"000"; end if;
			if Y = STAFF_TOP_Y + 2 * STAFF_SPACING then RGB <= x"000"; end if;
			if Y = STAFF_TOP_Y + 3 * STAFF_SPACING then RGB <= x"000"; end if;
			if Y = STAFF_TOP_Y + 4 * STAFF_SPACING then RGB <= x"000"; end if;

			-- display note if in correct opsition
			if (iX >= note_x) and (iX < (note_x + NOTE_WIDTH)) and
			   (iY >= note_y) and (iY < (note_y + NOTE_HEIGHT)) then
				if data(0) = '0' then
					RGB <= x"f00" when NOTE_WRONG = '1' else x"000";
				end if;
			end if;
		end if;
	end process;
end Behavioral;