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.

137 lines
3.4KB

  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. ; *** STDIO ***
  88. ; These function below follow the stdio API.
  89. aciaGetC:
  90. push de
  91. .loop:
  92. ld a, (ACIA_BUFWRIDX)
  93. ld e, a
  94. ld a, (ACIA_BUFRDIDX)
  95. cp e
  96. jr z, .loop ; equal? nothing to read. loop
  97. ; Alrighty, buffer not empty. let's read.
  98. ld de, ACIA_BUF
  99. ; A already contains our read index, add it to DE
  100. call addDE
  101. ; increase our buf ptr while we still have it in A
  102. call aciaIncIndex
  103. ld (ACIA_BUFRDIDX), a
  104. ; And finally, fetch the value.
  105. ld a, (de)
  106. pop de
  107. ret
  108. ; spits character in A in port SER_OUT
  109. aciaPutC:
  110. push af
  111. .stwait:
  112. in a, (ACIA_CTL) ; get status byte from SER
  113. bit 1, a ; are we still transmitting?
  114. jr z, .stwait ; if yes, wait until we aren't
  115. pop af
  116. out (ACIA_IO), a ; push current char
  117. ret