mirror of
https://github.com/mcgurk/Arduino-USB-HID-RetroJoystickAdapter
synced 2024-11-30 21:02:19 -05:00
3344 lines
107 KiB
Plaintext
3344 lines
107 KiB
Plaintext
|
|
C:\Users\lehti\AppData\Local\Temp\arduino_build_972304\c64_4joystick-adapter.ino.elf: file format elf32-avr
|
|
|
|
|
|
Disassembly of section .text:
|
|
|
|
00000000 <__vectors>:
|
|
0: 0c 94 bf 00 jmp 0x17e ; 0x17e <__ctors_end>
|
|
4: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
8: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
c: 0c 94 70 06 jmp 0xce0 ; 0xce0 <__vector_3>
|
|
10: 0c 94 5d 06 jmp 0xcba ; 0xcba <__vector_4>
|
|
14: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
18: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
1c: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
20: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
24: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
28: 0c 94 64 03 jmp 0x6c8 ; 0x6c8 <__vector_10>
|
|
2c: 0c 94 d3 03 jmp 0x7a6 ; 0x7a6 <__vector_11>
|
|
30: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
34: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
38: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
3c: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
40: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
44: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
48: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
4c: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
50: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
54: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
58: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
5c: 0c 94 05 06 jmp 0xc0a ; 0xc0a <__vector_23>
|
|
60: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
64: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
68: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
6c: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
70: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
74: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
78: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
7c: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
80: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
84: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
88: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
8c: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
90: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
94: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
98: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
9c: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
a0: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
a4: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
a8: 0c 94 e7 00 jmp 0x1ce ; 0x1ce <__bad_interrupt>
|
|
|
|
000000ac <__trampolines_end>:
|
|
ac: 08 0b sbc r16, r24
|
|
ae: 00 02 muls r16, r16
|
|
b0: 02 02 muls r16, r18
|
|
b2: 00 00 nop
|
|
b4: 09 04 cpc r0, r9
|
|
b6: 00 00 nop
|
|
b8: 01 02 muls r16, r17
|
|
ba: 02 00 .word 0x0002 ; ????
|
|
bc: 00 05 cpc r16, r0
|
|
be: 24 00 .word 0x0024 ; ????
|
|
c0: 10 01 movw r2, r0
|
|
c2: 05 24 eor r0, r5
|
|
c4: 01 01 movw r0, r2
|
|
c6: 01 04 cpc r0, r1
|
|
c8: 24 02 muls r18, r20
|
|
ca: 06 05 cpc r16, r6
|
|
cc: 24 06 cpc r2, r20
|
|
ce: 00 01 movw r0, r0
|
|
d0: 07 05 cpc r16, r7
|
|
d2: 81 03 fmuls r16, r17
|
|
d4: 10 00 .word 0x0010 ; ????
|
|
d6: 40 09 sbc r20, r0
|
|
d8: 04 01 movw r0, r8
|
|
da: 00 02 muls r16, r16
|
|
dc: 0a 00 .word 0x000a ; ????
|
|
de: 00 00 nop
|
|
e0: 07 05 cpc r16, r7
|
|
e2: 02 02 muls r16, r18
|
|
e4: 40 00 .word 0x0040 ; ????
|
|
e6: 00 07 cpc r16, r16
|
|
e8: 05 83 std Z+5, r16 ; 0x05
|
|
ea: 02 40 sbci r16, 0x02 ; 2
|
|
...
|
|
|
|
000000ee <STRING_LANGUAGE>:
|
|
ee: 04 03 09 04 ....
|
|
|
|
000000f2 <USB_DeviceDescriptorIAD>:
|
|
f2: 12 01 00 02 ef 02 01 40 41 23 36 80 00 01 01 02 .......@A#6.....
|
|
102: 03 01 ..
|
|
|
|
00000104 <STRING_MANUFACTURER>:
|
|
104: 41 72 64 75 69 6e 6f 20 4c 4c 43 00 Arduino LLC.
|
|
|
|
00000110 <STRING_PRODUCT>:
|
|
110: 41 72 64 75 69 6e 6f 20 4c 65 6f 6e 61 72 64 6f Arduino Leonardo
|
|
...
|
|
|
|
00000121 <port_to_output_PGM>:
|
|
121: 00 00 00 00 25 00 28 00 2b 00 2e 00 31 00 ....%.(.+...1.
|
|
|
|
0000012f <port_to_mode_PGM>:
|
|
12f: 00 00 00 00 24 00 27 00 2a 00 2d 00 30 00 ....$.'.*.-.0.
|
|
|
|
0000013d <digital_pin_to_port_PGM>:
|
|
13d: 04 04 04 04 04 03 04 05 02 02 02 02 04 03 02 02 ................
|
|
14d: 02 02 06 06 06 06 06 06 04 04 02 02 02 04 04 ...............
|
|
|
|
0000015c <digital_pin_to_bit_mask_PGM>:
|
|
15c: 04 08 02 01 10 40 80 40 10 20 40 80 40 80 08 02 .....@.@. @.@...
|
|
16c: 04 01 80 40 20 10 02 01 10 80 10 20 40 40 20 00 ...@ ...... @@ .
|
|
|
|
0000017c <__ctors_start>:
|
|
17c: 75 06 cpc r7, r21
|
|
|
|
0000017e <__ctors_end>:
|
|
17e: 11 24 eor r1, r1
|
|
180: 1f be out 0x3f, r1 ; 63
|
|
182: cf ef ldi r28, 0xFF ; 255
|
|
184: da e0 ldi r29, 0x0A ; 10
|
|
186: de bf out 0x3e, r29 ; 62
|
|
188: cd bf out 0x3d, r28 ; 61
|
|
|
|
0000018a <__do_copy_data>:
|
|
18a: 11 e0 ldi r17, 0x01 ; 1
|
|
18c: a0 e0 ldi r26, 0x00 ; 0
|
|
18e: b1 e0 ldi r27, 0x01 ; 1
|
|
190: e6 e0 ldi r30, 0x06 ; 6
|
|
192: ff e0 ldi r31, 0x0F ; 15
|
|
194: 02 c0 rjmp .+4 ; 0x19a <__do_copy_data+0x10>
|
|
196: 05 90 lpm r0, Z+
|
|
198: 0d 92 st X+, r0
|
|
19a: a6 32 cpi r26, 0x26 ; 38
|
|
19c: b1 07 cpc r27, r17
|
|
19e: d9 f7 brne .-10 ; 0x196 <__do_copy_data+0xc>
|
|
|
|
000001a0 <__do_clear_bss>:
|
|
1a0: 21 e0 ldi r18, 0x01 ; 1
|
|
1a2: a6 e2 ldi r26, 0x26 ; 38
|
|
1a4: b1 e0 ldi r27, 0x01 ; 1
|
|
1a6: 01 c0 rjmp .+2 ; 0x1aa <.do_clear_bss_start>
|
|
|
|
000001a8 <.do_clear_bss_loop>:
|
|
1a8: 1d 92 st X+, r1
|
|
|
|
000001aa <.do_clear_bss_start>:
|
|
1aa: a5 39 cpi r26, 0x95 ; 149
|
|
1ac: b2 07 cpc r27, r18
|
|
1ae: e1 f7 brne .-8 ; 0x1a8 <.do_clear_bss_loop>
|
|
|
|
000001b0 <__do_global_ctors>:
|
|
1b0: 10 e0 ldi r17, 0x00 ; 0
|
|
1b2: cf eb ldi r28, 0xBF ; 191
|
|
1b4: d0 e0 ldi r29, 0x00 ; 0
|
|
1b6: 04 c0 rjmp .+8 ; 0x1c0 <__do_global_ctors+0x10>
|
|
1b8: 21 97 sbiw r28, 0x01 ; 1
|
|
1ba: fe 01 movw r30, r28
|
|
1bc: 0e 94 7b 07 call 0xef6 ; 0xef6 <__tablejump2__>
|
|
1c0: ce 3b cpi r28, 0xBE ; 190
|
|
1c2: d1 07 cpc r29, r17
|
|
1c4: c9 f7 brne .-14 ; 0x1b8 <__do_global_ctors+0x8>
|
|
1c6: 0e 94 8a 06 call 0xd14 ; 0xd14 <main>
|
|
1ca: 0c 94 81 07 jmp 0xf02 ; 0xf02 <_exit>
|
|
|
|
000001ce <__bad_interrupt>:
|
|
1ce: 0c 94 00 00 jmp 0 ; 0x0 <__vectors>
|
|
|
|
000001d2 <pinMode.constprop.11>:
|
|
|
|
#define ARDUINO_MAIN
|
|
#include "wiring_private.h"
|
|
#include "pins_arduino.h"
|
|
|
|
void pinMode(uint8_t pin, uint8_t mode)
|
|
1d2: cf 93 push r28
|
|
1d4: df 93 push r29
|
|
{
|
|
uint8_t bit = digitalPinToBitMask(pin);
|
|
1d6: 90 e0 ldi r25, 0x00 ; 0
|
|
1d8: fc 01 movw r30, r24
|
|
1da: e4 5a subi r30, 0xA4 ; 164
|
|
1dc: fe 4f sbci r31, 0xFE ; 254
|
|
1de: 24 91 lpm r18, Z
|
|
uint8_t port = digitalPinToPort(pin);
|
|
1e0: 83 5c subi r24, 0xC3 ; 195
|
|
1e2: 9e 4f sbci r25, 0xFE ; 254
|
|
1e4: fc 01 movw r30, r24
|
|
1e6: 84 91 lpm r24, Z
|
|
volatile uint8_t *reg, *out;
|
|
|
|
if (port == NOT_A_PIN) return;
|
|
1e8: 88 23 and r24, r24
|
|
1ea: c1 f0 breq .+48 ; 0x21c <pinMode.constprop.11+0x4a>
|
|
|
|
// JWS: can I let the optimizer do this?
|
|
reg = portModeRegister(port);
|
|
1ec: 90 e0 ldi r25, 0x00 ; 0
|
|
1ee: 88 0f add r24, r24
|
|
1f0: 99 1f adc r25, r25
|
|
1f2: fc 01 movw r30, r24
|
|
1f4: e1 5d subi r30, 0xD1 ; 209
|
|
1f6: fe 4f sbci r31, 0xFE ; 254
|
|
1f8: c5 91 lpm r28, Z+
|
|
1fa: d4 91 lpm r29, Z
|
|
out = portOutputRegister(port);
|
|
1fc: fc 01 movw r30, r24
|
|
1fe: ef 5d subi r30, 0xDF ; 223
|
|
200: fe 4f sbci r31, 0xFE ; 254
|
|
202: a5 91 lpm r26, Z+
|
|
204: b4 91 lpm r27, Z
|
|
cli();
|
|
*reg &= ~bit;
|
|
*out &= ~bit;
|
|
SREG = oldSREG;
|
|
} else if (mode == INPUT_PULLUP) {
|
|
uint8_t oldSREG = SREG;
|
|
206: 9f b7 in r25, 0x3f ; 63
|
|
cli();
|
|
208: f8 94 cli
|
|
*reg &= ~bit;
|
|
20a: 38 81 ld r19, Y
|
|
20c: 82 2f mov r24, r18
|
|
20e: 80 95 com r24
|
|
210: 83 23 and r24, r19
|
|
212: 88 83 st Y, r24
|
|
*out |= bit;
|
|
214: ec 91 ld r30, X
|
|
216: e2 2b or r30, r18
|
|
218: ec 93 st X, r30
|
|
SREG = oldSREG;
|
|
21a: 9f bf out 0x3f, r25 ; 63
|
|
uint8_t oldSREG = SREG;
|
|
cli();
|
|
*reg |= bit;
|
|
SREG = oldSREG;
|
|
}
|
|
}
|
|
21c: df 91 pop r29
|
|
21e: cf 91 pop r28
|
|
220: 08 95 ret
|
|
|
|
00000222 <_Z8USB_RecvhPvi.constprop.5>:
|
|
return FifoByteCount();
|
|
}
|
|
|
|
// Non Blocking receive
|
|
// Return number of bytes read
|
|
int USB_Recv(u8 ep, void* d, int len)
|
|
222: fc 01 movw r30, r24
|
|
{
|
|
if (!_usbConfiguration || len < 0)
|
|
224: 80 91 94 01 lds r24, 0x0194 ; 0x800194 <_usbConfiguration>
|
|
228: 88 23 and r24, r24
|
|
22a: 11 f1 breq .+68 ; 0x270 <_Z8USB_RecvhPvi.constprop.5+0x4e>
|
|
#define USB_RECV_TIMEOUT
|
|
class LockEP
|
|
{
|
|
u8 _sreg;
|
|
public:
|
|
LockEP(u8 ep) : _sreg(SREG)
|
|
22c: 3f b7 in r19, 0x3f ; 63
|
|
{
|
|
cli();
|
|
22e: f8 94 cli
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
230: 82 e0 ldi r24, 0x02 ; 2
|
|
232: 80 93 e9 00 sts 0x00E9, r24 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
}
|
|
|
|
static inline u8 FifoByteCount()
|
|
{
|
|
return UEBCLX;
|
|
236: 20 91 f2 00 lds r18, 0x00F2 ; 0x8000f2 <__DATA_REGION_ORIGIN__+0x92>
|
|
if (!_usbConfiguration || len < 0)
|
|
return -1;
|
|
|
|
LockEP lock(ep);
|
|
u8 n = FifoByteCount();
|
|
len = min(n,len);
|
|
23a: 82 2f mov r24, r18
|
|
23c: 90 e0 ldi r25, 0x00 ; 0
|
|
23e: 18 16 cp r1, r24
|
|
240: 19 06 cpc r1, r25
|
|
242: 14 f4 brge .+4 ; 0x248 <_Z8USB_RecvhPvi.constprop.5+0x26>
|
|
244: 81 e0 ldi r24, 0x01 ; 1
|
|
246: 90 e0 ldi r25, 0x00 ; 0
|
|
n = len;
|
|
u8* dst = (u8*)d;
|
|
while (n--)
|
|
248: 88 23 and r24, r24
|
|
24a: 39 f0 breq .+14 ; 0x25a <_Z8USB_RecvhPvi.constprop.5+0x38>
|
|
RxLEDPulse = TX_RX_LED_PULSE_MS;
|
|
}
|
|
|
|
static inline u8 Recv8()
|
|
{
|
|
RXLED1; // light the RX LED
|
|
24c: 28 98 cbi 0x05, 0 ; 5
|
|
RxLEDPulse = TX_RX_LED_PULSE_MS;
|
|
24e: 44 e6 ldi r20, 0x64 ; 100
|
|
250: 40 93 93 01 sts 0x0193, r20 ; 0x800193 <RxLEDPulse>
|
|
|
|
return UEDATX;
|
|
254: 40 91 f1 00 lds r20, 0x00F1 ; 0x8000f1 <__DATA_REGION_ORIGIN__+0x91>
|
|
u8 n = FifoByteCount();
|
|
len = min(n,len);
|
|
n = len;
|
|
u8* dst = (u8*)d;
|
|
while (n--)
|
|
*dst++ = Recv8();
|
|
258: 40 83 st Z, r20
|
|
if (len && !FifoByteCount()) // release empty buffer
|
|
25a: 22 23 and r18, r18
|
|
25c: 39 f0 breq .+14 ; 0x26c <_Z8USB_RecvhPvi.constprop.5+0x4a>
|
|
UENUM = ep;
|
|
}
|
|
|
|
static inline u8 FifoByteCount()
|
|
{
|
|
return UEBCLX;
|
|
25e: 20 91 f2 00 lds r18, 0x00F2 ; 0x8000f2 <__DATA_REGION_ORIGIN__+0x92>
|
|
len = min(n,len);
|
|
n = len;
|
|
u8* dst = (u8*)d;
|
|
while (n--)
|
|
*dst++ = Recv8();
|
|
if (len && !FifoByteCount()) // release empty buffer
|
|
262: 21 11 cpse r18, r1
|
|
264: 03 c0 rjmp .+6 ; 0x26c <_Z8USB_RecvhPvi.constprop.5+0x4a>
|
|
return UEINTX & (1<<FIFOCON);
|
|
}
|
|
|
|
static inline void ReleaseRX()
|
|
{
|
|
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
|
|
266: 2b e6 ldi r18, 0x6B ; 107
|
|
268: 20 93 e8 00 sts 0x00E8, r18 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
cli();
|
|
SetEP(ep & 7);
|
|
}
|
|
~LockEP()
|
|
{
|
|
SREG = _sreg;
|
|
26c: 3f bf out 0x3f, r19 ; 63
|
|
26e: 08 95 ret
|
|
// Non Blocking receive
|
|
// Return number of bytes read
|
|
int USB_Recv(u8 ep, void* d, int len)
|
|
{
|
|
if (!_usbConfiguration || len < 0)
|
|
return -1;
|
|
270: 8f ef ldi r24, 0xFF ; 255
|
|
272: 9f ef ldi r25, 0xFF ; 255
|
|
*dst++ = Recv8();
|
|
if (len && !FifoByteCount()) // release empty buffer
|
|
ReleaseRX();
|
|
|
|
return len;
|
|
}
|
|
274: 08 95 ret
|
|
|
|
00000276 <_Z13USB_SendSpaceh.constprop.3>:
|
|
#define USB_RECV_TIMEOUT
|
|
class LockEP
|
|
{
|
|
u8 _sreg;
|
|
public:
|
|
LockEP(u8 ep) : _sreg(SREG)
|
|
276: 2f b7 in r18, 0x3f ; 63
|
|
{
|
|
cli();
|
|
278: f8 94 cli
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
27a: 83 e0 ldi r24, 0x03 ; 3
|
|
27c: 80 93 e9 00 sts 0x00E9, r24 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
UECONX = (1<<STALLRQ) | (1<<EPEN);
|
|
}
|
|
|
|
static inline u8 ReadWriteAllowed()
|
|
{
|
|
return UEINTX & (1<<RWAL);
|
|
280: 90 91 e8 00 lds r25, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
|
|
// Space in send EP
|
|
u8 USB_SendSpace(u8 ep)
|
|
{
|
|
LockEP lock(ep);
|
|
if (!ReadWriteAllowed())
|
|
284: 89 2f mov r24, r25
|
|
286: 80 72 andi r24, 0x20 ; 32
|
|
288: 95 ff sbrs r25, 5
|
|
28a: 04 c0 rjmp .+8 ; 0x294 <_Z13USB_SendSpaceh.constprop.3+0x1e>
|
|
UENUM = ep;
|
|
}
|
|
|
|
static inline u8 FifoByteCount()
|
|
{
|
|
return UEBCLX;
|
|
28c: 90 91 f2 00 lds r25, 0x00F2 ; 0x8000f2 <__DATA_REGION_ORIGIN__+0x92>
|
|
u8 USB_SendSpace(u8 ep)
|
|
{
|
|
LockEP lock(ep);
|
|
if (!ReadWriteAllowed())
|
|
return 0;
|
|
return USB_EP_SIZE - FifoByteCount();
|
|
290: 80 e4 ldi r24, 0x40 ; 64
|
|
292: 89 1b sub r24, r25
|
|
cli();
|
|
SetEP(ep & 7);
|
|
}
|
|
~LockEP()
|
|
{
|
|
SREG = _sreg;
|
|
294: 2f bf out 0x3f, r18 ; 63
|
|
{
|
|
LockEP lock(ep);
|
|
if (!ReadWriteAllowed())
|
|
return 0;
|
|
return USB_EP_SIZE - FifoByteCount();
|
|
}
|
|
296: 08 95 ret
|
|
|
|
00000298 <_Z12PluggableUSBv>:
|
|
// restart USB layer???
|
|
}
|
|
|
|
PluggableUSB_& PluggableUSB()
|
|
{
|
|
static PluggableUSB_ obj;
|
|
298: 80 91 8b 01 lds r24, 0x018B ; 0x80018b <_ZGVZ12PluggableUSBvE3obj>
|
|
29c: 81 11 cpse r24, r1
|
|
29e: 0d c0 rjmp .+26 ; 0x2ba <_Z12PluggableUSBv+0x22>
|
|
return obj;
|
|
}
|
|
|
|
PluggableUSB_::PluggableUSB_() : lastIf(CDC_ACM_INTERFACE + CDC_INTERFACE_COUNT),
|
|
lastEp(CDC_FIRST_ENDPOINT + CDC_ENPOINT_COUNT),
|
|
rootNode(NULL)
|
|
2a0: 82 e0 ldi r24, 0x02 ; 2
|
|
2a2: 80 93 87 01 sts 0x0187, r24 ; 0x800187 <_ZZ12PluggableUSBvE3obj>
|
|
2a6: 84 e0 ldi r24, 0x04 ; 4
|
|
2a8: 80 93 88 01 sts 0x0188, r24 ; 0x800188 <_ZZ12PluggableUSBvE3obj+0x1>
|
|
2ac: 10 92 8a 01 sts 0x018A, r1 ; 0x80018a <_ZZ12PluggableUSBvE3obj+0x3>
|
|
2b0: 10 92 89 01 sts 0x0189, r1 ; 0x800189 <_ZZ12PluggableUSBvE3obj+0x2>
|
|
// restart USB layer???
|
|
}
|
|
|
|
PluggableUSB_& PluggableUSB()
|
|
{
|
|
static PluggableUSB_ obj;
|
|
2b4: 81 e0 ldi r24, 0x01 ; 1
|
|
2b6: 80 93 8b 01 sts 0x018B, r24 ; 0x80018b <_ZGVZ12PluggableUSBvE3obj>
|
|
return obj;
|
|
}
|
|
2ba: 87 e8 ldi r24, 0x87 ; 135
|
|
2bc: 91 e0 ldi r25, 0x01 ; 1
|
|
2be: 08 95 ret
|
|
|
|
000002c0 <_ZN7Serial_5writeEh>:
|
|
{
|
|
USB_Flush(CDC_TX);
|
|
}
|
|
|
|
size_t Serial_::write(uint8_t c)
|
|
{
|
|
2c0: cf 93 push r28
|
|
2c2: df 93 push r29
|
|
2c4: 1f 92 push r1
|
|
2c6: cd b7 in r28, 0x3d ; 61
|
|
2c8: de b7 in r29, 0x3e ; 62
|
|
2ca: 69 83 std Y+1, r22 ; 0x01
|
|
return write(&c, 1);
|
|
2cc: dc 01 movw r26, r24
|
|
2ce: ed 91 ld r30, X+
|
|
2d0: fc 91 ld r31, X
|
|
2d2: 02 80 ldd r0, Z+2 ; 0x02
|
|
2d4: f3 81 ldd r31, Z+3 ; 0x03
|
|
2d6: e0 2d mov r30, r0
|
|
2d8: 41 e0 ldi r20, 0x01 ; 1
|
|
2da: 50 e0 ldi r21, 0x00 ; 0
|
|
2dc: be 01 movw r22, r28
|
|
2de: 6f 5f subi r22, 0xFF ; 255
|
|
2e0: 7f 4f sbci r23, 0xFF ; 255
|
|
2e2: 09 95 icall
|
|
}
|
|
2e4: 0f 90 pop r0
|
|
2e6: df 91 pop r29
|
|
2e8: cf 91 pop r28
|
|
2ea: 08 95 ret
|
|
|
|
000002ec <_ZN7Serial_5flushEv>:
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
2ec: 83 e0 ldi r24, 0x03 ; 3
|
|
2ee: 80 93 e9 00 sts 0x00E9, r24 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
}
|
|
|
|
static inline u8 FifoByteCount()
|
|
{
|
|
return UEBCLX;
|
|
2f2: 80 91 f2 00 lds r24, 0x00F2 ; 0x8000f2 <__DATA_REGION_ORIGIN__+0x92>
|
|
}
|
|
|
|
void USB_Flush(u8 ep)
|
|
{
|
|
SetEP(ep);
|
|
if (FifoByteCount())
|
|
2f6: 88 23 and r24, r24
|
|
2f8: 19 f0 breq .+6 ; 0x300 <_ZN7Serial_5flushEv+0x14>
|
|
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
|
|
}
|
|
|
|
static inline void ReleaseTX()
|
|
{
|
|
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
|
|
2fa: 8a e3 ldi r24, 0x3A ; 58
|
|
2fc: 80 93 e8 00 sts 0x00E8, r24 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
}
|
|
|
|
void Serial_::flush(void)
|
|
{
|
|
USB_Flush(CDC_TX);
|
|
}
|
|
300: 08 95 ret
|
|
|
|
00000302 <_ZN7Serial_17availableForWriteEv>:
|
|
return USB_Recv(CDC_RX);
|
|
}
|
|
|
|
int Serial_::availableForWrite(void)
|
|
{
|
|
return USB_SendSpace(CDC_TX);
|
|
302: 0e 94 3b 01 call 0x276 ; 0x276 <_Z13USB_SendSpaceh.constprop.3>
|
|
}
|
|
306: 90 e0 ldi r25, 0x00 ; 0
|
|
308: 08 95 ret
|
|
|
|
0000030a <_ZN7Serial_4readEv>:
|
|
peek_buffer = USB_Recv(CDC_RX);
|
|
return peek_buffer;
|
|
}
|
|
|
|
int Serial_::read(void)
|
|
{
|
|
30a: cf 93 push r28
|
|
30c: df 93 push r29
|
|
30e: 1f 92 push r1
|
|
310: cd b7 in r28, 0x3d ; 61
|
|
312: de b7 in r29, 0x3e ; 62
|
|
314: fc 01 movw r30, r24
|
|
if (peek_buffer >= 0) {
|
|
316: 84 85 ldd r24, Z+12 ; 0x0c
|
|
318: 95 85 ldd r25, Z+13 ; 0x0d
|
|
31a: 97 fd sbrc r25, 7
|
|
31c: 08 c0 rjmp .+16 ; 0x32e <_ZN7Serial_4readEv+0x24>
|
|
int c = peek_buffer;
|
|
peek_buffer = -1;
|
|
31e: 2f ef ldi r18, 0xFF ; 255
|
|
320: 3f ef ldi r19, 0xFF ; 255
|
|
322: 35 87 std Z+13, r19 ; 0x0d
|
|
324: 24 87 std Z+12, r18 ; 0x0c
|
|
return c;
|
|
}
|
|
return USB_Recv(CDC_RX);
|
|
}
|
|
326: 0f 90 pop r0
|
|
328: df 91 pop r29
|
|
32a: cf 91 pop r28
|
|
32c: 08 95 ret
|
|
|
|
// Recv 1 byte if ready
|
|
int USB_Recv(u8 ep)
|
|
{
|
|
u8 c;
|
|
if (USB_Recv(ep,&c,1) != 1)
|
|
32e: ce 01 movw r24, r28
|
|
330: 01 96 adiw r24, 0x01 ; 1
|
|
332: 0e 94 11 01 call 0x222 ; 0x222 <_Z8USB_RecvhPvi.constprop.5>
|
|
336: 01 97 sbiw r24, 0x01 ; 1
|
|
338: 19 f4 brne .+6 ; 0x340 <_ZN7Serial_4readEv+0x36>
|
|
return -1;
|
|
return c;
|
|
33a: 89 81 ldd r24, Y+1 ; 0x01
|
|
33c: 90 e0 ldi r25, 0x00 ; 0
|
|
33e: f3 cf rjmp .-26 ; 0x326 <_ZN7Serial_4readEv+0x1c>
|
|
// Recv 1 byte if ready
|
|
int USB_Recv(u8 ep)
|
|
{
|
|
u8 c;
|
|
if (USB_Recv(ep,&c,1) != 1)
|
|
return -1;
|
|
340: 8f ef ldi r24, 0xFF ; 255
|
|
342: 9f ef ldi r25, 0xFF ; 255
|
|
344: f0 cf rjmp .-32 ; 0x326 <_ZN7Serial_4readEv+0x1c>
|
|
|
|
00000346 <_ZN7Serial_4peekEv>:
|
|
}
|
|
return USB_Available(CDC_RX);
|
|
}
|
|
|
|
int Serial_::peek(void)
|
|
{
|
|
346: 0f 93 push r16
|
|
348: 1f 93 push r17
|
|
34a: cf 93 push r28
|
|
34c: df 93 push r29
|
|
34e: 1f 92 push r1
|
|
350: cd b7 in r28, 0x3d ; 61
|
|
352: de b7 in r29, 0x3e ; 62
|
|
354: 8c 01 movw r16, r24
|
|
if (peek_buffer < 0)
|
|
356: fc 01 movw r30, r24
|
|
358: 84 85 ldd r24, Z+12 ; 0x0c
|
|
35a: 95 85 ldd r25, Z+13 ; 0x0d
|
|
35c: 97 ff sbrs r25, 7
|
|
35e: 0b c0 rjmp .+22 ; 0x376 <_ZN7Serial_4peekEv+0x30>
|
|
|
|
// Recv 1 byte if ready
|
|
int USB_Recv(u8 ep)
|
|
{
|
|
u8 c;
|
|
if (USB_Recv(ep,&c,1) != 1)
|
|
360: ce 01 movw r24, r28
|
|
362: 01 96 adiw r24, 0x01 ; 1
|
|
364: 0e 94 11 01 call 0x222 ; 0x222 <_Z8USB_RecvhPvi.constprop.5>
|
|
368: 01 97 sbiw r24, 0x01 ; 1
|
|
36a: 71 f4 brne .+28 ; 0x388 <_ZN7Serial_4peekEv+0x42>
|
|
return -1;
|
|
return c;
|
|
36c: 89 81 ldd r24, Y+1 ; 0x01
|
|
36e: 90 e0 ldi r25, 0x00 ; 0
|
|
peek_buffer = USB_Recv(CDC_RX);
|
|
370: f8 01 movw r30, r16
|
|
372: 95 87 std Z+13, r25 ; 0x0d
|
|
374: 84 87 std Z+12, r24 ; 0x0c
|
|
return peek_buffer;
|
|
}
|
|
376: f8 01 movw r30, r16
|
|
378: 84 85 ldd r24, Z+12 ; 0x0c
|
|
37a: 95 85 ldd r25, Z+13 ; 0x0d
|
|
37c: 0f 90 pop r0
|
|
37e: df 91 pop r29
|
|
380: cf 91 pop r28
|
|
382: 1f 91 pop r17
|
|
384: 0f 91 pop r16
|
|
386: 08 95 ret
|
|
// Recv 1 byte if ready
|
|
int USB_Recv(u8 ep)
|
|
{
|
|
u8 c;
|
|
if (USB_Recv(ep,&c,1) != 1)
|
|
return -1;
|
|
388: 8f ef ldi r24, 0xFF ; 255
|
|
38a: 9f ef ldi r25, 0xFF ; 255
|
|
38c: f1 cf rjmp .-30 ; 0x370 <_ZN7Serial_4peekEv+0x2a>
|
|
|
|
0000038e <_ZN7Serial_9availableEv>:
|
|
{
|
|
}
|
|
|
|
int Serial_::available(void)
|
|
{
|
|
if (peek_buffer >= 0) {
|
|
38e: fc 01 movw r30, r24
|
|
390: 84 85 ldd r24, Z+12 ; 0x0c
|
|
392: 95 85 ldd r25, Z+13 ; 0x0d
|
|
394: 97 fd sbrc r25, 7
|
|
396: 0b c0 rjmp .+22 ; 0x3ae <_ZN7Serial_9availableEv+0x20>
|
|
#define USB_RECV_TIMEOUT
|
|
class LockEP
|
|
{
|
|
u8 _sreg;
|
|
public:
|
|
LockEP(u8 ep) : _sreg(SREG)
|
|
398: 9f b7 in r25, 0x3f ; 63
|
|
{
|
|
cli();
|
|
39a: f8 94 cli
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
39c: 82 e0 ldi r24, 0x02 ; 2
|
|
39e: 80 93 e9 00 sts 0x00E9, r24 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
}
|
|
|
|
static inline u8 FifoByteCount()
|
|
{
|
|
return UEBCLX;
|
|
3a2: 80 91 f2 00 lds r24, 0x00F2 ; 0x8000f2 <__DATA_REGION_ORIGIN__+0x92>
|
|
cli();
|
|
SetEP(ep & 7);
|
|
}
|
|
~LockEP()
|
|
{
|
|
SREG = _sreg;
|
|
3a6: 9f bf out 0x3f, r25 ; 63
|
|
return 1 + USB_Available(CDC_RX);
|
|
3a8: 90 e0 ldi r25, 0x00 ; 0
|
|
3aa: 01 96 adiw r24, 0x01 ; 1
|
|
3ac: 08 95 ret
|
|
#define USB_RECV_TIMEOUT
|
|
class LockEP
|
|
{
|
|
u8 _sreg;
|
|
public:
|
|
LockEP(u8 ep) : _sreg(SREG)
|
|
3ae: 9f b7 in r25, 0x3f ; 63
|
|
{
|
|
cli();
|
|
3b0: f8 94 cli
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
3b2: 82 e0 ldi r24, 0x02 ; 2
|
|
3b4: 80 93 e9 00 sts 0x00E9, r24 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
}
|
|
|
|
static inline u8 FifoByteCount()
|
|
{
|
|
return UEBCLX;
|
|
3b8: 80 91 f2 00 lds r24, 0x00F2 ; 0x8000f2 <__DATA_REGION_ORIGIN__+0x92>
|
|
cli();
|
|
SetEP(ep & 7);
|
|
}
|
|
~LockEP()
|
|
{
|
|
SREG = _sreg;
|
|
3bc: 9f bf out 0x3f, r25 ; 63
|
|
}
|
|
return USB_Available(CDC_RX);
|
|
3be: 90 e0 ldi r25, 0x00 ; 0
|
|
}
|
|
3c0: 08 95 ret
|
|
|
|
000003c2 <_ZL11SendControlh>:
|
|
}
|
|
|
|
static
|
|
bool SendControl(u8 d)
|
|
{
|
|
if (_cmark < _cend)
|
|
3c2: 40 91 31 01 lds r20, 0x0131 ; 0x800131 <_ZL6_cmark>
|
|
3c6: 50 91 32 01 lds r21, 0x0132 ; 0x800132 <_ZL6_cmark+0x1>
|
|
3ca: 20 91 2f 01 lds r18, 0x012F ; 0x80012f <_ZL5_cend>
|
|
3ce: 30 91 30 01 lds r19, 0x0130 ; 0x800130 <_ZL5_cend+0x1>
|
|
3d2: 42 17 cp r20, r18
|
|
3d4: 53 07 cpc r21, r19
|
|
3d6: b4 f4 brge .+44 ; 0x404 <__LOCK_REGION_LENGTH__+0x4>
|
|
;
|
|
}
|
|
|
|
static inline u8 WaitForINOrOUT()
|
|
{
|
|
while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
|
|
3d8: 90 91 e8 00 lds r25, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
3dc: 95 70 andi r25, 0x05 ; 5
|
|
3de: e1 f3 breq .-8 ; 0x3d8 <_ZL11SendControlh+0x16>
|
|
;
|
|
return (UEINTX & (1<<RXOUTI)) == 0;
|
|
3e0: 90 91 e8 00 lds r25, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
static
|
|
bool SendControl(u8 d)
|
|
{
|
|
if (_cmark < _cend)
|
|
{
|
|
if (!WaitForINOrOUT())
|
|
3e4: 92 fd sbrc r25, 2
|
|
3e6: 19 c0 rjmp .+50 ; 0x41a <__LOCK_REGION_LENGTH__+0x1a>
|
|
return UEDATX;
|
|
}
|
|
|
|
static inline void Send8(u8 d)
|
|
{
|
|
UEDATX = d;
|
|
3e8: 80 93 f1 00 sts 0x00F1, r24 ; 0x8000f1 <__DATA_REGION_ORIGIN__+0x91>
|
|
if (_cmark < _cend)
|
|
{
|
|
if (!WaitForINOrOUT())
|
|
return false;
|
|
Send8(d);
|
|
if (!((_cmark + 1) & 0x3F))
|
|
3ec: 80 91 31 01 lds r24, 0x0131 ; 0x800131 <_ZL6_cmark>
|
|
3f0: 90 91 32 01 lds r25, 0x0132 ; 0x800132 <_ZL6_cmark+0x1>
|
|
3f4: 01 96 adiw r24, 0x01 ; 1
|
|
3f6: 8f 73 andi r24, 0x3F ; 63
|
|
3f8: 99 27 eor r25, r25
|
|
3fa: 89 2b or r24, r25
|
|
3fc: 19 f4 brne .+6 ; 0x404 <__LOCK_REGION_LENGTH__+0x4>
|
|
;
|
|
}
|
|
|
|
static inline void ClearIN(void)
|
|
{
|
|
UEINTX = ~(1<<TXINI);
|
|
3fe: 8e ef ldi r24, 0xFE ; 254
|
|
400: 80 93 e8 00 sts 0x00E8, r24 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
return false;
|
|
Send8(d);
|
|
if (!((_cmark + 1) & 0x3F))
|
|
ClearIN(); // Fifo is full, release this packet
|
|
}
|
|
_cmark++;
|
|
404: 80 91 31 01 lds r24, 0x0131 ; 0x800131 <_ZL6_cmark>
|
|
408: 90 91 32 01 lds r25, 0x0132 ; 0x800132 <_ZL6_cmark+0x1>
|
|
40c: 01 96 adiw r24, 0x01 ; 1
|
|
40e: 90 93 32 01 sts 0x0132, r25 ; 0x800132 <_ZL6_cmark+0x1>
|
|
412: 80 93 31 01 sts 0x0131, r24 ; 0x800131 <_ZL6_cmark>
|
|
return true;
|
|
416: 81 e0 ldi r24, 0x01 ; 1
|
|
418: 08 95 ret
|
|
bool SendControl(u8 d)
|
|
{
|
|
if (_cmark < _cend)
|
|
{
|
|
if (!WaitForINOrOUT())
|
|
return false;
|
|
41a: 80 e0 ldi r24, 0x00 ; 0
|
|
if (!((_cmark + 1) & 0x3F))
|
|
ClearIN(); // Fifo is full, release this packet
|
|
}
|
|
_cmark++;
|
|
return true;
|
|
}
|
|
41c: 08 95 ret
|
|
|
|
0000041e <_ZL24USB_SendStringDescriptorPKhhh>:
|
|
}
|
|
|
|
// Send a USB descriptor string. The string is stored in PROGMEM as a
|
|
// 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, uint8_t flags) {
|
|
41e: ef 92 push r14
|
|
420: ff 92 push r15
|
|
422: 0f 93 push r16
|
|
424: 1f 93 push r17
|
|
426: cf 93 push r28
|
|
428: df 93 push r29
|
|
42a: f8 2e mov r15, r24
|
|
42c: 19 2f mov r17, r25
|
|
42e: e6 2e mov r14, r22
|
|
430: 04 2f mov r16, r20
|
|
SendControl(2 + string_len * 2);
|
|
432: 81 e0 ldi r24, 0x01 ; 1
|
|
434: 86 0f add r24, r22
|
|
436: 88 0f add r24, r24
|
|
438: 0e 94 e1 01 call 0x3c2 ; 0x3c2 <_ZL11SendControlh>
|
|
SendControl(3);
|
|
43c: 83 e0 ldi r24, 0x03 ; 3
|
|
43e: 0e 94 e1 01 call 0x3c2 ; 0x3c2 <_ZL11SendControlh>
|
|
442: cf 2d mov r28, r15
|
|
444: d1 2f mov r29, r17
|
|
446: ec 0e add r14, r28
|
|
448: fd 2e mov r15, r29
|
|
44a: f1 1c adc r15, r1
|
|
bool pgm = flags & TRANSFER_PGM;
|
|
for(u8 i = 0; i < string_len; i++) {
|
|
44c: ce 15 cp r28, r14
|
|
44e: df 05 cpc r29, r15
|
|
450: b9 f0 breq .+46 ; 0x480 <_ZL24USB_SendStringDescriptorPKhhh+0x62>
|
|
bool r = SendControl(pgm ? pgm_read_byte(&string_P[i]) : string_P[i]);
|
|
452: 07 ff sbrs r16, 7
|
|
454: 13 c0 rjmp .+38 ; 0x47c <_ZL24USB_SendStringDescriptorPKhhh+0x5e>
|
|
456: fe 01 movw r30, r28
|
|
458: 84 91 lpm r24, Z
|
|
45a: 0e 94 e1 01 call 0x3c2 ; 0x3c2 <_ZL11SendControlh>
|
|
45e: 18 2f mov r17, r24
|
|
r &= SendControl(0); // high byte
|
|
460: 80 e0 ldi r24, 0x00 ; 0
|
|
462: 0e 94 e1 01 call 0x3c2 ; 0x3c2 <_ZL11SendControlh>
|
|
466: 81 23 and r24, r17
|
|
468: 21 96 adiw r28, 0x01 ; 1
|
|
if(!r) {
|
|
46a: 81 11 cpse r24, r1
|
|
46c: ef cf rjmp .-34 ; 0x44c <_ZL24USB_SendStringDescriptorPKhhh+0x2e>
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
46e: df 91 pop r29
|
|
470: cf 91 pop r28
|
|
472: 1f 91 pop r17
|
|
474: 0f 91 pop r16
|
|
476: ff 90 pop r15
|
|
478: ef 90 pop r14
|
|
47a: 08 95 ret
|
|
static bool USB_SendStringDescriptor(const u8*string_P, u8 string_len, uint8_t flags) {
|
|
SendControl(2 + string_len * 2);
|
|
SendControl(3);
|
|
bool pgm = flags & TRANSFER_PGM;
|
|
for(u8 i = 0; i < string_len; i++) {
|
|
bool r = SendControl(pgm ? pgm_read_byte(&string_P[i]) : string_P[i]);
|
|
47c: 88 81 ld r24, Y
|
|
47e: ed cf rjmp .-38 ; 0x45a <_ZL24USB_SendStringDescriptorPKhhh+0x3c>
|
|
r &= SendControl(0); // high byte
|
|
if(!r) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
480: 81 e0 ldi r24, 0x01 ; 1
|
|
482: f5 cf rjmp .-22 ; 0x46e <_ZL24USB_SendStringDescriptorPKhhh+0x50>
|
|
|
|
00000484 <_Z15USB_SendControlhPKvi>:
|
|
return true;
|
|
}
|
|
|
|
// Clipped by _cmark/_cend
|
|
int USB_SendControl(u8 flags, const void* d, int len)
|
|
{
|
|
484: df 92 push r13
|
|
486: ef 92 push r14
|
|
488: ff 92 push r15
|
|
48a: 0f 93 push r16
|
|
48c: 1f 93 push r17
|
|
48e: cf 93 push r28
|
|
490: df 93 push r29
|
|
492: d8 2e mov r13, r24
|
|
494: 8a 01 movw r16, r20
|
|
496: eb 01 movw r28, r22
|
|
498: 7b 01 movw r14, r22
|
|
49a: e4 0e add r14, r20
|
|
49c: f5 1e adc r15, r21
|
|
int sent = len;
|
|
const u8* data = (const u8*)d;
|
|
bool pgm = flags & TRANSFER_PGM;
|
|
while (len--)
|
|
49e: ce 15 cp r28, r14
|
|
4a0: df 05 cpc r29, r15
|
|
4a2: 59 f0 breq .+22 ; 0x4ba <_Z15USB_SendControlhPKvi+0x36>
|
|
{
|
|
u8 c = pgm ? pgm_read_byte(data++) : *data++;
|
|
4a4: d7 fe sbrs r13, 7
|
|
4a6: 12 c0 rjmp .+36 ; 0x4cc <_Z15USB_SendControlhPKvi+0x48>
|
|
4a8: fe 01 movw r30, r28
|
|
4aa: 84 91 lpm r24, Z
|
|
if (!SendControl(c))
|
|
4ac: 0e 94 e1 01 call 0x3c2 ; 0x3c2 <_ZL11SendControlh>
|
|
4b0: 21 96 adiw r28, 0x01 ; 1
|
|
4b2: 81 11 cpse r24, r1
|
|
4b4: f4 cf rjmp .-24 ; 0x49e <_Z15USB_SendControlhPKvi+0x1a>
|
|
return -1;
|
|
4b6: 0f ef ldi r16, 0xFF ; 255
|
|
4b8: 1f ef ldi r17, 0xFF ; 255
|
|
}
|
|
return sent;
|
|
}
|
|
4ba: c8 01 movw r24, r16
|
|
4bc: df 91 pop r29
|
|
4be: cf 91 pop r28
|
|
4c0: 1f 91 pop r17
|
|
4c2: 0f 91 pop r16
|
|
4c4: ff 90 pop r15
|
|
4c6: ef 90 pop r14
|
|
4c8: df 90 pop r13
|
|
4ca: 08 95 ret
|
|
int sent = len;
|
|
const u8* data = (const u8*)d;
|
|
bool pgm = flags & TRANSFER_PGM;
|
|
while (len--)
|
|
{
|
|
u8 c = pgm ? pgm_read_byte(data++) : *data++;
|
|
4cc: 88 81 ld r24, Y
|
|
4ce: ee cf rjmp .-36 ; 0x4ac <_Z15USB_SendControlhPKvi+0x28>
|
|
|
|
000004d0 <_ZL14SendInterfacesv>:
|
|
}
|
|
return len;
|
|
}
|
|
|
|
static u8 SendInterfaces()
|
|
{
|
|
4d0: 0f 93 push r16
|
|
4d2: 1f 93 push r17
|
|
4d4: cf 93 push r28
|
|
4d6: df 93 push r29
|
|
4d8: 1f 92 push r1
|
|
4da: cd b7 in r28, 0x3d ; 61
|
|
4dc: de b7 in r29, 0x3e ; 62
|
|
return pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE;
|
|
}
|
|
|
|
int CDC_GetInterface(u8* interfaceNum)
|
|
{
|
|
interfaceNum[0] += 2; // uses 2
|
|
4de: 82 e0 ldi r24, 0x02 ; 2
|
|
4e0: 89 83 std Y+1, r24 ; 0x01
|
|
return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface));
|
|
4e2: 42 e4 ldi r20, 0x42 ; 66
|
|
4e4: 50 e0 ldi r21, 0x00 ; 0
|
|
4e6: 6c ea ldi r22, 0xAC ; 172
|
|
4e8: 70 e0 ldi r23, 0x00 ; 0
|
|
4ea: 80 e8 ldi r24, 0x80 ; 128
|
|
4ec: 0e 94 42 02 call 0x484 ; 0x484 <_Z15USB_SendControlhPKvi>
|
|
#ifdef CDC_ENABLED
|
|
CDC_GetInterface(&interfaces);
|
|
#endif
|
|
|
|
#ifdef PLUGGABLE_USB_ENABLED
|
|
PluggableUSB().getInterface(&interfaces);
|
|
4f0: 0e 94 4c 01 call 0x298 ; 0x298 <_Z12PluggableUSBv>
|
|
|
|
int PluggableUSB_::getInterface(uint8_t* interfaceCount)
|
|
{
|
|
int sent = 0;
|
|
PluggableUSBModule* node;
|
|
for (node = rootNode; node; node = node->next) {
|
|
4f4: dc 01 movw r26, r24
|
|
4f6: 12 96 adiw r26, 0x02 ; 2
|
|
4f8: 0d 91 ld r16, X+
|
|
4fa: 1c 91 ld r17, X
|
|
4fc: 01 15 cp r16, r1
|
|
4fe: 11 05 cpc r17, r1
|
|
500: 89 f0 breq .+34 ; 0x524 <_ZL14SendInterfacesv+0x54>
|
|
int res = node->getInterface(interfaceCount);
|
|
502: d8 01 movw r26, r16
|
|
504: ed 91 ld r30, X+
|
|
506: fc 91 ld r31, X
|
|
508: 02 80 ldd r0, Z+2 ; 0x02
|
|
50a: f3 81 ldd r31, Z+3 ; 0x03
|
|
50c: e0 2d mov r30, r0
|
|
50e: be 01 movw r22, r28
|
|
510: 6f 5f subi r22, 0xFF ; 255
|
|
512: 7f 4f sbci r23, 0xFF ; 255
|
|
514: c8 01 movw r24, r16
|
|
516: 09 95 icall
|
|
if (res < 0)
|
|
518: 97 fd sbrc r25, 7
|
|
51a: 04 c0 rjmp .+8 ; 0x524 <_ZL14SendInterfacesv+0x54>
|
|
|
|
int PluggableUSB_::getInterface(uint8_t* interfaceCount)
|
|
{
|
|
int sent = 0;
|
|
PluggableUSBModule* node;
|
|
for (node = rootNode; node; node = node->next) {
|
|
51c: f8 01 movw r30, r16
|
|
51e: 00 85 ldd r16, Z+8 ; 0x08
|
|
520: 11 85 ldd r17, Z+9 ; 0x09
|
|
522: ec cf rjmp .-40 ; 0x4fc <_ZL14SendInterfacesv+0x2c>
|
|
#endif
|
|
|
|
return interfaces;
|
|
}
|
|
524: 89 81 ldd r24, Y+1 ; 0x01
|
|
526: 0f 90 pop r0
|
|
528: df 91 pop r29
|
|
52a: cf 91 pop r28
|
|
52c: 1f 91 pop r17
|
|
52e: 0f 91 pop r16
|
|
530: 08 95 ret
|
|
|
|
00000532 <_ZL4RecvPVhh>:
|
|
UEINTX = ~(1<<RXOUTI);
|
|
}
|
|
|
|
static inline void Recv(volatile u8* data, u8 count)
|
|
{
|
|
while (count--)
|
|
532: 61 50 subi r22, 0x01 ; 1
|
|
534: 30 f0 brcs .+12 ; 0x542 <_ZL4RecvPVhh+0x10>
|
|
*data++ = UEDATX;
|
|
536: 20 91 f1 00 lds r18, 0x00F1 ; 0x8000f1 <__DATA_REGION_ORIGIN__+0x91>
|
|
53a: fc 01 movw r30, r24
|
|
53c: 20 83 st Z, r18
|
|
53e: 01 96 adiw r24, 0x01 ; 1
|
|
540: f8 cf rjmp .-16 ; 0x532 <_ZL4RecvPVhh>
|
|
|
|
RXLED1; // light the RX LED
|
|
542: 28 98 cbi 0x05, 0 ; 5
|
|
RxLEDPulse = TX_RX_LED_PULSE_MS;
|
|
544: 84 e6 ldi r24, 0x64 ; 100
|
|
546: 80 93 93 01 sts 0x0193, r24 ; 0x800193 <RxLEDPulse>
|
|
}
|
|
54a: 08 95 ret
|
|
|
|
0000054c <micros>:
|
|
return m;
|
|
}
|
|
|
|
unsigned long micros() {
|
|
unsigned long m;
|
|
uint8_t oldSREG = SREG, t;
|
|
54c: 3f b7 in r19, 0x3f ; 63
|
|
|
|
cli();
|
|
54e: f8 94 cli
|
|
m = timer0_overflow_count;
|
|
550: 80 91 2b 01 lds r24, 0x012B ; 0x80012b <timer0_overflow_count>
|
|
554: 90 91 2c 01 lds r25, 0x012C ; 0x80012c <timer0_overflow_count+0x1>
|
|
558: a0 91 2d 01 lds r26, 0x012D ; 0x80012d <timer0_overflow_count+0x2>
|
|
55c: b0 91 2e 01 lds r27, 0x012E ; 0x80012e <timer0_overflow_count+0x3>
|
|
#if defined(TCNT0)
|
|
t = TCNT0;
|
|
560: 26 b5 in r18, 0x26 ; 38
|
|
#else
|
|
#error TIMER 0 not defined
|
|
#endif
|
|
|
|
#ifdef TIFR0
|
|
if ((TIFR0 & _BV(TOV0)) && (t < 255))
|
|
562: a8 9b sbis 0x15, 0 ; 21
|
|
564: 05 c0 rjmp .+10 ; 0x570 <micros+0x24>
|
|
566: 2f 3f cpi r18, 0xFF ; 255
|
|
568: 19 f0 breq .+6 ; 0x570 <micros+0x24>
|
|
m++;
|
|
56a: 01 96 adiw r24, 0x01 ; 1
|
|
56c: a1 1d adc r26, r1
|
|
56e: b1 1d adc r27, r1
|
|
#else
|
|
if ((TIFR & _BV(TOV0)) && (t < 255))
|
|
m++;
|
|
#endif
|
|
|
|
SREG = oldSREG;
|
|
570: 3f bf out 0x3f, r19 ; 63
|
|
|
|
return ((m << 8) + t) * (64 / clockCyclesPerMicrosecond());
|
|
572: ba 2f mov r27, r26
|
|
574: a9 2f mov r26, r25
|
|
576: 98 2f mov r25, r24
|
|
578: 88 27 eor r24, r24
|
|
57a: bc 01 movw r22, r24
|
|
57c: cd 01 movw r24, r26
|
|
57e: 62 0f add r22, r18
|
|
580: 71 1d adc r23, r1
|
|
582: 81 1d adc r24, r1
|
|
584: 91 1d adc r25, r1
|
|
586: 42 e0 ldi r20, 0x02 ; 2
|
|
588: 66 0f add r22, r22
|
|
58a: 77 1f adc r23, r23
|
|
58c: 88 1f adc r24, r24
|
|
58e: 99 1f adc r25, r25
|
|
590: 4a 95 dec r20
|
|
592: d1 f7 brne .-12 ; 0x588 <micros+0x3c>
|
|
}
|
|
594: 08 95 ret
|
|
|
|
00000596 <delay.constprop.10>:
|
|
|
|
void delay(unsigned long ms)
|
|
596: cf 92 push r12
|
|
598: df 92 push r13
|
|
59a: ef 92 push r14
|
|
59c: ff 92 push r15
|
|
{
|
|
uint32_t start = micros();
|
|
59e: 0e 94 a6 02 call 0x54c ; 0x54c <micros>
|
|
5a2: 6b 01 movw r12, r22
|
|
5a4: 7c 01 movw r14, r24
|
|
|
|
while (ms > 0) {
|
|
yield();
|
|
while ( ms > 0 && (micros() - start) >= 1000) {
|
|
5a6: 0e 94 a6 02 call 0x54c ; 0x54c <micros>
|
|
5aa: 6c 19 sub r22, r12
|
|
5ac: 7d 09 sbc r23, r13
|
|
5ae: 8e 09 sbc r24, r14
|
|
5b0: 9f 09 sbc r25, r15
|
|
5b2: 68 3e cpi r22, 0xE8 ; 232
|
|
5b4: 73 40 sbci r23, 0x03 ; 3
|
|
5b6: 81 05 cpc r24, r1
|
|
5b8: 91 05 cpc r25, r1
|
|
5ba: a8 f3 brcs .-22 ; 0x5a6 <delay.constprop.10+0x10>
|
|
ms--;
|
|
start += 1000;
|
|
}
|
|
}
|
|
}
|
|
5bc: ff 90 pop r15
|
|
5be: ef 90 pop r14
|
|
5c0: df 90 pop r13
|
|
5c2: cf 90 pop r12
|
|
5c4: 08 95 ret
|
|
|
|
000005c6 <_ZN7Serial_5writeEPKhj>:
|
|
{
|
|
return write(&c, 1);
|
|
}
|
|
|
|
size_t Serial_::write(const uint8_t *buffer, size_t size)
|
|
{
|
|
5c6: 8f 92 push r8
|
|
5c8: 9f 92 push r9
|
|
5ca: af 92 push r10
|
|
5cc: bf 92 push r11
|
|
5ce: cf 92 push r12
|
|
5d0: df 92 push r13
|
|
5d2: ef 92 push r14
|
|
5d4: ff 92 push r15
|
|
5d6: 0f 93 push r16
|
|
5d8: 1f 93 push r17
|
|
5da: cf 93 push r28
|
|
5dc: df 93 push r29
|
|
5de: 6c 01 movw r12, r24
|
|
5e0: 7b 01 movw r14, r22
|
|
5e2: 8a 01 movw r16, r20
|
|
the connection is closed are lost - just like with a UART. */
|
|
|
|
// TODO - ZE - check behavior on different OSes and test what happens if an
|
|
// open connection isn't broken cleanly (cable is yanked out, host dies
|
|
// or locks up, or host virtual serial port hangs)
|
|
if (_usbLineInfo.lineState > 0) {
|
|
5e4: 80 91 0b 01 lds r24, 0x010B ; 0x80010b <_ZL12_usbLineInfo+0x7>
|
|
5e8: 88 23 and r24, r24
|
|
5ea: 09 f4 brne .+2 ; 0x5ee <_ZN7Serial_5writeEPKhj+0x28>
|
|
5ec: 58 c0 rjmp .+176 ; 0x69e <_ZN7Serial_5writeEPKhj+0xd8>
|
|
}
|
|
|
|
// Blocking Send of data to an endpoint
|
|
int USB_Send(u8 ep, const void* d, int len)
|
|
{
|
|
if (!_usbConfiguration)
|
|
5ee: 80 91 94 01 lds r24, 0x0194 ; 0x800194 <_usbConfiguration>
|
|
5f2: 88 23 and r24, r24
|
|
5f4: 09 f4 brne .+2 ; 0x5f8 <_ZN7Serial_5writeEPKhj+0x32>
|
|
5f6: 53 c0 rjmp .+166 ; 0x69e <_ZN7Serial_5writeEPKhj+0xd8>
|
|
return -1;
|
|
|
|
if (_usbSuspendState & (1<<SUSPI)) {
|
|
5f8: 80 91 36 01 lds r24, 0x0136 ; 0x800136 <_usbSuspendState>
|
|
5fc: 80 ff sbrs r24, 0
|
|
5fe: 05 c0 rjmp .+10 ; 0x60a <_ZN7Serial_5writeEPKhj+0x44>
|
|
//send a remote wakeup
|
|
UDCON |= (1 << RMWKUP);
|
|
600: 80 91 e0 00 lds r24, 0x00E0 ; 0x8000e0 <__DATA_REGION_ORIGIN__+0x80>
|
|
604: 82 60 ori r24, 0x02 ; 2
|
|
606: 80 93 e0 00 sts 0x00E0, r24 ; 0x8000e0 <__DATA_REGION_ORIGIN__+0x80>
|
|
{
|
|
return write(&c, 1);
|
|
}
|
|
|
|
size_t Serial_::write(const uint8_t *buffer, size_t size)
|
|
{
|
|
60a: e8 01 movw r28, r16
|
|
60c: b1 2c mov r11, r1
|
|
60e: 8a ef ldi r24, 0xFA ; 250
|
|
610: a8 2e mov r10, r24
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
612: 93 e0 ldi r25, 0x03 ; 3
|
|
614: 89 2e mov r8, r25
|
|
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
|
|
}
|
|
|
|
static inline void ReleaseTX()
|
|
{
|
|
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
|
|
616: 2a e3 ldi r18, 0x3A ; 58
|
|
618: 92 2e mov r9, r18
|
|
int r = len;
|
|
const u8* data = (const u8*)d;
|
|
u8 timeout = 250; // 250ms timeout on send? TODO
|
|
bool sendZlp = false;
|
|
|
|
while (len || sendZlp)
|
|
61a: 20 97 sbiw r28, 0x00 ; 0
|
|
61c: 11 f4 brne .+4 ; 0x622 <_ZN7Serial_5writeEPKhj+0x5c>
|
|
61e: bb 20 and r11, r11
|
|
620: b9 f1 breq .+110 ; 0x690 <_ZN7Serial_5writeEPKhj+0xca>
|
|
{
|
|
u8 n = USB_SendSpace(ep);
|
|
622: 0e 94 3b 01 call 0x276 ; 0x276 <_Z13USB_SendSpaceh.constprop.3>
|
|
if (n == 0)
|
|
626: 81 11 cpse r24, r1
|
|
628: 06 c0 rjmp .+12 ; 0x636 <_ZN7Serial_5writeEPKhj+0x70>
|
|
{
|
|
if (!(--timeout))
|
|
62a: aa 94 dec r10
|
|
62c: aa 20 and r10, r10
|
|
62e: b9 f1 breq .+110 ; 0x69e <_ZN7Serial_5writeEPKhj+0xd8>
|
|
return -1;
|
|
delay(1);
|
|
630: 0e 94 cb 02 call 0x596 ; 0x596 <delay.constprop.10>
|
|
634: f2 cf rjmp .-28 ; 0x61a <_ZN7Serial_5writeEPKhj+0x54>
|
|
continue;
|
|
}
|
|
|
|
if (n > len) {
|
|
636: 8c 17 cp r24, r28
|
|
638: 1d 06 cpc r1, r29
|
|
63a: 11 f0 breq .+4 ; 0x640 <_ZN7Serial_5writeEPKhj+0x7a>
|
|
63c: 0c f0 brlt .+2 ; 0x640 <_ZN7Serial_5writeEPKhj+0x7a>
|
|
n = len;
|
|
63e: 8c 2f mov r24, r28
|
|
#define USB_RECV_TIMEOUT
|
|
class LockEP
|
|
{
|
|
u8 _sreg;
|
|
public:
|
|
LockEP(u8 ep) : _sreg(SREG)
|
|
640: 9f b7 in r25, 0x3f ; 63
|
|
{
|
|
cli();
|
|
642: f8 94 cli
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
644: 80 92 e9 00 sts 0x00E9, r8 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
UECONX = (1<<STALLRQ) | (1<<EPEN);
|
|
}
|
|
|
|
static inline u8 ReadWriteAllowed()
|
|
{
|
|
return UEINTX & (1<<RWAL);
|
|
648: 20 91 e8 00 lds r18, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
}
|
|
|
|
{
|
|
LockEP lock(ep);
|
|
// Frame may have been released by the SOF interrupt handler
|
|
if (!ReadWriteAllowed())
|
|
64c: 25 fd sbrc r18, 5
|
|
64e: 02 c0 rjmp .+4 ; 0x654 <_ZN7Serial_5writeEPKhj+0x8e>
|
|
cli();
|
|
SetEP(ep & 7);
|
|
}
|
|
~LockEP()
|
|
{
|
|
SREG = _sreg;
|
|
650: 9f bf out 0x3f, r25 ; 63
|
|
652: e3 cf rjmp .-58 ; 0x61a <_ZN7Serial_5writeEPKhj+0x54>
|
|
LockEP lock(ep);
|
|
// Frame may have been released by the SOF interrupt handler
|
|
if (!ReadWriteAllowed())
|
|
continue;
|
|
|
|
len -= n;
|
|
654: 28 2f mov r18, r24
|
|
656: 30 e0 ldi r19, 0x00 ; 0
|
|
658: c2 1b sub r28, r18
|
|
65a: d3 0b sbc r29, r19
|
|
65c: f7 01 movw r30, r14
|
|
while (n--)
|
|
Send8(pgm_read_byte(data++));
|
|
}
|
|
else
|
|
{
|
|
while (n--)
|
|
65e: 81 50 subi r24, 0x01 ; 1
|
|
660: 20 f0 brcs .+8 ; 0x66a <_ZN7Serial_5writeEPKhj+0xa4>
|
|
Send8(*data++);
|
|
662: 41 91 ld r20, Z+
|
|
return UEDATX;
|
|
}
|
|
|
|
static inline void Send8(u8 d)
|
|
{
|
|
UEDATX = d;
|
|
664: 40 93 f1 00 sts 0x00F1, r20 ; 0x8000f1 <__DATA_REGION_ORIGIN__+0x91>
|
|
668: fa cf rjmp .-12 ; 0x65e <_ZN7Serial_5writeEPKhj+0x98>
|
|
66a: e2 0e add r14, r18
|
|
66c: f3 1e adc r15, r19
|
|
{
|
|
while (n--)
|
|
Send8(*data++);
|
|
}
|
|
|
|
if (sendZlp) {
|
|
66e: bb 20 and r11, r11
|
|
670: 21 f0 breq .+8 ; 0x67a <_ZN7Serial_5writeEPKhj+0xb4>
|
|
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
|
|
}
|
|
|
|
static inline void ReleaseTX()
|
|
{
|
|
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
|
|
672: 90 92 e8 00 sts 0x00E8, r9 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
if (sendZlp) {
|
|
ReleaseTX();
|
|
sendZlp = false;
|
|
} else if (!ReadWriteAllowed()) { // ...release if buffer is full...
|
|
ReleaseTX();
|
|
if (len == 0) sendZlp = true;
|
|
676: b1 2c mov r11, r1
|
|
678: eb cf rjmp .-42 ; 0x650 <_ZN7Serial_5writeEPKhj+0x8a>
|
|
UECONX = (1<<STALLRQ) | (1<<EPEN);
|
|
}
|
|
|
|
static inline u8 ReadWriteAllowed()
|
|
{
|
|
return UEINTX & (1<<RWAL);
|
|
67a: 80 91 e8 00 lds r24, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
}
|
|
|
|
if (sendZlp) {
|
|
ReleaseTX();
|
|
sendZlp = false;
|
|
} else if (!ReadWriteAllowed()) { // ...release if buffer is full...
|
|
67e: 85 fd sbrc r24, 5
|
|
680: e7 cf rjmp .-50 ; 0x650 <_ZN7Serial_5writeEPKhj+0x8a>
|
|
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
|
|
}
|
|
|
|
static inline void ReleaseTX()
|
|
{
|
|
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
|
|
682: 90 92 e8 00 sts 0x00E8, r9 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
if (sendZlp) {
|
|
ReleaseTX();
|
|
sendZlp = false;
|
|
} else if (!ReadWriteAllowed()) { // ...release if buffer is full...
|
|
ReleaseTX();
|
|
if (len == 0) sendZlp = true;
|
|
686: bb 24 eor r11, r11
|
|
688: b3 94 inc r11
|
|
68a: 20 97 sbiw r28, 0x00 ; 0
|
|
68c: 09 f3 breq .-62 ; 0x650 <_ZN7Serial_5writeEPKhj+0x8a>
|
|
68e: f3 cf rjmp .-26 ; 0x676 <_ZN7Serial_5writeEPKhj+0xb0>
|
|
// XXX: TRANSFER_RELEASE is never used can be removed?
|
|
ReleaseTX();
|
|
}
|
|
}
|
|
}
|
|
TXLED1; // light the TX LED
|
|
690: 5d 98 cbi 0x0b, 5 ; 11
|
|
TxLEDPulse = TX_RX_LED_PULSE_MS;
|
|
692: 84 e6 ldi r24, 0x64 ; 100
|
|
694: 80 93 35 01 sts 0x0135, r24 ; 0x800135 <TxLEDPulse>
|
|
// TODO - ZE - check behavior on different OSes and test what happens if an
|
|
// open connection isn't broken cleanly (cable is yanked out, host dies
|
|
// or locks up, or host virtual serial port hangs)
|
|
if (_usbLineInfo.lineState > 0) {
|
|
int r = USB_Send(CDC_TX,buffer,size);
|
|
if (r > 0) {
|
|
698: 10 16 cp r1, r16
|
|
69a: 11 06 cpc r1, r17
|
|
69c: 3c f0 brlt .+14 ; 0x6ac <_ZN7Serial_5writeEPKhj+0xe6>
|
|
private:
|
|
int write_error;
|
|
size_t printNumber(unsigned long, uint8_t);
|
|
size_t printFloat(double, uint8_t);
|
|
protected:
|
|
void setWriteError(int err = 1) { write_error = err; }
|
|
69e: 81 e0 ldi r24, 0x01 ; 1
|
|
6a0: 90 e0 ldi r25, 0x00 ; 0
|
|
6a2: f6 01 movw r30, r12
|
|
6a4: 93 83 std Z+3, r25 ; 0x03
|
|
6a6: 82 83 std Z+2, r24 ; 0x02
|
|
return r;
|
|
} else {
|
|
setWriteError();
|
|
return 0;
|
|
6a8: 10 e0 ldi r17, 0x00 ; 0
|
|
6aa: 00 e0 ldi r16, 0x00 ; 0
|
|
}
|
|
}
|
|
setWriteError();
|
|
return 0;
|
|
}
|
|
6ac: c8 01 movw r24, r16
|
|
6ae: df 91 pop r29
|
|
6b0: cf 91 pop r28
|
|
6b2: 1f 91 pop r17
|
|
6b4: 0f 91 pop r16
|
|
6b6: ff 90 pop r15
|
|
6b8: ef 90 pop r14
|
|
6ba: df 90 pop r13
|
|
6bc: cf 90 pop r12
|
|
6be: bf 90 pop r11
|
|
6c0: af 90 pop r10
|
|
6c2: 9f 90 pop r9
|
|
6c4: 8f 90 pop r8
|
|
6c6: 08 95 ret
|
|
|
|
000006c8 <__vector_10>:
|
|
#endif
|
|
}
|
|
|
|
// General interrupt
|
|
ISR(USB_GEN_vect)
|
|
{
|
|
6c8: 1f 92 push r1
|
|
6ca: 0f 92 push r0
|
|
6cc: 0f b6 in r0, 0x3f ; 63
|
|
6ce: 0f 92 push r0
|
|
6d0: 11 24 eor r1, r1
|
|
6d2: 8f 93 push r24
|
|
6d4: 9f 93 push r25
|
|
u8 udint = UDINT;
|
|
6d6: 80 91 e1 00 lds r24, 0x00E1 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
UDINT &= ~((1<<EORSTI) | (1<<SOFI)); // clear the IRQ flags for the IRQs which are handled here, except WAKEUPI and SUSPI (see below)
|
|
6da: 90 91 e1 00 lds r25, 0x00E1 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
6de: 93 7f andi r25, 0xF3 ; 243
|
|
6e0: 90 93 e1 00 sts 0x00E1, r25 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
|
|
// End of Reset
|
|
if (udint & (1<<EORSTI))
|
|
6e4: 83 ff sbrs r24, 3
|
|
6e6: 0f c0 rjmp .+30 ; 0x706 <__vector_10+0x3e>
|
|
#define EP_SINGLE_16 0x12
|
|
|
|
static
|
|
void InitEP(u8 index, u8 type, u8 size)
|
|
{
|
|
UENUM = index;
|
|
6e8: 10 92 e9 00 sts 0x00E9, r1 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
UECONX = (1<<EPEN);
|
|
6ec: 91 e0 ldi r25, 0x01 ; 1
|
|
6ee: 90 93 eb 00 sts 0x00EB, r25 ; 0x8000eb <__DATA_REGION_ORIGIN__+0x8b>
|
|
UECFG0X = type;
|
|
6f2: 10 92 ec 00 sts 0x00EC, r1 ; 0x8000ec <__DATA_REGION_ORIGIN__+0x8c>
|
|
UECFG1X = size;
|
|
6f6: 92 e3 ldi r25, 0x32 ; 50
|
|
6f8: 90 93 ed 00 sts 0x00ED, r25 ; 0x8000ed <__DATA_REGION_ORIGIN__+0x8d>
|
|
|
|
// End of Reset
|
|
if (udint & (1<<EORSTI))
|
|
{
|
|
InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // init ep0
|
|
_usbConfiguration = 0; // not configured yet
|
|
6fc: 10 92 94 01 sts 0x0194, r1 ; 0x800194 <_usbConfiguration>
|
|
UEIENX = 1 << RXSTPE; // Enable interrupts for ep0
|
|
700: 98 e0 ldi r25, 0x08 ; 8
|
|
702: 90 93 f0 00 sts 0x00F0, r25 ; 0x8000f0 <__DATA_REGION_ORIGIN__+0x90>
|
|
}
|
|
|
|
// Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
|
|
if (udint & (1<<SOFI))
|
|
706: 82 ff sbrs r24, 2
|
|
708: 22 c0 rjmp .+68 ; 0x74e <__vector_10+0x86>
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
70a: 93 e0 ldi r25, 0x03 ; 3
|
|
70c: 90 93 e9 00 sts 0x00E9, r25 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
}
|
|
|
|
static inline u8 FifoByteCount()
|
|
{
|
|
return UEBCLX;
|
|
710: 90 91 f2 00 lds r25, 0x00F2 ; 0x8000f2 <__DATA_REGION_ORIGIN__+0x92>
|
|
}
|
|
|
|
void USB_Flush(u8 ep)
|
|
{
|
|
SetEP(ep);
|
|
if (FifoByteCount())
|
|
714: 99 23 and r25, r25
|
|
716: 19 f0 breq .+6 ; 0x71e <__vector_10+0x56>
|
|
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
|
|
}
|
|
|
|
static inline void ReleaseTX()
|
|
{
|
|
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
|
|
718: 9a e3 ldi r25, 0x3A ; 58
|
|
71a: 90 93 e8 00 sts 0x00E8, r25 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
if (udint & (1<<SOFI))
|
|
{
|
|
USB_Flush(CDC_TX); // Send a tx frame if found
|
|
|
|
// check whether the one-shot period has elapsed. if so, turn off the LED
|
|
if (TxLEDPulse && !(--TxLEDPulse))
|
|
71e: 90 91 35 01 lds r25, 0x0135 ; 0x800135 <TxLEDPulse>
|
|
722: 99 23 and r25, r25
|
|
724: 41 f0 breq .+16 ; 0x736 <__vector_10+0x6e>
|
|
726: 90 91 35 01 lds r25, 0x0135 ; 0x800135 <TxLEDPulse>
|
|
72a: 91 50 subi r25, 0x01 ; 1
|
|
72c: 90 93 35 01 sts 0x0135, r25 ; 0x800135 <TxLEDPulse>
|
|
730: 91 11 cpse r25, r1
|
|
732: 01 c0 rjmp .+2 ; 0x736 <__vector_10+0x6e>
|
|
TXLED0;
|
|
734: 5d 9a sbi 0x0b, 5 ; 11
|
|
if (RxLEDPulse && !(--RxLEDPulse))
|
|
736: 90 91 93 01 lds r25, 0x0193 ; 0x800193 <RxLEDPulse>
|
|
73a: 99 23 and r25, r25
|
|
73c: 41 f0 breq .+16 ; 0x74e <__vector_10+0x86>
|
|
73e: 90 91 93 01 lds r25, 0x0193 ; 0x800193 <RxLEDPulse>
|
|
742: 91 50 subi r25, 0x01 ; 1
|
|
744: 90 93 93 01 sts 0x0193, r25 ; 0x800193 <RxLEDPulse>
|
|
748: 91 11 cpse r25, r1
|
|
74a: 01 c0 rjmp .+2 ; 0x74e <__vector_10+0x86>
|
|
RXLED0;
|
|
74c: 28 9a sbi 0x05, 0 ; 5
|
|
}
|
|
|
|
// the WAKEUPI interrupt is triggered as soon as there are non-idle patterns on the data
|
|
// lines. Thus, the WAKEUPI interrupt can occur even if the controller is not in the "suspend" mode.
|
|
// Therefore the we enable it only when USB is suspended
|
|
if (udint & (1<<WAKEUPI))
|
|
74e: 84 ff sbrs r24, 4
|
|
750: 18 c0 rjmp .+48 ; 0x782 <__vector_10+0xba>
|
|
{
|
|
UDIEN = (UDIEN & ~(1<<WAKEUPE)) | (1<<SUSPE); // Disable interrupts for WAKEUP and enable interrupts for SUSPEND
|
|
752: 80 91 e2 00 lds r24, 0x00E2 ; 0x8000e2 <__DATA_REGION_ORIGIN__+0x82>
|
|
756: 8e 7e andi r24, 0xEE ; 238
|
|
758: 81 60 ori r24, 0x01 ; 1
|
|
75a: 80 93 e2 00 sts 0x00E2, r24 ; 0x8000e2 <__DATA_REGION_ORIGIN__+0x82>
|
|
|
|
//TODO
|
|
// WAKEUPI shall be cleared by software (USB clock inputs must be enabled before).
|
|
//USB_ClockEnable();
|
|
UDINT &= ~(1<<WAKEUPI);
|
|
75e: 80 91 e1 00 lds r24, 0x00E1 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
762: 8f 7e andi r24, 0xEF ; 239
|
|
764: 80 93 e1 00 sts 0x00E1, r24 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
_usbSuspendState = (_usbSuspendState & ~(1<<SUSPI)) | (1<<WAKEUPI);
|
|
768: 80 91 36 01 lds r24, 0x0136 ; 0x800136 <_usbSuspendState>
|
|
76c: 8e 7e andi r24, 0xEE ; 238
|
|
76e: 80 61 ori r24, 0x10 ; 16
|
|
|
|
//TODO
|
|
//USB_ClockDisable();
|
|
|
|
UDINT &= ~((1<<WAKEUPI) | (1<<SUSPI)); // clear any already pending WAKEUP IRQs and the SUSPI request
|
|
_usbSuspendState = (_usbSuspendState & ~(1<<WAKEUPI)) | (1<<SUSPI);
|
|
770: 80 93 36 01 sts 0x0136, r24 ; 0x800136 <_usbSuspendState>
|
|
}
|
|
}
|
|
774: 9f 91 pop r25
|
|
776: 8f 91 pop r24
|
|
778: 0f 90 pop r0
|
|
77a: 0f be out 0x3f, r0 ; 63
|
|
77c: 0f 90 pop r0
|
|
77e: 1f 90 pop r1
|
|
780: 18 95 reti
|
|
// WAKEUPI shall be cleared by software (USB clock inputs must be enabled before).
|
|
//USB_ClockEnable();
|
|
UDINT &= ~(1<<WAKEUPI);
|
|
_usbSuspendState = (_usbSuspendState & ~(1<<SUSPI)) | (1<<WAKEUPI);
|
|
}
|
|
else if (udint & (1<<SUSPI)) // only one of the WAKEUPI / SUSPI bits can be active at time
|
|
782: 80 ff sbrs r24, 0
|
|
784: f7 cf rjmp .-18 ; 0x774 <__vector_10+0xac>
|
|
{
|
|
UDIEN = (UDIEN & ~(1<<SUSPE)) | (1<<WAKEUPE); // Disable interrupts for SUSPEND and enable interrupts for WAKEUP
|
|
786: 80 91 e2 00 lds r24, 0x00E2 ; 0x8000e2 <__DATA_REGION_ORIGIN__+0x82>
|
|
78a: 8e 7e andi r24, 0xEE ; 238
|
|
78c: 80 61 ori r24, 0x10 ; 16
|
|
78e: 80 93 e2 00 sts 0x00E2, r24 ; 0x8000e2 <__DATA_REGION_ORIGIN__+0x82>
|
|
|
|
//TODO
|
|
//USB_ClockDisable();
|
|
|
|
UDINT &= ~((1<<WAKEUPI) | (1<<SUSPI)); // clear any already pending WAKEUP IRQs and the SUSPI request
|
|
792: 80 91 e1 00 lds r24, 0x00E1 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
796: 8e 7e andi r24, 0xEE ; 238
|
|
798: 80 93 e1 00 sts 0x00E1, r24 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
_usbSuspendState = (_usbSuspendState & ~(1<<WAKEUPI)) | (1<<SUSPI);
|
|
79c: 80 91 36 01 lds r24, 0x0136 ; 0x800136 <_usbSuspendState>
|
|
7a0: 8e 7e andi r24, 0xEE ; 238
|
|
7a2: 81 60 ori r24, 0x01 ; 1
|
|
7a4: e5 cf rjmp .-54 ; 0x770 <__vector_10+0xa8>
|
|
|
|
000007a6 <__vector_11>:
|
|
return true;
|
|
}
|
|
|
|
// Endpoint 0 interrupt
|
|
ISR(USB_COM_vect)
|
|
{
|
|
7a6: 1f 92 push r1
|
|
7a8: 0f 92 push r0
|
|
7aa: 0f b6 in r0, 0x3f ; 63
|
|
7ac: 0f 92 push r0
|
|
7ae: 11 24 eor r1, r1
|
|
7b0: cf 92 push r12
|
|
7b2: df 92 push r13
|
|
7b4: ef 92 push r14
|
|
7b6: ff 92 push r15
|
|
7b8: 0f 93 push r16
|
|
7ba: 1f 93 push r17
|
|
7bc: 2f 93 push r18
|
|
7be: 3f 93 push r19
|
|
7c0: 4f 93 push r20
|
|
7c2: 5f 93 push r21
|
|
7c4: 6f 93 push r22
|
|
7c6: 7f 93 push r23
|
|
7c8: 8f 93 push r24
|
|
7ca: 9f 93 push r25
|
|
7cc: af 93 push r26
|
|
7ce: bf 93 push r27
|
|
7d0: ef 93 push r30
|
|
7d2: ff 93 push r31
|
|
7d4: cf 93 push r28
|
|
7d6: df 93 push r29
|
|
7d8: cd b7 in r28, 0x3d ; 61
|
|
7da: de b7 in r29, 0x3e ; 62
|
|
7dc: 6c 97 sbiw r28, 0x1c ; 28
|
|
7de: de bf out 0x3e, r29 ; 62
|
|
7e0: cd bf out 0x3d, r28 ; 61
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
7e2: 10 92 e9 00 sts 0x00E9, r1 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
return UEBCLX;
|
|
}
|
|
|
|
static inline u8 ReceivedSetupInt()
|
|
{
|
|
return UEINTX & (1<<RXSTPI);
|
|
7e6: 80 91 e8 00 lds r24, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
|
|
// Endpoint 0 interrupt
|
|
ISR(USB_COM_vect)
|
|
{
|
|
SetEP(0);
|
|
if (!ReceivedSetupInt())
|
|
7ea: 83 ff sbrs r24, 3
|
|
7ec: 25 c0 rjmp .+74 ; 0x838 <__vector_11+0x92>
|
|
return;
|
|
|
|
USBSetup setup;
|
|
Recv((u8*)&setup,8);
|
|
7ee: 68 e0 ldi r22, 0x08 ; 8
|
|
7f0: ce 01 movw r24, r28
|
|
7f2: 45 96 adiw r24, 0x15 ; 21
|
|
7f4: 0e 94 99 02 call 0x532 ; 0x532 <_ZL4RecvPVhh>
|
|
return UEINTX & (1<<RXSTPI);
|
|
}
|
|
|
|
static inline void ClearSetupInt()
|
|
{
|
|
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
|
|
7f8: 82 ef ldi r24, 0xF2 ; 242
|
|
7fa: 80 93 e8 00 sts 0x00E8, r24 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
|
|
USBSetup setup;
|
|
Recv((u8*)&setup,8);
|
|
ClearSetupInt();
|
|
|
|
u8 requestType = setup.bmRequestType;
|
|
7fe: 8d 89 ldd r24, Y+21 ; 0x15
|
|
if (requestType & REQUEST_DEVICETOHOST)
|
|
800: 87 ff sbrs r24, 7
|
|
802: 39 c0 rjmp .+114 ; 0x876 <__vector_11+0xd0>
|
|
volatile u8 _usbCurrentStatus = 0; // meaning of bits see usb_20.pdf, Figure 9-4. Information Returned by a GetStatus() Request to a Device
|
|
volatile u8 _usbSuspendState = 0; // copy of UDINT to check SUSPI and WAKEUPI bits
|
|
|
|
static inline void WaitIN(void)
|
|
{
|
|
while (!(UEINTX & (1<<TXINI)))
|
|
804: 90 91 e8 00 lds r25, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
808: 90 ff sbrs r25, 0
|
|
80a: fc cf rjmp .-8 ; 0x804 <__vector_11+0x5e>
|
|
WaitIN();
|
|
else
|
|
ClearIN();
|
|
|
|
bool ok = true;
|
|
if (REQUEST_STANDARD == (requestType & REQUEST_TYPE))
|
|
80c: 98 2f mov r25, r24
|
|
80e: 90 76 andi r25, 0x60 ; 96
|
|
810: 09 f0 breq .+2 ; 0x814 <__vector_11+0x6e>
|
|
812: 34 c1 rjmp .+616 ; 0xa7c <__vector_11+0x2d6>
|
|
{
|
|
// Standard Requests
|
|
u8 r = setup.bRequest;
|
|
814: 9e 89 ldd r25, Y+22 ; 0x16
|
|
816: 4f 89 ldd r20, Y+23 ; 0x17
|
|
818: 58 8d ldd r21, Y+24 ; 0x18
|
|
u16 wValue = setup.wValueL | (setup.wValueH << 8);
|
|
81a: 2f 89 ldd r18, Y+23 ; 0x17
|
|
81c: f8 8c ldd r15, Y+24 ; 0x18
|
|
if (GET_STATUS == r)
|
|
81e: 91 11 cpse r25, r1
|
|
820: 31 c0 rjmp .+98 ; 0x884 <__vector_11+0xde>
|
|
{
|
|
if (requestType == (REQUEST_DEVICETOHOST | REQUEST_STANDARD | REQUEST_DEVICE))
|
|
822: 80 38 cpi r24, 0x80 ; 128
|
|
824: 61 f5 brne .+88 ; 0x87e <__vector_11+0xd8>
|
|
{
|
|
Send8(_usbCurrentStatus);
|
|
826: 80 91 34 01 lds r24, 0x0134 ; 0x800134 <_usbCurrentStatus>
|
|
return UEDATX;
|
|
}
|
|
|
|
static inline void Send8(u8 d)
|
|
{
|
|
UEDATX = d;
|
|
82a: 80 93 f1 00 sts 0x00F1, r24 ; 0x8000f1 <__DATA_REGION_ORIGIN__+0x91>
|
|
82e: 10 92 f1 00 sts 0x00F1, r1 ; 0x8000f1 <__DATA_REGION_ORIGIN__+0x91>
|
|
;
|
|
}
|
|
|
|
static inline void ClearIN(void)
|
|
{
|
|
UEINTX = ~(1<<TXINI);
|
|
832: 8e ef ldi r24, 0xFE ; 254
|
|
834: 80 93 e8 00 sts 0x00E8, r24 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
ClearIN();
|
|
else
|
|
{
|
|
Stall();
|
|
}
|
|
}
|
|
838: 6c 96 adiw r28, 0x1c ; 28
|
|
83a: 0f b6 in r0, 0x3f ; 63
|
|
83c: f8 94 cli
|
|
83e: de bf out 0x3e, r29 ; 62
|
|
840: 0f be out 0x3f, r0 ; 63
|
|
842: cd bf out 0x3d, r28 ; 61
|
|
844: df 91 pop r29
|
|
846: cf 91 pop r28
|
|
848: ff 91 pop r31
|
|
84a: ef 91 pop r30
|
|
84c: bf 91 pop r27
|
|
84e: af 91 pop r26
|
|
850: 9f 91 pop r25
|
|
852: 8f 91 pop r24
|
|
854: 7f 91 pop r23
|
|
856: 6f 91 pop r22
|
|
858: 5f 91 pop r21
|
|
85a: 4f 91 pop r20
|
|
85c: 3f 91 pop r19
|
|
85e: 2f 91 pop r18
|
|
860: 1f 91 pop r17
|
|
862: 0f 91 pop r16
|
|
864: ff 90 pop r15
|
|
866: ef 90 pop r14
|
|
868: df 90 pop r13
|
|
86a: cf 90 pop r12
|
|
86c: 0f 90 pop r0
|
|
86e: 0f be out 0x3f, r0 ; 63
|
|
870: 0f 90 pop r0
|
|
872: 1f 90 pop r1
|
|
874: 18 95 reti
|
|
;
|
|
}
|
|
|
|
static inline void ClearIN(void)
|
|
{
|
|
UEINTX = ~(1<<TXINI);
|
|
876: 9e ef ldi r25, 0xFE ; 254
|
|
878: 90 93 e8 00 sts 0x00E8, r25 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
87c: c7 cf rjmp .-114 ; 0x80c <__vector_11+0x66>
|
|
return UEDATX;
|
|
}
|
|
|
|
static inline void Send8(u8 d)
|
|
{
|
|
UEDATX = d;
|
|
87e: 10 92 f1 00 sts 0x00F1, r1 ; 0x8000f1 <__DATA_REGION_ORIGIN__+0x91>
|
|
882: d5 cf rjmp .-86 ; 0x82e <__vector_11+0x88>
|
|
// see "Figure 9-6. Information Returned by a GetStatus() Request to an Endpoint" in usb_20.pdf for more information
|
|
Send8(0);
|
|
Send8(0);
|
|
}
|
|
}
|
|
else if (CLEAR_FEATURE == r)
|
|
884: 91 30 cpi r25, 0x01 ; 1
|
|
886: 59 f4 brne .+22 ; 0x89e <__vector_11+0xf8>
|
|
{
|
|
if((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE))
|
|
888: 81 11 cpse r24, r1
|
|
88a: d3 cf rjmp .-90 ; 0x832 <__vector_11+0x8c>
|
|
&& (wValue == DEVICE_REMOTE_WAKEUP))
|
|
88c: 41 30 cpi r20, 0x01 ; 1
|
|
88e: 51 05 cpc r21, r1
|
|
890: 81 f6 brne .-96 ; 0x832 <__vector_11+0x8c>
|
|
{
|
|
_usbCurrentStatus &= ~FEATURE_REMOTE_WAKEUP_ENABLED;
|
|
892: 80 91 34 01 lds r24, 0x0134 ; 0x800134 <_usbCurrentStatus>
|
|
896: 8d 7f andi r24, 0xFD ; 253
|
|
else if (SET_FEATURE == r)
|
|
{
|
|
if((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE))
|
|
&& (wValue == DEVICE_REMOTE_WAKEUP))
|
|
{
|
|
_usbCurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
|
|
898: 80 93 34 01 sts 0x0134, r24 ; 0x800134 <_usbCurrentStatus>
|
|
89c: ca cf rjmp .-108 ; 0x832 <__vector_11+0x8c>
|
|
&& (wValue == DEVICE_REMOTE_WAKEUP))
|
|
{
|
|
_usbCurrentStatus &= ~FEATURE_REMOTE_WAKEUP_ENABLED;
|
|
}
|
|
}
|
|
else if (SET_FEATURE == r)
|
|
89e: 93 30 cpi r25, 0x03 ; 3
|
|
8a0: 49 f4 brne .+18 ; 0x8b4 <__vector_11+0x10e>
|
|
{
|
|
if((requestType == (REQUEST_HOSTTODEVICE | REQUEST_STANDARD | REQUEST_DEVICE))
|
|
8a2: 81 11 cpse r24, r1
|
|
8a4: c6 cf rjmp .-116 ; 0x832 <__vector_11+0x8c>
|
|
&& (wValue == DEVICE_REMOTE_WAKEUP))
|
|
8a6: 41 30 cpi r20, 0x01 ; 1
|
|
8a8: 51 05 cpc r21, r1
|
|
8aa: 19 f6 brne .-122 ; 0x832 <__vector_11+0x8c>
|
|
{
|
|
_usbCurrentStatus |= FEATURE_REMOTE_WAKEUP_ENABLED;
|
|
8ac: 80 91 34 01 lds r24, 0x0134 ; 0x800134 <_usbCurrentStatus>
|
|
8b0: 82 60 ori r24, 0x02 ; 2
|
|
8b2: f2 cf rjmp .-28 ; 0x898 <__vector_11+0xf2>
|
|
}
|
|
}
|
|
else if (SET_ADDRESS == r)
|
|
8b4: 95 30 cpi r25, 0x05 ; 5
|
|
8b6: 41 f4 brne .+16 ; 0x8c8 <__vector_11+0x122>
|
|
volatile u8 _usbCurrentStatus = 0; // meaning of bits see usb_20.pdf, Figure 9-4. Information Returned by a GetStatus() Request to a Device
|
|
volatile u8 _usbSuspendState = 0; // copy of UDINT to check SUSPI and WAKEUPI bits
|
|
|
|
static inline void WaitIN(void)
|
|
{
|
|
while (!(UEINTX & (1<<TXINI)))
|
|
8b8: 80 91 e8 00 lds r24, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
8bc: 80 ff sbrs r24, 0
|
|
8be: fc cf rjmp .-8 ; 0x8b8 <__vector_11+0x112>
|
|
}
|
|
}
|
|
else if (SET_ADDRESS == r)
|
|
{
|
|
WaitIN();
|
|
UDADDR = setup.wValueL | (1<<ADDEN);
|
|
8c0: 20 68 ori r18, 0x80 ; 128
|
|
8c2: 20 93 e3 00 sts 0x00E3, r18 ; 0x8000e3 <__DATA_REGION_ORIGIN__+0x83>
|
|
8c6: b5 cf rjmp .-150 ; 0x832 <__vector_11+0x8c>
|
|
}
|
|
else if (GET_DESCRIPTOR == r)
|
|
8c8: 96 30 cpi r25, 0x06 ; 6
|
|
8ca: 09 f0 breq .+2 ; 0x8ce <__vector_11+0x128>
|
|
8cc: a9 c0 rjmp .+338 ; 0xa20 <__vector_11+0x27a>
|
|
8ce: 0b 8d ldd r16, Y+27 ; 0x1b
|
|
8d0: 1c 8d ldd r17, Y+28 ; 0x1c
|
|
|
|
static
|
|
bool SendDescriptor(USBSetup& setup)
|
|
{
|
|
u8 t = setup.wValueH;
|
|
if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
|
|
8d2: 22 e0 ldi r18, 0x02 ; 2
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
8d4: 10 92 e9 00 sts 0x00E9, r1 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
static int _cmark;
|
|
static int _cend;
|
|
void InitControl(int end)
|
|
{
|
|
SetEP(0);
|
|
_cmark = 0;
|
|
8d8: 10 92 32 01 sts 0x0132, r1 ; 0x800132 <_ZL6_cmark+0x1>
|
|
8dc: 10 92 31 01 sts 0x0131, r1 ; 0x800131 <_ZL6_cmark>
|
|
|
|
static
|
|
bool SendDescriptor(USBSetup& setup)
|
|
{
|
|
u8 t = setup.wValueH;
|
|
if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
|
|
8e0: f2 12 cpse r15, r18
|
|
8e2: 2e c0 rjmp .+92 ; 0x940 <__vector_11+0x19a>
|
|
static int _cend;
|
|
void InitControl(int end)
|
|
{
|
|
SetEP(0);
|
|
_cmark = 0;
|
|
_cend = end;
|
|
8e4: 10 92 30 01 sts 0x0130, r1 ; 0x800130 <_ZL5_cend+0x1>
|
|
8e8: 10 92 2f 01 sts 0x012F, r1 ; 0x80012f <_ZL5_cend>
|
|
static
|
|
bool SendConfiguration(int maxlen)
|
|
{
|
|
// Count and measure interfaces
|
|
InitControl(0);
|
|
u8 interfaces = SendInterfaces();
|
|
8ec: 0e 94 68 02 call 0x4d0 ; 0x4d0 <_ZL14SendInterfacesv>
|
|
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
|
|
8f0: 1f 82 std Y+7, r1 ; 0x07
|
|
8f2: 99 e0 ldi r25, 0x09 ; 9
|
|
8f4: 99 83 std Y+1, r25 ; 0x01
|
|
8f6: fa 82 std Y+2, r15 ; 0x02
|
|
8f8: 91 e0 ldi r25, 0x01 ; 1
|
|
8fa: 9e 83 std Y+6, r25 ; 0x06
|
|
8fc: 90 ea ldi r25, 0xA0 ; 160
|
|
8fe: 98 87 std Y+8, r25 ; 0x08
|
|
900: 9a ef ldi r25, 0xFA ; 250
|
|
902: 99 87 std Y+9, r25 ; 0x09
|
|
904: 20 91 31 01 lds r18, 0x0131 ; 0x800131 <_ZL6_cmark>
|
|
908: 30 91 32 01 lds r19, 0x0132 ; 0x800132 <_ZL6_cmark+0x1>
|
|
90c: 27 5f subi r18, 0xF7 ; 247
|
|
90e: 3f 4f sbci r19, 0xFF ; 255
|
|
910: 3c 83 std Y+4, r19 ; 0x04
|
|
912: 2b 83 std Y+3, r18 ; 0x03
|
|
914: 8d 83 std Y+5, r24 ; 0x05
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
916: 10 92 e9 00 sts 0x00E9, r1 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
static int _cmark;
|
|
static int _cend;
|
|
void InitControl(int end)
|
|
{
|
|
SetEP(0);
|
|
_cmark = 0;
|
|
91a: 10 92 32 01 sts 0x0132, r1 ; 0x800132 <_ZL6_cmark+0x1>
|
|
91e: 10 92 31 01 sts 0x0131, r1 ; 0x800131 <_ZL6_cmark>
|
|
_cend = end;
|
|
922: 10 93 30 01 sts 0x0130, r17 ; 0x800130 <_ZL5_cend+0x1>
|
|
926: 00 93 2f 01 sts 0x012F, r16 ; 0x80012f <_ZL5_cend>
|
|
u8 interfaces = SendInterfaces();
|
|
ConfigDescriptor config = D_CONFIG(_cmark + sizeof(ConfigDescriptor),interfaces);
|
|
|
|
// Now send them
|
|
InitControl(maxlen);
|
|
USB_SendControl(0,&config,sizeof(ConfigDescriptor));
|
|
92a: 49 e0 ldi r20, 0x09 ; 9
|
|
92c: 50 e0 ldi r21, 0x00 ; 0
|
|
92e: be 01 movw r22, r28
|
|
930: 6f 5f subi r22, 0xFF ; 255
|
|
932: 7f 4f sbci r23, 0xFF ; 255
|
|
934: 80 e0 ldi r24, 0x00 ; 0
|
|
936: 0e 94 42 02 call 0x484 ; 0x484 <_Z15USB_SendControlhPKvi>
|
|
SendInterfaces();
|
|
93a: 0e 94 68 02 call 0x4d0 ; 0x4d0 <_ZL14SendInterfacesv>
|
|
93e: 79 cf rjmp .-270 ; 0x832 <__vector_11+0x8c>
|
|
static int _cend;
|
|
void InitControl(int end)
|
|
{
|
|
SetEP(0);
|
|
_cmark = 0;
|
|
_cend = end;
|
|
940: 10 93 30 01 sts 0x0130, r17 ; 0x800130 <_ZL5_cend+0x1>
|
|
944: 00 93 2f 01 sts 0x012F, r16 ; 0x80012f <_ZL5_cend>
|
|
if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
|
|
return SendConfiguration(setup.wLength);
|
|
|
|
InitControl(setup.wLength);
|
|
#ifdef PLUGGABLE_USB_ENABLED
|
|
int ret = PluggableUSB().getDescriptor(setup);
|
|
948: 0e 94 4c 01 call 0x298 ; 0x298 <_Z12PluggableUSBv>
|
|
}
|
|
|
|
int PluggableUSB_::getDescriptor(USBSetup& setup)
|
|
{
|
|
PluggableUSBModule* node;
|
|
for (node = rootNode; node; node = node->next) {
|
|
94c: dc 01 movw r26, r24
|
|
94e: 12 96 adiw r26, 0x02 ; 2
|
|
950: 0d 91 ld r16, X+
|
|
952: 1c 91 ld r17, X
|
|
954: 01 15 cp r16, r1
|
|
956: 11 05 cpc r17, r1
|
|
958: 09 f4 brne .+2 ; 0x95c <__vector_11+0x1b6>
|
|
95a: 51 c1 rjmp .+674 ; 0xbfe <__stack+0xff>
|
|
int ret = node->getDescriptor(setup);
|
|
95c: d8 01 movw r26, r16
|
|
95e: ed 91 ld r30, X+
|
|
960: fc 91 ld r31, X
|
|
962: 04 80 ldd r0, Z+4 ; 0x04
|
|
964: f5 81 ldd r31, Z+5 ; 0x05
|
|
966: e0 2d mov r30, r0
|
|
968: be 01 movw r22, r28
|
|
96a: 6b 5e subi r22, 0xEB ; 235
|
|
96c: 7f 4f sbci r23, 0xFF ; 255
|
|
96e: c8 01 movw r24, r16
|
|
970: 09 95 icall
|
|
// ret!=0 -> request has been processed
|
|
if (ret)
|
|
972: 00 97 sbiw r24, 0x00 ; 0
|
|
974: 09 f0 breq .+2 ; 0x978 <__vector_11+0x1d2>
|
|
976: 3e c1 rjmp .+636 ; 0xbf4 <__stack+0xf5>
|
|
}
|
|
|
|
int PluggableUSB_::getDescriptor(USBSetup& setup)
|
|
{
|
|
PluggableUSBModule* node;
|
|
for (node = rootNode; node; node = node->next) {
|
|
978: f8 01 movw r30, r16
|
|
97a: 00 85 ldd r16, Z+8 ; 0x08
|
|
97c: 11 85 ldd r17, Z+9 ; 0x09
|
|
97e: ea cf rjmp .-44 ; 0x954 <__vector_11+0x1ae>
|
|
const u8* desc_addr = 0;
|
|
if (USB_DEVICE_DESCRIPTOR_TYPE == t)
|
|
{
|
|
desc_addr = (const u8*)&USB_DeviceDescriptorIAD;
|
|
}
|
|
else if (USB_STRING_DESCRIPTOR_TYPE == t)
|
|
980: f3 e0 ldi r31, 0x03 ; 3
|
|
982: ff 12 cpse r15, r31
|
|
984: 0e c0 rjmp .+28 ; 0x9a2 <__vector_11+0x1fc>
|
|
{
|
|
if (setup.wValueL == 0) {
|
|
986: 8f 89 ldd r24, Y+23 ; 0x17
|
|
988: 88 23 and r24, r24
|
|
98a: 09 f4 brne .+2 ; 0x98e <__vector_11+0x1e8>
|
|
98c: 40 c0 rjmp .+128 ; 0xa0e <__vector_11+0x268>
|
|
desc_addr = (const u8*)&STRING_LANGUAGE;
|
|
}
|
|
else if (setup.wValueL == IPRODUCT) {
|
|
98e: 82 30 cpi r24, 0x02 ; 2
|
|
990: 61 f4 brne .+24 ; 0x9aa <__vector_11+0x204>
|
|
return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT), TRANSFER_PGM);
|
|
992: 40 e8 ldi r20, 0x80 ; 128
|
|
994: 60 e1 ldi r22, 0x10 ; 16
|
|
996: 80 e1 ldi r24, 0x10 ; 16
|
|
998: 91 e0 ldi r25, 0x01 ; 1
|
|
}
|
|
else if (setup.wValueL == ISERIAL) {
|
|
#ifdef PLUGGABLE_USB_ENABLED
|
|
char name[ISERIAL_MAX_LEN];
|
|
PluggableUSB().getShortName(name);
|
|
return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0);
|
|
99a: 0e 94 0f 02 call 0x41e ; 0x41e <_ZL24USB_SendStringDescriptorPKhhh>
|
|
{
|
|
InitControl(setup.wLength); // Max length of transfer
|
|
ok = ClassInterfaceRequest(setup);
|
|
}
|
|
|
|
if (ok)
|
|
99e: 81 11 cpse r24, r1
|
|
9a0: 48 cf rjmp .-368 ; 0x832 <__vector_11+0x8c>
|
|
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
|
|
}
|
|
|
|
static inline void Stall()
|
|
{
|
|
UECONX = (1<<STALLRQ) | (1<<EPEN);
|
|
9a2: 81 e2 ldi r24, 0x21 ; 33
|
|
9a4: 80 93 eb 00 sts 0x00EB, r24 ; 0x8000eb <__DATA_REGION_ORIGIN__+0x8b>
|
|
9a8: 47 cf rjmp .-370 ; 0x838 <__vector_11+0x92>
|
|
desc_addr = (const u8*)&STRING_LANGUAGE;
|
|
}
|
|
else if (setup.wValueL == IPRODUCT) {
|
|
return USB_SendStringDescriptor(STRING_PRODUCT, strlen(USB_PRODUCT), TRANSFER_PGM);
|
|
}
|
|
else if (setup.wValueL == IMANUFACTURER) {
|
|
9aa: 81 30 cpi r24, 0x01 ; 1
|
|
9ac: 29 f4 brne .+10 ; 0x9b8 <__vector_11+0x212>
|
|
return USB_SendStringDescriptor(STRING_MANUFACTURER, strlen(USB_MANUFACTURER), TRANSFER_PGM);
|
|
9ae: 40 e8 ldi r20, 0x80 ; 128
|
|
9b0: 6b e0 ldi r22, 0x0B ; 11
|
|
9b2: 84 e0 ldi r24, 0x04 ; 4
|
|
9b4: 91 e0 ldi r25, 0x01 ; 1
|
|
9b6: f1 cf rjmp .-30 ; 0x99a <__vector_11+0x1f4>
|
|
}
|
|
else if (setup.wValueL == ISERIAL) {
|
|
9b8: 83 30 cpi r24, 0x03 ; 3
|
|
9ba: 99 f7 brne .-26 ; 0x9a2 <__vector_11+0x1fc>
|
|
#ifdef PLUGGABLE_USB_ENABLED
|
|
char name[ISERIAL_MAX_LEN];
|
|
PluggableUSB().getShortName(name);
|
|
9bc: 0e 94 4c 01 call 0x298 ; 0x298 <_Z12PluggableUSBv>
|
|
}
|
|
|
|
void PluggableUSB_::getShortName(char *iSerialNum)
|
|
{
|
|
PluggableUSBModule* node;
|
|
for (node = rootNode; node; node = node->next) {
|
|
9c0: dc 01 movw r26, r24
|
|
9c2: 12 96 adiw r26, 0x02 ; 2
|
|
9c4: ed 90 ld r14, X+
|
|
9c6: fc 90 ld r15, X
|
|
9c8: 8e 01 movw r16, r28
|
|
9ca: 0f 5f subi r16, 0xFF ; 255
|
|
9cc: 1f 4f sbci r17, 0xFF ; 255
|
|
9ce: 68 01 movw r12, r16
|
|
9d0: e1 14 cp r14, r1
|
|
9d2: f1 04 cpc r15, r1
|
|
9d4: 79 f0 breq .+30 ; 0x9f4 <__vector_11+0x24e>
|
|
iSerialNum += node->getShortName(iSerialNum);
|
|
9d6: d7 01 movw r26, r14
|
|
9d8: ed 91 ld r30, X+
|
|
9da: fc 91 ld r31, X
|
|
9dc: 06 80 ldd r0, Z+6 ; 0x06
|
|
9de: f7 81 ldd r31, Z+7 ; 0x07
|
|
9e0: e0 2d mov r30, r0
|
|
9e2: b8 01 movw r22, r16
|
|
9e4: c7 01 movw r24, r14
|
|
9e6: 09 95 icall
|
|
9e8: 08 0f add r16, r24
|
|
9ea: 11 1d adc r17, r1
|
|
}
|
|
|
|
void PluggableUSB_::getShortName(char *iSerialNum)
|
|
{
|
|
PluggableUSBModule* node;
|
|
for (node = rootNode; node; node = node->next) {
|
|
9ec: f7 01 movw r30, r14
|
|
9ee: e0 84 ldd r14, Z+8 ; 0x08
|
|
9f0: f1 84 ldd r15, Z+9 ; 0x09
|
|
9f2: ee cf rjmp .-36 ; 0x9d0 <__vector_11+0x22a>
|
|
iSerialNum += node->getShortName(iSerialNum);
|
|
}
|
|
*iSerialNum = 0;
|
|
9f4: d8 01 movw r26, r16
|
|
9f6: 1c 92 st X, r1
|
|
return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0);
|
|
9f8: f6 01 movw r30, r12
|
|
9fa: 01 90 ld r0, Z+
|
|
9fc: 00 20 and r0, r0
|
|
9fe: e9 f7 brne .-6 ; 0x9fa <__vector_11+0x254>
|
|
a00: 31 97 sbiw r30, 0x01 ; 1
|
|
a02: bf 01 movw r22, r30
|
|
a04: 6c 19 sub r22, r12
|
|
a06: 7d 09 sbc r23, r13
|
|
a08: 40 e0 ldi r20, 0x00 ; 0
|
|
a0a: c6 01 movw r24, r12
|
|
a0c: c6 cf rjmp .-116 ; 0x99a <__vector_11+0x1f4>
|
|
desc_addr = (const u8*)&USB_DeviceDescriptorIAD;
|
|
}
|
|
else if (USB_STRING_DESCRIPTOR_TYPE == t)
|
|
{
|
|
if (setup.wValueL == 0) {
|
|
desc_addr = (const u8*)&STRING_LANGUAGE;
|
|
a0e: 6e ee ldi r22, 0xEE ; 238
|
|
a10: 70 e0 ldi r23, 0x00 ; 0
|
|
return false;
|
|
}
|
|
|
|
if (desc_addr == 0)
|
|
return false;
|
|
u8 desc_length = pgm_read_byte(desc_addr);
|
|
a12: fb 01 movw r30, r22
|
|
a14: 44 91 lpm r20, Z
|
|
|
|
USB_SendControl(TRANSFER_PGM,desc_addr,desc_length);
|
|
a16: 50 e0 ldi r21, 0x00 ; 0
|
|
a18: 80 e8 ldi r24, 0x80 ; 128
|
|
|
|
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
|
|
{
|
|
if (CDC_GET_LINE_CODING == r)
|
|
{
|
|
USB_SendControl(0,(void*)&_usbLineInfo,7);
|
|
a1a: 0e 94 42 02 call 0x484 ; 0x484 <_Z15USB_SendControlhPKvi>
|
|
a1e: 09 cf rjmp .-494 ; 0x832 <__vector_11+0x8c>
|
|
}
|
|
else if (GET_DESCRIPTOR == r)
|
|
{
|
|
ok = SendDescriptor(setup);
|
|
}
|
|
else if (SET_DESCRIPTOR == r)
|
|
a20: 97 30 cpi r25, 0x07 ; 7
|
|
a22: 09 f4 brne .+2 ; 0xa26 <__vector_11+0x280>
|
|
a24: be cf rjmp .-132 ; 0x9a2 <__vector_11+0x1fc>
|
|
{
|
|
ok = false;
|
|
}
|
|
else if (GET_CONFIGURATION == r)
|
|
a26: 98 30 cpi r25, 0x08 ; 8
|
|
a28: 21 f4 brne .+8 ; 0xa32 <__vector_11+0x28c>
|
|
return UEDATX;
|
|
}
|
|
|
|
static inline void Send8(u8 d)
|
|
{
|
|
UEDATX = d;
|
|
a2a: 81 e0 ldi r24, 0x01 ; 1
|
|
a2c: 80 93 f1 00 sts 0x00F1, r24 ; 0x8000f1 <__DATA_REGION_ORIGIN__+0x91>
|
|
a30: 00 cf rjmp .-512 ; 0x832 <__vector_11+0x8c>
|
|
}
|
|
else if (GET_CONFIGURATION == r)
|
|
{
|
|
Send8(1);
|
|
}
|
|
else if (SET_CONFIGURATION == r)
|
|
a32: 99 30 cpi r25, 0x09 ; 9
|
|
a34: 09 f0 breq .+2 ; 0xa38 <__vector_11+0x292>
|
|
a36: fd ce rjmp .-518 ; 0x832 <__vector_11+0x8c>
|
|
{
|
|
if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT))
|
|
a38: 83 70 andi r24, 0x03 ; 3
|
|
a3a: 09 f0 breq .+2 ; 0xa3e <__vector_11+0x298>
|
|
a3c: b2 cf rjmp .-156 ; 0x9a2 <__vector_11+0x1fc>
|
|
a3e: ed e0 ldi r30, 0x0D ; 13
|
|
a40: f1 e0 ldi r31, 0x01 ; 1
|
|
}
|
|
|
|
static
|
|
void InitEndpoints()
|
|
{
|
|
for (u8 i = 1; i < sizeof(_initEndpoints) && _initEndpoints[i] != 0; i++)
|
|
a42: 81 e0 ldi r24, 0x01 ; 1
|
|
{
|
|
UENUM = i;
|
|
UECONX = (1<<EPEN);
|
|
a44: 31 e0 ldi r19, 0x01 ; 1
|
|
UECFG0X = _initEndpoints[i];
|
|
#if USB_EP_SIZE == 16
|
|
UECFG1X = EP_SINGLE_16;
|
|
#elif USB_EP_SIZE == 64
|
|
UECFG1X = EP_DOUBLE_64;
|
|
a46: 96 e3 ldi r25, 0x36 ; 54
|
|
}
|
|
|
|
static
|
|
void InitEndpoints()
|
|
{
|
|
for (u8 i = 1; i < sizeof(_initEndpoints) && _initEndpoints[i] != 0; i++)
|
|
a48: 21 91 ld r18, Z+
|
|
a4a: 22 23 and r18, r18
|
|
a4c: 71 f0 breq .+28 ; 0xa6a <__vector_11+0x2c4>
|
|
{
|
|
UENUM = i;
|
|
a4e: 80 93 e9 00 sts 0x00E9, r24 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
UECONX = (1<<EPEN);
|
|
a52: 30 93 eb 00 sts 0x00EB, r19 ; 0x8000eb <__DATA_REGION_ORIGIN__+0x8b>
|
|
UECFG0X = _initEndpoints[i];
|
|
a56: df 01 movw r26, r30
|
|
a58: 11 97 sbiw r26, 0x01 ; 1
|
|
a5a: 2c 91 ld r18, X
|
|
a5c: 20 93 ec 00 sts 0x00EC, r18 ; 0x8000ec <__DATA_REGION_ORIGIN__+0x8c>
|
|
#if USB_EP_SIZE == 16
|
|
UECFG1X = EP_SINGLE_16;
|
|
#elif USB_EP_SIZE == 64
|
|
UECFG1X = EP_DOUBLE_64;
|
|
a60: 90 93 ed 00 sts 0x00ED, r25 ; 0x8000ed <__DATA_REGION_ORIGIN__+0x8d>
|
|
}
|
|
|
|
static
|
|
void InitEndpoints()
|
|
{
|
|
for (u8 i = 1; i < sizeof(_initEndpoints) && _initEndpoints[i] != 0; i++)
|
|
a64: 8f 5f subi r24, 0xFF ; 255
|
|
a66: 87 30 cpi r24, 0x07 ; 7
|
|
a68: 79 f7 brne .-34 ; 0xa48 <__vector_11+0x2a2>
|
|
UECFG1X = EP_DOUBLE_64;
|
|
#else
|
|
#error Unsupported value for USB_EP_SIZE
|
|
#endif
|
|
}
|
|
UERST = 0x7E; // And reset them
|
|
a6a: 8e e7 ldi r24, 0x7E ; 126
|
|
a6c: 80 93 ea 00 sts 0x00EA, r24 ; 0x8000ea <__DATA_REGION_ORIGIN__+0x8a>
|
|
UERST = 0;
|
|
a70: 10 92 ea 00 sts 0x00EA, r1 ; 0x8000ea <__DATA_REGION_ORIGIN__+0x8a>
|
|
else if (SET_CONFIGURATION == r)
|
|
{
|
|
if (REQUEST_DEVICE == (requestType & REQUEST_RECIPIENT))
|
|
{
|
|
InitEndpoints();
|
|
_usbConfiguration = setup.wValueL;
|
|
a74: 8f 89 ldd r24, Y+23 ; 0x17
|
|
a76: 80 93 94 01 sts 0x0194, r24 ; 0x800194 <_usbConfiguration>
|
|
a7a: db ce rjmp .-586 ; 0x832 <__vector_11+0x8c>
|
|
{
|
|
}
|
|
}
|
|
else
|
|
{
|
|
InitControl(setup.wLength); // Max length of transfer
|
|
a7c: 8b 8d ldd r24, Y+27 ; 0x1b
|
|
a7e: 9c 8d ldd r25, Y+28 ; 0x1c
|
|
UEDATX = d;
|
|
}
|
|
|
|
static inline void SetEP(u8 ep)
|
|
{
|
|
UENUM = ep;
|
|
a80: 10 92 e9 00 sts 0x00E9, r1 ; 0x8000e9 <__DATA_REGION_ORIGIN__+0x89>
|
|
static int _cmark;
|
|
static int _cend;
|
|
void InitControl(int end)
|
|
{
|
|
SetEP(0);
|
|
_cmark = 0;
|
|
a84: 10 92 32 01 sts 0x0132, r1 ; 0x800132 <_ZL6_cmark+0x1>
|
|
a88: 10 92 31 01 sts 0x0131, r1 ; 0x800131 <_ZL6_cmark>
|
|
_cend = end;
|
|
a8c: 90 93 30 01 sts 0x0130, r25 ; 0x800130 <_ZL5_cend+0x1>
|
|
a90: 80 93 2f 01 sts 0x012F, r24 ; 0x80012f <_ZL5_cend>
|
|
bool ClassInterfaceRequest(USBSetup& setup)
|
|
{
|
|
#ifdef CDC_ENABLED
|
|
u8 i = setup.wIndex;
|
|
|
|
if (CDC_ACM_INTERFACE == i)
|
|
a94: 89 8d ldd r24, Y+25 ; 0x19
|
|
a96: 81 11 cpse r24, r1
|
|
a98: 92 c0 rjmp .+292 ; 0xbbe <__stack+0xbf>
|
|
return USB_SendControl(TRANSFER_PGM,&_cdcInterface,sizeof(_cdcInterface));
|
|
}
|
|
|
|
bool CDC_Setup(USBSetup& setup)
|
|
{
|
|
u8 r = setup.bRequest;
|
|
a9a: 8e 89 ldd r24, Y+22 ; 0x16
|
|
u8 requestType = setup.bmRequestType;
|
|
a9c: 9d 89 ldd r25, Y+21 ; 0x15
|
|
|
|
if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)
|
|
a9e: 91 3a cpi r25, 0xA1 ; 161
|
|
aa0: 49 f4 brne .+18 ; 0xab4 <__vector_11+0x30e>
|
|
{
|
|
if (CDC_GET_LINE_CODING == r)
|
|
aa2: 81 32 cpi r24, 0x21 ; 33
|
|
aa4: 09 f0 breq .+2 ; 0xaa8 <__vector_11+0x302>
|
|
aa6: 7d cf rjmp .-262 ; 0x9a2 <__vector_11+0x1fc>
|
|
{
|
|
USB_SendControl(0,(void*)&_usbLineInfo,7);
|
|
aa8: 47 e0 ldi r20, 0x07 ; 7
|
|
aaa: 50 e0 ldi r21, 0x00 ; 0
|
|
aac: 64 e0 ldi r22, 0x04 ; 4
|
|
aae: 71 e0 ldi r23, 0x01 ; 1
|
|
ab0: 80 e0 ldi r24, 0x00 ; 0
|
|
ab2: b3 cf rjmp .-154 ; 0xa1a <__vector_11+0x274>
|
|
return true;
|
|
}
|
|
}
|
|
|
|
if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)
|
|
ab4: 91 32 cpi r25, 0x21 ; 33
|
|
ab6: 09 f0 breq .+2 ; 0xaba <__vector_11+0x314>
|
|
ab8: 74 cf rjmp .-280 ; 0x9a2 <__vector_11+0x1fc>
|
|
{
|
|
if (CDC_SEND_BREAK == r)
|
|
aba: 83 32 cpi r24, 0x23 ; 35
|
|
abc: 69 f4 brne .+26 ; 0xad8 <__vector_11+0x332>
|
|
{
|
|
breakValue = ((uint16_t)setup.wValueH << 8) | setup.wValueL;
|
|
abe: 8f 89 ldd r24, Y+23 ; 0x17
|
|
ac0: 98 8d ldd r25, Y+24 ; 0x18
|
|
ac2: b0 e0 ldi r27, 0x00 ; 0
|
|
ac4: a0 e0 ldi r26, 0x00 ; 0
|
|
ac6: 80 93 00 01 sts 0x0100, r24 ; 0x800100 <__data_start>
|
|
aca: 90 93 01 01 sts 0x0101, r25 ; 0x800101 <__data_start+0x1>
|
|
ace: a0 93 02 01 sts 0x0102, r26 ; 0x800102 <__data_start+0x2>
|
|
ad2: b0 93 03 01 sts 0x0103, r27 ; 0x800103 <__data_start+0x3>
|
|
ad6: ad ce rjmp .-678 ; 0x832 <__vector_11+0x8c>
|
|
}
|
|
|
|
if (CDC_SET_LINE_CODING == r)
|
|
ad8: 80 32 cpi r24, 0x20 ; 32
|
|
ada: 69 f4 brne .+26 ; 0xaf6 <__vector_11+0x350>
|
|
UEINTX = ~(1<<TXINI);
|
|
}
|
|
|
|
static inline void WaitOUT(void)
|
|
{
|
|
while (!(UEINTX & (1<<RXOUTI)))
|
|
adc: 80 91 e8 00 lds r24, 0x00E8 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
ae0: 82 ff sbrs r24, 2
|
|
ae2: fc cf rjmp .-8 ; 0xadc <__vector_11+0x336>
|
|
recvLength = 64;
|
|
}
|
|
|
|
// Write data to fit to the end (not the beginning) of the array
|
|
WaitOUT();
|
|
Recv((u8*)d + len - length, recvLength);
|
|
ae4: 67 e0 ldi r22, 0x07 ; 7
|
|
ae6: 84 e0 ldi r24, 0x04 ; 4
|
|
ae8: 91 e0 ldi r25, 0x01 ; 1
|
|
aea: 0e 94 99 02 call 0x532 ; 0x532 <_ZL4RecvPVhh>
|
|
return (UEINTX & (1<<RXOUTI)) == 0;
|
|
}
|
|
|
|
static inline void ClearOUT(void)
|
|
{
|
|
UEINTX = ~(1<<RXOUTI);
|
|
aee: 8b ef ldi r24, 0xFB ; 251
|
|
af0: 80 93 e8 00 sts 0x00E8, r24 ; 0x8000e8 <__DATA_REGION_ORIGIN__+0x88>
|
|
af4: 9e ce rjmp .-708 ; 0x832 <__vector_11+0x8c>
|
|
{
|
|
USB_RecvControl((void*)&_usbLineInfo,7);
|
|
}
|
|
|
|
if (CDC_SET_CONTROL_LINE_STATE == r)
|
|
af6: 82 32 cpi r24, 0x22 ; 34
|
|
af8: 09 f0 breq .+2 ; 0xafc <__vector_11+0x356>
|
|
afa: 9b ce rjmp .-714 ; 0x832 <__vector_11+0x8c>
|
|
{
|
|
_usbLineInfo.lineState = setup.wValueL;
|
|
afc: 8f 89 ldd r24, Y+23 ; 0x17
|
|
afe: 80 93 0b 01 sts 0x010B, r24 ; 0x80010b <_ZL12_usbLineInfo+0x7>
|
|
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,USB_EP_SIZE,0)
|
|
};
|
|
|
|
bool isLUFAbootloader()
|
|
{
|
|
return pgm_read_word(FLASHEND - 1) == NEW_LUFA_SIGNATURE;
|
|
b02: ee ef ldi r30, 0xFE ; 254
|
|
b04: ff e7 ldi r31, 0x7F ; 127
|
|
b06: 85 91 lpm r24, Z+
|
|
b08: 94 91 lpm r25, Z
|
|
// This is used to keep compatible with the old leonardo bootloaders.
|
|
// You are still able to set the magic key position manually to RAMEND-1 to save a few bytes for this check.
|
|
#if MAGIC_KEY_POS != (RAMEND-1)
|
|
// For future boards save the key in the inproblematic RAMEND
|
|
// Which is reserved for the main() return value (which will never return)
|
|
if (isLUFAbootloader()) {
|
|
b0a: 8b 3f cpi r24, 0xFB ; 251
|
|
b0c: 9c 4d sbci r25, 0xDC ; 220
|
|
b0e: 51 f1 breq .+84 ; 0xb64 <__stack+0x65>
|
|
// auto-reset into the bootloader is triggered when the port, already
|
|
// open at 1200 bps, is closed. this is the signal to start the watchdog
|
|
// with a relatively long period so it can finish housekeeping tasks
|
|
// like servicing endpoints before the sketch ends
|
|
|
|
uint16_t magic_key_pos = MAGIC_KEY_POS;
|
|
b10: e0 e0 ldi r30, 0x00 ; 0
|
|
b12: f8 e0 ldi r31, 0x08 ; 8
|
|
magic_key_pos = (RAMEND-1);
|
|
}
|
|
#endif
|
|
|
|
// We check DTR state to determine if host port is open (bit 0 of lineState).
|
|
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
|
|
b14: 80 91 04 01 lds r24, 0x0104 ; 0x800104 <_ZL12_usbLineInfo>
|
|
b18: 90 91 05 01 lds r25, 0x0105 ; 0x800105 <_ZL12_usbLineInfo+0x1>
|
|
b1c: a0 91 06 01 lds r26, 0x0106 ; 0x800106 <_ZL12_usbLineInfo+0x2>
|
|
b20: b0 91 07 01 lds r27, 0x0107 ; 0x800107 <_ZL12_usbLineInfo+0x3>
|
|
b24: 80 3b cpi r24, 0xB0 ; 176
|
|
b26: 94 40 sbci r25, 0x04 ; 4
|
|
b28: a1 05 cpc r26, r1
|
|
b2a: b1 05 cpc r27, r1
|
|
b2c: f1 f4 brne .+60 ; 0xb6a <__stack+0x6b>
|
|
b2e: 80 91 0b 01 lds r24, 0x010B ; 0x80010b <_ZL12_usbLineInfo+0x7>
|
|
b32: 80 fd sbrc r24, 0
|
|
b34: 1a c0 rjmp .+52 ; 0xb6a <__stack+0x6b>
|
|
{
|
|
#if MAGIC_KEY_POS != (RAMEND-1)
|
|
// Backup ram value if its not a newer bootloader and it hasn't already been saved.
|
|
// This should avoid memory corruption at least a bit, not fully
|
|
if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) {
|
|
b36: ee 3f cpi r30, 0xFE ; 254
|
|
b38: 8a e0 ldi r24, 0x0A ; 10
|
|
b3a: f8 07 cpc r31, r24
|
|
b3c: 89 f5 brne .+98 ; 0xba0 <__stack+0xa1>
|
|
*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
|
|
}
|
|
#endif
|
|
// Store boot key
|
|
*(uint16_t *)magic_key_pos = MAGIC_KEY;
|
|
b3e: 87 e7 ldi r24, 0x77 ; 119
|
|
b40: 97 e7 ldi r25, 0x77 ; 119
|
|
b42: 91 83 std Z+1, r25 ; 0x01
|
|
b44: 80 83 st Z, r24
|
|
// Save the watchdog state in case the reset is aborted.
|
|
wdtcsr_save = WDTCSR;
|
|
b46: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <__DATA_REGION_ORIGIN__>
|
|
b4a: 80 93 33 01 sts 0x0133, r24 ; 0x800133 <_ZL11wdtcsr_save>
|
|
: "n" (_SFR_MEM_ADDR(_WD_CONTROL_REG)),
|
|
"r" ((uint8_t)(_BV(_WD_CHANGE_BIT) | _BV(WDE))),
|
|
"r" ((uint8_t) ((value & 0x08 ? _WD_PS3_MASK : 0x00) |
|
|
_BV(WDE) | (value & 0x07)) )
|
|
: "r0"
|
|
);
|
|
b4e: 88 e1 ldi r24, 0x18 ; 24
|
|
b50: 9b e0 ldi r25, 0x0B ; 11
|
|
b52: 0f b6 in r0, 0x3f ; 63
|
|
b54: f8 94 cli
|
|
b56: a8 95 wdr
|
|
b58: 80 93 60 00 sts 0x0060, r24 ; 0x800060 <__DATA_REGION_ORIGIN__>
|
|
b5c: 0f be out 0x3f, r0 ; 63
|
|
b5e: 90 93 60 00 sts 0x0060, r25 ; 0x800060 <__DATA_REGION_ORIGIN__>
|
|
b62: 67 ce rjmp .-818 ; 0x832 <__vector_11+0x8c>
|
|
#if MAGIC_KEY_POS != (RAMEND-1)
|
|
// For future boards save the key in the inproblematic RAMEND
|
|
// Which is reserved for the main() return value (which will never return)
|
|
if (isLUFAbootloader()) {
|
|
// horray, we got a new bootloader!
|
|
magic_key_pos = (RAMEND-1);
|
|
b64: ee ef ldi r30, 0xFE ; 254
|
|
b66: fa e0 ldi r31, 0x0A ; 10
|
|
b68: d5 cf rjmp .-86 ; 0xb14 <__stack+0x15>
|
|
*(uint16_t *)magic_key_pos = MAGIC_KEY;
|
|
// Save the watchdog state in case the reset is aborted.
|
|
wdtcsr_save = WDTCSR;
|
|
wdt_enable(WDTO_120MS);
|
|
}
|
|
else if (*(uint16_t *)magic_key_pos == MAGIC_KEY)
|
|
b6a: 80 81 ld r24, Z
|
|
b6c: 91 81 ldd r25, Z+1 ; 0x01
|
|
b6e: 87 37 cpi r24, 0x77 ; 119
|
|
b70: 97 47 sbci r25, 0x77 ; 119
|
|
b72: 09 f0 breq .+2 ; 0xb76 <__stack+0x77>
|
|
b74: 5e ce rjmp .-836 ; 0x832 <__vector_11+0x8c>
|
|
// To avoid spurious resets we set the watchdog to 120ms and eventually
|
|
// cancel if DTR goes back high.
|
|
// Cancellation is only done if an auto-reset was started, which is
|
|
// indicated by the magic key having been set.
|
|
|
|
wdt_reset();
|
|
b76: a8 95 wdr
|
|
// Restore the watchdog state in case the sketch was using it.
|
|
WDTCSR |= (1<<WDCE) | (1<<WDE);
|
|
b78: 80 91 60 00 lds r24, 0x0060 ; 0x800060 <__DATA_REGION_ORIGIN__>
|
|
b7c: 88 61 ori r24, 0x18 ; 24
|
|
b7e: 80 93 60 00 sts 0x0060, r24 ; 0x800060 <__DATA_REGION_ORIGIN__>
|
|
WDTCSR = wdtcsr_save;
|
|
b82: 80 91 33 01 lds r24, 0x0133 ; 0x800133 <_ZL11wdtcsr_save>
|
|
b86: 80 93 60 00 sts 0x0060, r24 ; 0x800060 <__DATA_REGION_ORIGIN__>
|
|
#if MAGIC_KEY_POS != (RAMEND-1)
|
|
// Restore backed up (old bootloader) magic key data
|
|
if (magic_key_pos != (RAMEND-1)) {
|
|
b8a: ee 3f cpi r30, 0xFE ; 254
|
|
b8c: 2a e0 ldi r18, 0x0A ; 10
|
|
b8e: f2 07 cpc r31, r18
|
|
b90: 89 f0 breq .+34 ; 0xbb4 <__stack+0xb5>
|
|
*(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1);
|
|
b92: 80 91 fe 0a lds r24, 0x0AFE ; 0x800afe <__bss_end+0x969>
|
|
b96: 90 91 ff 0a lds r25, 0x0AFF ; 0x800aff <__bss_end+0x96a>
|
|
b9a: 91 83 std Z+1, r25 ; 0x01
|
|
b9c: 80 83 st Z, r24
|
|
b9e: 49 ce rjmp .-878 ; 0x832 <__vector_11+0x8c>
|
|
if (1200 == _usbLineInfo.dwDTERate && (_usbLineInfo.lineState & 0x01) == 0)
|
|
{
|
|
#if MAGIC_KEY_POS != (RAMEND-1)
|
|
// Backup ram value if its not a newer bootloader and it hasn't already been saved.
|
|
// This should avoid memory corruption at least a bit, not fully
|
|
if (magic_key_pos != (RAMEND-1) && *(uint16_t *)magic_key_pos != MAGIC_KEY) {
|
|
ba0: 80 81 ld r24, Z
|
|
ba2: 91 81 ldd r25, Z+1 ; 0x01
|
|
ba4: 87 37 cpi r24, 0x77 ; 119
|
|
ba6: 98 07 cpc r25, r24
|
|
ba8: 51 f2 breq .-108 ; 0xb3e <__stack+0x3f>
|
|
*(uint16_t *)(RAMEND-1) = *(uint16_t *)magic_key_pos;
|
|
baa: 90 93 ff 0a sts 0x0AFF, r25 ; 0x800aff <__bss_end+0x96a>
|
|
bae: 80 93 fe 0a sts 0x0AFE, r24 ; 0x800afe <__bss_end+0x969>
|
|
bb2: c5 cf rjmp .-118 ; 0xb3e <__stack+0x3f>
|
|
*(uint16_t *)magic_key_pos = *(uint16_t *)(RAMEND-1);
|
|
} else
|
|
#endif
|
|
{
|
|
// Clean up RAMEND key
|
|
*(uint16_t *)magic_key_pos = 0x0000;
|
|
bb4: 10 92 ff 0a sts 0x0AFF, r1 ; 0x800aff <__bss_end+0x96a>
|
|
bb8: 10 92 fe 0a sts 0x0AFE, r1 ; 0x800afe <__bss_end+0x969>
|
|
bbc: 3a ce rjmp .-908 ; 0x832 <__vector_11+0x8c>
|
|
if (CDC_ACM_INTERFACE == i)
|
|
return CDC_Setup(setup);
|
|
#endif
|
|
|
|
#ifdef PLUGGABLE_USB_ENABLED
|
|
return PluggableUSB().setup(setup);
|
|
bbe: 0e 94 4c 01 call 0x298 ; 0x298 <_Z12PluggableUSBv>
|
|
}
|
|
|
|
bool PluggableUSB_::setup(USBSetup& setup)
|
|
{
|
|
PluggableUSBModule* node;
|
|
for (node = rootNode; node; node = node->next) {
|
|
bc2: dc 01 movw r26, r24
|
|
bc4: 12 96 adiw r26, 0x02 ; 2
|
|
bc6: 0d 91 ld r16, X+
|
|
bc8: 1c 91 ld r17, X
|
|
bca: 01 15 cp r16, r1
|
|
bcc: 11 05 cpc r17, r1
|
|
bce: 09 f4 brne .+2 ; 0xbd2 <__stack+0xd3>
|
|
bd0: e8 ce rjmp .-560 ; 0x9a2 <__vector_11+0x1fc>
|
|
if (node->setup(setup)) {
|
|
bd2: d8 01 movw r26, r16
|
|
bd4: ed 91 ld r30, X+
|
|
bd6: fc 91 ld r31, X
|
|
bd8: 01 90 ld r0, Z+
|
|
bda: f0 81 ld r31, Z
|
|
bdc: e0 2d mov r30, r0
|
|
bde: be 01 movw r22, r28
|
|
be0: 6b 5e subi r22, 0xEB ; 235
|
|
be2: 7f 4f sbci r23, 0xFF ; 255
|
|
be4: c8 01 movw r24, r16
|
|
be6: 09 95 icall
|
|
be8: 81 11 cpse r24, r1
|
|
bea: 23 ce rjmp .-954 ; 0x832 <__vector_11+0x8c>
|
|
}
|
|
|
|
bool PluggableUSB_::setup(USBSetup& setup)
|
|
{
|
|
PluggableUSBModule* node;
|
|
for (node = rootNode; node; node = node->next) {
|
|
bec: f8 01 movw r30, r16
|
|
bee: 00 85 ldd r16, Z+8 ; 0x08
|
|
bf0: 11 85 ldd r17, Z+9 ; 0x09
|
|
bf2: eb cf rjmp .-42 ; 0xbca <__stack+0xcb>
|
|
|
|
InitControl(setup.wLength);
|
|
#ifdef PLUGGABLE_USB_ENABLED
|
|
int ret = PluggableUSB().getDescriptor(setup);
|
|
if (ret != 0) {
|
|
return (ret > 0 ? true : false);
|
|
bf4: 18 16 cp r1, r24
|
|
bf6: 19 06 cpc r1, r25
|
|
bf8: 0c f4 brge .+2 ; 0xbfc <__stack+0xfd>
|
|
bfa: 1b ce rjmp .-970 ; 0x832 <__vector_11+0x8c>
|
|
bfc: d2 ce rjmp .-604 ; 0x9a2 <__vector_11+0x1fc>
|
|
}
|
|
#endif
|
|
|
|
const u8* desc_addr = 0;
|
|
if (USB_DEVICE_DESCRIPTOR_TYPE == t)
|
|
bfe: f1 e0 ldi r31, 0x01 ; 1
|
|
c00: ff 12 cpse r15, r31
|
|
c02: be ce rjmp .-644 ; 0x980 <__vector_11+0x1da>
|
|
{
|
|
desc_addr = (const u8*)&USB_DeviceDescriptorIAD;
|
|
c04: 62 ef ldi r22, 0xF2 ; 242
|
|
c06: 70 e0 ldi r23, 0x00 ; 0
|
|
c08: 04 cf rjmp .-504 ; 0xa12 <__vector_11+0x26c>
|
|
|
|
00000c0a <__vector_23>:
|
|
#if defined(TIM0_OVF_vect)
|
|
ISR(TIM0_OVF_vect)
|
|
#else
|
|
ISR(TIMER0_OVF_vect)
|
|
#endif
|
|
{
|
|
c0a: 1f 92 push r1
|
|
c0c: 0f 92 push r0
|
|
c0e: 0f b6 in r0, 0x3f ; 63
|
|
c10: 0f 92 push r0
|
|
c12: 11 24 eor r1, r1
|
|
c14: 2f 93 push r18
|
|
c16: 3f 93 push r19
|
|
c18: 8f 93 push r24
|
|
c1a: 9f 93 push r25
|
|
c1c: af 93 push r26
|
|
c1e: bf 93 push r27
|
|
// copy these to local variables so they can be stored in registers
|
|
// (volatile variables must be read from memory on every access)
|
|
unsigned long m = timer0_millis;
|
|
c20: 80 91 27 01 lds r24, 0x0127 ; 0x800127 <timer0_millis>
|
|
c24: 90 91 28 01 lds r25, 0x0128 ; 0x800128 <timer0_millis+0x1>
|
|
c28: a0 91 29 01 lds r26, 0x0129 ; 0x800129 <timer0_millis+0x2>
|
|
c2c: b0 91 2a 01 lds r27, 0x012A ; 0x80012a <timer0_millis+0x3>
|
|
unsigned char f = timer0_fract;
|
|
c30: 30 91 26 01 lds r19, 0x0126 ; 0x800126 <__data_end>
|
|
|
|
m += MILLIS_INC;
|
|
f += FRACT_INC;
|
|
c34: 23 e0 ldi r18, 0x03 ; 3
|
|
c36: 23 0f add r18, r19
|
|
if (f >= FRACT_MAX) {
|
|
c38: 2d 37 cpi r18, 0x7D ; 125
|
|
c3a: 58 f5 brcc .+86 ; 0xc92 <__vector_23+0x88>
|
|
// copy these to local variables so they can be stored in registers
|
|
// (volatile variables must be read from memory on every access)
|
|
unsigned long m = timer0_millis;
|
|
unsigned char f = timer0_fract;
|
|
|
|
m += MILLIS_INC;
|
|
c3c: 01 96 adiw r24, 0x01 ; 1
|
|
c3e: a1 1d adc r26, r1
|
|
c40: b1 1d adc r27, r1
|
|
if (f >= FRACT_MAX) {
|
|
f -= FRACT_MAX;
|
|
m += 1;
|
|
}
|
|
|
|
timer0_fract = f;
|
|
c42: 20 93 26 01 sts 0x0126, r18 ; 0x800126 <__data_end>
|
|
timer0_millis = m;
|
|
c46: 80 93 27 01 sts 0x0127, r24 ; 0x800127 <timer0_millis>
|
|
c4a: 90 93 28 01 sts 0x0128, r25 ; 0x800128 <timer0_millis+0x1>
|
|
c4e: a0 93 29 01 sts 0x0129, r26 ; 0x800129 <timer0_millis+0x2>
|
|
c52: b0 93 2a 01 sts 0x012A, r27 ; 0x80012a <timer0_millis+0x3>
|
|
timer0_overflow_count++;
|
|
c56: 80 91 2b 01 lds r24, 0x012B ; 0x80012b <timer0_overflow_count>
|
|
c5a: 90 91 2c 01 lds r25, 0x012C ; 0x80012c <timer0_overflow_count+0x1>
|
|
c5e: a0 91 2d 01 lds r26, 0x012D ; 0x80012d <timer0_overflow_count+0x2>
|
|
c62: b0 91 2e 01 lds r27, 0x012E ; 0x80012e <timer0_overflow_count+0x3>
|
|
c66: 01 96 adiw r24, 0x01 ; 1
|
|
c68: a1 1d adc r26, r1
|
|
c6a: b1 1d adc r27, r1
|
|
c6c: 80 93 2b 01 sts 0x012B, r24 ; 0x80012b <timer0_overflow_count>
|
|
c70: 90 93 2c 01 sts 0x012C, r25 ; 0x80012c <timer0_overflow_count+0x1>
|
|
c74: a0 93 2d 01 sts 0x012D, r26 ; 0x80012d <timer0_overflow_count+0x2>
|
|
c78: b0 93 2e 01 sts 0x012E, r27 ; 0x80012e <timer0_overflow_count+0x3>
|
|
}
|
|
c7c: bf 91 pop r27
|
|
c7e: af 91 pop r26
|
|
c80: 9f 91 pop r25
|
|
c82: 8f 91 pop r24
|
|
c84: 3f 91 pop r19
|
|
c86: 2f 91 pop r18
|
|
c88: 0f 90 pop r0
|
|
c8a: 0f be out 0x3f, r0 ; 63
|
|
c8c: 0f 90 pop r0
|
|
c8e: 1f 90 pop r1
|
|
c90: 18 95 reti
|
|
unsigned char f = timer0_fract;
|
|
|
|
m += MILLIS_INC;
|
|
f += FRACT_INC;
|
|
if (f >= FRACT_MAX) {
|
|
f -= FRACT_MAX;
|
|
c92: 26 e8 ldi r18, 0x86 ; 134
|
|
c94: 23 0f add r18, r19
|
|
m += 1;
|
|
c96: 02 96 adiw r24, 0x02 ; 2
|
|
c98: a1 1d adc r26, r1
|
|
c9a: b1 1d adc r27, r1
|
|
c9c: d2 cf rjmp .-92 ; 0xc42 <__vector_23+0x38>
|
|
|
|
00000c9e <INT3_vect_part_2>:
|
|
" rjmp INT3_vect_part_2 \n" // go to part 2 for required prologue and epilogue
|
|
:: [pin] "I" (_SFR_IO_ADDR(PORTB)), [gpio] "I" (_SFR_IO_ADDR(GPIOR1)));
|
|
//:: [pin] "I" (_SFR_IO_ADDR(PORTB)), [gpio] "M" (_SFR_MEM_ADDR(GPIOR1)));
|
|
}
|
|
|
|
ISR(INT3_vect_part_2) { GPIOR2 = &GPIOR1; }
|
|
c9e: 1f 92 push r1
|
|
ca0: 0f 92 push r0
|
|
ca2: 0f b6 in r0, 0x3f ; 63
|
|
ca4: 0f 92 push r0
|
|
ca6: 11 24 eor r1, r1
|
|
ca8: 8f 93 push r24
|
|
caa: 8a e4 ldi r24, 0x4A ; 74
|
|
cac: 8b bd out 0x2b, r24 ; 43
|
|
cae: 8f 91 pop r24
|
|
cb0: 0f 90 pop r0
|
|
cb2: 0f be out 0x3f, r0 ; 63
|
|
cb4: 0f 90 pop r0
|
|
cb6: 1f 90 pop r1
|
|
cb8: 18 95 reti
|
|
|
|
00000cba <__vector_4>:
|
|
// " lds r0, %[gpio] \n" // GPIOR1 address is 42
|
|
" in r0, %[gpio] \n"
|
|
" out %[pin], r0 \n"
|
|
" pop r0 \n"
|
|
" rjmp INT3_vect_part_2 \n" // go to part 2 for required prologue and epilogue
|
|
:: [pin] "I" (_SFR_IO_ADDR(PORTB)), [gpio] "I" (_SFR_IO_ADDR(GPIOR1)));
|
|
cba: 0f 92 push r0
|
|
cbc: 0a b4 in r0, 0x2a ; 42
|
|
cbe: 05 b8 out 0x05, r0 ; 5
|
|
cc0: 0f 90 pop r0
|
|
cc2: ed cf rjmp .-38 ; 0xc9e <INT3_vect_part_2>
|
|
|
|
00000cc4 <INT2_vect_part_2>:
|
|
" pop r0 \n"
|
|
" rjmp INT2_vect_part_2 \n" // go to part 2 for required prologue and epilogue
|
|
:: [pin] "I" (_SFR_IO_ADDR(PORTB)), [gpio] "I" (_SFR_IO_ADDR(GPIOR0)));
|
|
}
|
|
|
|
ISR(INT2_vect_part_2) { GPIOR2 = &GPIOR0; }
|
|
cc4: 1f 92 push r1
|
|
cc6: 0f 92 push r0
|
|
cc8: 0f b6 in r0, 0x3f ; 63
|
|
cca: 0f 92 push r0
|
|
ccc: 11 24 eor r1, r1
|
|
cce: 8f 93 push r24
|
|
cd0: 8e e3 ldi r24, 0x3E ; 62
|
|
cd2: 8b bd out 0x2b, r24 ; 43
|
|
cd4: 8f 91 pop r24
|
|
cd6: 0f 90 pop r0
|
|
cd8: 0f be out 0x3f, r0 ; 63
|
|
cda: 0f 90 pop r0
|
|
cdc: 1f 90 pop r1
|
|
cde: 18 95 reti
|
|
|
|
00000ce0 <__vector_3>:
|
|
" push r0 \n"
|
|
" in r0, %[gpio] \n"
|
|
" out %[pin], r0 \n"
|
|
" pop r0 \n"
|
|
" rjmp INT2_vect_part_2 \n" // go to part 2 for required prologue and epilogue
|
|
:: [pin] "I" (_SFR_IO_ADDR(PORTB)), [gpio] "I" (_SFR_IO_ADDR(GPIOR0)));
|
|
ce0: 0f 92 push r0
|
|
ce2: 0e b2 in r0, 0x1e ; 30
|
|
ce4: 05 b8 out 0x05, r0 ; 5
|
|
ce6: 0f 90 pop r0
|
|
ce8: ed cf rjmp .-38 ; 0xcc4 <INT2_vect_part_2>
|
|
|
|
00000cea <_GLOBAL__sub_I__cdcInterface>:
|
|
public:
|
|
Print() : write_error(0) {}
|
|
cea: e7 e3 ldi r30, 0x37 ; 55
|
|
cec: f1 e0 ldi r31, 0x01 ; 1
|
|
cee: 13 82 std Z+3, r1 ; 0x03
|
|
cf0: 12 82 std Z+2, r1 ; 0x02
|
|
public:
|
|
virtual int available() = 0;
|
|
virtual int read() = 0;
|
|
virtual int peek() = 0;
|
|
|
|
Stream() {_timeout=1000;}
|
|
cf2: 88 ee ldi r24, 0xE8 ; 232
|
|
cf4: 93 e0 ldi r25, 0x03 ; 3
|
|
cf6: a0 e0 ldi r26, 0x00 ; 0
|
|
cf8: b0 e0 ldi r27, 0x00 ; 0
|
|
cfa: 84 83 std Z+4, r24 ; 0x04
|
|
cfc: 95 83 std Z+5, r25 ; 0x05
|
|
cfe: a6 83 std Z+6, r26 ; 0x06
|
|
d00: b7 83 std Z+7, r27 ; 0x07
|
|
class Serial_ : public Stream
|
|
{
|
|
private:
|
|
int peek_buffer;
|
|
public:
|
|
Serial_() { peek_buffer = -1; };
|
|
d02: 87 e1 ldi r24, 0x17 ; 23
|
|
d04: 91 e0 ldi r25, 0x01 ; 1
|
|
d06: 91 83 std Z+1, r25 ; 0x01
|
|
d08: 80 83 st Z, r24
|
|
d0a: 8f ef ldi r24, 0xFF ; 255
|
|
d0c: 9f ef ldi r25, 0xFF ; 255
|
|
d0e: 95 87 std Z+13, r25 ; 0x0d
|
|
d10: 84 87 std Z+12, r24 ; 0x0c
|
|
breakValue = -1;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
Serial_ Serial;
|
|
d12: 08 95 ret
|
|
|
|
00000d14 <main>:
|
|
|
|
void init()
|
|
{
|
|
// this needs to be called before setup() or some functions won't
|
|
// work there
|
|
sei();
|
|
d14: 78 94 sei
|
|
|
|
// on the ATmega168, timer 0 is also used for fast hardware pwm
|
|
// (using phase-correct PWM would mean that timer 0 overflowed half as often
|
|
// resulting in different millis() behavior on the ATmega8 and ATmega168)
|
|
#if defined(TCCR0A) && defined(WGM01)
|
|
sbi(TCCR0A, WGM01);
|
|
d16: 84 b5 in r24, 0x24 ; 36
|
|
d18: 82 60 ori r24, 0x02 ; 2
|
|
d1a: 84 bd out 0x24, r24 ; 36
|
|
sbi(TCCR0A, WGM00);
|
|
d1c: 84 b5 in r24, 0x24 ; 36
|
|
d1e: 81 60 ori r24, 0x01 ; 1
|
|
d20: 84 bd out 0x24, r24 ; 36
|
|
// this combination is for the standard atmega8
|
|
sbi(TCCR0, CS01);
|
|
sbi(TCCR0, CS00);
|
|
#elif defined(TCCR0B) && defined(CS01) && defined(CS00)
|
|
// this combination is for the standard 168/328/1280/2560
|
|
sbi(TCCR0B, CS01);
|
|
d22: 85 b5 in r24, 0x25 ; 37
|
|
d24: 82 60 ori r24, 0x02 ; 2
|
|
d26: 85 bd out 0x25, r24 ; 37
|
|
sbi(TCCR0B, CS00);
|
|
d28: 85 b5 in r24, 0x25 ; 37
|
|
d2a: 81 60 ori r24, 0x01 ; 1
|
|
d2c: 85 bd out 0x25, r24 ; 37
|
|
|
|
// enable timer 0 overflow interrupt
|
|
#if defined(TIMSK) && defined(TOIE0)
|
|
sbi(TIMSK, TOIE0);
|
|
#elif defined(TIMSK0) && defined(TOIE0)
|
|
sbi(TIMSK0, TOIE0);
|
|
d2e: 80 91 6e 00 lds r24, 0x006E ; 0x80006e <__DATA_REGION_ORIGIN__+0xe>
|
|
d32: 81 60 ori r24, 0x01 ; 1
|
|
d34: 80 93 6e 00 sts 0x006E, r24 ; 0x80006e <__DATA_REGION_ORIGIN__+0xe>
|
|
// this is better for motors as it ensures an even waveform
|
|
// note, however, that fast pwm mode can achieve a frequency of up
|
|
// 8 MHz (with a 16 MHz clock) at 50% duty cycle
|
|
|
|
#if defined(TCCR1B) && defined(CS11) && defined(CS10)
|
|
TCCR1B = 0;
|
|
d38: 10 92 81 00 sts 0x0081, r1 ; 0x800081 <__DATA_REGION_ORIGIN__+0x21>
|
|
|
|
// set timer 1 prescale factor to 64
|
|
sbi(TCCR1B, CS11);
|
|
d3c: 80 91 81 00 lds r24, 0x0081 ; 0x800081 <__DATA_REGION_ORIGIN__+0x21>
|
|
d40: 82 60 ori r24, 0x02 ; 2
|
|
d42: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__DATA_REGION_ORIGIN__+0x21>
|
|
#if F_CPU >= 8000000L
|
|
sbi(TCCR1B, CS10);
|
|
d46: 80 91 81 00 lds r24, 0x0081 ; 0x800081 <__DATA_REGION_ORIGIN__+0x21>
|
|
d4a: 81 60 ori r24, 0x01 ; 1
|
|
d4c: 80 93 81 00 sts 0x0081, r24 ; 0x800081 <__DATA_REGION_ORIGIN__+0x21>
|
|
sbi(TCCR1, CS10);
|
|
#endif
|
|
#endif
|
|
// put timer 1 in 8-bit phase correct pwm mode
|
|
#if defined(TCCR1A) && defined(WGM10)
|
|
sbi(TCCR1A, WGM10);
|
|
d50: 80 91 80 00 lds r24, 0x0080 ; 0x800080 <__DATA_REGION_ORIGIN__+0x20>
|
|
d54: 81 60 ori r24, 0x01 ; 1
|
|
d56: 80 93 80 00 sts 0x0080, r24 ; 0x800080 <__DATA_REGION_ORIGIN__+0x20>
|
|
//#else
|
|
// Timer 2 not finished (may not be present on this CPU)
|
|
#endif
|
|
|
|
#if defined(TCCR3B) && defined(CS31) && defined(WGM30)
|
|
sbi(TCCR3B, CS31); // set timer 3 prescale factor to 64
|
|
d5a: 80 91 91 00 lds r24, 0x0091 ; 0x800091 <__DATA_REGION_ORIGIN__+0x31>
|
|
d5e: 82 60 ori r24, 0x02 ; 2
|
|
d60: 80 93 91 00 sts 0x0091, r24 ; 0x800091 <__DATA_REGION_ORIGIN__+0x31>
|
|
sbi(TCCR3B, CS30);
|
|
d64: 80 91 91 00 lds r24, 0x0091 ; 0x800091 <__DATA_REGION_ORIGIN__+0x31>
|
|
d68: 81 60 ori r24, 0x01 ; 1
|
|
d6a: 80 93 91 00 sts 0x0091, r24 ; 0x800091 <__DATA_REGION_ORIGIN__+0x31>
|
|
sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode
|
|
d6e: 80 91 90 00 lds r24, 0x0090 ; 0x800090 <__DATA_REGION_ORIGIN__+0x30>
|
|
d72: 81 60 ori r24, 0x01 ; 1
|
|
d74: 80 93 90 00 sts 0x0090, r24 ; 0x800090 <__DATA_REGION_ORIGIN__+0x30>
|
|
#endif
|
|
|
|
#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */
|
|
sbi(TCCR4B, CS42); // set timer4 prescale factor to 64
|
|
d78: 80 91 c1 00 lds r24, 0x00C1 ; 0x8000c1 <__DATA_REGION_ORIGIN__+0x61>
|
|
d7c: 84 60 ori r24, 0x04 ; 4
|
|
d7e: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__DATA_REGION_ORIGIN__+0x61>
|
|
sbi(TCCR4B, CS41);
|
|
d82: 80 91 c1 00 lds r24, 0x00C1 ; 0x8000c1 <__DATA_REGION_ORIGIN__+0x61>
|
|
d86: 82 60 ori r24, 0x02 ; 2
|
|
d88: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__DATA_REGION_ORIGIN__+0x61>
|
|
sbi(TCCR4B, CS40);
|
|
d8c: 80 91 c1 00 lds r24, 0x00C1 ; 0x8000c1 <__DATA_REGION_ORIGIN__+0x61>
|
|
d90: 81 60 ori r24, 0x01 ; 1
|
|
d92: 80 93 c1 00 sts 0x00C1, r24 ; 0x8000c1 <__DATA_REGION_ORIGIN__+0x61>
|
|
sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
|
|
d96: 80 91 c3 00 lds r24, 0x00C3 ; 0x8000c3 <__DATA_REGION_ORIGIN__+0x63>
|
|
d9a: 81 60 ori r24, 0x01 ; 1
|
|
d9c: 80 93 c3 00 sts 0x00C3, r24 ; 0x8000c3 <__DATA_REGION_ORIGIN__+0x63>
|
|
sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A
|
|
da0: 80 91 c0 00 lds r24, 0x00C0 ; 0x8000c0 <__DATA_REGION_ORIGIN__+0x60>
|
|
da4: 82 60 ori r24, 0x02 ; 2
|
|
da6: 80 93 c0 00 sts 0x00C0, r24 ; 0x8000c0 <__DATA_REGION_ORIGIN__+0x60>
|
|
sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D
|
|
daa: 80 91 c2 00 lds r24, 0x00C2 ; 0x8000c2 <__DATA_REGION_ORIGIN__+0x62>
|
|
dae: 81 60 ori r24, 0x01 ; 1
|
|
db0: 80 93 c2 00 sts 0x00C2, r24 ; 0x8000c2 <__DATA_REGION_ORIGIN__+0x62>
|
|
#endif
|
|
|
|
#if defined(ADCSRA)
|
|
// set a2d prescaler so we are inside the desired 50-200 KHz range.
|
|
#if F_CPU >= 16000000 // 16 MHz / 128 = 125 KHz
|
|
sbi(ADCSRA, ADPS2);
|
|
db4: 80 91 7a 00 lds r24, 0x007A ; 0x80007a <__DATA_REGION_ORIGIN__+0x1a>
|
|
db8: 84 60 ori r24, 0x04 ; 4
|
|
dba: 80 93 7a 00 sts 0x007A, r24 ; 0x80007a <__DATA_REGION_ORIGIN__+0x1a>
|
|
sbi(ADCSRA, ADPS1);
|
|
dbe: 80 91 7a 00 lds r24, 0x007A ; 0x80007a <__DATA_REGION_ORIGIN__+0x1a>
|
|
dc2: 82 60 ori r24, 0x02 ; 2
|
|
dc4: 80 93 7a 00 sts 0x007A, r24 ; 0x80007a <__DATA_REGION_ORIGIN__+0x1a>
|
|
sbi(ADCSRA, ADPS0);
|
|
dc8: 80 91 7a 00 lds r24, 0x007A ; 0x80007a <__DATA_REGION_ORIGIN__+0x1a>
|
|
dcc: 81 60 ori r24, 0x01 ; 1
|
|
dce: 80 93 7a 00 sts 0x007A, r24 ; 0x80007a <__DATA_REGION_ORIGIN__+0x1a>
|
|
cbi(ADCSRA, ADPS2);
|
|
cbi(ADCSRA, ADPS1);
|
|
sbi(ADCSRA, ADPS0);
|
|
#endif
|
|
// enable a2d conversions
|
|
sbi(ADCSRA, ADEN);
|
|
dd2: 80 91 7a 00 lds r24, 0x007A ; 0x80007a <__DATA_REGION_ORIGIN__+0x1a>
|
|
dd6: 80 68 ori r24, 0x80 ; 128
|
|
dd8: 80 93 7a 00 sts 0x007A, r24 ; 0x80007a <__DATA_REGION_ORIGIN__+0x1a>
|
|
{
|
|
}
|
|
|
|
void USBDevice_::attach()
|
|
{
|
|
_usbConfiguration = 0;
|
|
ddc: 10 92 94 01 sts 0x0194, r1 ; 0x800194 <_usbConfiguration>
|
|
_usbCurrentStatus = 0;
|
|
de0: 10 92 34 01 sts 0x0134, r1 ; 0x800134 <_usbCurrentStatus>
|
|
_usbSuspendState = 0;
|
|
de4: 10 92 36 01 sts 0x0136, r1 ; 0x800136 <_usbSuspendState>
|
|
}
|
|
|
|
static inline void USB_ClockEnable()
|
|
{
|
|
#if defined(UHWCON)
|
|
UHWCON |= (1<<UVREGE); // power internal reg
|
|
de8: 80 91 d7 00 lds r24, 0x00D7 ; 0x8000d7 <__DATA_REGION_ORIGIN__+0x77>
|
|
dec: 81 60 ori r24, 0x01 ; 1
|
|
dee: 80 93 d7 00 sts 0x00D7, r24 ; 0x8000d7 <__DATA_REGION_ORIGIN__+0x77>
|
|
#endif
|
|
USBCON = (1<<USBE) | (1<<FRZCLK); // clock frozen, usb enabled
|
|
df2: 80 ea ldi r24, 0xA0 ; 160
|
|
df4: 80 93 d8 00 sts 0x00D8, r24 ; 0x8000d8 <__DATA_REGION_ORIGIN__+0x78>
|
|
|
|
// ATmega32U4
|
|
#if defined(PINDIV)
|
|
#if F_CPU == 16000000UL
|
|
PLLCSR |= (1<<PINDIV); // Need 16 MHz xtal
|
|
df8: 89 b5 in r24, 0x29 ; 41
|
|
dfa: 80 61 ori r24, 0x10 ; 16
|
|
dfc: 89 bd out 0x29, r24 ; 41
|
|
#endif
|
|
#else
|
|
#error "USB Chip not supported, please defined method of USB PLL initialization"
|
|
#endif
|
|
|
|
PLLCSR |= (1<<PLLE);
|
|
dfe: 89 b5 in r24, 0x29 ; 41
|
|
e00: 82 60 ori r24, 0x02 ; 2
|
|
e02: 89 bd out 0x29, r24 ; 41
|
|
while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
|
|
e04: 09 b4 in r0, 0x29 ; 41
|
|
e06: 00 fe sbrs r0, 0
|
|
e08: fd cf rjmp .-6 ; 0xe04 <main+0xf0>
|
|
}
|
|
|
|
// Some tests on specific versions of macosx (10.7.3), reported some
|
|
// strange behaviors when the board is reset using the serial
|
|
// port touch at 1200 bps. This delay fixes this behavior.
|
|
delay(1);
|
|
e0a: 0e 94 cb 02 call 0x596 ; 0x596 <delay.constprop.10>
|
|
#if defined(OTGPADE)
|
|
USBCON = (USBCON & ~(1<<FRZCLK)) | (1<<OTGPADE); // start USB clock, enable VBUS Pad
|
|
e0e: 80 91 d8 00 lds r24, 0x00D8 ; 0x8000d8 <__DATA_REGION_ORIGIN__+0x78>
|
|
e12: 8f 7c andi r24, 0xCF ; 207
|
|
e14: 80 61 ori r24, 0x10 ; 16
|
|
e16: 80 93 d8 00 sts 0x00D8, r24 ; 0x8000d8 <__DATA_REGION_ORIGIN__+0x78>
|
|
USBCON &= ~(1 << FRZCLK); // start USB clock
|
|
#endif
|
|
|
|
#if defined(RSTCPU)
|
|
#if defined(LSM)
|
|
UDCON &= ~((1<<RSTCPU) | (1<<LSM) | (1<<RMWKUP) | (1<<DETACH)); // enable attach resistor, set full speed mode
|
|
e1a: 80 91 e0 00 lds r24, 0x00E0 ; 0x8000e0 <__DATA_REGION_ORIGIN__+0x80>
|
|
e1e: 80 7f andi r24, 0xF0 ; 240
|
|
e20: 80 93 e0 00 sts 0x00E0, r24 ; 0x8000e0 <__DATA_REGION_ORIGIN__+0x80>
|
|
_usbConfiguration = 0;
|
|
_usbCurrentStatus = 0;
|
|
_usbSuspendState = 0;
|
|
USB_ClockEnable();
|
|
|
|
UDINT &= ~((1<<WAKEUPI) | (1<<SUSPI)); // clear already pending WAKEUP / SUSPEND requests
|
|
e24: 80 91 e1 00 lds r24, 0x00E1 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
e28: 8e 7e andi r24, 0xEE ; 238
|
|
e2a: 80 93 e1 00 sts 0x00E1, r24 ; 0x8000e1 <__DATA_REGION_ORIGIN__+0x81>
|
|
UDIEN = (1<<EORSTE) | (1<<SOFE) | (1<<SUSPE); // Enable interrupts for EOR (End of Reset), SOF (start of frame) and SUSPEND
|
|
e2e: 8d e0 ldi r24, 0x0D ; 13
|
|
e30: 80 93 e2 00 sts 0x00E2, r24 ; 0x8000e2 <__DATA_REGION_ORIGIN__+0x82>
|
|
|
|
TX_RX_LED_INIT;
|
|
e34: 55 9a sbi 0x0a, 5 ; 10
|
|
e36: 20 9a sbi 0x04, 0 ; 4
|
|
}
|
|
|
|
ISR(INT3_vect_part_2) { GPIOR2 = &GPIOR1; }
|
|
|
|
void setup() {
|
|
DDRB = 0xff; PORTB = 0xff; //all PB-ports are outputs and high (0xff = zero state, because signals are inverted)
|
|
e38: 8f ef ldi r24, 0xFF ; 255
|
|
e3a: 84 b9 out 0x04, r24 ; 4
|
|
e3c: 85 b9 out 0x05, r24 ; 5
|
|
DDRF = 0; PORTF = 0xff; // all PF-ports are inputs with pullups
|
|
e3e: 10 ba out 0x10, r1 ; 16
|
|
e40: 81 bb out 0x11, r24 ; 17
|
|
DDRD = B00100000; PORTD = B11110011; // all PD-ports are inputs (except PD5) with pullups (PD2,PD3 without pullup)
|
|
e42: 80 e2 ldi r24, 0x20 ; 32
|
|
e44: 8a b9 out 0x0a, r24 ; 10
|
|
e46: 83 ef ldi r24, 0xF3 ; 243
|
|
e48: 8b b9 out 0x0b, r24 ; 11
|
|
pinMode(5, INPUT_PULLUP); // pin5 (PC6) is input
|
|
e4a: 85 e0 ldi r24, 0x05 ; 5
|
|
e4c: 0e 94 e9 00 call 0x1d2 ; 0x1d2 <pinMode.constprop.11>
|
|
pinMode(7, INPUT_PULLUP); // pin7 (PE6) is input
|
|
e50: 87 e0 ldi r24, 0x07 ; 7
|
|
e52: 0e 94 e9 00 call 0x1d2 ; 0x1d2 <pinMode.constprop.11>
|
|
|
|
if (selectC) GPIOR2 = &GPIOR0; else GPIOR2 = &GPIOR1;
|
|
e56: 4a 9b sbis 0x09, 2 ; 9
|
|
e58: 4a c0 rjmp .+148 ; 0xeee <main+0x1da>
|
|
e5a: 8e e3 ldi r24, 0x3E ; 62
|
|
e5c: 8b bd out 0x2b, r24 ; 43
|
|
GPIOR0 = 0xff; GPIOR1 = 0xff; // start from zero state (signals are inverted)
|
|
e5e: 8f ef ldi r24, 0xFF ; 255
|
|
e60: 8e bb out 0x1e, r24 ; 30
|
|
e62: 8a bd out 0x2a, r24 ; 42
|
|
|
|
TIMSK0 = 0; // disable timer0 interrupts (Arduino Uno/Pro Micro millis()/micros() update ISR)
|
|
e64: 10 92 6e 00 sts 0x006E, r1 ; 0x80006e <__DATA_REGION_ORIGIN__+0xe>
|
|
|
|
EICRA = B10110000; // INT2 ÔÇô rising edge on RXD (Bxx11xxxx), INT3 - falling edge on TXD (B10xxxxxx)
|
|
e68: 80 eb ldi r24, 0xB0 ; 176
|
|
e6a: 80 93 69 00 sts 0x0069, r24 ; 0x800069 <__DATA_REGION_ORIGIN__+0x9>
|
|
EIMSK = B1100; // enable INT2 (Bx1xx) and INT3 (B1xxx)
|
|
e6e: 8c e0 ldi r24, 0x0C ; 12
|
|
e70: 8d bb out 0x1d, r24 ; 29
|
|
|
|
setup();
|
|
|
|
for (;;) {
|
|
loop();
|
|
if (serialEventRun) serialEventRun();
|
|
e72: c0 e0 ldi r28, 0x00 ; 0
|
|
e74: d0 e0 ldi r29, 0x00 ; 0
|
|
TCNT1 = 0; // reset Timer1 counter*/
|
|
}
|
|
|
|
void loop() {
|
|
uint8_t PF, PD, PC, PE;
|
|
PF = PINF; PD = PIND; PC = PINC; PE = PINE;
|
|
e76: 3f b1 in r19, 0x0f ; 15
|
|
e78: 29 b1 in r18, 0x09 ; 9
|
|
e7a: 86 b1 in r24, 0x06 ; 6
|
|
e7c: 4c b1 in r20, 0x0c ; 12
|
|
uint8_t joy1 = 0xff; uint8_t joy2 = 0xff; // all signals are inverted
|
|
if (up1) bitClear(joy1,upC);
|
|
e7e: 9d ef ldi r25, 0xFD ; 253
|
|
e80: 27 fd sbrc r18, 7
|
|
}
|
|
|
|
void loop() {
|
|
uint8_t PF, PD, PC, PE;
|
|
PF = PINF; PD = PIND; PC = PINC; PE = PINE;
|
|
uint8_t joy1 = 0xff; uint8_t joy2 = 0xff; // all signals are inverted
|
|
e82: 9f ef ldi r25, 0xFF ; 255
|
|
if (up1) bitClear(joy1,upC);
|
|
if (down1) bitClear(joy1,downC);
|
|
e84: 86 ff sbrs r24, 6
|
|
e86: 97 7f andi r25, 0xF7 ; 247
|
|
if (left1) bitClear(joy1,leftC);
|
|
e88: 24 ff sbrs r18, 4
|
|
e8a: 9b 7f andi r25, 0xFB ; 251
|
|
if (right1) bitClear(joy1,rightC);
|
|
e8c: 20 ff sbrs r18, 0
|
|
e8e: 9f 7b andi r25, 0xBF ; 191
|
|
if (up2) bitClear(joy2,upC);
|
|
e90: 8d ef ldi r24, 0xFD ; 253
|
|
e92: 37 fd sbrc r19, 7
|
|
}
|
|
|
|
void loop() {
|
|
uint8_t PF, PD, PC, PE;
|
|
PF = PINF; PD = PIND; PC = PINC; PE = PINE;
|
|
uint8_t joy1 = 0xff; uint8_t joy2 = 0xff; // all signals are inverted
|
|
e94: 8f ef ldi r24, 0xFF ; 255
|
|
if (up1) bitClear(joy1,upC);
|
|
if (down1) bitClear(joy1,downC);
|
|
if (left1) bitClear(joy1,leftC);
|
|
if (right1) bitClear(joy1,rightC);
|
|
if (up2) bitClear(joy2,upC);
|
|
if (down2) bitClear(joy2,downC);
|
|
e96: 36 ff sbrs r19, 6
|
|
e98: 87 7f andi r24, 0xF7 ; 247
|
|
if (left2) bitClear(joy2,leftC);
|
|
e9a: 35 ff sbrs r19, 5
|
|
e9c: 8b 7f andi r24, 0xFB ; 251
|
|
if (right2) bitClear(joy2,rightC);
|
|
e9e: 34 ff sbrs r19, 4
|
|
ea0: 8f 7b andi r24, 0xBF ; 191
|
|
if (fire1) { bitClear(joy1,fire1C); bitClear(joy2,fire1C); }
|
|
ea2: 21 fd sbrc r18, 1
|
|
ea4: 02 c0 rjmp .+4 ; 0xeaa <main+0x196>
|
|
ea6: 9f 7e andi r25, 0xEF ; 239
|
|
ea8: 8f 7e andi r24, 0xEF ; 239
|
|
if (fire2) { bitClear(joy1,fire2C); bitClear(joy2,fire2C); }
|
|
eaa: 46 fd sbrc r20, 6
|
|
eac: 02 c0 rjmp .+4 ; 0xeb2 <main+0x19e>
|
|
eae: 9f 7d andi r25, 0xDF ; 223
|
|
eb0: 8f 7d andi r24, 0xDF ; 223
|
|
|
|
if (GPIOR2 == &GPIOR0) { PORTD &= ~_BV(5); } else { PORTD |= _BV(5); } //TX-LED on, if joystick 3 is activated
|
|
eb2: 2b b5 in r18, 0x2b ; 43
|
|
eb4: 2e 33 cpi r18, 0x3E ; 62
|
|
eb6: e9 f4 brne .+58 ; 0xef2 <main+0x1de>
|
|
eb8: 5d 98 cbi 0x0b, 5 ; 11
|
|
if (GPIOR2 == &GPIOR1) { bitClear(joy2,0); } //RX-LED on, if joystick 4 is activated
|
|
eba: 2b b5 in r18, 0x2b ; 43
|
|
ebc: 2a 34 cpi r18, 0x4A ; 74
|
|
ebe: 09 f4 brne .+2 ; 0xec2 <main+0x1ae>
|
|
ec0: 8e 7f andi r24, 0xFE ; 254
|
|
|
|
GPIOR0 = joy1; GPIOR1 = joy2;
|
|
ec2: 9e bb out 0x1e, r25 ; 30
|
|
ec4: 8a bd out 0x2a, r24 ; 42
|
|
|
|
//PORTB = *ptr; // is this atomic? probably, because ptr is 6-bit pointer. nope...
|
|
noInterrupts();
|
|
ec6: f8 94 cli
|
|
PORTB = *((unsigned int *)GPIOR2);
|
|
ec8: eb b5 in r30, 0x2b ; 43
|
|
eca: f0 e0 ldi r31, 0x00 ; 0
|
|
ecc: 80 81 ld r24, Z
|
|
ece: 85 b9 out 0x05, r24 ; 5
|
|
//ec8: eb b5 in r30, 0x2b ; 43
|
|
//eca: f0 e0 ldi r31, 0x00 ; 0
|
|
//ecc: 80 81 ld r24, Z
|
|
//ece: 85 b9 out 0x05, r24 ; 5
|
|
interrupts();
|
|
ed0: 78 94 sei
|
|
" cli \n"
|
|
" lds r30, %[gpio] \n"
|
|
" ld __tmp_reg__, Z \n"
|
|
" sts %[pin], __tmp_reg__ \n"
|
|
" sei \n"
|
|
:: [pin] "M" (_SFR_MEM_ADDR(PORTB)), [gpio] "M" (_SFR_MEM_ADDR(GPIOR2)) : "r30", "r31");
|
|
ed2: ff 27 eor r31, r31
|
|
ed4: f8 94 cli
|
|
ed6: e0 91 4b 00 lds r30, 0x004B ; 0x80004b <__TEXT_REGION_LENGTH__+0x7e004b>
|
|
eda: 00 80 ld r0, Z
|
|
edc: 00 92 25 00 sts 0x0025, r0 ; 0x800025 <__TEXT_REGION_LENGTH__+0x7e0025>
|
|
ee0: 78 94 sei
|
|
ee2: 20 97 sbiw r28, 0x00 ; 0
|
|
ee4: 09 f4 brne .+2 ; 0xee8 <main+0x1d4>
|
|
ee6: c7 cf rjmp .-114 ; 0xe76 <main+0x162>
|
|
ee8: 0e 94 00 00 call 0 ; 0x0 <__vectors>
|
|
eec: c4 cf rjmp .-120 ; 0xe76 <main+0x162>
|
|
DDRF = 0; PORTF = 0xff; // all PF-ports are inputs with pullups
|
|
DDRD = B00100000; PORTD = B11110011; // all PD-ports are inputs (except PD5) with pullups (PD2,PD3 without pullup)
|
|
pinMode(5, INPUT_PULLUP); // pin5 (PC6) is input
|
|
pinMode(7, INPUT_PULLUP); // pin7 (PE6) is input
|
|
|
|
if (selectC) GPIOR2 = &GPIOR0; else GPIOR2 = &GPIOR1;
|
|
eee: 8a e4 ldi r24, 0x4A ; 74
|
|
ef0: b5 cf rjmp .-150 ; 0xe5c <main+0x148>
|
|
if (left2) bitClear(joy2,leftC);
|
|
if (right2) bitClear(joy2,rightC);
|
|
if (fire1) { bitClear(joy1,fire1C); bitClear(joy2,fire1C); }
|
|
if (fire2) { bitClear(joy1,fire2C); bitClear(joy2,fire2C); }
|
|
|
|
if (GPIOR2 == &GPIOR0) { PORTD &= ~_BV(5); } else { PORTD |= _BV(5); } //TX-LED on, if joystick 3 is activated
|
|
ef2: 5d 9a sbi 0x0b, 5 ; 11
|
|
ef4: e2 cf rjmp .-60 ; 0xeba <main+0x1a6>
|
|
|
|
00000ef6 <__tablejump2__>:
|
|
ef6: ee 0f add r30, r30
|
|
ef8: ff 1f adc r31, r31
|
|
efa: 05 90 lpm r0, Z+
|
|
efc: f4 91 lpm r31, Z
|
|
efe: e0 2d mov r30, r0
|
|
f00: 09 94 ijmp
|
|
|
|
00000f02 <_exit>:
|
|
f02: f8 94 cli
|
|
|
|
00000f04 <__stop_program>:
|
|
f04: ff cf rjmp .-2 ; 0xf04 <__stop_program>
|