/*
LUFA Library
- Copyright (C) Dean Camera, 2011.
-
+ Copyright (C) Dean Camera, 2012.
+
dean [at] fourwalledcubicle [dot] com
www.lufa-lib.org
*/
/*
- Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
+ Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
- Permission to use, copy, modify, distribute, and sell this
+ 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
+ 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
+ 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
{
.Status = TMC_STATUS_SUCCESS,
.TMCVersion = VERSION_BCD(1.00),
-
+
.Interface =
{
.ListenOnly = false,
static uint8_t CurrentTransferTag = 0;
/** Length of last data transfer, for reporting to the host in case an in-progress transfer is aborted */
-static uint32_t LastTransferLength = 0;
+static uint16_t LastTransferLength = 0;
+
+/** Buffer to hold the next message to sent to the TMC host */
+static uint8_t NextResponseBuffer[64];
+
+/** Indicates the length of the next response to send */
+static uint8_t NextResponseLen;
/** Main program entry point. This routine contains the overall program flow, including initial
* setup of all components and the main program loop.
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);
sei();
-
+
for (;;)
{
TMC_Task();
/* Disable clock division */
clock_prescale_set(clock_div_1);
-
+
/* Hardware Initialization */
LEDs_Init();
USB_Init();
bool ConfigSuccess = true;
/* Setup TMC In, Out and Notification Endpoints */
- ConfigSuccess &= Endpoint_ConfigureEndpoint(TMC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT, ENDPOINT_DIR_IN,
- TMC_IO_EPSIZE, ENDPOINT_BANK_SINGLE);
- ConfigSuccess &= Endpoint_ConfigureEndpoint(TMC_IN_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_IN,
- TMC_IO_EPSIZE, ENDPOINT_BANK_SINGLE);
- ConfigSuccess &= Endpoint_ConfigureEndpoint(TMC_OUT_EPNUM, EP_TYPE_BULK, ENDPOINT_DIR_OUT,
- TMC_IO_EPSIZE, ENDPOINT_BANK_SINGLE);
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(TMC_NOTIFICATION_EPADDR, EP_TYPE_INTERRUPT, TMC_IO_EPSIZE, 1);
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(TMC_IN_EPADDR, EP_TYPE_BULK, TMC_IO_EPSIZE, 1);
+ ConfigSuccess &= Endpoint_ConfigureEndpoint(TMC_OUT_EPADDR, EP_TYPE_BULK, TMC_IO_EPSIZE, 1);
/* Indicate endpoint configuration success or failure */
LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR);
{
/* Indicate that all in-progress/pending data OUT requests should be aborted */
IsTMCBulkOUTReset = true;
-
+
/* Save the split request for later checking when a new request is received */
RequestInProgress = Req_InitiateAbortBulkOut;
}
Endpoint_ClearSETUP();
-
+
/* Write the request response byte */
Endpoint_Write_8(TMCRequestStatus);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
-
+
break;
case Req_CheckAbortBulkOutStatus:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT))
{
/* Check that an ABORT BULK OUT transaction has been requested and that the request has completed */
if (RequestInProgress != Req_InitiateAbortBulkOut)
- TMCRequestStatus = TMC_STATUS_SPLIT_NOT_IN_PROGRESS;
+ TMCRequestStatus = TMC_STATUS_SPLIT_NOT_IN_PROGRESS;
else if (IsTMCBulkOUTReset)
TMCRequestStatus = TMC_STATUS_PENDING;
else
- RequestInProgress = 0;
+ RequestInProgress = 0;
Endpoint_ClearSETUP();
-
+
/* Write the request response bytes */
Endpoint_Write_8(TMCRequestStatus);
Endpoint_Write_16_LE(0);
Endpoint_Write_32_LE(LastTransferLength);
Endpoint_ClearIN();
- Endpoint_ClearStatusStage();
+ Endpoint_ClearStatusStage();
}
-
+
break;
case Req_InitiateAbortBulkIn:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT))
/* Check that no split transaction is already in progress and the data transfer tag is valid */
if (RequestInProgress != 0)
{
- TMCRequestStatus = TMC_STATUS_SPLIT_IN_PROGRESS;
+ TMCRequestStatus = TMC_STATUS_SPLIT_IN_PROGRESS;
}
else if (USB_ControlRequest.wValue != CurrentTransferTag)
{
{
/* Indicate that all in-progress/pending data IN requests should be aborted */
IsTMCBulkINReset = true;
-
+
/* Save the split request for later checking when a new request is received */
RequestInProgress = Req_InitiateAbortBulkIn;
}
Endpoint_ClearSETUP();
-
+
/* Write the request response bytes */
Endpoint_Write_8(TMCRequestStatus);
Endpoint_Write_8(CurrentTransferTag);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
-
+
break;
case Req_CheckAbortBulkInStatus:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_ENDPOINT))
RequestInProgress = 0;
Endpoint_ClearSETUP();
-
+
/* Write the request response bytes */
Endpoint_Write_8(TMCRequestStatus);
Endpoint_Write_16_LE(0);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
-
+
break;
case Req_InitiateClear:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
/* Check that no split transaction is already in progress */
if (RequestInProgress != 0)
{
- Endpoint_Write_8(TMC_STATUS_SPLIT_IN_PROGRESS);
+ Endpoint_Write_8(TMC_STATUS_SPLIT_IN_PROGRESS);
}
else
{
/* Indicate that all in-progress/pending data IN and OUT requests should be aborted */
IsTMCBulkINReset = true;
IsTMCBulkOUTReset = true;
-
+
/* Save the split request for later checking when a new request is received */
RequestInProgress = Req_InitiateClear;
}
Endpoint_ClearSETUP();
-
+
/* Write the request response byte */
Endpoint_Write_8(TMCRequestStatus);
Endpoint_ClearIN();
Endpoint_ClearStatusStage();
}
-
+
break;
case Req_CheckClearStatus:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
/* Check that a CLEAR transaction has been requested and that the request has completed */
if (RequestInProgress != Req_InitiateClear)
- TMCRequestStatus = TMC_STATUS_SPLIT_NOT_IN_PROGRESS;
+ TMCRequestStatus = TMC_STATUS_SPLIT_NOT_IN_PROGRESS;
else if (IsTMCBulkINReset || IsTMCBulkOUTReset)
TMCRequestStatus = TMC_STATUS_PENDING;
else
/* Write the request response bytes */
Endpoint_Write_8(TMCRequestStatus);
Endpoint_Write_8(0);
-
+
Endpoint_ClearIN();
- Endpoint_ClearStatusStage();
+ Endpoint_ClearStatusStage();
}
-
+
break;
case Req_GetCapabilities:
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
{
Endpoint_ClearSETUP();
-
+
/* Write the device capabilities to the control endpoint */
- Endpoint_Write_Control_Stream_LE(&Capabilities, sizeof(TMC_Capabilities_t));
+ Endpoint_Write_Control_Stream_LE(&Capabilities, sizeof(TMC_Capabilities_t));
Endpoint_ClearOUT();
}
-
+
break;
}
}
+void ProcessSentMessage(uint8_t* const Data, const uint8_t Length)
+{
+ if (strncmp((char*)Data, "*IDN?", 5) == 0)
+ strcpy((char*)NextResponseBuffer, "LUFA TMC DEMO");
+
+ NextResponseLen = strlen((char*)NextResponseBuffer);
+}
+
+uint8_t GetNextMessage(uint8_t* const Data)
+{
+ strcpy((char*)NextResponseBuffer, "LUFA TMC DEMO");
+
+ NextResponseLen = strlen((char*)NextResponseBuffer);
+// ---
+ uint8_t DataLen = MIN(NextResponseLen, 64);
+
+ strlcpy((char*)Data, (char*)NextResponseBuffer, DataLen);
+
+ return DataLen;
+}
+
/** Function to manage TMC data transmission and reception to and from the host. */
void TMC_Task(void)
{
/* Device must be connected and configured for the task to run */
if (USB_DeviceState != DEVICE_STATE_Configured)
return;
-
+
TMC_MessageHeader_t MessageHeader;
- uint16_t BytesTransferred;
-
+ uint8_t MessagePayload[128];
+
/* Try to read in a TMC message from the interface, process if one is available */
if (ReadTMCHeader(&MessageHeader))
{
/* Indicate busy */
LEDs_SetAllLEDs(LEDMASK_USB_BUSY);
-
+
switch (MessageHeader.MessageID)
{
case TMC_MESSAGEID_DEV_DEP_MSG_OUT:
- BytesTransferred = 0;
- while (Endpoint_Discard_Stream(MessageHeader.TransferSize, &BytesTransferred) ==
+ LastTransferLength = 0;
+ while (Endpoint_Read_Stream_LE(MessagePayload, MIN(MessageHeader.TransferSize, sizeof(MessagePayload)), &LastTransferLength) ==
ENDPOINT_RWSTREAM_IncompleteTransfer)
{
if (IsTMCBulkOUTReset)
break;
}
- LastTransferLength = BytesTransferred;
-
+
Endpoint_ClearOUT();
+
+ ProcessSentMessage(MessagePayload, LastTransferLength);
break;
case TMC_MESSAGEID_DEV_DEP_MSG_IN:
Endpoint_ClearOUT();
-
- char MessageData[] = "TMC Class Test";
- MessageHeader.TransferSize = strlen(MessageData);
+ MessageHeader.TransferSize = GetNextMessage(MessagePayload);
MessageHeader.MessageIDSpecific.DeviceOUT.LastMessageTransaction = true;
WriteTMCHeader(&MessageHeader);
- BytesTransferred = 0;
- while (Endpoint_Write_Stream_LE(MessageData, MessageHeader.TransferSize, &BytesTransferred) ==
+ LastTransferLength = 0;
+ while (Endpoint_Write_Stream_LE(MessagePayload, MessageHeader.TransferSize, &LastTransferLength) ==
ENDPOINT_RWSTREAM_IncompleteTransfer)
{
if (IsTMCBulkINReset)
break;
}
- LastTransferLength = BytesTransferred;
Endpoint_ClearIN();
break;
LEDs_SetAllLEDs(LEDMASK_USB_READY);
}
-
+
/* All pending data has been processed - reset the data abort flags */
IsTMCBulkINReset = false;
IsTMCBulkOUTReset = false;
uint8_t ErrorCode;
/* Select the Data Out endpoint */
- Endpoint_SelectEndpoint(TMC_OUT_EPNUM);
-
+ Endpoint_SelectEndpoint(TMC_OUT_EPADDR);
+
/* Abort if no command has been sent from the host */
if (!(Endpoint_IsOUTReceived()))
return false;
-
+
/* Read in the header of the command from the host */
BytesTransferred = 0;
while ((ErrorCode = Endpoint_Read_Stream_LE(MessageHeader, sizeof(TMC_MessageHeader_t), &BytesTransferred)) ==
/* Store the new command tag value for later use */
CurrentTransferTag = MessageHeader->Tag;
-
+
/* Indicate if the command has been aborted or not */
return (!(IsTMCBulkOUTReset) && (ErrorCode == ENDPOINT_RWSTREAM_NoError));
}
MessageHeader->InverseTag = ~CurrentTransferTag;
/* Select the Data In endpoint */
- Endpoint_SelectEndpoint(TMC_IN_EPNUM);
+ Endpoint_SelectEndpoint(TMC_IN_EPADDR);
/* Send the command header to the host */
BytesTransferred = 0;
/* Indicate if the command has been aborted or not */
return (!(IsTMCBulkINReset) && (ErrorCode == ENDPOINT_RWSTREAM_NoError));
}
+