aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Code_Composer/twine_usblib/usb_serial_adapter.c
diff options
context:
space:
mode:
Diffstat (limited to 'Software/Code_Composer/twine_usblib/usb_serial_adapter.c')
-rw-r--r--Software/Code_Composer/twine_usblib/usb_serial_adapter.c479
1 files changed, 479 insertions, 0 deletions
diff --git a/Software/Code_Composer/twine_usblib/usb_serial_adapter.c b/Software/Code_Composer/twine_usblib/usb_serial_adapter.c
new file mode 100644
index 000000000..9cf3ef3b4
--- /dev/null
+++ b/Software/Code_Composer/twine_usblib/usb_serial_adapter.c
@@ -0,0 +1,479 @@
+//Twine USB Serial Communication Library
+
+//! Assuming you installed TivaWare in the default directory, a
+//! driver information (INF) file for use with Windows XP, Windows Vista and
+//! Windows7 can be found in C:/ti/TivaWare-for-C-Series/windows_drivers.
+//! For Windows 2000, the required INF file is in
+//! C:/ti/TivaWare-for-C-Series/windows_drivers/win2K.
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include "inc/hw_ints.h"
+#include "inc/hw_memmap.h"
+#include "inc/hw_types.h"
+#include "inc/hw_uart.h"
+#include "driverlib/debug.h"
+#include "driverlib/gpio.h"
+#include "driverlib/interrupt.h"
+#include "driverlib/sysctl.h"
+#include "driverlib/systick.h"
+#include "driverlib/timer.h"
+#include "driverlib/uart.h"
+#include "driverlib/usb.h"
+#include "driverlib/rom.h"
+#include "driverlib/rom_map.h"
+#include "usblib/usblib.h"
+#include "usblib/usbcdc.h"
+#include "usblib/usb-ids.h"
+#include "usblib/device/usbdevice.h"
+#include "usblib/device/usbdcdc.h"
+#include <ti/sysbios/knl/Task.h>
+#include "utils/ustdlib.h"
+#include "usb_serial_structs.h"
+#include "usb_serial_buffer.h"
+#include "usb_serial_adapter.h"
+
+static SerialBuffer inBuffer;
+
+//*****************************************************************************
+//
+// This function is called whenever serial data is received from the UART.
+// It is passed the accumulated error flags from each character received in
+// this interrupt and determines from them whether or not an interrupt
+// notification to the host is required.
+//
+// If a notification is required and the control interrupt endpoint is idle,
+// we send the notification immediately. If the endpoint is not idle, we
+// accumulate the errors in a global variable which will be checked on
+// completion of the previous notification and used to send a second one
+// if necessary.
+//
+//*****************************************************************************
+void CheckForSerialStateChange(const tUSBDCDCDevice *psDevice, uint32_t ui32Errors)
+{
+ uint16_t ui16SerialState;
+
+ //
+ // Clear our USB serial state. Since we are faking the handshakes, always
+ // set the TXCARRIER (DSR) and RXCARRIER (DCD) bits.
+ //
+ ui16SerialState = USB_CDC_SERIAL_STATE_TXCARRIER |
+ USB_CDC_SERIAL_STATE_RXCARRIER;
+
+ //
+ // Are any error bits set?
+ //
+ if(ui32Errors)
+ {
+ //
+ // At least one error is being notified so translate from our hardware
+ // error bits into the correct state markers for the USB notification.
+ //
+ if(ui32Errors & UART_DR_OE)
+ {
+ ui16SerialState |= USB_CDC_SERIAL_STATE_OVERRUN;
+ }
+
+ if(ui32Errors & UART_DR_PE)
+ {
+ ui16SerialState |= USB_CDC_SERIAL_STATE_PARITY;
+ }
+
+ if(ui32Errors & UART_DR_FE)
+ {
+ ui16SerialState |= USB_CDC_SERIAL_STATE_FRAMING;
+ }
+
+ if(ui32Errors & UART_DR_BE)
+ {
+ ui16SerialState |= USB_CDC_SERIAL_STATE_BREAK;
+ }
+
+ //
+ // Call the CDC driver to notify the state change.
+ //
+ USBDCDCSerialStateChange((void *)psDevice, ui16SerialState);
+ }
+}
+
+//*****************************************************************************
+//
+// Set the state of the RS232 RTS and DTR signals.
+//
+//*****************************************************************************
+void SetControlLineState(uint16_t ui16State)
+{
+ //
+ // TODO: If configured with GPIOs controlling the handshake lines,
+ // set them appropriately depending upon the flags passed in the wValue
+ // field of the request structure passed.
+ //
+}
+
+//*****************************************************************************
+//
+// Get the communication parameters in use on the UART.
+//
+//*****************************************************************************
+void GetLineCoding(tLineCoding *psLineCoding)
+{
+ psLineCoding->ui32Rate = 9600;
+ psLineCoding->ui8Databits = 8;
+ psLineCoding->ui8Parity = USB_CDC_PARITY_NONE;
+ psLineCoding->ui8Stop = USB_CDC_STOP_BITS_1;
+}
+
+//*****************************************************************************
+//
+// Handles CDC driver notifications related to control and setup of the device.
+//
+// \param pvCBData is the client-supplied callback pointer for this channel.
+// \param ulEvent identifies the event we are being notified about.
+// \param ulMsgValue is an event-specific value.
+// \param pvMsgData is an event-specific pointer.
+//
+// This function is called by the CDC driver to perform control-related
+// operations on behalf of the USB host. These functions include setting
+// and querying the serial communication parameters, setting handshake line
+// states and sending break conditions.
+//
+// \return The return value is event-specific.
+//
+//*****************************************************************************
+uint32_t ControlHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData)
+{
+ //
+ // Which event are we being asked to process?
+ //
+ switch(ui32Event)
+ {
+ //
+ // We are connected to a host and communication is now possible.
+ //
+ case USB_EVENT_CONNECTED:
+ {
+ //
+ // Now connected and ready for normal operation.
+ //
+ HWREGBITW(&g_ui32Flags, FLAG_USB_CONFIGURED) = 1;
+
+ //
+ // Flush our buffers.
+ //
+ USBBufferFlush(&g_sTxBuffer);
+ USBBufferFlush(&g_sRxBuffer);
+
+ //TODO: Notify connection!
+
+ //
+ // Set the command status update flag.
+ //
+ HWREGBITW(&g_ui32Flags, FLAG_STATUS_UPDATE) = 1;
+
+ break;
+ }
+
+ //
+ // The host has disconnected.
+ //
+ case USB_EVENT_DISCONNECTED:
+ {
+ //
+ // No longer connected.
+ //
+ HWREGBITW(&g_ui32Flags, FLAG_USB_CONFIGURED) = 0;
+
+ //TODO: Notify disconnection!
+
+ //
+ // Set the command status update flag.
+ //
+ HWREGBITW(&g_ui32Flags, FLAG_STATUS_UPDATE) = 1;
+
+ break;
+ }
+
+ //
+ // Return the current serial communication parameters.
+ //
+ case USBD_CDC_EVENT_GET_LINE_CODING:
+ {
+ GetLineCoding(pvMsgData);
+ break;
+ }
+
+ //
+ // Set the current serial communication parameters.
+ //
+ case USBD_CDC_EVENT_SET_LINE_CODING:
+ {
+ GetLineCoding(pvMsgData);
+ break;
+ }
+
+ //
+ // Set the current serial communication parameters.
+ //
+ case USBD_CDC_EVENT_SET_CONTROL_LINE_STATE:
+ {
+ SetControlLineState((uint16_t)ui32MsgValue);
+ break;
+ }
+
+ //
+ // Send a break condition on the serial line.
+ //
+ case USBD_CDC_EVENT_SEND_BREAK:
+ {
+ break;
+ }
+
+ //
+ // Clear the break condition on the serial line.
+ //
+ case USBD_CDC_EVENT_CLEAR_BREAK:
+ {
+ break;
+ }
+
+ //
+ // Ignore SUSPEND and RESUME for now.
+ //
+ case USB_EVENT_SUSPEND:
+ case USB_EVENT_RESUME:
+ {
+ break;
+ }
+
+ //
+ // We don't expect to receive any other events. Ignore any that show
+ // up in a release build or hang in a debug build.
+ //
+ default:
+ {
+#ifdef DEBUG
+ while(1);
+#else
+ break;
+#endif
+ }
+
+ }
+
+ return(0);
+}
+
+//*****************************************************************************
+//
+// Handles CDC driver notifications related to the transmit channel (data to
+// the USB host).
+//
+// \param pvCBData is the client-supplied callback pointer for this channel.
+// \param ui32Event identifies the event we are being notified about.
+// \param ui32MsgValue is an event-specific value.
+// \param pvMsgData is an event-specific pointer.
+//
+// This function is called by the CDC driver to notify us of any events
+// related to operation of the transmit data channel (the IN channel carrying
+// data to the USB host).
+//
+// \return The return value is event-specific.
+//
+//*****************************************************************************
+uint32_t TxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue, void *pvMsgData)
+{
+ //
+ // Which event have we been sent?
+ //
+ switch(ui32Event)
+ {
+ case USB_EVENT_TX_COMPLETE:
+ {
+ //
+ // Since we are using the USBBuffer, we don't need to do anything
+ // here.
+ //
+ break;
+ }
+
+ //
+ // We don't expect to receive any other events. Ignore any that show
+ // up in a release build or hang in a debug build.
+ //
+ default:
+ {
+#ifdef DEBUG
+ while(1);
+#else
+ break;
+#endif
+ }
+ }
+ return(0);
+}
+
+//*****************************************************************************
+//
+// Handles CDC driver notifications related to the receive channel (data from
+// the USB host).
+//
+// \param pvCBData is the client-supplied callback data value for this channel.
+// \param ui32Event identifies the event we are being notified about.
+// \param ui32MsgValue is an event-specific value.
+// \param pvMsgData is an event-specific pointer.
+//
+// This function is called by the CDC driver to notify us of any events
+// related to operation of the receive data channel (the OUT channel carrying
+// data from the USB host).
+//
+// \return The return value is event-specific.
+//
+//*****************************************************************************
+uint32_t RxHandler(void *pvCBData, uint32_t ui32Event, uint32_t ui32MsgValue,void *pvMsgData)
+{
+ //
+ // Which event are we being sent?
+ //
+ switch(ui32Event)
+ {
+ //
+ // A new packet has been received.
+ //
+ case USB_EVENT_RX_AVAILABLE:
+ {
+ //
+ // Feed some characters into the UART TX FIFO and enable the
+ // interrupt so we are told when there is more space.
+ //
+ handleRx();
+ break;
+ }
+
+ //
+ // We are being asked how much unprocessed data we have still to
+ // process. We return 0 if the UART is currently idle or 1 if it is
+ // in the process of transmitting something. The actual number of
+ // bytes in the UART FIFO is not important here, merely whether or
+ // not everything previously sent to us has been transmitted.
+ //
+ case USB_EVENT_DATA_REMAINING:
+ {
+ //
+ // Get the number of bytes in the buffer and add 1 if some data
+ // still has to clear the transmitter.
+ return(0);
+ }
+
+ //
+ // We are being asked to provide a buffer into which the next packet
+ // can be read. We do not support this mode of receiving data so let
+ // the driver know by returning 0. The CDC driver should not be sending
+ // this message but this is included just for illustration and
+ // completeness.
+ //
+ case USB_EVENT_REQUEST_BUFFER:
+ {
+ return(0);
+ }
+
+ //
+ // We don't expect to receive any other events. Ignore any that show
+ // up in a release build or hang in a debug build.
+ //
+ default:
+#ifdef DEBUG
+ while(1);
+#else
+ break;
+#endif
+ }
+
+ return(0);
+}
+
+void handleRx(void)
+{
+ uint32_t ui32Read;
+ uint8_t ui8Char;
+
+ do
+ {
+ ui32Read = USBBufferRead((tUSBBuffer *)&g_sRxBuffer, &ui8Char, 1);
+
+ // Did we get a character?
+ if(ui32Read)
+ {
+ insertArray(&inBuffer, ui8Char);
+ g_RxCount++;
+ }
+
+ } while(ui32Read);
+}
+
+//Execute this function on UART0 Interrupt;
+void InitUSB(void)
+{
+ CheckForSerialStateChange(&g_sCDCDevice, 0);
+}
+
+//Initialize USB.
+void StartUSB(uint32_t ui32SysClock)
+{
+ uint32_t ui32PLLRate, ui32RxCount;
+
+ ui32RxCount = 0;
+ g_RxCount = 0;
+
+ initArray(&inBuffer, 1);
+
+ // Save the PLL rate used by this application.
+ SysCtlVCOGet(SYSCTL_XTAL_25MHZ, &ui32PLLRate);
+
+ // Not configured initially.
+ g_ui32Flags = 0;
+
+ // Initialize the transmit and receive buffers.
+ USBBufferInit(&g_sTxBuffer);
+ USBBufferInit(&g_sRxBuffer);
+
+ // Set the USB stack mode to Device mode with VBUS monitoring.
+ USBStackModeSet(0, eUSBModeDevice, 0);
+
+ // Tell the USB library the CPU clock and the PLL frequency. This is a
+ // new requirement for TM4C129 devices.
+ USBDCDFeatureSet(0, USBLIB_FEATURE_CPUCLK, &ui32SysClock);
+ USBDCDFeatureSet(0, USBLIB_FEATURE_USBPLL, &ui32PLLRate);
+
+ // Pass our device information to the USB library and place the device
+ // on the bus.
+ USBDCDCInit(0, (tUSBDCDCDevice *)&g_sCDCDevice);
+
+ while (1)
+ {
+ if(ui32RxCount != g_RxCount)
+ {
+ ui32RxCount = g_RxCount;
+
+ if (callback != NULL)
+ {
+ callback(inBuffer.buffer,inBuffer.used);
+ }
+
+ freeArray(&inBuffer);
+ initArray(&inBuffer, 1);
+ }
+ }
+}
+
+//Send a sequence of chars to PC.
+uint32_t SendChars(char* buffer,size_t length)
+{
+ return USBBufferWrite((tUSBBuffer *)&g_sTxBuffer, (uint8_t*)buffer, length);
+}
+
+//Register for serial data receive callback.
+void RegisterReceiveCallback(void (*callback_ptr)(char* buffer, size_t length))
+{
+ callback = callback_ptr;
+}