/*\r
LUFA Library\r
- Copyright (C) Dean Camera, 2009.\r
+ Copyright (C) Dean Camera, 2010.\r
\r
dean [at] fourwalledcubicle [dot] com\r
www.fourwalledcubicle.com\r
*/\r
\r
/*\r
- Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
+ Copyright 2010 Dean Camera (dean [at] fourwalledcubicle [dot] com)\r
\r
Permission to use, copy, modify, distribute, and sell this \r
software and its documentation for any purpose is hereby granted\r
},\r
};\r
\r
+/** Buffer to hold the previously generated HID report, for comparison purposes inside the HID class driver. */\r
+uint8_t PrevHIDReportBuffer[GENERIC_REPORT_SIZE];\r
+\r
+/** LUFA HID Class driver interface configuration and state information. This structure is\r
+ * passed to all HID Class driver functions, so that multiple instances of the same class\r
+ * within a device can be differentiated from one another.\r
+ */\r
+USB_ClassInfo_HID_Device_t Generic_HID_Interface =\r
+ {\r
+ .Config =\r
+ {\r
+ .InterfaceNumber = 1,\r
+\r
+ .ReportINEndpointNumber = GENERIC_IN_EPNUM,\r
+ .ReportINEndpointSize = GENERIC_EPSIZE,\r
+ .ReportINEndpointDoubleBank = false,\r
+ \r
+ .PrevReportINBuffer = PrevHIDReportBuffer,\r
+ .PrevReportINBufferSize = sizeof(PrevHIDReportBuffer),\r
+ },\r
+ };\r
+\r
+/** Non-volatile Logging Interval value in EEPROM, stored as a number of 500ms ticks */\r
+uint8_t EEMEM LoggingInterval500MS_EEPROM;\r
+\r
+/** SRAM Logging Interval value fetched from EEPROM, stored as a number of 500ms ticks */\r
+uint8_t LoggingInterval500MS_SRAM;\r
+\r
+/** Total number of 500ms logging ticks elapsed since the last log value was recorded */\r
+uint16_t CurrentLoggingTicks;\r
+\r
/** FAT Fs structure to hold the internal state of the FAT driver for the dataflash contents. */\r
FATFS DiskFATState;\r
\r
/** FAT Fs structure to hold a FAT file handle for the log data write destination. */\r
FIL TempLogFile;\r
\r
-/** Counter to count the number of 10 millisecond tick that has elapsed since the last sample */\r
-uint16_t CurrentLogTick;\r
-\r
\r
+/** ISR to handle the 500ms ticks for sampling and data logging */\r
ISR(TIMER1_COMPA_vect, ISR_BLOCK)\r
{\r
- if (CurrentLogTick++ != LOG_INTERVAL_10MS)\r
+ uint8_t LEDMask = LEDs_GetLEDs();\r
+\r
+ /* Check to see if the logging interval has expired */\r
+ if (CurrentLoggingTicks++ < LoggingInterval500MS_SRAM)\r
return;\r
- \r
- CurrentLogTick = 0;\r
+ \r
+ LEDs_SetAllLEDs(LEDMASK_USB_BUSY);\r
\r
+ /* Reset log tick counter to prepare for next logging interval */\r
+ CurrentLoggingTicks = 0;\r
+ \r
+ /* Only log when not connected to a USB host */\r
if (USB_DeviceState == DEVICE_STATE_Unattached)\r
{\r
- f_printf(&TempLogFile, "%d Degrees\r\n", Temperature_GetTemperature());\r
+ uint8_t Day, Month, Year;\r
+ uint8_t Hour, Minute, Second;\r
+\r
+ DS1307_GetDate(&Day, &Month, &Year);\r
+ DS1307_GetTime(&Hour, &Minute, &Second);\r
+\r
+ char LineBuffer[100];\r
+ uint16_t BytesWritten;\r
+\r
+ BytesWritten = sprintf(LineBuffer, "%02d/%02d/20%04d, %02d:%02d:%02d, %d Degrees\r\n",\r
+ Day, Month, Year, Hour, Minute, Second, Temperature_GetTemperature());\r
+\r
+ f_write(&TempLogFile, LineBuffer, BytesWritten, &BytesWritten);\r
f_sync(&TempLogFile);\r
}\r
+ \r
+ LEDs_SetAllLEDs(LEDMask);\r
}\r
\r
-\r
/** Main program entry point. This routine contains the overall program flow, including initial\r
* setup of all components and the main program loop.\r
*/\r
int main(void)\r
{\r
+ /* Fetch logging interval from EEPROM */\r
+ LoggingInterval500MS_SRAM = eeprom_read_byte(&LoggingInterval500MS_EEPROM);\r
+\r
SetupHardware();\r
\r
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
\r
/* Mount and open the log file on the dataflash FAT partition */\r
- f_mount(0, &DiskFATState);\r
- f_open(&TempLogFile, LOG_FILENAME, FA_OPEN_ALWAYS | FA_WRITE);\r
- f_lseek(&TempLogFile, TempLogFile.fsize);\r
-\r
- /* Write out the log seperator line */\r
- f_printf(&TempLogFile, "===========================\r\n");\r
- Temperature_GetTemperature(); // Discard first temperature reading to ensure accuracy\r
+ OpenLogFile();\r
\r
+ /* Discard the first sample from the temperature sensor, as it is generally incorrect */\r
+ volatile uint8_t Dummy = Temperature_GetTemperature();\r
+ (void)Dummy;\r
+ \r
for (;;)\r
{\r
MS_Device_USBTask(&Disk_MS_Interface);\r
+ HID_Device_USBTask(&Generic_HID_Interface);\r
USB_USBTask();\r
}\r
}\r
\r
+/** Opens the log file on the Dataflash's FAT formatted partition according to the current date */\r
+void OpenLogFile(void)\r
+{\r
+ char LogFileName[12];\r
+\r
+ /* Get the current date for the filename as "DDMMYY.csv" */\r
+ uint8_t Day, Month, Year;\r
+ DS1307_GetDate(&Day, &Month, &Year);\r
+ sprintf(LogFileName, "%02d%02d%02d.csv", Day, Month, Year);\r
+\r
+ /* Mount the storage device, open the file */\r
+ f_mount(0, &DiskFATState);\r
+ f_open(&TempLogFile, LogFileName, FA_OPEN_ALWAYS | FA_WRITE);\r
+ f_lseek(&TempLogFile, TempLogFile.fsize);\r
+}\r
+\r
+/** Closes the open data log file on the Dataflash's FAT formatted partition */\r
+void CloseLogFile(void)\r
+{\r
+ /* Sync any data waiting to be written, unmount the storage device */\r
+ f_sync(&TempLogFile);\r
+ f_close(&TempLogFile);\r
+}\r
+\r
/** Configures the board hardware and chip peripherals for the demo's functionality. */\r
void SetupHardware(void)\r
{\r
/* Hardware Initialization */\r
LEDs_Init();\r
SPI_Init(SPI_SPEED_FCPU_DIV_2 | SPI_SCK_LEAD_FALLING | SPI_SAMPLE_TRAILING | SPI_MODE_MASTER);\r
- Dataflash_Init();\r
- USB_Init();\r
ADC_Init(ADC_REFERENCE_AVCC | ADC_FREE_RUNNING | ADC_PRESCALE_128);\r
Temperature_Init();\r
+ Dataflash_Init();\r
+ USB_Init();\r
+ TWI_Init();\r
\r
- /* 10ms interval timer configuration */\r
- OCR1A = (((F_CPU / 1024) / 100) - 1);\r
- TCCR1A = (1 << WGM01); // CTC mode\r
- TCCR1B = (1 << CS12) | (1 << CS10); // Fcpu/1024 speed\r
+ /* 500ms logging interval timer configuration */\r
+ OCR1A = ((F_CPU / 1024) / 2);\r
+ TCCR1B = (1 << WGM12) | (1 << CS12) | (1 << CS10);\r
TIMSK1 = (1 << OCIE1A);\r
\r
/* Clear Dataflash sector protections, if enabled */\r
LEDs_SetAllLEDs(LEDMASK_USB_ENUMERATING);\r
\r
/* Close the log file so that the host has exclusive filesystem access */\r
- f_close(&TempLogFile);\r
+ CloseLogFile();\r
}\r
\r
/** Event handler for the library USB Disconnection event. */\r
{\r
LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY);\r
\r
- /* When disconnected from the host, re-open log file so we can resume logging */\r
- f_mount(0, &DiskFATState);\r
- f_open(&TempLogFile, LOG_FILENAME, FA_OPEN_ALWAYS | FA_WRITE);\r
- f_lseek(&TempLogFile, TempLogFile.fsize);\r
+ /* Mount and open the log file on the dataflash FAT partition */\r
+ OpenLogFile();\r
}\r
\r
/** Event handler for the library USB Configuration Changed event. */\r
\r
if (!(MS_Device_ConfigureEndpoints(&Disk_MS_Interface)))\r
LEDs_SetAllLEDs(LEDMASK_USB_ERROR);\r
+ \r
+ if (!(HID_Device_ConfigureEndpoints(&Generic_HID_Interface)))\r
+ LEDs_SetAllLEDs(LEDMASK_USB_ERROR); \r
}\r
\r
/** Event handler for the library USB Unhandled Control Request event. */\r
void EVENT_USB_Device_UnhandledControlRequest(void)\r
{\r
MS_Device_ProcessControlRequest(&Disk_MS_Interface);\r
+ HID_Device_ProcessControlRequest(&Generic_HID_Interface);\r
}\r
\r
/** Mass Storage class driver callback function the reception of SCSI commands from the host, which must be processed.\r
\r
return CommandSuccess;\r
}\r
+\r
+/** HID class driver callback function for the creation of HID reports to the host.\r
+ *\r
+ * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced\r
+ * \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID\r
+ * \param[in] ReportType Type of the report to create, either REPORT_ITEM_TYPE_In or REPORT_ITEM_TYPE_Feature\r
+ * \param[out] ReportData Pointer to a buffer where the created report should be stored\r
+ * \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent\r
+ *\r
+ * \return Boolean true to force the sending of the report, false to let the library determine if it needs to be sent\r
+ */\r
+bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, uint8_t* const ReportID,\r
+ const uint8_t ReportType, void* ReportData, uint16_t* ReportSize)\r
+{\r
+ Device_Report_t* ReportParams = (Device_Report_t*)ReportData;\r
+\r
+ DS1307_GetDate(&ReportParams->Day, &ReportParams->Month, &ReportParams->Year);\r
+ DS1307_GetTime(&ReportParams->Hour, &ReportParams->Minute, &ReportParams->Second);\r
+ \r
+ ReportParams->LogInterval500MS = LoggingInterval500MS_SRAM;\r
+\r
+ *ReportSize = sizeof(Device_Report_t);\r
+ return true;\r
+}\r
+\r
+/** HID class driver callback function for the processing of HID reports from the host.\r
+ *\r
+ * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced\r
+ * \param[in] ReportID Report ID of the received report from the host\r
+ * \param[in] ReportData Pointer to a buffer where the created report has been stored\r
+ * \param[in] ReportSize Size in bytes of the received HID report\r
+ */\r
+void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, const uint8_t ReportID,\r
+ const void* ReportData, const uint16_t ReportSize)\r
+{\r
+ Device_Report_t* ReportParams = (Device_Report_t*)ReportData;\r
+ \r
+ GPIOR0 = ReportParams->Day;\r
+ GPIOR1 = ReportParams->Month;\r
+ GPIOR2 = ReportParams->Year;\r
+ \r
+ DS1307_SetDate(ReportParams->Day, ReportParams->Month, ReportParams->Year);\r
+ DS1307_SetTime(ReportParams->Hour, ReportParams->Minute, ReportParams->Second);\r
+ \r
+ /* If the logging interval has changed from its current value, write it to EEPROM */\r
+ if (LoggingInterval500MS_SRAM != ReportParams->LogInterval500MS)\r
+ {\r
+ LoggingInterval500MS_SRAM = ReportParams->LogInterval500MS;\r
+ eeprom_write_byte(&LoggingInterval500MS_EEPROM, LoggingInterval500MS_SRAM);\r
+ }\r
+}\r