199 lines
3.7 KiB
C++
199 lines
3.7 KiB
C++
#include "train.h"
|
|
|
|
static volatile unsigned char *_port = &PORTD;
|
|
|
|
Train::Train(const uint8_t address, uint8_t protocol): _address(address), _protocol(protocol)
|
|
{
|
|
}
|
|
|
|
Train::Train()
|
|
{
|
|
_address = 0;
|
|
}
|
|
|
|
void Train::setAddress(const uint8_t address)
|
|
{
|
|
_address = address;
|
|
}
|
|
|
|
uint8_t Train::getAddress()
|
|
{
|
|
return _address;
|
|
}
|
|
|
|
void Train::stop()
|
|
{
|
|
lastDataPacket = 0;
|
|
resendData();
|
|
}
|
|
|
|
bool Train::isActive()
|
|
{
|
|
return lastDataPacket & 0b0000000111111111;
|
|
}
|
|
|
|
|
|
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()
|
|
{
|
|
for(uint8_t i = 0; i < 8; i++)
|
|
{
|
|
sendBit(_address & (1 << i));
|
|
}
|
|
}
|
|
|
|
void Train::sendRaw(const uint16_t data)
|
|
{
|
|
for(uint8_t j = 0; j < SEND_COUNT; j++)
|
|
{
|
|
sendAddress();
|
|
for(uint8_t i = 0; i < 10; i++)
|
|
{
|
|
sendBit(data & (1 << i));
|
|
}
|
|
_delay_ms(2);
|
|
}
|
|
}
|
|
|
|
void Train::setSpeed(uint8_t speed)
|
|
{
|
|
if(speed != 0)speed = speed + 1;
|
|
else if(speed > 15) speed = 15;
|
|
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));
|
|
}
|
|
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;
|
|
}
|
|
|
|
void Train::resendData()
|
|
{
|
|
sendRaw(lastDataPacket);
|
|
if(functionTimer > 0)
|
|
{
|
|
--functionTimer;
|
|
}
|
|
else if(functionTimer == 0)
|
|
{
|
|
functionClear();
|
|
--functionTimer;
|
|
}
|
|
}
|
|
|
|
uint16_t Train::getLastPacket()
|
|
{
|
|
return lastDataPacket;
|
|
}
|
|
|
|
void Train::reverse()
|
|
{
|
|
functionClear();
|
|
resendData();
|
|
resendData();
|
|
if(getSpeed() > 0)
|
|
{
|
|
setSpeed(0);
|
|
resendData();
|
|
resendData();
|
|
_delay_ms(2000);
|
|
}
|
|
sendRaw(0b000001100);
|
|
sendRaw(0b000001100);
|
|
}
|
|
|
|
void Train::functionClear()
|
|
{
|
|
lastDataPacket = lastDataPacket & ~(0b10101010);
|
|
}
|
|
|
|
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));
|
|
}
|
|
}
|
|
resendData();
|
|
functionTimer = 10;
|
|
}
|
|
|
|
void Train::setProtocol(const uint8_t protocol)
|
|
{
|
|
_protocol = protocol;
|
|
}
|
|
|
|
uint8_t Train::getProtocol()
|
|
{
|
|
return _protocol;
|
|
}
|