From ba67c5138d83ec63fa40fc56caa926df43f2e714 Mon Sep 17 00:00:00 2001 From: uvos Date: Wed, 19 Jan 2022 22:35:55 +0100 Subject: [PATCH] send sucess message if command is processed sucessfully --- main.cpp | 686 ++++++++++++++++++++++++++++++------------------------ serial.h | 2 +- train.cpp | 176 ++++++++------ train.h | 51 ++-- trains | 8 +- 5 files changed, 513 insertions(+), 410 deletions(-) diff --git a/main.cpp b/main.cpp index 7ed6f78..efd533d 100644 --- a/main.cpp +++ b/main.cpp @@ -12,7 +12,7 @@ #define MAX_TRAINS 16 #define COMMAND_BUFFER_SIZE 64 -#define SNPRINTF_BUFFER_SIZE 64 +#define SNPRINTF_BUFFER_SIZE 128 #define EPPROM_SIZE 1024 char buffer[SNPRINTF_BUFFER_SIZE]; @@ -30,344 +30,414 @@ volatile bool resendEvent = false; ISR(TIMER0_OVF_vect) { - ++tick; - if(tick == 0) resendEvent = true; - if((tick & 0b00000111) < 1) Train::setOutput(Train::HIGH); - else Train::setOutput(Train::LOW); + ++tick; + if(tick == 0) + resendEvent = true; + if((tick & 0b00000111) < 1) Train::setOutput(Train::HIGH); + else Train::setOutput(Train::LOW); } void timer0InterruptEnable(const bool enable) { - if(enable) TIMSK0 = 0b00000001; - else TIMSK0 = 0b00000000; + if(enable) TIMSK0 = 0b00000001; + else TIMSK0 = 0b00000000; } void save_state() { - cli(); - EEPROM_write_char( 0, storedTrains ); - EEPROM_write_char( 1, autoff ); - for(uint16_t i = 0; i < storedTrains; i++) - { - EEPROM_write_char( i*2+32, trains[i].getAddress()); - EEPROM_write_char( i*2+32+1, trains[i].getProtocol()); - } - sei(); + cli(); + EEPROM_write_char( 0, storedTrains ); + EEPROM_write_char( 1, autoff ); + for(uint16_t i = 0; i < storedTrains; i++) + { + EEPROM_write_char( i*2+32, trains[i].getAddress()); + EEPROM_write_char( i*2+32+1, trains[i].getFunctionMask()); + } + sei(); } void restore_state() { - storedTrains = EEPROM_read_char(0); - autoff = EEPROM_read_char(1); - if(storedTrains > MAX_TRAINS ) - { - for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0); - storedTrains = 0; - } - else for(uint8_t i = 0; i < storedTrains; i++) - { - trains[i].setAddress(EEPROM_read_char(32+i*2)); - trains[i].setProtocol(EEPROM_read_char(32+1+i*2)); - } + storedTrains = EEPROM_read_char(0); + autoff = EEPROM_read_char(1); + if(storedTrains > MAX_TRAINS ) + { + for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0); + storedTrains = 0; + } + else for(uint8_t i = 0; i < storedTrains; i++) + { + trains[i].setAddress(EEPROM_read_char(32+i*2)); + trains[i].setFunctionMask(EEPROM_read_char(32+1+i*2)); + } } 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")); + serial->write_p(PSTR("Available Commands: \n\ + help : Show this prompt.\n\ + train add [address] [functionmask] : Add train.\n\ + train delete : Delete last train.\n\ + train list : Print list of saved trains.\n\ + train [nn] s(top) : Stop nth train.\n\ + train [nn] s(peed) [sp] : Set nth train speed.\n\ + train [nn] function [x] : Toggle x'ed fuction on train n.\n\ + train [nn] r(everse) : 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) +int trainDispatch(char* inBuffer, Serial* serial) { - cli(); - if( strcmp(inBuffer, "add") == 0 ) - { - char* token = strtok(NULL, " "); - uint8_t address = 0; - if(token != NULL) address = strtol(token, nullptr, 2 ); - if(address != 0 && storedTrains < MAX_TRAINS) - { - trains[storedTrains].setAddress(address); - - token = strtok(NULL, " "); - if(token != NULL && strcmp(token, "delta") == 0 ) trains[storedTrains].setProtocol(Train::M_DELTA); - else trains[storedTrains].setProtocol(Train::M_DIGITAL); - - uint8_t size = snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRAIN saved! NUMBER: %u ADRESS: %s%s PROTCOL: %s\n", storedTrains, bit_rep[address >> 4], bit_rep[address & 0x0F], trains[storedTrains].getProtocol() == Train::M_DELTA ? "delta" : "digital" ); - serial->write(buffer, size); - - storedTrains++; - save_state(); - } - 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 PACKET: %x SPEED: %u", i, bit_rep[trains[i].getAddress() >> 4], bit_rep[trains[i].getAddress() & 0x0F], trains[i].getLastPacket(), trains[i].getSpeed()); - serial->write(buffer, SNPRINTF_BUFFER_SIZE); - serial->write_p(PSTR(" PROTOCOL: ")); - if(trains[i].getProtocol() == Train::M_DELTA)serial->write_p(PSTR("delta\n")); - else serial->write_p(PSTR("digital\n")); - } - serial->putChar('\n'); - } - else - { - uint8_t id = strtol(inBuffer, nullptr, 10); - if(id < storedTrains ) - { - if(powerIsOn == false) - { - powerIsOn = true; - Train::setOutput(Train::LOW); - _delay_ms(100); - timer0InterruptEnable(true); - } - char* token = strtok(NULL, " "); - if( token != NULL && (strcmp(token, "speed") == 0 || strcmp(token, "s") == 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, " "); - char* boolToken = strtok(NULL, " "); - if(token != NULL && boolToken != NULL) - { - uint8_t functionId = atoi(token); - bool on = (strcmp(boolToken, "on") == 0); - trains[id].sendFunction(functionId, on ); - serial->write_p(PSTR("Set Train function ")); - serial->write(functionId); - serial->write(on ? " on\n" : " off\n"); - } - } - else if(token != NULL && strcmp(token, "probe") == 0 ) - { - for(uint16_t j = 0; j < 1024; j++) - { - trains[id].sendRaw(j); - snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRYING: %x\n", j); - serial->write(buffer, strlen(buffer)); - sei(); - _delay_ms(250); - cli(); - - } - } - else if(token != NULL && strcmp(token, "raw") == 0 ) - { - token = strtok(NULL, " "); - if(token != NULL) - { - cli(); - uint16_t i = strtol(token, nullptr, 16 ); - snprintf(buffer, SNPRINTF_BUFFER_SIZE, "SENDING: %x\n", i); - serial->write(buffer, strlen(buffer)); - for(uint8_t j = 0; j < 100; j++) - { - trains[id].sendRaw(i); - _delay_ms(20); - } - serial->write_p(PSTR("Finished\n")); - sei(); - } - } - else if( token != NULL && (strcmp(token, "reverse") == 0 || strcmp(token, "r") == 0) ) - { - trains[id].reverse(); - serial->write_p(PSTR("Reversed Train\n")); - } - else if( token != NULL && (strcmp(token, "stop") == 0 || strcmp(token, "p") == 0)) trains[id].stop(); - else serial->write_p(PSTR("Not a valid command\n")); - } - else serial->write_p(PSTR("Id out of range.\n")); - } - sei(); + if( strcmp(inBuffer, "add") == 0 ) + { + char* token = strtok(NULL, " "); + uint8_t address = 0; + if(token != NULL) + address = strtol(token, nullptr, 10); + if(address != 0 && storedTrains < MAX_TRAINS) + { + trains[storedTrains].setAddress(address); + + token = strtok(NULL, " "); + if(token != NULL) + trains[storedTrains].setFunctionMask(strtol(token, nullptr, 2 )); + + uint8_t size = snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRAIN saved! NUMBER: %u ADDRESS: %u FUNCTIONS: %u FUNCTIONMASK: %u\n", + storedTrains, + address, + trains[storedTrains].getFunctions(), + trains[storedTrains].getFunctionMask()); + serial->write(buffer, size); + + storedTrains++; + save_state(); + return 0; + } + serial->write_p(PSTR("Usage: train add [address] [functionmask]")); + } + else if( strcmp(inBuffer, "delete") == 0) + { + serial->write_p(PSTR("Train: ")); + serial->write(storedTrains-1); + serial->write_p(PSTR(" deleted\n")); + storedTrains--; + if(storedTrains < 0) + storedTrains = 0; + save_state(); + return 0; + } + 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: %u CURRENT PACKET: %x SPEED: %i FUNCTIONS: %u FUNCTIONMASK: %u\n", + i, trains[i].getAddress(), + trains[i].getLastPacket(), trains[i].getSpeed(), + trains[i].getFunctions(), trains[i].getFunctionMask()); + serial->write(buffer, SNPRINTF_BUFFER_SIZE); + } + serial->putChar('\n'); + return 0; + } + else if( strcmp(inBuffer, "probe") == 0 ) + { + for(uint16_t j = 0; j < 255; j++) + { + snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRYING ADDR: %x\n", j); + serial->write(buffer, strlen(buffer)); + cli(); + for(uint8_t k = 0; k < 10; k++) + { + Train::sendRawAddr(j, 60); + _delay_ms(20); + } + for(uint8_t k = 0; k < 3; k++) + { + Train::sendRawAddr(j, 0); + _delay_ms(20); + } + sei(); + } + return 0; + } + else + { + uint8_t id = strtol(inBuffer, nullptr, 10); + if(id < storedTrains ) + { + if(powerIsOn == false) + { + powerIsOn = true; + Train::setOutput(Train::LOW); + _delay_ms(100); + timer0InterruptEnable(true); + } + char* token = strtok(NULL, " "); + if( token != NULL && (strcmp(token, "speed") == 0 || strcmp(token, "s") == 0) ) + { + token = strtok(NULL, " "); + trains[id].setSpeed(atoi(token)); + serial->write_p(PSTR("Set Train speed\n")); + return 0; + } + else if(token != NULL && strcmp(token, "function") == 0 ) + { + token = strtok(NULL, " "); + char* boolToken = strtok(NULL, " "); + if(token != NULL && boolToken != NULL) + { + uint8_t functionId = atoi(token); + bool on = (strcmp(boolToken, "on") == 0); + trains[id].sendFunction(functionId, on ); + serial->write_p(PSTR("Set Train function ")); + serial->write(functionId); + serial->write(on ? " on\n" : " off\n"); + return 0; + } + } + else if(token != NULL && strcmp(token, "probe") == 0 ) + { + for(uint16_t j = 0; j < 1024; j++) + { + trains[id].sendRaw(j); + snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRYING: %x\n", j); + serial->write(buffer, strlen(buffer)); + sei(); + _delay_ms(250); + cli(); + } + sei(); + return 0; + } + else if(token != NULL && strcmp(token, "raw") == 0 ) + { + token = strtok(NULL, " "); + if(token != NULL) + { + cli(); + uint16_t i = strtol(token, nullptr, 16 ); + snprintf(buffer, SNPRINTF_BUFFER_SIZE, "SENDING: %x to %x\n", i, trains[id].getAddress()); + serial->write(buffer, strlen(buffer)); + for(uint8_t j = 0; j < 100; j++) + { + trains[id].sendRaw(i); + _delay_ms(20); + } + serial->write_p(PSTR("Finished\n")); + sei(); + return 0; + } + } + else if( token != NULL && (strcmp(token, "reverse") == 0 || strcmp(token, "r") == 0) ) + { + trains[id].reverse(); + serial->write_p(PSTR("Reversed Train\n")); + return 0; + } + else if( token != NULL && (strcmp(token, "stop") == 0 || strcmp(token, "p") == 0)) + { + trains[id].stop(); + return 0; + } + else + { + serial->write_p(PSTR("Not a valid command\n")); + return -1; + } + } + else + { + serial->write_p(PSTR("Id out of range.\n")); + return -2; + } + } + return -3; } -void powerDispatch(char* token, Serial* serial) +int powerDispatch(char* token, Serial* serial) { - if(strcmp(token, "off") == 0) - { - timer0InterruptEnable(false); - 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); - timer0InterruptEnable(true); - } - 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")); - } - } + if(strcmp(token, "off") == 0) + { + timer0InterruptEnable(false); + Train::setOutput(Train::OFF); + powerIsOn = false; + return 0; + } + else if( strcmp(token, "on") == 0) + { + for(uint16_t i = 0; i < storedTrains; i++) + { + trains[i].setSpeed(0); + } + Train::setOutput(Train::LOW); + timer0InterruptEnable(true); + return 0; + } + 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")); + } + return 0; + } + return -1; } void serialDispatch(Serial* serial) { - if(serial->dataIsWaiting()) - { - char buffer[COMMAND_BUFFER_SIZE]; - unsigned int length = serial->getString(buffer, COMMAND_BUFFER_SIZE); - if(length > 0) - { - 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 || strcmp(token, "t") == 0 )) - { - token = strtok(NULL, " "); - if(token != NULL) - trainDispatch(token, serial); - } - else if(strncmp(token, "erase", 4) == 0) - { - for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0); - serial->write_p(PSTR("EEPROM erased\n")); - storedTrains = 0; - } - else if(strcmp(token, "dump") == 0) - { - for(uint16_t i = 0; i < EPPROM_SIZE; i++) - { - if(i != 0) serial->putChar(','); - serial->write((uint16_t)EEPROM_read_char(i)); - } - serial->putChar('\n'); - } - else if((strcmp(token, "stop") == 0 || strcmp(token, "s") == 0 )) - { - for(uint16_t i = 0; i < storedTrains; i++) - { - cli(); - trains[i].stop(); - sei(); - } - } - else if(strcmp(token, "power") == 0) - { - token = strtok(NULL, " "); - if(token != NULL)powerDispatch(token, serial); - } - else if(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")); - } - } - } + if(serial->dataIsWaiting()) + { + char buffer[COMMAND_BUFFER_SIZE]; + unsigned int length = serial->getString(buffer, COMMAND_BUFFER_SIZE); + if(length > 0) + { + int ret = -1; + char* token = strtok(buffer, " "); + if(length > 4 && (strcmp(token, "train") == 0 || strcmp(token, "t") == 0 )) + { + token = strtok(NULL, " "); + if(token != NULL) + ret = trainDispatch(token, serial); + } + else if(strncmp(token, "erase", 4) == 0) + { + for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0); + serial->write_p(PSTR("EEPROM erased\n")); + storedTrains = 0; + ret = 0; + } + else if(strcmp(token, "dump") == 0) + { + for(uint16_t i = 0; i < EPPROM_SIZE; i++) + { + if(i != 0) serial->putChar(','); + serial->write((uint16_t)EEPROM_read_char(i)); + } + serial->putChar('\n'); + ret = 0; + } + else if((strcmp(token, "stop") == 0 || strcmp(token, "s") == 0 )) + { + for(uint16_t i = 0; i < storedTrains; i++) + { + cli(); + trains[i].stop(); + sei(); + } + ret = 0; + } + else if(strcmp(token, "power") == 0) + { + token = strtok(NULL, " "); + if(token != NULL) + ret = powerDispatch(token, serial); + } + else if(strcmp(token, "help") == 0) + { + printHelp(serial); + ret = 0; + } + else + { + serial->putChar('\"'); + serial->write(buffer, length); + serial->putChar('\"'); + serial->write_p(PSTR(" is not a valid command\n")); + ret = -1; + } + + if(ret < 0) + { + serial->write_p(PSTR("Command Failed\n")); + } + else + { + serial->write_p(PSTR("Sucess \"")); + serial->write(buffer, length); + serial->write("\"\n"); + } + } + } } int main() { - TCNT0 = 0; - TCCR0B = (1< 0) - { - timer0InterruptEnable(false); - trains[trainToResend].resendData(); - trainToResend++; - if(storedTrains <= trainToResend) trainToResend = 0; - resendEvent = false; - timer0InterruptEnable(true); - } - - if(autoff) - { - bool trainsRunning = false; - for(uint16_t i = 0; i < storedTrains; i++) trainsRunning = trainsRunning || trains[i].isActive(); - if(!trainsRunning) - { - powerIsOn = false; - timer0InterruptEnable(false); - Train::setOutput(Train::OFF); - } - } - serialDispatch(&serial); - } - return 0; + DDRD = (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5); + + restore_state(); + + if(autoff) + { + timer0InterruptEnable(false); + Train::setOutput(Train::OFF); + } + else + { + timer0InterruptEnable(true); + Train::setOutput(Train::LOW); + } + + sei(); + + Serial serial; + + serial.write_p(PSTR("TrainController v0.5 starting\n")); + + uint8_t trainToResend = 0; + + while(true) + { + if(resendEvent && storedTrains > 0) + { + timer0InterruptEnable(false); + _delay_us(255); + trains[trainToResend].resendData(); + trainToResend++; + if(storedTrains <= trainToResend) + trainToResend = 0; + resendEvent = false; + timer0InterruptEnable(true); + } + + if(autoff) + { + bool trainsRunning = false; + for(uint16_t i = 0; i < storedTrains; i++) + trainsRunning = trainsRunning || trains[i].isActive(); + if(!trainsRunning) + { + powerIsOn = false; + timer0InterruptEnable(false); + Train::setOutput(Train::OFF); + } + } + serialDispatch(&serial); + } + return 0; } diff --git a/serial.h b/serial.h index 3610289..af85802 100644 --- a/serial.h +++ b/serial.h @@ -2,7 +2,7 @@ #define SERIAL_H #define BAUD 38400 -#define SERIAL_BUFFER_SIZE 256 +#define SERIAL_BUFFER_SIZE 512 #include #include diff --git a/train.cpp b/train.cpp index 0bec4e1..3c6db5a 100644 --- a/train.cpp +++ b/train.cpp @@ -1,8 +1,9 @@ #include "train.h" +#include static volatile unsigned char *_port = &PORTD; -Train::Train(const uint8_t address, uint8_t protocol): _address(address), _protocol(protocol) +Train::Train(const uint8_t address, uint8_t functionmask): _address(address), _functionmask(functionmask) { } @@ -23,16 +24,11 @@ uint8_t Train::getAddress() void Train::stop() { - lastDataPacket = 0; + _speed = 0; + _function = 0; resendData(); } -bool Train::isActive() -{ - return lastDataPacket & 0b0000000111111111; -} - - void Train::off() { writePin(_port, _pinHighA, false); @@ -81,19 +77,20 @@ void Train::sendBit(const bool bit) } } -void Train::sendAddress() +void Train::sendAddress(uint8_t address) { for(uint8_t i = 0; i < 8; i++) { - sendBit(_address & (1 << i)); + sendBit(address & (1 << i)); } } -void Train::sendRaw(const uint16_t data) + +void Train::sendRawAddr(const uint16_t address, const uint16_t data) { for(uint8_t j = 0; j < SEND_COUNT; j++) { - sendAddress(); + sendAddress(address); for(uint8_t i = 0; i < 10; i++) { sendBit(data & (1 << i)); @@ -102,97 +99,130 @@ void Train::sendRaw(const uint16_t data) } } -void Train::setSpeed(uint8_t speed) +void Train::sendRaw(const uint16_t data) { - if(speed != 0)speed = speed + 1; - else if(speed > 15) speed = 15; + sendRawAddr(_address, data); +} + +uint16_t Train::packetAddSpeed() +{ + uint16_t packet = 0; + if(_speed > 14) + _speed = 14; for(uint8_t i = 0; i < 4; i++) { - lastDataPacket = (lastDataPacket & ~(1 << (i+1)*2)) | (((uint16_t)speed & (1 << i)) << (i+1)*2-i); - if(_protocol == M_DELTA) lastDataPacket = (lastDataPacket & ~(1 << ((i+1)*2+1))) | (((uint16_t)speed & (1 << i)) << ((i+1)*2+1-i)); + packet |= ((bool)((_speed+1) & (1 << i))) << (i*2+2); } + return packet; +} + +uint16_t Train::packetAddDirection() +{ + uint16_t packet = 0; + + uint8_t data = 0; + if(!_direction) + { + if(_speed > 6) + data = 0b0100; + else if(_speed > 0) + data = 0b0101; + } + else + { + if(_speed > 0) + data = 0b1011; + else if (_speed > 6) + data = 0b1010; + } + + if(_speed == 0) + data = !_direction ? 0b0101 : 0b1011; + + for(uint8_t i = 0; i < 4; i++) + { + uint8_t bit = (data & (1 << (3-i))) >> (3-i); + packet |= bit << ((i*2)+3); + } + return packet; +} + +uint16_t Train::packetAddFunction(const uint8_t function) +{ + uint16_t packet = 0; + bool enabled = _function & (1 << function); + if(function == 0) + { + packet |= enabled ? 0b00000011 : 0b00000000; + } + else + { + if(enabled) + packet |= 0b1000000000; + for(uint8_t i = 0; i < 4; ++i ) + { + if(function > i) + packet = packet | (1 << (7-i*2)); + else + packet = packet & ~(1 << (7-i*2)); + } + } + return packet; +} + +void Train::setSpeed(uint8_t speed) +{ + _speed = speed; resendData(); } uint8_t Train::getSpeed() { - uint8_t speed = 0; - for(uint8_t i = 0; i < 4; i++) - speed |= ((bool)(lastDataPacket & (1 << (i+1)*2))) << i; - return speed; + return _speed; +} + +uint16_t Train::assemblePacket() +{ + uint16_t packet = packetAddSpeed() | packetAddFunction(0) | packetAddDirection(); + return packet; } void Train::resendData() { - sendRaw(lastDataPacket); - if(functionTimer > 0) + sendRaw(assemblePacket()); + for(uint8_t i = 1; i < 4; ++i) { - --functionTimer; - } - else if(functionTimer == 0) - { - functionClear(); - --functionTimer; + if(_functionmask & (1 << i)) + sendRaw(packetAddSpeed() | packetAddFunction(i) | packetAddFunction(0)); } } uint16_t Train::getLastPacket() { - return lastDataPacket; + return assemblePacket(); } void Train::reverse() { - functionClear(); + _direction = !_direction; resendData(); - resendData(); - if(getSpeed() > 0) - { - setSpeed(0); - resendData(); - resendData(); - _delay_ms(2000); - } - sendRaw(0b000001100); - sendRaw(0b000001100); } -void Train::functionClear() + +uint8_t Train::getFunctions() { - lastDataPacket = lastDataPacket & ~(0b10101010); + return _function; +} + +uint8_t Train::getFunctionMask() +{ + return _functionmask; } void Train::sendFunction(const uint8_t function, bool enable) { - if(function == 0) - { - lastDataPacket = (lastDataPacket & ~0b00000001) | (enable ? 0b00000001 : 0b00000000); - //lastDataPacket = (lastDataPacket & ~0b1100000000) | (enable ? 0b1100000000 : 0); - } - else if(_protocol == M_DIGITAL && function <= 3) - { - if(enable) - lastDataPacket |= 0b1000000000; - else - lastDataPacket &= ~0b1000000000; - for(uint8_t i = 0; i < 4; ++i ) - { - if(function > i) - lastDataPacket = lastDataPacket | (1 << (7-i*2)); - else - lastDataPacket = lastDataPacket & ~(1 << (7-i*2)); - } - } + if(function > 3) + return; + _function = (_function & ~(1 << function)) | (enable << function); resendData(); - functionTimer = 10; -} - -void Train::setProtocol(const uint8_t protocol) -{ - _protocol = protocol; -} - -uint8_t Train::getProtocol() -{ - return _protocol; } diff --git a/train.h b/train.h index 50b463c..bf8e4f2 100644 --- a/train.h +++ b/train.h @@ -8,61 +8,62 @@ class Train { public: - static const uint8_t M_DELTA = 0; - static const uint8_t M_DIGITAL = 1; - static const uint8_t HIGH = 2; - static const uint8_t LOW = 1; - static const uint8_t OFF = 0; + static constexpr uint8_t HIGH = 2; + static constexpr uint8_t LOW = 1; + static constexpr uint8_t OFF = 0; private: + + static constexpr unsigned char _pinHighA = PD5; + static constexpr unsigned char _pinLowA = PD4; + static constexpr unsigned char _pinHighB = PD2; + static constexpr unsigned char _pinLowB = PD3; + uint8_t _address; uint8_t _function = 0; + uint8_t _functionmask; uint8_t _speed = 0; - - static const unsigned char _pinHighA = PD5; - static const unsigned char _pinLowA = PD4; - static const unsigned char _pinHighB = PD2; - static const unsigned char _pinLowB = PD3; + bool _direction = false; static const uint8_t SEND_COUNT = 2; - - uint8_t _protocol = M_DIGITAL; - - uint16_t lastDataPacket = 0; - int8_t functionTimer = -1; inline static void off(); - void sendBit(const bool bit); - void sendAddress(); - void functionClear(); + static void sendBit(const bool bit); + static void sendAddress(uint8_t address); + uint16_t packetAddSpeed(); + uint16_t packetAddDirection(); + uint16_t packetAddFunction(const uint8_t function); + uint16_t assemblePacket(); public: static void setOutput(const uint8_t state); - Train(const uint8_t address, uint8_t protocol = M_DIGITAL); + Train(const uint8_t address, uint8_t functionmask = 0b1111); Train(); - + void resendData(); void reverse(); void stop(); - bool isActive(); + bool isActive() {return _speed || _function;} uint8_t getAddress(); uint16_t getLastPacket(); - uint8_t getProtocol(); - void setSpeed(uint8_t speed); uint8_t getSpeed(); - void setProtocol(const uint8_t protocol); + void setFunctionMask(uint8_t functionmask) {_functionmask = functionmask;} + + uint8_t getFunctions(); + + uint8_t getFunctionMask(); void setAddress(const uint8_t address); @@ -70,4 +71,6 @@ public: void sendRaw(const uint16_t data); + static void sendRawAddr(const uint16_t address, const uint16_t data); + }; diff --git a/trains b/trains index 1690d55..1f9dd29 100644 --- a/trains +++ b/trains @@ -1,4 +1,4 @@ -NUMBER: 0 ID: 01010100 CURRENT SPD: 0 -NUMBER: 1 ID: 01010000 CURRENT SPD: 0 -NUMBER: 2 ID: 01000100 CURRENT SPD: 0 -NUMBER: 3 ID: 00010100 CURRENT SPD: 0 +NUMBER: 0 ID: 01010100 CURRENT PACKET: 220 SPEED: 0 PROTOCOL: digital +NUMBER: 1 ID: 01010000 CURRENT PACKET: 220 SPEED: 0 PROTOCOL: digital +NUMBER: 2 ID: 01000100 CURRENT PACKET: 237 SPEED: 3 PROTOCOL: digital +NUMBER: 3 ID: 00010100 CURRENT PACKET: 220 SPEED: 0 PROTOCOL: digital