/*
-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.
#include <avr/io.h>
#include <avr/interrupt.h>
#include "adb.h"
+#include "print.h"
// GCC doesn't inline functions normally
* <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919>
* <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139>
*/
-uint16_t adb_host_kbd_recv(void)
+uint16_t adb_host_kbd_recv(uint8_t addr)
{
- return adb_host_talk(ADB_ADDR_KEYBOARD, ADB_REG_0);
+ return adb_host_talk(addr, ADB_REG_0);
}
#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;
- }
- else if (n == 17) {
- sei();
- return -20;
+ buf[n/8] <<= 1;
+ if ((130 - lo) < (lo - hi)) {
+ buf[n/8] |= 1;
}
}
- 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;
+}
+
+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(uint8_t cmd, uint8_t data_h, uint8_t data_l)
+void adb_host_listen_buf(uint8_t addr, uint8_t reg, uint8_t *buf, uint8_t len)
{
cli();
attention();
- send_byte(cmd);
+ 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 led)
+void adb_host_kbd_led(uint8_t addr, uint8_t led)
{
- // Addr:Keyboard(0010), Cmd:Listen(10), Register2(10)
- // send upper byte (not used)
- // send lower byte (bit2: ScrollLock, bit1: CapsLock, bit0:
- adb_host_listen(0x2A,0,led&0x07);
+ // Listen Register2
+ // upper byte: not used
+ // lower byte: bit2=ScrollLock, bit1=CapsLock, bit0=NumLock
+ adb_host_listen(addr, 2, 0, led & 0x07);
}
bits commands
------------------------------------------------------
- - - - - 0 0 0 0 Send Request(reset all devices)
+ - - - - 0 0 0 0 Send Reset(reset all devices)
A A A A 0 0 0 1 Flush(reset a device)
- - - - 0 0 1 0 Reserved
- - - - 0 0 1 1 Reserved
| +----------------------------- Delete
+------------------------------- Reserved
+Address, Handler ID and bits(Register3)
+ 1514131211 . . 8 7 . . . . . . 0
+ | | | | | | | | | | | | | | | |
+ | | | | | | | | +-+-+-+-+-+-+-+- Handler ID
+ | | | | +-+-+-+----------------- Address
+ | | | +------------------------- 0
+ | | +--------------------------- Service request enable(1 = enabled)
+ | +----------------------------- Exceptional event(alwyas 1 if not used)
+ +------------------------------- 0
+
ADB Bit Cells
bit cell time: 70-130us
low part of bit0: 60-70% of bit cell