Keyboard firmwares for Atmel AVR and Cortex-M
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.

ibm4704.c 3.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. /*
  2. Copyright 2010,2011,2012,2013 Jun WAKO <[email protected]>
  3. */
  4. #include <stdbool.h>
  5. #include <util/delay.h>
  6. #include "debug.h"
  7. #include "ibm4704.h"
  8. #define WAIT(stat, us, err) do { \
  9. if (!wait_##stat(us)) { \
  10. ibm4704_error = err; \
  11. goto ERROR; \
  12. } \
  13. } while (0)
  14. uint8_t ibm4704_error = 0;
  15. void ibm4704_init(void)
  16. {
  17. inhibit();
  18. }
  19. uint8_t ibm4704_send(uint8_t data)
  20. {
  21. bool parity = true; // odd parity
  22. ibm4704_error = 0;
  23. /* Request to send */
  24. idle();
  25. clock_lo();
  26. /* wait for Start bit(Clock:lo/Data:hi) */
  27. WAIT(data_hi, 300, 0x30);
  28. /* Data bit */
  29. for (uint8_t i = 0; i < 8; i++) {
  30. WAIT(clock_hi, 100, 0x40+i);
  31. //_delay_us(5);
  32. if (data&(1<<i)) {
  33. parity = !parity;
  34. data_hi();
  35. } else {
  36. data_lo();
  37. }
  38. WAIT(clock_lo, 100, 0x48+i);
  39. }
  40. /* Parity bit */
  41. WAIT(clock_hi, 100, 0x34);
  42. if (parity) { data_hi(); } else { data_lo(); }
  43. WAIT(clock_lo, 100, 0x35);
  44. /* Stop bit */
  45. WAIT(clock_hi, 100, 0x34);
  46. data_hi();
  47. /* End */
  48. WAIT(data_lo, 100, 0x36);
  49. inhibit();
  50. _delay_us(200); // wait to recover clock to hi
  51. return 0;
  52. ERROR:
  53. inhibit();
  54. if (ibm4704_error >= 0x30) {
  55. xprintf("x%02X ", ibm4704_error);
  56. }
  57. _delay_us(200); // wait to recover clock to hi
  58. return -1;
  59. }
  60. /* receive data when host want else inhibit communication */
  61. uint8_t ibm4704_recv_response(void)
  62. {
  63. // 250 * 100us(wait start bit in ibm4704_recv)
  64. uint8_t data = 0;
  65. uint8_t try = 250;
  66. do {
  67. data = ibm4704_recv();
  68. } while (try-- && ibm4704_error);
  69. return data;
  70. }
  71. /*
  72. Keyboard to Host:
  73. Clock ~~~~___~~_~~_~~_~~_~~_~~_~~_~~_~~_~~~~~~~~ H:60us/L:30us
  74. Data ____~~X==X==X==X==X==X==X==X==X==X________
  75. | 0 1 2 3 4 5 6 7 P(odd)
  76. | LSB MSB
  77. Start bit(80us)
  78. */
  79. uint8_t ibm4704_recv(void)
  80. {
  81. uint8_t data = 0;
  82. bool parity = true; // odd parity
  83. ibm4704_error = IBM4704_ERR_NONE;
  84. idle();
  85. _delay_us(5); // wait for line settles
  86. /* start bit */
  87. WAIT(clock_lo, 100, 0x11); // wait for keyboard to send
  88. WAIT(data_hi, 100, 0x12); // can be delayed that long
  89. WAIT(clock_hi, 100, 0x13); // first rising edge which can take longer
  90. /* data */
  91. for (uint8_t i = 0; i < 8; i++) {
  92. WAIT(clock_hi, 100, 0x20+i);
  93. //_delay_us(5);
  94. if (data_in()) {
  95. parity = !parity;
  96. data |= (1<<i);
  97. }
  98. WAIT(clock_lo, 150, 0x28+i);
  99. }
  100. /* parity */
  101. WAIT(clock_hi, 100, 0x17);
  102. if (data_in() != parity) {
  103. ibm4704_error = IBM4704_ERR_PARITY;
  104. goto ERROR;
  105. }
  106. WAIT(clock_lo, 150, 0x18);
  107. /* stop bit */
  108. WAIT(clock_hi, 100, 0x19);
  109. WAIT(data_lo, 1, 0x19);
  110. inhibit();
  111. _delay_us(200); // wait to recover clock to hi
  112. return data;
  113. ERROR:
  114. if (ibm4704_error > 0x12) {
  115. xprintf("x%02X ", ibm4704_error);
  116. }
  117. inhibit();
  118. _delay_us(200); // wait to recover clock to hi
  119. return -1;
  120. }