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"  /************************************************************************** | 
