198 lines
		
	
	
	
		
			3.7 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			198 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;
 | |
| }
 |