Mirror of CollapseOS
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.

326 lines
8.3KB

  1. ( Receives keystrokes from PS/2 keyboard and send them to the
  2. '164. On the PS/2 side, it works the same way as the controller
  3. in the rc2014/ps2 recipe. However, in this case, what we have
  4. on the other side isn't a z80 bus, it's the one of the two
  5. controller ports of the SMS through a DB9 connector.
  6. The PS/2 related code is copied from rc2014/ps2 without much
  7. change. The only differences are that it pushes its data to a
  8. '164 instead of a '595 and that it synchronizes with the SMS
  9. with a SR latch, so we don't need PCINT. We can also afford to
  10. run at 1MHz instead of 8.
  11. *** Register Usage ***
  12. GPIOR0 flags:
  13. 0 - when set, indicates that the DATA pin was high when we
  14. received a bit through INT0. When we receive a bit, we set
  15. flag T to indicate it.
  16. R16: tmp stuff
  17. R17: recv buffer. Whenever we receive a bit, we push it in
  18. there.
  19. R18: recv step:
  20. - 0: idle
  21. - 1: receiving data
  22. - 2: awaiting parity bit
  23. - 3: awaiting stop bit
  24. R19: Register used for parity computations and tmp value in
  25. some other places
  26. R20: data being sent to the '164
  27. Y: pointer to the memory location where the next scan code from
  28. ps/2 will be written.
  29. Z: pointer to the next scan code to push to the 595 )
  30. 0x0060 CONSTANT SRAM_START
  31. 0x015f CONSTANT RAMEND
  32. 0x3d CONSTANT SPL
  33. 0x3e CONSTANT SPH
  34. 0x11 CONSTANT GPIOR0
  35. 0x35 CONSTANT MCUCR
  36. 0x33 CONSTANT TCCR0B
  37. 0x3b CONSTANT GIMSK
  38. 0x38 CONSTANT TIFR
  39. 0x32 CONSTANT TCNT0
  40. 0x16 CONSTANT PINB
  41. 0x17 CONSTANT DDRB
  42. 0x18 CONSTANT PORTB
  43. 2 CONSTANT CLK
  44. 1 CONSTANT DATA
  45. 3 CONSTANT CP
  46. 0 CONSTANT LQ
  47. 4 CONSTANT LR
  48. 0x100 100 - CONSTANT TIMER_INITVAL
  49. ( We need a lot of labels in this program... )
  50. VARIABLE L5 VARIABLE L6 VARIABLE L7 VARIABLE L8
  51. H@ ORG !
  52. L1 FLBL, ( main )
  53. L2 FLBL, ( hdlINT0 )
  54. ( Read DATA and set GPIOR0/0 if high. Then, set flag T.
  55. no SREG fiddling because no SREG-modifying instruction )
  56. L2 ' RJMP FLBL! ( hdlINT0 )
  57. PINB DATA SBIC,
  58. GPIOR0 0 SBI,
  59. SET,
  60. RETI,
  61. L1 ' RJMP FLBL! ( main )
  62. R16 RAMEND 0xff AND LDI,
  63. SPL R16 OUT,
  64. R16 RAMEND 8 RSHIFT LDI,
  65. SPH R16 OUT,
  66. ( init variables )
  67. R18 CLR,
  68. GPIOR0 R18 OUT,
  69. ( Setup int0
  70. INT0, falling edge )
  71. R16 0x02 ( ISC01 ) LDI,
  72. MCUCR R16 OUT,
  73. ( Enable INT0 )
  74. R16 0x40 ( INT0 ) LDI,
  75. GIMSK R16 OUT,
  76. ( Setup buffer )
  77. YH CLR,
  78. YL SRAM_START 0xff AND LDI,
  79. ZH CLR,
  80. ZL SRAM_START 0xff AND LDI,
  81. ( Setup timer. We use the timer to clear up "processbit"
  82. registers after 100us without a clock. This allows us to start
  83. the next frame in a fresh state. at 1MHZ, no prescaling is
  84. necessary. Each TCNT0 tick is already 1us long. )
  85. R16 0x01 ( CS00 ) LDI, ( no prescaler )
  86. TCCR0B R16 OUT,
  87. ( init DDRB )
  88. DDRB CP SBI,
  89. PORTB LR CBI,
  90. DDRB LR SBI,
  91. SEI,
  92. L1 LBL! ( loop )
  93. L2 FLBL, ( BRTS processbit. flag T set? we have a bit to
  94. process )
  95. YL ZL CP, ( if YL == ZL, buf is empty )
  96. L3 FLBL, ( BRNE sendTo164. YL != ZL? buf has data )
  97. ( nothing to do. Before looping, let's check if our
  98. communication timer overflowed. )
  99. R16 TIFR IN,
  100. R16 1 ( TOV0 ) SBRC,
  101. L4 FLBL, ( RJMP processbitReset, timer0 overflow? reset )
  102. ( Nothing to do for real. )
  103. L1 ' RJMP LBL, ( loop )
  104. ( Process the data bit received in INT0 handler. )
  105. L2 ' BRTS FLBL! ( processbit )
  106. R19 GPIOR0 IN, ( backup GPIOR0 before we reset T )
  107. R19 0x1 ANDI, ( only keep the first flag )
  108. GPIOR0 0 CBI,
  109. CLT, ( ready to receive another bit )
  110. ( We've received a bit. reset timer )
  111. L2 FLBL, ( RCALL resetTimer )
  112. ( Which step are we at? )
  113. R18 TST,
  114. L5 FLBL, ( BREQ processbits0 )
  115. R18 1 CPI,
  116. L6 FLBL, ( BREQ processbits1 )
  117. R18 2 CPI,
  118. L7 FLBL, ( BREQ processbits2 )
  119. ( step 3: stop bit )
  120. R18 CLR, ( happens in all cases )
  121. ( DATA has to be set )
  122. R19 TST, ( was DATA set? )
  123. L1 ' BREQ LBL, ( loop, not set? error, don't push to buf )
  124. ( push r17 to the buffer )
  125. Y+ R17 ST,
  126. L8 FLBL, ( RCALL checkBoundsY )
  127. L1 ' RJMP LBL,
  128. L5 ' BREQ FLBL! ( processbits0 )
  129. ( step 0 - start bit )
  130. ( DATA has to be cleared )
  131. R19 TST, ( was DATA set? )
  132. L1 ' BRNE LBL, ( loop. set? error. no need to do anything. keep
  133. r18 as-is. )
  134. ( DATA is cleared. prepare r17 and r18 for step 1 )
  135. R18 INC,
  136. R17 0x80 LDI,
  137. L1 ' RJMP LBL, ( loop )
  138. L6 ' BREQ FLBL! ( processbits1 )
  139. ( step 1 - receive bit
  140. We're about to rotate the carry flag into r17. Let's set it
  141. first depending on whether DATA is set. )
  142. CLC,
  143. R19 0 SBRC, ( skip if DATA is cleared )
  144. SEC,
  145. ( Carry flag is set )
  146. R17 ROR,
  147. ( Good. now, are we finished rotating? If carry flag is set,
  148. it means that we've rotated in 8 bits. )
  149. L1 ' BRCC LBL, ( loop )
  150. ( We're finished, go to step 2 )
  151. R18 INC,
  152. L1 ' RJMP LBL, ( loop )
  153. L7 ' BREQ FLBL! ( processbits2 )
  154. ( step 2 - parity bit )
  155. R1 R19 MOV,
  156. R19 R17 MOV,
  157. L5 FLBL, ( RCALL checkParity )
  158. R1 R16 CP,
  159. L6 FLBL, ( BRNE processBitError, r1 != r16? wrong parity )
  160. R18 INC,
  161. L1 ' RJMP LBL, ( loop )
  162. L6 ' BRNE FLBL! ( processBitError )
  163. R18 CLR,
  164. R19 0xfe LDI,
  165. L6 FLBL, ( RCALL sendToPS2 )
  166. L1 ' RJMP LBL, ( loop )
  167. L4 ' RJMP FLBL! ( processbitReset )
  168. R18 CLR,
  169. L4 FLBL, ( RCALL resetTimer )
  170. L1 ' RJMP LBL, ( loop )
  171. L3 ' BRNE FLBL! ( sendTo164 )
  172. ( Send the value of r20 to the '164 )
  173. PINB LQ SBIS, ( LQ is set? we can send the next byte )
  174. L1 ' RJMP LBL, ( loop, even if we have something in the
  175. buffer, we can't: the SMS hasn't read our
  176. previous buffer yet. )
  177. ( We disable any interrupt handling during this routine.
  178. Whatever it is, it has no meaning to us at this point in time
  179. and processing it might mess things up. )
  180. CLI,
  181. DDRB DATA SBI,
  182. R20 Z+ LD,
  183. L3 FLBL, ( RCALL checkBoundsZ )
  184. R16 R8 LDI,
  185. BEGIN,
  186. PORTB DATA CBI,
  187. R20 7 SBRC, ( if leftmost bit isn't cleared, set DATA high )
  188. PORTB DATA SBI,
  189. ( toggle CP )
  190. PORTB CP CBI,
  191. R20 LSL,
  192. PORTB CP SBI,
  193. R16 DEC,
  194. ' BRNE AGAIN?, ( not zero yet? loop )
  195. ( release PS/2 )
  196. DDRB DATA CBI,
  197. SEI,
  198. ( Reset the latch to indicate that the next number is ready )
  199. PORTB LR SBI,
  200. PORTB LR CBI,
  201. L1 ' RJMP LBL, ( loop )
  202. L2 ' RCALL FLBL! L4 ' RCALL FLBL! L2 LBL! ( resetTimer )
  203. R16 TIMER_INITVAL LDI,
  204. TCNT0 R16 OUT,
  205. R16 0x02 ( TOV0 ) LDI,
  206. TIFR R16 OUT,
  207. RET,
  208. L6 ' RCALL FLBL! ( sendToPS2 )
  209. ( Send the value of r19 to the PS/2 keyboard )
  210. CLI,
  211. ( First, indicate our request to send by holding both Clock low
  212. for 100us, then pull Data low lines low for 100us. )
  213. PORTB CLK CBI,
  214. DDRB CLK SBI,
  215. L2 ' RCALL LBL, ( resetTimer )
  216. ( Wait until the timer overflows )
  217. BEGIN,
  218. R16 TIFR IN,
  219. R16 1 ( TOV0 ) SBRS,
  220. AGAIN,
  221. ( Good, 100us passed. )
  222. ( Pull Data low, that's our start bit. )
  223. PORTB DATA CBI,
  224. DDRB DATA SBI,
  225. ( Now, let's release the clock. At the next raising edge, we'll
  226. be expected to have set up our first bit (LSB). We set up
  227. when CLK is low. )
  228. DDRB CLK CBI, ( Should be starting high now. )
  229. ( We will do the next loop 8 times )
  230. R16 8 LDI,
  231. ( Let's remember initial r19 for parity )
  232. R1 R19 MOV,
  233. BEGIN,
  234. ( Wait for CLK to go low )
  235. BEGIN, PINB CLK SBIC, AGAIN,
  236. ( set up DATA )
  237. PORTB DATA CBI,
  238. R19 0 SBRC, ( skip if LSB is clear )
  239. PORTB DATA SBI,
  240. R19 LSR,
  241. ( Wait for CLK to go high )
  242. BEGIN, PINB CLK SBIS, AGAIN,
  243. 16 DEC,
  244. ' BRNE AGAIN?, ( not zero? loop )
  245. ( Data was sent, CLK is high. Let's send parity )
  246. R19 R1 MOV, ( recall saved value )
  247. L6 FLBL, ( RCALL checkParity )
  248. ( Wait for CLK to go low )
  249. BEGIN, PINB CLK SBIC, AGAIN,
  250. ( set parity bit )
  251. PORTB DATA CBI,
  252. R16 0 SBRC, ( parity bit in r16 )
  253. PORTB DATA SBI,
  254. ( Wait for CLK to go high )
  255. BEGIN, PINB CLK SBIS, AGAIN,
  256. ( Wait for CLK to go low )
  257. BEGIN, PINB CLK SBIC, AGAIN,
  258. ( We can now release the DATA line )
  259. DDRB DATA CBI,
  260. ( Wait for DATA to go low, that's our ACK )
  261. BEGIN, PINB DATA SBIC, AGAIN,
  262. ( Wait for CLK to go low )
  263. BEGIN, PINB CLK SBIC, AGAIN,
  264. ( We're finished! Enable INT0, reset timer, everything back to
  265. normal! )
  266. L2 ' RCALL LBL, ( resetTimer )
  267. CLT, ( also, make sure T isn't mistakely set. )
  268. SEI,
  269. RET,
  270. L8 ' RCALL FLBL! ( checkBoundsY )
  271. ( Check that Y is within bounds, reset to SRAM_START if not. )
  272. YL TST,
  273. IF, RET, ( not zero, nothing to do ) THEN,
  274. ( YL is zero. Reset Z )
  275. YH CLR,
  276. YL SRAM_START 0xff AND LDI,
  277. RET,
  278. L3 ' RCALL FLBL! ( checkBoundsZ )
  279. ( Check that Z is within bounds, reset to SRAM_START if not. )
  280. ZL TST,
  281. IF, RET, ( not zero, nothing to do ) THEN,
  282. ( ZL is zero. Reset Z )
  283. ZH CLR,
  284. ZL SRAM_START 0xff AND LDI,
  285. RET,
  286. L5 ' RCALL FLBL! L6 ' RCALL FLBL! ( checkParity )
  287. ( Counts the number of 1s in r19 and set r16 to 1 if there's an
  288. even number of 1s, 0 if they're odd. )
  289. R16 1 LDI,
  290. BEGIN,
  291. R19 LSR,
  292. ' BRCC SKIP, R16 INC, ( carry set? we had a 1 ) TO,
  293. R19 TST, ( is r19 zero yet? )
  294. ' BRNE AGAIN?, ( no? loop )
  295. R16 0x1 ANDI,
  296. RET,