diff --git a/CMakeLists.txt b/CMakeLists.txt index 3f6eea0..38c98b7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,9 +17,7 @@ set(PORT_SPEED "57600" CACHE STRING "Serial Port Speed") set(PROGRAMMER "stk500v1" CACHE STRING "Programmer Type") set(COMPILE_FLAGS "" CACHE STRING "Additional Compiler Flags") -# Set own source files -# Simply list all your C / C++ source (not header!) files here -set(SRC_FILES main.cpp serial.cpp train.cpp) +set(SRC_FILES main.cpp serial.cpp train.cpp item.cpp) # Compiler suite specification set(CMAKE_C_COMPILER /usr/bin/avr-gcc) diff --git a/item.cpp b/item.cpp new file mode 100644 index 0000000..9dea2c0 --- /dev/null +++ b/item.cpp @@ -0,0 +1,93 @@ +#include "item.h" +#include + +static volatile unsigned char *_port = &PORTD; + +Item::Item(const uint8_t address): _address(address) +{ +} + +void Item::setAddress(const uint8_t address) +{ + _address = address; +} + +uint8_t Item::getAddress() +{ + return _address; +} + +void Item::off() +{ + writePin(_port, _pinHighA, false); + writePin(_port, _pinHighB, false); + writePin(_port, _pinLowA, true); + writePin(_port, _pinLowB, true); +} + +void Item::setOutput(const uint8_t state) +{ + if(state == HIGH) + { + off(); + _delay_us(3); + writePin(_port, _pinHighA, true); + writePin(_port, _pinLowB, false); + } + else if (state == LOW) + { + off(); + _delay_us(3); + writePin(_port, _pinHighB, true); + writePin(_port, _pinLowA, false); + } + else + { + off(); + } +} + +void Item::sendBit(const bool bit) +{ + if(bit) + { + setOutput(HIGH); + _delay_us(170); + setOutput(LOW); + _delay_us(25); + } + else + { + setOutput(HIGH); + _delay_us(20); + setOutput(LOW); + _delay_us(175); + } +} + +void Item::sendAddress(uint8_t address) +{ + for(uint8_t i = 0; i < 8; i++) + { + sendBit(address & (1 << i)); + } +} + + +void Item::sendRawAddr(const uint16_t address, const uint16_t data) +{ + for(uint8_t j = 0; j < SEND_COUNT; j++) + { + sendAddress(address); + for(uint8_t i = 0; i < 10; i++) + { + sendBit(data & (1 << i)); + } + _delay_ms(1); + } +} + +void Item::sendRaw(const uint16_t data) +{ + sendRawAddr(_address, data); +} diff --git a/item.h b/item.h new file mode 100644 index 0000000..400d2b2 --- /dev/null +++ b/item.h @@ -0,0 +1,46 @@ +#include "writepin.h" +#include +#include +#include + +class Item +{ +public: + + 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; + static constexpr uint8_t SEND_COUNT = 2; + + uint8_t _address; + +protected: + + inline static void off(); + 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); + + Item(const uint8_t address); + + void sendRaw(const uint16_t data); + static void sendRawAddr(const uint16_t address, const uint16_t data); + + void setAddress(const uint8_t address); + uint8_t getAddress(); + +}; diff --git a/main.cpp b/main.cpp index e130cef..f1a2a6f 100644 --- a/main.cpp +++ b/main.cpp @@ -9,16 +9,15 @@ #include "eeprom.h" #include "bitrep.h" #include "ringbuffer.h" +#include "staticvector.h" -#define MAX_TRAINS 16 #define COMMAND_BUFFER_SIZE 64 #define SNPRINTF_BUFFER_SIZE 128 #define EPPROM_SIZE 1024 char buffer[SNPRINTF_BUFFER_SIZE]; -uint16_t storedTrains = 0; -Train trains[MAX_TRAINS]; +SVector trains; bool autoff = true; bool powerIsOn = true; @@ -54,9 +53,9 @@ void timer0InterruptEnable(const bool enable) void save_state() { cli(); - EEPROM_write_char( 0, storedTrains ); + EEPROM_write_char( 0, trains.count() ); EEPROM_write_char( 1, autoff ); - for(uint16_t i = 0; i < storedTrains; i++) + for(uint16_t i = 0; i < trains.count(); i++) { EEPROM_write_char( i*2+32, trains[i].getAddress()); EEPROM_write_char( i*2+32+1, trains[i].getFunctionMask()); @@ -66,17 +65,19 @@ void save_state() void restore_state() { - storedTrains = EEPROM_read_char(0); + uint8_t trainCount = EEPROM_read_char(0); autoff = EEPROM_read_char(1); - if(storedTrains > MAX_TRAINS ) + + trains.clear(); + if(trainCount > trains.maxSize() ) { - for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0); - storedTrains = 0; + for(uint16_t i = 0; i < EPPROM_SIZE; i++) + EEPROM_write_char(i, 0); } - else for(uint8_t i = 0; i < storedTrains; i++) + else { - trains[i].setAddress(EEPROM_read_char(32+i*2)); - trains[i].setFunctionMask(EEPROM_read_char(32+1+i*2)); + for(uint8_t i = 0; i < trainCount; i++) + trains.push_back(Train(EEPROM_read_char(32+i*2), EEPROM_read_char(32+1+i*2))); } } @@ -108,42 +109,32 @@ int trainDispatch(char* inBuffer, Serial* serial) uint8_t address = 0; if(token != NULL) address = strtol(token, nullptr, 10); - if(address != 0 && storedTrains < MAX_TRAINS) + if(address != 0 && trains.remainingCapacity() > 0) { - trains[storedTrains].setAddress(address); - + uint8_t functionMask = 0; + token = strtok(NULL, " "); if(token != NULL) - trains[storedTrains].setFunctionMask(strtol(token, nullptr, 2 )); - + functionMask = strtol(token, nullptr, 2); + + trains.push_back(Train(address, functionMask)); + uint8_t size = snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRAIN saved! NUMBER: %u ADDRESS: %u FUNCTIONS: %s FUNCTIONMASK: %s\n", - storedTrains, + trains.count(), address, - bit_rep[trains[storedTrains].getFunctions() & 0x0F], - bit_rep[trains[storedTrains].getFunctionMask() & 0x0F]); + bit_rep[trains.back().getFunctions() & 0x0F], + bit_rep[trains.back().getFunctionMask() & 0x0F]); 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++) + for(uint8_t i = 0; i < trains.count(); i++) { snprintf(buffer, SNPRINTF_BUFFER_SIZE, "NUMBER: %u ID: %u CURRENT PACKET: %x SPEED: %i FUNCTIONS: %s FUNCTIONMASK: %s\n", i, trains[i].getAddress(), @@ -178,7 +169,7 @@ int trainDispatch(char* inBuffer, Serial* serial) else { uint8_t id = strtol(inBuffer, nullptr, 10); - if(id < storedTrains ) + if(id < trains.count() ) { if(powerIsOn == false) { @@ -233,7 +224,7 @@ int trainDispatch(char* inBuffer, Serial* serial) 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++) + for(uint8_t j = 0; j < 100; j++) { trains[id].sendRaw(i); _delay_ms(20); @@ -254,6 +245,13 @@ int trainDispatch(char* inBuffer, Serial* serial) trains[id].stop(); return 0; } + else if( strcmp(inBuffer, "delete") == 0) + { + trains.erase(id); + serial->write_p(PSTR("Train: ")); + serial->write(id); + serial->write_p(PSTR(" deleted\n")); + } else { serial->write_p(PSTR("Not a valid command\n")); @@ -280,7 +278,7 @@ int powerDispatch(char* token, Serial* serial) } else if( strcmp(token, "on") == 0) { - for(uint16_t i = 0; i < storedTrains; i++) + for(uint16_t i = 0; i < trains.count(); i++) { trains[i].setSpeed(0); } @@ -334,7 +332,7 @@ void serialDispatch(Serial* serial) { for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0); serial->write_p(PSTR("EEPROM erased\n")); - storedTrains = 0; + trains.clear(); ret = 0; } else if(strcmp(token, "dump") == 0) @@ -349,7 +347,7 @@ void serialDispatch(Serial* serial) } else if((strcmp(token, "stop") == 0 || strcmp(token, "s") == 0 )) { - for(uint16_t i = 0; i < storedTrains; i++) + for(uint16_t i = 0; i < trains.count(); i++) { cli(); trains[i].stop(); @@ -426,13 +424,12 @@ int main() while(true) { - if(resendEvent && storedTrains > 0) + if(resendEvent && trains.count() > 0) { - //_delay_ms(100); timer0InterruptEnable(false); trains[trainToResend].sendData(); trainToResend++; - if(storedTrains <= trainToResend) + if(trains.count() <= trainToResend) trainToResend = 0; resendEvent = false; timer0InterruptEnable(true); @@ -441,7 +438,7 @@ int main() if(autoff) { bool trainsRunning = false; - for(uint16_t i = 0; i < storedTrains; i++) + for(uint16_t i = 0; i < trains.count(); i++) trainsRunning = trainsRunning || trains[i].isActive(); if(!trainsRunning) { diff --git a/staticvector.h b/staticvector.h new file mode 100644 index 0000000..2747528 --- /dev/null +++ b/staticvector.h @@ -0,0 +1,88 @@ +#pragma once +#include + +template class SVector +{ +private: + size_t stored = 0; + + + char buff[sizeof(T)*size]; + T *array = (T*)buff; + +public: + + T* data() + { + return array; + } + + T& operator[](size_t i) + { + return array[i]; + } + + T& at(size_t i) + { + return array[i]; + } + + T& front() + { + return array[0]; + } + + T& back() + { + return array[stored-1]; + } + + bool empty() const + { + return stored == 0 ? true : false; + } + + size_t count() const + { + return stored; + } + + constexpr size_t maxSize() const + { + return size; + } + + size_t remainingCapacity() const + { + return size - stored; + } + + bool push_back(const T in) + { + if( remainingCapacity() != 0) + { + array[stored] = in; + ++stored; + return true; + } + else return false; + } + + bool erase(size_t position) + { + if(position > stored) + return false; + array[position].~T(); + --stored; + for( size_t i = position; i < stored; i++ ) + memcpy(&array[i], &array[i+1], sizeof(T)); + return true; + } + + void clear() + { + for( size_t i = 0; i < stored; i++ ) + array[i].~T(); + stored = 0; + } +}; diff --git a/train.cpp b/train.cpp index 506b278..fe9b3cf 100644 --- a/train.cpp +++ b/train.cpp @@ -1,109 +1,10 @@ #include "train.h" #include -static volatile unsigned char *_port = &PORTD; - -Train::Train(const uint8_t address, uint8_t functionmask): _address(address), _functionmask(functionmask) +Train::Train(const uint8_t address, uint8_t functionmask): Item(address), _functionmask(functionmask) { } -Train::Train() -{ - _address = 0; -} - -void Train::setAddress(const uint8_t address) -{ - _address = address; -} - -uint8_t Train::getAddress() -{ - return _address; -} - -void Train::stop() -{ - _speed = 0; - _function = 0; - sendData(); -} - -void Train::off() -{ - writePin(_port, _pinHighA, false); - writePin(_port, _pinHighB, false); - writePin(_port, _pinLowA, true); - writePin(_port, _pinLowB, true); -} - -void Train::setOutput(const uint8_t state) -{ - if(state == HIGH) - { - off(); - _delay_us(3); - writePin(_port, _pinHighA, true); - writePin(_port, _pinLowB, false); - } - else if (state == LOW) - { - off(); - _delay_us(3); - writePin(_port, _pinHighB, true); - writePin(_port, _pinLowA, false); - } - else - { - off(); - } -} - -void Train::sendBit(const bool bit) -{ - if(bit) - { - setOutput(HIGH); - _delay_us(170); - setOutput(LOW); - _delay_us(25); - } - else - { - setOutput(HIGH); - _delay_us(20); - setOutput(LOW); - _delay_us(175); - } -} - -void Train::sendAddress(uint8_t address) -{ - for(uint8_t i = 0; i < 8; i++) - { - sendBit(address & (1 << i)); - } -} - - -void Train::sendRawAddr(const uint16_t address, const uint16_t data) -{ - for(uint8_t j = 0; j < SEND_COUNT; j++) - { - sendAddress(address); - for(uint8_t i = 0; i < 10; i++) - { - sendBit(data & (1 << i)); - } - _delay_ms(1); - } -} - -void Train::sendRaw(const uint16_t data) -{ - sendRawAddr(_address, data); -} - uint16_t Train::packetAddSpeed() { uint16_t packet = 0; @@ -181,7 +82,15 @@ uint8_t Train::getSpeed() return _speed; } -uint16_t Train::assemblePacket() +void Train::stop() +{ + _speed = 0; + _function = 0; + sendData(); +} + + +uint16_t Train::assembleSpeedPacket() { uint16_t packet = packetAddSpeed() | packetAddFunction(0) | packetAddDirection(); return packet; @@ -189,7 +98,7 @@ uint16_t Train::assemblePacket() void Train::sendData() { - sendRaw(assemblePacket()); + sendRaw(assembleSpeedPacket()); if(_functionmask) { uint8_t functionToResend = (_function & 0xF0) >> 4; @@ -208,7 +117,7 @@ void Train::sendData() uint16_t Train::getLastPacket() { - return assemblePacket(); + return assembleSpeedPacket(); } void Train::reverse() diff --git a/train.h b/train.h index 96876a7..24e536e 100644 --- a/train.h +++ b/train.h @@ -1,47 +1,23 @@ #pragma once -#include "writepin.h" -#include -#include -#include +#include "item.h" -class Train +class Train: public Item { -public: - - 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 _function = 0; uint8_t _functionmask; uint8_t _speed = 0; bool _direction = false; - - static const uint8_t SEND_COUNT = 2; - inline static void off(); - 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(); + uint16_t assembleSpeedPacket(); public: - static void setOutput(const uint8_t state); - - Train(const uint8_t address, uint8_t functionmask = 0b1111); - Train(); + Train(const uint8_t address, uint8_t functionmask = 0b0000); void sendData(); @@ -51,8 +27,6 @@ public: bool isActive() {return getSpeed() || getFunctions();} - uint8_t getAddress(); - uint16_t getLastPacket(); void setSpeed(uint8_t speed); @@ -65,12 +39,5 @@ public: uint8_t getFunctionMask(); - void setAddress(const uint8_t address); - void sendFunction(const uint8_t function, bool enable = true); - - void sendRaw(const uint16_t data); - - static void sendRawAddr(const uint16_t address, const uint16_t data); - };