#include #include #include #include #include #include "serial.h" #include "writepin.h" #include "eeprom.h" #include "bitrep.h" #include "watchdog.h" #include "staticvector.h" #include "W433DataReciver.h" #include "CL56.h" #include "buttons.h" #include "ds1302.h" #include "sensor.h" #include "pwm.h" #define MAX_SENSORS 32 #define COMMAND_BUFFER_SIZE 64 #define SNPRINTF_BUFFER_SIZE 96 void buttonHandler(uint8_t index, uint8_t type, void* data); SVector sensors; ShiftReg<16> shiftReg(&PORTB, PB3, PB2, PB1); DS1302 clock(&PORTC, &PINC, &DDRC, PC0, PC2, PC1); DualCl56 display(&shiftReg); Buttons buttons(&buttonHandler); uint8_t displaying = 0; char buffer[SNPRINTF_BUFFER_SIZE]; volatile bool sensorsPaused=true; ISR(INT1_vect) { W433DataReciver::staticInterrupt(); } ISR(TIMER2_OVF_vect) { display.tick(); buttons.tick(); } void buttonHandler(uint8_t index, uint8_t type, void* data) { if(index == 0 && type == Buttons::RELEASED) { if(++displaying < sensors.count()+2); else displaying = 0; } } void printSensor(const Sensor& sensor, Serial* serial) { serial->write_p(PSTR("SENSOR TYPE: ")); serial->write(sensor.type); serial->write_p(PSTR(" ID: ")); serial->write(sensor.id); if(sensor.type == 1) serial->write_p(PSTR(" TEMPERATURE: ")); else if(sensor.type == 2) serial->write_p(PSTR(" HUMIDITY: ")); else serial->write_p(PSTR(" FIELD: ")); serial->write(sensor.field); serial->putChar('\n'); } void packetHandler(uint32_t packet, void* data) { Serial* serial = reinterpret_cast(data); Sensor sensor; sensor.field = packet & 0x0000FFFF; sensor.type = packet >> 24; sensor.id = (packet & 0x00FF0000) >> 16; bool found = false; for(uint8_t i = 0; i < sensors.count() && !found; ++i) { if(sensors[i] == sensor) { sensors[i] = sensor; found = true; } } if(!found) sensors.push_back(sensor); if(!sensorsPaused) printSensor(sensor, serial); } void reciverError(uint8_t code, void* userData) { if(!sensorsPaused) { Serial* serial = reinterpret_cast(userData); serial->write_p(PSTR("RECV ERROR CODE: ")); serial->write(code); serial->putChar('\n'); } } inline static void printHelp(Serial* serial) { serial->write_p(PSTR("Available Commands: \n\ help : Show this prompt.\n\ date : Show current date and time.\n\ set [yyyy] [mm] [dd] [hh] [mm] [ss] : Show current date and time.\n\ pause : pause sensor output.\n\ resume : resume sensor output.\n\ dump : Dump epprom.\n\ free : Show free ram.\n\ beep : Test buzzer.\n\ list : List sensors.\n")); } int freeRAM() { extern int __heap_start, *__brkval; int v; return (int) &v - (__brkval == 0 ? (int) &__heap_start: (int) __brkval); } void serialDispatch(Serial* serial, SVector* sensors) { if(serial->dataIsWaiting()) { char buffer[COMMAND_BUFFER_SIZE]; unsigned int length = serial->getString(buffer, COMMAND_BUFFER_SIZE); if(length > 2) { char* token = strtok(buffer, " \n"); if(strcmp(token, "date") == 0) { DS1302::Timeval time = clock.getTime(); snprintf(buffer, SNPRINTF_BUFFER_SIZE, "%04u.%02u.%02u %02u:%02u:%02u\n", time.year, time.month, time.day, time.hour, time.min, time.sec); serial->write(buffer, SNPRINTF_BUFFER_SIZE); } else if(strcmp(token, "set") == 0) { char* year = strtok(NULL, " \n"); char* mon = strtok(NULL, " \n"); char* day = strtok(NULL, " \n"); char* hour = strtok(NULL, " \n"); char* min = strtok(NULL, " \n"); char* sec = strtok(NULL, " \n"); if(year != NULL && mon != NULL && day != NULL && hour != NULL && min != NULL && sec != NULL) { DS1302::Timeval time = {atoi(sec),atoi(min),atoi(hour),atoi(day),atoi(mon),atoi(year)}; clock.setTime(time); serial->write_p(PSTR("date and time set\n")); display.setString("SET"); _delay_ms(1000); } else serial->write_p(PSTR("usage: set [yyyy] [mm] [dd] [hh] [mm] [ss]\n")); } else if(strcmp(token, "pause") == 0) { sensorsPaused = true; serial->write_p(PSTR("Sensors paused\n")); } else if(strcmp(token, "resume") == 0) { sensorsPaused = false; serial->write_p(PSTR("Sensors resumed\n")); } else if(strcmp(token, "list") == 0) { serial->write_p(PSTR("Sensors:\n")); for(uint8_t i = 0; i < sensors->count(); ++i) printSensor(sensors->at(i), serial); serial->write('\n'); } else if(strcmp(token, "erase") == 0) { for(uint16_t i = 0; i < 1024; i++) EEPROM_write_char(i, 0); serial->write_p(PSTR("EEPROM erased\n")); } else if(strcmp(token, "dump") == 0) { for(uint16_t i = 0; i < 1024; i++) { if(i != 0) serial->putChar(','); serial->write((uint16_t)EEPROM_read_char(i)); } serial->putChar('\n'); } else if(strcmp(token, "free") == 0) { serial->write_p(PSTR("Free Ram: ")); serial->write(freeRAM()); serial->write_p(PSTR(" Bytes.\n")); } else if(strcmp(token, "beep") == 0) { for(uint16_t i = 0; i < 250; ++i) { writePin(&PORTD, PD4, true); _delay_us(500); writePin(&PORTD, PD4, false); _delay_us(1000); } } else if(strcmp(token, "help") == 0) { printHelp(serial); } else serial->write_p(PSTR("Not a valid command\n")); } } } void displayItems(const DS1302::Timeval& time) { switch(displaying) { case 0: writePin(&PORTB, PB4, time.sec % 2); snprintf(buffer, 9, " %02u%02u", time.hour, time.min); display.setString(buffer); break; case 1: writePin(&PORTB, PB4, false); snprintf(buffer, 9, "%02u%02u%04u", time.day, time.month, time.year); display.setString(buffer, DualCl56::DP_B | DualCl56::DP_D); break; default: if(displaying == 2 && sensors.count() == 0) display.setString("0 SENSOR"); else { writePin(&PORTB, PB4, false); snprintf(buffer, 9, "%u%3u%4u", sensors[displaying-2].id, sensors[displaying-2].type, sensors[displaying-2].field); display.setString(buffer, sensors[displaying-2].type == 1 || sensors[displaying-2].type == 2 ? DualCl56::DP_G : 0); } } } int main() { DDRB = (1 << PB1) | ( 1 << PB2) | ( 1 << PB3) | ( 1 << PB4) | ( 1 << PB5); DDRD = 1<(&serial), &reciverError); uint8_t deleteDate = 0; serial.write_p(PSTR("Ready\n")); while(true) { time = clock.getTime(); displayItems(time); serialDispatch(&serial, &sensors); if(deleteDate != time.day) { displaying = 0; sensors.clear(); deleteDate = time.day; } } return 0; }