Desktop Station gateway software for mbed
Dependents: DSGatewayMBED_Nucleo DSGatewayMBED_Nucleo_Step128
This library provides to control DCC and Marklin Motorola 2 locomtoives and turnouts via DCC/MM2 Shield. Please check our wiki site(http://desktopstation.net/wiki/).
Diff: DSGatewayMBED.cpp
- Revision:
- 0:96eb8cc345dc
- Child:
- 1:39249e22e9f5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DSGatewayMBED.cpp Sat Jan 17 01:48:50 2015 +0000 @@ -0,0 +1,366 @@ +#include "DSGatewayMBED.h" +#include "mbed.h" + +SPI spiDS(SPI_MOSI, SPI_MISO, SPI_SCK); +DigitalOut cs(D10); + +DSGatewayLib::DSGatewayLib() +{ + + poweron = false; + +} + +void DSGatewayLib::begin() +{ + /* Open SPI */ + + spiDS.format(8, 0); + spiDS.frequency(1000000); + +} + + +DSGatewayLib::~DSGatewayLib() +{ + + SetPower(false); + +} + +bool DSGatewayLib::IsPower() +{ + + return poweron; + +} + + +void DSGatewayLib::clearMessage(unsigned char *inPackets) +{ + for( int i = 0; i < SIZE_PACKET; i++) + { + inPackets[i] = 0; + } +} + +bool DSGatewayLib::sendMessage(unsigned char *inPackets) +{ + byte aReceived[SIZE_PACKET] = {0,0,0,0,0,0,0,0}; + int i; + + cs = 0; + + for( i = 0; i < SIZE_PACKET; i++) + { + aReceived[i] = spiDS.write(inPackets[i]); + wait_us(10); + } + + cs = 1; + + + /* 遅延 */ + wait_ms(30); + + /* Check for receiving */ + if((aReceived[1] & 0xF0) == CMD_OK) + { + return true; + } + else if((aReceived[1] & 0xF0) == CMD_WAIT) + { + return true; + } + else + { + return false; + } +} + +bool DSGatewayLib::exchangeMessage(unsigned char *inPackets, word timeout) +{ + //unsigned char aTemp[SIZE_PACKET]; + + bool aReturnOk = sendMessage(inPackets); + + /* + unsigned long aTime = millis(); + + // response; + + while ((millis() < aTime + timeout) || (!aReturnOk)) { + aTemp[0] = CMD_WAIT | 0b0010; + aTemp[1] = aTemp[0]; + + delay(20); + + if (sendMessage(aTemp) == true) { + return true; + } + } + + if (DEBUG && !aReturnOk) { + Serial.println(F("!!! Communication Error(Timeout, Command etc)")); + } + */ + + return aReturnOk; +} + + +bool DSGatewayLib::SetPower(bool power) +{ + unsigned char aPacktes[SIZE_PACKET]; + + clearMessage(aPacktes); + + if (power) { + aPacktes[0] = CMD_PWR_ON | 0x02; + aPacktes[1] = aPacktes[0];//CRC + poweron = true; + + } + else + { + aPacktes[0] = CMD_PWR_OFF | 0x02; + aPacktes[1] = aPacktes[0];//CRC + poweron = false; + } + + return exchangeMessage(aPacktes, TIME_REPLY); +} + +bool DSGatewayLib::SetPowerEx(bool power) +{ + unsigned char aPacktes[SIZE_PACKET]; + + clearMessage(aPacktes); + + if (power) { + aPacktes[0] = CMD_PWR_ON | 0x03; + aPacktes[1] = 3;//Extend command (DCC128 and MM2-28step) + aPacktes[2] = generateCRC(aPacktes, 2); + + } + else + { + aPacktes[0] = CMD_PWR_OFF | 0x02; + aPacktes[1] = aPacktes[0];//CRC + } + + + + return exchangeMessage(aPacktes, TIME_REPLY); +} + +bool DSGatewayLib::SetLocoSpeed(word address, int inSpeed) +{ + unsigned char aPacktes[SIZE_PACKET]; + + clearMessage(aPacktes); + + aPacktes[0] = CMD_SPEED | 0x06; + aPacktes[1] = lowByte(address); + aPacktes[2] = highByte(address); + aPacktes[3] = lowByte(inSpeed); + aPacktes[4] = highByte(inSpeed); + aPacktes[5] = generateCRC(aPacktes, 5); + + return exchangeMessage(aPacktes, TIME_REPLY); +} + + +bool DSGatewayLib::SetLocoSpeedEx(word address, int inSpeed, int inProtcol) +{ + unsigned char aPacktes[SIZE_PACKET]; + + clearMessage(aPacktes); + + aPacktes[0] = CMD_SPEED | 0x07; + aPacktes[1] = lowByte(address); + aPacktes[2] = highByte(address); + aPacktes[3] = lowByte(inSpeed); + aPacktes[4] = highByte(inSpeed); + aPacktes[5] = inProtcol; + aPacktes[6] = generateCRC(aPacktes, 6); + + return exchangeMessage(aPacktes, TIME_REPLY); +} + +bool DSGatewayLib::SetLocoFunction(word address, unsigned char inFunction, unsigned char inPower) +{ + unsigned char aPacktes[SIZE_PACKET]; + + clearMessage(aPacktes); + + aPacktes[0] = CMD_FUNCTION | 0x06; + aPacktes[1] = lowByte(address); + aPacktes[2] = highByte(address); + aPacktes[3] = inFunction + 1; //1はじまり + aPacktes[4] = inPower; + aPacktes[5] = generateCRC(aPacktes, 5); + + return exchangeMessage(aPacktes, TIME_REPLY); +} + + +bool DSGatewayLib::SetLocoDirection(word address, unsigned char inDirection) +{ + unsigned char aPacktes[SIZE_PACKET]; + + clearMessage(aPacktes); + + aPacktes[0] = CMD_DIRECTION | 0x05; + aPacktes[1] = lowByte(address); + aPacktes[2] = highByte(address); + aPacktes[3] = inDirection - 1;// FWD 1->0, REV:2->1 + aPacktes[4] = generateCRC(aPacktes, 4); + + return exchangeMessage(aPacktes, TIME_REPLY); +} + +/* +bool DSGatewayLib::SetTurnout(word address, bool straight) +{ + byte aSwitch = straight == true ? (byte)1 : (byte)0; + + return SetTurnout(address, aSwitch); +}*/ + +bool DSGatewayLib::SetTurnout(word address, byte inSwitch) +{ + unsigned char aPacktes[SIZE_PACKET]; + + clearMessage(aPacktes); + + aPacktes[0] = CMD_ACCESSORY | 0x06; + aPacktes[1] = lowByte(address); + aPacktes[2] = highByte(address); + aPacktes[3] = 0x00; // position + aPacktes[4] = convertAcc_MMDCC(address, inSwitch);// 0: Straight, 1: diverging from DS 1:straight, 0: diverging + aPacktes[5] = generateCRC(aPacktes, 5); + + return exchangeMessage(aPacktes, TIME_REPLY); +} + +byte DSGatewayLib::convertAcc_MMDCC(word address, byte inSwitch) +{ + byte aReturn = inSwitch; + + switch( GetLocIDProtocol(address >> 8)) + { + case ADDR_ACC_MM2: + /* 0:Straight, 1: diverging */ + aReturn = (inSwitch == 0) ? 1 : 0; + break; + + case ADDR_ACC_DCC: + /* 1:Straight, 0: diverging */ + aReturn = inSwitch; + break; + + default: + aReturn = inSwitch; + break; + } + + return aReturn; + +} + +word DSGatewayLib::GetLocIDProtocol(byte address) +{ + if( address < 0x04) + { + return ADDR_MM2; + } + else if( (address >= 0x30) && (address <= 0x33)) + { + return ADDR_ACC_MM2; + } + else if( (address >= 0x38) && (address <= 0x3F)) + { + return ADDR_ACC_DCC; + } + else if( (address >= 0x40) && (address <= 0x70)) + { + return ADDR_MFX; + } + else if( (address >= 0xC0) && (address <= 0xFF)) + { + return ADDR_DCC; + } + else + { + return 0; + } +} + +bool DSGatewayLib::WriteConfig(word address, word number, byte value) +{ + unsigned char aPacktes[SIZE_PACKET]; + + word aOffsetCVNo; + + if( address >= ADDR_DCC) + { + aOffsetCVNo = number; + } + else + { + aOffsetCVNo = number | 0x8000; + } + + clearMessage(aPacktes); + + aPacktes[0] = CMD_CVWRITE | 0x05; + aPacktes[1] = lowByte(aOffsetCVNo); + aPacktes[2] = highByte(aOffsetCVNo); + aPacktes[3] = value; + aPacktes[4] = generateCRC(aPacktes, 4); + + return exchangeMessage(aPacktes, TIME_REPLY); +} + +bool DSGatewayLib::ReadConfig(word address, word number, byte *value) +{ + unsigned char aPacktes[SIZE_PACKET]; + + clearMessage(aPacktes); + + aPacktes[0] = CMD_CVREAD || 0x04; + aPacktes[1] = lowByte(number); + aPacktes[2] = highByte(number); + aPacktes[3] = generateCRC(aPacktes, 3); + + *value = 0; + + return exchangeMessage(aPacktes, TIME_REPLY); +} + + +unsigned char DSGatewayLib::generateCRC(unsigned char *inPackets, unsigned char inLen) +{ + unsigned char aCRC = inPackets[0]; + + for( int i = 1; i < inLen; i++) + { + aCRC = aCRC ^ inPackets[i]; + } + + return aCRC; + +} + +byte lowByte(short int low) { + byte bytelow = 0; + bytelow = (low & 0xFF); + return bytelow; +} + +byte highByte(short int high) { + byte bytehigh = 0; + bytehigh = ((high >> 8) & 0xFF); + return bytehigh; +} \ No newline at end of file