<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-cn">
		<id>http://wiki.ywrobot.net/index.php?action=history&amp;feed=atom&amp;title=CDC.cpp</id>
		<title>CDC.cpp - 版本历史</title>
		<link rel="self" type="application/atom+xml" href="http://wiki.ywrobot.net/index.php?action=history&amp;feed=atom&amp;title=CDC.cpp"/>
		<link rel="alternate" type="text/html" href="http://wiki.ywrobot.net/index.php?title=CDC.cpp&amp;action=history"/>
		<updated>2026-05-14T11:40:40Z</updated>
		<subtitle>本wiki的该页面的版本历史</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://wiki.ywrobot.net/index.php?title=CDC.cpp&amp;diff=58&amp;oldid=prev</id>
		<title>YWrobot WM：创建页面，内容为“&lt;pre style=&quot;color:blue&quot;&gt;   /* Copyright (c) 2011, Peter Barrett   **   ** Permission to use, copy, modify, and/or distribute this software for   ** any purpose with...”</title>
		<link rel="alternate" type="text/html" href="http://wiki.ywrobot.net/index.php?title=CDC.cpp&amp;diff=58&amp;oldid=prev"/>
				<updated>2016-04-25T02:01:01Z</updated>
		
		<summary type="html">&lt;p&gt;创建页面，内容为“&amp;lt;pre style=&amp;quot;color:blue&amp;quot;&amp;gt;   /* Copyright (c) 2011, Peter Barrett   **   ** Permission to use, copy, modify, and/or distribute this software for   ** any purpose with...”&lt;/p&gt;
&lt;p&gt;&lt;b&gt;新页面&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;pre style=&amp;quot;color:blue&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* Copyright (c) 2011, Peter Barrett  &lt;br /&gt;
**  &lt;br /&gt;
** Permission to use, copy, modify, and/or distribute this software for  &lt;br /&gt;
** any purpose with or without fee is hereby granted, provided that the  &lt;br /&gt;
** above copyright notice and this permission notice appear in all copies.  &lt;br /&gt;
** &lt;br /&gt;
** THE SOFTWARE IS PROVIDED &amp;quot;AS IS&amp;quot; AND THE AUTHOR DISCLAIMS ALL  &lt;br /&gt;
** WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED  &lt;br /&gt;
** WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR  &lt;br /&gt;
** BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES  &lt;br /&gt;
** OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,  &lt;br /&gt;
** WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  &lt;br /&gt;
** ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS  &lt;br /&gt;
** SOFTWARE.  &lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;Platform.h&amp;quot;&lt;br /&gt;
#include &amp;quot;USBAPI.h&amp;quot;&lt;br /&gt;
#include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#if defined(USBCON)&lt;br /&gt;
#ifdef CDC_ENABLED&lt;br /&gt;
&lt;br /&gt;
#if (RAMEND &amp;lt; 1000)&lt;br /&gt;
#define SERIAL_BUFFER_SIZE 16&lt;br /&gt;
#else&lt;br /&gt;
#define SERIAL_BUFFER_SIZE 64&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
struct ring_buffer&lt;br /&gt;
{&lt;br /&gt;
	unsigned char buffer[SERIAL_BUFFER_SIZE];&lt;br /&gt;
	volatile int head;&lt;br /&gt;
	volatile int tail;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};&lt;br /&gt;
&lt;br /&gt;
typedef struct&lt;br /&gt;
{&lt;br /&gt;
	u32	dwDTERate;&lt;br /&gt;
	u8	bCharFormat;&lt;br /&gt;
	u8 	bParityType;&lt;br /&gt;
	u8 	bDataBits;&lt;br /&gt;
	u8	lineState;&lt;br /&gt;
} LineInfo;&lt;br /&gt;
&lt;br /&gt;
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };&lt;br /&gt;
&lt;br /&gt;
#define WEAK __attribute__ ((weak))&lt;br /&gt;
&lt;br /&gt;
extern const CDCDescriptor _cdcInterface PROGMEM;&lt;br /&gt;
const CDCDescriptor _cdcInterface =&lt;br /&gt;
{&lt;br /&gt;
	D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),&lt;br /&gt;
&lt;br /&gt;
	//	CDC communication interface&lt;br /&gt;
	D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),&lt;br /&gt;
	D_CDCCS(CDC_HEADER,0x10,0x01),								// Header (1.10 bcd)&lt;br /&gt;
	D_CDCCS(CDC_CALL_MANAGEMENT,1,1),							// Device handles call management (not)&lt;br /&gt;
	D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,6),				// SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported&lt;br /&gt;
	D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE),	// Communication interface is master, data interface is slave 0&lt;br /&gt;
	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40),&lt;br /&gt;
&lt;br /&gt;
	//	CDC data interface&lt;br /&gt;
	D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),&lt;br /&gt;
	D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0),&lt;br /&gt;
	D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0)&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
int WEAK CDC_GetInterface(u8* interfaceNum)&lt;br /&gt;
{&lt;br /&gt;
	interfaceNum[0] += 2;	// uses 2&lt;br /&gt;
	return USB_SendControl(TRANSFER_PGM,&amp;amp;_cdcInterface,sizeof(_cdcInterface));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bool WEAK CDC_Setup(Setup&amp;amp; setup)&lt;br /&gt;
{&lt;br /&gt;
	u8 r = setup.bRequest;&lt;br /&gt;
	u8 requestType = setup.bmRequestType;&lt;br /&gt;
&lt;br /&gt;
	if (REQUEST_DEVICETOHOST_CLASS_INTERFACE == requestType)&lt;br /&gt;
	{&lt;br /&gt;
		if (CDC_GET_LINE_CODING == r)&lt;br /&gt;
		{&lt;br /&gt;
			USB_SendControl(0,(void*)&amp;amp;_usbLineInfo,7);&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	if (REQUEST_HOSTTODEVICE_CLASS_INTERFACE == requestType)&lt;br /&gt;
	{&lt;br /&gt;
		if (CDC_SET_LINE_CODING == r)&lt;br /&gt;
		{&lt;br /&gt;
			USB_RecvControl((void*)&amp;amp;_usbLineInfo,7);&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
		if (CDC_SET_CONTROL_LINE_STATE == r)&lt;br /&gt;
		{&lt;br /&gt;
			_usbLineInfo.lineState = setup.wValueL;&lt;br /&gt;
&lt;br /&gt;
			// auto-reset into the bootloader is triggered when the port, already &lt;br /&gt;
			// open at 1200 bps, is closed.  this is the signal to start the watchdog&lt;br /&gt;
			// with a relatively long period so it can finish housekeeping tasks&lt;br /&gt;
			// like servicing endpoints before the sketch ends&lt;br /&gt;
			if (1200 == _usbLineInfo.dwDTERate) {&lt;br /&gt;
				// We check DTR state to determine if host port is open (bit 0 of lineState).&lt;br /&gt;
				if ((_usbLineInfo.lineState &amp;amp; 0x01) == 0) {&lt;br /&gt;
					*(uint16_t *)0x0800 = 0x7777;&lt;br /&gt;
					wdt_enable(WDTO_120MS);&lt;br /&gt;
				} else {&lt;br /&gt;
					// Most OSs do some intermediate steps when configuring ports and DTR can&lt;br /&gt;
					// twiggle more than once before stabilizing.&lt;br /&gt;
					// To avoid spurious resets we set the watchdog to 250ms and eventually&lt;br /&gt;
					// cancel if DTR goes back high.&lt;br /&gt;
	&lt;br /&gt;
					wdt_disable();&lt;br /&gt;
					wdt_reset();&lt;br /&gt;
					*(uint16_t *)0x0800 = 0x0;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			return true;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	return false;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int _serialPeek = -1;&lt;br /&gt;
void Serial_::begin(uint16_t baud_count)&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Serial_::end(void)&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Serial_::accept(void) &lt;br /&gt;
{&lt;br /&gt;
	ring_buffer *buffer = &amp;amp;cdc_rx_buffer;&lt;br /&gt;
	int i = (unsigned int)(buffer-&amp;gt;head+1) % SERIAL_BUFFER_SIZE;&lt;br /&gt;
	&lt;br /&gt;
	// if we should be storing the received character into the location&lt;br /&gt;
	// just before the tail (meaning that the head would advance to the&lt;br /&gt;
	// current location of the tail), we're about to overflow the buffer&lt;br /&gt;
	// and so we don't write the character or advance the head.&lt;br /&gt;
&lt;br /&gt;
	// while we have room to store a byte&lt;br /&gt;
	while (i != buffer-&amp;gt;tail) {&lt;br /&gt;
		int c = USB_Recv(CDC_RX);&lt;br /&gt;
		if (c == -1)&lt;br /&gt;
			break;	// no more data&lt;br /&gt;
		buffer-&amp;gt;buffer[buffer-&amp;gt;head] = c;&lt;br /&gt;
		buffer-&amp;gt;head = i;&lt;br /&gt;
&lt;br /&gt;
		i = (unsigned int)(buffer-&amp;gt;head+1) % SERIAL_BUFFER_SIZE;&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int Serial_::available(void)&lt;br /&gt;
{&lt;br /&gt;
	ring_buffer *buffer = &amp;amp;cdc_rx_buffer;&lt;br /&gt;
	return (unsigned int)(SERIAL_BUFFER_SIZE + buffer-&amp;gt;head - buffer-&amp;gt;tail) % SERIAL_BUFFER_SIZE;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int Serial_::peek(void)&lt;br /&gt;
{&lt;br /&gt;
	ring_buffer *buffer = &amp;amp;cdc_rx_buffer;&lt;br /&gt;
	if (buffer-&amp;gt;head == buffer-&amp;gt;tail) {&lt;br /&gt;
		return -1;&lt;br /&gt;
	} else {&lt;br /&gt;
		return buffer-&amp;gt;buffer[buffer-&amp;gt;tail];&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int Serial_::read(void)&lt;br /&gt;
{&lt;br /&gt;
	ring_buffer *buffer = &amp;amp;cdc_rx_buffer;&lt;br /&gt;
	// if the head isn't ahead of the tail, we don't have any characters&lt;br /&gt;
	if (buffer-&amp;gt;head == buffer-&amp;gt;tail) {&lt;br /&gt;
		return -1;&lt;br /&gt;
	} else {&lt;br /&gt;
		unsigned char c = buffer-&amp;gt;buffer[buffer-&amp;gt;tail];&lt;br /&gt;
		buffer-&amp;gt;tail = (unsigned int)(buffer-&amp;gt;tail + 1) % SERIAL_BUFFER_SIZE;&lt;br /&gt;
		return c;&lt;br /&gt;
	}	&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Serial_::flush(void)&lt;br /&gt;
{&lt;br /&gt;
	USB_Flush(CDC_TX);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
size_t Serial_::write(uint8_t c)&lt;br /&gt;
{&lt;br /&gt;
	/* only try to send bytes if the high-level CDC connection itself &lt;br /&gt;
	 is open (not just the pipe) - the OS should set lineState when the port&lt;br /&gt;
	 is opened and clear lineState when the port is closed.&lt;br /&gt;
	 bytes sent before the user opens the connection or after&lt;br /&gt;
	 the connection is closed are lost - just like with a UART. */&lt;br /&gt;
	&lt;br /&gt;
	// TODO - ZE - check behavior on different OSes and test what happens if an&lt;br /&gt;
	// open connection isn't broken cleanly (cable is yanked out, host dies&lt;br /&gt;
	// or locks up, or host virtual serial port hangs)&lt;br /&gt;
	if (_usbLineInfo.lineState &amp;gt; 0)	{&lt;br /&gt;
		int r = USB_Send(CDC_TX,&amp;amp;c,1);&lt;br /&gt;
		if (r &amp;gt; 0) {&lt;br /&gt;
			return r;&lt;br /&gt;
		} else {&lt;br /&gt;
			setWriteError();&lt;br /&gt;
			return 0;&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
	setWriteError();&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// This operator is a convenient way for a sketch to check whether the&lt;br /&gt;
// port has actually been configured and opened by the host (as opposed&lt;br /&gt;
// to just being connected to the host).  It can be used, for example, in &lt;br /&gt;
// setup() before printing to ensure that an application on the host is&lt;br /&gt;
// actually ready to receive and display the data.&lt;br /&gt;
// We add a short delay before returning to fix a bug observed by Federico&lt;br /&gt;
// where the port is configured (lineState != 0) but not quite opened.&lt;br /&gt;
Serial_::operator bool() {&lt;br /&gt;
	bool result = false;&lt;br /&gt;
	if (_usbLineInfo.lineState &amp;gt; 0) &lt;br /&gt;
		result = true;&lt;br /&gt;
	delay(10);&lt;br /&gt;
	return result;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
Serial_ Serial;&lt;br /&gt;
&lt;br /&gt;
#endif&lt;br /&gt;
#endif /* if defined(USBCON) */&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>YWrobot WM</name></author>	</entry>

	</feed>