📄 mousectrl.vhd
字号:
-- sets the value of x_pos from another module when setx is active
-- else, computes the new x_pos from the old position when new x
-- movement detected by adding the delta movement in x_inc, or by
-- adding 256 or -256 when overflow occurs.
set_x: process(clk)
variable x_inter: std_logic_vector(10 downto 0);
variable inc: std_logic_vector(10 downto 0);
begin
if(rising_edge(clk)) then
-- if setx active, set new x_pos value
if(setx = '1') then
x_pos <= '0' & value;
-- if delta movement received from mouse
elsif(x_new = '1') then
-- if negative movement on x axis
if(x_sign = '1') then
-- if overflow occurred
if(x_overflow = '1') then
-- inc is -256
inc := "11100000000";
else
-- inc is sign extended x_inc
inc := "111" & x_inc;
end if;
-- intermediary horizontal position
x_inter := x_pos + inc;
-- if first bit of x_inter is 1
-- then negative overflow occurred and
-- new x position is 0.
-- Note: x_pos and x_inter have 11 bits,
-- and because xpos has only 10, when
-- first bit becomes 1, this is considered
-- a negative number when moving left
if(x_inter(10) = '1') then
x_pos <= (others => '0');
else
x_pos <= x_inter;
end if;
-- if positive movement on x axis
else
-- if overflow occurred
if(x_overflow = '1') then
-- inc is 256
inc := "00100000000";
else
-- inc is sign extended x_inc
inc := "000" & x_inc;
end if;
-- intermediary horizontal position
x_inter := x_pos + inc;
-- if x_inter is greater than x_max
-- then positive overflow occurred and
-- new x position is x_max.
if(x_inter > ('0' & x_max)) then
x_pos <= '0' & x_max;
else
x_pos <= x_inter;
end if;
end if;
end if;
end if;
end process set_x;
-- sets the value of y_pos from another module when sety is active
-- else, computes the new y_pos from the old position when new y
-- movement detected by adding the delta movement in y_inc, or by
-- adding 256 or -256 when overflow occurs.
set_y: process(clk)
variable y_inter: std_logic_vector(10 downto 0);
variable inc: std_logic_vector(10 downto 0);
begin
if(rising_edge(clk)) then
-- if sety active, set new y_pos value
if(sety = '1') then
y_pos <= '0' & value;
-- if delta movement received from mouse
elsif(y_new = '1') then
-- if negative movement on y axis
-- Note: axes origin is upper-left corner
if(y_sign = '1') then
-- if overflow occurred
if(y_overflow = '1') then
-- inc is -256
inc := "11100000000";
else
-- inc is sign extended y_inc
inc := "111" & y_inc;
end if;
-- intermediary vertical position
y_inter := y_pos + inc;
-- if first bit of y_inter is 1
-- then negative overflow occurred and
-- new y position is 0.
-- Note: y_pos and y_inter have 11 bits,
-- and because ypos has only 10, when
-- first bit becomes 1, this is considered
-- a negative number when moving upward
if(y_inter(10) = '1') then
y_pos <= (others => '0');
else
y_pos <= y_inter;
end if;
-- if positive movement on y axis
else
-- if overflow occurred
if(y_overflow = '1') then
-- inc is 256
inc := "00100000000";
else
-- inc is sign extended y_inc
inc := "000" & y_inc;
end if;
-- intermediary vertical position
y_inter := y_pos + inc;
-- if y_inter is greater than y_max
-- then positive overflow occurred and
-- new y position is y_max.
if(y_inter > ('0' & y_max)) then
y_pos <= '0' & y_max;
else
y_pos <= y_inter;
end if;
end if;
end if;
end if;
end process set_y;
-- sets the maximum value of the x movement register, stored in x_max
-- when setmax_x is active, max value should be on value input pin
set_max_x: process(clk,rst)
begin
if(rising_edge(clk)) then
if(rst = '1') then
x_max <= DEFAULT_MAX_X;
elsif(setmax_x = '1') then
x_max <= value;
end if;
end if;
end process set_max_x;
-- sets the maximum value of the y movement register, stored in y_max
-- when setmax_y is active, max value should be on value input pin
set_max_y: process(clk,rst)
begin
if(rising_edge(clk)) then
if(rst = '1') then
y_max <= DEFAULT_MAX_Y;
elsif(setmax_y = '1') then
y_max <= value;
end if;
end if;
end process set_max_y;
-- Synchronous one process fsm to handle the communication
-- with the mouse.
-- When reset and at start-up it enters reset state
-- where it begins the procedure of initializing the mouse.
-- After initialization is complete, it waits packets from
-- the mouse.
-- Read at Behavioral decription for details.
manage_fsm: process(clk,rst)
begin
-- when reset occurs, give signals default values.
if(rst = '1') then
state <= reset;
haswheel <= '0';
x_overflow <= '0';
y_overflow <= '0';
x_sign <= '0';
y_sign <= '0';
x_inc <= (others => '0');
y_inc <= (others => '0');
x_new <= '0';
y_new <= '0';
new_event <= '0';
left_down <= '0';
middle_down <= '0';
right_down <= '0';
elsif(rising_edge(clk)) then
-- at every rising edge of the clock, this signals
-- are reset, thus assuring that they are active
-- for one clock period only if a state sets then
-- because the fsm will transition from the state
-- that set them on the next rising edge of clock.
write <= '0';
x_new <= '0';
y_new <= '0';
case state is
-- if just powered-up, reset occurred or some error in
-- transmision encountered, then fsm will transition to
-- this state. Here the RESET command (FF) is sent to the
-- mouse, and various signals receive their default values
-- From here the FSM transitions to a series of states that
-- perform the mouse initialization procedure. All this
-- state are prefixed by "reset_". After sending a byte
-- to the mouse, it respondes by sending ack (FA). All
-- states that wait ack from the mouse are postfixed by
-- "_wait_ack".
-- Read at Behavioral decription for details.
when reset =>
haswheel <= '0';
x_overflow <= '0';
y_overflow <= '0';
x_sign <= '0';
y_sign <= '0';
x_inc <= (others => '0');
y_inc <= (others => '0');
x_new <= '0';
y_new <= '0';
left_down <= '0';
middle_down <= '0';
right_down <= '0';
tx_data <= FF;
write <= '1';
state <= reset_wait_ack;
-- wait ack for the reset command.
-- when received transition to reset_wait_bat_completion.
-- if error occurs go to reset state.
when reset_wait_ack =>
if(read = '1') then
-- if received ack
if(rx_data = FA) then
state <= reset_wait_bat_completion;
else
state <= reset;
end if;
elsif(err = '1') then
state <= reset;
else
state <= reset_wait_ack;
end if;
-- wait for bat completion test
-- mouse should send AA if test is successful
when reset_wait_bat_completion =>
if(read = '1') then
if(rx_data = AA) then
state <= reset_wait_id;
else
state <= reset;
end if;
elsif(err = '1') then
state <= reset;
else
state <= reset_wait_bat_completion;
end if;
-- the mouse sends its id after performing bat test
-- the mouse id should be 00
when reset_wait_id =>
if(read = '1') then
if(rx_data = OO) then
state <= reset_set_sample_rate_200;
else
state <= reset;
end if;
elsif(err = '1') then
state <= reset;
else
state <= reset_wait_id;
end if;
-- with this state begins the enable wheel mouse
-- procedure. The procedure consists of setting
-- the sample rate of the mouse first 200, then 100
-- then 80. After this is done, the mouse id is
-- requested and if the mouse id is 03, then
-- mouse is in wheel mode and will send 4 byte packets
-- when reporting is enabled.
-- If the id is 00, the mouse does not have a wheel
-- and will send 3 byte packets when reporting is enabled.
-- This state issues the set_sample_rate command to the
-- mouse.
when reset_set_sample_rate_200 =>
tx_data <= SET_SAMPLE_RATE;
write <= '1';
state <= reset_set_sample_rate_200_wait_ack;
-- wait ack for set sample rate command
when reset_set_sample_rate_200_wait_ack =>
if(read = '1') then
if(rx_data = FA) then
state <= reset_send_sample_rate_200;
else
state <= reset;
end if;
elsif(err = '1') then
state <= reset;
else
state <= reset_set_sample_rate_200_wait_ack;
end if;
-- send the desired sample rate (200 = 0xC8)
when reset_send_sample_rate_200 =>
tx_data <= "11001000"; -- 0xC8
write <= '1';
state <= reset_send_sample_rate_200_wait_ack;
-- wait ack for sending the sample rate
when reset_send_sample_rate_200_wait_ack =>
if(read = '1') then
if(rx_data = FA) then
state <= reset_set_sample_rate_100;
else
state <= reset;
end if;
elsif(err = '1') then
state <= reset;
else
state <= reset_send_sample_rate_200_wait_ack;
end if;
-- send the sample rate command
when reset_set_sample_rate_100 =>
tx_data <= SET_SAMPLE_RATE;
write <= '1';
state <= reset_set_sample_rate_100_wait_ack;
-- wait ack for sending the sample rate command
when reset_set_sample_rate_100_wait_ack =>
if(read = '1') then
if(rx_data = FA) then
state <= reset_send_sample_rate_100;
else
state <= reset;
end if;
elsif(err = '1') then
state <= reset;
else
state <= reset_set_sample_rate_100_wait_ack;
end if;
-- send the desired sample rate (100 = 0x64)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -