From 37b69b854997391ab22188ac2c955fd7fe4b5654 Mon Sep 17 00:00:00 2001 From: PaulStoffregen Date: Fri, 10 Jun 2022 03:56:39 -0700 Subject: [PATCH] Add function descriptions for Arduino IDE 2.0 language server --- teensy4/Print.h | 9 ++++-- teensy4/core_pins.h | 8 ++++++ teensy4/delay.c | 9 ++++++ teensy4/elapsedMillis.h | 8 ++++++ teensy4/usb_serial.h | 61 ++++++++++++++++++++++++++++++++++++++++- 5 files changed, 92 insertions(+), 3 deletions(-) diff --git a/teensy4/Print.h b/teensy4/Print.h index b3d6006bf..053cc5797 100644 --- a/teensy4/Print.h +++ b/teensy4/Print.h @@ -110,10 +110,15 @@ class Print size_t println(const Printable &obj) { return obj.printTo(*this) + println(); } int getWriteError() { return write_error; } void clearWriteError() { setWriteError(0); } + + // printf is a C standard function which allows you to print any number of variables using a somewhat cryptic format string + int printf(const char *format, ...) + int printf(const __FlashStringHelper *format, ...); + // format warnings are too pedantic - disable until newer toolchain offers better... // https://forum.pjrc.com/threads/62473?p=256873&viewfull=1#post256873 - int printf(const char *format, ...) /*__attribute__ ((format (printf, 2, 3)))*/; - int printf(const __FlashStringHelper *format, ...); + // int printf(const char *format, ...) __attribute__ ((format (printf, 2, 3))); + protected: void setWriteError(int err = 1) { write_error = err; } private: diff --git a/teensy4/core_pins.h b/teensy4/core_pins.h index 4259d8482..dd25f85b0 100644 --- a/teensy4/core_pins.h +++ b/teensy4/core_pins.h @@ -2357,6 +2357,9 @@ extern volatile uint32_t scale_cpu_cycles_to_microseconds; extern volatile uint32_t systick_millis_count; static inline uint32_t millis(void) __attribute__((always_inline, unused)); +// Returns the number of milliseconds since your program started running. +// This 32 bit number will roll back to zero after about 49.7 days. For a +// simpler way to build delays or timeouts, consider using elapsedMillis. static inline uint32_t millis(void) { return systick_millis_count; @@ -2365,6 +2368,9 @@ static inline uint32_t millis(void) uint32_t micros(void); static inline void delayMicroseconds(uint32_t) __attribute__((always_inline, unused)); +// Wait for a number of microseconds. During this time, interrupts remain +// active, but the rest of your program becomes effectively stalled. For shorter +// delay, use delayNanoseconds(). static inline void delayMicroseconds(uint32_t usec) { uint32_t begin = ARM_DWT_CYCCNT; @@ -2374,6 +2380,8 @@ static inline void delayMicroseconds(uint32_t usec) } static inline void delayNanoseconds(uint32_t) __attribute__((always_inline, unused)); +// Wait for a number of nanoseconds. During this time, interrupts remain +// active, but the rest of your program becomes effectively stalled. static inline void delayNanoseconds(uint32_t nsec) { uint32_t begin = ARM_DWT_CYCCNT; diff --git a/teensy4/delay.c b/teensy4/delay.c index ac459ec0f..277deae68 100644 --- a/teensy4/delay.c +++ b/teensy4/delay.c @@ -48,6 +48,11 @@ void millis_init(void) }*/ +// Wait for a number of milliseconds. During this time, interrupts remain +// active, but the rest of your program becomes effectively stalled. Usually +// delay() is used in very simple programs. To achieve delay without waiting +// use millis() or elapsedMillis. For shorter delay, use delayMicroseconds() +// or delayNanoseconds(). void delay(uint32_t msec) { uint32_t start; @@ -64,6 +69,10 @@ void delay(uint32_t msec) // TODO... } +// Returns the number of microseconds since your program started running. +// This 32 bit number will roll back to zero after about 71 minutes and +// 35 seconds. For a simpler way to build delays or timeouts, consider +// using elapsedMicros. uint32_t micros(void) { uint32_t smc, scc; diff --git a/teensy4/elapsedMillis.h b/teensy4/elapsedMillis.h index 48cff11da..5d53d1889 100644 --- a/teensy4/elapsedMillis.h +++ b/teensy4/elapsedMillis.h @@ -31,6 +31,10 @@ #include "WProgram.h" #endif +// elapsedMillis acts as an integer which autoamtically increments 1000 times +// per second. Useful for creating delays, timeouts, or measuing how long an +// operation takes. You can create as many elapsedMillis variables as needed. +// All of them are independent. Any may be written, modified or read at any time. class elapsedMillis { private: @@ -54,6 +58,10 @@ class elapsedMillis elapsedMillis operator + (unsigned long val) const { elapsedMillis r(*this); r.ms -= val; return r; } }; +// elapsedMicros acts as an integer which autoamtically increments 1 million times +// per second. Useful for creating delays, timeouts, or measuing how long an +// operation takes. You can create as many elapsedMicros variables as needed. +// All of them are independent. Any may be written, modified or read at any time. class elapsedMicros { private: diff --git a/teensy4/usb_serial.h b/teensy4/usb_serial.h index 1ac0e7f58..0ec507fdf 100644 --- a/teensy4/usb_serial.h +++ b/teensy4/usb_serial.h @@ -72,7 +72,12 @@ class usb_serial_class : public Stream { public: constexpr usb_serial_class() {} - void begin(long) { + // Serial.begin(baud) is optional on Teensy. The main USB device port + // is always initialized early during startup. The baud rate setting + // is not used. Communication occurs at USB native speed. For + // compatibility with Arduino code, Serial.begin waits up to 2 seconds + // for your PC to open the virtual serial port. + void begin(long baud_unused) { uint32_t millis_begin = systick_millis_count; while (!(*this)) { uint32_t elapsed = systick_millis_count - millis_begin; @@ -88,31 +93,84 @@ class usb_serial_class : public Stream } } void end() { /* TODO: flush output and shut down USB port */ }; + // Returns the number of bytes which have been received from your PC and + // can be fetched using Serial.read() or Serial.readBytes(). virtual int available() { return usb_serial_available(); } + // Reads the next received byte, or returns -1 if nothing has been received + // from your PC. virtual int read() { return usb_serial_getchar(); } + // Returns the next received byte, but does not remove it from the receive + // buffer. Returns -1 if nothing has been received from your PC. virtual int peek() { return usb_serial_peekchar(); } + // Wait for all data written by print() or write() to actually transmit to + // your PC. On Teensy 4, this function has a known limitation where it + // returns early, when buffered data has been given to Teensy's USB device + // controller, but before your PC's USB host controller actually transfers + // the data across your USB cable. virtual void flush() { usb_serial_flush_output(); } // TODO: actually wait for data to leave USB... + // Discard all received data which has not been read. virtual void clear(void) { usb_serial_flush_input(); } + // Transmit a single byte to your PC virtual size_t write(uint8_t c) { return usb_serial_putchar(c); } + // Transmit a buffer containing any number of bytes to your PC virtual size_t write(const uint8_t *buffer, size_t size) { return usb_serial_write(buffer, size); } + // Transmit a single byte to your PC size_t write(unsigned long n) { return write((uint8_t)n); } + // Transmit a single byte to your PC size_t write(long n) { return write((uint8_t)n); } + // Transmit a single byte to your PC size_t write(unsigned int n) { return write((uint8_t)n); } + // Transmit a single byte to your PC size_t write(int n) { return write((uint8_t)n); } + // Returns the number of bytes which may be transmitted by write() or print() + // without waiting. Typically programs which must maintain rapid checking + // and response to sensors use availableForWrite() to decide whether to + // transmit. virtual int availableForWrite() { return usb_serial_write_buffer_free(); } using Print::write; + // Cause any previously transmitted data written to buffers to be actually + // sent over the USB cable to your PC as soon as possible. Normally writes + // are combined to efficiently use maximum size USB packets. Use of send_now() + // minimizes latency, but excessive use can lead to inefficient utilization + // of USB bandwidth. void send_now(void) { usb_serial_flush_output(); } + // Returns the baud rate configuration set by PC software. This setting is + // not used for USB communication. You would typically call this function + // when making a USB to Serial converter, where you wish to know the baud + // rate software on the PC intends for you to configure on the serial port. uint32_t baud(void) { return usb_cdc_line_coding[0]; } + // Returns the baud rate configuration set by PC software. This setting is + // not used for USB communication. You would typically call this function + // when making a USB to Serial converter, where you wish to know the baud + // rate software on the PC intends for you to configure on the serial port. uint8_t stopbits(void) { uint8_t b = usb_cdc_line_coding[1]; if (!b) b = 1; return b; } + // Returns the number of stop bits configuration set by PC software. This + // setting is not used for USB communication. You would typically call this + // function when making a USB to Serial converter, where you wish to know how + // the PC software intends for you to configure the serial port. uint8_t paritytype(void) { return usb_cdc_line_coding[1] >> 8; } // 0=none, 1=odd, 2=even + // Returns the number of data bits configuration set by PC software. + // 0=none, 1=odd, 2=even. This setting is not used for USB communication, + // which always checks for errors at the USB packet level. You would typically + // call this function when making a USB to Serial converter, where you wish + // to know how the PC software intends for you to configure the serial port. uint8_t numbits(void) { return usb_cdc_line_coding[1] >> 16; } + // Returns the current state of the virtual serial DTR signal. uint8_t dtr(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) ? 1 : 0; } + // Returns the current state of the virtual serial RTS signal. uint8_t rts(void) { return (usb_cdc_line_rtsdtr & USB_SERIAL_RTS) ? 1 : 0; } + // Testing Serial as a boolean indicates whether USB is active and a program + // running on your PC has raised the DTR signal, which typically means it has + // opened the port and is ready to communicate. operator bool() { yield(); return usb_configuration && (usb_cdc_line_rtsdtr & USB_SERIAL_DTR) && ((uint32_t)(systick_millis_count - usb_cdc_line_rtsdtr_millis) >= 15); } + // Read up to length bytes into a buffer. readBytes() will wait up to + // the number of milliseconds configured by setTimeout(). The return value + // is the number of bytes actually read, which may be zero if your PC + // does not send anything. To read without waiting, configure setTimeout(0). size_t readBytes(char *buffer, size_t length) { size_t count=0; unsigned long startMillis = millis(); @@ -125,6 +183,7 @@ class usb_serial_class : public Stream } }; +// Serial provides USB Virtual Serial communication with your computer. extern usb_serial_class Serial; extern void serialEvent(void); #endif // __cplusplus