#include #include #include #include #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) { // }