You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
256 lines
8.2 KiB
256 lines
8.2 KiB
/* |
|
LUFA Library |
|
Copyright (C) Dean Camera, 2010. |
|
|
|
dean [at] fourwalledcubicle [dot] com |
|
www.fourwalledcubicle.com |
|
*/ |
|
|
|
/* |
|
Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com) |
|
|
|
Permission to use, copy, modify, distribute, and sell this |
|
software and its documentation for any purpose is hereby granted |
|
without fee, provided that the above copyright notice appear in |
|
all copies and that both that the copyright notice and this |
|
permission notice and warranty disclaimer appear in supporting |
|
documentation, and that the name of the author not be used in |
|
advertising or publicity pertaining to distribution of the |
|
software without specific, written prior permission. |
|
|
|
The author disclaim all warranties with regard to this |
|
software, including all implied warranties of merchantability |
|
and fitness. In no event shall the author be liable for any |
|
special, indirect or consequential damages or any damages |
|
whatsoever resulting from loss of use, data or profits, whether |
|
in an action of contract, negligence or other tortious action, |
|
arising out of or in connection with the use or performance of |
|
this software. |
|
*/ |
|
|
|
/** \file |
|
* |
|
* Main source file for the Arduino-usbserial project. This file contains the main tasks of |
|
* the project and is responsible for the initial application hardware configuration. |
|
*/ |
|
|
|
#include "Arduino-usbserial.h" |
|
#include "../../../Libraries/PPM_Encoder.h" |
|
|
|
|
|
/** Circular buffer to hold data from the host before it is sent to the device via the serial port. */ |
|
RingBuff_t USBtoUSART_Buffer; |
|
|
|
/** Circular buffer to hold data from the serial port before it is sent to the host. */ |
|
RingBuff_t USARTtoUSB_Buffer; |
|
|
|
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */ |
|
volatile struct |
|
{ |
|
uint8_t TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */ |
|
uint8_t RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */ |
|
uint8_t PingPongLEDPulse; /**< Milliseconds remaining for enumeration Tx/Rx ping-pong LED pulse */ |
|
} PulseMSRemaining; |
|
|
|
/** LUFA CDC Class driver interface configuration and state information. This structure is |
|
* passed to all CDC Class driver functions, so that multiple instances of the same class |
|
* within a device can be differentiated from one another. |
|
*/ |
|
USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface = |
|
{ |
|
.Config = |
|
{ |
|
.ControlInterfaceNumber = 0, |
|
|
|
.DataINEndpointNumber = CDC_TX_EPNUM, |
|
.DataINEndpointSize = CDC_TXRX_EPSIZE, |
|
.DataINEndpointDoubleBank = false, |
|
|
|
.DataOUTEndpointNumber = CDC_RX_EPNUM, |
|
.DataOUTEndpointSize = CDC_TXRX_EPSIZE, |
|
.DataOUTEndpointDoubleBank = false, |
|
|
|
.NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM, |
|
.NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE, |
|
.NotificationEndpointDoubleBank = false, |
|
}, |
|
}; |
|
|
|
/** Main program entry point. This routine contains the overall program flow, including initial |
|
* setup of all components and the main program loop. |
|
*/ |
|
int main(void) |
|
{ |
|
// Start PPM Encoder |
|
ppm_encoder_init(); |
|
|
|
|
|
// Unmodified Arduino code from here |
|
// -------------------------------------------- |
|
|
|
SetupHardware(); |
|
|
|
RingBuffer_InitBuffer(&USBtoUSART_Buffer); |
|
RingBuffer_InitBuffer(&USARTtoUSB_Buffer); |
|
|
|
sei(); |
|
|
|
|
|
for (;;) |
|
{ |
|
|
|
// Only try to read in bytes from the CDC interface if the transmit buffer is not full |
|
if (!(RingBuffer_IsFull(&USBtoUSART_Buffer))) |
|
{ |
|
int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); |
|
|
|
// Read bytes from the USB OUT endpoint into the USART transmit buffer |
|
if (!(ReceivedByte < 0)) |
|
RingBuffer_Insert(&USBtoUSART_Buffer, ReceivedByte); |
|
} |
|
|
|
// Check if the UART receive buffer flush timer has expired or the buffer is nearly full |
|
RingBuff_Count_t BufferCount = RingBuffer_GetCount(&USARTtoUSB_Buffer); |
|
if ((TIFR0 & (1 << TOV0)) || (BufferCount > BUFFER_NEARLY_FULL)) |
|
{ |
|
TIFR0 |= (1 << TOV0); |
|
|
|
if (USARTtoUSB_Buffer.Count) { |
|
LEDs_TurnOnLEDs(LEDMASK_TX); |
|
PulseMSRemaining.TxLEDPulse = TX_RX_LED_PULSE_MS; |
|
} |
|
|
|
// Read bytes from the USART receive buffer into the USB IN endpoint |
|
while (BufferCount--) |
|
CDC_Device_SendByte(&VirtualSerial_CDC_Interface, RingBuffer_Remove(&USARTtoUSB_Buffer)); |
|
|
|
// Turn off TX LED(s) once the TX pulse period has elapsed |
|
if (PulseMSRemaining.TxLEDPulse && !(--PulseMSRemaining.TxLEDPulse)) |
|
LEDs_TurnOffLEDs(LEDMASK_TX); |
|
|
|
// Turn off RX LED(s) once the RX pulse period has elapsed |
|
if (PulseMSRemaining.RxLEDPulse && !(--PulseMSRemaining.RxLEDPulse)) |
|
LEDs_TurnOffLEDs(LEDMASK_RX); |
|
} |
|
|
|
// Load the next byte from the USART transmit buffer into the USART |
|
if (!(RingBuffer_IsEmpty(&USBtoUSART_Buffer))) { |
|
Serial_TxByte(RingBuffer_Remove(&USBtoUSART_Buffer)); |
|
|
|
LEDs_TurnOnLEDs(LEDMASK_RX); |
|
PulseMSRemaining.RxLEDPulse = TX_RX_LED_PULSE_MS; |
|
} |
|
|
|
CDC_Device_USBTask(&VirtualSerial_CDC_Interface); |
|
USB_USBTask(); |
|
} |
|
|
|
} |
|
|
|
/** Configures the board hardware and chip peripherals for the demo's functionality. */ |
|
void SetupHardware(void) |
|
{ |
|
/* Disable watchdog if enabled by bootloader/fuses */ |
|
|
|
// Watchdog used by PPM Encoder to set failsafe values |
|
//MCUSR &= ~(1 << WDRF); |
|
//wdt_disable(); |
|
|
|
/* Hardware Initialization */ |
|
Serial_Init(9600, false); |
|
LEDs_Init(); |
|
USB_Init(); |
|
|
|
/* Start the flush timer so that overflows occur rapidly to push received bytes to the USB interface */ |
|
TCCR0B = (1 << CS02); |
|
|
|
/* Pull target /RESET line high */ |
|
AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; |
|
AVR_RESET_LINE_DDR |= AVR_RESET_LINE_MASK; |
|
} |
|
|
|
/** Event handler for the library USB Configuration Changed event. */ |
|
void EVENT_USB_Device_ConfigurationChanged(void) |
|
{ |
|
CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface); |
|
} |
|
|
|
/** Event handler for the library USB Unhandled Control Request event. */ |
|
void EVENT_USB_Device_UnhandledControlRequest(void) |
|
{ |
|
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); |
|
} |
|
|
|
/** Event handler for the CDC Class driver Line Encoding Changed event. |
|
* |
|
* \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced |
|
*/ |
|
void EVENT_CDC_Device_LineEncodingChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) |
|
{ |
|
uint8_t ConfigMask = 0; |
|
|
|
switch (CDCInterfaceInfo->State.LineEncoding.ParityType) |
|
{ |
|
case CDC_PARITY_Odd: |
|
ConfigMask = ((1 << UPM11) | (1 << UPM10)); |
|
break; |
|
case CDC_PARITY_Even: |
|
ConfigMask = (1 << UPM11); |
|
break; |
|
} |
|
|
|
if (CDCInterfaceInfo->State.LineEncoding.CharFormat == CDC_LINEENCODING_TwoStopBits) |
|
ConfigMask |= (1 << USBS1); |
|
|
|
switch (CDCInterfaceInfo->State.LineEncoding.DataBits) |
|
{ |
|
case 6: |
|
ConfigMask |= (1 << UCSZ10); |
|
break; |
|
case 7: |
|
ConfigMask |= (1 << UCSZ11); |
|
break; |
|
case 8: |
|
ConfigMask |= ((1 << UCSZ11) | (1 << UCSZ10)); |
|
break; |
|
} |
|
|
|
/* Must turn off USART before reconfiguring it, otherwise incorrect operation may occur */ |
|
UCSR1B = 0; |
|
UCSR1A = 0; |
|
UCSR1C = 0; |
|
|
|
/* Special case 57600 baud for compatibility with the ATmega328 bootloader. */ |
|
UBRR1 = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600) |
|
? SERIAL_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS) |
|
: SERIAL_2X_UBBRVAL(CDCInterfaceInfo->State.LineEncoding.BaudRateBPS); |
|
|
|
UCSR1C = ConfigMask; |
|
UCSR1A = (CDCInterfaceInfo->State.LineEncoding.BaudRateBPS == 57600) ? 0 : (1 << U2X1); |
|
UCSR1B = ((1 << RXCIE1) | (1 << TXEN1) | (1 << RXEN1)); |
|
} |
|
|
|
/** ISR to manage the reception of data from the serial port, placing received bytes into a circular buffer |
|
* for later transmission to the host. |
|
*/ |
|
ISR(USART1_RX_vect, ISR_BLOCK) |
|
{ |
|
uint8_t ReceivedByte = UDR1; |
|
|
|
if (USB_DeviceState == DEVICE_STATE_Configured) |
|
RingBuffer_Insert(&USARTtoUSB_Buffer, ReceivedByte); |
|
} |
|
|
|
/** Event handler for the CDC Class driver Host-to-Device Line Encoding Changed event. |
|
* |
|
* \param[in] CDCInterfaceInfo Pointer to the CDC class interface configuration structure being referenced |
|
*/ |
|
void EVENT_CDC_Device_ControLineStateChanged(USB_ClassInfo_CDC_Device_t* const CDCInterfaceInfo) |
|
{ |
|
bool CurrentDTRState = (CDCInterfaceInfo->State.ControlLineStates.HostToDevice & CDC_CONTROL_LINE_OUT_DTR); |
|
|
|
if (CurrentDTRState) |
|
AVR_RESET_LINE_PORT &= ~AVR_RESET_LINE_MASK; |
|
else |
|
AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; |
|
}
|
|
|