#include #include #include #include #include #include "serial.h" #include "writepin.h" #include "train.h" #include "eeprom.h" #include "bitrep.h" #define MAX_TRAINS 16 #define COMMAND_BUFFER_SIZE 64 #define SNPRINTF_BUFFER_SIZE 64 char buffer[SNPRINTF_BUFFER_SIZE]; uint16_t storedTrains = 0; Train trains[MAX_TRAINS]; #define TICK_MAX 255 uint8_t tick = 0; bool autoff = true; bool powerIsOn = true; ISR(TIMER0_OVF_vect) { if(powerIsOn) { ++tick; if(tick == TICK_MAX) { for(uint16_t i = 0; i < storedTrains; i++) trains[i].resendSpeed(); if(autoff) { bool trainsRunning = false; for(uint16_t i = 0; i < storedTrains; i++) trainsRunning = trainsRunning || trains[i].getSpeed(); if(!trainsRunning) { powerIsOn = false; Train::setOutput(Train::OFF); } } tick = 0; } else { Train::setOutput(Train::HIGH); _delay_us(200); Train::setOutput(Train::LOW); } } } void save_state() { EEPROM_write_char( 0, storedTrains ); EEPROM_write_char( 1, autoff ); for(uint16_t i = 0; i < storedTrains; i++) { EEPROM_write_char( i+32, trains[i].getAddress()); } } void restore_state() { storedTrains = EEPROM_read_char(0); autoff = EEPROM_read_char(1); if(storedTrains > MAX_TRAINS ) { for(uint16_t i = 0; i < MAX_TRAINS+32; i++) EEPROM_write_char(i, 0); storedTrains = 0; } else for(uint8_t i = 0; i <= storedTrains; i++) { uint8_t address = EEPROM_read_char(32+i); trains[i].setAddress(address); } } inline static void printHelp(Serial* serial) { serial->write_p(PSTR("Available Commands: \n\ help : Show this prompt.\n\ train add [address] : Add train.\n\ train delete : Delete last train.\n\ train list : Print list of saved trains.\n\ train [nn] stop : Stop nth train.\n\ train [nn] speed [sp] : Set nth train speed.\n\ train [nn] function [x] : Toggle x'ed fuction on train n.\n\ train [nn] reverse : Reverse train n.\n\ stop : stop all trains\n\ power off : power off the rail\n\ power on : power on the rail\n\ power auto : power off the rail when no trains are moveing\n\ dump : prints epprom contence\n\ erase : Erase epprom.\n")); } void trainDispatch(char* inBuffer, Serial* serial) { cli(); if(powerIsOn == false) { powerIsOn = true; Train::setOutput(Train::LOW); _delay_ms(100); } if( strcmp(inBuffer, "add") == 0 ) { char* token = strtok(NULL, " "); uint8_t address = strtol(token, nullptr, 2 ); if(address != 0 && storedTrains < MAX_TRAINS) { trains[storedTrains].setAddress(address); uint8_t size = snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRAIN saved! NUMBER: %u ADRESS: %s%s\n", storedTrains, bit_rep[address >> 4], bit_rep[address & 0x0F]); serial->write(buffer, size); storedTrains++; save_state(); } else serial->write_p(PSTR("Usage: train add [address]")); } else if( strcmp(inBuffer, "delete") == 0) { serial->write_p(PSTR("Train: ")); serial->write(storedTrains); serial->write_p(PSTR(" deleted\n")); storedTrains--; } else if( strcmp(inBuffer, "list") == 0 ) { serial->write_p(PSTR("Trains:\n")); for(uint8_t i = 0; i < storedTrains; i++) { snprintf(buffer, SNPRINTF_BUFFER_SIZE, "NUMBER: %u ID: %s%s CURRENT SPD: %u\n", i, bit_rep[trains[i].getAddress() >> 4], bit_rep[trains[i].getAddress() & 0x0F], trains[i].getSpeed()); serial->write(buffer, SNPRINTF_BUFFER_SIZE); } serial->putChar('\n'); } else { uint8_t id = strtol(inBuffer, nullptr, 10); if(id < storedTrains ) { char* token = strtok(NULL, " "); if( token != NULL && strcmp(token, "speed") == 0 ) { token = strtok(NULL, " "); trains[id].setSpeed(atoi(token)); serial->write_p(PSTR("Set Train speed\n")); } else if(token != NULL && strcmp(token, "function") == 0 ) { token = strtok(NULL, " "); if(token != NULL) { for(uint16_t j = 0; j < 8; j++) { uint16_t i = strtol(token, nullptr, 16 ); trains[id].sendFunction(i); snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRYING: %x\n", i); serial->write(buffer, strlen(buffer)); sei(); _delay_ms(250); cli(); } } /* trains[id].sendFunction(atoi(token)); serial->write_p(PSTR("Set Train function\n"));*/ } else if( token != NULL && strcmp(token, "reverse") == 0 ) { trains[id].reverse(); serial->write_p(PSTR("Reversed Train\n")); } else if( token != NULL && strcmp(token, "stop") )trains[id].setSpeed(0); else serial->write_p(PSTR("Not a valid command\n")); } else serial->write_p(PSTR("Id out of range.\n")); } sei(); } void powerDispatch(char* token, Serial* serial) { if(strcmp(token, "off") == 0) { for(uint16_t i = 0; i < storedTrains; i++) { trains[i].setSpeed(0); } Train::setOutput(Train::OFF); powerIsOn = false; } else if( strcmp(token, "on") == 0) { for(uint16_t i = 0; i < storedTrains; i++) { trains[i].setSpeed(0); } Train::setOutput(Train::LOW); } else if(strcmp(token, "auto") == 0) { token = strtok(NULL, " "); if(token != NULL && strcmp(token, "on") == 0) { autoff = true; serial->write_p(PSTR("auto power off turned on.\n")); save_state(); } else if(token != NULL && strcmp(token, "off") == 0) { autoff = false; serial->write_p(PSTR("auto power off turned off.\n")); save_state(); } else { serial->write_p(PSTR("argument must be \"on\" or \"off\". This feature is currently ")); autoff ? serial->write_p(PSTR("on.\n")) : serial->write_p(PSTR("off.\n")); } } } void serialDispatch(Serial* serial) { if(serial->dataIsWaiting()) { char buffer[COMMAND_BUFFER_SIZE]; unsigned int length = serial->getString(buffer, COMMAND_BUFFER_SIZE); if(length > 2) { serial->write_p(PSTR("Got: ")); serial->putChar('\"'); serial->write(buffer, length); serial->write("\"\n"); char* token = strtok(buffer, " "); if(length > 4 && strcmp(token, "train") == 0) { token = strtok(NULL, " "); if(token != NULL)trainDispatch(token, serial); } else if(length > 4 && strncmp(token, "erase", 4) == 0) { for(uint16_t i = 0; i < MAX_TRAINS+1; i++) EEPROM_write_char(i, 0); serial->write_p(PSTR("EEPROM erased\n")); storedTrains = 0; } else if(length > 3 && strcmp(token, "dump") == 0) { for(uint16_t i = 0; i < MAX_TRAINS+32; i++) { if(i != 0) serial->putChar(','); serial->write((uint16_t)EEPROM_read_char(i)); } serial->putChar('\n'); } else if(length > 3 && strcmp(token, "stop") == 0) { for(uint16_t i = 0; i < storedTrains; i++) { cli(); trains[i].setSpeed(0); sei(); } } else if(length > 3 && strcmp(token, "power") == 0) { token = strtok(NULL, " "); if(token != NULL)powerDispatch(token, serial); } else if(length > 3 && strcmp(token, "help") == 0) { printHelp(serial); } else { serial->putChar('\"'); serial->write(buffer, length); serial->putChar('\"'); serial->write_p(PSTR(" is not a valid command\n")); } } } } int main() { TCNT0 = 0; TIMSK0 = 0b00000001; //turn on timer0 interupt on OCIEB TCCR0B = (1<