]> git.friedersdorff.com Git - max/tmk_keyboard.git/blobdiff - tmk_core/protocol/adb.c
Add my keymap
[max/tmk_keyboard.git] / tmk_core / protocol / adb.c
index 164255efaeccf25b63c2a0cbbafb3d890b4317e8..3600595121ce1b606e5ba66eeb08026a393842a7 100644 (file)
@@ -1,5 +1,5 @@
 /*
-Copyright 2011 Jun WAKO <wakojun@gmail.com>
+Copyright 2011-19 Jun WAKO <wakojun@gmail.com>
 Copyright 2013 Shay Green <gblargg@gmail.com>
 
 This software is licensed with a Modified BSD License.
@@ -41,6 +41,7 @@ POSSIBILITY OF SUCH DAMAGE.
 #include <avr/io.h>
 #include <avr/interrupt.h>
 #include "adb.h"
+#include "print.h"
 
 
 // GCC doesn't inline functions normally
@@ -92,84 +93,167 @@ uint16_t adb_host_kbd_recv(uint8_t addr)
 }
 
 #ifdef ADB_MOUSE_ENABLE
+__attribute__ ((weak))
 void adb_mouse_init(void) {
-           return;
+    return;
 }
 
-uint16_t adb_host_mouse_recv(void)
-{
-    return adb_host_talk(ADB_ADDR_MOUSE, ADB_REG_0);
+__attribute__ ((weak))
+void adb_mouse_task(void) {
+    return;
 }
 #endif
 
-uint16_t adb_host_talk(uint8_t addr, uint8_t reg)
+// This sends Talk command to read data from register and returns length of the data.
+uint8_t adb_host_talk_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
 {
-    uint16_t data = 0;
+    for (int8_t i =0; i < len; i++) buf[i] = 0;
+
     cli();
     attention();
-    send_byte((addr<<4) | (ADB_CMD_TALK<<2) | reg);
+    send_byte((addr<<4) | ADB_CMD_TALK | reg);
     place_bit0();               // Stopbit(0)
+    // TODO: Service Request(Srq):
+    // Device holds low part of comannd stopbit for 140-260us
+    //
+    // Command:
+    // ......._     ______________________    ___ ............_     -------
+    //         |   |                      |  |   |             |   |
+    // Command |   |                      |  |   | Data bytes  |   |
+    // ........|___|  |     140-260       |__|   |_............|___|
+    //         |stop0 | Tlt Stop-to-Start |start1|             |stop0 |
+    //
+    // Command without data:
+    // ......._     __________________________
+    //         |   |
+    // Command |   |
+    // ........|___|  |     140-260       |
+    //         |stop0 | Tlt Stop-to-Start |
+    //
+    // Service Request:
+    // ......._                     ______    ___ ............_     -------
+    //         |     140-260       |      |  |   |             |   |
+    // Command |  Service Request  |      |  |   | Data bytes  |   |
+    // ........|___________________|      |__|   |_............|___|
+    //         |stop0 |                   |start1|             |stop0 |
+    // ......._                     __________
+    //         |     140-260       |
+    // Command |  Service Request  |
+    // ........|___________________|
+    //         |stop0 |
+    // This can be happened?
+    // ......._     ______________________    ___ ............_                   -----
+    //         |   |                      |  |   |             |    140-260      |
+    // Command |   |                      |  |   | Data bytes  | Service Request |
+    // ........|___|  |     140-260       |__|   |_............|_________________|
+    //         |stop0 | Tlt Stop-to-Start |start1|             |stop0 |
+    //
+    // "Service requests are issued by the devices during a very specific time at the
+    // end of the reception of the command packet.
+    // If a device in need of service issues a service request, it must do so within
+    // the 65 µs of the Stop Bit’s low time and maintain the line low for a total of 300 µs."
+    //
+    // "A device sends a Service Request signal by holding the bus low during the low
+    // portion of the stop bit of any command or data transaction. The device must lengthen
+    // the stop by a minimum of 140 J.lS beyond its normal duration, as shown in Figure 8-15."
+    // http://ww1.microchip.com/downloads/en/AppNotes/00591b.pdf
     if (!wait_data_hi(500)) {    // Service Request(310us Adjustable Keyboard): just ignored
+        xprintf("R");
         sei();
-        return -30;             // something wrong
+        return 0;
     }
     if (!wait_data_lo(500)) {   // Tlt/Stop to Start(140-260us)
         sei();
-        return 0;               // No data to send
+        return 0;               // No data from device(not error);
+    }
+
+    // start bit(1)
+    if (!wait_data_hi(40)) {
+        xprintf("S");
+        sei();
+        return 0;
+    }
+    if (!wait_data_lo(100)) {
+        xprintf("s");
+        sei();
+        return 0;
     }
 
-    uint8_t n = 17; // start bit + 16 data bits
+    uint8_t n = 0; // bit count
     do {
+        //
+        // |<- bit_cell_max(130) ->|
+        // |        |<-   lo     ->|
+        // |        |       |<-hi->|
+        //           _______
+        // |        |       |
+        // | 130-lo | lo-hi |
+        // |________|       |
+        //
         uint8_t lo = (uint8_t) wait_data_hi(130);
         if (!lo)
-            goto error;
+            goto error; // no more bit or after stop bit
 
         uint8_t hi = (uint8_t) wait_data_lo(lo);
         if (!hi)
-            goto error;
+            goto error; // stop bit extedned by Srq?
 
-        hi = lo - hi;
-        lo = 130 - lo;
+        if (n/8 >= len) continue; // can't store in buf
 
-        data <<= 1;
-        if (lo < hi) {
-            data |= 1;
+        buf[n/8] <<= 1;
+        if ((130 - lo) < (lo - hi)) {
+            buf[n/8] |= 1;
         }
-        else if (n == 17) {
-            sei();
-            return -20;
-        }
-    }
-    while ( --n );
-
-    // Stop bit can't be checked normally since it could have service request lenghtening
-    // and its high state never goes low.
-    if (!wait_data_hi(351) || wait_data_lo(91)) {
-        sei();
-        return -21;
     }
-    sei();
-    return data;
+    while ( ++n );
 
 error:
     sei();
-    return -n;
+    return n/8;
 }
 
-void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l)
+uint16_t adb_host_talk(uint8_t addr, uint8_t reg)
+{
+    uint8_t len;
+    uint8_t buf[8];
+    len = adb_host_talk_buf(addr, reg, buf, 8);
+    if (len != 2) return 0;
+    return (buf[0]<<8 | buf[1]);
+}
+
+void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
 {
     cli();
     attention();
-    send_byte((addr<<4) | (ADB_CMD_LISTEN<<2) | reg);
+    send_byte((addr<<4) | ADB_CMD_LISTEN | reg);
     place_bit0();               // Stopbit(0)
+    // TODO: Service Request
     _delay_us(200);             // Tlt/Stop to Start
     place_bit1();               // Startbit(1)
-    send_byte(data_h);
-    send_byte(data_l);
+    for (int8_t i = 0; i < len; i++) {
+        send_byte(buf[i]);
+        //xprintf("%02X ", buf[i]);
+    }
     place_bit0();               // Stopbit(0);
     sei();
 }
 
+void adb_host_listen(uint8_t addr, uint8_t reg, uint8_t data_h, uint8_t data_l)
+{
+    uint8_t buf[2] = { data_h, data_l };
+    adb_host_listen_buf(addr, reg, buf, 2);
+}
+
+void adb_host_flush(uint8_t addr)
+{
+    cli();
+    attention();
+    send_byte((addr<<4) | ADB_CMD_FLUSH);
+    place_bit0();               // Stopbit(0)
+    _delay_us(200);             // Tlt/Stop to Start
+    sei();
+}
+
 // send state of LEDs
 void adb_host_kbd_led(uint8_t addr, uint8_t led)
 {