add support for signals
split main into more files
This commit is contained in:
@ -17,7 +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(SRC_FILES main.cpp serial.cpp train.cpp item.cpp turnout.cpp)
|
set(SRC_FILES main.cpp serial.cpp train.cpp item.cpp turnout.cpp signal.cpp)
|
||||||
|
|
||||||
# Compiler suite specification
|
# Compiler suite specification
|
||||||
set(CMAKE_C_COMPILER /usr/bin/avr-gcc)
|
set(CMAKE_C_COMPILER /usr/bin/avr-gcc)
|
||||||
|
391
main.cpp
391
main.cpp
@ -11,6 +11,7 @@
|
|||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
#include "staticvector.h"
|
#include "staticvector.h"
|
||||||
#include "turnout.h"
|
#include "turnout.h"
|
||||||
|
#include "signal.h"
|
||||||
|
|
||||||
#define COMMAND_BUFFER_SIZE 64
|
#define COMMAND_BUFFER_SIZE 64
|
||||||
#define SNPRINTF_BUFFER_SIZE 128
|
#define SNPRINTF_BUFFER_SIZE 128
|
||||||
@ -18,8 +19,12 @@
|
|||||||
|
|
||||||
char buffer[SNPRINTF_BUFFER_SIZE];
|
char buffer[SNPRINTF_BUFFER_SIZE];
|
||||||
|
|
||||||
SVector<Train, 16> trains;
|
static constexpr uint8_t EEPROM_RESERVE = 32;
|
||||||
|
static constexpr uint8_t BLOCK = 4;
|
||||||
|
|
||||||
|
SVector<Train, 32> trains;
|
||||||
SVector<Turnout, 32> turnouts;
|
SVector<Turnout, 32> turnouts;
|
||||||
|
SVector<Signal, 32> signals;
|
||||||
|
|
||||||
bool autoff = true;
|
bool autoff = true;
|
||||||
bool powerIsOn = true;
|
bool powerIsOn = true;
|
||||||
@ -31,6 +36,13 @@ volatile bool resendEvent = false;
|
|||||||
|
|
||||||
constexpr bool USE_PULSES = false;
|
constexpr bool USE_PULSES = false;
|
||||||
|
|
||||||
|
void setPower(bool on);
|
||||||
|
void save_state();
|
||||||
|
|
||||||
|
#include "traindispatch.h"
|
||||||
|
#include "turnoutdispatch.h"
|
||||||
|
#include "signaldispatch.h"
|
||||||
|
|
||||||
ISR(TIMER0_OVF_vect)
|
ISR(TIMER0_OVF_vect)
|
||||||
{
|
{
|
||||||
++tick;
|
++tick;
|
||||||
@ -60,15 +72,30 @@ void save_state()
|
|||||||
EEPROM_write_char( 2, trains.maxSize());
|
EEPROM_write_char( 2, trains.maxSize());
|
||||||
EEPROM_write_char( 3, turnouts.count());
|
EEPROM_write_char( 3, turnouts.count());
|
||||||
EEPROM_write_char( 4, turnouts.maxSize());
|
EEPROM_write_char( 4, turnouts.maxSize());
|
||||||
for(uint16_t i = 0; i < trains.count(); i++)
|
EEPROM_write_char( 5, signals.count());
|
||||||
|
EEPROM_write_char( 6, signals.maxSize());
|
||||||
|
|
||||||
|
const uint16_t trainOffset = EEPROM_RESERVE;
|
||||||
|
for(uint8_t i = 0; i < trains.count(); i++)
|
||||||
{
|
{
|
||||||
EEPROM_write_char( i*2+32, trains[i].getAddress());
|
EEPROM_write_char( i*BLOCK+trainOffset, trains[i].getAddress());
|
||||||
EEPROM_write_char( i*2+32+1, trains[i].getFunctionMask());
|
EEPROM_write_char( i*BLOCK+trainOffset+1, trains[i].getFunctionMask());
|
||||||
|
EEPROM_write_char( i*BLOCK+trainOffset+2, trains[i].getQuirks());
|
||||||
}
|
}
|
||||||
for(uint16_t i = 0; i < turnouts.count(); i++)
|
|
||||||
|
const uint16_t turnoutOffset = trains.maxSize()*BLOCK+EEPROM_RESERVE;
|
||||||
|
for(uint8_t i = 0; i < turnouts.count(); i++)
|
||||||
{
|
{
|
||||||
EEPROM_write_char( i*2+32+trains.maxSize()*2, turnouts[i].getAddress());
|
EEPROM_write_char( i*BLOCK+turnoutOffset, turnouts[i].getAddress());
|
||||||
EEPROM_write_char( i*2+32+1+trains.maxSize()*2, turnouts[i].getSubaddress());
|
EEPROM_write_char( i*BLOCK+turnoutOffset+1, turnouts[i].getSubaddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint16_t signalOffset = trains.maxSize()*BLOCK+turnouts.maxSize()*BLOCK+EEPROM_RESERVE;
|
||||||
|
for(uint8_t i = 0; i < signals.count(); i++)
|
||||||
|
{
|
||||||
|
EEPROM_write_char( i*4+signalOffset, signals[i].getAddress());
|
||||||
|
EEPROM_write_char( i*4+signalOffset+1, signals[i].getSubaddress());
|
||||||
|
EEPROM_write_char( i*4+signalOffset+2, signals[i].getType());
|
||||||
}
|
}
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
@ -77,44 +104,65 @@ void restore_state()
|
|||||||
{
|
{
|
||||||
uint8_t trainCount = EEPROM_read_char(0);
|
uint8_t trainCount = EEPROM_read_char(0);
|
||||||
uint8_t turnoutCount = EEPROM_read_char(3);
|
uint8_t turnoutCount = EEPROM_read_char(3);
|
||||||
|
uint8_t signalCount = EEPROM_read_char(5);
|
||||||
autoff = EEPROM_read_char(1);
|
autoff = EEPROM_read_char(1);
|
||||||
|
|
||||||
trains.clear();
|
trains.clear();
|
||||||
if(trainCount > trains.maxSize() || trains.maxSize() != EEPROM_read_char(2) )
|
turnouts.clear();
|
||||||
|
signals.clear();
|
||||||
|
if(trainCount > trains.maxSize() || trains.maxSize() != EEPROM_read_char(2) ||
|
||||||
|
turnoutCount > turnouts.maxSize() || turnouts.maxSize() != EEPROM_read_char(4) ||
|
||||||
|
signalCount > signals.maxSize() || signals.maxSize() != EEPROM_read_char(6))
|
||||||
{
|
{
|
||||||
for(uint16_t i = 0; i < EPPROM_SIZE; i++)
|
for(uint16_t i = 0; i < EPPROM_SIZE; i++)
|
||||||
EEPROM_write_char(i, 0);
|
EEPROM_write_char(i, 0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
const uint16_t trainOffset = EEPROM_RESERVE;
|
||||||
|
const uint16_t turnoutOffset = trains.maxSize()*BLOCK+EEPROM_RESERVE;
|
||||||
|
const uint16_t signalOffset = trains.maxSize()*BLOCK+turnouts.maxSize()*BLOCK+EEPROM_RESERVE;
|
||||||
|
|
||||||
for(uint8_t i = 0; i < trainCount; i++)
|
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)));
|
trains.push_back(Train(EEPROM_read_char(trainOffset+i*4),
|
||||||
|
EEPROM_read_char(trainOffset+1+i*4),
|
||||||
|
EEPROM_read_char(trainOffset+2+i*4)));
|
||||||
for(uint8_t i = 0; i < turnoutCount; i++)
|
for(uint8_t i = 0; i < turnoutCount; i++)
|
||||||
turnouts.push_back(Turnout(EEPROM_read_char(32+i*2+trains.maxSize()*2), EEPROM_read_char(32+1+i*2+trains.maxSize()*2)));
|
turnouts.push_back(Turnout(EEPROM_read_char(i*4+turnoutOffset),
|
||||||
|
EEPROM_read_char(1+i*4+turnoutOffset)));
|
||||||
|
for(uint8_t i = 0; i < signalCount; i++)
|
||||||
|
signals.push_back(Signal(EEPROM_read_char(i*4+signalOffset),
|
||||||
|
EEPROM_read_char(1+i*4+signalOffset),
|
||||||
|
EEPROM_read_char(2+i*4+signalOffset)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline static void printHelp(Serial* serial)
|
inline static void printHelp(Serial* serial)
|
||||||
{
|
{
|
||||||
serial->write_p(PSTR("Available Commands: \n\
|
serial->write_p(PSTR("Available Commands: \n\
|
||||||
help : Show this prompt.\n\
|
help : Show this prompt.\n\
|
||||||
train add [address] [functionmask] : Add train.\n\
|
train add [address] [functionmask] [quriks] : Add train.\n\
|
||||||
train [nn] delete : Delete last train.\n\
|
train [nn] delete : Delete last train.\n\
|
||||||
train list : Print list of saved trains.\n\
|
train list : Print list of saved trains.\n\
|
||||||
train [nn] s(top) : Stop nth train.\n\
|
train [nn] s(top) : Stop nth train.\n\
|
||||||
train [nn] s(peed) [sp] : Set nth train speed.\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] function [x] : Toggle x'ed fuction on train n.\n\
|
||||||
train [nn] r(everse) : Reverse train n.\n\
|
train [nn] r(everse) : Reverse train n.\n\
|
||||||
turnout add [address] [subaddress] : Add a turnout\n\
|
train [nn] edit [functionmask] [quriks] : Edit train n.\n\
|
||||||
turnout list : List turnouts\n\
|
turnout add [address] [subaddress] : Add a turnout\n\
|
||||||
turnout set [left/right] : Set turnout direction\n\
|
turnout list : List turnouts\n\
|
||||||
turnout delete [nn] : Delete Turnout\n\
|
turnout [nn] set [left/right] : Set turnout direction\n\
|
||||||
stop : stop all trains\n\
|
turnout [nn] delete : Delete Turnout\n\
|
||||||
power off : power off the rail\n\
|
signal add [address] [subaddress] [type] : Add a signal\n\
|
||||||
power on : power on the rail\n\
|
signal list : List signal\n\
|
||||||
power auto : power off the rail when no trains are moveing\n\
|
signal [nn] set [status] : Set signal direction\n\
|
||||||
dump : prints epprom contence\n\
|
signal [nn] delete : Delete signal\n\
|
||||||
erase : Erase epprom.\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 setPower(bool on)
|
void setPower(bool on)
|
||||||
@ -137,282 +185,6 @@ void setPower(bool on)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void printTurnoutState(uint8_t id, Serial* serial)
|
|
||||||
{
|
|
||||||
snprintf(buffer, SNPRINTF_BUFFER_SIZE,
|
|
||||||
"TURNOUT NUMBER: %u ADDRESS: %u SUBADDRESS: %u CURRENT PACKET: %x DIRECTION: %u\n",
|
|
||||||
id, turnouts[id].getAddress(), turnouts[id].getSubaddress(),
|
|
||||||
turnouts[id].getPacket(), turnouts[id].getDirection());
|
|
||||||
serial->write(buffer, SNPRINTF_BUFFER_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int turnoutDispatch(char* inBuffer, Serial* serial)
|
|
||||||
{
|
|
||||||
if( strcmp(inBuffer, "add") == 0 )
|
|
||||||
{
|
|
||||||
char* token = strtok(NULL, " ");
|
|
||||||
uint8_t address = 0;
|
|
||||||
if(token != NULL)
|
|
||||||
address = strtol(token, nullptr, 10);
|
|
||||||
if(address != 0 && turnouts.remainingCapacity() > 0)
|
|
||||||
{
|
|
||||||
uint8_t subaddress = 0;
|
|
||||||
|
|
||||||
token = strtok(NULL, " ");
|
|
||||||
if(token != NULL)
|
|
||||||
subaddress = strtol(token, nullptr, 10);
|
|
||||||
|
|
||||||
turnouts.push_back(Turnout(address, subaddress));
|
|
||||||
serial->write_p(PSTR("TUNROUT saved! "));
|
|
||||||
printTurnoutState(turnouts.count()-1, serial);
|
|
||||||
|
|
||||||
save_state();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
serial->write_p(PSTR("Usage: turnout add [address] [subaddress]"));
|
|
||||||
}
|
|
||||||
else if( strcmp(inBuffer, "list") == 0 )
|
|
||||||
{
|
|
||||||
serial->write_p(PSTR("Turnouts:\n"));
|
|
||||||
for(uint8_t i = 0; i < turnouts.count(); i++)
|
|
||||||
printTurnoutState(i, serial);
|
|
||||||
serial->putChar('\n');
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint8_t id = strtol(inBuffer, nullptr, 10);
|
|
||||||
if(id < turnouts.count() )
|
|
||||||
{
|
|
||||||
setPower(true);
|
|
||||||
char* token = strtok(NULL, " ");
|
|
||||||
if(token != NULL && strcmp(token, "set") == 0 )
|
|
||||||
{
|
|
||||||
char* boolToken = strtok(NULL, " ");
|
|
||||||
if(token != NULL && boolToken != NULL)
|
|
||||||
{
|
|
||||||
bool direction = (strcmp(boolToken, "right") == 0);
|
|
||||||
turnouts[id].setDirection(direction);
|
|
||||||
serial->write_p(PSTR("Set turnout direction "));
|
|
||||||
serial->write(direction ? "right\n" : "left\n");
|
|
||||||
printTurnoutState(id, serial);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(token != NULL && strcmp(token, "raw") == 0 )
|
|
||||||
{
|
|
||||||
token = strtok(NULL, " ");
|
|
||||||
serial->flush();
|
|
||||||
if(token != NULL)
|
|
||||||
{
|
|
||||||
cli();
|
|
||||||
uint16_t i = strtol(token, nullptr, 16 );
|
|
||||||
snprintf(buffer, SNPRINTF_BUFFER_SIZE, "SENDING: %x to %x\n", i, turnouts[id].getAddress());
|
|
||||||
serial->write(buffer, strlen(buffer));
|
|
||||||
while(!serial->dataIsWaiting())
|
|
||||||
{
|
|
||||||
turnouts[id].sendRaw(i);
|
|
||||||
sei();
|
|
||||||
_delay_ms(20);
|
|
||||||
cli();
|
|
||||||
}
|
|
||||||
serial->write_p(PSTR("Finished\n"));
|
|
||||||
serial->flush();
|
|
||||||
sei();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(token != NULL && strcmp(token, "delete") == 0)
|
|
||||||
{
|
|
||||||
turnouts.erase(id);
|
|
||||||
serial->write_p(PSTR("Turnout: "));
|
|
||||||
serial->write(id);
|
|
||||||
serial->write_p(PSTR(" deleted\n"));
|
|
||||||
save_state();
|
|
||||||
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 printTrainState(int id, Serial* serial)
|
|
||||||
{
|
|
||||||
snprintf(buffer, SNPRINTF_BUFFER_SIZE,
|
|
||||||
"TRAIN NUMBER: %u ADDRESS: %u CURRENT PACKET: %x SPEED: %i FUNCTIONS: %s FUNCTIONMASK: %s\n",
|
|
||||||
id, trains[id].getAddress(),
|
|
||||||
trains[id].getLastPacket(), trains[id].getSpeed(),
|
|
||||||
bit_rep[trains[id].getFunctions() & 0x0F], bit_rep[trains[id].getFunctionMask() & 0x0F]);
|
|
||||||
serial->write(buffer, SNPRINTF_BUFFER_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
int trainDispatch(char* inBuffer, Serial* serial)
|
|
||||||
{
|
|
||||||
if( strcmp(inBuffer, "add") == 0 )
|
|
||||||
{
|
|
||||||
char* token = strtok(NULL, " ");
|
|
||||||
uint8_t address = 0;
|
|
||||||
if(token != NULL)
|
|
||||||
address = strtol(token, nullptr, 10);
|
|
||||||
if(address != 0 && trains.remainingCapacity() > 0)
|
|
||||||
{
|
|
||||||
uint8_t functionMask = 0;
|
|
||||||
|
|
||||||
token = strtok(NULL, " ");
|
|
||||||
if(token != NULL)
|
|
||||||
functionMask = strtol(token, nullptr, 2);
|
|
||||||
|
|
||||||
trains.push_back(Train(address, functionMask));
|
|
||||||
|
|
||||||
serial->write_p(PSTR("TRAIN saved! "));
|
|
||||||
printTrainState(trains.count()-1, serial);
|
|
||||||
|
|
||||||
save_state();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
serial->write_p(PSTR("Usage: train add [address] [functionmask]"));
|
|
||||||
}
|
|
||||||
else if( strcmp(inBuffer, "list") == 0 )
|
|
||||||
{
|
|
||||||
serial->write_p(PSTR("Trains:\n"));
|
|
||||||
for(uint8_t i = 0; i < trains.count(); i++)
|
|
||||||
printTrainState(i, serial);
|
|
||||||
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 < trains.count() )
|
|
||||||
{
|
|
||||||
setPower(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"));
|
|
||||||
printTrainState(id, serial);
|
|
||||||
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");
|
|
||||||
printTrainState(id, serial);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(token != NULL && strcmp(token, "probe") == 0 )
|
|
||||||
{
|
|
||||||
serial->flush();
|
|
||||||
for(uint16_t j = 0; j < 1024 && !serial->dataIsWaiting(); 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();
|
|
||||||
serial->flush();
|
|
||||||
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();
|
|
||||||
printTrainState(id, serial);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else if( token != NULL && strcmp(token, "delete") == 0)
|
|
||||||
{
|
|
||||||
trains.erase(id);
|
|
||||||
serial->write_p(PSTR("Train: "));
|
|
||||||
serial->write(id);
|
|
||||||
serial->write_p(PSTR(" deleted\n"));
|
|
||||||
save_state();
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
int powerDispatch(char* token, Serial* serial)
|
int powerDispatch(char* token, Serial* serial)
|
||||||
{
|
{
|
||||||
if(strcmp(token, "off") == 0)
|
if(strcmp(token, "off") == 0)
|
||||||
@ -477,6 +249,12 @@ void serialDispatch(Serial* serial)
|
|||||||
if(token != NULL)
|
if(token != NULL)
|
||||||
ret = turnoutDispatch(token, serial);
|
ret = turnoutDispatch(token, serial);
|
||||||
}
|
}
|
||||||
|
else if(strcmp(token, "signal") == 0)
|
||||||
|
{
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
ret = signalDispatch(token, serial);
|
||||||
|
}
|
||||||
else if(strncmp(token, "erase", 4) == 0)
|
else if(strncmp(token, "erase", 4) == 0)
|
||||||
{
|
{
|
||||||
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);
|
||||||
@ -500,6 +278,7 @@ void serialDispatch(Serial* serial)
|
|||||||
{
|
{
|
||||||
cli();
|
cli();
|
||||||
trains[i].stop();
|
trains[i].stop();
|
||||||
|
printTrainState(i, serial);
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
ret = 0;
|
ret = 0;
|
||||||
@ -580,8 +359,10 @@ int main()
|
|||||||
trains[itemToResend].sendData();
|
trains[itemToResend].sendData();
|
||||||
else if(itemToResend < trains.count() + turnouts.count())
|
else if(itemToResend < trains.count() + turnouts.count())
|
||||||
turnouts[itemToResend-trains.count()].sendData();
|
turnouts[itemToResend-trains.count()].sendData();
|
||||||
|
else if(itemToResend < trains.count() + turnouts.count()+signals.count())
|
||||||
|
signals[itemToResend-trains.count()-turnouts.count()].sendData();
|
||||||
itemToResend++;
|
itemToResend++;
|
||||||
if(trains.count()+turnouts.count() <= itemToResend)
|
if(trains.count()+turnouts.count()+signals.count() <= itemToResend)
|
||||||
itemToResend = 0;
|
itemToResend = 0;
|
||||||
resendEvent = false;
|
resendEvent = false;
|
||||||
timer0InterruptEnable(true);
|
timer0InterruptEnable(true);
|
||||||
|
50
signal.cpp
Normal file
50
signal.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
#include "signal.h"
|
||||||
|
|
||||||
|
Signal::Signal(uint8_t address, uint8_t subaddress, uint8_t type): Item(address), _subaddress(subaddress), _type(type)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Signal::setState(uint8_t state)
|
||||||
|
{
|
||||||
|
_state = state;
|
||||||
|
sendData();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Signal::getState()
|
||||||
|
{
|
||||||
|
return _state;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Signal::getSubaddress()
|
||||||
|
{
|
||||||
|
return _subaddress;
|
||||||
|
}
|
||||||
|
uint16_t Signal::getPacket()
|
||||||
|
{
|
||||||
|
uint16_t data;
|
||||||
|
if(!(_type & 1))
|
||||||
|
{
|
||||||
|
data = _state | _subaddress << 6;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data = 0;
|
||||||
|
data |= ((_state == GO) << 9) | ((_state == GO) << 8);
|
||||||
|
for (uint8_t i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
uint8_t bit = (_subaddress & (1 << i)) >> i;
|
||||||
|
data |= (bit << (7-i*2)) | (bit << (6-i*2));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Signal::sendData()
|
||||||
|
{
|
||||||
|
sendRaw(getPacket());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t Signal::getType()
|
||||||
|
{
|
||||||
|
return _type;
|
||||||
|
}
|
32
signal.h
Normal file
32
signal.h
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "item.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class Signal: public Item
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static constexpr uint8_t GO = 0;
|
||||||
|
static constexpr uint8_t STOP = 1;
|
||||||
|
static constexpr uint8_t SLOW = 2;
|
||||||
|
static constexpr uint8_t EXPECT_GO = 0;
|
||||||
|
static constexpr uint8_t EXPECT_STOP = 1 << 3;
|
||||||
|
static constexpr uint8_t RIGHT = 2 << 3;
|
||||||
|
static constexpr uint8_t TYPE_NORMAL = 0;
|
||||||
|
static constexpr uint8_t TYPE_RELAY = 1;
|
||||||
|
static constexpr uint8_t TYPE_HAS_SLOW = 1 << 1;
|
||||||
|
static constexpr uint8_t TYPE_HAS_EXPECT = 1 << 2;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint8_t _state = GO;
|
||||||
|
uint8_t _subaddress;
|
||||||
|
uint8_t _type;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Signal(uint8_t address, uint8_t subaddress, uint8_t type = TYPE_NORMAL | TYPE_HAS_SLOW);
|
||||||
|
void setState(uint8_t state);
|
||||||
|
uint8_t getState();
|
||||||
|
uint8_t getSubaddress();
|
||||||
|
uint16_t getPacket();
|
||||||
|
void sendData();
|
||||||
|
uint8_t getType();
|
||||||
|
};
|
116
signaldispatch.h
Normal file
116
signaldispatch.h
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void printSignalState(uint8_t id, Serial* serial)
|
||||||
|
{
|
||||||
|
snprintf(buffer, SNPRINTF_BUFFER_SIZE,
|
||||||
|
"SIGNAL NUMBER: %u ADDRESS: %u SUBADDRESS: %u TYPE: %u CURRENT PACKET: %x STATE: %u\n",
|
||||||
|
id, signals[id].getAddress(), signals[id].getSubaddress(), signals[id].getType(),
|
||||||
|
signals[id].getPacket(), signals[id].getState());
|
||||||
|
serial->write(buffer, SNPRINTF_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int signalDispatch(char* inBuffer, Serial* serial)
|
||||||
|
{
|
||||||
|
if( strcmp(inBuffer, "add") == 0 )
|
||||||
|
{
|
||||||
|
char* token = strtok(NULL, " ");
|
||||||
|
uint8_t address = 0;
|
||||||
|
if(token != NULL)
|
||||||
|
address = strtol(token, nullptr, 10);
|
||||||
|
if(address != 0 && signals.remainingCapacity() > 0)
|
||||||
|
{
|
||||||
|
uint8_t subaddress = 0;
|
||||||
|
uint8_t type = 0;
|
||||||
|
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
subaddress = strtol(token, nullptr, 10);
|
||||||
|
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
type = strtol(token, nullptr, 10);
|
||||||
|
|
||||||
|
signals.push_back(Signal(address, subaddress, type));
|
||||||
|
serial->write_p(PSTR("SIGNAL saved! "));
|
||||||
|
printSignalState(signals.count()-1, serial);
|
||||||
|
|
||||||
|
save_state();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
serial->write_p(PSTR("Usage: signal add [address] [subaddress] [type]"));
|
||||||
|
}
|
||||||
|
else if( strcmp(inBuffer, "list") == 0 )
|
||||||
|
{
|
||||||
|
serial->write_p(PSTR("Signals:\n"));
|
||||||
|
for(uint8_t i = 0; i < signals.count(); i++)
|
||||||
|
printSignalState(i, serial);
|
||||||
|
serial->putChar('\n');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t id = strtol(inBuffer, nullptr, 10);
|
||||||
|
if(id < signals.count() )
|
||||||
|
{
|
||||||
|
setPower(true);
|
||||||
|
char* token = strtok(NULL, " ");
|
||||||
|
if(token != NULL && strcmp(token, "set") == 0 )
|
||||||
|
{
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
{
|
||||||
|
uint8_t state = strtol(token, nullptr, 10);;
|
||||||
|
signals[id].setState(state);
|
||||||
|
serial->write_p(PSTR("Set signal state"));
|
||||||
|
serial->write((int)state);
|
||||||
|
serial->putChar('\n');
|
||||||
|
printSignalState(id, serial);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(token != NULL && strcmp(token, "raw") == 0 )
|
||||||
|
{
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
serial->flush();
|
||||||
|
if(token != NULL)
|
||||||
|
{
|
||||||
|
cli();
|
||||||
|
uint16_t i = strtol(token, nullptr, 16 );
|
||||||
|
snprintf(buffer, SNPRINTF_BUFFER_SIZE, "SENDING: %x to %x\n", i, signals[id].getAddress());
|
||||||
|
serial->write(buffer, strlen(buffer));
|
||||||
|
while(!serial->dataIsWaiting())
|
||||||
|
{
|
||||||
|
signals[id].sendRaw(i);
|
||||||
|
sei();
|
||||||
|
_delay_ms(20);
|
||||||
|
cli();
|
||||||
|
}
|
||||||
|
serial->write_p(PSTR("Finished\n"));
|
||||||
|
serial->flush();
|
||||||
|
sei();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(token != NULL && strcmp(token, "delete") == 0)
|
||||||
|
{
|
||||||
|
signals.erase(id);
|
||||||
|
serial->write_p(PSTR("Signal: "));
|
||||||
|
serial->write(id);
|
||||||
|
serial->write_p(PSTR(" deleted\n"));
|
||||||
|
save_state();
|
||||||
|
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;
|
||||||
|
}
|
57
train.cpp
57
train.cpp
@ -1,7 +1,9 @@
|
|||||||
#include "train.h"
|
#include "train.h"
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
|
||||||
Train::Train(const uint8_t address, uint8_t functionmask): Item(address), _functionmask(functionmask)
|
Train::Train(const uint8_t address, uint8_t functionmask, uint8_t quirks):
|
||||||
|
Item(address), _functionmask(functionmask), _quirks(quirks)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,15 +73,48 @@ uint16_t Train::packetAddFunction(const uint8_t function)
|
|||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Train::setSpeed(uint8_t speed)
|
void Train::setSpeed(int8_t speed)
|
||||||
{
|
{
|
||||||
_speed = speed;
|
bool direction = _direction;
|
||||||
sendData();
|
|
||||||
|
if(_quirks & (1 << 1))
|
||||||
|
speed = 0-speed;
|
||||||
|
|
||||||
|
if(speed < 0)
|
||||||
|
_direction = true;
|
||||||
|
else if(speed > 0)
|
||||||
|
_direction = false;
|
||||||
|
|
||||||
|
_speed = abs(speed);
|
||||||
|
|
||||||
|
if((_quirks & 1) && direction != _direction)
|
||||||
|
{
|
||||||
|
cli();
|
||||||
|
for(uint8_t i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
sendRaw(0x28c);
|
||||||
|
_delay_ms(4);
|
||||||
|
}
|
||||||
|
if(!_direction)
|
||||||
|
{
|
||||||
|
for(uint8_t i = 0; i < 2; ++i)
|
||||||
|
{
|
||||||
|
sendRaw(0x224);
|
||||||
|
_delay_ms(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sei();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendData();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t Train::getSpeed()
|
int8_t Train::getSpeed()
|
||||||
{
|
{
|
||||||
return _speed;
|
int8_t speed = _direction ? 0-_speed : _speed;
|
||||||
|
return _quirks & (1 << 1) ? 0-speed : speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Train::stop()
|
void Train::stop()
|
||||||
@ -144,3 +179,13 @@ void Train::sendFunction(const uint8_t function, bool enable)
|
|||||||
_function = (_function & ~(1 << function)) | (enable << function);
|
_function = (_function & ~(1 << function)) | (enable << function);
|
||||||
sendData();
|
sendData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t Train::getQuirks()
|
||||||
|
{
|
||||||
|
return _quirks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Train::setQuirks(uint8_t quirks)
|
||||||
|
{
|
||||||
|
_quirks = quirks;
|
||||||
|
}
|
||||||
|
18
train.h
18
train.h
@ -8,6 +8,7 @@ private:
|
|||||||
uint8_t _function = 0;
|
uint8_t _function = 0;
|
||||||
uint8_t _functionmask;
|
uint8_t _functionmask;
|
||||||
uint8_t _speed = 0;
|
uint8_t _speed = 0;
|
||||||
|
uint8_t _quirks = 0;
|
||||||
bool _direction = false;
|
bool _direction = false;
|
||||||
|
|
||||||
uint16_t packetAddSpeed();
|
uint16_t packetAddSpeed();
|
||||||
@ -17,27 +18,24 @@ private:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Train(const uint8_t address, uint8_t functionmask = 0b0000);
|
Train(const uint8_t address, uint8_t functionmask = 0, uint8_t quirks = 0);
|
||||||
|
|
||||||
void sendData();
|
void sendData();
|
||||||
|
|
||||||
void reverse();
|
void reverse();
|
||||||
|
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
bool isActive() {return getSpeed() || getFunctions();}
|
bool isActive() {return getSpeed() || getFunctions();}
|
||||||
|
|
||||||
uint16_t getLastPacket();
|
uint16_t getLastPacket();
|
||||||
|
|
||||||
void setSpeed(uint8_t speed);
|
void setSpeed(int8_t speed);
|
||||||
|
int8_t getSpeed();
|
||||||
uint8_t getSpeed();
|
|
||||||
|
|
||||||
void setFunctionMask(uint8_t functionmask) {_functionmask = functionmask;}
|
void setFunctionMask(uint8_t functionmask) {_functionmask = functionmask;}
|
||||||
|
|
||||||
uint8_t getFunctions();
|
uint8_t getFunctions();
|
||||||
|
uint8_t getFunctionMask();
|
||||||
uint8_t getFunctionMask();
|
|
||||||
|
|
||||||
void sendFunction(const uint8_t function, bool enable = true);
|
void sendFunction(const uint8_t function, bool enable = true);
|
||||||
|
|
||||||
|
uint8_t getQuirks();
|
||||||
|
void setQuirks(uint8_t quirks);
|
||||||
};
|
};
|
||||||
|
198
traindispatch.h
Normal file
198
traindispatch.h
Normal file
@ -0,0 +1,198 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void printTrainState(int id, Serial* serial)
|
||||||
|
{
|
||||||
|
snprintf(buffer, SNPRINTF_BUFFER_SIZE,
|
||||||
|
"TRAIN NUMBER: %u ADDRESS: %u CURRENT PACKET: %x SPEED: %i FUNCTIONS: %s FUNCTIONMASK: %s QUIRKS: %s\n",
|
||||||
|
id, trains[id].getAddress(),
|
||||||
|
trains[id].getLastPacket(), trains[id].getSpeed(),
|
||||||
|
bit_rep[trains[id].getFunctions() & 0x0F], bit_rep[trains[id].getFunctionMask() & 0x0F],
|
||||||
|
bit_rep[trains[id].getQuirks() & 0x0F]);
|
||||||
|
serial->write(buffer, SNPRINTF_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int trainDispatch(char* inBuffer, Serial* serial)
|
||||||
|
{
|
||||||
|
if( strcmp(inBuffer, "add") == 0 )
|
||||||
|
{
|
||||||
|
char* token = strtok(NULL, " ");
|
||||||
|
uint8_t address = 0;
|
||||||
|
if(token != NULL)
|
||||||
|
address = strtol(token, nullptr, 10);
|
||||||
|
if(address != 0 && trains.remainingCapacity() > 0)
|
||||||
|
{
|
||||||
|
uint8_t functionMask = 0;
|
||||||
|
uint8_t quirks = 0;
|
||||||
|
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
{
|
||||||
|
functionMask = strtol(token, nullptr, 2);
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
{
|
||||||
|
quirks = strtol(token, nullptr, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trains.push_back(Train(address, functionMask, quirks));
|
||||||
|
|
||||||
|
serial->write_p(PSTR("TRAIN saved! "));
|
||||||
|
printTrainState(trains.count()-1, serial);
|
||||||
|
|
||||||
|
save_state();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
serial->write_p(PSTR("Usage: train add [address] [functionmask] [quirks]"));
|
||||||
|
}
|
||||||
|
else if( strcmp(inBuffer, "list") == 0 )
|
||||||
|
{
|
||||||
|
serial->write_p(PSTR("Trains:\n"));
|
||||||
|
for(uint8_t i = 0; i < trains.count(); i++)
|
||||||
|
printTrainState(i, serial);
|
||||||
|
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 < trains.count() )
|
||||||
|
{
|
||||||
|
setPower(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"));
|
||||||
|
printTrainState(id, serial);
|
||||||
|
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");
|
||||||
|
printTrainState(id, serial);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(token != NULL && strcmp(token, "probe") == 0 )
|
||||||
|
{
|
||||||
|
serial->flush();
|
||||||
|
for(uint16_t j = 0; j < 1024 && !serial->dataIsWaiting(); 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();
|
||||||
|
serial->flush();
|
||||||
|
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();
|
||||||
|
printTrainState(id, serial);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if( token != NULL && strcmp(token, "edit") == 0)
|
||||||
|
{
|
||||||
|
uint8_t functionMask = 0;
|
||||||
|
uint8_t quirks = 0;
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
{
|
||||||
|
functionMask = strtol(token, nullptr, 2);
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
{
|
||||||
|
quirks = strtol(token, nullptr, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trains[id].stop();
|
||||||
|
trains[id].setFunctionMask(functionMask);
|
||||||
|
trains[id].setQuirks(quirks);
|
||||||
|
save_state();
|
||||||
|
printTrainState(id, serial);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if( token != NULL && strcmp(token, "delete") == 0)
|
||||||
|
{
|
||||||
|
trains.erase(id);
|
||||||
|
serial->write_p(PSTR("Train: "));
|
||||||
|
serial->write(id);
|
||||||
|
serial->write_p(PSTR(" deleted\n"));
|
||||||
|
save_state();
|
||||||
|
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;
|
||||||
|
}
|
10
trains
10
trains
@ -1,5 +1,5 @@
|
|||||||
NUMBER: 0 ID: 84 CURRENT PACKET: 28c SPEED: 0 FUNCTIONS: 0 FUNCTIONMASK: 0 //rangier dampf lok
|
TRAIN NUMBER: 0 ADDRESS: 84 CURRENT PACKET: 224 SPEED: 0 FUNCTIONS: 0000 FUNCTIONMASK: 0000 //rangier dampf lok
|
||||||
NUMBER: 1 ID: 4 CURRENT PACKET: 227 SPEED: 0 FUNCTIONS: 0 FUNCTIONMASK: 0 //dampf lok
|
TRAIN NUMBER: 1 ADDRESS: 4 CURRENT PACKET: 224 SPEED: 0 FUNCTIONS: 0000 FUNCTIONMASK: 0000 //dampf lok
|
||||||
NUMBER: 2 ID: 68 CURRENT PACKET: 224 SPEED: 0 FUNCTIONS: 0 FUNCTIONMASK: 7 //rangier lok
|
TRAIN NUMBER: 2 ADDRESS: 68 CURRENT PACKET: 28c SPEED: 0 FUNCTIONS: 0000 FUNCTIONMASK: 0111 //rangier lok
|
||||||
NUMBER: 3 ID: 64 CURRENT PACKET: 274 SPEED: 0 FUNCTIONS: 0 FUNCTIONMASK: 0 //ICE
|
TRAIN NUMBER: 3 ADDRESS: 64 CURRENT PACKET: 224 SPEED: 0 FUNCTIONS: 0000 FUNCTIONMASK: 0000 //ICE 2
|
||||||
NUMBER: 4 ID: 40 CURRENT PACKET: 260 SPEED: 0 FUNCTIONS: 0 FUNCTIONMASK: 0 //br143
|
TRAIN NUMBER: 4 ADDRESS: 20 CURRENT PACKET: 224 SPEED: 0 FUNCTIONS: 0000 FUNCTIONMASK: 0000 //br143
|
||||||
|
110
turnoutdispatch.h
Normal file
110
turnoutdispatch.h
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
void printTurnoutState(uint8_t id, Serial* serial)
|
||||||
|
{
|
||||||
|
snprintf(buffer, SNPRINTF_BUFFER_SIZE,
|
||||||
|
"TURNOUT NUMBER: %u ADDRESS: %u SUBADDRESS: %u CURRENT PACKET: %x DIRECTION: %u\n",
|
||||||
|
id, turnouts[id].getAddress(), turnouts[id].getSubaddress(),
|
||||||
|
turnouts[id].getPacket(), turnouts[id].getDirection());
|
||||||
|
serial->write(buffer, SNPRINTF_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int turnoutDispatch(char* inBuffer, Serial* serial)
|
||||||
|
{
|
||||||
|
if( strcmp(inBuffer, "add") == 0 )
|
||||||
|
{
|
||||||
|
char* token = strtok(NULL, " ");
|
||||||
|
uint8_t address = 0;
|
||||||
|
if(token != NULL)
|
||||||
|
address = strtol(token, nullptr, 10);
|
||||||
|
if(address != 0 && turnouts.remainingCapacity() > 0)
|
||||||
|
{
|
||||||
|
uint8_t subaddress = 0;
|
||||||
|
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
if(token != NULL)
|
||||||
|
subaddress = strtol(token, nullptr, 10);
|
||||||
|
|
||||||
|
turnouts.push_back(Turnout(address, subaddress));
|
||||||
|
serial->write_p(PSTR("TUNROUT saved! "));
|
||||||
|
printTurnoutState(turnouts.count()-1, serial);
|
||||||
|
|
||||||
|
save_state();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
serial->write_p(PSTR("Usage: turnout add [address] [subaddress]"));
|
||||||
|
}
|
||||||
|
else if( strcmp(inBuffer, "list") == 0 )
|
||||||
|
{
|
||||||
|
serial->write_p(PSTR("Turnouts:\n"));
|
||||||
|
for(uint8_t i = 0; i < turnouts.count(); i++)
|
||||||
|
printTurnoutState(i, serial);
|
||||||
|
serial->putChar('\n');
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
uint8_t id = strtol(inBuffer, nullptr, 10);
|
||||||
|
if(id < turnouts.count() )
|
||||||
|
{
|
||||||
|
setPower(true);
|
||||||
|
char* token = strtok(NULL, " ");
|
||||||
|
if(token != NULL && strcmp(token, "set") == 0 )
|
||||||
|
{
|
||||||
|
char* boolToken = strtok(NULL, " ");
|
||||||
|
if(token != NULL && boolToken != NULL)
|
||||||
|
{
|
||||||
|
bool direction = (strcmp(boolToken, "right") == 0);
|
||||||
|
turnouts[id].setDirection(direction);
|
||||||
|
serial->write_p(PSTR("Set turnout direction "));
|
||||||
|
serial->write(direction ? "right\n" : "left\n");
|
||||||
|
printTurnoutState(id, serial);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(token != NULL && strcmp(token, "raw") == 0 )
|
||||||
|
{
|
||||||
|
token = strtok(NULL, " ");
|
||||||
|
serial->flush();
|
||||||
|
if(token != NULL)
|
||||||
|
{
|
||||||
|
cli();
|
||||||
|
uint16_t i = strtol(token, nullptr, 16 );
|
||||||
|
snprintf(buffer, SNPRINTF_BUFFER_SIZE, "SENDING: %x to %x\n", i, turnouts[id].getAddress());
|
||||||
|
serial->write(buffer, strlen(buffer));
|
||||||
|
while(!serial->dataIsWaiting())
|
||||||
|
{
|
||||||
|
turnouts[id].sendRaw(i);
|
||||||
|
sei();
|
||||||
|
_delay_ms(20);
|
||||||
|
cli();
|
||||||
|
}
|
||||||
|
serial->write_p(PSTR("Finished\n"));
|
||||||
|
serial->flush();
|
||||||
|
sei();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(token != NULL && strcmp(token, "delete") == 0)
|
||||||
|
{
|
||||||
|
turnouts.erase(id);
|
||||||
|
serial->write_p(PSTR("Turnout: "));
|
||||||
|
serial->write(id);
|
||||||
|
serial->write_p(PSTR(" deleted\n"));
|
||||||
|
save_state();
|
||||||
|
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;
|
||||||
|
}
|
Reference in New Issue
Block a user