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(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)

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 "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<Train, 16> 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)
{

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 <stdlib.h>
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()

41
train.h
View File

@ -1,47 +1,23 @@
#pragma once
#include "writepin.h"
#include <util/delay.h>
#include <stdint.h>
#include <avr/io.h>
#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 _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);
};