send sucess message if command is processed sucessfully
This commit is contained in:
		
							parent
							
								
									6a02c2f8cd
								
							
						
					
					
						commit
						ba67c5138d
					
				
					 5 changed files with 513 additions and 410 deletions
				
			
		
							
								
								
									
										664
									
								
								main.cpp
									
										
									
									
									
								
							
							
						
						
									
										664
									
								
								main.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -12,7 +12,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define MAX_TRAINS 16
 | 
					#define MAX_TRAINS 16
 | 
				
			||||||
#define COMMAND_BUFFER_SIZE 64
 | 
					#define COMMAND_BUFFER_SIZE 64
 | 
				
			||||||
#define SNPRINTF_BUFFER_SIZE 64
 | 
					#define SNPRINTF_BUFFER_SIZE 128
 | 
				
			||||||
#define EPPROM_SIZE 1024
 | 
					#define EPPROM_SIZE 1024
 | 
				
			||||||
 | 
					
 | 
				
			||||||
char buffer[SNPRINTF_BUFFER_SIZE];
 | 
					char buffer[SNPRINTF_BUFFER_SIZE];
 | 
				
			||||||
| 
						 | 
					@ -30,344 +30,414 @@ volatile bool resendEvent = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
ISR(TIMER0_OVF_vect) 
 | 
					ISR(TIMER0_OVF_vect) 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    ++tick;
 | 
						++tick;
 | 
				
			||||||
    if(tick  == 0) resendEvent = true;
 | 
						if(tick  == 0)
 | 
				
			||||||
    if((tick & 0b00000111) < 1) Train::setOutput(Train::HIGH);
 | 
							resendEvent = true;
 | 
				
			||||||
    else Train::setOutput(Train::LOW);
 | 
						if((tick & 0b00000111) < 1) Train::setOutput(Train::HIGH);
 | 
				
			||||||
 | 
						else Train::setOutput(Train::LOW);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void timer0InterruptEnable(const bool enable)
 | 
					void timer0InterruptEnable(const bool enable)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
     if(enable) TIMSK0 = 0b00000001;
 | 
						if(enable) TIMSK0 = 0b00000001;
 | 
				
			||||||
     else TIMSK0 = 0b00000000;
 | 
						else TIMSK0 = 0b00000000;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void save_state()
 | 
					void save_state()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    cli();
 | 
						cli();
 | 
				
			||||||
    EEPROM_write_char( 0, storedTrains );
 | 
						EEPROM_write_char( 0, storedTrains );
 | 
				
			||||||
    EEPROM_write_char( 1, autoff );
 | 
						EEPROM_write_char( 1, autoff );
 | 
				
			||||||
    for(uint16_t i = 0; i < storedTrains; i++)
 | 
						for(uint16_t i = 0; i < storedTrains; 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].getProtocol());
 | 
							EEPROM_write_char( i*2+32+1, trains[i].getFunctionMask());
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
    sei();
 | 
						sei();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void restore_state()
 | 
					void restore_state()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    storedTrains = EEPROM_read_char(0);
 | 
						storedTrains = EEPROM_read_char(0);
 | 
				
			||||||
    autoff = EEPROM_read_char(1);
 | 
						autoff = EEPROM_read_char(1);
 | 
				
			||||||
    if(storedTrains > MAX_TRAINS ) 
 | 
						if(storedTrains > MAX_TRAINS ) 
 | 
				
			||||||
    {
 | 
						{
 | 
				
			||||||
        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);
 | 
				
			||||||
        storedTrains = 0;
 | 
							storedTrains = 0;
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
    else for(uint8_t i = 0; i < storedTrains; i++)
 | 
						else for(uint8_t i = 0; i < storedTrains; i++)
 | 
				
			||||||
    {
 | 
						{
 | 
				
			||||||
        trains[i].setAddress(EEPROM_read_char(32+i*2)); 
 | 
							trains[i].setAddress(EEPROM_read_char(32+i*2)); 
 | 
				
			||||||
        trains[i].setProtocol(EEPROM_read_char(32+1+i*2));
 | 
							trains[i].setFunctionMask(EEPROM_read_char(32+1+i*2));
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
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]        :  Add train.\n\
 | 
									train add [address] [functionmask]       :  Add train.\n\
 | 
				
			||||||
                train delete               :  Delete last train.\n\
 | 
									train delete                             :  Delete last train.\n\
 | 
				
			||||||
                train list                 :  Print list of saved trains.\n\
 | 
									train list                               :  Print list of saved trains.\n\
 | 
				
			||||||
                train [nn] stop            :  Stop nth train.\n\
 | 
									train [nn] s(top)                        :  Stop nth train.\n\
 | 
				
			||||||
                train [nn] speed [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] reverse         :  Reverse train n.\n\
 | 
									train [nn] r(everse)                     :  Reverse train n.\n\
 | 
				
			||||||
                stop                       :  stop all trains\n\
 | 
									stop                                     :  stop all trains\n\
 | 
				
			||||||
                power off                  :  power off the rail\n\
 | 
									power off                                :  power off the rail\n\
 | 
				
			||||||
                power on                   :  power on the rail\n\
 | 
									power on                                 :  power on the rail\n\
 | 
				
			||||||
                power auto                 :  power off the rail when no trains are moveing\n\
 | 
									power auto                               :  power off the rail when no trains are moveing\n\
 | 
				
			||||||
                dump                       :  prints epprom contence\n\
 | 
									dump                                     :  prints epprom contence\n\
 | 
				
			||||||
                erase                      :  Erase epprom.\n"));
 | 
									erase                                    :  Erase epprom.\n"));
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void trainDispatch(char* inBuffer, Serial* serial)
 | 
					int trainDispatch(char* inBuffer, Serial* serial)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    cli();
 | 
						if( strcmp(inBuffer, "add") == 0 )
 | 
				
			||||||
    if( strcmp(inBuffer, "add") == 0 )
 | 
						{
 | 
				
			||||||
    {
 | 
							char* token = strtok(NULL, " ");
 | 
				
			||||||
        char* token = strtok(NULL, " ");
 | 
							uint8_t address = 0;
 | 
				
			||||||
        uint8_t address = 0;
 | 
							if(token != NULL)
 | 
				
			||||||
        if(token != NULL) address = strtol(token, nullptr, 2 );
 | 
								address = strtol(token, nullptr, 10);
 | 
				
			||||||
        if(address != 0 && storedTrains < MAX_TRAINS) 
 | 
							if(address != 0 && storedTrains < MAX_TRAINS) 
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            trains[storedTrains].setAddress(address);
 | 
								trains[storedTrains].setAddress(address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            token = strtok(NULL, " ");
 | 
								token = strtok(NULL, " ");
 | 
				
			||||||
            if(token != NULL && strcmp(token, "delta") == 0 )  trains[storedTrains].setProtocol(Train::M_DELTA);
 | 
								if(token != NULL) 
 | 
				
			||||||
            else trains[storedTrains].setProtocol(Train::M_DIGITAL);
 | 
									trains[storedTrains].setFunctionMask(strtol(token, nullptr, 2 ));
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
            uint8_t size = snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRAIN saved! NUMBER: %u ADRESS: %s%s PROTCOL: %s\n", storedTrains, bit_rep[address >> 4], bit_rep[address & 0x0F], trains[storedTrains].getProtocol() == Train::M_DELTA ? "delta" : "digital" );
 | 
								uint8_t size = snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRAIN saved! NUMBER: %u ADDRESS: %u FUNCTIONS: %u FUNCTIONMASK: %u\n", 
 | 
				
			||||||
            serial->write(buffer, size);
 | 
														storedTrains,
 | 
				
			||||||
 | 
														address,
 | 
				
			||||||
 | 
														trains[storedTrains].getFunctions(),
 | 
				
			||||||
 | 
														trains[storedTrains].getFunctionMask());
 | 
				
			||||||
 | 
								serial->write(buffer, size);
 | 
				
			||||||
			
 | 
								
 | 
				
			||||||
            storedTrains++;
 | 
								storedTrains++;
 | 
				
			||||||
            save_state();
 | 
								save_state();
 | 
				
			||||||
        }
 | 
								return 0;
 | 
				
			||||||
        serial->write_p(PSTR("Usage: train add [address]"));
 | 
							}
 | 
				
			||||||
    }
 | 
							serial->write_p(PSTR("Usage: train add [address] [functionmask]"));
 | 
				
			||||||
    else if( strcmp(inBuffer, "delete") == 0)
 | 
						}
 | 
				
			||||||
    {
 | 
						else if( strcmp(inBuffer, "delete") == 0)
 | 
				
			||||||
        serial->write_p(PSTR("Train: "));
 | 
						{
 | 
				
			||||||
        serial->write(storedTrains);
 | 
							serial->write_p(PSTR("Train: "));
 | 
				
			||||||
        serial->write_p(PSTR(" deleted\n"));
 | 
							serial->write(storedTrains-1);
 | 
				
			||||||
        storedTrains--;
 | 
							serial->write_p(PSTR(" deleted\n"));
 | 
				
			||||||
    }
 | 
							storedTrains--;
 | 
				
			||||||
    else if( strcmp(inBuffer, "list") == 0 )
 | 
							if(storedTrains < 0)
 | 
				
			||||||
    {
 | 
								storedTrains = 0;
 | 
				
			||||||
        serial->write_p(PSTR("Trains:\n"));
 | 
							save_state();
 | 
				
			||||||
        for(uint8_t i = 0; i < storedTrains; i++)
 | 
							return 0;
 | 
				
			||||||
        {
 | 
						}
 | 
				
			||||||
            snprintf(buffer, SNPRINTF_BUFFER_SIZE, "NUMBER: %u ID: %s%s CURRENT PACKET: %x SPEED: %u", i, bit_rep[trains[i].getAddress() >> 4], bit_rep[trains[i].getAddress() & 0x0F], trains[i].getLastPacket(), trains[i].getSpeed());
 | 
						else if( strcmp(inBuffer, "list") == 0 )
 | 
				
			||||||
            serial->write(buffer, SNPRINTF_BUFFER_SIZE);
 | 
						{
 | 
				
			||||||
            serial->write_p(PSTR(" PROTOCOL: "));
 | 
							serial->write_p(PSTR("Trains:\n"));
 | 
				
			||||||
            if(trains[i].getProtocol() == Train::M_DELTA)serial->write_p(PSTR("delta\n"));
 | 
							for(uint8_t i = 0; i < storedTrains; i++)
 | 
				
			||||||
            else serial->write_p(PSTR("digital\n"));
 | 
							{
 | 
				
			||||||
        }
 | 
								snprintf(buffer, SNPRINTF_BUFFER_SIZE, "NUMBER: %u ID: %u CURRENT PACKET: %x SPEED: %i FUNCTIONS: %u FUNCTIONMASK: %u\n", 
 | 
				
			||||||
        serial->putChar('\n');
 | 
											i, trains[i].getAddress(),
 | 
				
			||||||
    }
 | 
											trains[i].getLastPacket(), trains[i].getSpeed(),
 | 
				
			||||||
    else
 | 
											trains[i].getFunctions(), trains[i].getFunctionMask());
 | 
				
			||||||
    {
 | 
								serial->write(buffer, SNPRINTF_BUFFER_SIZE);
 | 
				
			||||||
        uint8_t id = strtol(inBuffer, nullptr, 10);
 | 
							}
 | 
				
			||||||
        if(id < storedTrains )
 | 
							serial->putChar('\n');
 | 
				
			||||||
        {
 | 
							return 0;
 | 
				
			||||||
            if(powerIsOn == false)
 | 
						}
 | 
				
			||||||
            {
 | 
						else if( strcmp(inBuffer, "probe") == 0 )
 | 
				
			||||||
                powerIsOn = true;
 | 
						{
 | 
				
			||||||
                Train::setOutput(Train::LOW);
 | 
							for(uint16_t j = 0; j < 255; j++)
 | 
				
			||||||
                _delay_ms(100);
 | 
							{
 | 
				
			||||||
                timer0InterruptEnable(true);
 | 
								snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRYING ADDR: %x\n", j);
 | 
				
			||||||
            }
 | 
								serial->write(buffer, strlen(buffer));
 | 
				
			||||||
            char* token = strtok(NULL, " ");
 | 
								cli();
 | 
				
			||||||
            if( token != NULL &&  (strcmp(token, "speed") == 0 || strcmp(token, "s") == 0) )
 | 
								for(uint8_t k = 0; k < 10; k++)
 | 
				
			||||||
            {
 | 
								{
 | 
				
			||||||
                token = strtok(NULL, " ");
 | 
									Train::sendRawAddr(j, 60);
 | 
				
			||||||
                trains[id].setSpeed(atoi(token));
 | 
									_delay_ms(20);
 | 
				
			||||||
                serial->write_p(PSTR("Set Train speed\n"));
 | 
								}
 | 
				
			||||||
            }
 | 
								for(uint8_t k = 0; k < 3; k++)
 | 
				
			||||||
            else if(token != NULL && strcmp(token, "function") == 0 ) 
 | 
								{
 | 
				
			||||||
            {
 | 
									Train::sendRawAddr(j, 0);
 | 
				
			||||||
                token = strtok(NULL, " ");
 | 
									_delay_ms(20);
 | 
				
			||||||
                char* boolToken = strtok(NULL, " ");
 | 
								}
 | 
				
			||||||
                if(token != NULL && boolToken !=  NULL)
 | 
								sei();
 | 
				
			||||||
                {
 | 
							}
 | 
				
			||||||
                    uint8_t functionId = atoi(token);
 | 
							return 0;
 | 
				
			||||||
                    bool on = (strcmp(boolToken, "on") == 0);
 | 
						}
 | 
				
			||||||
                    trains[id].sendFunction(functionId, on );
 | 
						else
 | 
				
			||||||
                    serial->write_p(PSTR("Set Train function "));
 | 
						{
 | 
				
			||||||
                    serial->write(functionId);
 | 
							uint8_t id = strtol(inBuffer, nullptr, 10);
 | 
				
			||||||
                    serial->write(on ? " on\n" : " off\n");
 | 
							if(id < storedTrains )
 | 
				
			||||||
                }
 | 
							{
 | 
				
			||||||
            }
 | 
								if(powerIsOn == false)
 | 
				
			||||||
            else if(token != NULL && strcmp(token, "probe") == 0 ) 
 | 
								{
 | 
				
			||||||
            {
 | 
									powerIsOn = true;
 | 
				
			||||||
                for(uint16_t j = 0; j < 1024; j++)
 | 
									Train::setOutput(Train::LOW);
 | 
				
			||||||
                {
 | 
									_delay_ms(100);
 | 
				
			||||||
                    trains[id].sendRaw(j);
 | 
									timer0InterruptEnable(true);
 | 
				
			||||||
                    snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRYING: %x\n", j);
 | 
								}
 | 
				
			||||||
                    serial->write(buffer, strlen(buffer));
 | 
								char* token = strtok(NULL, " ");
 | 
				
			||||||
                    sei();
 | 
								if( token != NULL &&  (strcmp(token, "speed") == 0 || strcmp(token, "s") == 0) )
 | 
				
			||||||
                    _delay_ms(250);
 | 
								{
 | 
				
			||||||
                    cli();
 | 
									token = strtok(NULL, " ");
 | 
				
			||||||
                    
 | 
									trains[id].setSpeed(atoi(token));
 | 
				
			||||||
                }
 | 
									serial->write_p(PSTR("Set Train speed\n"));
 | 
				
			||||||
            }
 | 
									return 0;
 | 
				
			||||||
            else if(token != NULL && strcmp(token, "raw") == 0 ) 
 | 
								}
 | 
				
			||||||
            {
 | 
								else if(token != NULL && strcmp(token, "function") == 0 ) 
 | 
				
			||||||
                token = strtok(NULL, " ");
 | 
								{
 | 
				
			||||||
                if(token != NULL)
 | 
									token = strtok(NULL, " ");
 | 
				
			||||||
                {
 | 
									char* boolToken = strtok(NULL, " ");
 | 
				
			||||||
                    cli();
 | 
									if(token != NULL && boolToken !=  NULL)
 | 
				
			||||||
                    uint16_t i = strtol(token, nullptr, 16 );
 | 
									{
 | 
				
			||||||
                    snprintf(buffer, SNPRINTF_BUFFER_SIZE, "SENDING: %x\n", i);
 | 
										uint8_t functionId = atoi(token);
 | 
				
			||||||
                    serial->write(buffer, strlen(buffer));
 | 
										bool on = (strcmp(boolToken, "on") == 0);
 | 
				
			||||||
                    for(uint8_t j = 0; j < 100; j++)
 | 
										trains[id].sendFunction(functionId, on );
 | 
				
			||||||
                    {
 | 
										serial->write_p(PSTR("Set Train function "));
 | 
				
			||||||
                        trains[id].sendRaw(i);
 | 
										serial->write(functionId);
 | 
				
			||||||
                        _delay_ms(20);
 | 
										serial->write(on ? " on\n" : " off\n");
 | 
				
			||||||
                    }
 | 
										return 0;
 | 
				
			||||||
                    serial->write_p(PSTR("Finished\n"));
 | 
									}
 | 
				
			||||||
                    sei();
 | 
								}
 | 
				
			||||||
                }
 | 
								else if(token != NULL && strcmp(token, "probe") == 0 ) 
 | 
				
			||||||
            }
 | 
								{
 | 
				
			||||||
            else if( token != NULL && (strcmp(token, "reverse") == 0 || strcmp(token, "r") == 0) )
 | 
									for(uint16_t j = 0; j < 1024; j++)
 | 
				
			||||||
            {
 | 
									{
 | 
				
			||||||
                trains[id].reverse();
 | 
										trains[id].sendRaw(j);
 | 
				
			||||||
                serial->write_p(PSTR("Reversed Train\n"));
 | 
										snprintf(buffer, SNPRINTF_BUFFER_SIZE, "TRYING: %x\n", j);
 | 
				
			||||||
            }
 | 
										serial->write(buffer, strlen(buffer));
 | 
				
			||||||
            else if( token != NULL && (strcmp(token, "stop") == 0 || strcmp(token, "p") == 0)) trains[id].stop();
 | 
										sei();
 | 
				
			||||||
            else serial->write_p(PSTR("Not a valid command\n"));
 | 
										_delay_ms(250);
 | 
				
			||||||
        }
 | 
										cli();
 | 
				
			||||||
        else serial->write_p(PSTR("Id out of range.\n"));
 | 
									}
 | 
				
			||||||
    }
 | 
									sei();
 | 
				
			||||||
    sei();
 | 
									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();
 | 
				
			||||||
 | 
									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 powerDispatch(char* token, Serial* serial)
 | 
					int powerDispatch(char* token, Serial* serial)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(strcmp(token, "off") == 0)
 | 
						if(strcmp(token, "off") == 0)
 | 
				
			||||||
    {
 | 
						{
 | 
				
			||||||
        timer0InterruptEnable(false);
 | 
							timer0InterruptEnable(false);
 | 
				
			||||||
        Train::setOutput(Train::OFF);
 | 
							Train::setOutput(Train::OFF);
 | 
				
			||||||
        powerIsOn = false;
 | 
							powerIsOn = false;
 | 
				
			||||||
    }
 | 
							return 0;
 | 
				
			||||||
    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 < storedTrains; i++)
 | 
				
			||||||
            trains[i].setSpeed(0);
 | 
							{
 | 
				
			||||||
        }
 | 
								trains[i].setSpeed(0);
 | 
				
			||||||
        Train::setOutput(Train::LOW);
 | 
							}
 | 
				
			||||||
        timer0InterruptEnable(true);
 | 
							Train::setOutput(Train::LOW);
 | 
				
			||||||
    }
 | 
							timer0InterruptEnable(true);
 | 
				
			||||||
    else if(strcmp(token, "auto") == 0)
 | 
							return 0;
 | 
				
			||||||
    {
 | 
						}
 | 
				
			||||||
        token = strtok(NULL, " ");
 | 
						else if(strcmp(token, "auto") == 0)
 | 
				
			||||||
        if(token != NULL && strcmp(token, "on") == 0)
 | 
						{
 | 
				
			||||||
        {
 | 
							token = strtok(NULL, " ");
 | 
				
			||||||
            autoff = true;
 | 
							if(token != NULL && strcmp(token, "on") == 0)
 | 
				
			||||||
            serial->write_p(PSTR("auto power off turned on.\n"));
 | 
							{
 | 
				
			||||||
            save_state();
 | 
								autoff = true;
 | 
				
			||||||
        }
 | 
								serial->write_p(PSTR("auto power off turned on.\n"));
 | 
				
			||||||
        else if(token != NULL && strcmp(token, "off") == 0)
 | 
								save_state();
 | 
				
			||||||
        {
 | 
							}
 | 
				
			||||||
            autoff = false;
 | 
							else if(token != NULL && strcmp(token, "off") == 0)
 | 
				
			||||||
            serial->write_p(PSTR("auto power off turned off.\n"));
 | 
							{
 | 
				
			||||||
            save_state();
 | 
								autoff = false;
 | 
				
			||||||
        }
 | 
								serial->write_p(PSTR("auto power off turned off.\n"));
 | 
				
			||||||
        else 
 | 
								save_state();
 | 
				
			||||||
        {
 | 
							}
 | 
				
			||||||
            serial->write_p(PSTR("argument must be \"on\" or \"off\". This feature is currently "));
 | 
							else 
 | 
				
			||||||
            autoff ? serial->write_p(PSTR("on.\n")) : serial->write_p(PSTR("off.\n"));
 | 
							{
 | 
				
			||||||
        }
 | 
								serial->write_p(PSTR("argument must be \"on\" or \"off\". This feature is currently "));
 | 
				
			||||||
    }
 | 
								autoff ? serial->write_p(PSTR("on.\n")) : serial->write_p(PSTR("off.\n"));
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return -1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void serialDispatch(Serial* serial)
 | 
					void serialDispatch(Serial* serial)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(serial->dataIsWaiting())
 | 
						if(serial->dataIsWaiting())
 | 
				
			||||||
    {
 | 
						{
 | 
				
			||||||
        char buffer[COMMAND_BUFFER_SIZE];
 | 
							char buffer[COMMAND_BUFFER_SIZE];
 | 
				
			||||||
        unsigned int length = serial->getString(buffer, COMMAND_BUFFER_SIZE);
 | 
							unsigned int length = serial->getString(buffer, COMMAND_BUFFER_SIZE);
 | 
				
			||||||
        if(length > 0)
 | 
							if(length > 0)
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            serial->write_p(PSTR("Got: "));
 | 
								int ret = -1;
 | 
				
			||||||
            serial->putChar('\"');
 | 
								char* token = strtok(buffer, " ");
 | 
				
			||||||
            serial->write(buffer, length);
 | 
								if(length > 4 && (strcmp(token, "train") == 0 || strcmp(token, "t") == 0 ))
 | 
				
			||||||
            serial->write("\"\n");
 | 
								{
 | 
				
			||||||
            char* token = strtok(buffer, " ");
 | 
									token = strtok(NULL, " ");
 | 
				
			||||||
            if(length > 4 && (strcmp(token, "train") == 0 || strcmp(token, "t") == 0 ))
 | 
									if(token != NULL)
 | 
				
			||||||
            {
 | 
										ret = trainDispatch(token, serial);
 | 
				
			||||||
                token = strtok(NULL, " ");
 | 
								}
 | 
				
			||||||
                if(token != NULL)
 | 
								else if(strncmp(token, "erase", 4) == 0)
 | 
				
			||||||
                    trainDispatch(token, serial);
 | 
								{
 | 
				
			||||||
            }
 | 
									for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0);
 | 
				
			||||||
            else if(strncmp(token, "erase", 4) == 0)
 | 
									serial->write_p(PSTR("EEPROM erased\n"));
 | 
				
			||||||
            {
 | 
									storedTrains = 0;
 | 
				
			||||||
                for(uint16_t i = 0; i < EPPROM_SIZE; i++) EEPROM_write_char(i, 0);
 | 
									ret = 0;
 | 
				
			||||||
                serial->write_p(PSTR("EEPROM erased\n"));
 | 
								}
 | 
				
			||||||
                storedTrains = 0;
 | 
								else if(strcmp(token, "dump") == 0)
 | 
				
			||||||
            }
 | 
								{
 | 
				
			||||||
            else if(strcmp(token, "dump") == 0)
 | 
									for(uint16_t i = 0; i < EPPROM_SIZE; i++) 
 | 
				
			||||||
            {
 | 
									{
 | 
				
			||||||
                for(uint16_t i = 0; i < EPPROM_SIZE; i++) 
 | 
										if(i != 0) serial->putChar(',');
 | 
				
			||||||
                {
 | 
										serial->write((uint16_t)EEPROM_read_char(i));
 | 
				
			||||||
                    if(i != 0) serial->putChar(',');
 | 
									}
 | 
				
			||||||
                    serial->write((uint16_t)EEPROM_read_char(i));
 | 
									serial->putChar('\n');
 | 
				
			||||||
                }
 | 
									ret = 0;
 | 
				
			||||||
                serial->putChar('\n');
 | 
								}
 | 
				
			||||||
            }
 | 
								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 < storedTrains; i++)
 | 
									{
 | 
				
			||||||
                {
 | 
										cli();
 | 
				
			||||||
                    cli();
 | 
										trains[i].stop();
 | 
				
			||||||
                    trains[i].stop();
 | 
										sei();
 | 
				
			||||||
                    sei();
 | 
									}
 | 
				
			||||||
                }
 | 
									ret = 0;
 | 
				
			||||||
            }
 | 
								}
 | 
				
			||||||
            else if(strcmp(token, "power") == 0)
 | 
								else if(strcmp(token, "power") == 0)
 | 
				
			||||||
            {
 | 
								{
 | 
				
			||||||
                token = strtok(NULL, " ");
 | 
									token = strtok(NULL, " ");
 | 
				
			||||||
                if(token != NULL)powerDispatch(token, serial);
 | 
									if(token != NULL)
 | 
				
			||||||
            }
 | 
										ret = powerDispatch(token, serial);
 | 
				
			||||||
            else if(strcmp(token, "help") == 0)
 | 
								}
 | 
				
			||||||
            {
 | 
								else if(strcmp(token, "help") == 0)
 | 
				
			||||||
                printHelp(serial);
 | 
								{
 | 
				
			||||||
            }
 | 
									printHelp(serial);
 | 
				
			||||||
            else
 | 
									ret = 0;
 | 
				
			||||||
            {
 | 
								}
 | 
				
			||||||
                serial->putChar('\"');
 | 
								else
 | 
				
			||||||
                serial->write(buffer, length);
 | 
								{
 | 
				
			||||||
                serial->putChar('\"');
 | 
									serial->putChar('\"');
 | 
				
			||||||
                serial->write_p(PSTR(" is not a valid command\n"));
 | 
									serial->write(buffer, length);
 | 
				
			||||||
            }
 | 
									serial->putChar('\"');
 | 
				
			||||||
        }
 | 
									serial->write_p(PSTR(" is not a valid command\n"));
 | 
				
			||||||
    }
 | 
									ret = -1;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								if(ret < 0)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									serial->write_p(PSTR("Command Failed\n"));
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									serial->write_p(PSTR("Sucess \""));
 | 
				
			||||||
 | 
									serial->write(buffer, length);
 | 
				
			||||||
 | 
									serial->write("\"\n");
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main() 
 | 
					int main() 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    TCNT0 = 0;
 | 
						TCNT0 = 0;
 | 
				
			||||||
    TCCR0B = (1<<CS01) /*| (1<<CS00)*/; // run timer0 with /64 scaler
 | 
						TCCR0B = (1<<CS01) /*| (1<<CS00)*/; // run timer0 with /64 scaler
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    DDRD =  (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5);
 | 
						DDRD =  (1 << PD2) | (1 << PD3) | (1 << PD4) | (1 << PD5);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    restore_state();
 | 
						restore_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if(autoff) 
 | 
						if(autoff) 
 | 
				
			||||||
    {
 | 
						{
 | 
				
			||||||
        timer0InterruptEnable(false);
 | 
							timer0InterruptEnable(false);
 | 
				
			||||||
        Train::setOutput(Train::OFF);
 | 
							Train::setOutput(Train::OFF);
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
    else
 | 
						else
 | 
				
			||||||
    {
 | 
						{
 | 
				
			||||||
        timer0InterruptEnable(true);
 | 
							timer0InterruptEnable(true);
 | 
				
			||||||
        Train::setOutput(Train::LOW);
 | 
							Train::setOutput(Train::LOW);
 | 
				
			||||||
    }
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    sei();
 | 
						sei();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Serial serial;
 | 
						Serial serial;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    serial.write_p(PSTR("TrainController v0.1 starting\n"));
 | 
						serial.write_p(PSTR("TrainController v0.5 starting\n"));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t trainToResend = 0;
 | 
						uint8_t trainToResend = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    while(true)
 | 
						while(true)
 | 
				
			||||||
    {        
 | 
						{        
 | 
				
			||||||
        if(resendEvent && storedTrains > 0) 
 | 
							if(resendEvent && storedTrains > 0) 
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            timer0InterruptEnable(false);
 | 
								timer0InterruptEnable(false);
 | 
				
			||||||
            trains[trainToResend].resendData();
 | 
								_delay_us(255);
 | 
				
			||||||
            trainToResend++;
 | 
								trains[trainToResend].resendData();
 | 
				
			||||||
            if(storedTrains <= trainToResend) trainToResend = 0;
 | 
								trainToResend++;
 | 
				
			||||||
            resendEvent = false;
 | 
								if(storedTrains <= trainToResend)
 | 
				
			||||||
            timer0InterruptEnable(true);
 | 
									trainToResend = 0;
 | 
				
			||||||
        }
 | 
								resendEvent = false;
 | 
				
			||||||
 | 
								timer0InterruptEnable(true);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
        if(autoff) 
 | 
							if(autoff) 
 | 
				
			||||||
        {
 | 
							{
 | 
				
			||||||
            bool trainsRunning = false;
 | 
								bool trainsRunning = false;
 | 
				
			||||||
            for(uint16_t i = 0; i < storedTrains; i++) trainsRunning = trainsRunning || trains[i].isActive();
 | 
								for(uint16_t i = 0; i < storedTrains; i++)
 | 
				
			||||||
            if(!trainsRunning)
 | 
									trainsRunning = trainsRunning || trains[i].isActive();
 | 
				
			||||||
            {
 | 
								if(!trainsRunning)
 | 
				
			||||||
                powerIsOn = false;
 | 
								{
 | 
				
			||||||
                timer0InterruptEnable(false);
 | 
									powerIsOn = false;
 | 
				
			||||||
                Train::setOutput(Train::OFF);
 | 
									timer0InterruptEnable(false);
 | 
				
			||||||
            }
 | 
									Train::setOutput(Train::OFF);
 | 
				
			||||||
        }
 | 
								}
 | 
				
			||||||
        serialDispatch(&serial);
 | 
							}
 | 
				
			||||||
    }
 | 
							serialDispatch(&serial);
 | 
				
			||||||
    return 0;
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										2
									
								
								serial.h
									
										
									
									
									
								
							
							
						
						
									
										2
									
								
								serial.h
									
										
									
									
									
								
							| 
						 | 
					@ -2,7 +2,7 @@
 | 
				
			||||||
#define SERIAL_H
 | 
					#define SERIAL_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define BAUD 38400
 | 
					#define BAUD 38400
 | 
				
			||||||
#define SERIAL_BUFFER_SIZE 256
 | 
					#define SERIAL_BUFFER_SIZE 512
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include <util/setbaud.h>
 | 
					#include <util/setbaud.h>
 | 
				
			||||||
#include <avr/io.h>
 | 
					#include <avr/io.h>
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										176
									
								
								train.cpp
									
										
									
									
									
								
							
							
						
						
									
										176
									
								
								train.cpp
									
										
									
									
									
								
							| 
						 | 
					@ -1,8 +1,9 @@
 | 
				
			||||||
#include "train.h"
 | 
					#include "train.h"
 | 
				
			||||||
 | 
					#include <stdlib.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static volatile unsigned char *_port = &PORTD;
 | 
					static volatile unsigned char *_port = &PORTD;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Train::Train(const uint8_t address, uint8_t protocol):  _address(address), _protocol(protocol)
 | 
					Train::Train(const uint8_t address, uint8_t functionmask):  _address(address), _functionmask(functionmask)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -23,16 +24,11 @@ uint8_t Train::getAddress()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Train::stop()
 | 
					void Train::stop()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    lastDataPacket = 0;
 | 
					    _speed = 0;
 | 
				
			||||||
 | 
					    _function = 0;
 | 
				
			||||||
    resendData();
 | 
					    resendData();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool Train::isActive()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return lastDataPacket & 0b0000000111111111;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Train::off()
 | 
					void Train::off()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    writePin(_port, _pinHighA, false);
 | 
					    writePin(_port, _pinHighA, false);
 | 
				
			||||||
| 
						 | 
					@ -81,19 +77,20 @@ void Train::sendBit(const bool bit)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Train::sendAddress()
 | 
					void Train::sendAddress(uint8_t address)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for(uint8_t i = 0; i < 8; i++) 
 | 
					    for(uint8_t i = 0; i < 8; i++) 
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        sendBit(_address & (1 << i));
 | 
					        sendBit(address & (1 << i));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Train::sendRaw(const uint16_t data)
 | 
					
 | 
				
			||||||
 | 
					void Train::sendRawAddr(const uint16_t address, const uint16_t data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    for(uint8_t j = 0; j < SEND_COUNT; j++)
 | 
					    for(uint8_t j = 0; j < SEND_COUNT; j++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        sendAddress();
 | 
					        sendAddress(address);
 | 
				
			||||||
        for(uint8_t i = 0; i < 10; i++)
 | 
					        for(uint8_t i = 0; i < 10; i++)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            sendBit(data & (1 << i));
 | 
					            sendBit(data & (1 << i));
 | 
				
			||||||
| 
						 | 
					@ -102,97 +99,130 @@ void Train::sendRaw(const uint16_t data)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Train::setSpeed(uint8_t speed)
 | 
					void Train::sendRaw(const uint16_t data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(speed != 0)speed = speed + 1;
 | 
					    sendRawAddr(_address, data);
 | 
				
			||||||
    else if(speed > 15) speed = 15;
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t Train::packetAddSpeed()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t packet = 0;
 | 
				
			||||||
 | 
					    if(_speed > 14)
 | 
				
			||||||
 | 
					        _speed = 14;
 | 
				
			||||||
    for(uint8_t i = 0; i < 4; i++)
 | 
					    for(uint8_t i = 0; i < 4; i++)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
                                 lastDataPacket = (lastDataPacket & ~(1 << (i+1)*2))     | (((uint16_t)speed & (1 << i)) << (i+1)*2-i);
 | 
					        packet |= ((bool)((_speed+1) & (1 << i))) << (i*2+2);
 | 
				
			||||||
        if(_protocol == M_DELTA) lastDataPacket = (lastDataPacket & ~(1 << ((i+1)*2+1))) | (((uint16_t)speed & (1 << i)) << ((i+1)*2+1-i));
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return packet;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t Train::packetAddDirection()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t packet = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    uint8_t data = 0;
 | 
				
			||||||
 | 
					    if(!_direction)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(_speed > 6)
 | 
				
			||||||
 | 
					            data = 0b0100;
 | 
				
			||||||
 | 
					        else if(_speed > 0)
 | 
				
			||||||
 | 
					            data = 0b0101;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(_speed > 0)
 | 
				
			||||||
 | 
					            data = 0b1011;
 | 
				
			||||||
 | 
					        else if (_speed > 6)
 | 
				
			||||||
 | 
					            data = 0b1010;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if(_speed == 0)
 | 
				
			||||||
 | 
					        data = !_direction ?  0b0101 : 0b1011;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for(uint8_t i = 0; i < 4; i++)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        uint8_t bit = (data & (1 << (3-i))) >> (3-i);
 | 
				
			||||||
 | 
					        packet |= bit << ((i*2)+3);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return packet;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					uint16_t Train::packetAddFunction(const uint8_t function)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t packet = 0;
 | 
				
			||||||
 | 
					    bool enabled = _function & (1 << function);
 | 
				
			||||||
 | 
					    if(function == 0)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        packet |= enabled ? 0b00000011 : 0b00000000;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        if(enabled)
 | 
				
			||||||
 | 
					            packet |=  0b1000000000;
 | 
				
			||||||
 | 
					        for(uint8_t i = 0; i < 4; ++i )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if(function > i)
 | 
				
			||||||
 | 
					              packet = packet |  (1 << (7-i*2));
 | 
				
			||||||
 | 
					            else
 | 
				
			||||||
 | 
					              packet = packet & ~(1 << (7-i*2));
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return packet;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Train::setSpeed(uint8_t speed)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    _speed = speed;
 | 
				
			||||||
    resendData();
 | 
					    resendData();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t Train::getSpeed()
 | 
					uint8_t Train::getSpeed()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    uint8_t speed = 0;
 | 
					    return _speed;
 | 
				
			||||||
    for(uint8_t i = 0; i < 4; i++)
 | 
					}
 | 
				
			||||||
        speed |= ((bool)(lastDataPacket & (1 << (i+1)*2))) << i;
 | 
					
 | 
				
			||||||
    return speed;
 | 
					uint16_t Train::assemblePacket()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    uint16_t packet = packetAddSpeed() | packetAddFunction(0) | packetAddDirection();
 | 
				
			||||||
 | 
					    return packet;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Train::resendData()
 | 
					void Train::resendData()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    sendRaw(lastDataPacket);
 | 
					    sendRaw(assemblePacket());
 | 
				
			||||||
    if(functionTimer > 0)
 | 
					    for(uint8_t i = 1; i < 4; ++i)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        --functionTimer;
 | 
					        if(_functionmask & (1 << i))
 | 
				
			||||||
    }
 | 
					        sendRaw(packetAddSpeed() | packetAddFunction(i) | packetAddFunction(0));
 | 
				
			||||||
    else if(functionTimer == 0)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        functionClear();
 | 
					 | 
				
			||||||
        --functionTimer;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint16_t Train::getLastPacket()
 | 
					uint16_t Train::getLastPacket()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    return lastDataPacket;
 | 
					    return assemblePacket();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Train::reverse()
 | 
					void Train::reverse()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    functionClear();
 | 
					    _direction = !_direction;
 | 
				
			||||||
    resendData();
 | 
					    resendData();
 | 
				
			||||||
    resendData();
 | 
					 | 
				
			||||||
    if(getSpeed() > 0)
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        setSpeed(0);
 | 
					 | 
				
			||||||
        resendData();
 | 
					 | 
				
			||||||
        resendData();
 | 
					 | 
				
			||||||
        _delay_ms(2000);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    sendRaw(0b000001100);
 | 
					 | 
				
			||||||
    sendRaw(0b000001100);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Train::functionClear()
 | 
					
 | 
				
			||||||
 | 
					uint8_t Train::getFunctions()
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	lastDataPacket = lastDataPacket & ~(0b10101010);
 | 
					    return _function;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					uint8_t Train::getFunctionMask()
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    return _functionmask;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void Train::sendFunction(const uint8_t function, bool enable)
 | 
					void Train::sendFunction(const uint8_t function, bool enable)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    if(function == 0)
 | 
					    if(function > 3)
 | 
				
			||||||
    {
 | 
					        return;
 | 
				
			||||||
        lastDataPacket = (lastDataPacket & ~0b00000001) | (enable ? 0b00000001 : 0b00000000);
 | 
					    _function = (_function & ~(1 << function)) | (enable << function);
 | 
				
			||||||
        //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();
 | 
					    resendData();
 | 
				
			||||||
    functionTimer = 10;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void Train::setProtocol(const uint8_t protocol)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
   _protocol = protocol;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
uint8_t Train::getProtocol()
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    return _protocol;
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										49
									
								
								train.h
									
										
									
									
									
								
							
							
						
						
									
										49
									
								
								train.h
									
										
									
									
									
								
							| 
						 | 
					@ -8,40 +8,39 @@
 | 
				
			||||||
class Train
 | 
					class Train
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    static const uint8_t M_DELTA = 0;
 | 
					 | 
				
			||||||
    static const uint8_t M_DIGITAL = 1;
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    static const uint8_t HIGH = 2;
 | 
					    static constexpr uint8_t HIGH = 2;
 | 
				
			||||||
    static const uint8_t LOW = 1;
 | 
					    static constexpr uint8_t LOW = 1;
 | 
				
			||||||
    static const uint8_t OFF = 0;
 | 
					    static constexpr uint8_t OFF = 0;
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
private:
 | 
					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 _address;
 | 
				
			||||||
    uint8_t _function = 0;
 | 
					    uint8_t _function = 0;
 | 
				
			||||||
 | 
					    uint8_t _functionmask;
 | 
				
			||||||
    uint8_t _speed = 0;
 | 
					    uint8_t _speed = 0;
 | 
				
			||||||
    
 | 
					    bool _direction = false;
 | 
				
			||||||
    static const unsigned char _pinHighA = PD5;
 | 
					 | 
				
			||||||
    static const unsigned char _pinLowA = PD4;
 | 
					 | 
				
			||||||
    static const unsigned char _pinHighB = PD2;
 | 
					 | 
				
			||||||
    static const unsigned char _pinLowB = PD3;
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    static const uint8_t SEND_COUNT = 2;
 | 
					    static const uint8_t SEND_COUNT = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    uint8_t _protocol = M_DIGITAL;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    uint16_t lastDataPacket = 0;
 | 
					 | 
				
			||||||
    int8_t functionTimer = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    inline static void off();
 | 
					    inline static void off();
 | 
				
			||||||
    void sendBit(const bool bit);
 | 
					    static void sendBit(const bool bit);
 | 
				
			||||||
    void sendAddress();
 | 
					    static void sendAddress(uint8_t address);
 | 
				
			||||||
    void functionClear();
 | 
					    uint16_t packetAddSpeed();
 | 
				
			||||||
 | 
					    uint16_t packetAddDirection();
 | 
				
			||||||
 | 
					    uint16_t packetAddFunction(const uint8_t function);
 | 
				
			||||||
 | 
					    uint16_t assemblePacket();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    static void setOutput(const uint8_t state);
 | 
					    static void setOutput(const uint8_t state);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    Train(const uint8_t address, uint8_t protocol = M_DIGITAL);
 | 
					    Train(const uint8_t address, uint8_t functionmask = 0b1111);
 | 
				
			||||||
    Train();
 | 
					    Train();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    void resendData();
 | 
					    void resendData();
 | 
				
			||||||
| 
						 | 
					@ -50,19 +49,21 @@ public:
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void stop();
 | 
					    void stop();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    bool isActive();
 | 
					    bool isActive() {return _speed || _function;}
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    uint8_t getAddress();
 | 
					    uint8_t getAddress();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    uint16_t getLastPacket();
 | 
					    uint16_t getLastPacket();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    uint8_t getProtocol();
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    void setSpeed(uint8_t speed);
 | 
					    void setSpeed(uint8_t speed);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    uint8_t getSpeed();
 | 
					    uint8_t getSpeed();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void setProtocol(const uint8_t protocol);
 | 
					    void setFunctionMask(uint8_t functionmask) {_functionmask = functionmask;}
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    uint8_t getFunctions();
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    uint8_t getFunctionMask();
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void setAddress(const uint8_t address);
 | 
					    void setAddress(const uint8_t address);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
| 
						 | 
					@ -70,4 +71,6 @@ public:
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    void sendRaw(const uint16_t data);
 | 
					    void sendRaw(const uint16_t data);
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    static void sendRawAddr(const uint16_t address, const uint16_t data);
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										8
									
								
								trains
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								trains
									
										
									
									
									
								
							| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
NUMBER: 0 ID: 01010100 CURRENT SPD: 0
 | 
					NUMBER: 0 ID: 01010100 CURRENT PACKET: 220 SPEED: 0 PROTOCOL: digital
 | 
				
			||||||
NUMBER: 1 ID: 01010000 CURRENT SPD: 0
 | 
					NUMBER: 1 ID: 01010000 CURRENT PACKET: 220 SPEED: 0 PROTOCOL: digital
 | 
				
			||||||
NUMBER: 2 ID: 01000100 CURRENT SPD: 0
 | 
					NUMBER: 2 ID: 01000100 CURRENT PACKET: 237 SPEED: 3 PROTOCOL: digital
 | 
				
			||||||
NUMBER: 3 ID: 00010100 CURRENT SPD: 0
 | 
					NUMBER: 3 ID: 00010100 CURRENT PACKET: 220 SPEED: 0 PROTOCOL: digital
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue