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.

143 lines
3.5KB

  1. ; acia
  2. ;
  3. ; Manage I/O from an asynchronous communication interface adapter (ACIA).
  4. ; provides "aciaPutC" to put c char on the ACIA as well as an input buffer.
  5. ; You have to call "aciaInt" on interrupt for this module to work well.
  6. ;
  7. ; "aciaInit" also has to be called on boot, but it doesn't call "ei" and "im 1",
  8. ; which is the responsibility of the main asm file, but is needed.
  9. ; *** DEFINES ***
  10. ; ACIA_CTL: IO port for the ACIA's control registers
  11. ; ACIA_IO: IO port for the ACIA's data registers
  12. ; ACIA_RAMSTART: Address at which ACIA-related variables should be stored in
  13. ; RAM.
  14. ; *** CONSTS ***
  15. ; size of the input buffer. If our input goes over this size, we start losing
  16. ; data.
  17. .equ ACIA_BUFSIZE 0x20
  18. ; *** VARIABLES ***
  19. ; Our input buffer starts there. This is a circular buffer.
  20. .equ ACIA_BUF ACIA_RAMSTART
  21. ; The "read" index of the circular buffer. It points to where the next char
  22. ; should be read. If rd == wr, the buffer is empty. Not touched by the
  23. ; interrupt.
  24. .equ ACIA_BUFRDIDX ACIA_BUF+ACIA_BUFSIZE
  25. ; The "write" index of the circular buffer. Points to where the next char
  26. ; should be written. Should only be touched by the interrupt. if wr == rd-1,
  27. ; the interrupt will *not* write in the buffer until some space has been freed.
  28. .equ ACIA_BUFWRIDX ACIA_BUFRDIDX+1
  29. .equ ACIA_RAMEND ACIA_BUFWRIDX+1
  30. aciaInit:
  31. ; initialize variables
  32. xor a
  33. ld (ACIA_BUFRDIDX), a ; starts at 0
  34. ld (ACIA_BUFWRIDX), a
  35. ; setup ACIA
  36. ; CR7 (1) - Receive Interrupt enabled
  37. ; CR6:5 (00) - RTS low, transmit interrupt disabled.
  38. ; CR4:2 (101) - 8 bits + 1 stop bit
  39. ; CR1:0 (10) - Counter divide: 64
  40. ld a, 0b10010110
  41. out (ACIA_CTL), a
  42. ret
  43. ; Increase the circular buffer index in A, properly considering overflow.
  44. ; returns value in A.
  45. aciaIncIndex:
  46. inc a
  47. cp ACIA_BUFSIZE
  48. ret nz ; not equal? nothing to do
  49. ; equal? reset
  50. xor a
  51. ret
  52. ; read char in the ACIA and put it in the read buffer
  53. aciaInt:
  54. push af
  55. push hl
  56. ; Read our character from ACIA into our BUFIDX
  57. in a, (ACIA_CTL)
  58. bit 0, a ; is our ACIA rcv buffer full?
  59. jr z, .end ; no? a interrupt was triggered for nothing.
  60. ; Load both read and write indexes so we can compare them. To do so, we
  61. ; perform a "fake" read increase and see if it brings it to the same
  62. ; value as the write index.
  63. ld a, (ACIA_BUFRDIDX)
  64. call aciaIncIndex
  65. ld l, a
  66. ld a, (ACIA_BUFWRIDX)
  67. cp l
  68. jr z, .end ; Equal? buffer is full
  69. push de ; <|
  70. ; Alrighty, buffer not full|. let's write.
  71. ld de, ACIA_BUF ; |
  72. ; A already contains our wr|ite index, add it to DE
  73. call addDE ; |
  74. ; increase our buf ptr whil|e we still have it in A
  75. call aciaIncIndex ; |
  76. ld (ACIA_BUFWRIDX), a ;
  77. ; |
  78. ; And finally, fetch the va|lue and write it.
  79. in a, (ACIA_IO) ; |
  80. ld (de), a ; |
  81. pop de ; <|
  82. .end:
  83. pop hl
  84. pop af
  85. ei
  86. reti
  87. ; *** BLOCKDEV ***
  88. ; These function below follow the blockdev API.
  89. aciaGetC:
  90. push de
  91. ld a, (ACIA_BUFWRIDX)
  92. ld e, a
  93. ld a, (ACIA_BUFRDIDX)
  94. cp e
  95. jr z, .nothingToRead ; equal? nothing to read.
  96. ; Alrighty, buffer not empty. let's read.
  97. ld de, ACIA_BUF
  98. ; A already contains our read index, add it to DE
  99. call addDE
  100. ; increase our buf ptr while we still have it in A
  101. call aciaIncIndex
  102. ld (ACIA_BUFRDIDX), a
  103. ; And finally, fetch the value.
  104. ld a, (de)
  105. cp a ; ensure Z
  106. jr .end
  107. .nothingToRead:
  108. call unsetZ
  109. .end:
  110. pop de
  111. ret
  112. ; spits character in A in port SER_OUT
  113. aciaPutC:
  114. push af
  115. .stwait:
  116. in a, (ACIA_CTL) ; get status byte from SER
  117. bit 1, a ; are we still transmitting?
  118. jr z, .stwait ; if yes, wait until we aren't
  119. pop af
  120. out (ACIA_IO), a ; push current char
  121. ret