#include <avr/power.h> #include <stdlib.h> #include <avr/eeprom.h> #include <avr/wdt.h> #include "string.h" #include "lcd_temp.h" #include "bootloader.h" #ifdef LCD #include "lib/lcd.h" #endif #ifdef TIME_H #include "time.h" #endif //#include "eeprom.c" // *** Globals *** char input_buffer[SIZE_INPUT_BUFFER] = ""; char *p_input = input_buffer; uint8_t input_complete = 0; #ifdef RTC volatile int32_t seconds_count = TIMESTAMP; int8_t show_rtc = SHOW_RTC; int8_t timezone = TZ; uint16_t timer_corr = 0; uint16_t timer_corr_counter; #endif #ifdef PWM uint16_t pwm_loop_count = PWM_LOOP_COUNT; // Speed PWM loop cycle int8_t pwm_cycle = 0; // Cycle PWM n times; -1 for continuous #endif #ifdef KEYBOARD uint8_t keyb_buffer[5] = ""; uint8_t keyb_keepalive = 0; #endif #ifdef COUNTER volatile uint32_t counter_major; volatile uint16_t counter_minor; uint16_t counter_minor_overflow = COUNTER_MINOR_OVERFLOW; uint8_t counter_reported; uint16_t counter_minor_report = COUNTER_MINOR_REPORT; volatile uint16_t counter_freq = 0; ISR(COUNTER_INTERRUPT_VECTOR) { counter_minor++; counter_reported = 0; if (counter_minor == counter_minor_overflow) { counter_minor = 0; counter_major++; } } #endif // *** Interupt for 1s counter *** #ifdef RTC ISR(TIMER1_OVF_vect) { TCNT1H = (unsigned char) (TIMER_1000ms >> 8); TCNT1L = (unsigned char) TIMER_1000ms; seconds_count++; #ifdef COUNTER { static uint16_t last_minor; static uint16_t last_major; counter_freq = (counter_major-last_major)*counter_minor_overflow + (counter_minor - last_minor); last_minor = counter_minor; last_major = counter_major; } #endif } #endif // *** USB Class definitions *** USB_ClassInfo_CDC_Device_t VirtualSerial_CDC_Interface = { .Config = { .ControlInterfaceNumber = 0, .DataINEndpoint = { .Address = CDC_TX_EPADDR, .Size = CDC_TXRX_EPSIZE, .Banks = 1, }, .DataOUTEndpoint = { .Address = CDC_RX_EPADDR, .Size = CDC_TXRX_EPSIZE, .Banks = 1, }, .NotificationEndpoint = { .Address = CDC_NOTIFICATION_EPADDR, .Size = CDC_NOTIFICATION_EPSIZE, .Banks = 1, }, }, }; #ifdef KEYBOARD /** Buffer to hold the previously generated Keyboard HID report, for comparison purposes inside the HID class driver. */ static uint8_t PrevKeyboardHIDReportBuffer[sizeof(USB_KeyboardReport_Data_t)]; /** LUFA HID Class driver interface configuration and state information. This structure is * passed to all HID Class driver functions, so that multiple instances of the same class * within a device can be differentiated from one another. */ USB_ClassInfo_HID_Device_t Keyboard_HID_Interface = { .Config = { .InterfaceNumber = 2, .ReportINEndpoint = { .Address = KEYBOARD_EPADDR, .Size = KEYBOARD_EPSIZE, .Banks = 1, }, .PrevReportINBuffer = PrevKeyboardHIDReportBuffer, .PrevReportINBufferSize = sizeof(PrevKeyboardHIDReportBuffer), }, }; /** HID class driver callback function for the creation of HID reports to the host. * * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced * \param[in,out] ReportID Report ID requested by the host if non-zero, otherwise callback should set to the generated report ID * \param[in] ReportType Type of the report to create, either HID_REPORT_ITEM_In or HID_REPORT_ITEM_Feature * \param[out] ReportData Pointer to a buffer where the created report should be stored * \param[out] ReportSize Number of bytes written in the report (or zero if no report is to be sent) * * \return Boolean true to force the sending of the report, false to let the library determine if it needs to be sent */ bool CALLBACK_HID_Device_CreateHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, uint8_t* const ReportID, const uint8_t ReportType, void* ReportData, uint16_t* const ReportSize) { USB_KeyboardReport_Data_t* KeyboardReport = (USB_KeyboardReport_Data_t*)ReportData; if (keyb_buffer[0]) { KeyboardReport->KeyCode[0] = keyb_buffer[0]; keyb_buffer[0] = 0; } *ReportSize = sizeof(USB_KeyboardReport_Data_t); return false; } /** HID class driver callback function for the processing of HID reports from the host. * * \param[in] HIDInterfaceInfo Pointer to the HID class interface configuration structure being referenced * \param[in] ReportID Report ID of the received report from the host * \param[in] ReportType The type of report that the host has sent, either HID_REPORT_ITEM_Out or HID_REPORT_ITEM_Feature * \param[in] ReportData Pointer to a buffer where the received report has been stored * \param[in] ReportSize Size in bytes of the received HID report */ void CALLBACK_HID_Device_ProcessHIDReport(USB_ClassInfo_HID_Device_t* const HIDInterfaceInfo, const uint8_t ReportID, const uint8_t ReportType, const void* ReportData, const uint16_t ReportSize) { } #endif // USB Keyboard /** Event handler for the library USB Configuration Changed event. */ void EVENT_USB_Device_ConfigurationChanged(void) { CDC_Device_ConfigureEndpoints(&VirtualSerial_CDC_Interface); #ifdef KEYBOARD HID_Device_ConfigureEndpoints(&Keyboard_HID_Interface); USB_Device_EnableSOFEvents(); #endif } /** Event handler for the library USB Unhandled Control Request event. */ void EVENT_USB_Device_UnhandledControlRequest(void) { CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); } /** Event handler for the library USB Connection event. */ void EVENT_USB_Device_Connect(void) { input_buffer[0] = 0; p_input = input_buffer; } /** Event handler for the library USB Disconnection event. */ void EVENT_USB_Device_Disconnect(void) { } /** Event handler for the library USB Control Request reception event. */ void EVENT_USB_Device_ControlRequest(void) { CDC_Device_ProcessControlRequest(&VirtualSerial_CDC_Interface); #ifdef KEYBOARD HID_Device_ProcessControlRequest(&Keyboard_HID_Interface); #endif } #ifdef KEYBOARD /** Event handler for the USB device Start Of Frame event. */ void EVENT_USB_Device_StartOfFrame(void) { HID_Device_MillisecondElapsed(&Keyboard_HID_Interface); } #endif // *** USB output wrappers *** inline static void sendstr (char *s) { CDC_Device_SendString(&VirtualSerial_CDC_Interface, s); } inline static void sendchar (char c) { CDC_Device_SendByte(&VirtualSerial_CDC_Interface, c); } inline static void sendstr_P (const char *s) { char p; while ((p = pgm_read_byte_near(s++))) CDC_Device_SendByte(&VirtualSerial_CDC_Interface, p); } #ifdef LCD void lcd_send32 (int32_t s) { int8_t first = 0; if (s < 0) { s = -s; lcd_putc('-'); } if (s) { for (uint32_t n = 1e9; n>0; n=n/10) { uint8_t x = s / n; if (x || first) { lcd_putc(x+48); first = 1; } s = s % n ; } } else lcd_putc(48); } #endif void send32 (int32_t s) { int8_t first = 0; if (s < 0) { s = -s; sendchar('-'); } if (s) { for (uint32_t n = 1e9; n>0; n=n/10) { uint8_t x = s / n; if (x || first) { sendchar(x+48); first = 1; } s = s % n ; } } else sendchar(48); } void sendhex32 (int32_t s) { int8_t first = 0; sendchar('0'); sendchar('x'); if (s) { for (uint32_t n = 0x10000000; n>0; n=n/16) { uint8_t x = s / n; if (x || first) { if (x<10) x += 48; else x += 87; sendchar(x); first = 1; } s = s % n ; } } else sendchar(48); } int32_t read32(char *p) { uint32_t n = 0; char neg = 0; while (*p == ' ') p++; if ( *p == '0' && *(p+1) == 'x') { p++; p++; do { if ( (*p >=65) && (*p <= 70)) // A -> F n =- 55; if ( (*p >=97) && (*p <= 102)) // a -> f n =- 87; if ( (*p >=48) && (*p <= 48+17)) // 0 -> 9 n = n*16 + (*p) - 48; } while ( *(++p) && *p != ' ' ); } else { if (*p =='-') { neg = 1; p++; } do { if ( (*p >=48) && (*p <= 57)) n = n*10 + (*p) - 48; } while ( *(++p) && *p != ' ' ); } if (neg) return -n; else return n; } // *** Config to internal EEPROM *** void read_config(void) { struct s_config *config = malloc(sizeof(struct s_config)); eeprom_read_block(config, 0, sizeof(struct s_config)); if ( (config->signature[0] == 'L') && (config->signature[1] == 'C') && (config->signature[2] == 'D') ) { #ifdef RTC if (config->timestamp > seconds_count) seconds_count = config->timestamp; show_rtc = config->show_rtc; timezone = config->timezone; timer_corr = config->timer_corr; #endif #ifdef PWM OCR0A = config->lcd_bl; pwm_loop_count = config->pwm_loop_count; pwm_cycle = config->pwm_cycle; #else #ifdef LCD_BL_PORT if (config->lcd_bl) LCD_BL_PORT |= LCD_BL_MASK; else LCD_BL_PORT &= ~LCD_BL_MASK; #endif #endif #ifdef KEYBOARD keyb_keepalive = config->keyb_keepalive; #endif #ifdef BUTTONS for (uint8_t n=0; n<TOTAL_BUTTONS; n++) { buttons[n].scancode=config->buttons[n]; } #endif #ifdef RELAYS for (uint8_t n=0; n<TOTAL_RELAYS; n++) { if (config->relays[n]) *relays[n].port |= relays[n].mask; else *relays[n].port &= ~relays[n].mask; } #endif #ifdef COUNTER counter_major = config->counter_major; counter_minor = config->counter_minor; counter_minor_overflow = config->counter_minor_overflow; counter_minor_report = config->counter_minor_report; if (counter_minor > counter_minor_overflow) { counter_minor = counter_minor % counter_minor_overflow; counter_major += counter_minor / counter_minor_overflow; } #endif } free(config); } void save_config(void) { struct s_config *config = malloc(sizeof(struct s_config)); config->signature[0] = 'L'; config->signature[1] = 'C'; config->signature[2] = 'D'; #ifdef RTC config->timestamp = seconds_count; config->show_rtc = show_rtc; config->timezone = timezone; config->timer_corr = timer_corr; #else config->timestamp = TIMESTAMP; config->show_rtc = 0; config->timezone = 0; config->timer_corr = 0; #endif config->lcd_bl = 0; config->pwm_loop_count = 0; config->pwm_cycle = 0; #ifdef PWM config->lcd_bl = OCR0A; config->pwm_loop_count = pwm_loop_count; config->pwm_cycle = pwm_cycle; #else #ifdef LCD_BL_PORT if (LCD_BL_PORT & LCD_BL_MASK) config->lcd_bl = 255; else config->lcd_bl = 0; config->pwm_loop_count = PWM_LOOP_COUNT; config->pwm_cycle = 0; #endif #endif #ifdef KEYBOARD config->keyb_keepalive = keyb_keepalive; #endif #ifdef BUTTONS for (uint8_t n=0; n<TOTAL_BUTTONS; n++) { config->buttons[n]=buttons[n].scancode; } #endif #ifdef RELAYS for (uint8_t n=0; n<TOTAL_RELAYS; n++) { config->relays[n]= (PIN(*relays[n].port)) & relays[n].mask; } #endif #ifdef COUNTER config->counter_major = counter_major; config->counter_minor = counter_minor; config->counter_minor_overflow = counter_minor_overflow; config->counter_minor_report = counter_minor_report; #endif eeprom_write_block(config, 0, sizeof(struct s_config)); free(config); } // *** Temperature code start *** #ifdef TEMP #include "/lib/onewire.h" #include "/lib/ds18x20.h" #include "/lib/crc8.h" #define MAXSENSORS 3 uint8_t gSensorIDs[MAXSENSORS][OW_ROMCODE_SIZE]; uint8_t nSensor; void puthex_nibble(const unsigned char b) { unsigned char c = b & 0x0f; if ( c > 9 ) c += 'A'-10; else c += '0'; sendchar(c); } inline void puthex_byte( const unsigned char b ) { puthex_nibble( b >> 4 ); puthex_nibble( b ); } void DS18X20_show_id( uint8_t *id, size_t n ) { size_t i; for( i = 0; i < n; i++ ) { if ( i == 0 ) { sendstr_P(PSTR("FC: ")); } else if ( i == n-1 ) { sendstr_P(PSTR("CRC: ")); } if ( i == 1 ) { sendstr_P(PSTR("SN: ")); } puthex_byte(id[i]); // sendchar(' '); if ( i == 0 ) { if ( id[0] == DS18S20_FAMILY_CODE ) { sendstr_P(PSTR("(18S)")); } else if ( id[0] == DS18B20_FAMILY_CODE ) { sendstr_P(PSTR("(18B)")); } else if ( id[0] == DS1822_FAMILY_CODE ) { sendstr_P(PSTR("(22)")); } else { sendstr_P(PSTR("( ? )")); } } sendchar(' '); } if (crc8(id, OW_ROMCODE_SIZE)) sendstr_P(&CRC_FAIL[0]); else sendstr_P(&CRC_OK[0]); } void show_sensors(uint8_t n) { uint8_t i; sendstr_P(&SENSORS_FOUND[0]); CDC_Device_SendByte(&VirtualSerial_CDC_Interface, n+48); sendstr_P(&CRLF[0]); for (i = 0; i < n; i++ ) { sendstr_P(PSTR("# in Bus: ")); CDC_Device_SendByte(&VirtualSerial_CDC_Interface, i+1+48); sendchar(':'); sendchar(' '); DS18X20_show_id(&gSensorIDs[i][0], OW_ROMCODE_SIZE ); sendstr_P(&CRLF[0]); } } static uint8_t search_sensors(void) { uint8_t i; uint8_t id[OW_ROMCODE_SIZE]; uint8_t diff, nSensors; ow_reset(); nSensors = 0; diff = OW_SEARCH_FIRST; while ( diff != OW_LAST_DEVICE && nSensors < MAXSENSORS ) { DS18X20_find_sensor( &diff, &id[0] ); if( diff == OW_PRESENCE_ERR ) { // sendstr_P(PSTR("No Sensor found"); // sendstr_P(&CRLF[0]); break; } if( diff == OW_DATA_ERR ) { // sendstr_P(PSTR("Bus Error"); // sendstr_P(&CRLF[0]); break; } for ( i=0; i < OW_ROMCODE_SIZE; i++ ) gSensorIDs[nSensors][i] = id[i]; nSensors++; } return nSensors; } #endif // *** Temperature Code end *** // *** Harware init *** void SetupHardware(void) { #ifdef RTC // Timer_setup TIMSK1 = (1<<TOIE1); // | (1<<TOIE0); // TCCR1B |= (1<<CS12) & ~(1<<CS11) | (1<<CS10); // Timer1 CLK / 1024 // TCCR1B |= ~(1<<CS12) | (1<<CS11) | (1<<CS10); // Timer1 CLK / 64 TCCR1B = (1<<CS12) & ~(1<<CS11) & ~(1<<CS10); // Timer1 CLK / 256 // TCCR0B = (1<<CS02) & ~(1<<CS01) | (1<<CS00); // Timer0 CLK / 1024 #endif #ifdef PWM //PWM 0A PB7 TCCR0A |= (1<<WGM00)|(1<<WGM01)|(1<<COM0A1); TCCR0B |= (1<<CS00); DDRB|=LCD_BL_MASK; OCR0A=0; #endif // Prescaler and watchdog MCUSR &= ~(1 << WDRF); wdt_disable(); clock_prescale_set(clock_div_1); #ifdef LCD lcd_init(LCD_DISP_ON); lcd_puts_p(PSTR("LCD waiting...\n")); DDR(LCD_BL_PORT) |= LCD_BL_MASK; LCD_BL_PORT |= LCD_BL_MASK; #endif #ifdef TEMP nSensor = 0; nSensor = search_sensors(); #ifdef LCD lcd_puts_p(&SENSORS_FOUND[0]); lcd_putc(nSensor+48); lcd_putc('\n'); #endif #endif #ifdef COUNTER COUNTER_REGISTER_INIT; // Defined in lcd_temp.h EIMSK |= (1<<COUNTER_INTERRUPT); DDR(COUNTER_PORT) &= ~(COUNTER_MASK); #endif USB_Init(); sei(); #ifdef LCD lcd_puts_p(PSTR("USB ready...\n")); #endif // Pull target /RESET and HWB line high DDR(AVR_RESET_LINE_PORT) |= AVR_RESET_LINE_MASK; AVR_RESET_LINE_PORT |= AVR_RESET_LINE_MASK; DDR(HWB_PORT) |= HWB_MASK; HWB_PORT |= HWB_MASK; //turn off stat LED connected to PB0 // DDRB |= (1<<0); // sbi(PORTB, 0); // Init input buttons #ifdef BUTTONS for (uint8_t n=0; n<TOTAL_BUTTONS;n++) DDR(*buttons[n].port) &= ~(buttons[n].mask); #endif // Init Relays #ifdef RELAYS for (uint8_t n=0; n<TOTAL_RELAYS;n++) DDR(*relays[n].port) |= relays[n].mask; #endif } // *** Check input buttons *** #ifdef BUTTONS void check_buttons(void) { for (int8_t n=0; n<TOTAL_BUTTONS;n++) { if ( (!(PIN(*buttons[n].port) & (buttons[n].mask))) != buttons[n].status) { buttons[n].count++; if (buttons[n].count == READCOUNT) { buttons[n].status = !(PIN(*buttons[n].port) & (buttons[n].mask)); if (buttons[n].status) { // low/zero sendstr_P(PSTR("BUTTON ")); sendchar(n+48); sendstr_P(&CRLF[0]); #ifdef KEYBOARD if (buttons[n].scancode) keyb_buffer[0] = buttons[n].scancode; #endif //lcd.home(); //lcd_putc('b'); } } } else buttons[n].count = 0; } } #endif // *** Main program *** int main(void) { #ifdef PWM uint16_t loop = PWM_LOOP_COUNT; #endif check_bootloader(); #ifdef CHECK_HWB check_hwb(); #endif SetupHardware(); read_config(); #ifdef RTC timer_corr_counter = timer_corr; int8_t old_second = 0; #ifdef LCD if (show_rtc) lcd_clrscr(); #endif #endif for (;;) { // *** Process USB input *** int16_t ReceivedByte = CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); if (!(ReceivedByte < 0)) { *p_input++ = (char)ReceivedByte; if (*(p_input-1) == '\n') { if (*(p_input-2) == '\r') { *(p_input-2) = 0; } *(p_input-1) = 0; input_complete = 1; p_input = input_buffer; } if (p_input == &input_buffer[SIZE_INPUT_BUFFER-1]) { input_complete = 1; input_buffer[SIZE_INPUT_BUFFER-1] = 0; } } #ifdef BUTTONS check_buttons(); #endif if (input_complete) process_usb_cmd(); #ifdef KEYBOARD HID_Device_USBTask(&Keyboard_HID_Interface); #endif CDC_Device_USBTask(&VirtualSerial_CDC_Interface); USB_USBTask(); // *** Cycle LCD backlight LED intensity *** #ifdef PWM if (pwm_cycle) { if (!loop--) { static uint8_t dir = 1; static uint8_t duty = 0; duty += dir; OCR0A=duty; if (duty == 255) { dir = -1; if (pwm_cycle > 0) { pwm_cycle--;} } if (duty == 0) { dir = 1; if (pwm_cycle > 0) { pwm_cycle--;} } loop = pwm_loop_count; } } #endif // *** Counter report *** #ifdef COUNTER if ( !counter_reported && (counter_minor % counter_minor_report == 0)) { sendstr_P(PSTR("Counter ")); send32(counter_minor); sendchar(' '); send32(counter_major); sendchar(' '); send32(counter_freq); sendchar(' '); send32(seconds_count); sendstr_P(CRLF); counter_reported = 1; } #endif // *** Process timer update *** #ifdef RTC if ( (old_second != (int8_t)seconds_count) ) { if (timer_corr) { if (! --timer_corr_counter) { timer_corr_counter = timer_corr; seconds_count--; } } old_second = (int8_t)seconds_count; #ifdef KEYBOARD // Send shift key ask keep alive every 256s if (!old_second && keyb_keepalive) keyb_buffer[0] = KEYB_KEEPALIVE_KEY; #endif if ( !(seconds_count % TIMER_SAVE_CONFIG) ) { save_config(); } // Save config (timestamp) #ifdef LCD if (show_rtc == 1) lcd_display_time(); if (show_rtc >1) --show_rtc; #endif } #endif // RTC } // for loop } // *** Show time and date on LCD *** #ifdef LCD #ifdef RTC void lcd_display_time(void) { lcd_gotoxy(0, LCD_LINES-1); #ifndef TIME_H // lcd_puts_p(PSTR("Epoch: ")); lcd_gotoxy(LCD_DISP_LENGTH-10, LCD_LINES-1); lcd_send32(seconds_count); #else struct tm *t; t = (struct tm *) malloc(sizeof(struct tm)); timestamp2tm(seconds_count + (timezone*60*60), t); char mystr[12]; // Time progress bar /* lcd.home(); lcd_send32(round( ( (t->tm_hour)*60 + (t->tm_min)) * LCD_DISP_LENGTH/(24*60))); lcd_putc(' '); if ( !t->tm_hour && !t->tm_min && !t->tm_sec) { lcd_gotoxy(0, LCD_LINES-2); for (int8_t i = 0; i < LCD_DISP_LENGTH-1; i++) { lcd_putc('_'); } lcd_putc('X'); } // bar #if FLASHEND >= (0x7FFF) if (!old_second) { lcd_gotoxy(0, LCD_LINES-2); for (int8_t i = 1; i <= round( ((t->tm_hour)*60 + (t->tm_min)) * LCD_DISP_LENGTH/(24*60)); i++) { lcd_putc('.'); } // lcd_putc(' '); } #endif */ lcd_gotoxy(0, LCD_LINES-1); #if LCD_DISP_LENGTH >= 20 strcpy_P(mystr, dayname[t->tm_wday]); lcd_puts(mystr); lcd_putc(' '); strcpy_P(mystr, monthname[t->tm_mon-1]); lcd_puts(mystr); sprintf_P(mystr, PSTR(" %02d "), t->tm_mday); lcd_puts(mystr); #endif #if LCD_DISP_LENGTH == 16 sprintf_P(mystr, PSTR("%02d/%02d "), t->tm_mday, t->tm_mon); lcd_puts(mystr); #endif lcd_gotoxy(LCD_DISP_LENGTH-8, LCD_LINES-1); sprintf_P(mystr, PSTR("%02d:%02d:%02d"), t->tm_hour, t->tm_min, t->tm_sec); lcd_puts(mystr); free(t); #endif // TIME_H lcd.home(); } #endif // RTC #endif // LCD // *** Process input from USB *** void process_usb_cmd(void) { if (!strncmp_P(input_buffer, AT, strlen_P(AT) )) { switch (input_buffer[2]) { case 'r': // Reboot sendstr_P(&REBOOTING[0]); sendstr_P(&CRLF[0]); CDC_Device_Flush(&VirtualSerial_CDC_Interface); CDC_Device_USBTask(&VirtualSerial_CDC_Interface); USB_USBTask(); #ifdef LCD lcd_clrscr(); lcd_puts_p(REBOOTING); #endif save_config(); USB_Disable(); hardware_reset(); break; case 'f': // Enter boot loader sendstr_P(ENTERING); sendstr_P(ENTER_BOOTLOADER); sendstr_P(CRLF); CDC_Device_USBTask(&VirtualSerial_CDC_Interface); CDC_Device_Flush(&VirtualSerial_CDC_Interface); USB_USBTask(); #ifdef LCD lcd_clrscr(); lcd_puts_p(ENTER_BOOTLOADER); #endif // delay(24000); save_config(); USB_Disable(); // for (uint16_t x = 0; x < 50000; x++); boot_loader(); break; case 'v': // Version sendstr_P(COMPILEDATE); sendstr_P(CRLF); break; } #ifdef TEMP // Temperature commands if (!strncmp_P(input_buffer, ATT, strlen_P(ATT) )) { switch (input_buffer[3]) { uint8_t n; int16_t decicelsius; case 's': nSensor = search_sensors(); sendstr_P(&SENSORS_FOUND[0]); sendchar( nSensor + 48); sendstr_P(&CRLF[0]); break; case 'l': show_sensors(nSensor); break; case 't': n = input_buffer[4] - 48; sendstr_P(PSTR("Sensor ")); CDC_Device_SendByte(&VirtualSerial_CDC_Interface, n+48); sendchar(':'); sendchar(' '); if ( DS18X20_start_meas( DS18X20_POWER_EXTERN, &gSensorIDs[n-1][0] ) == DS18X20_OK ) { _delay_ms( DS18B20_TCONV_12BIT ); if ( DS18X20_read_decicelsius( &gSensorIDs[n-1][0], &decicelsius) == DS18X20_OK ) { send32(decicelsius); sendstr_P(PSTR(" dC ")); } else { sendstr_P(&CRC_FAIL[0]); } } else { sendstr_P(PSTR("Error, no contact")); } sendstr_P(CRLF); break; } } #endif #ifdef LCD // LCD Commands if (!strncmp_P(input_buffer, ATLCD, strlen_P(ATLCD) )) { #ifdef RTC if (show_rtc) show_rtc = 5; // Suspend RTC updates for 5s #endif if (!strncmp_P(input_buffer, LCDINIT, strlen_P(LCDINIT) )) { // uint8_t size = strlen_P(LCDINIT); // uint8_t cmd = (input_buffer[size+1]-48) * 10 + input_buffer[size+2]-48; uint8_t cmd = read32(&input_buffer[strlen_P(LCDINIT)]); // CDC_Device_SendString(&VirtualSerial_CDC_Interface, &LCDINIT[0]); if ( cmd != 0x08 && cmd != 0x0D && cmd != 0x0E && cmd != 0x0F ) cmd = 0x0C; // default on, no blink or curser lcd_init(cmd); sendstr_P(OK); } if (!strncmp_P(input_buffer, LCDCLRSCR, strlen_P(LCDCLRSCR) )) { lcd_clrscr(); sendstr_P(OK); } if (!strncmp_P(input_buffer, LCDHOME, strlen_P(LCDHOME) )) { lcd.home(); sendstr_P(OK); } if (!strncmp_P(input_buffer, LCDGOTOXY, strlen_P(LCDGOTOXY) )) { uint8_t size = strlen(LCDGOTOXY); if (input_buffer[size] == ' ') size++; uint8_t x = (input_buffer[size]-48)*10 + input_buffer[size+1]-48; uint8_t y = (input_buffer[size+2]-48)*10 + input_buffer[size+3]-48; lcd_gotoxy(x, y); } if (!strncmp_P(input_buffer, LCDPUTC, strlen_P(LCDPUTC) )) { lcd_putc(input_buffer[strlen(LCDPUTC)+1]); sendstr_P(OK); } if (!strncmp_P(input_buffer, LCDCMD, strlen_P(LCDCMD) )) { lcd_command(read32(&input_buffer[strlen_P(LCDCMD)])); sendstr_P(OK); } if (!strncmp_P(input_buffer, LCDBLON, strlen_P(LCDBLON) )) { #ifdef PWM OCR0A = 0; #else LCD_BL_PORT &= ~LCD_BL_MASK; #endif sendstr_P(OK); } if (!strncmp_P(input_buffer, LCDBLOFF, strlen_P(LCDBLOFF) )) { #ifdef PWM OCR0A = 255; #else LCD_BL_PORT |= LCD_BL_MASK; #endif sendstr_P(OK); } #endif // LCD #ifdef PWM if (!strncmp_P(input_buffer, LCDPWMSET, strlen_P(LCDPWMSET) )) { OCR0A = 255 - read32(&input_buffer[strlen_P(LCDPWMSET)]); sendstr_P(OK); } if (!strncmp_P(input_buffer, LCDPWMLOOP, strlen_P(LCDPWMLOOP) )) { pwm_loop_count = read32(&input_buffer[strlen_P(LCDPWMLOOP)]); sendstr_P(OK); } if (!strncmp_P(input_buffer, LCDPWMCYCLE, strlen_P(LCDPWMCYCLE) )) { pwm_cycle = read32(&input_buffer[strlen_P(LCDPWMCYCLE)]); sendstr_P(OK); } #endif // PWM #ifdef LCD } #endif // LCD // *** EEPROM Commands *** /* if (!strncmp_P(input_buffer, &EEREAD[0], strlen_P(&EEREAD[0]) )) { char mystr[10]; write_SPIeeprom (0, &mystr[10], 6); sendstr(mystr); sendstr("\r\n"); } */ // Mark EEPROM as clear if (!strncmp_P(input_buffer, EECLEAR, strlen_P(EECLEAR) )) { eeprom_write_dword(0, 0); sendstr_P(OK); } #ifdef RTC // Set RTC if (!strncmp_P(input_buffer, RTCSET, strlen_P(RTCSET) )) { seconds_count = read32(&input_buffer[strlen_P(RTCSET)]); if (seconds_count < 0) seconds_count = 0; timer_corr_counter = timer_corr; save_config(); sendstr_P(OK); } // Get RTC if (!strncmp_P(input_buffer, RTCGET, strlen_P(RTCGET) )) { send32(seconds_count); sendstr_P(CRLF); } // Set RTC offset if (!strncmp_P(input_buffer, RTCOSET, strlen_P(RTCOSET) )) { timer_corr = read32(&input_buffer[strlen_P(RTCOSET)]); timer_corr_counter = timer_corr; save_config(); sendstr_P(OK); } // Get RTC offset if (!strncmp_P(input_buffer, RTCOGET, strlen_P(RTCOGET) )) { send32(timer_corr); sendstr_P(CRLF); } // Turn on LCD RTC if (!strncmp_P(input_buffer, RTCON, strlen_P(RTCON) )) { show_rtc = 1; sendstr_P(OK); } // Turn off LCD RTC if (!strncmp_P(input_buffer, RTCOFF, strlen_P(RTCOFF) )) { show_rtc = 0; sendstr_P(OK); } #ifdef TIME_H // Set Timezone if (!strncmp_P(input_buffer, RTCTZSET, strlen_P(RTCTZSET) )) { timezone = read32(&input_buffer[strlen_P(RTCTZSET)]); if (timezone > 12) timezone = 0; if (timezone < -12) timezone = 0; sendstr_P(OK); save_config(); } // Get Timezone if (!strncmp_P(input_buffer, RTCTZGET, strlen_P(RTCTZGET) )) { send32(timezone); sendstr_P(CRLF); } // Write formatted RTC to USB // # if FLASHEND > (0x3FFF) if (!strncmp_P(input_buffer, RTCNOW, strlen_P(RTCNOW) )) { char mystr[12]; struct tm *t; t = (struct tm *) malloc(sizeof(struct tm)); timestamp2tm(seconds_count+timezone*60*60, t); #if LCD_DISP_LENGTH >= 20 sendstr_P(dayname[t->tm_wday]); #else sendchar(t->tm_wday+48); #endif sendchar(' '); send32(t->tm_yday); for (;t->tm_year > 100; t->tm_year -= 100); sprintf_P(mystr, PSTR(" %02d-%02d-%02d "), t->tm_year, t->tm_mon, t->tm_mday); sendstr(mystr); sprintf_P(mystr, PSTR("%02d:%02d:%02d\r\n"), t->tm_hour, t->tm_min, t->tm_sec); sendstr(mystr); free(t); } // # endif // FLASHEND #endif // TIME_H #endif // RTC #ifdef KEYBOARD if (!strncmp_P(input_buffer, ATKEYB, strlen_P(ATKEYB) )) { // Turn on keyboard keep alive, sending of shift key every 256 sec if (!strncmp_P(input_buffer+strlen_P(ATKEYB), KEYBALIVEON, strlen_P(KEYBALIVEON) )) { keyb_keepalive = 1; sendstr_P(OK); save_config(); } // Turn off keyboard keep alive, sending of shift key every 256 sec if (!strncmp_P(input_buffer+strlen_P(ATKEYB), KEYBALIVEOFF, strlen_P(KEYBALIVEOFF) )) { keyb_keepalive = 0; sendstr_P(OK); save_config(); } #ifdef BUTTONS // Get Keyboard scan code for button if (!strncmp_P(input_buffer+strlen_P(ATKEYB), KEYBGETKEY, strlen_P(KEYBGETKEY) )) { uint8_t n = read32(input_buffer + strlen_P(ATKEYB) + strlen_P(KEYBGETKEY)); if (n < TOTAL_BUTTONS) { sendhex32(buttons[n].scancode); } else { sendstr_P(BTN_NOT_DEFINED); } sendstr_P(CRLF); } // Set Keyboard scan code for button if (!strncmp_P(input_buffer+strlen_P(ATKEYB), KEYBSETKEY, strlen_P(KEYBSETKEY) )) { uint8_t n = read32(input_buffer + +strlen_P(ATKEYB) + strlen_P(KEYBSETKEY)); if (n < TOTAL_BUTTONS) { buttons[n].scancode = read32(&input_buffer[strlen_P(KEYBSETKEY)+2]); sendstr_P(OK); save_config(); } else { sendstr_P(BTN_NOT_DEFINED); sendstr_P(CRLF); } } // Get Keyboard status for button n if (!strncmp_P(input_buffer+strlen_P(ATKEYB), KEYBSTATUS, strlen_P(KEYBSTATUS) )) { uint8_t n = read32(input_buffer + strlen_P(ATKEYB) + strlen_P(KEYBSTATUS)); if (n < TOTAL_BUTTONS) { if (!(PIN(*buttons[n].port) & (buttons[n].mask))) sendstr_P(PSTR("ON")); else sendstr_P(PSTR("OFF")); } else { sendstr_P(BTN_NOT_DEFINED); } sendstr_P(CRLF); } #endif // BUTTONS } #endif //KEYBOARD #ifdef RELAYS // Turn on relay if (!strncmp_P(input_buffer, RELAYON, strlen_P(RELAYON) )) { uint8_t n = read32(input_buffer + strlen_P(RELAYON)); if (n < TOTAL_RELAYS) { *relays[n].port &= ~relays[n].mask; // zero/low sendstr_P(OK); save_config(); } else { sendstr_P(RELAY_NOT_DEFINED); sendstr_P(CRLF); } } // Turn off relay if (!strncmp_P(input_buffer, RELAYOFF, strlen_P(RELAYOFF) )) { uint8_t n = read32(input_buffer + strlen_P(RELAYOFF)); if (n < TOTAL_RELAYS) { *relays[n].port |= relays[n].mask; // one/high sendstr_P(OK); save_config(); } else { sendstr_P(RELAY_NOT_DEFINED); sendstr_P(CRLF); } } #endif // Relay #ifdef COUNTER // Get Major counter, minor counter, freq, minor report, minor overflow and timestamp if (!strncmp_P(input_buffer, COUNTERGET, strlen_P(COUNTERGET) )) { send32(counter_major); sendchar(' '); send32(counter_minor); sendchar(' '); send32(counter_freq); sendchar(' '); send32(counter_minor_report); sendchar(' '); send32(counter_minor_overflow); sendchar(' '); send32(seconds_count); sendstr_P(CRLF); } // Set Major counter if (!strncmp_P(input_buffer, COUNTERMAJORSET, strlen_P(COUNTERMAJORSET) )) { counter_major = read32(input_buffer + strlen_P(COUNTERMAJORSET)); sendstr_P(OK); sendstr_P(CRLF); save_config(); } // Set minor counter if (!strncmp_P(input_buffer, COUNTERMINORSET, strlen_P(COUNTERMINORSET) )) { counter_minor = read32(input_buffer + strlen_P(COUNTERMINORSET)); sendstr_P(OK); save_config(); } // Set minor overflow if (!strncmp_P(input_buffer, COUNTEROVERFLOW, strlen_P(COUNTEROVERFLOW) )) { counter_minor_overflow = read32(input_buffer + strlen_P(COUNTEROVERFLOW)); sendstr_P(OK); save_config(); } // Set minor report if (!strncmp_P(input_buffer, COUNTERREPORT, strlen_P(COUNTERREPORT) )) { counter_minor_report = read32(input_buffer + strlen_P(COUNTERREPORT)); if (counter_minor > counter_minor_overflow) { counter_minor = counter_minor % counter_minor_overflow; counter_major += counter_minor / counter_minor_overflow; } sendstr_P(OK); save_config(); } #endif } else { // Print to LCD and echo back to host #ifdef LCD lcd_puts(input_buffer); //lcd_putc('\n'); #endif sendstr_P(PSTR("Re: ")); sendstr(input_buffer); sendstr_P(CRLF); } CDC_Device_Flush(&VirtualSerial_CDC_Interface); input_buffer[0] = 0; input_complete = 0; p_input = input_buffer; }