No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MouseCtl.vhd 48KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
  1. ------------------------------------------------------------------------
  2. -- mouse_controller.vhd
  3. ------------------------------------------------------------------------
  4. -- Author : Ulrich Zoltán
  5. -- Copyright 2006 Digilent, Inc.
  6. ------------------------------------------------------------------------
  7. -- This file contains a controller for a ps/2 compatible mouse device.
  8. -- This controller uses the ps2interface module.
  9. ------------------------------------------------------------------------
  10. -- Behavioral description
  11. ------------------------------------------------------------------------
  12. -- Please read the following article on the web for understanding how
  13. -- to interface a ps/2 mouse:
  14. -- http://www.computer-engineering.org/ps2mouse/
  15. -- This controller is implemented as described in the above article.
  16. -- The mouse controller receives bytes from the ps2interface which, in
  17. -- turn, receives them from the mouse device. Data is received on the
  18. -- rx_data input port, and is validated by the read signal. read is
  19. -- active for one clock period when new byte available on rx_data. Data
  20. -- is sent to the ps2interface on the tx_data output port and validated
  21. -- by the write output signal. 'write' should be active for one clock
  22. -- period when tx_data contains the command or data to be sent to the
  23. -- mouse. ps2interface wraps the byte in a 11 bits packet that is sent
  24. -- through the ps/2 port using the ps/2 protocol. Similarly, when the
  25. -- mouse sends data, the ps2interface receives 11 bits for every byte,
  26. -- extracts the byte from the ps/2 frame, puts it on rx_data and
  27. -- activates read for one clock period. If an error occurs when sending
  28. -- or receiving a frame from the mouse, the err input goes high for one
  29. -- clock period. When this occurs, the controller enters reset state.
  30. -- When in reset state, the controller resets the mouse and begins an
  31. -- initialization procedure that consists of tring to put mouse in
  32. -- scroll mode (enables wheel if the mouse has one), setting the
  33. -- resolution of the mouse, the sample rate and finally enables
  34. -- reporting. Implicitly the mouse, after a reset or imediately after a
  35. -- reset, does not send data packets on its own. When reset(or power-up)
  36. -- the mouse enters reset state, where it performs a test, called the
  37. -- bat test (basic assurance test), when this test is done, it sends
  38. -- the result: AAh for test ok, FCh for error. After this it sends its
  39. -- ID which is 00h. When this is done, the mouse enters stream mode,
  40. -- but with reporting disabled (movement data packets are not sent).
  41. -- To enable reporting the enable data reporting command (F4h) must be
  42. -- sent to the mouse. After this command is sent, the mouse will send
  43. -- movement data packets when the mouse is moved or the status of the
  44. -- button changes.
  45. -- After sending a command or a byte following a command, the mouse
  46. -- must respond with ack (FAh). For managing the intialization
  47. -- procedure and receiving the movement data packets, a FSM is used.
  48. -- When the fpga is powered up or the logic is reset using the global
  49. -- reset, the FSM enters reset state. From this state, the FSM will
  50. -- transition to a series of states used to initialize the mouse. When
  51. -- initialization is complete, the FSM remains in state read_byte_1,
  52. -- waiting for a movement data packet to be sent. This is the idle
  53. -- state if the FSM. When a byte is received in this state, this is
  54. -- the first byte of the 3 bytes sent in a movement data packet (4 bytes
  55. -- if mouse in scrolling mode). After reading the last byte from the
  56. -- packet, the FSM enters mark_new_event state and sets new_event high.
  57. -- After that FSM enterss read_byte_1 state, resets new_event and waits
  58. -- for a new packet.
  59. -- After a packet is received, new_event is set high for one clock
  60. -- period to "inform" the clients of this controller a new packet was
  61. -- received and processed.
  62. -- During the initialization procedure, the controller tries to put the
  63. -- mouse in scroll mode (activates wheel, if mouse has one). This is
  64. -- done by successively setting the sample rate to 200, then to 100, and
  65. -- lastly to 80. After this is done, the mouse ID is requested by
  66. -- sending get device ID command (F2h). If the received ID is 00h than
  67. -- the mouse does not have a wheel. If the received ID is 03h than the
  68. -- mouse is in scroll mode, and when sending movement data packets
  69. -- (after enabling data reporting) it will include z movement data.
  70. -- If the mouse is in normal, non-scroll mode, the movement data packet
  71. -- consists of 3 successive bytes. This is their format:
  72. --
  73. --
  74. --
  75. -- bits 7 6 5 4 3 2 1 0
  76. -- -------------------------------------------------
  77. -- byte 1 | YOVF| XOVF|YSIGN|XSIGN| 1 | MBTN| RBTN| LBTN|
  78. -- -------------------------------------------------
  79. -- -------------------------------------------------
  80. -- byte 2 | X MOVEMENT |
  81. -- -------------------------------------------------
  82. -- -------------------------------------------------
  83. -- byte 3 | Y MOVEMENT |
  84. -- -------------------------------------------------
  85. -- OVF = overflow
  86. -- BTN = button
  87. -- M = middle
  88. -- R = right
  89. -- L = left
  90. --
  91. -- When scroll mode is enabled, the mouse send 4 byte movement packets.
  92. -- bits 7 6 5 4 3 2 1 0
  93. -- -------------------------------------------------
  94. -- byte 1 | YOVF| XOVF|YSIGN|XSIGN| 1 | MBTN| RBTN| LBTN|
  95. -- -------------------------------------------------
  96. -- -------------------------------------------------
  97. -- byte 2 | X MOVEMENT |
  98. -- -------------------------------------------------
  99. -- -------------------------------------------------
  100. -- byte 3 | Y MOVEMENT |
  101. -- -------------------------------------------------
  102. -- -------------------------------------------------
  103. -- byte 4 | Z MOVEMENT |
  104. -- -------------------------------------------------
  105. -- x and y movement counters are represented on 8 bits, 2's complement
  106. -- encoding. The first bit (sign bit) of the counters are the xsign and
  107. -- ysign bit from the first packet, the rest of the bits are the second
  108. -- byte for the x movement and the third byte for y movement. For the
  109. -- z movement the range is -8 -> +7 and only the 4 least significant
  110. -- bits from z movement are valid, the rest are sign extensions.
  111. -- The x and y movements are in range: -256 -> +255
  112. -- The mouse uses as axes origin the lower-left corner. For the purpose
  113. -- of displaying a mouse cursor on the screen, the controller inverts
  114. -- the y axis to move the axes origin in the upper-left corner. This
  115. -- is done by negating the y movement value (following the 2s complement
  116. -- encoding). The movement data received from the mouse are delta
  117. -- movements, the data represents the movement of the mouse relative
  118. -- to the last position. The controller keeps track of the position of
  119. -- the mouse relative to the upper-left corner. This is done by keeping
  120. -- the mouse position in two registers x_pos and y_pos and adding the
  121. -- delta movements to their value. The addition uses saturation. That
  122. -- means the value of the mouse position will not exceed certain bounds
  123. -- and will not rollover the a margin. For example, if the mouse is at
  124. -- the left margin and is moved left, the x position remains at the left
  125. -- margin(0). The lower bound is always 0 for both x and y movement.
  126. -- The upper margin can be set using input pins: value, setmax_x,
  127. -- setmax_y. To set the upper bound of the x movement counter, the new
  128. -- value is placed on the value input pins and setmax_x is activated
  129. -- for at least one clock period. Similarly for y movement counter, but
  130. -- setmax_y is activated instead. Notice that value has 10 bits, and so
  131. -- the maximum value for a bound is 1023.
  132. -- The position of the mouse (x_pos and y_pos) can be set at any time,
  133. -- by placing the x or y position on the value input pins and activating
  134. -- the setx, or sety respectively, for at least one clock period. This
  135. -- is useful for setting an original position of the mouse different
  136. -- from (0,0).
  137. ------------------------------------------------------------------------
  138. -- Port definitions
  139. ------------------------------------------------------------------------
  140. -- clk - global clock signal (100MHz)
  141. -- rst - global reset signal
  142. -- xpos - output pin, 10 bits
  143. -- - the x position of the mouse relative to the upper
  144. -- - left corner
  145. -- ypos - output pin, 10 bits
  146. -- - the y position of the mouse relative to the upper
  147. -- - left corner
  148. -- zpos - output pin, 4 bits
  149. -- - last delta movement on z axis
  150. -- left - output pin, high if the left mouse button is pressed
  151. -- middle - output pin, high if the middle mouse button is
  152. -- - pressed
  153. -- right - output pin, high if the right mouse button is
  154. -- - pressed
  155. -- new_event - output pin, active one clock period after receiving
  156. -- - and processing one movement data packet.
  157. ------------------------------------------------------------------------
  158. -- Revision History:
  159. -- 09/18/2006(UlrichZ): created
  160. ------------------------------------------------------------------------
  161. library IEEE;
  162. use IEEE.STD_LOGIC_1164.ALL;
  163. use IEEE.STD_LOGIC_ARITH.ALL;
  164. use IEEE.STD_LOGIC_UNSIGNED.ALL;
  165. -- simulation library
  166. library UNISIM;
  167. use UNISIM.VComponents.all;
  168. -- the mouse_controller entity declaration
  169. -- read above for behavioral description and port definitions.
  170. entity MouseCtl is
  171. generic
  172. (
  173. SYSCLK_FREQUENCY_HZ : integer := 100000000;
  174. CHECK_PERIOD_MS : integer := 500; -- Period in miliseconds to check if the mouse is present
  175. TIMEOUT_PERIOD_MS : integer := 100 -- Timeout period in miliseconds when the mouse presence is checked
  176. );
  177. port(
  178. clk : in std_logic;
  179. rst : in std_logic;
  180. xpos : out std_logic_vector(11 downto 0);
  181. ypos : out std_logic_vector(11 downto 0);
  182. zpos : out std_logic_vector(3 downto 0);
  183. left : out std_logic;
  184. middle : out std_logic;
  185. right : out std_logic;
  186. new_event : out std_logic;
  187. value : in std_logic_vector(11 downto 0);
  188. setx : in std_logic;
  189. sety : in std_logic;
  190. setmax_x : in std_logic;
  191. setmax_y : in std_logic;
  192. ps2_clk : inout std_logic;
  193. ps2_data : inout std_logic
  194. );
  195. end MouseCtl;
  196. architecture Behavioral of MouseCtl is
  197. ------------------------------------------------------------------------
  198. -- Ps2 Interface component declaration
  199. ------------------------------------------------------------------------
  200. COMPONENT Ps2Interface
  201. PORT(
  202. ps2_clk : inout std_logic;
  203. ps2_data : inout std_logic;
  204. clk : in std_logic;
  205. rst : in std_logic;
  206. tx_data : in std_logic_vector(7 downto 0);
  207. write_data : in std_logic;
  208. rx_data : out std_logic_vector(7 downto 0);
  209. read_data : out std_logic;
  210. busy : out std_logic;
  211. err : out std_logic
  212. );
  213. END COMPONENT;
  214. ------------------------------------------------------------------------
  215. -- CONSTANTS
  216. ------------------------------------------------------------------------
  217. -- constants defining commands to send or received from the mouse
  218. constant FA: std_logic_vector(7 downto 0) := "11111010"; -- 0xFA(ACK)
  219. constant FF: std_logic_vector(7 downto 0) := "11111111"; -- 0xFF(RESET)
  220. constant AA: std_logic_vector(7 downto 0) := "10101010"; -- 0xAA(BAT_OK)
  221. constant OO: std_logic_vector(7 downto 0) := "00000000"; -- 0x00(ID)
  222. -- (atention: name is 2 letters O not zero)
  223. -- command to read id
  224. constant READ_ID : std_logic_vector(7 downto 0) := x"F2";
  225. -- command to enable mouse reporting
  226. -- after this command is sent, the mouse begins sending data packets
  227. constant ENABLE_REPORTING : std_logic_vector(7 downto 0) := x"F4";
  228. -- command to set the mouse resolution
  229. constant SET_RESOLUTION : std_logic_vector(7 downto 0) := x"E8";
  230. -- the value of the resolution to send after sending SET_RESOLUTION
  231. constant RESOLUTION : std_logic_vector(7 downto 0) := x"03";
  232. -- (8 counts/mm)
  233. -- command to set the mouse sample rate
  234. constant SET_SAMPLE_RATE : std_logic_vector(7 downto 0) := x"F3";
  235. -- the value of the sample rate to send after sending SET_SAMPLE_RATE
  236. constant SAMPLE_RATE : std_logic_vector(7 downto 0) := x"28";
  237. -- (40 samples/s)
  238. -- default maximum value for the horizontal mouse position
  239. constant DEFAULT_MAX_X : std_logic_vector(11 downto 0) := x"4FF";
  240. -- 1279
  241. -- default maximum value for the vertical mouse position
  242. constant DEFAULT_MAX_Y : std_logic_vector(11 downto 0) := x"3FF";
  243. -- 1023
  244. -- Mouse check tick constants
  245. constant CHECK_PERIOD_CLOCKS : integer := ((CHECK_PERIOD_MS*1000000)/(1000000000/SYSCLK_FREQUENCY_HZ));
  246. constant TIMEOUT_PERIOD_CLOCKS : integer := ((TIMEOUT_PERIOD_MS*1000000)/(1000000000/SYSCLK_FREQUENCY_HZ));
  247. ------------------------------------------------------------------------
  248. -- SIGNALS
  249. ------------------------------------------------------------------------
  250. -- after doing the enable scroll mouse procedure, if the ID returned by
  251. -- the mouse is 03 (scroll mouse enabled) then this register will be set
  252. -- If '1' then the mouse is in scroll mode, else mouse is in simple
  253. -- mouse mode.
  254. signal haswheel: std_logic := '0';
  255. -- horizontal and veritcal mouse position
  256. -- origin of axes is upper-left corner
  257. -- the origin of axes the mouse uses is the lower-left corner
  258. -- The y-axis is inverted, by making negative the y movement received
  259. -- from the mouse (if it was positive it becomes negative
  260. -- and vice versa)
  261. signal x_pos,y_pos: std_logic_vector(11 downto 0) := (others => '0');
  262. -- active when an overflow occurred on the x and y axis
  263. -- bits 6 and 7 from the first byte received from the mouse
  264. signal x_overflow,y_overflow: std_logic := '0';
  265. -- active when the x,y movement is negative
  266. -- bits 4 and 5 from the first byte received from the mouse
  267. signal x_sign,y_sign: std_logic := '0';
  268. -- 2's complement value for incrementing the x_pos,y_pos
  269. -- y_inc is the negated value from the mouse in the third byte
  270. signal x_inc,y_inc: std_logic_vector(7 downto 0) := (others => '0');
  271. -- active for one clock period, indicates new delta movement received
  272. -- on x,y axis
  273. signal x_new,y_new: std_logic := '0';
  274. -- maximum value for x and y position registers(x_pos,y_pos)
  275. signal x_max: std_logic_vector(11 downto 0) := DEFAULT_MAX_X;
  276. signal y_max: std_logic_vector(11 downto 0) := DEFAULT_MAX_Y;
  277. -- active when left,middle,right mouse button is down
  278. signal left_down,middle_down,right_down: std_logic := '0';
  279. -- the FSM states
  280. -- states that begin with "reset" are part of the reset procedure.
  281. -- states that end in "_wait_ack" are states in which ack is waited
  282. -- as response to sending a byte to the mouse.
  283. -- read behavioral description above for details.
  284. type fsm_state is
  285. (
  286. reset,reset_wait_ack,reset_wait_bat_completion,reset_wait_id,
  287. reset_set_sample_rate_200,reset_set_sample_rate_200_wait_ack,
  288. reset_send_sample_rate_200,reset_send_sample_rate_200_wait_ack,
  289. reset_set_sample_rate_100,reset_set_sample_rate_100_wait_ack,
  290. reset_send_sample_rate_100,reset_send_sample_rate_100_wait_ack,
  291. reset_set_sample_rate_80,reset_set_sample_rate_80_wait_ack,
  292. reset_send_sample_rate_80,reset_send_sample_rate_80_wait_ack,
  293. reset_read_id,reset_read_id_wait_ack,reset_read_id_wait_id,
  294. reset_set_resolution,reset_set_resolution_wait_ack,
  295. reset_send_resolution,reset_send_resolution_wait_ack,
  296. reset_set_sample_rate_40,reset_set_sample_rate_40_wait_ack,
  297. reset_send_sample_rate_40,reset_send_sample_rate_40_wait_ack,
  298. reset_enable_reporting,reset_enable_reporting_wait_ack,
  299. read_byte_1,read_byte_2,read_byte_3,read_byte_4,
  300. check_read_id,check_read_id_wait_ack,check_read_id_wait_id,
  301. mark_new_event
  302. );
  303. -- holds current state of the FSM
  304. signal state: fsm_state := reset;
  305. -- PS2 Interface and Mouse Controller interconnection signals
  306. -- read_data - from ps2interface
  307. -- - active one clock period when new data received
  308. -- - and available on rx_data
  309. -- err - from ps2interface
  310. -- - active one clock period when error occurred when
  311. -- - receiving or sending data.
  312. -- rx_data - 8 bits, from ps2interface
  313. -- - the byte received from the mouse.
  314. -- tx_data - 8 bits, to ps2interface
  315. -- - byte to be sent to the mouse
  316. -- write_data - to ps2interface
  317. -- - active one clock period when sending a byte to the
  318. -- - ps2interface.
  319. signal read_data : std_logic;
  320. signal err : std_logic;
  321. signal rx_data: std_logic_vector (7 downto 0);
  322. signal tx_data: std_logic_vector (7 downto 0);
  323. signal write_data : std_logic;
  324. -- Periodic checking counter, reset and tick signal
  325. -- The periodic checking counter acts as a watchdog, periodically
  326. -- reading the Mouse ID, therefore checking if the mouse is present
  327. -- If there is no answer, after the timeout period passed, then the
  328. -- state machine is reinitialized
  329. signal periodic_check_cnt : integer range 0 to (CHECK_PERIOD_CLOCKS - 1) := 0;
  330. signal reset_periodic_check_cnt : STD_LOGIC := '0';
  331. signal periodic_check_tick : STD_LOGIC := '0';
  332. -- Self-blocking Timeout checking counter, reset and timeout indication signal
  333. signal timeout_cnt : integer range 0 to (TIMEOUT_PERIOD_CLOCKS - 1) := 0;
  334. signal reset_timeout_cnt : STD_LOGIC := '0';
  335. signal timeout : STD_LOGIC := '0';
  336. begin
  337. Inst_Ps2Interface: Ps2Interface
  338. PORT MAP
  339. (
  340. ps2_clk => ps2_clk,
  341. ps2_data => ps2_data,
  342. clk => clk,
  343. rst => rst,
  344. tx_data => tx_data,
  345. write_data => write_data,
  346. rx_data => rx_data,
  347. read_data => read_data,
  348. busy => open,
  349. err => err
  350. );
  351. -- Create the periodic_check_cnt counter
  352. Count_periodic_check: process (clk, periodic_check_cnt, reset_periodic_check_cnt)
  353. begin
  354. if clk'EVENT AND clk = '1' then
  355. if reset_periodic_check_cnt = '1' then
  356. periodic_check_cnt <= 0;
  357. elsif periodic_check_cnt = (CHECK_PERIOD_CLOCKS - 1) then
  358. periodic_check_cnt <= 0;
  359. else
  360. periodic_check_cnt <= periodic_check_cnt + 1;
  361. end if;
  362. end if;
  363. end process Count_periodic_check;
  364. periodic_check_tick <= '1' when periodic_check_cnt = (CHECK_PERIOD_CLOCKS - 1) else '0';
  365. -- Create the timeout counter
  366. Count_timeout: process (clk, timeout_cnt, reset_timeout_cnt)
  367. begin
  368. if clk'EVENT AND clk = '1' then
  369. if reset_timeout_cnt = '1' then
  370. timeout_cnt <= 0;
  371. elsif timeout_cnt = (TIMEOUT_PERIOD_CLOCKS - 1) then
  372. timeout_cnt <= (TIMEOUT_PERIOD_CLOCKS - 1);
  373. else
  374. timeout_cnt <= timeout_cnt + 1;
  375. end if;
  376. end if;
  377. end process Count_timeout;
  378. timeout <= '1' when timeout_cnt = (TIMEOUT_PERIOD_CLOCKS - 1) else '0';
  379. -- left output the state of the left_down register
  380. left <= left_down when rising_edge(clk);
  381. -- middle output the state of the middle_down register
  382. middle <= middle_down when rising_edge(clk);
  383. -- right output the state of the right_down register
  384. right <= right_down when rising_edge(clk);
  385. -- xpos output is the horizontal position of the mouse
  386. -- it has the range: 0-x_max
  387. xpos <= x_pos(11 downto 0) when rising_edge(clk);
  388. -- ypos output is the vertical position of the mouse
  389. -- it has the range: 0-y_max
  390. ypos <= y_pos(11 downto 0) when rising_edge(clk);
  391. -- sets the value of x_pos from another module when setx is active
  392. -- else, computes the new x_pos from the old position when new x
  393. -- movement detected by adding the delta movement in x_inc, or by
  394. -- adding 256 or -256 when overflow occurs.
  395. set_x: process(clk)
  396. variable x_inter: std_logic_vector(11 downto 0);
  397. variable inc: std_logic_vector(11 downto 0);
  398. begin
  399. if(rising_edge(clk)) then
  400. -- if setx active, set new x_pos value
  401. if(setx = '1') then
  402. x_pos <= value;
  403. -- if delta movement received from mouse
  404. elsif(x_new = '1') then
  405. -- if negative movement on x axis
  406. if(x_sign = '1') then
  407. -- if overflow occurred
  408. if(x_overflow = '1') then
  409. -- inc is -256
  410. inc := "111000000000";
  411. else
  412. -- inc is sign extended x_inc
  413. inc := "1111" & x_inc;
  414. end if;
  415. -- intermediary horizontal position
  416. x_inter := x_pos + inc;
  417. -- if first bit of x_inter is 1
  418. -- then negative overflow occurred and
  419. -- new x position is 0.
  420. -- Note: x_pos and x_inter have 11 bits,
  421. -- and because xpos has only 10, when
  422. -- first bit becomes 1, this is considered
  423. -- a negative number when moving left
  424. if(x_inter(11) = '1') then
  425. x_pos <= (others => '0');
  426. else
  427. x_pos <= x_inter;
  428. end if;
  429. -- if positive movement on x axis
  430. else
  431. -- if overflow occurred
  432. if(x_overflow = '1') then
  433. -- inc is 256
  434. inc := "000100000000";
  435. else
  436. -- inc is sign extended x_inc
  437. inc := "0000" & x_inc;
  438. end if;
  439. -- intermediary horizontal position
  440. x_inter := x_pos + inc;
  441. -- if x_inter is greater than x_max
  442. -- then positive overflow occurred and
  443. -- new x position is x_max.
  444. if(x_inter > ('0' & x_max)) then
  445. x_pos <= x_max;
  446. else
  447. x_pos <= x_inter;
  448. end if;
  449. end if;
  450. end if;
  451. end if;
  452. end process set_x;
  453. -- sets the value of y_pos from another module when sety is active
  454. -- else, computes the new y_pos from the old position when new y
  455. -- movement detected by adding the delta movement in y_inc, or by
  456. -- adding 256 or -256 when overflow occurs.
  457. set_y: process(clk)
  458. variable y_inter: std_logic_vector(11 downto 0);
  459. variable inc: std_logic_vector(11 downto 0);
  460. begin
  461. if(rising_edge(clk)) then
  462. -- if sety active, set new y_pos value
  463. if(sety = '1') then
  464. y_pos <= value;
  465. -- if delta movement received from mouse
  466. elsif(y_new = '1') then
  467. -- if negative movement on y axis
  468. -- Note: axes origin is upper-left corner
  469. if(y_sign = '1') then
  470. -- if overflow occurred
  471. if(y_overflow = '1') then
  472. -- inc is -256
  473. inc := "111100000000";
  474. else
  475. -- inc is sign extended y_inc
  476. inc := "1111" & y_inc;
  477. end if;
  478. -- intermediary vertical position
  479. y_inter := y_pos + inc;
  480. -- if first bit of y_inter is 1
  481. -- then negative overflow occurred and
  482. -- new y position is 0.
  483. -- Note: y_pos and y_inter have 11 bits,
  484. -- and because ypos has only 10, when
  485. -- first bit becomes 1, this is considered
  486. -- a negative number when moving upward
  487. if(y_inter(11) = '1') then
  488. y_pos <= (others => '0');
  489. else
  490. y_pos <= y_inter;
  491. end if;
  492. -- if positive movement on y axis
  493. else
  494. -- if overflow occurred
  495. if(y_overflow = '1') then
  496. -- inc is 256
  497. inc := "000100000000";
  498. else
  499. -- inc is sign extended y_inc
  500. inc := "0000" & y_inc;
  501. end if;
  502. -- intermediary vertical position
  503. y_inter := y_pos + inc;
  504. -- if y_inter is greater than y_max
  505. -- then positive overflow occurred and
  506. -- new y position is y_max.
  507. if(y_inter > (y_max)) then
  508. y_pos <= y_max;
  509. else
  510. y_pos <= y_inter;
  511. end if;
  512. end if;
  513. end if;
  514. end if;
  515. end process set_y;
  516. -- sets the maximum value of the x movement register, stored in x_max
  517. -- when setmax_x is active, max value should be on value input pin
  518. set_max_x: process(clk,rst)
  519. begin
  520. if(rising_edge(clk)) then
  521. if(rst = '1') then
  522. x_max <= DEFAULT_MAX_X;
  523. elsif(setmax_x = '1') then
  524. x_max <= value;
  525. end if;
  526. end if;
  527. end process set_max_x;
  528. -- sets the maximum value of the y movement register, stored in y_max
  529. -- when setmax_y is active, max value should be on value input pin
  530. set_max_y: process(clk,rst)
  531. begin
  532. if(rising_edge(clk)) then
  533. if(rst = '1') then
  534. y_max <= DEFAULT_MAX_Y;
  535. elsif(setmax_y = '1') then
  536. y_max <= value;
  537. end if;
  538. end if;
  539. end process set_max_y;
  540. -- Synchronous one process fsm to handle the communication
  541. -- with the mouse.
  542. -- When reset and at start-up it enters reset state
  543. -- where it begins the procedure of initializing the mouse.
  544. -- After initialization is complete, it waits packets from
  545. -- the mouse.
  546. -- Read at Behavioral decription for details.
  547. manage_fsm: process(clk,rst)
  548. begin
  549. -- when reset occurs, give signals default values.
  550. if(rst = '1') then
  551. state <= reset;
  552. haswheel <= '0';
  553. x_overflow <= '0';
  554. y_overflow <= '0';
  555. x_sign <= '0';
  556. y_sign <= '0';
  557. x_inc <= (others => '0');
  558. y_inc <= (others => '0');
  559. x_new <= '0';
  560. y_new <= '0';
  561. new_event <= '0';
  562. left_down <= '0';
  563. middle_down <= '0';
  564. right_down <= '0';
  565. reset_periodic_check_cnt <= '1';
  566. reset_timeout_cnt <= '1';
  567. elsif(rising_edge(clk)) then
  568. -- at every rising edge of the clock, this signals
  569. -- are reset, thus assuring that they are active
  570. -- for one clock period only if a state sets then
  571. -- because the fsm will transition from the state
  572. -- that set them on the next rising edge of clock.
  573. write_data <= '0';
  574. x_new <= '0';
  575. y_new <= '0';
  576. case state is
  577. -- if just powered-up, reset occurred or some error in
  578. -- transmision encountered, then fsm will transition to
  579. -- this state. Here the RESET command (FF) is sent to the
  580. -- mouse, and various signals receive their default values
  581. -- From here the FSM transitions to a series of states that
  582. -- perform the mouse initialization procedure. All this
  583. -- state are prefixed by "reset_". After sending a byte
  584. -- to the mouse, it respondes by sending ack (FA). All
  585. -- states that wait ack from the mouse are postfixed by
  586. -- "_wait_ack".
  587. -- Read at Behavioral decription for details.
  588. when reset =>
  589. haswheel <= '0';
  590. x_overflow <= '0';
  591. y_overflow <= '0';
  592. x_sign <= '0';
  593. y_sign <= '0';
  594. x_inc <= (others => '0');
  595. y_inc <= (others => '0');
  596. x_new <= '0';
  597. y_new <= '0';
  598. left_down <= '0';
  599. middle_down <= '0';
  600. right_down <= '0';
  601. tx_data <= FF;
  602. write_data <= '1';
  603. reset_periodic_check_cnt <= '1';
  604. reset_timeout_cnt <= '1';
  605. state <= reset_wait_ack;
  606. -- wait ack for the reset command.
  607. -- when received transition to reset_wait_bat_completion.
  608. -- if error occurs go to reset state.
  609. when reset_wait_ack =>
  610. if(read_data = '1') then
  611. -- if received ack
  612. if(rx_data = FA) then
  613. state <= reset_wait_bat_completion;
  614. else
  615. state <= reset;
  616. end if;
  617. elsif(err = '1') then
  618. state <= reset;
  619. else
  620. state <= reset_wait_ack;
  621. end if;
  622. -- wait for bat completion test
  623. -- mouse should send AA if test is successful
  624. when reset_wait_bat_completion =>
  625. if(read_data = '1') then
  626. if(rx_data = AA) then
  627. state <= reset_wait_id;
  628. else
  629. state <= reset;
  630. end if;
  631. elsif(err = '1') then
  632. state <= reset;
  633. else
  634. state <= reset_wait_bat_completion;
  635. end if;
  636. -- the mouse sends its id after performing bat test
  637. -- the mouse id should be 00
  638. when reset_wait_id =>
  639. if(read_data = '1') then
  640. if(rx_data = OO) then
  641. state <= reset_set_sample_rate_200;
  642. else
  643. state <= reset;
  644. end if;
  645. elsif(err = '1') then
  646. state <= reset;
  647. else
  648. state <= reset_wait_id;
  649. end if;
  650. -- with this state begins the enable wheel mouse
  651. -- procedure. The procedure consists of setting
  652. -- the sample rate of the mouse first 200, then 100
  653. -- then 80. After this is done, the mouse id is
  654. -- requested and if the mouse id is 03, then
  655. -- mouse is in wheel mode and will send 4 byte packets
  656. -- when reporting is enabled.
  657. -- If the id is 00, the mouse does not have a wheel
  658. -- and will send 3 byte packets when reporting is enabled.
  659. -- This state issues the set_sample_rate command to the
  660. -- mouse.
  661. when reset_set_sample_rate_200 =>
  662. tx_data <= SET_SAMPLE_RATE;
  663. write_data <= '1';
  664. state <= reset_set_sample_rate_200_wait_ack;
  665. -- wait ack for set sample rate command
  666. when reset_set_sample_rate_200_wait_ack =>
  667. if(read_data = '1') then
  668. if(rx_data = FA) then
  669. state <= reset_send_sample_rate_200;
  670. else
  671. state <= reset;
  672. end if;
  673. elsif(err = '1') then
  674. state <= reset;
  675. else
  676. state <= reset_set_sample_rate_200_wait_ack;
  677. end if;
  678. -- send the desired sample rate (200 = 0xC8)
  679. when reset_send_sample_rate_200 =>
  680. tx_data <= "11001000"; -- 0xC8
  681. write_data <= '1';
  682. state <= reset_send_sample_rate_200_wait_ack;
  683. -- wait ack for sending the sample rate
  684. when reset_send_sample_rate_200_wait_ack =>
  685. if(read_data = '1') then
  686. if(rx_data = FA) then
  687. state <= reset_set_sample_rate_100;
  688. else
  689. state <= reset;
  690. end if;
  691. elsif(err = '1') then
  692. state <= reset;
  693. else
  694. state <= reset_send_sample_rate_200_wait_ack;
  695. end if;
  696. -- send the sample rate command
  697. when reset_set_sample_rate_100 =>
  698. tx_data <= SET_SAMPLE_RATE;
  699. write_data <= '1';
  700. state <= reset_set_sample_rate_100_wait_ack;
  701. -- wait ack for sending the sample rate command
  702. when reset_set_sample_rate_100_wait_ack =>
  703. if(read_data = '1') then
  704. if(rx_data = FA) then
  705. state <= reset_send_sample_rate_100;
  706. else
  707. state <= reset;
  708. end if;
  709. elsif(err = '1') then
  710. state <= reset;
  711. else
  712. state <= reset_set_sample_rate_100_wait_ack;
  713. end if;
  714. -- send the desired sample rate (100 = 0x64)
  715. when reset_send_sample_rate_100 =>
  716. tx_data <= "01100100"; -- 0x64
  717. write_data <= '1';
  718. state <= reset_send_sample_rate_100_wait_ack;
  719. -- wait ack for sending the sample rate
  720. when reset_send_sample_rate_100_wait_ack =>
  721. if(read_data = '1') then
  722. if(rx_data = FA) then
  723. state <= reset_set_sample_rate_80;
  724. else
  725. state <= reset;
  726. end if;
  727. elsif(err = '1') then
  728. state <= reset;
  729. else
  730. state <= reset_send_sample_rate_100_wait_ack;
  731. end if;
  732. -- send set sample rate command
  733. when reset_set_sample_rate_80 =>
  734. tx_data <= SET_SAMPLE_RATE;
  735. write_data <= '1';
  736. state <= reset_set_sample_rate_80_wait_ack;
  737. -- wait ack for sending the sample rate command
  738. when reset_set_sample_rate_80_wait_ack =>
  739. if(read_data = '1') then
  740. if(rx_data = FA) then
  741. state <= reset_send_sample_rate_80;
  742. else
  743. state <= reset;
  744. end if;
  745. elsif(err = '1') then
  746. state <= reset;
  747. else
  748. state <= reset_set_sample_rate_80_wait_ack;
  749. end if;
  750. -- send desired sample rate (80 = 0x50)
  751. when reset_send_sample_rate_80 =>
  752. tx_data <= "01010000"; -- 0x50
  753. write_data <= '1';
  754. state <= reset_send_sample_rate_80_wait_ack;
  755. -- wait ack for sending the sample rate
  756. when reset_send_sample_rate_80_wait_ack =>
  757. if(read_data = '1') then
  758. if(rx_data = FA) then
  759. state <= reset_read_id;
  760. else
  761. state <= reset;
  762. end if;
  763. elsif(err = '1') then
  764. state <= reset;
  765. else
  766. state <= reset_send_sample_rate_80_wait_ack;
  767. end if;
  768. -- now the procedure for enabling wheel mode is done
  769. -- the mouse id is read to determine is mouse is in
  770. -- wheel mode.
  771. -- Read ID command is sent to the mouse.
  772. when reset_read_id =>
  773. tx_data <= READ_ID;
  774. write_data <= '1';
  775. state <= reset_read_id_wait_ack;
  776. -- wait ack for sending the read id command
  777. when reset_read_id_wait_ack =>
  778. if(read_data = '1') then
  779. if(rx_data = FA) then
  780. state <= reset_read_id_wait_id;
  781. else
  782. state <= reset;
  783. end if;
  784. elsif(err = '1') then
  785. state <= reset;
  786. else
  787. state <= reset_read_id_wait_ack;
  788. end if;
  789. -- received the mouse id
  790. -- if the id is 00, then the mouse does not have
  791. -- a wheel and haswheel is reset
  792. -- if the id is 03, then the mouse is in scroll mode
  793. -- and haswheel is set.
  794. -- if anything else is received or an error occurred
  795. -- then the FSM transitions to reset state.
  796. when reset_read_id_wait_id =>
  797. if(read_data = '1') then
  798. if(rx_data = "000000000") then
  799. -- the mouse does not have a wheel
  800. haswheel <= '0';
  801. state <= reset_set_resolution;
  802. elsif(rx_data = "00000011") then -- 0x03
  803. -- the mouse is in scroll mode
  804. haswheel <= '1';
  805. state <= reset_set_resolution;
  806. else
  807. state <= reset;
  808. end if;
  809. elsif(err = '1') then
  810. state <= reset;
  811. else
  812. state <= reset_read_id_wait_id;
  813. end if;
  814. -- send the set resolution command to the mouse
  815. when reset_set_resolution =>
  816. tx_data <= SET_RESOLUTION;
  817. write_data <= '1';
  818. state <= reset_set_resolution_wait_ack;
  819. -- wait ack for sending the set resolution command
  820. when reset_set_resolution_wait_ack =>
  821. if(read_data = '1') then
  822. if(rx_data = FA) then
  823. state <= reset_send_resolution;
  824. else
  825. state <= reset;
  826. end if;
  827. elsif(err = '1') then
  828. state <= reset;
  829. else
  830. state <= reset_set_resolution_wait_ack;
  831. end if;
  832. -- send the desired resolution (0x03 = 8 counts/mm)
  833. when reset_send_resolution =>
  834. tx_data <= RESOLUTION;
  835. write_data <= '1';
  836. state <= reset_send_resolution_wait_ack;
  837. -- wait ack for sending the resolution
  838. when reset_send_resolution_wait_ack =>
  839. if(read_data = '1') then
  840. if(rx_data = FA) then
  841. state <= reset_set_sample_rate_40;
  842. else
  843. state <= reset;
  844. end if;
  845. elsif(err = '1') then
  846. state <= reset;
  847. else
  848. state <= reset_send_resolution_wait_ack;
  849. end if;
  850. -- send the set sample rate command
  851. when reset_set_sample_rate_40 =>
  852. tx_data <= SET_SAMPLE_RATE;
  853. write_data <= '1';
  854. state <= reset_set_sample_rate_40_wait_ack;
  855. -- wait ack for sending the set sample rate command
  856. when reset_set_sample_rate_40_wait_ack =>
  857. if(read_data = '1') then
  858. if(rx_data = FA) then
  859. state <= reset_send_sample_rate_40;
  860. else
  861. state <= reset;
  862. end if;
  863. elsif(err = '1') then
  864. state <= reset;
  865. else
  866. state <= reset_set_sample_rate_40_wait_ack;
  867. end if;
  868. -- send the desired sampele rate.
  869. -- 40 samples per second is sent.
  870. when reset_send_sample_rate_40 =>
  871. tx_data <= SAMPLE_RATE;
  872. write_data <= '1';
  873. state <= reset_send_sample_rate_40_wait_ack;
  874. -- wait ack for sending the sample rate
  875. when reset_send_sample_rate_40_wait_ack =>
  876. if(read_data = '1') then
  877. if(rx_data = FA) then
  878. state <= reset_enable_reporting;
  879. else
  880. state <= reset;
  881. end if;
  882. elsif(err = '1') then
  883. state <= reset;
  884. else
  885. state <= reset_send_sample_rate_40_wait_ack;
  886. end if;
  887. -- in this state enable reporting command is sent
  888. -- to the mouse. Before this point, the mouse
  889. -- does not send packets. Only after issuing this
  890. -- command, the mouse begins sending data packets,
  891. -- 3 byte packets if it doesn't have a wheel and
  892. -- 4 byte packets if it is in scroll mode.
  893. when reset_enable_reporting =>
  894. tx_data <= ENABLE_REPORTING;
  895. write_data <= '1';
  896. state <= reset_enable_reporting_wait_ack;
  897. -- wait ack for sending the enable reporting command
  898. when reset_enable_reporting_wait_ack =>
  899. if(read_data = '1') then
  900. if(rx_data = FA) then
  901. state <= read_byte_1;
  902. else
  903. state <= reset;
  904. end if;
  905. elsif(err = '1') then
  906. state <= reset;
  907. else
  908. state <= reset_enable_reporting_wait_ack;
  909. end if;
  910. -- this is idle state of the FSM after the
  911. -- initialization is complete.
  912. -- Here the first byte of a packet is waited.
  913. -- The first byte contains the state of the
  914. -- buttons, the sign of the x and y movement
  915. -- and overflow information about these movements
  916. -- First byte looks like this:
  917. -- 7 6 5 4 3 2 1 0
  918. ------------------------------------------------------
  919. -- | Y OVF | X OVF | Y SIGN | X SIGN | 1 | M | R | L |
  920. ------------------------------------------------------
  921. when read_byte_1 =>
  922. -- Start periodic check counter
  923. reset_periodic_check_cnt <= '0';
  924. -- reset new_event when back in idle state.
  925. new_event <= '0';
  926. -- reset last z delta movement
  927. zpos <= (others => '0');
  928. if(read_data = '1') then
  929. -- mouse button states
  930. left_down <= rx_data(0);
  931. middle_down <= rx_data(2);
  932. right_down <= rx_data(1);
  933. -- sign of the movement data
  934. x_sign <= rx_data(4);
  935. -- y sign is changed to invert the y axis
  936. -- because the mouse uses the lower-left corner
  937. -- as axes origin and it is placed in the upper-left
  938. -- corner by this inversion (suitable for displaying
  939. -- a mouse cursor on the screen).
  940. -- y movement data from the third packet must be
  941. -- also negated.
  942. y_sign <= not rx_data(5);
  943. -- overflow status of the x and y movement
  944. x_overflow <= rx_data(6);
  945. y_overflow <= rx_data(7);
  946. -- transition to state read_byte_2
  947. state <= read_byte_2;
  948. elsif periodic_check_tick = '1' then -- Check periodically if the mouse is present
  949. state <= check_read_id;
  950. else
  951. -- no byte received yet.
  952. state <= read_byte_1;
  953. end if;
  954. -- wait the second byte of the packet
  955. -- this byte contains the x movement counter.
  956. when read_byte_2 =>
  957. if(read_data = '1') then
  958. -- put the delta movement in x_inc
  959. x_inc <= rx_data;
  960. -- signal the arrival of new x movement data.
  961. x_new <= '1';
  962. -- go to state read_byte_3.
  963. state <= read_byte_3;
  964. elsif periodic_check_tick = '1' then -- Check periodically if the mouse is present
  965. state <= check_read_id;
  966. elsif(err = '1') then
  967. state <= reset;
  968. else
  969. -- byte not received yet.
  970. state <= read_byte_2;
  971. end if;
  972. -- wait the third byte of the data, that
  973. -- contains the y data movement counter.
  974. -- negate its value, for the axis to be
  975. -- inverted.
  976. -- If mouse is in scroll mode, transition
  977. -- to read_byte_4, else go to mark_new_event
  978. when read_byte_3 =>
  979. if(read_data = '1') then
  980. -- when y movement is 0, then ignore
  981. if(rx_data /= "00000000") then
  982. -- 2's complement positive numbers
  983. -- become negative and vice versa
  984. y_inc <= (not rx_data) + "00000001";
  985. y_new <= '1';
  986. end if;
  987. -- if the mouse has a wheel then transition
  988. -- to read_byte_4, else go to mark_new_event
  989. if(haswheel = '1') then
  990. state <= read_byte_4;
  991. else
  992. state <= mark_new_event;
  993. end if;
  994. elsif periodic_check_tick = '1' then -- Check periodically if the mouse is present
  995. state <= check_read_id;
  996. elsif(err = '1') then
  997. state <= reset;
  998. else
  999. state <= read_byte_3;
  1000. end if;
  1001. -- only reached when mouse is in scroll mode
  1002. -- wait for the fourth byte to arrive
  1003. -- fourth byte contains the z movement counter
  1004. -- only least significant 4 bits are relevant
  1005. -- the rest are sign extension.
  1006. when read_byte_4 =>
  1007. if(read_data = '1') then
  1008. -- zpos is the delta movement on z
  1009. zpos <= rx_data(3 downto 0);
  1010. -- packet completly received,
  1011. -- go to mark_new_event
  1012. state <= mark_new_event;
  1013. elsif periodic_check_tick = '1' then -- Check periodically if the mouse is present
  1014. state <= check_read_id;
  1015. elsif(err = '1') then
  1016. state <= reset;
  1017. else
  1018. state <= read_byte_4;
  1019. end if;
  1020. -- From timer to time determined by the CHECK_TICK_PERIOD_MS,
  1021. -- Read ID command is sent to the mouse.
  1022. when check_read_id =>
  1023. -- Start the timeout counter
  1024. reset_timeout_cnt <= '0';
  1025. tx_data <= READ_ID;
  1026. write_data <= '1';
  1027. state <= check_read_id_wait_ack;
  1028. -- wait ack for sending the read id command
  1029. when check_read_id_wait_ack =>
  1030. if(read_data = '1') then
  1031. if(rx_data = FA) then
  1032. state <= check_read_id_wait_id;
  1033. else
  1034. state <= reset;
  1035. end if;
  1036. elsif(err = '1') then
  1037. state <= reset;
  1038. elsif (timeout = '1') then -- Timeout ocurred, so the mouse is not present, go to the reset state
  1039. state <= reset;
  1040. else
  1041. state <= check_read_id_wait_ack;
  1042. end if;
  1043. -- received the mouse id
  1044. -- It means that the mouse is present and reading data
  1045. -- can continue
  1046. -- if anything else is received or timeout or an error occurred
  1047. -- then the FSM transitions to reset state.
  1048. when check_read_id_wait_id =>
  1049. if(read_data = '1') then
  1050. if(rx_data = "000000000") or (rx_data = "00000011") then
  1051. -- The mouse is present, so reset the timeout counter
  1052. reset_timeout_cnt <= '1';
  1053. state <= read_byte_1;
  1054. else
  1055. state <= reset;
  1056. end if;
  1057. elsif(err = '1') then
  1058. state <= reset;
  1059. elsif (timeout = '1') then-- Timeout ocurred, so the mouse is not present, go to the reset state
  1060. state <= reset;
  1061. else
  1062. state <= check_read_id_wait_id;
  1063. end if;
  1064. -- set new_event high
  1065. -- it will be reset in next state
  1066. -- informs client new packet received and processed
  1067. when mark_new_event =>
  1068. new_event <= '1';
  1069. state <= read_byte_1;
  1070. -- if invalid transition occurred, reset
  1071. when others =>
  1072. state <= reset;
  1073. end case;
  1074. end if;
  1075. end process manage_fsm;
  1076. end Behavioral;