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

183 lines
4.3 KiB

#include <util/delay.h>
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <LUFA/Drivers/USB/USB.h>
#include "Descriptors.h"
// Pro Micro LEDs are: B0, D5
#define LED_SETUP() DDRB |= (1<<0); DDRD |= (1<<5);
#define L_LED_OFF() PORTD |= (1<<5)
#define L_LED_ON() PORTD &= ~(1<<5)
#define DATA_LED_OFF() PORTB |= (1<<0)
#define DATA_LED_ON() PORTB &= ~(1<<0)
static uint16_t DataBlinkCounter = 0;
static uint32_t HeartbeatCounter = 498000; // make it blink immediately
void LEDPulse(void)
{
HeartbeatCounter++;
if (HeartbeatCounter > 498000) {
L_LED_ON();
}
if (HeartbeatCounter > 500000) {
L_LED_OFF();
HeartbeatCounter = 0;
}
}
static int16_t UsbReceiveByte() {
return CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface);
}
static int8_t UsbSendByte(uint8_t byte) {
return CDC_Device_SendByte(&VirtualSerial_CDC_Interface, byte);
}
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();
/* Initialize USB Subsystem */
USB_Init();
/* Enable global interrupts so that the USB stack can function */
sei();
#define PINS \
X(D, 3, 'A') \
X(D, 2, 'B') \
X(D, 1, 'C') \
X(D, 0, 'D') \
X(D, 4, 'E') \
X(C, 6, 'F') \
X(D, 7, 'G') \
X(E, 6, 'H') \
X(B, 4, 'I') \
X(B, 5, 'J') \
X(B, 6, 'K') \
X(B, 2, 'L') \
X(B, 3, 'M') \
X(B, 1, 'N') \
X(F, 7, 'O') \
X(F, 6, 'P') \
X(F, 5, 'Q') \
X(F, 4, 'R')
#define X(port, pin, ch) DDR##port |= _BV(pin);
PINS
#undef X
for (;;)
{
LEDPulse();
int16_t readch = UsbReceiveByte();
if (readch > 0 && readch != '\r' && readch != '\n') {
DATA_LED_ON();
DataBlinkCounter = 1000; // this makes a pretty short blink
bool valid = 0;
if (readch == '0') {
valid = 1;
#define X(port, pin, ch) \
PORT##port &= ~_BV(pin);
PINS
#undef X
} else if (readch == '1') {
valid = 1;
#define X(port, pin, ch) \
PORT##port |= _BV(pin);
PINS
#undef X
} else
// xmacro magic
#define X(port, pin, ch) \
if (readch == ch) { \
PORT##port |= _BV(pin); \
valid = 1; \
} else if (readch == (ch + 32)) { /* lowercase */ \
PORT##port &= ~_BV(pin); \
valid = 1; \
} else
PINS
/* last else */ {}
#undef X
if (valid) {
UsbSendByte(readch);
} else {
UsbSendByte('?');
}
}
if (DataBlinkCounter > 0) {
DataBlinkCounter--;
} else {
DATA_LED_OFF();
}
CDC_Device_USBTask(&VirtualSerial_CDC_Interface);
USB_USBTask();
}
}
/** Event handler for the library USB Connection event. */
void EVENT_USB_Device_Connect(void)
{
//
}
/** Event handler for the library USB Disconnection event. */
void EVENT_USB_Device_Disconnect(void)
{
//
}
/** 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);
}
/** Event handler for the library USB Control Request reception event. */
void EVENT_USB_Device_ControlRequest(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)
{
//
}