Skip to content

Commit 6367ff1

Browse files
committed
Merged master
2 parents 65e4fc6 + ac6bc77 commit 6367ff1

File tree

21 files changed

+469
-169
lines changed

21 files changed

+469
-169
lines changed

hardware/arduino/avr/cores/arduino/Arduino.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ extern "C"{
2020

2121
#define INPUT 0x0
2222
#define OUTPUT 0x1
23+
#define INPUT_PULLUP 0x2
2324

2425
#define true 0x1
2526
#define false 0x0

hardware/arduino/avr/cores/arduino/CDC.cpp

Lines changed: 82 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,20 @@
2323
#if defined(USBCON)
2424
#ifdef CDC_ENABLED
2525

26-
void Reboot()
26+
#if (RAMEND < 1000)
27+
#define SERIAL_BUFFER_SIZE 16
28+
#else
29+
#define SERIAL_BUFFER_SIZE 64
30+
#endif
31+
32+
struct ring_buffer
2733
{
28-
USB.detach();
29-
cli();
30-
asm volatile("jmp 0x7800"); // jump to bootloader - DiskLoader takes up last 2 kB
31-
}
34+
unsigned char buffer[SERIAL_BUFFER_SIZE];
35+
volatile int head;
36+
volatile int tail;
37+
};
38+
39+
ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
3240

3341
typedef struct
3442
{
@@ -92,9 +100,28 @@ bool WEAK CDC_Setup(Setup& setup)
92100

93101
if (CDC_SET_CONTROL_LINE_STATE == r)
94102
{
95-
if (0 != _usbLineInfo.lineState && 1200 == _usbLineInfo.dwDTERate) // auto-reset is triggered when the port, already open at 1200 bps, is closed
96-
Reboot();
97103
_usbLineInfo.lineState = setup.wValueL;
104+
105+
// auto-reset into the bootloader is triggered when the port, already
106+
// open at 1200 bps, is closed. this is the signal to start the watchdog
107+
// with a relatively long period so it can finish housekeeping tasks
108+
// like servicing endpoints before the sketch ends
109+
if (1200 == _usbLineInfo.dwDTERate) {
110+
// We check DTR state to determine if host port is open (bit 0 of lineState).
111+
if ((_usbLineInfo.lineState & 0x01) == 0) {
112+
*(uint16_t *)0x0800 = 0x7777;
113+
wdt_enable(WDTO_120MS);
114+
} else {
115+
// Most OSs do some intermediate steps when configuring ports and DTR can
116+
// twiggle more than once before stabilizing.
117+
// To avoid spurious resets we set the watchdog to 250ms and eventually
118+
// cancel if DTR goes back high.
119+
120+
wdt_disable();
121+
wdt_reset();
122+
*(uint16_t *)0x0800 = 0x0;
123+
}
124+
}
98125
return true;
99126
}
100127
}
@@ -111,33 +138,49 @@ void Serial_::end(void)
111138
{
112139
}
113140

141+
void Serial_::accept(void)
142+
{
143+
ring_buffer *buffer = &cdc_rx_buffer;
144+
int c = USB_Recv(CDC_RX);
145+
int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE;
146+
147+
// if we should be storing the received character into the location
148+
// just before the tail (meaning that the head would advance to the
149+
// current location of the tail), we're about to overflow the buffer
150+
// and so we don't write the character or advance the head.
151+
if (i != buffer->tail) {
152+
buffer->buffer[buffer->head] = c;
153+
buffer->head = i;
154+
}
155+
}
156+
114157
int Serial_::available(void)
115158
{
116-
u8 avail = USB_Available(CDC_RX);
117-
if (_serialPeek != -1)
118-
avail++;
119-
return avail;
159+
ring_buffer *buffer = &cdc_rx_buffer;
160+
return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE;
120161
}
121162

122-
// peek is nasty
123163
int Serial_::peek(void)
124164
{
125-
if (_serialPeek == -1)
126-
_serialPeek = read();
127-
return _serialPeek;
165+
ring_buffer *buffer = &cdc_rx_buffer;
166+
if (buffer->head == buffer->tail) {
167+
return -1;
168+
} else {
169+
return buffer->buffer[buffer->tail];
170+
}
128171
}
129172

130173
int Serial_::read(void)
131174
{
132-
int c;
133-
if (_serialPeek != -1)
134-
{
135-
c = _serialPeek;
136-
_serialPeek = -1;
175+
ring_buffer *buffer = &cdc_rx_buffer;
176+
// if the head isn't ahead of the tail, we don't have any characters
177+
if (buffer->head == buffer->tail) {
178+
return -1;
137179
} else {
138-
c = USB_Recv(CDC_RX);
139-
}
140-
return c;
180+
unsigned char c = buffer->buffer[buffer->tail];
181+
buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE;
182+
return c;
183+
}
141184
}
142185

143186
void Serial_::flush(void)
@@ -169,7 +212,22 @@ size_t Serial_::write(uint8_t c)
169212
return 0;
170213
}
171214

215+
// This operator is a convenient way for a sketch to check whether the
216+
// port has actually been configured and opened by the host (as opposed
217+
// to just being connected to the host). It can be used, for example, in
218+
// setup() before printing to ensure that an application on the host is
219+
// actually ready to receive and display the data.
220+
// We add a short delay before returning to fix a bug observed by Federico
221+
// where the port is configured (lineState != 0) but not quite opened.
222+
Serial_::operator bool() {
223+
bool result = false;
224+
if (_usbLineInfo.lineState > 0)
225+
result = true;
226+
delay(10);
227+
return result;
228+
}
229+
172230
Serial_ Serial;
173231

174232
#endif
175-
#endif /* if defined(USBCON) */
233+
#endif /* if defined(USBCON) */

hardware/arduino/avr/cores/arduino/HID.cpp

Lines changed: 109 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ u8 _hid_protocol = 1;
144144
u8 _hid_idle = 1;
145145

146146
#define WEAK __attribute__ ((weak))
147-
#define WEAK
148147

149148
int WEAK HID_GetInterface(u8* interfaceNum)
150149
{
@@ -202,7 +201,15 @@ bool WEAK HID_Setup(Setup& setup)
202201
//================================================================================
203202
// Mouse
204203

205-
Mouse_::Mouse_() : _buttons(0)
204+
Mouse_::Mouse_(void) : _buttons(0)
205+
{
206+
}
207+
208+
void Mouse_::begin(void)
209+
{
210+
}
211+
212+
void Mouse_::end(void)
206213
{
207214
}
208215

@@ -245,7 +252,7 @@ void Mouse_::release(uint8_t b)
245252

246253
bool Mouse_::isPressed(uint8_t b)
247254
{
248-
if (b & _buttons > 0)
255+
if ((b & _buttons) > 0)
249256
return true;
250257
return false;
251258
}
@@ -254,18 +261,21 @@ bool Mouse_::isPressed(uint8_t b)
254261
//================================================================================
255262
// Keyboard
256263

257-
Keyboard_::Keyboard_() : _keyMap(0)
264+
Keyboard_::Keyboard_(void)
258265
{
259266
}
260267

261-
void Keyboard_::sendReport(KeyReport* keys)
268+
void Keyboard_::begin(void)
269+
{
270+
}
271+
272+
void Keyboard_::end(void)
262273
{
263-
HID_SendReport(2,keys,sizeof(KeyReport));
264274
}
265275

266-
void Keyboard_::setKeyMap(KeyMap* keyMap)
276+
void Keyboard_::sendReport(KeyReport* keys)
267277
{
268-
_keyMap = keyMap;
278+
HID_SendReport(2,keys,sizeof(KeyReport));
269279
}
270280

271281
extern
@@ -406,41 +416,105 @@ const uint8_t _asciimap[128] =
406416
};
407417

408418
uint8_t USBPutChar(uint8_t c);
409-
size_t Keyboard_::write(uint8_t c)
419+
420+
// press() adds the specified key (printing, non-printing, or modifier)
421+
// to the persistent key report and sends the report. Because of the way
422+
// USB HID works, the host acts like the key remains pressed until we
423+
// call release(), releaseAll(), or otherwise clear the report and resend.
424+
size_t Keyboard_::press(uint8_t k)
410425
{
411-
// Keydown
412-
{
413-
KeyReport keys = {0};
414-
if (_keyMap)
415-
_keyMap->charToKey(c,&keys);
416-
else
417-
{
418-
if (c >= 128) {
419-
setWriteError();
420-
return 0;
421-
}
422-
c = pgm_read_byte(_asciimap + c);
423-
if (!c) {
424-
setWriteError();
425-
return 0;
426-
}
427-
if (c & 0x80)
428-
{
429-
keys.modifiers |= KEY_MODIFIER_LEFT_SHIFT;
430-
c &= 0x7F;
426+
uint8_t i;
427+
if (k >= 136) { // it's a non-printing key (not a modifier)
428+
k = k - 136;
429+
} else if (k >= 128) { // it's a modifier key
430+
_keyReport.modifiers |= (1<<(k-128));
431+
k = 0;
432+
} else { // it's a printing key
433+
k = pgm_read_byte(_asciimap + k);
434+
if (!k) {
435+
setWriteError();
436+
return 0;
437+
}
438+
if (k & 0x80) { // it's a capital letter or other character reached with shift
439+
_keyReport.modifiers |= 0x02; // the left shift modifier
440+
k &= 0x7F;
441+
}
442+
}
443+
444+
// Add k to the key report only if it's not already present
445+
// and if there is an empty slot.
446+
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
447+
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
448+
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
449+
450+
for (i=0; i<6; i++) {
451+
if (_keyReport.keys[i] == 0x00) {
452+
_keyReport.keys[i] = k;
453+
break;
431454
}
432-
keys.keys[0] = c;
433455
}
434-
sendReport(&keys);
456+
if (i == 6) {
457+
setWriteError();
458+
return 0;
459+
}
435460
}
436-
// Keyup
437-
{
438-
KeyReport keys = {0};
439-
sendReport(&keys);
461+
sendReport(&_keyReport);
462+
return 1;
463+
}
464+
465+
// release() takes the specified key out of the persistent key report and
466+
// sends the report. This tells the OS the key is no longer pressed and that
467+
// it shouldn't be repeated any more.
468+
size_t Keyboard_::release(uint8_t k)
469+
{
470+
uint8_t i;
471+
if (k >= 136) { // it's a non-printing key (not a modifier)
472+
k = k - 136;
473+
} else if (k >= 128) { // it's a modifier key
474+
_keyReport.modifiers &= ~(1<<(k-128));
475+
k = 0;
476+
} else { // it's a printing key
477+
k = pgm_read_byte(_asciimap + k);
478+
if (!k) {
479+
return 0;
480+
}
481+
if (k & 0x80) { // it's a capital letter or other character reached with shift
482+
_keyReport.modifiers &= ~(0x02); // the left shift modifier
483+
k &= 0x7F;
484+
}
440485
}
486+
487+
// Test the key report to see if k is present. Clear it if it exists.
488+
// Check all positions in case the key is present more than once (which it shouldn't be)
489+
for (i=0; i<6; i++) {
490+
if (0 != k && _keyReport.keys[i] == k) {
491+
_keyReport.keys[i] = 0x00;
492+
}
493+
}
494+
495+
sendReport(&_keyReport);
441496
return 1;
442497
}
443498

499+
void Keyboard_::releaseAll(void)
500+
{
501+
_keyReport.keys[0] = 0;
502+
_keyReport.keys[1] = 0;
503+
_keyReport.keys[2] = 0;
504+
_keyReport.keys[3] = 0;
505+
_keyReport.keys[4] = 0;
506+
_keyReport.keys[5] = 0;
507+
_keyReport.modifiers = 0;
508+
sendReport(&_keyReport);
509+
}
510+
511+
size_t Keyboard_::write(uint8_t c)
512+
{
513+
uint8_t p = press(c); // Keydown
514+
uint8_t r = release(c); // Keyup
515+
return (p); // just return the result of press() since release() almost always returns 1
516+
}
517+
444518
#endif
445519

446520
#endif /* if defined(USBCON) */

hardware/arduino/avr/cores/arduino/HardwareSerial.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@
4646
struct ring_buffer
4747
{
4848
unsigned char buffer[SERIAL_BUFFER_SIZE];
49-
volatile int head;
50-
volatile int tail;
49+
volatile unsigned int head;
50+
volatile unsigned int tail;
5151
};
5252

5353
#if defined(USBCON)
@@ -398,6 +398,10 @@ size_t HardwareSerial::write(uint8_t c)
398398
return 1;
399399
}
400400

401+
HardwareSerial::operator bool() {
402+
return true;
403+
}
404+
401405
// Preinstantiate Objects //////////////////////////////////////////////////////
402406

403407
#if defined(UBRRH) && defined(UBRRL)

hardware/arduino/avr/cores/arduino/HardwareSerial.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class HardwareSerial : public Stream
5757
virtual void flush(void);
5858
virtual size_t write(uint8_t);
5959
using Print::write; // pull in write(str) and write(buf, size) from Print
60+
operator bool();
6061
};
6162

6263
#if defined(UBRRH) || defined(UBRR0H)

hardware/arduino/avr/cores/arduino/Print.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ size_t Print::write(const uint8_t *buffer, size_t size)
4141

4242
size_t Print::print(const __FlashStringHelper *ifsh)
4343
{
44-
const prog_char *p = (const prog_char *)ifsh;
44+
const char PROGMEM *p = (const char PROGMEM *)ifsh;
4545
size_t n = 0;
4646
while (1) {
4747
unsigned char c = pgm_read_byte(p++);
@@ -226,6 +226,9 @@ size_t Print::printFloat(double number, uint8_t digits)
226226
{
227227
size_t n = 0;
228228

229+
if (isnan(number)) return print("nan");
230+
if (isinf(number)) return print("inf");
231+
229232
// Handle negative numbers
230233
if (number < 0.0)
231234
{

0 commit comments

Comments
 (0)