|
|
|
@ -1,92 +1,19 @@ |
|
|
|
|
#include <util/delay.h> |
|
|
|
|
#include <avr/io.h> |
|
|
|
|
#include <avr/pgmspace.h> |
|
|
|
|
|
|
|
|
|
#include <LUFA/Drivers/USB/USB.h> |
|
|
|
|
|
|
|
|
|
#include <LUFA/Drivers/USB/USB.h> |
|
|
|
|
#include "Descriptors.h" |
|
|
|
|
|
|
|
|
|
// Pro Micro LEDs are: B0, D5
|
|
|
|
|
|
|
|
|
|
#include "Descriptors.h" |
|
|
|
|
|
|
|
|
|
#define LED_SETUP() DDRB |= (1<<0); DDRD |= (1<<5); |
|
|
|
|
#define L_LED_OFF() PORTD |= (1<<5) |
|
|
|
|
#define L_LED_ON() PORTD &= ~(1<<5) |
|
|
|
|
#define L_LED_TOGGLE() PORTD ^= (1<<5) |
|
|
|
|
#define DATA_LED_OFF() PORTB |= (1<<0) |
|
|
|
|
#define DATA_LED_ON() PORTB &= ~(1<<0) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Endpoint address for the CDC control interface event notification endpoint. */ |
|
|
|
|
#define CDC_NOTIFICATION_EPADDR (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM) |
|
|
|
|
|
|
|
|
|
/** Endpoint address for the CDC data interface TX (data IN) endpoint. */ |
|
|
|
|
#define CDC_TX_EPADDR (ENDPOINT_DIR_IN | CDC_TX_EPNUM) |
|
|
|
|
|
|
|
|
|
/** Endpoint address for the CDC data interface RX (data OUT) endpoint. */ |
|
|
|
|
#define CDC_RX_EPADDR (ENDPOINT_DIR_OUT | CDC_RX_EPNUM) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed
|
|
|
|
|
* to allow reception of the next data packet from the host. |
|
|
|
|
* |
|
|
|
|
* \return Next received byte from the host in the CDC data OUT endpoint |
|
|
|
|
*/ |
|
|
|
|
static uint8_t FetchNextCommandByte(void) |
|
|
|
|
{ |
|
|
|
|
/* Select the OUT endpoint so that the next data byte can be read */ |
|
|
|
|
Endpoint_SelectEndpoint(CDC_RX_EPADDR); |
|
|
|
|
|
|
|
|
|
/* If OUT endpoint empty, clear it and wait for the next packet from the host */ |
|
|
|
|
while (!(Endpoint_IsReadWriteAllowed())) |
|
|
|
|
{ |
|
|
|
|
Endpoint_ClearOUT(); |
|
|
|
|
|
|
|
|
|
while (!(Endpoint_IsOUTReceived())) |
|
|
|
|
{ |
|
|
|
|
if (USB_DeviceState == DEVICE_STATE_Unattached) |
|
|
|
|
return 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Fetch the next byte from the OUT endpoint */ |
|
|
|
|
return Endpoint_Read_8(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free up the
|
|
|
|
|
* bank when full ready for the next byte in the packet to the host. |
|
|
|
|
* |
|
|
|
|
* \param[in] Response Next response byte to send to the host |
|
|
|
|
*/ |
|
|
|
|
static void WriteNextResponseByte(const uint8_t Response) |
|
|
|
|
{ |
|
|
|
|
/* Select the IN endpoint so that the next data byte can be written */ |
|
|
|
|
Endpoint_SelectEndpoint(CDC_TX_EPADDR); |
|
|
|
|
|
|
|
|
|
/* If IN endpoint full, clear it and wait until ready for the next packet to the host */ |
|
|
|
|
if (!(Endpoint_IsReadWriteAllowed())) |
|
|
|
|
{ |
|
|
|
|
Endpoint_ClearIN(); |
|
|
|
|
|
|
|
|
|
while (!(Endpoint_IsINReady())) |
|
|
|
|
{ |
|
|
|
|
if (USB_DeviceState == DEVICE_STATE_Unattached) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Write the next byte to the IN endpoint */ |
|
|
|
|
Endpoint_Write_8(Response); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CDC_Task(void); |
|
|
|
|
#define LED_SETUP() DDRB |= (1<<0); DDRD |= (1<<5); |
|
|
|
|
#define L_LED_OFF() PORTD |= (1<<5) |
|
|
|
|
#define L_LED_ON() PORTD &= ~(1<<5) |
|
|
|
|
#define L_LED_TOGGLE() PORTD ^= (1<<5) |
|
|
|
|
#define DATA_LED_OFF() PORTB |= (1<<0) |
|
|
|
|
#define DATA_LED_ON() PORTB &= ~(1<<0) |
|
|
|
|
|
|
|
|
|
/* Pulse generation counters to keep track of the time remaining for each pulse type */ |
|
|
|
|
#define DATA_LED_PULSE_PERIOD 100 |
|
|
|
@ -107,6 +34,26 @@ void LEDPulse(void) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static int16_t UsbReceiveByte() { |
|
|
|
|
return CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int8_t UsbSendData(const uint8_t* const bytes, uint16_t len) { |
|
|
|
|
return CDC_Device_SendData(&VirtualSerial_CDC_Interface, bytes, len); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int8_t UsbSendData_P(const uint8_t* const bytes, uint16_t len) { |
|
|
|
|
return CDC_Device_SendData_P(&VirtualSerial_CDC_Interface, bytes, len); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int8_t UsbSendString(const char* const str) { |
|
|
|
|
return CDC_Device_SendString(&VirtualSerial_CDC_Interface, str); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static int8_t UsbSendString_P(const char* const str) { |
|
|
|
|
return CDC_Device_SendString_P(&VirtualSerial_CDC_Interface, str); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void main () { |
|
|
|
|
LED_SETUP(); |
|
|
|
@ -117,126 +64,73 @@ void main () { |
|
|
|
|
/* Enable global interrupts so that the USB stack can function */ |
|
|
|
|
sei(); |
|
|
|
|
|
|
|
|
|
for(;;) { |
|
|
|
|
CDC_Task(); |
|
|
|
|
USB_USBTask(); |
|
|
|
|
// keep the indicator on for a while
|
|
|
|
|
int light_cnt = 0; |
|
|
|
|
for (;;) |
|
|
|
|
{ |
|
|
|
|
LEDPulse(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int16_t ch = UsbReceiveByte(); |
|
|
|
|
|
|
|
|
|
if (ch > 0) { |
|
|
|
|
light_cnt = 10; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* some parts of this code are from LUFA. |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
Copyright 2011 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. |
|
|
|
|
*/ |
|
|
|
|
|
|
|
|
|
// /*
|
|
|
|
|
//
|
|
|
|
|
// /** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed
|
|
|
|
|
// * to allow reception of the next data packet from the host.
|
|
|
|
|
// *
|
|
|
|
|
// * \return Next received byte from the host in the CDC data OUT endpoint
|
|
|
|
|
// */
|
|
|
|
|
// static uint8_t FetchNextCommandByte(void)
|
|
|
|
|
// {
|
|
|
|
|
// /* Select the OUT endpoint so that the next data byte can be read */
|
|
|
|
|
// Endpoint_SelectEndpoint(CDC_RX_EPNUM);
|
|
|
|
|
//
|
|
|
|
|
// /* If OUT endpoint empty, clear it and wait for the next packet from the host */
|
|
|
|
|
// while (!(Endpoint_IsReadWriteAllowed()))
|
|
|
|
|
// {
|
|
|
|
|
// Endpoint_ClearOUT();
|
|
|
|
|
//
|
|
|
|
|
// while (!(Endpoint_IsOUTReceived()))
|
|
|
|
|
// {
|
|
|
|
|
// if (USB_DeviceState == DEVICE_STATE_Unattached)
|
|
|
|
|
// return 0;
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
//
|
|
|
|
|
// /* Fetch the next byte from the OUT endpoint */
|
|
|
|
|
// return Endpoint_Read_8();
|
|
|
|
|
// }
|
|
|
|
|
// */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required actions
|
|
|
|
|
* and send the appropriate response back to the host. |
|
|
|
|
*/ |
|
|
|
|
void CDC_Task(void) |
|
|
|
|
{ |
|
|
|
|
/* Select the OUT endpoint */ |
|
|
|
|
Endpoint_SelectEndpoint(CDC_RX_EPNUM); |
|
|
|
|
|
|
|
|
|
/* Check if endpoint has a command in it sent from the host */ |
|
|
|
|
if (!(Endpoint_IsOUTReceived())) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
DATA_LED_ON(); |
|
|
|
|
DataLEDPulse = DATA_LED_PULSE_PERIOD; |
|
|
|
|
if (ch == 'a') { |
|
|
|
|
UsbSendString_P(PSTR("OFF\r\n")); |
|
|
|
|
} else if (ch == 'A') { |
|
|
|
|
UsbSendString_P(PSTR("ON\r\n")); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Read in the bootloader command (first byte sent from host) */ |
|
|
|
|
uint8_t Command = FetchNextCommandByte(); |
|
|
|
|
if (light_cnt > 0) { |
|
|
|
|
light_cnt--; |
|
|
|
|
} else { |
|
|
|
|
DATA_LED_OFF(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// COMMAND PROCESSING
|
|
|
|
|
if (Command == 'a') |
|
|
|
|
{ |
|
|
|
|
WriteNextResponseByte('b'); |
|
|
|
|
WriteNextResponseByte('\r'); |
|
|
|
|
WriteNextResponseByte('\n'); |
|
|
|
|
CDC_Device_USBTask(&VirtualSerial_CDC_Interface); |
|
|
|
|
USB_USBTask(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Select the IN endpoint */ |
|
|
|
|
Endpoint_SelectEndpoint(CDC_TX_EPNUM); |
|
|
|
|
|
|
|
|
|
/* Remember if the endpoint is completely full before clearing it */ |
|
|
|
|
bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed()); |
|
|
|
|
|
|
|
|
|
/* Send the endpoint data to the host */ |
|
|
|
|
Endpoint_ClearIN(); |
|
|
|
|
|
|
|
|
|
/* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */ |
|
|
|
|
if (IsEndpointFull) |
|
|
|
|
{ |
|
|
|
|
while (!(Endpoint_IsINReady())) |
|
|
|
|
{ |
|
|
|
|
if (USB_DeviceState == DEVICE_STATE_Unattached) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
/** Event handler for the library USB Connection event. */ |
|
|
|
|
void EVENT_USB_Device_Connect(void) |
|
|
|
|
{ |
|
|
|
|
//
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Endpoint_ClearIN(); |
|
|
|
|
} |
|
|
|
|
/** Event handler for the library USB Disconnection event. */ |
|
|
|
|
void EVENT_USB_Device_Disconnect(void) |
|
|
|
|
{ |
|
|
|
|
//
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Wait until the data has been sent to the host */ |
|
|
|
|
while (!(Endpoint_IsINReady())) |
|
|
|
|
{ |
|
|
|
|
if (USB_DeviceState == DEVICE_STATE_Unattached) |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
/** Event handler for the library USB Configuration Changed event. */ |
|
|
|
|
void EVENT_USB_Device_ConfigurationChanged(void) |
|
|
|
|
{ |
|
|
|
|
bool ConfigSuccess = true; |
|
|
|
|
ConfigSuccess &= CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Select the OUT endpoint */ |
|
|
|
|
Endpoint_SelectEndpoint(CDC_RX_EPNUM); |
|
|
|
|
/** Event handler for the library USB Control Request reception event. */ |
|
|
|
|
void EVENT_USB_Device_ControlRequest(void) |
|
|
|
|
{ |
|
|
|
|
CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Acknowledge the command from the host */ |
|
|
|
|
Endpoint_ClearOUT(); |
|
|
|
|
|
|
|
|
|
/** 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) |
|
|
|
|
{ |
|
|
|
|
//
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|