USB controlled relay
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.
 
 
usb-relay/src/main.c

242 lines
6.3 KiB

#include <util/delay.h>
#include <avr/io.h>
#include <LUFA/Drivers/USB/USB.h>
#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);
/* Pulse generation counters to keep track of the time remaining for each pulse type */
#define DATA_LED_PULSE_PERIOD 100
uint16_t DataLEDPulse = 0; // time remaining for Data LED pulse
uint16_t LLEDPulse;
void LEDPulse(void)
{
LLEDPulse++;
uint8_t p = LLEDPulse >> 8;
if (p > 127)
p = 254-p;
p += p;
if (((uint8_t)LLEDPulse) > p)
L_LED_OFF();
else
L_LED_ON();
}
void main () {
LED_SETUP();
/* Initialize USB Subsystem */
USB_Init();
/* Enable global interrupts so that the USB stack can function */
sei();
for(;;) {
CDC_Task();
USB_USBTask();
LEDPulse();
}
}
/*
* 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;
/* Read in the bootloader command (first byte sent from host) */
uint8_t Command = FetchNextCommandByte();
// COMMAND PROCESSING
if (Command == 'a')
{
WriteNextResponseByte('b');
WriteNextResponseByte('\r');
WriteNextResponseByte('\n');
}
/* 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;
}
Endpoint_ClearIN();
}
/* Wait until the data has been sent to the host */
while (!(Endpoint_IsINReady()))
{
if (USB_DeviceState == DEVICE_STATE_Unattached)
return;
}
/* Select the OUT endpoint */
Endpoint_SelectEndpoint(CDC_RX_EPNUM);
/* Acknowledge the command from the host */
Endpoint_ClearOUT();
}