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.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

ibm4704.c 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  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. // POR
  18. //_delay_ms(2500);
  19. //while ( 0xA3 != ibm4704_recv() ) ;
  20. inhibit();
  21. DDRD |= 1<<3;
  22. PORTD &= ~(1<<3);
  23. }
  24. uint8_t ibm4704_send(uint8_t data)
  25. {
  26. bool parity = true; // odd parity
  27. ibm4704_error = 0;
  28. /* Request to send */
  29. idle();
  30. clock_lo();
  31. PIND |= 1<<3;
  32. /* wait for Start bit(Clock:lo/Data:hi) */
  33. WAIT(data_hi, 300, 0x30);
  34. /* Data bit */
  35. for (uint8_t i = 0; i < 8; i++) {
  36. WAIT(clock_hi, 100, 0x31);
  37. //_delay_us(5);
  38. PIND |= 1<<3;
  39. if (data&(1<<i)) {
  40. parity = !parity;
  41. data_hi();
  42. } else {
  43. data_lo();
  44. }
  45. WAIT(clock_lo, 100, 0x32);
  46. }
  47. /* Parity bit */
  48. WAIT(clock_hi, 100, 4);
  49. PIND |= 1<<3;
  50. if (parity) { data_hi(); } else { data_lo(); }
  51. WAIT(clock_lo, 100, 5);
  52. /* Stop bit */
  53. WAIT(clock_hi, 100, 4);
  54. data_hi();
  55. /* End */
  56. WAIT(data_lo, 100, 6);
  57. inhibit();
  58. _delay_us(200); // wait to recover clock to hi
  59. return 0;
  60. ERROR:
  61. inhibit();
  62. xprintf("x%02X ", ibm4704_error);
  63. _delay_us(200); // wait to recover clock to hi
  64. return -1;
  65. }
  66. /* receive data when host want else inhibit communication */
  67. uint8_t ibm4704_recv_response(void)
  68. {
  69. // 250 * 100us(wait start bit in ibm4704_recv)
  70. uint8_t data = 0;
  71. uint8_t try = 250;
  72. do {
  73. data = ibm4704_recv();
  74. } while (try-- && ibm4704_error);
  75. return data;
  76. }
  77. /*
  78. Keyboard to Host:
  79. Clock ~~~~___~~_~~_~~_~~_~~_~~_~~_~~_~~_~~~~~~~~ H:60us/L:30us
  80. Data ____~~X==X==X==X==X==X==X==X==X==X________
  81. | 0 1 2 3 4 5 6 7 P(odd)
  82. | LSB MSB
  83. Start bit(80us)
  84. */
  85. uint8_t ibm4704_recv(void)
  86. {
  87. uint8_t data = 0;
  88. bool parity = true; // odd parity
  89. ibm4704_error = IBM4704_ERR_NONE;
  90. idle();
  91. _delay_us(5); // wait for line settles
  92. /* start bit */
  93. WAIT(clock_lo, 100, 1); // wait for keyboard to send
  94. WAIT(data_hi, 100, 2); // can be delayed that long
  95. WAIT(clock_hi, 100, 3); // first rising edge which can take longer
  96. /* data */
  97. for (uint8_t i = 0; i < 8; i++) {
  98. WAIT(clock_hi, 100, 0x20+i);
  99. //_delay_us(5);
  100. if (data_in()) {
  101. parity = !parity;
  102. data |= (1<<i);
  103. }
  104. WAIT(clock_lo, 150, 0x28+i);
  105. }
  106. /* parity */
  107. WAIT(clock_hi, 100, 7);
  108. if (data_in() != parity) {
  109. ibm4704_error = IBM4704_ERR_PARITY;
  110. goto ERROR;
  111. }
  112. WAIT(clock_lo, 150, 8);
  113. /* stop bit */
  114. WAIT(clock_hi, 100, 9);
  115. WAIT(data_lo, 1, 9);
  116. inhibit();
  117. _delay_us(200); // wait to recover clock to hi
  118. return data;
  119. ERROR:
  120. if (ibm4704_error > 2) {
  121. xprintf("x%02X ", ibm4704_error);
  122. }
  123. inhibit();
  124. _delay_us(200); // wait to recover clock to hi
  125. return -1;
  126. }