Added 16u2 Compatibility + New HID Cores

This commit is contained in:
Nico 2014-11-21 18:39:36 +01:00
parent ef26d3b442
commit 23ba2788b4
6 changed files with 1371 additions and 572 deletions

28
CDC.cpp
View file

@ -16,6 +16,29 @@
** SOFTWARE.
*/
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "USBAPI.h"
#include <avr/wdt.h>
@ -50,8 +73,9 @@ const CDCDescriptor _cdcInterface =
// CDC data interface
D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0),
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0)
// edit by NicoHood
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0),
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0)
};
int WEAK CDC_GetInterface(u8* interfaceNum)

690
HID.cpp
View file

@ -1,19 +1,42 @@
/* Copyright (c) 2011, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
/* Copyright (c) 2011, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "USBAPI.h"
@ -21,117 +44,205 @@
#if defined(USBCON)
#ifdef HID_ENABLED
//#define RAWHID_ENABLED
// Singletons for mouse and keyboard
Mouse_ Mouse;
Keyboard_ Keyboard;
//================================================================================
//================================================================================
// HID report descriptor
#define LSB(_x) ((_x) & 0xFF)
#define MSB(_x) ((_x) >> 8)
#define RAWHID_USAGE_PAGE 0xFFC0
#define RAWHID_USAGE 0x0C00
#define RAWHID_TX_SIZE 64
#define RAWHID_RX_SIZE 64
extern const u8 _hidReportDescriptor[] PROGMEM;
const u8 _hidReportDescriptor[] = {
// Mouse
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, 0x01, // REPORT_ID (1)
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x03, // USAGE_MAXIMUM (Button 3)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x03, // REPORT_COUNT (3)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x05, // REPORT_SIZE (5)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x06, // INPUT (Data,Var,Rel)
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
#ifdef HID_MOUSE_ENABLED
// Mouse
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 54
0x09, 0x02, // USAGE (Mouse)
0xa1, 0x01, // COLLECTION (Application)
0x09, 0x01, // USAGE (Pointer)
0xa1, 0x00, // COLLECTION (Physical)
0x85, HID_REPORTID_MouseReport,// REPORT_ID
// 5 buttons
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x05, // USAGE_MAXIMUM (Button 5)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x95, 0x05, // REPORT_COUNT (5)
0x75, 0x01, // REPORT_SIZE (1)
0x81, 0x02, // INPUT (Data,Var,Abs)
// reserved
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x03, // REPORT_SIZE (3)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
// x, y, wheel
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x38, // USAGE (Wheel)
0x15, 0x81, // LOGICAL_MINIMUM (-127)
0x25, 0x7f, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x03, // REPORT_COUNT (3)
0x81, 0x06, // INPUT (Data,Var,Rel)
// end
0xc0, // END_COLLECTION
0xc0, // END_COLLECTION
#endif
// Keyboard
0x05, 0x01, // USAGE_PAGE (Generic Desktop) // 47
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, 0x02, // REPORT_ID (2)
0x05, 0x07, // USAGE_PAGE (Keyboard)
#ifdef HID_KEYBOARD_ENABLED
// Keyboard
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x06, // USAGE (Keyboard)
0xa1, 0x01, // COLLECTION (Application)
0x85, HID_REPORTID_KeyboardReport, // REPORT_ID
0x05, 0x07, // USAGE_PAGE (Keyboard)
// modifiers
0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x08, // REPORT_COUNT (8)
0x81, 0x02, // INPUT (Data,Var,Abs)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
0x81, 0x02, // INPUT (Data,Var,Abs)
// reserved byte
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x03, // INPUT (Cnst,Var,Abs)
// Key[6] Array
0x95, 0x06, // REPORT_COUNT (6)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x75, 0x08, // REPORT_SIZE (8)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x65, // LOGICAL_MAXIMUM (101)
0x05, 0x07, // USAGE_PAGE (Keyboard)
0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
0x81, 0x00, // INPUT (Data,Ary,Abs)
// LEDs for num lock etc
//0x05, 0x08, /* USAGE_PAGE (LEDs) */
//0x19, 0x01, /* USAGE_MINIMUM (Num Lock) */
//0x29, 0x05, /* USAGE_MAXIMUM (Kana) */
//0x95, 0x05, /* REPORT_COUNT (5) */
//0x75, 0x01, /* REPORT_SIZE (1) */
//0x91, 0x02, /* OUTPUT (Data,Var,Abs) */
// Reserved 3 bits
//0x95, 0x01, /* REPORT_COUNT (1) */
//0x75, 0x03, /* REPORT_SIZE (3) */
//0x91, 0x03, /* OUTPUT (Cnst,Var,Abs) */
// end
0xc0, // END_COLLECTION
#endif
#ifdef RAWHID_ENABLED
// RAW HID
#ifdef HID_RAWHID_ENABLED
// RAW HID
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
0xA1, 0x01, // Collection 0x01
0x85, 0x03, // REPORT_ID (3)
0x75, 0x08, // report size = 8 bits
0x15, 0x00, // logical minimum = 0
0x26, 0xFF, 0x00, // logical maximum = 255
0xA1, 0x01, // Collection 0x01
0x85, HID_REPORTID_RawKeyboardReport, // REPORT_ID
0x75, 0x08, // report size = 8 bits
0x15, 0x00, // logical minimum = 0
0x26, 0xFF, 0x00, // logical maximum = 255
0x95, 64, // report count TX
0x09, 0x01, // usage
0x81, 0x02, // Input (array)
0x95, RAWHID_TX_SIZE, // report count TX
0x09, 0x01, // usage
0x81, 0x02, // Input (array)
0x95, 64, // report count RX
0x09, 0x02, // usage
0x91, 0x02, // Output (array)
0xC0 // end collection
0x95, RAWHID_RX_SIZE, // report count RX
0x09, 0x02, // usage
0x91, 0x02, // Output (array)
0xC0, // end collection
#endif
#ifdef HID_MEDIA_ENABLED
// Media
0x05, 0x0C, // usage page (consumer device)
0x09, 0x01, // usage -- consumer control
0xA1, 0x01, // collection (application)
0x85, HID_REPORTID_MediaReport, // report id
//0x05, 0x0C, // usage page (consumer)
// 4 media Keys
0x15, 0x00, //logical minimum
0x26, 0xFF, 0x03, //logical maximum (3ff)
0x19, 0x00, // usage minimum (0)
0x2A, 0xFF, 0x03, //usage maximum (3ff)
0x95, 0x04, //report count (4)
0x75, 0x10, //report size (16)
0x81, 0x00, //input
0xC0, //end collection
#endif
#ifdef HID_SYSTEM_ENABLED
// System
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x80, // USAGE (System Control)
0xa1, 0x01, // COLLECTION (Application)
0x85, HID_REPORTID_SystemReport, // REPORT_ID
// 1 system key
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x26, 0xff, 0x00, // LOGICAL_MAXIMUM (255)
0x19, 0x00, // USAGE_MINIMUM (Undefined)
0x29, 0xff, // USAGE_MAXIMUM (System Menu Down)
0x95, 0x01, // REPORT_COUNT (1)
0x75, 0x08, // REPORT_SIZE (8)
0x81, 0x00, // INPUT (Data,Ary,Abs)
0xc0, // END_COLLECTION
#endif
#ifdef HID_GAMEPAD_ENABLED
// Gamepad
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x04, // USAGE (Joystick)
0xa1, 0x01, // COLLECTION (Application)
0x85, HID_REPORTID_GamepadReport, // REPORT_ID
// 32 Buttons
0x05, 0x09, // USAGE_PAGE (Button)
0x19, 0x01, // USAGE_MINIMUM (Button 1)
0x29, 0x20, // USAGE_MAXIMUM (Button 32)
0x15, 0x00, // LOGICAL_MINIMUM (0)
0x25, 0x01, // LOGICAL_MAXIMUM (1)
0x75, 0x01, // REPORT_SIZE (1)
0x95, 0x20, // REPORT_COUNT (32)
0x81, 0x02, // INPUT (Data,Var,Abs)
// 4 16bit Axis
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0xa1, 0x00, // COLLECTION (Physical)
0x09, 0x30, // USAGE (X)
0x09, 0x31, // USAGE (Y)
0x09, 0x33, // USAGE (Rx)
0x09, 0x34, // USAGE (Ry)
0x16, 0x00, 0x80, // LOGICAL_MINIMUM (-32768)
0x26, 0xFF, 0x7F, // LOGICAL_MAXIMUM (32767)
0x75, 0x10, // REPORT_SIZE (16)
0x95, 0x04, // REPORT_COUNT (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
// 2 8bit Axis
0x09, 0x32, // USAGE (Z)
0x09, 0x35, // USAGE (Rz)
0x15, 0x80, // LOGICAL_MINIMUM (-128)
0x25, 0x7F, // LOGICAL_MAXIMUM (127)
0x75, 0x08, // REPORT_SIZE (8)
0x95, 0x02, // REPORT_COUNT (2)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
// 2 Hat Switches
0x05, 0x01, // USAGE_PAGE (Generic Desktop)
0x09, 0x39, // USAGE (Hat switch)
0x09, 0x39, // USAGE (Hat switch)
0x15, 0x01, // LOGICAL_MINIMUM (1)
0x25, 0x08, // LOGICAL_MAXIMUM (8)
0x95, 0x02, // REPORT_COUNT (2)
0x75, 0x04, // REPORT_SIZE (4)
0x81, 0x02, // INPUT (Data,Var,Abs)
0xc0, // END_COLLECTION
#endif
};
extern const HIDDescriptor _hidInterface PROGMEM;
const HIDDescriptor _hidInterface =
{
D_INTERFACE(HID_INTERFACE,1,3,0,0),
D_INTERFACE(HID_INTERFACE, 1, 3, 0, 0),
D_HIDREPORT(sizeof(_hidReportDescriptor)),
D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x01)
// edit by NicoHood
D_ENDPOINT(USB_ENDPOINT_IN(HID_ENDPOINT_INT), USB_ENDPOINT_TYPE_INTERRUPT, USB_EP_SIZE, 0x01)
};
//================================================================================
@ -146,18 +257,18 @@ u8 _hid_idle = 1;
int WEAK HID_GetInterface(u8* interfaceNum)
{
interfaceNum[0] += 1; // uses 1
return USB_SendControl(TRANSFER_PGM,&_hidInterface,sizeof(_hidInterface));
return USB_SendControl(TRANSFER_PGM, &_hidInterface, sizeof(_hidInterface));
}
int WEAK HID_GetDescriptor(int /* i */)
{
return USB_SendControl(TRANSFER_PGM,_hidReportDescriptor,sizeof(_hidReportDescriptor));
return USB_SendControl(TRANSFER_PGM, _hidReportDescriptor, sizeof(_hidReportDescriptor));
}
void WEAK HID_SendReport(u8 id, const void* data, int len)
{
USB_Send(HID_TX, &id, 1);
USB_Send(HID_TX | TRANSFER_RELEASE,data,len);
USB_Send(HID_TX | TRANSFER_RELEASE, data, len);
}
bool WEAK HID_Setup(Setup& setup)
@ -177,7 +288,7 @@ bool WEAK HID_Setup(Setup& setup)
return true;
}
}
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
{
if (HID_SET_PROTOCOL == r)
@ -195,324 +306,77 @@ bool WEAK HID_Setup(Setup& setup)
return false;
}
//================================================================================
//================================================================================
// Mouse
#endif
Mouse_::Mouse_(void) : _buttons(0)
#else if defined(USE_USB_API)
// still provide the weak HID_SendReport function to be able to overwrite it externaly
void __attribute__((weak)) HID_SendReport(uint8_t id, const void* data, int len)
{
// the user has to overwrite this if no USB Core is used
}
void Mouse_::begin(void)
{
}
#endif /* if defined(USBCON) */
void Mouse_::end(void)
{
}
void Mouse_::click(uint8_t b)
{
_buttons = b;
move(0,0,0);
_buttons = 0;
move(0,0,0);
}
void Mouse_::move(signed char x, signed char y, signed char wheel)
{
u8 m[4];
m[0] = _buttons;
m[1] = x;
m[2] = y;
m[3] = wheel;
HID_SendReport(1,m,4);
}
void Mouse_::buttons(uint8_t b)
{
if (b != _buttons)
{
_buttons = b;
move(0,0,0);
}
}
void Mouse_::press(uint8_t b)
{
buttons(_buttons | b);
}
void Mouse_::release(uint8_t b)
{
buttons(_buttons & ~b);
}
bool Mouse_::isPressed(uint8_t b)
{
if ((b & _buttons) > 0)
return true;
return false;
}
// HID API libs are only included if the device has USB functionality or if the USE_USB_API is needed
#if defined(USBCON) || defined(USE_USB_API)
//================================================================================
// Mouse
//================================================================================
// Keyboard
Keyboard_::Keyboard_(void)
{
}
#ifdef HID_MOUSE_ENABLED
void Keyboard_::begin(void)
{
}
void Keyboard_::end(void)
{
}
void Keyboard_::sendReport(KeyReport* keys)
{
HID_SendReport(2,keys,sizeof(KeyReport));
}
extern
const uint8_t _asciimap[128] PROGMEM;
#define SHIFT 0x80
const uint8_t _asciimap[128] =
{
0x00, // NUL
0x00, // SOH
0x00, // STX
0x00, // ETX
0x00, // EOT
0x00, // ENQ
0x00, // ACK
0x00, // BEL
0x2a, // BS Backspace
0x2b, // TAB Tab
0x28, // LF Enter
0x00, // VT
0x00, // FF
0x00, // CR
0x00, // SO
0x00, // SI
0x00, // DEL
0x00, // DC1
0x00, // DC2
0x00, // DC3
0x00, // DC4
0x00, // NAK
0x00, // SYN
0x00, // ETB
0x00, // CAN
0x00, // EM
0x00, // SUB
0x00, // ESC
0x00, // FS
0x00, // GS
0x00, // RS
0x00, // US
0x2c, // ' '
0x1e|SHIFT, // !
0x34|SHIFT, // "
0x20|SHIFT, // #
0x21|SHIFT, // $
0x22|SHIFT, // %
0x24|SHIFT, // &
0x34, // '
0x26|SHIFT, // (
0x27|SHIFT, // )
0x25|SHIFT, // *
0x2e|SHIFT, // +
0x36, // ,
0x2d, // -
0x37, // .
0x38, // /
0x27, // 0
0x1e, // 1
0x1f, // 2
0x20, // 3
0x21, // 4
0x22, // 5
0x23, // 6
0x24, // 7
0x25, // 8
0x26, // 9
0x33|SHIFT, // :
0x33, // ;
0x36|SHIFT, // <
0x2e, // =
0x37|SHIFT, // >
0x38|SHIFT, // ?
0x1f|SHIFT, // @
0x04|SHIFT, // A
0x05|SHIFT, // B
0x06|SHIFT, // C
0x07|SHIFT, // D
0x08|SHIFT, // E
0x09|SHIFT, // F
0x0a|SHIFT, // G
0x0b|SHIFT, // H
0x0c|SHIFT, // I
0x0d|SHIFT, // J
0x0e|SHIFT, // K
0x0f|SHIFT, // L
0x10|SHIFT, // M
0x11|SHIFT, // N
0x12|SHIFT, // O
0x13|SHIFT, // P
0x14|SHIFT, // Q
0x15|SHIFT, // R
0x16|SHIFT, // S
0x17|SHIFT, // T
0x18|SHIFT, // U
0x19|SHIFT, // V
0x1a|SHIFT, // W
0x1b|SHIFT, // X
0x1c|SHIFT, // Y
0x1d|SHIFT, // Z
0x2f, // [
0x31, // bslash
0x30, // ]
0x23|SHIFT, // ^
0x2d|SHIFT, // _
0x35, // `
0x04, // a
0x05, // b
0x06, // c
0x07, // d
0x08, // e
0x09, // f
0x0a, // g
0x0b, // h
0x0c, // i
0x0d, // j
0x0e, // k
0x0f, // l
0x10, // m
0x11, // n
0x12, // o
0x13, // p
0x14, // q
0x15, // r
0x16, // s
0x17, // t
0x18, // u
0x19, // v
0x1a, // w
0x1b, // x
0x1c, // y
0x1d, // z
0x2f|SHIFT, //
0x31|SHIFT, // |
0x30|SHIFT, // }
0x35|SHIFT, // ~
0 // DEL
};
uint8_t USBPutChar(uint8_t c);
// press() adds the specified key (printing, non-printing, or modifier)
// to the persistent key report and sends the report. Because of the way
// USB HID works, the host acts like the key remains pressed until we
// call release(), releaseAll(), or otherwise clear the report and resend.
size_t Keyboard_::press(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers |= (1<<(k-128));
k = 0;
} else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
setWriteError();
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers |= 0x02; // the left shift modifier
k &= 0x7F;
}
}
// Add k to the key report only if it's not already present
// and if there is an empty slot.
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
for (i=0; i<6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
setWriteError();
return 0;
}
}
sendReport(&_keyReport);
return 1;
}
// release() takes the specified key out of the persistent key report and
// sends the report. This tells the OS the key is no longer pressed and that
// it shouldn't be repeated any more.
size_t Keyboard_::release(uint8_t k)
{
uint8_t i;
if (k >= 136) { // it's a non-printing key (not a modifier)
k = k - 136;
} else if (k >= 128) { // it's a modifier key
_keyReport.modifiers &= ~(1<<(k-128));
k = 0;
} else { // it's a printing key
k = pgm_read_byte(_asciimap + k);
if (!k) {
return 0;
}
if (k & 0x80) { // it's a capital letter or other character reached with shift
_keyReport.modifiers &= ~(0x02); // the left shift modifier
k &= 0x7F;
}
}
// Test the key report to see if k is present. Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i=0; i<6; i++) {
if (0 != k && _keyReport.keys[i] == k) {
_keyReport.keys[i] = 0x00;
}
}
sendReport(&_keyReport);
return 1;
}
void Keyboard_::releaseAll(void)
{
_keyReport.keys[0] = 0;
_keyReport.keys[1] = 0;
_keyReport.keys[2] = 0;
_keyReport.keys[3] = 0;
_keyReport.keys[4] = 0;
_keyReport.keys[5] = 0;
_keyReport.modifiers = 0;
sendReport(&_keyReport);
}
size_t Keyboard_::write(uint8_t c)
{
uint8_t p = press(c); // Keydown
release(c); // Keyup
return p; // just return the result of press() since release() almost always returns 1
}
// object instance
Mouse_ Mouse;
#endif
#endif /* if defined(USBCON) */
//================================================================================
// Keyboard
//================================================================================
#ifdef HID_KEYBOARD_ENABLED
// object instance
Keyboard_ Keyboard;
#endif
//================================================================================
// Media
//================================================================================
#ifdef HID_MEDIA_ENABLED
// object instance
Media_ Media;
#endif
//================================================================================
// System
//================================================================================
#ifdef HID_SYSTEAM_ENABLED
// object instance
System_ System;
#endif
//================================================================================
// Gamepad
//================================================================================
#ifdef HID_GAMEPAD_ENABLED
// object instance
Gamepad_ Gamepad;
#endif
#endif // if defined(USBCON) || defined(USE_USB_API)

975
USBAPI.h

File diff suppressed because it is too large Load diff

View file

@ -1,19 +1,42 @@
/* Copyright (c) 2010, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
/* Copyright (c) 2010, Peter Barrett
**
** Permission to use, copy, modify, and/or distribute this software for
** any purpose with or without fee is hereby granted, provided that the
** above copyright notice and this permission notice appear in all copies.
**
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
** SOFTWARE.
*/
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include "USBAPI.h"
@ -43,7 +66,7 @@ extern const DeviceDescriptor USB_DeviceDescriptor PROGMEM;
extern const DeviceDescriptor USB_DeviceDescriptorA PROGMEM;
const u16 STRING_LANGUAGE[2] = {
(3<<8) | (2+2),
(3 << 8) | (2 + 2),
0x0409 // English
};
@ -78,12 +101,13 @@ const u8 STRING_MANUFACTURER[] PROGMEM = USB_MANUFACTURER;
#define DEVICE_CLASS 0x00
#endif
//TODO warning from USBlyzer with a 16u2
// DEVICE DESCRIPTOR
const DeviceDescriptor USB_DeviceDescriptor =
D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
D_DEVICE(0x00, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1);
const DeviceDescriptor USB_DeviceDescriptorA =
D_DEVICE(DEVICE_CLASS,0x00,0x00,64,USB_VID,USB_PID,0x100,IMANUFACTURER,IPRODUCT,0,1);
D_DEVICE(DEVICE_CLASS, 0x00, 0x00, 64, USB_VID, USB_PID, 0x100, IMANUFACTURER, IPRODUCT, 0, 1);
//==================================================================
//==================================================================
@ -92,40 +116,40 @@ volatile u8 _usbConfiguration = 0;
static inline void WaitIN(void)
{
while (!(UEINTX & (1<<TXINI)))
while (!(UEINTX & (1 << TXINI)))
;
}
static inline void ClearIN(void)
{
UEINTX = ~(1<<TXINI);
UEINTX = ~(1 << TXINI);
}
static inline void WaitOUT(void)
{
while (!(UEINTX & (1<<RXOUTI)))
while (!(UEINTX & (1 << RXOUTI)))
;
}
static inline u8 WaitForINOrOUT()
{
while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
while (!(UEINTX & ((1 << TXINI) | (1 << RXOUTI))))
;
return (UEINTX & (1<<RXOUTI)) == 0;
return (UEINTX & (1 << RXOUTI)) == 0;
}
static inline void ClearOUT(void)
{
UEINTX = ~(1<<RXOUTI);
UEINTX = ~(1 << RXOUTI);
}
void Recv(volatile u8* data, u8 count)
{
while (count--)
*data++ = UEDATX;
RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;
RxLEDPulse = TX_RX_LED_PULSE_MS;
}
static inline u8 Recv8()
@ -133,7 +157,7 @@ static inline u8 Recv8()
RXLED1; // light the RX LED
RxLEDPulse = TX_RX_LED_PULSE_MS;
return UEDATX;
return UEDATX;
}
static inline void Send8(u8 d)
@ -153,32 +177,32 @@ static inline u8 FifoByteCount()
static inline u8 ReceivedSetupInt()
{
return UEINTX & (1<<RXSTPI);
return UEINTX & (1 << RXSTPI);
}
static inline void ClearSetupInt()
{
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
UEINTX = ~((1 << RXSTPI) | (1 << RXOUTI) | (1 << TXINI));
}
static inline void Stall()
{
UECONX = (1<<STALLRQ) | (1<<EPEN);
UECONX = (1 << STALLRQ) | (1 << EPEN);
}
static inline u8 ReadWriteAllowed()
{
return UEINTX & (1<<RWAL);
return UEINTX & (1 << RWAL);
}
static inline u8 Stalled()
{
return UEINTX & (1<<STALLEDI);
return UEINTX & (1 << STALLEDI);
}
static inline u8 FifoFree()
{
return UEINTX & (1<<FIFOCON);
return UEINTX & (1 << FIFOCON);
}
static inline void ReleaseRX()
@ -233,17 +257,17 @@ int USB_Recv(u8 ep, void* d, int len)
{
if (!_usbConfiguration || len < 0)
return -1;
LockEP lock(ep);
u8 n = FifoByteCount();
len = min(n,len);
len = min(n, len);
n = len;
u8* dst = (u8*)d;
while (n--)
*dst++ = Recv8();
if (len && !FifoByteCount()) // release empty buffer
ReleaseRX();
return len;
}
@ -251,7 +275,7 @@ int USB_Recv(u8 ep, void* d, int len)
int USB_Recv(u8 ep)
{
u8 c;
if (USB_Recv(ep,&c,1) != 1)
if (USB_Recv(ep, &c, 1) != 1)
return -1;
return c;
}
@ -262,7 +286,8 @@ u8 USB_SendSpace(u8 ep)
LockEP lock(ep);
if (!ReadWriteAllowed())
return 0;
return 64 - FifoByteCount();
// edit by NicoHood
return USB_EP_SIZE - FifoByteCount();
}
// Blocking Send of data to an endpoint
@ -318,10 +343,10 @@ int USB_Send(u8 ep, const void* d, int len)
}
extern const u8 _initEndpoints[] PROGMEM;
const u8 _initEndpoints[] =
const u8 _initEndpoints[] =
{
0,
#ifdef CDC_ENABLED
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
@ -335,6 +360,8 @@ const u8 _initEndpoints[] =
#define EP_SINGLE_64 0x32 // EP0
#define EP_DOUBLE_64 0x36 // Other endpoints
// edit by NicoHood
#define EP_SINGLE_16 0x12
static
void InitEP(u8 index, u8 type, u8 size)
@ -352,8 +379,15 @@ void InitEndpoints()
{
UENUM = i;
UECONX = 1;
UECFG0X = pgm_read_byte(_initEndpoints+i);
UECFG0X = pgm_read_byte(_initEndpoints + i);
// edit by NicoHood
#if USB_EP_SIZE == 16
UECFG1X = EP_SINGLE_16;
#elif USB_EP_SIZE == 64
UECFG1X = EP_DOUBLE_64;
#else
#error Unsupported value for USB_EP_SIZE
#endif
}
UERST = 0x7E; // And reset them
UERST = 0;
@ -420,16 +454,16 @@ int USB_SendControl(u8 flags, const void* d, int len)
// plain ASCII string but is sent out as UTF-16 with the correct 2-byte
// prefix
static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) {
SendControl(2 + string_len * 2);
SendControl(3);
for(u8 i = 0; i < string_len; i++) {
bool r = SendControl(pgm_read_byte(&string_P[i]));
r &= SendControl(0); // high byte
if(!r) {
return false;
}
}
return true;
SendControl(2 + string_len * 2);
SendControl(3);
for (u8 i = 0; i < string_len; i++) {
bool r = SendControl(pgm_read_byte(&string_P[i]));
r &= SendControl(0); // high byte
if (!r) {
return false;
}
}
return true;
}
// Does not timeout or cross fifo boundaries
@ -438,7 +472,7 @@ static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len) {
int USB_RecvControl(void* d, int len)
{
WaitOUT();
Recv((u8*)d,len);
Recv((u8*)d, len);
ClearOUT();
return len;
}
@ -466,13 +500,13 @@ static
bool SendConfiguration(int maxlen)
{
// Count and measure interfaces
InitControl(0);
InitControl(0);
int interfaces = SendInterfaces();
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor), interfaces);
// Now send them
InitControl(maxlen);
USB_SendControl(0,&config,sizeof(ConfigDescriptor));
USB_SendControl(0, &config, sizeof(ConfigDescriptor));
SendInterfaces();
return true;
}
@ -497,7 +531,7 @@ bool SendDescriptor(Setup& setup)
{
if (setup.wLength == 8)
_cdcComposite = 1;
desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor;
desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor;
}
else if (USB_STRING_DESCRIPTOR_TYPE == t)
{
@ -518,19 +552,19 @@ bool SendDescriptor(Setup& setup)
return false;
u8 desc_length = pgm_read_byte(desc_addr);
USB_SendControl(TRANSFER_PGM,desc_addr,desc_length);
USB_SendControl(TRANSFER_PGM, desc_addr, desc_length);
return true;
}
// Endpoint 0 interrupt
ISR(USB_COM_vect)
{
SetEP(0);
SetEP(0);
if (!ReceivedSetupInt())
return;
Setup setup;
Recv((u8*)&setup,8);
Recv((u8*)&setup, 8);
ClearSetupInt();
u8 requestType = setup.bmRequestType;
@ -539,7 +573,7 @@ ISR(USB_COM_vect)
else
ClearIN();
bool ok = true;
bool ok = true;
if (REQUEST_STANDARD == (requestType & REQUEST_TYPE))
{
// Standard Requests
@ -558,7 +592,7 @@ ISR(USB_COM_vect)
else if (SET_ADDRESS == r)
{
WaitIN();
UDADDR = setup.wValueL | (1<<ADDEN);
UDADDR = setup.wValueL | (1 << ADDEN);
}
else if (GET_DESCRIPTOR == r)
{
@ -578,7 +612,8 @@ ISR(USB_COM_vect)
{
InitEndpoints();
_usbConfiguration = setup.wValueL;
} else
}
else
ok = false;
}
else if (GET_INTERFACE == r)
@ -616,20 +651,20 @@ ISR(USB_GEN_vect)
UDINT = 0;
// End of Reset
if (udint & (1<<EORSTI))
if (udint & (1 << EORSTI))
{
InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // init ep0
InitEP(0, EP_TYPE_CONTROL, EP_SINGLE_64); // init ep0
_usbConfiguration = 0; // not configured yet
UEIENX = 1 << RXSTPE; // Enable interrupts for ep0
}
// Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
if (udint & (1<<SOFI))
if (udint & (1 << SOFI))
{
#ifdef CDC_ENABLED
USB_Flush(CDC_TX); // Send a tx frame if found
#endif
// check whether the one-shot period has elapsed. if so, turn off the LED
if (TxLEDPulse && !(--TxLEDPulse))
TXLED0;
@ -656,17 +691,55 @@ USBDevice_::USBDevice_()
{
}
// edit by NicoHood
// added from teensy definition by paul stoffregen
#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__)
#define HW_CONFIG()
#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
#define USB_CONFIG() (USBCON = (1<<USBE))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_ATmega32U4__)
#define HW_CONFIG() (UHWCON = 0x01)
#define PLL_CONFIG() (PLLCSR = 0x12)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_AT90USB646__)
#define HW_CONFIG() (UHWCON = 0x81)
#define PLL_CONFIG() (PLLCSR = 0x1A)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#elif defined(__AVR_AT90USB1286__)
#define HW_CONFIG() (UHWCON = 0x81)
#define PLL_CONFIG() (PLLCSR = 0x16)
#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
#endif
void USBDevice_::attach()
{
// edit by NicoHood
_usbConfiguration = 0;
UHWCON = 0x01; // power internal reg
USBCON = (1<<USBE)|(1<<FRZCLK); // clock frozen, usb enabled
HW_CONFIG(); // power internal reg
// from Paul, TODO needed?
//USBCON = 0; // Reset controller
USB_FREEZE(); // clock frozen, usb enabled
#if F_CPU == 16000000UL
PLLCSR = 0x12; // Need 16 MHz xtal
// Need 16 MHz xtal
#ifdef PINDIV
PLLCSR = (1 << PINDIV) | (1 << PLLE);
#else
// added from paul, no idea for what board this is used for
PLLCSR = (1 << PLLP0) | (1 << PLLE);
#endif
#elif F_CPU == 8000000UL
PLLCSR = 0x02; // Need 8 MHz xtal
// Need 8 MHz xtal
PLLCSR = (1 << PLLE);
#endif
while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
while (!(PLLCSR & (1 << PLOCK))) // wait for lock pll
;
// Some tests on specific versions of macosx (10.7.3), reported some
@ -674,10 +747,10 @@ void USBDevice_::attach()
// port touch at 1200 bps. This delay fixes this behaviour.
delay(1);
USBCON = ((1<<USBE)|(1<<OTGPADE)); // start USB clock
UDIEN = (1<<EORSTE)|(1<<SOFE); // Enable interrupts for EOR (End of Reset) and SOF (start of frame)
USB_CONFIG(); // start USB clock
UDIEN = (1 << EORSTE) | (1 << SOFE); // Enable interrupts for EOR (End of Reset) and SOF (start of frame)
UDCON = 0; // enable attach resistor
TX_RX_LED_INIT;
}

View file

@ -16,6 +16,29 @@
** SOFTWARE.
*/
/*
Copyright (c) 2014 NicoHood
See the readme for credit to other people.
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#define CDC_ENABLED
#define HID_ENABLED
@ -58,6 +81,10 @@
#define HID_TX HID_ENDPOINT_INT
#endif
// edit by NicoHood
#ifndef USB_EP_SIZE
#define USB_EP_SIZE 64
#endif
#define IMANUFACTURER 1
#define IPRODUCT 2

View file

@ -52,7 +52,9 @@ extern "C"{
#define EXTERNAL_INT_6 6
#define EXTERNAL_INT_7 7
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__)
// edit by NicoHood
#if defined(__AVR_AT90USB82__) || defined(__AVR_AT90USB162__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega8U2__) \
|| defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) || defined(__AVR_ATmega128RFA1__) || defined(__AVR_ATmega256RFR2__)
#define EXTERNAL_NUM_INTERRUPTS 8
#elif defined(__AVR_ATmega1284__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega644__) || defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__)
#define EXTERNAL_NUM_INTERRUPTS 3