Split train class into item and train

Use SVector to store trains
This commit is contained in:
2022-01-20 20:25:51 +01:00
parent 86c36f7a21
commit 0b528fbf1e
7 changed files with 285 additions and 187 deletions

View File

@ -17,9 +17,7 @@ set(PORT_SPEED "57600" CACHE STRING "Serial Port Speed")
set(PROGRAMMER "stk500v1" CACHE STRING "Programmer Type") set(PROGRAMMER "stk500v1" CACHE STRING "Programmer Type")
set(COMPILE_FLAGS "" CACHE STRING "Additional Compiler Flags") set(COMPILE_FLAGS "" CACHE STRING "Additional Compiler Flags")
# Set own source files set(SRC_FILES main.cpp serial.cpp train.cpp item.cpp)
# Simply list all your C / C++ source (not header!) files here
set(SRC_FILES main.cpp serial.cpp train.cpp)
# Compiler suite specification # Compiler suite specification
set(CMAKE_C_COMPILER /usr/bin/avr-gcc) set(CMAKE_C_COMPILER /usr/bin/avr-gcc)

93
item.cpp Normal file
View File

@ -0,0 +1,93 @@
#include "item.h"
#include <stdlib.h>
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);
}

46
item.h Normal file
View File

@ -0,0 +1,46 @@
#include "writepin.h"
#include <util/delay.h>
#include <stdint.h>
#include <avr/io.h>
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();
};

View File

@ -9,16 +9,15 @@
#include "eeprom.h" #include "eeprom.h"
#include "bitrep.h" #include "bitrep.h"
#include "ringbuffer.h" #include "ringbuffer.h"
#include "staticvector.h"
#define MAX_TRAINS 16
#define COMMAND_BUFFER_SIZE 64 #define COMMAND_BUFFER_SIZE 64
#define SNPRINTF_BUFFER_SIZE 128 #define SNPRINTF_BUFFER_SIZE 128
#define EPPROM_SIZE 1024 #define EPPROM_SIZE 1024
char buffer[SNPRINTF_BUFFER_SIZE]; char buffer[SNPRINTF_BUFFER_SIZE];
uint16_t storedTrains = 0; SVector<Train, 16> trains;
Train trains[MAX_TRAINS];
bool autoff = true; bool autoff = true;
bool powerIsOn = true; bool powerIsOn = true;
@ -54,9 +53,9 @@ void timer0InterruptEnable(const bool enable)
void save_state() void save_state()
{ {
cli(); cli();
EEPROM_write_char( 0, storedTrains ); EEPROM_write_char( 0, trains.count() );
EEPROM_write_char( 1, autoff ); 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, trains[i].getAddress());
EEPROM_write_char( i*2+32+1, trains[i].getFunctionMask()); EEPROM_write_char( i*2+32+1, trains[i].getFunctionMask());
@ -66,17 +65,19 @@ void save_state()
void restore_state() void restore_state()
{ {
storedTrains = EEPROM_read_char(0); uint8_t trainCount = EEPROM_read_char(0);
autoff = EEPROM_read_char(1); 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); for(uint16_t i = 0; i < EPPROM_SIZE; i++)
storedTrains = 0; EEPROM_write_char(i, 0);
} }
else for(uint8_t i = 0; i < storedTrains; i++) else
{ {
trains[i].setAddress(EEPROM_read_char(32+i*2)); for(uint8_t i = 0; i < trainCount; i++)
trains[i].setFunctionMask(EEPROM_read_char(32+1+i*2)); 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; uint8_t address = 0;
if(token != NULL) if(token != NULL)
address = strtol(token, nullptr, 10); 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, " "); token = strtok(NULL, " ");
if(token != 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", uint8_t size = snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRAIN saved! NUMBER: %u ADDRESS: %u FUNCTIONS: %s FUNCTIONMASK: %s\n",
storedTrains, trains.count(),
address, address,
bit_rep[trains[storedTrains].getFunctions() & 0x0F], bit_rep[trains.back().getFunctions() & 0x0F],
bit_rep[trains[storedTrains].getFunctionMask() & 0x0F]); bit_rep[trains.back().getFunctionMask() & 0x0F]);
serial->write(buffer, size); serial->write(buffer, size);
storedTrains++;
save_state(); save_state();
return 0; return 0;
} }
serial->write_p(PSTR("Usage: train add [address] [functionmask]")); 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 ) else if( strcmp(inBuffer, "list") == 0 )
{ {
serial->write_p(PSTR("Trains:\n")); 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", snprintf(buffer, SNPRINTF_BUFFER_SIZE, "NUMBER: %u ID: %u CURRENT PACKET: %x SPEED: %i FUNCTIONS: %s FUNCTIONMASK: %s\n",
i, trains[i].getAddress(), i, trains[i].getAddress(),
@ -178,7 +169,7 @@ int trainDispatch(char* inBuffer, Serial* serial)
else else
{ {
uint8_t id = strtol(inBuffer, nullptr, 10); uint8_t id = strtol(inBuffer, nullptr, 10);
if(id < storedTrains ) if(id < trains.count() )
{ {
if(powerIsOn == false) if(powerIsOn == false)
{ {
@ -233,7 +224,7 @@ int trainDispatch(char* inBuffer, Serial* serial)
uint16_t i = strtol(token, nullptr, 16 ); uint16_t i = strtol(token, nullptr, 16 );
snprintf(buffer, SNPRINTF_BUFFER_SIZE, "SENDING: %x to %x\n", i, trains[id].getAddress()); snprintf(buffer, SNPRINTF_BUFFER_SIZE, "SENDING: %x to %x\n", i, trains[id].getAddress());
serial->write(buffer, strlen(buffer)); 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); trains[id].sendRaw(i);
_delay_ms(20); _delay_ms(20);
@ -254,6 +245,13 @@ int trainDispatch(char* inBuffer, Serial* serial)
trains[id].stop(); trains[id].stop();
return 0; 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 else
{ {
serial->write_p(PSTR("Not a valid command\n")); 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) 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); 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); for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0);
serial->write_p(PSTR("EEPROM erased\n")); serial->write_p(PSTR("EEPROM erased\n"));
storedTrains = 0; trains.clear();
ret = 0; ret = 0;
} }
else if(strcmp(token, "dump") == 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 )) 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(); cli();
trains[i].stop(); trains[i].stop();
@ -426,13 +424,12 @@ int main()
while(true) while(true)
{ {
if(resendEvent && storedTrains > 0) if(resendEvent && trains.count() > 0)
{ {
//_delay_ms(100);
timer0InterruptEnable(false); timer0InterruptEnable(false);
trains[trainToResend].sendData(); trains[trainToResend].sendData();
trainToResend++; trainToResend++;
if(storedTrains <= trainToResend) if(trains.count() <= trainToResend)
trainToResend = 0; trainToResend = 0;
resendEvent = false; resendEvent = false;
timer0InterruptEnable(true); timer0InterruptEnable(true);
@ -441,7 +438,7 @@ int main()
if(autoff) if(autoff)
{ {
bool trainsRunning = false; 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(); trainsRunning = trainsRunning || trains[i].isActive();
if(!trainsRunning) if(!trainsRunning)
{ {

88
staticvector.h Normal file
View File

@ -0,0 +1,88 @@
#pragma once
#include <stdint.h>
template<typename T, size_t size> 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;
}
};

115
train.cpp
View File

@ -1,109 +1,10 @@
#include "train.h" #include "train.h"
#include <stdlib.h> #include <stdlib.h>
static volatile unsigned char *_port = &PORTD; Train::Train(const uint8_t address, uint8_t functionmask): Item(address), _functionmask(functionmask)
Train::Train(const uint8_t address, uint8_t functionmask): _address(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 Train::packetAddSpeed()
{ {
uint16_t packet = 0; uint16_t packet = 0;
@ -181,7 +82,15 @@ uint8_t Train::getSpeed()
return _speed; 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(); uint16_t packet = packetAddSpeed() | packetAddFunction(0) | packetAddDirection();
return packet; return packet;
@ -189,7 +98,7 @@ uint16_t Train::assemblePacket()
void Train::sendData() void Train::sendData()
{ {
sendRaw(assemblePacket()); sendRaw(assembleSpeedPacket());
if(_functionmask) if(_functionmask)
{ {
uint8_t functionToResend = (_function & 0xF0) >> 4; uint8_t functionToResend = (_function & 0xF0) >> 4;
@ -208,7 +117,7 @@ void Train::sendData()
uint16_t Train::getLastPacket() uint16_t Train::getLastPacket()
{ {
return assemblePacket(); return assembleSpeedPacket();
} }
void Train::reverse() void Train::reverse()

43
train.h
View File

@ -1,47 +1,23 @@
#pragma once #pragma once
#include "writepin.h" #include "item.h"
#include <util/delay.h>
#include <stdint.h>
#include <avr/io.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: private:
uint8_t _function = 0;
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 _functionmask;
uint8_t _speed = 0; uint8_t _speed = 0;
bool _direction = false; 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 packetAddSpeed();
uint16_t packetAddDirection(); uint16_t packetAddDirection();
uint16_t packetAddFunction(const uint8_t function); uint16_t packetAddFunction(const uint8_t function);
uint16_t assemblePacket(); uint16_t assembleSpeedPacket();
public: public:
static void setOutput(const uint8_t state); Train(const uint8_t address, uint8_t functionmask = 0b0000);
Train(const uint8_t address, uint8_t functionmask = 0b1111);
Train();
void sendData(); void sendData();
@ -51,8 +27,6 @@ public:
bool isActive() {return getSpeed() || getFunctions();} bool isActive() {return getSpeed() || getFunctions();}
uint8_t getAddress();
uint16_t getLastPacket(); uint16_t getLastPacket();
void setSpeed(uint8_t speed); void setSpeed(uint8_t speed);
@ -65,12 +39,5 @@ public:
uint8_t getFunctionMask(); uint8_t getFunctionMask();
void setAddress(const uint8_t address);
void sendFunction(const uint8_t function, bool enable = true); 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);
}; };