Mirror of CollapseOS
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

143 rindas
4.0KB

  1. #include <string.h>
  2. #include "t6a04.h"
  3. void t6a04_init(T6A04 *lcd)
  4. {
  5. memset(lcd->ram, 0, T6A04_RAMSIZE);
  6. lcd->enabled = false;
  7. lcd->incmode = T6A04_XINC;
  8. lcd->offset = 0;
  9. lcd->currow = 0;
  10. lcd->curcol = 0;
  11. lcd->just_moved = true;
  12. lcd->has8bitmode = false;
  13. }
  14. uint8_t t6a04_cmd_rd(T6A04 *lcd)
  15. {
  16. return 0; // we are always ready for a new cmd
  17. }
  18. /*
  19. * 0x00/0x01: 6/8 bit mode
  20. * 0x02/0x03: enable/disable
  21. * 0x04-0x07: incmodes
  22. * 0x20-0x34: set col
  23. * 0x40-0x7f: set Z offset
  24. * 0x80-0xbf: set row
  25. * 0xc0-0xff: set contrast
  26. */
  27. void t6a04_cmd_wr(T6A04 *lcd, uint8_t val)
  28. {
  29. if ((val & 0xc0) == 0xc0) {
  30. // contrast, ignoring
  31. } else if (val & 0x80) {
  32. lcd->currow = val & 0x3f;
  33. lcd->just_moved = true;
  34. } else if (val & 0x40) {
  35. lcd->offset = val & 0x3f;
  36. } else if (val & 0x20) {
  37. lcd->curcol = val & 0x1f;
  38. lcd->just_moved = true;
  39. } else if (val & 0x18) {
  40. // stuff we don't emulate
  41. } else if (val & 0x04) {
  42. lcd->incmode = val & 0x03;
  43. } else if (val & 0x02) {
  44. lcd->enabled = val & 0x01;
  45. } else {
  46. lcd->has8bitmode = val;
  47. }
  48. }
  49. // Advance current position according to current incmode
  50. static void _advance(T6A04 *lcd)
  51. {
  52. uint8_t maxY = lcd->has8bitmode ? 14 : 19;
  53. switch (lcd->incmode) {
  54. case T6A04_XDEC:
  55. lcd->currow = (lcd->currow-1) & 0x3f;
  56. break;
  57. case T6A04_XINC:
  58. lcd->currow = (lcd->currow+1) & 0x3f;
  59. break;
  60. case T6A04_YDEC:
  61. if (lcd->curcol == 0) {
  62. lcd->curcol = maxY;
  63. } else {
  64. lcd->curcol--;
  65. }
  66. break;
  67. case T6A04_YINC:
  68. if (lcd->curcol < maxY) {
  69. lcd->curcol++;
  70. } else {
  71. lcd->curcol = 0;
  72. }
  73. break;
  74. }
  75. }
  76. uint8_t t6a04_data_rd(T6A04 *lcd)
  77. {
  78. uint8_t res;
  79. if (lcd->just_moved) {
  80. // After a move command, the first read op is a noop.
  81. lcd->just_moved = false;
  82. return 0;
  83. }
  84. if (lcd->has8bitmode) {
  85. int pos = lcd->currow * T6A04_ROWSIZE + lcd->curcol;
  86. res = lcd->ram[pos];
  87. } else {
  88. // 6bit mode is a bit more complicated because the 6-bit number often
  89. // spans two bytes. We manage this by loading two bytes into a uint16_t
  90. // and then shift it right properly.
  91. // bitpos represents the leftmost bit of our 6bit number.
  92. int bitpos = lcd->curcol * 6;
  93. // offset represents the shift right we need to perform from the two
  94. // bytes following bitpos/8 so that we can have our number with a 6-bit
  95. // mask.
  96. // Example, col 3 has a bitpos of 18, which means that it loads bytes 2
  97. // and 3. Its bits would be in bit pos 14:8, which means it has an
  98. // offset of 8. There is always an offset and its always in the 3-10
  99. // range
  100. int offset = 10 - (bitpos % 8); // 10 is for 16bit - 6bit
  101. int pos = (lcd->currow * T6A04_ROWSIZE) + (bitpos / 8);
  102. uint16_t word = lcd->ram[pos] << 8;
  103. word |= lcd->ram[pos+1];
  104. res = (word >> offset) & 0x3f;
  105. }
  106. _advance(lcd);
  107. return res;
  108. }
  109. void t6a04_data_wr(T6A04 *lcd, uint8_t val)
  110. {
  111. lcd->just_moved = false;
  112. if (lcd->has8bitmode) {
  113. int pos = lcd->currow * T6A04_ROWSIZE + lcd->curcol;
  114. lcd->ram[pos] = val;
  115. } else {
  116. // See comments in t6a04_data_rd().
  117. int bitpos = lcd->curcol * 6;
  118. int offset = 10 - (bitpos % 8);
  119. int pos = (lcd->currow * T6A04_ROWSIZE) + (bitpos / 8);
  120. uint16_t word = lcd->ram[pos] << 8;
  121. word |= lcd->ram[pos+1];
  122. // word contains our current ram value. Let's fit val in this.
  123. word &= ~(0x003f << offset);
  124. word |= val << offset;
  125. lcd->ram[pos] = word >> 8;
  126. lcd->ram[pos+1] = word & 0xff;
  127. }
  128. _advance(lcd);
  129. }
  130. bool t6a04_pixel(T6A04 *lcd, uint8_t y, uint8_t x)
  131. {
  132. x = (x + lcd->offset) & 0x3f;
  133. uint8_t val = lcd->ram[x * T6A04_ROWSIZE + (y / 8)];
  134. return (val >> (7 - (y % 8))) & 1;
  135. }