diff options
Diffstat (limited to 'firmware/VirtualSerial.c')
-rw-r--r-- | firmware/VirtualSerial.c | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/firmware/VirtualSerial.c b/firmware/VirtualSerial.c new file mode 100644 index 0000000..70a8ddc --- /dev/null +++ b/firmware/VirtualSerial.c @@ -0,0 +1,298 @@ +/* + LUFA Library + Copyright (C) Dean Camera, 2010. + + dean [at] fourwalledcubicle [dot] com + www.lufa-lib.org +*/ + +/* + Copyright 2010 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. +*/ + +/** \file + * + * Main source file for the VirtualSerial demo. This file contains the main tasks of + * the demo and is responsible for the initial application hardware configuration. + */ + +#include "VirtualSerial.h" +#include <util/delay.h> +#include <avr/interrupt.h> + +static int running = true; + +/** LUFA CDC Class driver interface configuration and state information. This structure is + * passed to all CDC Class driver functions, so that multiple instances of the same class + * within a device can be differentiated from one another. + */ +USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface = + { + .Config = + { + .ControlInterfaceNumber = 0, + + .DataINEndpointNumber = CDC_TX_EPNUM, + .DataINEndpointSize = CDC_TXRX_EPSIZE, + .DataINEndpointDoubleBank = false, + + .DataOUTEndpointNumber = CDC_RX_EPNUM, + .DataOUTEndpointSize = CDC_TXRX_EPSIZE, + .DataOUTEndpointDoubleBank = false, + + .NotificationEndpointNumber = CDC_NOTIFICATION_EPNUM, + .NotificationEndpointSize = CDC_NOTIFICATION_EPSIZE, + .NotificationEndpointDoubleBank = false, + }, + }; + +/** Standard file stream for the CDC interface when set up, so that the virtual CDC COM port can be + * used like any regular character stream in the C APIs + */ +static FILE USBSerialStream; + +static volatile uint8_t lock_timer_ticks; + +void lock_timer_setup(void) +{ + OCR1A = 128; + + // CTC mode + TCCR1A = (1 << WGM12); + + // Prescaler + TCCR1B = (1 << CS12); + + // Enable interrupt + TIMSK1 = (1 << OCIE1A); +} + +void lock_timer_reset(void) +{ + lock_timer_ticks = 0; +} + +/** Main program entry point. This routine contains the overall program flow, including initial + * setup of all components and the main program loop. + */ +int main(void) +{ + DDRB = 1 << PB0 | 1 << PB4 | 0 << PB5; + PORTB = 0 << PB0; + + SetupHardware(); + + lock_timer_setup(); + + /* Create a regular character stream for the interface so that it can be used with the stdio.h functions */ + CDC_Device_CreateStream(&VirtualSerial_CDC_Interface, &USBSerialStream); + +// LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); + sei(); + + while(running) + { + wdt_reset(); + + _delay_ms(250); +// PORTB ^= 1 << PB0; // Toggle external LED + +// CheckPinStatus(); + + CheckACMStatus(); + + CDC_Device_USBTask(&VirtualSerial_CDC_Interface); + USB_USBTask(); + } + + USB_Detach(); + + /* Enable the watchdog and force a timeout to reset the AVR */ + wdt_enable(WDTO_250MS); + + for (;;); +} + +void handle_command(const char *buf) +{ + if (strcmp("cola", buf) == 0) + { + PORTB ^= 1 << PB5; + fputs("mmm! LED toggeled\r\n", &USBSerialStream); + } + + else if (strcmp("reboot", buf) == 0 || strcmp("reset", buf) == 0) + { + fputs("Rebooting!\r\n", &USBSerialStream); + running = false; + } + + else if (strcmp("toggle", buf) == 0) + { + fputs("Toggling Magnet Lock\r\n", &USBSerialStream); + PORTB ^= 1 << PB4; + } + + else if (strcmp("lock", buf) == 0) + { + fputs("status: locked\n", &USBSerialStream); + PORTB |= 1 << PB4; + } + + else if (strcmp("unlock", buf) == 0) + { + fputs("status: unlocked\n", &USBSerialStream); + PORTB &= ~(1 << PB4); + lock_timer_reset(); + } + + else if (strcmp("doorstatus", buf) == 0) + { + if (PINB & (1 << PB5)) + fputs("doorstatus: open\n", &USBSerialStream); + else + fputs("doorstatus: closed\n", &USBSerialStream); + } +} + +void CheckACMStatus() +{ + static char buf[32]; + static uint8_t len = 0; + + int c; + while((c = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface)) > 0) + { + putc(c, &USBSerialStream); + + if (c == '\r') + { + putc('\n', &USBSerialStream); + buf[len++] = '\0'; + handle_command(buf); + len = 0; + continue; + } + + buf[len++] = c; + + if (len == sizeof(buf)) + { + len = 0; + continue; + } + } +} + +/** Configures the board hardware and chip peripherals for the demo's functionality. */ +void SetupHardware(void) +{ + /* Disable watchdog if enabled by bootloader/fuses */ + MCUSR &= ~(1 << WDRF); + + /* Enable the watchdog timer. */ + wdt_enable(WDTO_1S); + + /* Disable clock division */ + clock_prescale_set(clock_div_1); + + /* Hardware Initialization */ + USB_Init(); +} + +/** Checks for changes in the position of the board joystick, sending strings to the host upon each change. */ +void CheckPinStatus(void) +{ + char* ReportString = NULL; + static bool ActionSent = false; + + if (!(PINB & (1 << PB6))) + { + ReportString = "Hello, World!\r\n"; + ActionSent = false; + } + + if (!(PINB & (1 << PB7))) + { + ReportString = "Rebooting!\r\n"; + ActionSent = false; + running = false; + } + + if ((ReportString != NULL) && (ActionSent == false)) + { + ActionSent = true; + + /* Write the string to the virtual COM port via the created character stream */ + fputs(ReportString, &USBSerialStream); + + _delay_ms(100); + + /* Alternatively, without the stream: */ + // CDC_Device_SendString(&VirtualSerial_CDC_Interface, ReportString, strlen(ReportString)); + } +} + +/** Event handler for the library USB Connection event. */ +void EVENT_USB_Device_Connect(void) +{ +// LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING); +} + +/** Event handler for the library USB Disconnection event. */ +void EVENT_USB_Device_Disconnect(void) +{ +// LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); +} + +/** 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); + +// LEDs_SetAllLEDs(ConfigSuccess ? LEDMASK_USB_READY : LEDMASK_USB_ERROR); +} + +/** Event handler for the library USB Control Request reception event. */ +void EVENT_USB_Device_ControlRequest(void) +{ + CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); +} + +ISR(TIMER1_COMPA_vect) +{ + if(PINB & (1 << PB5)) + PORTB |= 1 << PB4; + + if(lock_timer_ticks == 0xff) + return; + + if(lock_timer_ticks < 30) + { + ++lock_timer_ticks; + return; + } + + PORTB |= 1 << PB4; + lock_timer_ticks = 0xff; +} |