diff options
Diffstat (limited to 'protocol')
-rw-r--r-- | protocol/adb.c | 217 | ||||
-rw-r--r-- | protocol/lufa/lufa.c | 9 | ||||
-rw-r--r-- | protocol/m0110.c | 50 | ||||
-rw-r--r-- | protocol/pjrc/main.c | 3 | ||||
-rw-r--r-- | protocol/pjrc/usb.c | 1 |
5 files changed, 145 insertions, 135 deletions
diff --git a/protocol/adb.c b/protocol/adb.c index 2baad32340..750f4b9650 100644 --- a/protocol/adb.c +++ b/protocol/adb.c @@ -1,5 +1,6 @@ /* Copyright 2011 Jun WAKO <wakojun@gmail.com> +Copyright 2013 Shay Green <gblargg@gmail.com> This software is licensed with a Modified BSD License. All of this is supposed to be Free Software, Open Source, DFSG-free, @@ -40,11 +41,14 @@ POSSIBILITY OF SUCH DAMAGE. #include <avr/io.h> #include <avr/interrupt.h> #include "adb.h" +#include "debug.h" -static inline void data_lo(void); -static inline void data_hi(void); -static inline bool data_in(void); +// GCC doesn't inline functions normally +#define data_lo() (ADB_DDR |= (1<<ADB_DATA_BIT)) +#define data_hi() (ADB_DDR &= ~(1<<ADB_DATA_BIT)) +#define data_in() (ADB_PIN & (1<<ADB_DATA_BIT)) + #ifdef ADB_PSW_BIT static inline void psw_lo(void); static inline void psw_hi(void); @@ -55,24 +59,17 @@ static inline void attention(void); static inline void place_bit0(void); static inline void place_bit1(void); static inline void send_byte(uint8_t data); -static inline bool read_bit(void); -static inline uint8_t read_byte(void); -static inline uint8_t wait_data_lo(uint16_t us); -static inline uint8_t wait_data_hi(uint8_t us); +static inline uint16_t wait_data_lo(uint16_t us); +static inline uint16_t wait_data_hi(uint16_t us); void adb_host_init(void) { + ADB_PORT &= ~(1<<ADB_DATA_BIT); data_hi(); #ifdef ADB_PSW_BIT psw_hi(); #endif - - // Enable keyboard left/right modifier distinction - // Addr:Keyboard(0010), Cmd:Listen(10), Register3(11) - // upper byte: reserved bits 0000, device address 0010 - // lower byte: device handler 00000011 - adb_host_listen(0x2B,0x02,0x03); } #ifdef ADB_PSW_BIT @@ -82,6 +79,49 @@ bool adb_host_psw(void) } #endif +/* + * Don't call this in a row without the delay, otherwise it makes some of poor controllers + * overloaded and misses strokes. Recommended interval is 12ms. + * + * Thanks a lot, blargg! + * <http://geekhack.org/index.php?topic=14290.msg1068919#msg1068919> + * <http://geekhack.org/index.php?topic=14290.msg1070139#msg1070139> + */ + +// ADB Bit Cells +// +// bit cell time: 70-130us +// low part of bit0: 60-70% of bit cell +// low part of bit1: 30-40% of bit cell +// +// bit cell time 70us 130us +// -------------------------------------------- +// low part of bit0 42-49 78-91 +// high part of bit0 21-28 39-52 +// low part of bit1 21-28 39-52 +// high part of bit1 42-49 78-91 +// +// +// bit0: +// 70us bit cell: +// ____________~~~~~~ +// 42-49 21-28 +// +// 130us bit cell: +// ____________~~~~~~ +// 78-91 39-52 +// +// bit1: +// 70us bit cell: +// ______~~~~~~~~~~~~ +// 21-28 42-49 +// +// 130us bit cell: +// ______~~~~~~~~~~~~ +// 39-52 78-91 +// +// [from Apple IIgs Hardware Reference Second Edition] + uint16_t adb_host_kbd_recv(void) { uint16_t data = 0; @@ -91,22 +131,50 @@ uint16_t adb_host_kbd_recv(void) if (!wait_data_lo(500)) { // Tlt/Stop to Start(140-260us) return 0; // No data to send } - if (!read_bit()) { // Startbit(1) - // Service Request - return -2; - } - + // ad hoc fix: without block inerrupt read wrong bit occasionally and get keys stuck - cli(); - data = read_byte(); - data = (data<<8) | read_byte(); - uint8_t stop = read_bit(); // Stopbit(0) - sei(); + // TODO: is this needed anymore with improved timing? + //cli(); + uint8_t n = 17; // start bit + 16 data bits + do { + uint8_t lo = (uint8_t) wait_data_hi(130); + if (!lo) + goto error; + + uint8_t hi = (uint8_t) wait_data_lo(lo); + if (!hi) + goto error; + + hi = lo - hi; + lo = 130 - lo; + + data <<= 1; + if (lo < hi) { + data |= 1; + } + else if (n == 17) { + // Service Request + dprintf("Startbit ERROR\n"); + sei(); + return -2; + } + } + while ( --n ); - if (stop) { + // 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)) { + dprintf("Stopbit ERROR\n"); + sei(); return -3; } + sei(); return data; + +error: + dprintf("Bit ERROR\n"); + sei(); + return -4; } void adb_host_listen(uint8_t cmd, uint8_t data_h, uint8_t data_l) @@ -131,23 +199,6 @@ void adb_host_kbd_led(uint8_t led) } -static inline void data_lo() -{ - ADB_DDR |= (1<<ADB_DATA_BIT); - ADB_PORT &= ~(1<<ADB_DATA_BIT); -} -static inline void data_hi() -{ - ADB_PORT |= (1<<ADB_DATA_BIT); - ADB_DDR &= ~(1<<ADB_DATA_BIT); -} -static inline bool data_in() -{ - ADB_PORT |= (1<<ADB_DATA_BIT); - ADB_DDR &= ~(1<<ADB_DATA_BIT); - return ADB_PIN&(1<<ADB_DATA_BIT); -} - #ifdef ADB_PSW_BIT static inline void psw_lo() { @@ -170,7 +221,7 @@ static inline bool psw_in() static inline void attention(void) { data_lo(); - _delay_us(700); + _delay_us(800-35); // bit1 holds lo for 35 more place_bit1(); } @@ -200,81 +251,27 @@ static inline void send_byte(uint8_t data) } } -static inline bool read_bit(void) -{ - // ADB Bit Cells - // - // bit cell time: 70-130us - // low part of bit0: 60-70% of bit cell - // low part of bit1: 30-40% of bit cell - // - // bit cell time 70us 130us - // -------------------------------------------- - // low part of bit0 42-49 78-91 - // high part of bit0 21-28 39-52 - // low part of bit1 21-28 39-52 - // high part of bit1 42-49 78-91 - // - // - // bit0: - // 70us bit cell: - // ____________~~~~~~ - // 42-49 21-28 - // - // 130us bit cell: - // ____________~~~~~~ - // 78-91 39-52 - // - // bit1: - // 70us bit cell: - // ______~~~~~~~~~~~~ - // 21-28 42-49 - // - // 130us bit cell: - // ______~~~~~~~~~~~~ - // 39-52 78-91 - // - // read: - // ________|~~~~~~~~~ - // 55us - // Read data line after 55us. If data line is low/high then bit is 0/1. - // This method might not work at <90us bit cell time. - // - // [from Apple IIgs Hardware Reference Second Edition] - bool bit; - wait_data_lo(75); // wait the start of bit cell at least 130ms(55+0+75) - _delay_us(55); - bit = data_in(); - wait_data_hi(36); // wait high part of bit cell at least 91ms(55+36) - return bit; -} - -static inline uint8_t read_byte(void) -{ - uint8_t data = 0; - for (int i = 0; i < 8; i++) { - data <<= 1; - if (read_bit()) - data = data | 1; - } - return data; -} - -static inline uint8_t wait_data_lo(uint16_t us) +// These are carefully coded to take 6 cycles of overhead. +// inline asm approach became too convoluted +static inline uint16_t wait_data_lo(uint16_t us) { - while (data_in() && us) { - _delay_us(1); - us--; + do { + if ( !data_in() ) + break; + _delay_us(1 - (6 * 1000000.0 / F_CPU)); } + while ( --us ); return us; } -static inline uint8_t wait_data_hi(uint8_t us) +static inline uint16_t wait_data_hi(uint16_t us) { - while (!data_in() && us) { - _delay_us(1); - us--; + do { + if ( data_in() ) + break; + _delay_us(1 - (6 * 1000000.0 / F_CPU)); } + while ( --us ); return us; } diff --git a/protocol/lufa/lufa.c b/protocol/lufa/lufa.c index c1617cd05a..a230d5ba20 100644 --- a/protocol/lufa/lufa.c +++ b/protocol/lufa/lufa.c @@ -531,19 +531,26 @@ static void SetupHardware(void) // for Console_Task USB_Device_EnableSOFEvents(); + print_set_sendchar(sendchar); } int main(void) __attribute__ ((weak)); int main(void) { SetupHardware(); + sei(); +#if defined(INTERRUPT_CONTROL_ENDPOINT) + while (USB_DeviceState != DEVICE_STATE_Configured) ; +#endif + print("USB configured.\n"); + keyboard_init(); host_set_driver(&lufa_driver); #ifdef SLEEP_LED_ENABLE sleep_led_init(); #endif - sei(); + print("Keyboard start.\n"); while (1) { while (USB_DeviceState == DEVICE_STATE_Suspended) { suspend_power_down(); diff --git a/protocol/m0110.c b/protocol/m0110.c index 8bf7cfe4fe..924ec316b8 100644 --- a/protocol/m0110.c +++ b/protocol/m0110.c @@ -91,10 +91,11 @@ uint8_t m0110_error = 0; void m0110_init(void) { - uint8_t data; idle(); _delay_ms(1000); +/* Not needed to initialize in fact. + uint8_t data; m0110_send(M0110_MODEL); data = m0110_recv(); print("m0110_init model: "); phex(data); print("\n"); @@ -102,6 +103,7 @@ void m0110_init(void) m0110_send(M0110_TEST); data = m0110_recv(); print("m0110_init test: "); phex(data); print("\n"); +*/ } uint8_t m0110_send(uint8_t data) @@ -503,29 +505,29 @@ Scan Code m0110_recv_key() function returns following scan codes instead of raw key events. Scan codes are 1 byte long and MSB(bit7) is set when key is released. - M0110 - ,---------------------------------------------------------. - | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| - |---------------------------------------------------------| - |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| - |---------------------------------------------------------| - |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| - |---------------------------------------------------------| - |Shift | Z| X| C| V| B| N| M| ,| ,| /| | - `---------------------------------------------------------' - |Opt|Mac | Space |Enter|Opt| - `------------------------------------------------' - ,---------------------------------------------------------. - | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| - |---------------------------------------------------------| - | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| - |---------------------------------------------------------| - | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| - |---------------------------------------------------------| - | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| - `---------------------------------------------------------' - | 3A| 37| 31 | 34| 3A| - `------------------------------------------------' + M0110 M0120 + ,---------------------------------------------------------. ,---------------. + | `| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =|Backs| |Clr| -|Lft|Rgt| + |---------------------------------------------------------| |---------------| + |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| | 7| 8| 9|Up | + |---------------------------------------------------------| |---------------| + |CapsLo| A| S| D| F| G| H| J| K| L| ;| '|Return| | 4| 5| 6|Dn | + |---------------------------------------------------------| |---------------| + |Shift | Z| X| C| V| B| N| M| ,| ,| /| | | 1| 2| 3| | + `---------------------------------------------------------' |-----------|Ent| + |Opt|Mac | Space |Enter|Opt| | 0| .| | + `------------------------------------------------' `---------------' + ,---------------------------------------------------------. ,---------------. + | 32| 12| 13| 14| 15| 17| 16| 1A| 1C| 19| 1D| 1B| 18| 33| | 47| 4E| 46| 42| + |---------------------------------------------------------| |---------------| + | 30| 0C| 0D| 0E| 0F| 10| 11| 20| 22| 1F| 23| 21| 1E| 2A| | 59| 5B| 5C| 4D| + |---------------------------------------------------------| |---------------| + | 39| 00| 01| 02| 03| 05| 04| 26| 28| 25| 29| 27| 24| | 56| 57| 58| 48| + |---------------------------------------------------------| |---------------| + | 38| 06| 07| 08| 09| 0B| 2D| 2E| 2B| 2F| 2C| 38| | 53| 54| 55| | + `---------------------------------------------------------' |-----------| 4C| + | 3A| 37| 31 | 34| 3A| | 52| 41| | + `------------------------------------------------' `---------------' M0110A ,---------------------------------------------------------. ,---------------. diff --git a/protocol/pjrc/main.c b/protocol/pjrc/main.c index 5f15dbf892..1ef87f8651 100644 --- a/protocol/pjrc/main.c +++ b/protocol/pjrc/main.c @@ -30,6 +30,7 @@ #include "matrix.h" #include "print.h" #include "debug.h" +#include "sendchar.h" #include "util.h" #include "suspend.h" #include "host.h" @@ -50,6 +51,8 @@ int main(void) usb_init(); while (!usb_configured()) /* wait */ ; + print_set_sendchar(sendchar); + keyboard_init(); host_set_driver(pjrc_driver()); #ifdef SLEEP_LED_ENABLE diff --git a/protocol/pjrc/usb.c b/protocol/pjrc/usb.c index 902f9f7f77..84c99972f2 100644 --- a/protocol/pjrc/usb.c +++ b/protocol/pjrc/usb.c @@ -38,6 +38,7 @@ #include "sleep_led.h" #endif #include "suspend.h" +#include "action_util.h" /************************************************************************** |