From: <jim...@us...> - 2013-04-07 16:03:38
|
Revision: 3142 http://sourceforge.net/p/openlcb/svn/3142 Author: jimkueneman626 Date: 2013-04-07 16:03:34 +0000 (Sun, 07 Apr 2013) Log Message: ----------- Lots of updates on the NCE Bridge Code with library bug fixes Modified Paths: -------------- trunk/prototypes/mikroPascal/Library/CANBus/CANStorage.mpas trunk/prototypes/mikroPascal/Library/NCE/NMRAnetNceBridge.mpas trunk/prototypes/mikroPascal/Library/NCE/NMRAnetNceBridgeDefines.mpas trunk/prototypes/mikroPascal/Library/NMRAnet/NMRAnetDefines.mpas trunk/prototypes/mikroPascal/Library/NMRAnet/NMRAnetNode.mpas trunk/prototypes/mikroPascal/Library/NMRAnet/NMRAnetStateMachine.mpas trunk/prototypes/mikroPascal/Library/Xpressnet/NMRAnetXpressnet.mpas trunk/prototypes/mikroPascal/Library/Xpressnet/NMRAnetXpressnetDefines.mpas trunk/prototypes/mikroPascal/Library/dsPIC33F/dsPIC33_CAN.mpas trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/NMRAnetAppCallbacks.mpas trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/NMRAnetAppDefines.mpas trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/Options.inc trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/dsPIC33EP_NMRABusCommandStation.hex trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/dsPIC33EP_NMRABusCommandStation.mppds trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/dsPIC33EP_NMRAnetCommandStation.mpas trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/NMRAnetAppCallbacks.mpas trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/dsPIC33EP_NMRABusCommandStation.mppds trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/MCU_Setup_dsPIC33EP64GP502.mpas trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/NMRAnetAppCallbacks.mpas trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/NMRAnetAppDefines.mpas trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/Options.inc trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/dsPIC33EP_NMRABusNceBridge.hex trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/dsPIC33EP_NMRABusNceBridge.mpas trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/dsPIC33EP_NMRABusNceBridge.mppds trunk/prototypes/mikroPascal/dsPIC33EP_XpressnetBridge/MCU_Setup_dsPIC33EP64GP502.mpas trunk/prototypes/mikroPascal/dsPIC33EP_XpressnetBridge/NMRAnetAppCallbacks.mpas trunk/prototypes/mikroPascal/dsPIC33EP_XpressnetBridge/NMRAnetAppDefines.mpas trunk/prototypes/mikroPascal/dsPIC33EP_XpressnetBridge/NMRAnetXpressnetAdapter.xml trunk/prototypes/mikroPascal/dsPIC33EP_XpressnetBridge/NMRAnetXpressnetDevice.xml trunk/prototypes/mikroPascal/dsPIC33EP_XpressnetBridge/dsPIC33EP_NMRABusXpressnet.hex trunk/prototypes/mikroPascal/dsPIC33EP_XpressnetBridge/dsPIC33EP_NMRABusXpressnet.mpas trunk/prototypes/mikroPascal/dsPIC33EP_XpressnetBridge/dsPIC33EP_NMRABusXpressnet.mppds trunk/prototypes/mikroPascal/dsPIC33FJ_Visual TFT_BasicThrottle/Throttle_Code/mikroPascal PRO for dsPIC/MCU_Setup_dsPIC33FJ256GP710A.mpas trunk/prototypes/mikroPascal/dsPIC33FJ_Visual TFT_BasicThrottle/Throttle_Code/mikroPascal PRO for dsPIC/NMRAnetAppCallbacks.mpas trunk/prototypes/mikroPascal/dsPIC33FJ_Visual TFT_BasicThrottle/Throttle_Code/mikroPascal PRO for dsPIC/Throttle.hex trunk/prototypes/mikroPascal/dsPIC33FJ_Visual TFT_BasicThrottle/Throttle_Code/mikroPascal PRO for dsPIC/Throttle.mppds Added Paths: ----------- trunk/prototypes/mikroPascal/Library/dsPIC33F/dsPIC33_Traps.mpas trunk/prototypes/mikroPascal/State Diagrams/DatagramStatemachineReceive.fsm trunk/prototypes/mikroPascal/State Diagrams/DatagramStatemachineReceive.pdf trunk/prototypes/mikroPascal/State Diagrams/NceBridge.fsm trunk/prototypes/mikroPascal/State Diagrams/NceBridge.pdf trunk/prototypes/mikroPascal/State Diagrams/Xpressnet.fsm trunk/prototypes/mikroPascal/State Diagrams/Xpressnet.pdf trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/NMRAnetNceAdapter.xml trunk/prototypes/mikroPascal/dsPIC33EP_NceBridge/NMRAnetNceDevice.xml Modified: trunk/prototypes/mikroPascal/Library/CANBus/CANStorage.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/CANBus/CANStorage.mpas 2013-04-07 06:53:18 UTC (rev 3141) +++ trunk/prototypes/mikroPascal/Library/CANBus/CANStorage.mpas 2013-04-07 16:03:34 UTC (rev 3142) @@ -97,6 +97,9 @@ function CANStorage_NextHighPriorityToSend: PCANBuffer; // ***************************************************************************** +procedure LockCANInterrupt; external; +procedure UnLockCANInterrupt; external; + var CAN_Engine: TCAN_Engine; @@ -126,6 +129,7 @@ procedure CANStorage_FlushBuffers(AliasID: Word); begin + LockCANInterrupt; if AliasID = 0 then begin CAN_Engine.TX_CANBuffer.State := 0; @@ -142,7 +146,8 @@ CAN_Engine.TX_AddressedErrorBuffer.State := 0; if CAN_Engine.TX_DatagramRejected.ID and MASK_SOURCE_ALIAS = AliasID then CAN_Engine.TX_DatagramRejected.State := 0; - end + end; + UnLockCANInterrupt end; function CANStorage_NextToSend: PCANBuffer; Modified: trunk/prototypes/mikroPascal/Library/NCE/NMRAnetNceBridge.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NCE/NMRAnetNceBridge.mpas 2013-04-07 06:53:18 UTC (rev 3141) +++ trunk/prototypes/mikroPascal/Library/NCE/NMRAnetNceBridge.mpas 2013-04-07 16:03:34 UTC (rev 3142) @@ -19,8 +19,8 @@ unit NMRAnetNceBridge; {.$DEFINE DEBUG_MAIN_STATEMACHINE} -{$DEFINE TRACE_XPRESSNET_MESSAGES} + uses NMRAnetStateMachine, NMRAnetCANReceive, @@ -43,7 +43,7 @@ implementation -function InsertHiBitParity(DataByte: Byte): Byte; forward; +//function InsertHiBitParity(DataByte: Byte): Byte; forward; procedure WriteNceBusByte(DataByte: Word; SetAddressBit: Boolean; TxReg: ^Word; StatusReg: ^Word); forward; procedure NceBus_HandleDeviceInstruction(NceBusMessage: PNceBusMessage; iDevice: Byte); forward; procedure SendNceBusMessage(NceBusMessage: PNceBusMessage; Command: Byte; iDevice: Byte); forward; @@ -81,12 +81,13 @@ // // Description: // Returns the next installed Device index on the bus after the passed index. -// If there are no Devices installed it returns 0 +// If there are no Devices installed it returns ID_NO_DEVICE // // ***************************************************************************** function NextAvailableDevice(iDevice: Byte): Byte; var i: Integer; + Device: pDevice; begin Result := ID_NO_DEVICE; @@ -98,8 +99,10 @@ Inc(i); if i > ID_MAX_DEVICE then i := ID_MIN_DEVICE; - if NceBusStateMachineInfo.DeviceList[i].State and XDS_NceBus_DEVICE_ACTIVE = XDS_NceBus_DEVICE_ACTIVE then - // if not Device_InServiceMode(i) then + + Device := @NceBusStateMachineInfo.DeviceList[i]; + if Device^.State and XDS_NCEBUS_DEVICE_ACTIVE = XDS_NCEBUS_DEVICE_ACTIVE then + if Device^.Node^.State and NS_PERMITTED = NS_PERMITTED then // If it is active then the Node MUST be valid// if not Device_InServiceMode(i) then begin Result := i; Exit @@ -125,12 +128,14 @@ function FirstActiveDevice: Byte; var i: Integer; + Device: PDevice; begin Result := ID_NO_DEVICE; for i := ID_MIN_DEVICE to ID_MAX_DEVICE do begin - if NceBusStateMachineInfo.DeviceList[i].State and XDS_NceBus_DEVICE_ACTIVE = XDS_NceBus_DEVICE_ACTIVE then - // if not Device_InServiceMode(i) then + Device := @NceBusStateMachineInfo.DeviceList[i]; + if Device^.State and XDS_NceBus_DEVICE_ACTIVE = XDS_NceBus_DEVICE_ACTIVE then + if Device^.Node^.State and NS_PERMITTED = NS_PERMITTED then begin Result := i; Exit @@ -144,32 +149,15 @@ begin while (URXDA_U2STA_bit = 1) do Temp := U2RXREG; // Flush the RX Buffer U2RXIF_Bit := 0; // Clear the interrupt flag to receive the next byte - NceBusStateMachineInfo.RS485.NceBusData.StateMachineIndex := STATE_RS485_READ_HEADER_BYTE; // Reset the RS485 RX statemachine + NceBusStateMachineInfo.RS485.NceBusData.StateMachineIndex := STATE_RS485_READ_CAB_BYTE_1; // Reset the RS485 RX statemachine NceBusStateMachineInfo.RS485.Done := False; - NceBusStateMachineInfo.RS485.XORFailed := False; end; -procedure SendTransferErrorMessage(Device: Byte); -begin - NceBus_RS485_Select := 1; - WriteNceBusByte(CALLBYTE_TRANSFER_ERRORS or Device, True, @U2TXREG, @U2STA); // 011AAAAA - WriteNceBusByte($80, False, @U2TXREG, @U2STA); // 10000000 - WriteNceBusByte($E1, False, @U2TXREG, @U2STA); // 11100001 - NceBus_RS485_Select := 0; -end; - -procedure SendAckRequestMessage(Device: Byte); -begin - NceBus_RS485_Select := 1; // Select the 485 chip to transmit mode - WriteNceBusByte( InsertHiBitParity(CALLBYTE_REQUEST_ACK_FROM_DEVICE or Device), True, @U2TXREG, @U2STA); // 000AAAAA - NceBus_RS485_Select := 0; -end; - procedure SendInquiryMessage(Device: Byte); begin - NceBus_RS485_Select := 1; // Select the 485 chip to transmit mode - WriteNceBusByte( InsertHiBitParity(CALLBYTE_INQUIRY or Device), True, @U2TXREG, @U2STA); // Write to the Bus for a query - NceBus_RS485_Select := 0; // Select the 485 chip to receive mode ASAP + NceBus_RS485_Select := 1; // Select the 485 chip to transmit mode + WriteNceBusByte(NCEBUS_PING or Device, True, @U2TXREG, @U2STA); // Write to the Bus for a query + NceBus_RS485_Select := 0; // Select the 485 chip to receive mode ASAP end; // ***************************************************************************** @@ -194,24 +182,29 @@ // Count up to the hung time then freeze. Once Hung it is hung until the next // device ID is queried and it is reset - if NceBusStateMachineInfo.WatchdogCount < NceBus_BUS_HUNG_COUNT then + if NceBusStateMachineInfo.WatchdogCount < NCEBUS_BUS_HUNG_COUNT then Inc(NceBusStateMachineInfo.WatchdogCount); - if NceBusStateMachineInfo.Bridge.WatchdogCount < NceBus_OLCB_BUS_TIMEOUT then + if NceBusStateMachineInfo.Bridge.WatchdogCount < NCEBUS_OLCB_BUS_TIMEOUT then Inc(NceBusStateMachineInfo.Bridge.WatchdogCount) end; procedure DetectDeviceResponse(Device: PDevice; DetectedState, NoDetectedState: Word); +var + NodeData: PNceBusDeviceVolatileData; begin - if (U2STA.RIDLE = 0) or (U2STA.URXDA = 1) then // Did we detect a Device starting to transmit on the UART? + if (U2STA.RIDLE = 0) or (U2STA.URXDA = 1) or (NceBusStateMachineInfo.RS485.Done) then // Did we detect a Device starting to transmit on the UART? begin // Yes so wait for it to be received NceBusStateMachineInfo.WatchdogCount := 0; // Reset the Watchdog for a hung bus NceBusStateMachineInfo.iState := DetectedState; end else - begin // No so set it device inactive and exit to the next device - NceBusStateMachineInfo.iState := NoDetectedState; + begin // If a Device has nothing to say we can fall into this branch it is not a signal // the device is has disappeared + NodeData := GetDeviceData(Device^.Node); + NodeData^.DeviceID := nil; + Device^.State := Device^.State and not XDS_NCEBUS_DEVICE_ACTIVE or XDS_NCEBUS_DEVICE_INACTIVE; + NceBusStateMachineInfo.iState := NoDetectedState; end; end; @@ -240,57 +233,66 @@ i: Integer; begin case NceBusBuffer^.RS485.NceBusData.StateMachineIndex of - STATE_RS485_READ_HEADER_BYTE : + STATE_RS485_READ_CAB_BYTE_1 : begin - NceBusBuffer^.RS485.NceBusData.DataCount := ReceivedByte and $0F; // Use only the lower nibble for the count - NceBusBuffer^.RS485.NceBusData.Instruction := ReceivedByte and $F0; // Strip off the Data Count in the lower nibble - NceBusBuffer^.RS485.NceBusData.StateMachineIndexDataByte := 0; - if NceBusBuffer^.RS485.NceBusData.DataCount = 0 then // If the count is 0 then jump to the XOR byte state - NceBusBuffer^.RS485.NceBusData.StateMachineIndex := STATE_RS485_READ_XOR_BYTE - else - Inc(NceBusBuffer^.RS485.NceBusData.StateMachineIndex) + NceBusBuffer^.RS485.NceBusData.DataCount := 2; // Per the Spec + NceBusBuffer^.RS485.NceBusData.Bytes[0] := ReceivedByte; + Inc(NceBusBuffer^.RS485.NceBusData.StateMachineIndex) end; - STATE_RS485_READ_MESSAGE_BYTE : + STATE_RS485_READ_CAB_BYTE_2 : begin - NceBusBuffer^.RS485.NceBusData.Bytes[NceBusBuffer^.RS485.NceBusData.StateMachineIndexDataByte] := ReceivedByte; - Inc(NceBusBuffer^.RS485.NceBusData.StateMachineIndexDataByte); - if NceBusBuffer^.RS485.NceBusData.StateMachineIndexDataByte >= NceBusBuffer^.RS485.NceBusData.DataCount then // Test to see if we are done reading - begin - Inc(NceBusBuffer^.RS485.NceBusData.StateMachineIndex) - end; + NceBusBuffer^.RS485.NceBusData.Bytes[1] := ReceivedByte; + NceBusBuffer^.RS485.Done := True; // Must be cleared in the main program + Inc(NceBusBuffer^.RS485.NceBusData.StateMachineIndex) end; - STATE_RS485_READ_XOR_BYTE : - begin - Error := NceBusBuffer^.RS485.NceBusData.DataCount or NceBusBuffer^.RS485.NceBusData.Instruction; // Reconstruct the Header Byte - for i := 0 to NceBusBuffer^.RS485.NceBusData.DataCount - 1 do - Error := Error xor NceBusBuffer^.RS485.NceBusData.Bytes[i]; - if Error <> ReceivedByte then // This is the implementation of the STATE_RECEIVEDEVICEMESSAGE for the NceBus StateMachine - NceBusStateMachineInfo.RS485.XORFailed := True; // Must be cleared in the main program - NceBusStateMachineInfo.RS485.Done := True; // Must be cleared in the main program - Inc(NceBusBuffer^.RS485.NceBusData.StateMachineIndex) // We are full move to Full State - end; STATE_RS485_FULL : begin // Spin here until the system resets the statemachine end; end end; - +// ***************************************************************************** +// +// procedure NceBusStateMachine_Process +// +// Parameters: +// Node: The physical Node of the Bridge +// Returns: +// None +// +// Description: +// There is no reason to send Device Nodes as internally the statemachine +// checks the Device Nodes for the Permitted state to use them. +// +// ***************************************************************************** procedure NceBusStateMachine_Process(Node: PNMRAnetNode); var Temp: Word; Device: PDevice; NodeData: PNceBusDeviceVolatileData; begin - if NMRAnetNode_TestStateFlag(Node, NS_INITIALIZED) then + if NMRAnetNode_TestStateFlag(Node, NS_PERMITTED) then begin case NceBusStateMachineInfo.iState of STATE_DISCOVERDEVICES : begin {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_DISCOVERDEVICES'+LF);{$ENDIF} NceBusStateMachineInfo.Discovering := True; - NceBusStateMachineInfo.iActiveDevice := 0; + NceBusStateMachineInfo.iActiveDevice := 1; + NceBusStateMachineInfo.iState := STATE_SENDDEVICESYNC; + end; + STATE_SENDDEVICESYNC : + begin + {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_SENDDEVICESYNC'+LF);{$ENDIF} + LATB4_bit := 1; // Scope Sync on the NCE Sync + + PrepareUARTReceiver; + Delay_us(10000); + SendInquiryMessage(0); + Delay_us(4000); // A bit of a hack to save another timer. Just wait for the Xpressent spec timeout then check if a UART transfer has started NceBusStateMachineInfo.iState := STATE_DISCOVERNEXTDEVICE; + + LATB4_bit := 0; end; STATE_DISCOVERNEXTDEVICE : begin @@ -310,7 +312,7 @@ {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_SENDDEVICEINQUIRY'+LF);{$ENDIF} PrepareUARTReceiver; SendInquiryMessage(NceBusStateMachineInfo.iActiveDevice); - Delay_us(120); // A bit of a hack to save another timer. Just wait for the Xpressent spec timeout then check if a UART transfer has started + Delay_us(4000); // A bit of a hack to save another timer. Just wait for the Xpressent spec timeout then check if a UART transfer has started Device := @NceBusStateMachineInfo.DeviceList[NceBusStateMachineInfo.iActiveDevice]; DetectDeviceResponse(Device, STATE_WAITFORDEVICEMESSAGE, STATE_TESTFORDISCOVERYMODE); end; @@ -318,29 +320,20 @@ begin {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_WAITFORDEVICEMESSAGE'+LF);{$ENDIF} if NceBusStateMachineInfo.RS485.Done then - NceBusStateMachineInfo.iState := STATE_RECEIVEDEVICEMESSAGE; - if NceBusStateMachineInfo.WatchdogCount > NceBus_BUS_HUNG_COUNT then + NceBusStateMachineInfo.iState := STATE_HANDLEMESSAGE; + if NceBusStateMachineInfo.WatchdogCount > NCEBUS_BUS_HUNG_COUNT then NceBusStateMachineInfo.iState := STATE_TESTFORDISCOVERYMODE; end; - STATE_RECEIVEDEVICEMESSAGE : - begin - {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_RECEIVEDEVICEMESSAGE'+LF);{$ENDIF} - if NceBusStateMachineInfo.RS485.XORFailed then - NceBusStateMachineInfo.iState := STATE_SENDDEVICEERROR - else - NceBusStateMachineInfo.iState := STATE_HANDLEMESSAGE - end; STATE_HANDLEMESSAGE : begin {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_HANDLEMESSAGE'+LF);{$ENDIF} Device := @NceBusStateMachineInfo.DeviceList[NceBusStateMachineInfo.iActiveDevice]; if Device^.Node = nil then // Did we find a new NceBus Device? - begin - Device^.State := Device^.State or XDS_NceBus_DEVICE_ACTIVE; - Device^.Node := NMRAnetNode_Allocate; // Link the Node to the Device - NodeData := GetDeviceData(Device^.Node); - NodeData^.DeviceID := NceBusStateMachineInfo.iActiveDevice; // Link the Device to the Node - end; + Device^.Node := NMRAnetNode_Allocate; + NodeData := GetDeviceData(Device^.Node); + Device^.State := Device^.State or XDS_NCEBUS_DEVICE_ACTIVE and not XDS_NCEBUS_DEVICE_INACTIVE; + NodeData^.DeviceID := NceBusStateMachineInfo.iActiveDevice; // Link the Device to the Node + NceBusStateMachineInfo.Bridge.RequiresReply := False; // The HandleDeviceInstruction call will set up the OlcbBridge info if needed. NceBusStateMachineInfo.Bridge.ReplyRead := False; NceBusStateMachineInfo.Bridge.WatchdogCount := 0; @@ -361,40 +354,28 @@ {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_WAIT_FOR_OLCB_REPLY'+LF);{$ENDIF} if NceBusStateMachineInfo.Bridge.ReplyRead then NceBusStateMachineInfo.iState := STATE_SEND_INSTRUCTION_REPLY; - if NceBusStateMachineInfo.Bridge.WatchdogCount > NceBus_OLCB_BUS_TIMEOUT then + if NceBusStateMachineInfo.Bridge.WatchdogCount > NCEBUS_OLCB_BUS_TIMEOUT then NceBusStateMachineInfo.iState := STATE_TESTFORDISCOVERYMODE; end; STATE_SEND_INSTRUCTION_REPLY : begin {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_SEND_INSTRUCTION_REPLY'+LF);{$ENDIF} // The NceBus message was created in the NMRAnetAppCallbacks.mpas - SendNceBusMessage(@NceBusStateMachineInfo.Bridge.NceBusMessage, CALLBYTE_RESPONSE, NceBusStateMachineInfo.iActiveDevice); + // SendNceBusMessage(@NceBusStateMachineInfo.Bridge.NceBusMessage, CALLBYTE_RESPONSE, NceBusStateMachineInfo.iActiveDevice); NceBusStateMachineInfo.iState := STATE_TESTFORDISCOVERYMODE; end; - STATE_SENDDEVICEERROR : - begin - {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_SENDDEVICEERROR'+LF);{$ENDIF} - PrepareUARTReceiver; - SendTransferErrorMessage(NceBusStateMachineInfo.iActiveDevice); - SendAckRequestMessage(NceBusStateMachineInfo.iActiveDevice); - Delay_us(120); // A bit of a hack to save another timer. Just wait for the Xpressent spec timeout then check if a UART transfer has started - Device := @NceBusStateMachineInfo.DeviceList[NceBusStateMachineInfo.iActiveDevice]; - DetectDeviceResponse(Device, STATE_WAITFORACKRESPONSE, STATE_TESTFORDISCOVERYMODE); - end; STATE_WAITFORACKRESPONSE : // Error detected earlier so sending an ACK to see if it is really broken begin {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_WAITFORACKRESPONSE'+LF);{$ENDIF} if NceBusStateMachineInfo.RS485.Done then NceBusStateMachineInfo.iState := STATE_DEVICEACKRESPONSE; - if NceBusStateMachineInfo.WatchdogCount > NceBus_BUS_HUNG_COUNT then + if NceBusStateMachineInfo.WatchdogCount > NCEBUS_BUS_HUNG_COUNT then NceBusStateMachineInfo.iState := STATE_TESTFORDISCOVERYMODE; end; STATE_DEVICEACKRESPONSE : begin {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_DEVICEACKRESPONSE'+LF);{$ENDIF} Device := @NceBusStateMachineInfo.DeviceList[NceBusStateMachineInfo.iActiveDevice]; - if NceBusStateMachineInfo.RS485.XORFailed then - Device^.State := Device^.State and not XDS_NceBus_DEVICE_ACTIVE or XDS_NceBus_DEVICE_INACTIVE; NceBusStateMachineInfo.iState := STATE_TESTFORDISCOVERYMODE end; STATE_TESTFORDISCOVERYMODE : @@ -410,15 +391,12 @@ {$IFDEF DEBUG_MAIN_STATEMACHINE} UART1_Write_Text('STATE_ENUMERATEACTIVEDEVICES'+LF);{$ENDIF} NceBusStateMachineInfo.iActiveDevice := NextAvailableDevice(NceBusStateMachineInfo.iActiveDevice); if NceBusStateMachineInfo.iActiveDevice <> ID_NO_DEVICE then - begin - NceBusStateMachineInfo.iState := STATE_SENDDEVICEINQUIRY - end; + NceBusStateMachineInfo.iState := STATE_SENDDEVICESYNC; if NceBusStateMachineInfo.DiscoveryCount >= REDISCOVERY_TIME then NceBusStateMachineInfo.iState := STATE_DISCOVERDEVICES - end; - end; + end; end end; @@ -444,15 +422,15 @@ i: Integer; XorError: Byte; begin - if MessageInfo^.CallByte <> 0 then - WriteNceBusByte(MessageInfo^.CallByte, True, TxReg, StatusReg); // Send the Call Byte if <> 0 - WriteNceBusByte(MessageInfo^.HeaderByte, False, TxReg, StatusReg); // Send the Header Byte - XorError := MessageInfo^.HeaderByte; // Start Calculating the Error Byte + if MessageInfo^.CabID <> 0 then + WriteNceBusByte(MessageInfo^.CabID, True, TxReg, StatusReg); // Send the Call Byte if <> 0 + //WriteNceBusByte(MessageInfo^.HeaderByte, False, TxReg, StatusReg); // Send the Header Byte + //XorError := MessageInfo^.HeaderByte; // Start Calculating the Error Byte for i := 0 to MessageInfo^.DataCount - 1 do - begin - WriteNceBusByte(MessageInfo^.Bytes[i], False, TxReg, StatusReg); - XorError := XorError xor MessageInfo^.Bytes[i] - end; + //begin + //WriteNceBusByte(MessageInfo^.Bytes[i], False, TxReg, StatusReg); + // XorError := XorError xor MessageInfo^.Bytes[i] + //end; WriteNceBusByte(XorError, False, TxReg, StatusReg) end; @@ -475,13 +453,13 @@ begin OldMode := NceBus_RS485_Select; NceBus_RS485_Select := 1; // Select the 485 chip to transmit mode - NceBusMessage^.CallByte := InsertHiBitParity(Command or Byte( iDevice)); // Send Message to the NceBus UART + NceBusMessage^.CabID := Command or Byte( iDevice); // Send Message to the NceBus UART WriteNceBusMessage(NceBusMessage, @U2TXREG, @U2STA); Delay_us(200); NceBus_RS485_Select := OldMode end else begin - NceBusMessage^.CallByte := 0; // Very Important to strip the CallByte from the PC Packet, Send to the PC UART + NceBusMessage^.CabID := 0; // Very Important to strip the CallByte from the PC Packet, Send to the PC UART WriteNceBusMessage(NceBusMessage, @U1TXREG, @U1STA); end; end; @@ -508,63 +486,8 @@ SendNceBusMessage(NceBusMessage, Command, i); end end; - // ***************************************************************************** // -// procedure Send_InstructionNotSupported(iDevice: Byte); -// -// Parameters: -// iDevice: ID of the NceBus Device to send the message to -// -// Description: -// Implements "2.1.10 Instruction not supported by command station" in the NceBus spec -// -// ***************************************************************************** -procedure Send_InstructionNotSupported(iDevice: Byte); -var - NceBusMessage: TNceBusMessage; -begin - NceBusMessage.HeaderByte := %01100001; // $61 - NceBusMessage.Bytes[0] := %10000010; // $82 - NceBusMessage.DataCount := 1; - SendNceBusMessage(@NceBusMessage, CALLBYTE_RESPONSE, iDevice); -end; - -// ***************************************************************************** -// -// function InsertHiBitParity(DataByte: Byte): Byte; -// -// Parameters: -// DataByte: Byte to count '1's in -// -// Returns: -// DataByte with the parity bit (inclusive) in the MSB -// -// Description: -// Adds the parity bit to B7. It is an inclusive parity only on -// address bytes -// -// ***************************************************************************** -function InsertHiBitParity(DataByte: Byte): Byte; -begin - Result := 0; - if DataByte.B0 then Inc(Result); - if DataByte.B1 then Inc(Result); - if DataByte.B2 then Inc(Result); - if DataByte.B3 then Inc(Result); - if DataByte.B4 then Inc(Result); - if DataByte.B5 then Inc(Result); - if DataByte.B6 then Inc(Result); - // This is inclusive parity so if there are an even number of 1's (mod 2 = 0) then - // adding the parity bit will make the number of 1's odd - if Result mod 2 <> 0 then - Result := DataByte or %10000000 - else - Result := DataByte -end; - -// ***************************************************************************** -// // procedure WriteNceBusByte(DataByte: Word; SetAddressBit: Boolean); // // Parameters: @@ -581,1843 +504,13 @@ // ***************************************************************************** procedure WriteNceBusByte(DataByte: Word; SetAddressBit: Boolean; TxReg: ^Word; StatusReg: ^Word); begin - {$IFNDEF DISABLE_NceBus_UART_WRITE} - if SetAddressBit then - DataByte := DataByte or $0100 - else - DataByte := DataByte and $00FF; - TxReg^ := DataByte; StatusReg^.UTXEN := 1; // Force the Register in to the TSR so the Idle check is not "too fast" to start while StatusReg^.TRMT = 1 do; // Wait for the UART to start transmitting while StatusReg^.TRMT = 0 do; // Wait for the UART to finsh transmitting to make sure the ENceBus timing is met - {$ENDIF} end; - // ***************************************************************************** -// -// procedure ResumeOperationsRequest; -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// -// Device Request : Paragraph 2.2.2 -// Command Station Response : Paragraph 2.1.4.1 -// Status: -// Complete 1/29/2011 -// ***************************************************************************** -procedure ResumeOperationsRequest(NceBusMessage: PNceBusMessage); -begin - - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('ResumeOperationsRequest'+LF);{$ENDIF} - -//TODO.... - -// ServiceMode_End; // Any kind of Service Mode in process is finshed -// SPI_UpdateDCC_Outputs; - -// NMRA_DCC_ResetTransmitter(@Track); // Reset the transmitters so we are not in the middle of an unknown message - // NMRA_DCC_ResetTransmitter(@Accessory); -// NMRA_DCC_ResetTransmitter(@Programming); - - // CommandStation.Flags.COMMANDSTATION_FLAGS_EMERGENCY_SHUTDOWN_BIT := 0; // Flag the Command Station is not in E-Shutdown or E-Stop - // CommandStation.Flags.COMMANDSTATION_FLAGS_EMERGENCY_STOP_BIT := 0; - - NceBusMessage^.HeaderByte := %01100001; // $61; Reuse the passed NceBus Message, enviromentally friendly save the bytes! - NceBusMessage^.Bytes[0] := %00000001; // $01 - NceBusMessage^.DataCount := 1; - Broadcast_NceBusMessage(NceBusMessage, CALLBYTE_BROADCAST); - Broadcast_NceBusMessage(NceBusMessage, CALLBYTE_BROADCAST); -end; - -// ***************************************************************************** -// -// procedure StopOperationsRequest(NceBusMessage: PNceBusMessage); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// -// Device Request : Paragraph 2.2.3 -// Command Station Response : Paragraph 2.1.4.2 -// Status: -// Complete 1/29/2011 -// ***************************************************************************** -procedure StopOperationsRequest(NceBusMessage: PNceBusMessage); -begin - - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('StopOperationsRequest'+LF);{$ENDIF} - -// TODO.... - -// CommandStation.Flags.COMMANDSTATION_FLAGS_EMERGENCY_SHUTDOWN_BIT := 1; // Flag the Command Station is in E-Shutdown - // ServiceMode_End; // Any kind of Service Mode in process is finshed -// SPI_UpdateDCC_Outputs; - - NceBusMessage^.HeaderByte := %01100001; // $61 - NceBusMessage^.Bytes[0] := %00000000; // $00 - NceBusMessage^.DataCount := 1; - Broadcast_NceBusMessage(NceBusMessage, CALLBYTE_BROADCAST); - Broadcast_NceBusMessage(NceBusMessage, CALLBYTE_BROADCAST); -end; - -// ***************************************************************************** -// -// procedure StopAllLocomotivesRequest(NceBusMessage: PNceBusMessage); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.4 -// Command Station Response : Paragraph 2.1.4.3 -// Status: -// Complete 1/29/2011 -// ***************************************************************************** -procedure StopAllLocomotivesRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -//var -// NewMessage: TDCCQueueMessage; -begin - - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('StopAllLocomotivesRequest'+LF);{$ENDIF} - - // TODO... - -// CommandStation.Flags.COMMANDSTATION_FLAGS_EMERGENCY_STOP_BIT := 1; -// NMRA_DCC_LoadMessage(@NewMessage, %00000000, %01000001, 0, 0, 0, 2); // NMRA Basic Emergency Stop All instruction -// NMRA_DCC_QueueMessage(@Track, @NewMessage, True); - NceBusMessage^.HeaderByte := %10000000; // $80 - NceBusMessage^.DataCount := 0; - Broadcast_NceBusMessage(NceBusMessage, CALLBYTE_BROADCAST); - Broadcast_NceBusMessage(NceBusMessage, CALLBYTE_BROADCAST); - SendNceBusMessage(NceBusMessage, CALLBYTE_RESPONSE, iDevice); - SendNceBusMessage(NceBusMessage, CALLBYTE_RESPONSE, iDevice); -end; - -{ -// ***************************************************************************** -// -// procedure EmergencyStopSlot(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// Slot: Slot to Emergency Stop -// -// Returns: -// True if the packet was queued -// -// ***************************************************************************** -function EmergencyStopSlot(Slot: PAddressSlot): Boolean; -begin - if Slot^.Flags.ADDRESS_SLOT_FLAGS_SPEED_128_BIT = 1 then - Slot^.SpeedDir := Slot^.SpeedDir and $80 // Clear the lower 7 bits, and set the speed to E-Stop - else - if Slot^.Flags.ADDRESS_SLOT_FLAGS_SPEED_28_BIT = 1 then - Slot^.SpeedDir := Slot^.SpeedDir and $E0 // Clear the lower 5 bits, and set the speed to E-Stop - else - Slot^.SpeedDir := Slot^.SpeedDir and $F0; // Clear the lower 4 bits, and set the speed to E-Stop - - Slot^.SpeedDir := Slot^.SpeedDir or SPEEDSTEP_E_STOP; - - Result := AddressSlot_QueueSpeedDCCMessage(Slot, True) -end; - } -// ***************************************************************************** -// -// procedure EmergencyStopLocomotiveRequestV3(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Returns: -// No Response to Device Defined, only notify PC -// -// Device Request : Paragraph 2.2.5.2 -// Command Station Response : Paragraph None -// Status: -// Complete 1/29/2011 -// -// ***************************************************************************** -procedure EmergencyStopLocomotiveRequestV3(NceBusMessage: PNceBusMessage; iDevice: Byte); -{var - Slot, Slot2: PAddressSlot; - Error: Byte; } -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('EmergencyStopLocomotiveRequestV3'+LF);{$ENDIF} - - { Error := E_PC_SUCCESS; - Slot := AddressSlot_FindSlot(ExtractAddressFromNceBusMessage(NceBusMessage, 0, 1), False); // If not found no harm done as there is nothing to stop! - if Slot <> nil then - begin - if Slot^.Flags.ADDRESS_SLOT_FLAGS_DOUBLEHEADER_BIT = 1 then - begin - // Slot is in a double header - Slot2 := AddressSlot_ExtractDoubleHeaderSecondSlot(Slot); - if (Slot2 <> nil) and (Track.Priority^.Count < MAX_TRACK_PRIORITY_BUFFER_DEPTH - 2) then - begin - Error := E_PC_COMMANDSTATION_COMMUNICATION; // Tell the device to try it again - if EmergencyStopSlot(Slot) then - if EmergencyStopSlot(Slot2) then - Error := E_PC_SUCCESS - end else - Error := E_PC_UNKNOWN; - end else - begin - if not EmergencyStopSlot(Slot) then - Error := E_PC_COMMANDSTATION_COMMUNICATION; // Tell the device to try it again - end - end; - // The PC needs a response - if iDevice = ID_PC_DEVICE then - Send_PCMessage(Error); } -end; - -// ***************************************************************************** -// -// procedure EmergencyStopLocomotiveRequestV2_Down(iDevice: Byte); -// -// Parameters: -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.5.1 -// Command Station Response : Paragraph None -// Status: -// Complete 1/29/2011 -// -// ***************************************************************************** -procedure EmergencyStopLocomotiveRequestV2_Down(iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('EmergencyStopLocomotiveRequestV2_Down'+LF);{$ENDIF} - Send_InstructionNotSupported(iDevice) -end; - - -// ***************************************************************************** -// -// procedure RegisterModeReadRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// MessageData: Global structure to hold the message information// -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.7 -// Command Station Response : Paragraph 2.1.4.4 -// Status: -// Complete: 2/19/2011 -// -// ***************************************************************************** -procedure RegisterModeReadRequest(MessageData: PNceBusDataArray; iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('RegisterModeReadRequest'+LF);{$ENDIF} - // Register Mode only support 8 Registers so what is sent = the "register" only 8 are supported (0000 RRRR) - { if not ServiceMode_QueueRequest(MessageData^[1]-1, 0, iDevice, SERVICE_MODE_REGISTER or SERVICE_MODE_COMMMAND_VERIFY_BYTE, STATE_SERVICEMODE_RESET_CYCLE) then - if iDevice = ID_PC_DEVICE then - Send_PCMessage(E_PC_LOSS_OF_TIMESLOT) } -end; - -// ***************************************************************************** -// -// procedure DirectModeReadRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// MessageData: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Description: Also known as CV Mode -// -// Device Request : Paragraph 2.2.8 (2.2.6 - 2.2.10 German Document v3.6) -// Command Station Response : Paragraph 2.1.4.4 -// Status: -// Complete: 2/19/2011 -// -// ***************************************************************************** -procedure DirectModeReadRequest(MessageData: PNceBusDataArray; iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('DirectModeReadRequest'+LF);{$ENDIF} -{ if not ServiceMode_QueueRequest(MapDirectModeCVToAddress(MessageData), 0, iDevice, SERVICE_MODE_DIRECT or SERVICE_MODE_COMMMAND_VERIFY_BYTE, STATE_SERVICEMODE_DIRECT_RESET_CYCLE) then - if iDevice = ID_PC_DEVICE then - Send_PCMessage(E_PC_LOSS_OF_TIMESLOT) } -end; - -// ***************************************************************************** -// -// procedure PagedModeReadRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// MessageData: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.9 -// Command Station Response : Paragraph 2.1.4.4 -// Status: -// Complete: 2/19/2011 -// -// ***************************************************************************** -procedure PagedModeReadRequest(MessageData: PNceBusDataArray; iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('PagedModeReadRequest'+LF);{$ENDIF} - { if not ServiceMode_QueueRequest(MessageData^[1]-1, 0, iDevice, SERVICE_MODE_PAGE or SERVICE_MODE_COMMMAND_VERIFY_BYTE, STATE_SERVICEMODE_RESET_CYCLE) then - if iDevice = ID_PC_DEVICE then - Send_PCMessage(E_PC_LOSS_OF_TIMESLOT) } -end; - - -// ***************************************************************************** -// -// procedure CheckAndRunNextServiceModeRequest; -// -// Parameters: None -// -// Returns: None -// -// Description: -// -// ***************************************************************************** -procedure CheckAndRunNextServiceModeRequest; -begin - { if ServiceModeInfo.Queue.Count > 0 then // There is another request waiting and the Service Mode engine is not busy with another request - begin - if ServiceModeInfo.Buffer.Mode and $F0 = ServiceModeInfo.Queue.Messages[ServiceModeInfo.Queue.iTail].Mode and $F0 then - begin - ServiceMode_LoadBufferFromNextInQueue(False); // If not changing ServiceMode types we can skip the PowerOn Cycle - if ServiceModeInfo.Buffer.iDevice = ID_PC_DEVICE then // This will force JMRI to send the Result Request for the Service Mode Request - Send_PCMessage(E_PC_SUCCESS) - end else - begin - ServiceMode_End; // Kick it out of Service Mode, the next loop through the main loop will restart with the new Service Mode type - SPI_UpdateDCC_Outputs; - end - end } -end; - - -// ***************************************************************************** -// -// function NceBus_HandleServiceModeAndResults; -// -// Parameters: None -// -// Returns: None -// -// Description: Called from the main loop to look for the service mode engine -// to be complete and reloads it when necessary -// -// ***************************************************************************** -procedure NceBus_HandleServiceModeAndResults; -begin - { if ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_IN_SERVICEMODE_BIT = 1 then // Already in Service Mode, handle it - begin - if ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_RESPONSE_READY_BIT = 1 then // Is the result ready? - begin - if ServiceModeInfo.Queue.ResultRequestCount > 0 then // Make sure someone is waiting for a result, note is can be a race condition between reading the decoder and the requesting sending a Result Request so don't - begin // and the requesting sending a Result Request so don't do anything if ResultRequestCount = 0. Just wait for it - DispatchServiceModeResultsRequest(ServiceModeInfo.Buffer.iDevice); - ServiceModeInfo.Buffer.iDevice := ID_NO_DEVICE; // Unlink the Device with the Service Mode - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_IDLE_BIT := 1; // Ready for the next SM request - ServiceMode_ResetForNewAck; - Dec(ServiceModeInfo.Queue.ResultRequestCount) - end - end; - if ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_IDLE_BIT = 1 then // Alway check if waiting for next message - CheckAndRunNextServiceModeRequest - end else - begin - if ServiceModeInfo.Queue.Count > 0 then - begin - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_MACHINE_ENABLED := 0; // Disable the State Machine (the Power On Cycle will just send "1"s) - NMRA_DCC_ResetTransmitter(@Programming); // Clean sheet of paper in the Transmitter - NMRA_DCC_LoadIdlePacketIntoTransmitter(@Programming, PREAMBLE_BIT_COUNT_SERVICEMODE); // Load up an Idle Packet - ServiceMode_LoadBufferFromNextInQueue(True); // Loads the Local Buffer with the request - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_IN_SERVICEMODE_BIT := 1; // After this is set a 56us interrupt will call the Service Mode statemachine. - SPI_UpdateDCC_Outputs; // Enable the DCC outputs, the statemachine will be sending "1"'s during this time (Not Enabled) - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_MACHINE_ENABLED := 1; // Enable the State Machine - Send_EnterServiceMode(ServiceModeInfo.Buffer.iDevice, True); // This will force JMRI to send the Result Request for the Service Mode Request, can be sent and in the Queue before this returns! - end - end } -end; - -// ***************************************************************************** -// -// procedure ServiceModeResultsRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.10 -// Command Station Response : Paragraph 2.1.5 -// Status: -// Complete: -// -// ***************************************************************************** -procedure ServiceModeResultsRequest(iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('ServiceModeResultsRequest'+LF);{$ENDIF} -{ if ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_IN_SERVICEMODE_BIT = 0 then - begin - Send_InstructionNotSupported(iDevice); // Per 2.1.5 Service Mode information response - ServiceMode_End; // Something is wrong so just clear everything and start over - SPI_UpdateDCC_Outputs - end else - begin - Inc(ServiceModeInfo.Queue.ResultRequestCount); // Here we just collect how many times the Results are Requested which should ideally match the number of requests for service mode - if ServiceModeInfo.Buffer.iDevice = ID_PC_DEVICE then // JMRI always needs some sort of reply to move it to the next state - Send_EnterServiceMode(ServiceModeInfo.Buffer.iDevice, True) - end } -end; - -// ***************************************************************************** -// -// procedure DispatchServiceModeResultsRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// ***************************************************************************** -procedure DispatchServiceModeResultsRequest(iDevice: Byte); -var - Mask: Byte; - RegisterIndex: Word; - NceBusMessage: TNceBusMessage; -begin - -// TODO... - - { case ServiceModeInfo.ServiceModeResult of - SERVICE_MODE_RESULT_SHORTCIRCUIT : // System had too much current draw - begin - NceBusMessage.HeaderByte := %01100001; // $61 - NceBusMessage.Bytes[0] := %00010010; // $12 - NceBusMessage.DataCount := 1; - end; - SERVICE_MODE_RESULT_DATA_NOT_FOUND : // No Acknowledgement was detected - begin - NceBusMessage.HeaderByte := %01100001; // $61 - NceBusMessage.Bytes[0] := %00010011; // $13 - NceBusMessage.DataCount := 1; - end; - SERVICE_MODE_RESULT_STATION_BUSY : // Not supported in NceBus yet - begin - NceBusMessage.HeaderByte := %01100001; // $61 - NceBusMessage.Bytes[0] := %00011111; // $1F - NceBusMessage.DataCount := 1; - end; - SERVICE_MODE_RESULT_STATION_READY : // Not supported in NceBus yet - begin } - NceBusMessage.HeaderByte := %01100001; // $61 - NceBusMessage.Bytes[0] := %00010001; // $11 - NceBusMessage.DataCount := 1; - { end; - SERVICE_MODE_RESULT_RESPONSE_PAGE_MODE : // Response was achieved in Register or Page mode - begin - // Page Mode supports 1024 but the NceBus implementation only support 256 - // Register Mode only support 8 Registers and Address = what is sent - NceBusMessage.HeaderByte := %01100011; // $63 - NceBusMessage.Bytes[0] := %00010000; // $10 - NceBusMessage.Bytes[1] := ServiceModeInfo.Buffer.DeviceCache.Address + 1; - NceBusMessage.Bytes[2] := ServiceModeInfo.Buffer.DeviceCache.Value; - NceBusMessage.DataCount := 3; - end; - SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE : // Response was achieved in Direct CV mode - begin - // We support only v3.6 here as Register Index = 0 mapped to 256 does not exist in the v3.6 spec - if ServiceModeInfo.Buffer.DeviceCache.Address < 256 (*$00FF*) then - begin - if ServiceModeInfo.Buffer.DeviceCache.Address = 255 then - RegisterIndex := 0 - else - RegisterIndex := (ServiceModeInfo.Buffer.DeviceCache.Address and $00FF) + 1; - Mask := %00010100 // $14 Pre v3.6 8 bit address only or v3.6 CV 1-255 and CV 1024 - end else - if ServiceModeInfo.Buffer.DeviceCache.Address < 512 (*$01FF*) then - begin - if ServiceModeInfo.Buffer.DeviceCache.Address = 511 then - RegisterIndex := 0 - else - RegisterIndex := (ServiceModeInfo.Buffer.DeviceCache.Address and $00FF) + 1; - Mask := %00010101 // $15 v3.6 CV 256-511 - end else - if ServiceModeInfo.Buffer.DeviceCache.Address < 768 (*$02FF*) then - begin - if ServiceModeInfo.Buffer.DeviceCache.Address = 767 then - RegisterIndex := 0 - else - RegisterIndex := (ServiceModeInfo.Buffer.DeviceCache.Address and $00FF) + 1; - Mask := %00010110 // $16 v3.6 CV 512-767 - end else - begin - if ServiceModeInfo.Buffer.DeviceCache.Address = 1023 then (*$03FF*) - RegisterIndex := 0 - else - RegisterIndex := (ServiceModeInfo.Buffer.DeviceCache.Address and $00FF) + 1; - Mask := %00010111; // $17 v3.6 CV 768-1023 - end; - - NceBusMessage.HeaderByte := %01100011; // $63 - NceBusMessage.Bytes[0] := Mask; - NceBusMessage.Bytes[1] := RegisterIndex; - NceBusMessage.Bytes[2] := ServiceModeInfo.Buffer.DeviceCache.Value; - NceBusMessage.DataCount := 3; - end; - end; } - SendNceBusMessage(@NceBusMessage, CALLBYTE_RESPONSE, iDevice); -end; - -// ***************************************************************************** -// -// procedure RegisterModeWriteRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// MessageData: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.11 -// Command Station Response : Paragraph 2.1.4.4 -// Status: -// Complete: 2/19/2011 -// -// ***************************************************************************** -procedure RegisterModeWriteRequest(MessageData: PNceBusDataArray; iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('RegisterModeWriteRequest'+LF);{$ENDIF} - { // Register Mode only support 8 Registers - if not ServiceMode_QueueRequest(MessageData^[1]-1, MessageData^[2], iDevice, SERVICE_MODE_REGISTER or SERVICE_MODE_COMMMAND_WRITE_BYTE, STATE_SERVICEMODE_RESET_CYCLE) then - if iDevice = ID_PC_DEVICE then - Send_PCMessage(E_PC_LOSS_OF_TIMESLOT) } -end; - -// ***************************************************************************** -// -// procedure DirectModeWriteRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// MessageData: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.12 -// Command Station Response : Paragraph 2.1.4.4 -// Status: -// Complete: 2/19/2011 -// -// ***************************************************************************** -procedure DirectModeWriteRequest(MessageData: PNceBusDataArray; iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('DirectModeWriteRequest'+LF);{$ENDIF} -{ if not ServiceMode_QueueRequest(MapDirectModeCVToAddress( MessageData), MessageData^[2], iDevice, SERVICE_MODE_DIRECT or SERVICE_MODE_COMMMAND_WRITE_BYTE, STATE_SERVICEMODE_DIRECT_RESET_CYCLE) then - if iDevice = ID_PC_DEVICE then - Send_PCMessage(E_PC_LOSS_OF_TIMESLOT); } -end; - -// ***************************************************************************** -// -// procedure PagedModeWriteRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// MessageData: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.13 -// Command Station Response : Paragraph 2.1.4.4 -// Status: -// Complete: 2/19/2011 -// -// ***************************************************************************** -procedure PagedModeWriteRequest(MessageData: PNceBusDataArray; iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('PagedModeWriteRequest'+LF);{$ENDIF} - { if not ServiceMode_QueueRequest(MessageData^[1]-1, MessageData^[2], iDevice, SERVICE_MODE_PAGE or SERVICE_MODE_COMMMAND_WRITE_BYTE, STATE_SERVICEMODE_RESET_CYCLE) then - if iDevice = ID_PC_DEVICE then - Send_PCMessage(E_PC_LOSS_OF_TIMESLOT) } -end; - -// ***************************************************************************** -// -// procedure CommandStationSoftwareVersionRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// -// Device Request : Paragraph 2.2.14 -// Command Station Response : Paragraph 2.1.6 -// Status: -// Complete 1/29/2011 -// -// ***************************************************************************** -procedure CommandStationSoftwareVersionRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -begin - // Fake V3 Software - NceBusMessage^.HeaderByte := %01100011; // $63 Reuse the passed NceBus Message, enviromentally friendly save the bytes! - NceBusMessage^.Bytes[0] := %00100001; // $21 - NceBusMessage^.Bytes[1] := VERSION_SOFTWARE_NceBus; - NceBusMessage^.Bytes[2] := VERSION_COMMANDSTATION_LZ100; - NceBusMessage^.DataCount := 3; - SendNceBusMessage(NceBusMessage, CALLBYTE_RESPONSE, iDevice); - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('CommandStationSoftwareVersionRequest'+LF);{$ENDIF} -end; - -// ***************************************************************************** -// -// procedure CommandStationStatusRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.15 -// Command Station Response : Paragraph 2.1.7 -// Status: -// Complete 1/29/2011 -// -// ***************************************************************************** -procedure CommandStationStatusRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -begin - NceBusMessage^.HeaderByte := %01100010; // Reuse the passed NceBus Message, enviromentally friendly save the bytes! - NceBusMessage^.Bytes[0] := %00100010; - NceBusMessage^.Bytes[1] := $00; // TODO: CommandStation.Flags and $00FF; // CommandStation State bottom 8 bits are mapped as the NceBus Spec - NceBusMessage^.DataCount := 2; - SendNceBusMessage(NceBusMessage, CALLBYTE_RESPONSE, iDevice); - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('CommandStationStatusRequest'+LF);{$ENDIF} -end; - -// ***************************************************************************** -// -// procedure SetCommandStationPowerUpMode(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.16 -// Command Station Response : Paragraph None -// Status: -// Complete 1/29/2011 -// -// ***************************************************************************** -procedure SetCommandStationPowerUpMode(NceBusMessage: PNceBusMessage; iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('SetCommandStationPowerUpMode'+LF);{$ENDIF} -{ CommandStation.Flags.COMMANDSTATION_FLAGS_STARTUP_MODE_BIT := NceBusMessage^.Bytes[1].2; // CommandStation.State bit 2 is mapped to this bit in the NceBus message - // The PC needs a response - if iDevice = ID_PC_DEVICE then - Send_PCMessage(E_PC_SUCCESS); } -end; - -// ***************************************************************************** -// -// procedure AccessoryInformationRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.17 -// Command Station Response : Paragraph 2.1.11 -// Status: -// Complete TBD -// -// ***************************************************************************** -procedure AccessoryInformationRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -var - Address: Word; -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('AccessoryInformationRequest'+LF);{$ENDIF} - Address := NceBusMessage^.Bytes[0] shl 2; // Address is sent as the Group Address need to mulitpy by 4 -// AddressSlotInfo.AccessorySlot[Address div 8]; - Send_InstructionNotSupported(iDevice) -end; - -// ***************************************************************************** -// -// procedure AccessoryOperationRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.18 -// Command Station Response : Paragraph None -// Status: -// Complete TBD -// -// ***************************************************************************** -procedure AccessoryOperationRequest(NceBusMessage: PNceBusMessage; iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('AccessoryOperationRequest'+LF);{$ENDIF} - Send_InstructionNotSupported(iDevice) -end; - -// ***************************************************************************** -// -// procedure LocomotiveInformationRequestV1(iDevice: Byte); -// -// Parameters: -// iDevice: The device ID that has the open window to send an Inquiry, send ID_PC_DEVICE to send to the RS485 PC link -// -// Device Request : Paragraph 2.2.19.1 -// Command Station Response : Paragraph 2.1.12 -// Status: -// Complete 1/29/2011 -// -// ***************************************************************************** -procedure LocomotiveInformationRequestV1(iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} UART1_Write_Text('LocomotiveInformationRequestV1'+LF);{$ENDIF} - Send_InstructionNotSupported(iDevice) -end; - -// ***************************************************************************** -// -// procedure LocomotiveInformationRequestV2(iDevice: Byte); -// -// Parameters: -// NceBusMessage: Global structure to hold the message information -// -// Device Request : Paragraph 2.2.19.2 -// Command Station Response : Paragraph 2.1.13 -// Status: -// Complete 1/29/2011 -// -// ***************************************************************************** -procedure LocomotiveInformationRequestV2(iDevice: Byte); -begin - {$IFDEF TRACE_NceBus_MESSAGES} ... [truncated message content] |