⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usb_cdc_uart.c

📁 USB CDC and HID composite unit.
💻 C
📖 第 1 页 / 共 2 页
字号:
//	Flush_COMbuffers:	initialize COM ring buffer
//	COMGetByte:			read a byte from COM TX buffer
//	COMPutByte:			write a byte to COM RX buffer
//
//	called by USB0 interrupt
//-----------------------------------------------------------------------------

//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma save
#pragma nooverlay
#endif // SDCC

void Flush_COMbuffers( void )
{
	TXRDIdx = 0;
	TXWTIdx = 0;
	RXRDIdx = 0;
	RXWTIdx = 0;
	TXcount = 0;
	RXcount = 0;
	TXReady = FALSE;
	RXReady = TRUE;
	
	cs_Bulk_IN_full_packet = FALSE;
}

//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma restore
#endif // SDCC


// TX buffer (host --> UART), UART side
BYTE COMGetByte( void )
{
	BYTE dt;

	dt = TXBuffer[ TXRDIdx++ ];

	if ( TXRDIdx >= TXBUFSIZE  )			// at the end of the buffer
		TXRDIdx = 0;						// go to the head of the buffer

//	TXRDIdx &= (TXBUFSIZE - 1);				// when TXBUFSIZE is just power of 2
											// above two lines are simplied with this line
	TXcount--;
	TXReady = (TXcount != 0);

	return dt;
}

// RX buffer (UART --> host), UART side
void COMPutByte( BYTE dt )
{
	RXBuffer[ RXWTIdx++ ] = dt;

	if ( RXWTIdx >= RXBUFSIZE )				// at the end of the buffer
		RXWTIdx = 0;						// go to the head of the buffer

//	RXWTIdx &= (RXBUFSIZE - 1);				// when RXBUFSIZE is just power of 2
											// above two lines are simplied with this line
	RXcount++;
	RXReady = (RXcount != RXBUFSIZE);
}


//-----------------------------------------------------------------------------
// CDC_Handle_INT_IN
//-----------------------------------------------------------------------------
//
// Interrupt IN EP - Notification element
//	Return SerialState notification response (10 bytes) to host 
//	whenever the status are changed
//
//	response
//    0:  0xA1   bmRequestType
//    1:  0x20   bNotification (SERIAL_STATE)
//    2:  0x00   wValue
//    3:  0x00
//    4:  0x00   wIndex (Interface #, LSB first)
//    5:  0x00
//    6:  0x02   wLength (Data length = 2 bytes, LSB first)
//    7:  0x00
//    8:  xx     UART State Bitmap (16bits, LSB first)
//    9:  xx
//
//  UART State Bitmap
//    15-8: reserved
//    7:  (no spec extra) CTS
//    6:  bOverRun    overrun error
//    5:  bParity     parity error
//    4:  bFraming    framing error
//    3:  bRingSignal RI
//    2:  bBreak      break reception
//    1:  bTxCarrier  DSR
//    0:  bRxCarrier  DCD
//
//	called by USB0 interrupt
//-----------------------------------------------------------------------------

#define CS_SERIAL_STATE_NUM		0x08

static BYTE code serialStateResponse[ CS_SERIAL_STATE_NUM ] = 
{
	0xA1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00
};

//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma save
#pragma nooverlay
#endif // SDCC

void CDC_Handle_INT_IN( void )
{
	if ( Ep_StatusIN1 == EP_HALT )	return;

	if ( cs_Line_State_Update && IN1_FIFO_empty )	// must update and FIFO is empty?
	{
		cs_Line_State_Update = FALSE;
		IN1_FIFO_empty = FALSE;
													// Put Serial State Response on Fifo
		POLL_WRITE_BYTE(INDEX, 1);					// Set index to endpoint 1 registers
		FIFO_Write_code(FIFO_EP1, CS_SERIAL_STATE_NUM, serialStateResponse);	// send fixed header
		USB0DAT = cs_Line_State;					// Put UART state bitmap (LSB)
		while(USB0ADR & 0x80);
		USB0DAT = 0x00;								//						 (MSB)
		while(USB0ADR & 0x80);
		POLL_WRITE_BYTE(EINCSRL, rbInINPRDY);		// validate the FIFO
													// Set In Packet ready bit, indicating 
													// fresh data on Fifo 1
	}
}

//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma restore
#endif // SDCC

//-----------------------------------------------------------------------------
// CDC_Handle_Bulk_IN
//-----------------------------------------------------------------------------
//	Handle bulk IN EP
//	- RX buffer (UART --> host), USB side
//	- Copy data from RX buffer to bulk IN EP
//
//	This routine is called from mainloop
//-----------------------------------------------------------------------------

void CDC_Handle_Bulk_IN( void )
{
	BYTE send_cnt, first_cnt, second_cnt;
	Trxcnt pos;
	bit turnover;

	if ( Ep_StatusIN2 == EP_HALT ) return;			// If endpoint is ready, 

	if ( IN2_FIFO_empty && RXcount )				// Is FIFO empty, and any data to send?
	{
		IN2_FIFO_empty = FALSE;

		if ( RXcount > EP2_IN_PACKET_SIZE )			// determine the bytes to send in this transaction
			send_cnt = EP2_IN_PACKET_SIZE;
		else
			send_cnt = (BYTE)RXcount;

		pos = RXBUFSIZE - RXRDIdx;					// consider on wrap around of ring buffer
		if ( send_cnt < pos )
		{											// data fits without wrap around
			first_cnt = send_cnt;
			second_cnt = 0;
			turnover = FALSE;
		}
		else
		{											// wrap around is required
			first_cnt = (BYTE)pos;
			second_cnt = send_cnt - first_cnt;
			turnover = TRUE;
		}

		EIE1 &= ~0x02;										// disable USB interrupt
		FIFO_WRITE_FUNC( FIFO_EP2, first_cnt, &RXBuffer[ RXRDIdx ] );	// send bytes to FIFO
		if ( second_cnt != 0 )
			FIFO_WRITE_FUNC( FIFO_EP2, second_cnt, RXBuffer );
		POLL_WRITE_BYTE(INDEX, 2);							// Set index to endpoint 2 registers
		POLL_WRITE_BYTE(EINCSRL, rbInINPRDY);				// validate the FIFO
		EIE1 |= 0x02;										// enable USB interrupt

		if ( turnover )										// maintainance of buffer parameters
			RXRDIdx = second_cnt;
		else
			RXRDIdx += send_cnt;

		RXcount -= send_cnt;
		RXReady = (RXcount != RXBUFSIZE);
															// detect full-packet to send ZLP
		cs_Bulk_IN_full_packet = (send_cnt == EP2_IN_PACKET_SIZE);
	}
}

//-----------------------------------------------------------------------------
// CDC_Handle_Bulk_IN_ZLP
//-----------------------------------------------------------------------------
//	When the size of the last packet of the transfer is just the wMaxPacketSize of the EP,
//	ZLP is required to terminate the transfer.
//
//	called by USB0 interrupt
//-----------------------------------------------------------------------------

//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma save
#pragma nooverlay
#endif // SDCC

void CDC_Handle_Bulk_IN_ZLP( void )
{
	if ( cs_Bulk_IN_full_packet && IN2_FIFO_empty && (RXcount == 0) )
	{														// Send ZLP
		POLL_WRITE_BYTE(INDEX, 2);							// Set index to endpoint 2 registers
		POLL_WRITE_BYTE(EINCSRL, rbInINPRDY);				// validate the FIFO without any data
	}
}

//---------------------------
// SDCC suport
//---------------------------
#if defined SDCC
#pragma restore
#endif // SDCC


//-----------------------------------------------------------------------------
// CDC_Handle_Bulk_OUT
//-----------------------------------------------------------------------------
//	Handle bulk OUT EP
//	- TX buffer (host --> UART), USB side
//	- Copy data from bulk OUT EP to TX buffer
//
//	This routine is called from mainloop
//
//-----------------------------------------------------------------------------

void CDC_Handle_Bulk_OUT( void )
{
	BYTE FIFO_Cnt, first_cnt, second_cnt;
	Ttxcnt pos;
	bit turnover;

	if ( Ep_StatusOUT2 == EP_HALT )	return;			// If endpoint is ready

	if ( OUT2_FIFO_loaded )							// FIFO has data?
	{
		OUT2_FIFO_loaded = FALSE;

		EIE1 &= ~0x02;								// disable USB interrupt
		POLL_WRITE_BYTE(INDEX, 2);					// Set index to endpoint 2 registers
		POLL_READ_BYTE(EOUTCNTL, FIFO_Cnt);			// read out number of bytes on the FIFO

		if ( (TXBUFSIZE - TXcount) >= FIFO_Cnt )	// if any room on the buffer to read out the FIFO
		{
			pos = TXBUFSIZE - TXWTIdx;				// consider on wrap around of ring buffer
			if ( FIFO_Cnt < pos )
			{
				first_cnt = FIFO_Cnt;
				second_cnt = 0;
				turnover = FALSE;
			}
			else
			{
				first_cnt = (BYTE)pos;
				second_cnt = FIFO_Cnt - first_cnt;
				turnover = TRUE;
			}

			FIFO_READ_FUNC( FIFO_EP2, first_cnt, &TXBuffer[ TXWTIdx ] );	// read bytes from FIFO
			if ( second_cnt != 0 )
				FIFO_READ_FUNC( FIFO_EP2, second_cnt, TXBuffer );
			POLL_WRITE_BYTE(EOUTCSRL, 0);					// Clear Out Packet ready bit

			if ( turnover )									// maintainance of buffer parameters
				TXWTIdx = second_cnt;
			else
				TXWTIdx += FIFO_Cnt;

			TXcount += FIFO_Cnt;
			TXReady = (TXcount != 0);
		}
		EIE1 |= 0x02;										// enable USB interrupt
	}
}

//-----------------------------------------------------------------------------
// End Of File
//-----------------------------------------------------------------------------

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -