From: <jim...@us...> - 2013-02-11 04:00:42
|
Revision: 2992 http://openlcb.svn.sourceforge.net/openlcb/?rev=2992&view=rev Author: jimkueneman626 Date: 2013-02-11 04:00:28 +0000 (Mon, 11 Feb 2013) Log Message: ----------- Updated mikroPascal Library with Command Station Service Mode units. Direct (byte/bit) Read Tested. Direct (byte/bit) Write implemented but not tested. Paged Mode Read/Write implemented but not tested. Started to layout v2 of the Command Station to add a SD card. Modified Paths: -------------- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/DirectServiceMode.mpas trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetDCC.mpas trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetServiceMode.mpas trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/MCU_Setup_dsPIC33EP64GP502.mpas trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/NMRAnetAppCallbacks.mpas trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/dsPIC33EP_NMRABusCommandStation.hex trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/dsPIC33EP_NMRABusCommandStation.mppds trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/dsPIC33EP_NMRAnetCommandStation.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 trunk/prototypes/mikroPascal/dsPIC33FJ_Visual TFT_BasicThrottle/Throttle_Code/mikroPascal PRO for dsPIC/Throttle_main.mpas trunk/scratchpads/jkueneman/Hardware/PcbArchitectLibrary/Mustangpeak.psl trunk/scratchpads/jkueneman/Hardware/PcbArchitectLibrary/Mustangpeak.psx trunk/scratchpads/jkueneman/Hardware/PcbArchitectLibrary/Mustangpeak.ssl trunk/scratchpads/jkueneman/Hardware/PcbArchitectLibrary/Mustangpeak.ssx trunk/scratchpads/jkueneman/Hardware/PcbArchitectLibrary/MustangpeakConnectors.cml trunk/scratchpads/jkueneman/Hardware/PcbArchitectLibrary/MustangpeakConnectors.cmx Added Paths: ----------- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/PagedServiceMode.mpas trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/RegisterServiceMode.mpas trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/ServiceModeDefines.mpas trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/RGS_40_CDI.xml trunk/scratchpads/jkueneman/Hardware/LCBlocks/MicroFoundation/Version 2.0/ trunk/scratchpads/jkueneman/Hardware/LCBlocks/MicroFoundation/Version 2.0/LCBricks_MicroFoundation.pcb trunk/scratchpads/jkueneman/Hardware/LCBlocks/MicroFoundation/Version 2.0/LCBricks_MicroFoundation.prj trunk/scratchpads/jkueneman/Hardware/LCBlocks/MicroFoundation/Version 2.0/LCBricks_MicroFoundation.sch Property Changed: ---------------- trunk/prototypes/mikroPascal/dsPIC33EP_CommandStation/ Modified: trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/DirectServiceMode.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/DirectServiceMode.mpas 2013-02-10 08:03:37 UTC (rev 2991) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/DirectServiceMode.mpas 2013-02-11 04:00:28 UTC (rev 2992) @@ -2,391 +2,238 @@ uses NMRAnetDCC, - NMRAnetServiceMode; + ServiceModeDefines; + + + procedure DirectServiceMode_StateMachineRead(BufferPtr: PDCCBufferInfo); + procedure DirectServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); implementation -type - TServiceModePowerOnFunc = procedure(BufferPtr: PDCCBufferInfo); - PServiceModePowerOnFunc = ^TServiceModePowerOnFunc; - TServiceModeResetNextStateFunc = procedure(BufferPtr: PDCCBufferInfo); - PServiceModeResetNextStateFunc = ^TServiceModeResetNextStateFunc; - TServiceModeHandleAckDetected = procedure (BufferPtr: PDCCBufferInfo); - PServiceModeHandleAckDetected = ^TServiceModeHandleAckDetected; - TServiceModeRequestNextStateFunc = procedure(BufferPtr: PDCCBufferInfo); - PServiceModeRequestNextStateFunc = ^TServiceModeRequestNextStateFunc; - TServiceModeRequestCurrentStateFunc = procedure(BufferPtr: PDCCBufferInfo; Command: Byte); - PServiceModeRequestCurrentStateFunc = ^TServiceModeRequestCurrentStateFunc; - TServiceModeWriteRecoverNextStateFunc = procedure(BufferPtr: PDCCBufferInfo); - PServiceModeWriteRecoverNextStateFunc = ^TServiceModeWriteRecoverNextStateFunc; - - procedure NextStateAndLoadResetPacket(NextStateMachineIndex: Byte; BufferPtr: PDCCBufferInfo); forward; - // *************************************************************************** -// procedure ServiceModePowerOn; +// procedure DirectLoadTransmitter // -// Common function that Direct CV Mode calls are started from +// Parameters: None // -// Note: that this function expects that ONE RESET MESSAGE HAS ALREADY BEEN SENT before -// this function is entered the first time. +// Result: None +// +// Description: // *************************************************************************** -procedure ServiceModePowerOn(BufferPtr: PDCCBufferInfo; NextStateFunc: PServiceModePowerOnFunc); +procedure DirectLoadTransmitter(BufferPtr: PDCCBufferInfo; CV_Address: Word; InstructionCode, DataByte: Byte); +var + i: Integer; begin - Inc(ServiceModeInfo.iInstructionCountSent); // We are always one behind so increment first - if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_POWER_ON_CYCLE_IDLE_COUNT then - begin - Inc(ServiceModeInfo.TotalSent); - NMRA_DCC_LoadIdlePacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); - end else - NextStateFunc(BufferPtr); + BufferPtr^.TX_TransmittingPacket.PacketBytes[0] := %01110000 or InstructionCode or Hi(CV_Address); + BufferPtr^.TX_TransmittingPacket.PacketBytes[1] := Lo(CV_Address); + BufferPtr^.TX_TransmittingPacket.PacketBytes[2] := DataByte; + BufferPtr^.TX_TransmittingPacket.Flags := 3; + BufferPtr^.TX_XOR_Byte := 0; + for i := 0 to 2 do + BufferPtr^.TX_XOR_Byte := BufferPtr^.TX_XOR_Byte xor BufferPtr^.TX_TransmittingPacket.PacketBytes[i]; + BufferPtr^.TX_PreambleBitCount := PREAMBLE_BIT_COUNT_SERVICEMODE; end; // *************************************************************************** -// procedure ServiceModeReset; +// procedure PowerOnCycle // -// Common function that Direct CV Mode calls are started from. +// Parameters: None // -// NOTE 1: This function expects that ONE RESET MESSAGE HAS ALREADY BEEN SENT before +// Result: None // -// this function is entered the first time. -// NOTE 2: The NextStateFunc must load the final ResetPacket, typically using NextStateAndLoadResetPacket +// Description: // *************************************************************************** -procedure ServiceModeReset(BufferPtr: PDCCBufferInfo; NextStateFunc: PServiceModeResetNextStateFunc; CycleCount: Byte; NewAck: Boolean); +procedure PowerOnCycle(BufferPtr: PDCCBufferInfo); begin - Inc(ServiceModeInfo.iInstructionCountSent); // We are always one behind so increment first - if ServiceModeInfo.iInstructionCountSent < CycleCount - 1 then // The NextStateFunc is responsible for the final Reset Packet + if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_POWER_ON_CYCLE_IDLE_COUNT then begin - Inc(ServiceModeInfo.TotalSent); - NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); + Inc(ServiceModeInfo.iInstructionCountSent); + NMRA_DCC_LoadIdlePacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) end else begin - if NewAck then - ServiceMode_ResetForNewAck; // Get ready for an new Ack run within the sequence - NextStateFunc(BufferPtr); + ServiceModeInfo.iInstructionCountSent := 1; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESET_CYCLE end end; // *************************************************************************** -// procedure ServiceModeRequest; +// procedure ResetCycle // -// Common function that many Direct CV Mode calls are started from -// *************************************************************************** -procedure ServiceModeRequest(BufferPtr: PDCCBufferInfo; NextStateFunc: PServiceModeRequestNextStateFunc; CurrentStateFunc: PServiceModeRequestCurrentStateFunc; AckDetectedFunc: PServiceModeHandleAckDetected; Command: Byte; CycleCount: Byte); -begin - if ServiceModeInfo.iInstructionCountSent = 2 then // Start looking for an ACK from the decoder after the packet sent to the decoder - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_SCAN_FOR_ACK_BIT := 1; - - if ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_DETECTED_BIT = 1 then // Break off once a ACK is detected - AckDetectedFunc(BufferPtr) - else begin - Inc(ServiceModeInfo.iInstructionCountSent); // We are always one behind so increment first - if ServiceModeInfo.iInstructionCountSent >= CycleCount then - begin - NextStateFunc(BufferPtr); - ServiceModeInfo.iInstructionCountSent := 0 - end else - CurrentStateFunc(BufferPtr, Command) // What to do for the Service Mode Request - end; -end; - -// *************************************************************************** -// procedure ServiceModeSendResetPackets; +// Parameters: None // -// Just loops keeping the decoder in Service Mode -// *************************************************************************** -procedure ServiceModeSendResetPackets(BufferPtr: PDCCBufferInfo); -begin - NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); -end; - -// *************************************************************************** -// procedure ServiceModeSequenceComplete; +// Result: None // -// Ready for the main loop to report back what occured during the Service Mode attempt -// This will continue to be called until a new Service Mode commmand is moved from -// the queue to the buffer. It keep the decoder in service mode by sending Resets +// Description: // *************************************************************************** -procedure ServiceModeSequenceComplete(BufferPtr: PDCCBufferInfo); +procedure ResetCycle(BufferPtr: PDCCBufferInfo); begin - ServiceModeInfo.Buffer.DeviceCache.Address := ServiceModeInfo.ScratchBuffer.Address; // Restore the raw address - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_RESPONSE_READY_BIT := 1; // It is ready one way or another (No Loco or the Ack Timer already set it to 1) - NextStateAndLoadResetPacket(STATE_SERVICEMODE_SEND_RESET_PACKETS, BufferPtr); // Keep the decoder in Service Mode + if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_POWER_ON_CYCLE_RESET_COUNT then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) + end else + begin + ServiceModeInfo.Flags.PROGRAMMING_ACK_SCANNING_FOR_ACK_BIT := 1; // Start Looking since we are now sending the read instruction + ServiceModeInfo.Flags.PROGRAMMING_ACK_DETECTED_BIT := 0; + ServiceModeInfo.Flags.PROGRAMMING_ACK_TIMER_DETECTED_LEADINGEDGE_BIT := 0; + ServiceModeInfo.Flags.PROGRAMMING_ACK_FAILED_TO_DETECT_TRAILINGEDGE_BIT := 0; + + ServiceModeInfo.iInstructionCountSent := 1; + case ServiceModeInfo.ServiceModeType of + SERVICE_MODE_TYPE_DIRECT_BYTE : + begin + if ServiceModeInfo.ReadWrite = SERVICEMODE_WRITE then + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00001100, ServiceModeInfo.ReadIndex) + else + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00000100, ServiceModeInfo.ReadIndex); + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_DIRECT_BYTE + end; + SERVICE_MODE_TYPE_DIRECT_BIT : + begin + if ServiceModeInfo.ReadWrite = SERVICEMODE_WRITE then + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00001000, %11110000 or ServiceModeInfo.Value) // The passed value must be in the xxxxDBBB format where D = Data and BBB is the offset 0..7 + else + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00001000, %11101000 or ServiceModeInfo.ReadIndex); // Always trying to read ones and assuming zeros if no response + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_DIRECT_BIT_ONE + end; + end; + end end; // *************************************************************************** -// procedure ServiceModeNotSupported; +// procedure NextBitAndTestForCompletion // -// Direct CV Mode is not supported (or problems occured) -// *************************************************************************** -procedure ServiceModeNotSupported(BufferPtr: PDCCBufferInfo); -begin - NextStateAndLoadResetPacket(STATE_SERVICEMODE_SEQUENCE_COMPLETE, BufferPtr); // TEMPORARY NEED TO TRY PAGED MODE -end; - -// *************************************************************************** -// procedure NextStateAndLoadResetPacket +// Parameters: None // -// General use function to reset variables and move to the next statemachine -// state -// *************************************************************************** -procedure NextStateAndLoadResetPacket(NextStateMachineIndex: Byte; BufferPtr: PDCCBufferInfo); -begin - ServiceModeInfo.iStateMachine := NextStateMachineIndex; - ServiceModeInfo.iInstructionCountSent := 0; - NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); - Inc(ServiceModeInfo.TotalSent); -end; - -// *************************************************************************** -// procedure Direct_AckDetectedFunc; +// Result: None // -// Called in response to a positive acknowledgement of a Direct Service Mode Request -// PROGRAMMING_ACK_STATE_NMRA_DCC_DETECTED_BIT has been set by the 5ms timer +// Description: // *************************************************************************** -procedure Direct_AckDetectedFunc(BufferPtr: PDCCBufferInfo); -var - State: Byte; +procedure NextBitAndTestForCompletion(BufferPtr: PDCCBufferInfo); begin - if ServiceModeInfo.Buffer.Mode and $0F > SERVICE_MODE_COMMAND_MAX_VERIFY then // Is it a Verify or Write Ack? - State := STATE_SERVICEMODE_DIRECT_WRITE_RECOVER_CYCLE // A Write needs a Recover Cycle - else - State := STATE_SERVICEMODE_SEQUENCE_COMPLETE; // A Verify can just end - NextStateAndLoadResetPacket(State, BufferPtr); - ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE; -end; - -// *************************************************************************** -// procedure Direct_AckDetectedSupportedTestFunc; -// -// Called in response to a positive acknowledgement of a Direct Service Mode availablity test -// PROGRAMMING_ACK_STATE_NMRA_DCC_DETECTED_BIT has been set by the 5ms timer -// *************************************************************************** -procedure Direct_AckDetectedSupportedTestFunc(BufferPtr: PDCCBufferInfo); -begin - {$IFNDEF DISABLE_BYTE_BY_BIT_DIRECT_SERVICEMODE} - if ServiceModeInfo.DirectSupportTest <= SERVICE_MODE_DIRECT_TEST_BIT_ONE_MODE then // Was it a Bit Test Command? - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_BITMODE_AVAILABLE := 1; // Bit Mode is available else Byte Mode is available - {$ENDIF DISABLE_BYTE_BY_BIT_DIRECT_SERVICEMODE} - NextStateAndLoadResetPacket(STATE_SERVICEMODE_DIRECT_RESET_CYCLE, BufferPtr); // Reset Cycle requires this preloaded Reset Packet -end; - -// *************************************************************************** -// procedure Direct_AckDetectedByteByBitFunc; -// -// Called in response to a positive acknowledgement of a Direct Service Mode -// when using Bit Mode to quickly read a Byte when available -// PROGRAMMING_ACK_STATE_NMRA_DCC_DETECTED_BIT has been set by the 5ms timer -// *************************************************************************** -procedure Direct_AckDetectedByteByBitFunc(BufferPtr: PDCCBufferInfo); -var - Offset: Byte; -begin - Offset := ServiceModeInfo.Buffer.DeviceCache.Value and %00000111; // Extract the Bit Offset that was tested - ServiceModeInfo.ScratchBuffer.Value.Offset := ServiceModeInfo.Buffer.DeviceCache.Value.3; // Copy the Tested bit into the Offset in the Resulting Byte - if ServiceModeInfo.Buffer.DeviceCache.Value and %00000111 = 0 then // Have we tested all 8 Bits yet? - begin // Yes we are done - ServiceModeInfo.Buffer.DeviceCache.Value := ServiceModeInfo.ScratchBuffer.Value; // Copy the Result to the output - ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE; // Tell the main loop the read was successful - NextStateAndLoadResetPacket(STATE_SERVICEMODE_SEQUENCE_COMPLETE, BufferPtr); // Spin until the main loop dispatches the result + Inc(ServiceModeInfo.ReadIndex); // Try the next Bit + if ServiceModeInfo.ReadIndex < 8 then // Have we run all the bits? + begin + ServiceModeInfo.iInstructionCountSent := 1; // Run the next bit cycle + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESET_CYCLE; end else - begin // No move to the next lower bit offset - Dec(ServiceModeInfo.Buffer.DeviceCache.Value); // Move to the next Bit Index - ServiceModeInfo.Buffer.DeviceCache.Value.3 := 0; // Start off by testing for a 0 - NextStateAndLoadResetPacket(STATE_SERVICEMODE_DIRECT_BYTEMODE_BY_BITS_RESET, BufferPtr); // Run a Reset Sequence before the next byte + begin + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE_READ; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY end; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); end; - // *************************************************************************** -// procedure Direct_TestBitNextStateFunc; +// procedure FailedToDetectCorrectAckWidth // -// Called in response to no acknowledgement of a Direct Service Mode test -// for the Manufacturing ID CV Bit 7 = 0 -// *************************************************************************** -procedure Direct_TestBitNextStateFunc(BufferPtr: PDCCBufferInfo); -begin - Inc(ServiceModeInfo.DirectSupportTest); // Next Test Mode - NextStateAndLoadResetPacket(STATE_SERVICEMODE_RESET_CYCLE, BufferPtr) // Try again -end; - -// *************************************************************************** -// procedure Direct_TestByteNextStateFunc; +// Parameters: None // -// Called in response to no acknowledgement of a Direct Service Mode test -// for the Manufacturing ID CV Byte. If this fails then the decoder does not -// support Direct Mode -// *************************************************************************** -procedure Direct_TestByteNextStateFunc(BufferPtr: PDCCBufferInfo); -begin - NextStateAndLoadResetPacket(STATE_SERVICEMODE_NOT_SUPPORTED, BufferPtr) // Direct Mode Failed -end; - -// *************************************************************************** -// procedure Direct_RequestNextStateFunc; +// Result: None // -// Called in response to no acknowledgement of a Direct Service Mode request -// on the deocoder. Exit the sequence, the fail flag has been set by the -// Service Mode timer +// Description: // *************************************************************************** -procedure Direct_RequestNextStateFunc(BufferPtr: PDCCBufferInfo); +procedure FailedToDetectCorrectAckWidth(BufferPtr: PDCCBufferInfo); begin - NextStateAndLoadResetPacket(STATE_SERVICEMODE_SEQUENCE_COMPLETE, BufferPtr) + ServiceModeInfo.Value := 0; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE_SHORT_ACK; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; end; - + // *************************************************************************** -// procedure Direct_ByteVerifyNextStateFunc; +// procedure DirectServiceMode_StateMachineRead // -// Called in response to no acknowledgement of a Direct Service Mode request -// to Verify a CV. It will be called up to 255 time or until the decoder -// acknowledges -// *************************************************************************** -procedure Direct_ByteVerifyNextStateFunc(BufferPtr: PDCCBufferInfo); -var - State: Byte; -begin - if ServiceModeInfo.Buffer.DeviceCache.Value = 255 then - State := STATE_SERVICEMODE_SEQUENCE_COMPLETE // Questions have run out without an acknowledgement, give up - else begin - Inc(ServiceModeInfo.Buffer.DeviceCache.Value); // Have not run all 255 Registers yet keep going - ServiceModeInfo.iInstructionCountSent := 0; - State := STATE_SERVICEMODE_DIRECT_RESET_CYCLE // Run the Rest packet sequence first then try the new Value - end; - NextStateAndLoadResetPacket(State, BufferPtr) -end; - -// *************************************************************************** -// procedure Direct_ByteByBitNextStateFunc; +// Parameters: None // -// Called in response to not receiving an Ack when using Bit Mode to read a Byte -// *************************************************************************** -procedure Direct_ByteByBitNextStateFunc(BufferPtr: PDCCBufferInfo); -var - State: Byte; -begin - if ServiceModeInfo.Buffer.DeviceCache.Value.3 = 0 then - begin - ServiceModeInfo.Buffer.DeviceCache.Value.3 := 1; // See if the bit is a "1" - State := STATE_SERVICEMODE_DIRECT_BYTEMODE_BY_BITS_RESET // Run the Reset Packet Sequence before trying the next bit - end else - State := STATE_SERVICEMODE_SEQUENCE_COMPLETE; // Failed somewhere in the 8 bits - NextStateAndLoadResetPacket(State, BufferPtr); -end; - -// *************************************************************************** -// procedure Direct_PowerOnNextStateFunc; +// Result: None // -// Called in response to finishing the Power On Cycle -// *************************************************************************** -procedure Direct_PowerOnNextStateFunc(BufferPtr: PDCCBufferInfo); -begin - ServiceModeInfo.DirectSupportTest := SERVICE_MODE_DIRECT_TEST_BIT_ZERO_MODE; // Setup to track what test we are in - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_BITMODE_AVAILABLE := 0; // Assume not available - NextStateAndLoadResetPacket(STATE_SERVICEMODE_RESET_CYCLE, BufferPtr); -end; - -// *************************************************************************** -// procedure Direct_ResetAndTestNextStateFunc; +// Description: +// StateMachine that handles a Direct CV Service Mode Programmming sequence +// per the S9.2.3 spec // -// Called in response to the Command Station placing the decoder into -// Service Mode +// NOTE: Everytime this StateMachine is entered the Transmitter MUST BE LOADED // *************************************************************************** -procedure Direct_ResetAndTestNextStateFunc(BufferPtr: PDCCBufferInfo); +procedure DirectServiceMode_StateMachineRead(BufferPtr: PDCCBufferInfo); var - Next: Byte; + BitOffset: Byte; begin - if ServiceModeInfo.DirectSupportTest = SERVICE_MODE_DIRECT_TEST_BIT_ZERO_MODE then // When the Buffer is loaded the original Address and Value are copied into the ServiceModeInfo.ScratchBuffer structure + if BufferPtr^.TX_Flags.TRANSMITTING_FLAG_STOP_BIT = 1 then begin - ServiceModeInfo.Buffer.DeviceCache := MFG_CV_ID_BIT_7_EQUALS_ZERO; // Set up to Verify a 0 in Bit 7 of CV 8 - Next := STATE_SERVICEMODE_DIRECT_MODE_BIT_TEST; - end else - if ServiceModeInfo.DirectSupportTest = SERVICE_MODE_DIRECT_TEST_BIT_ONE_MODE then - begin - ServiceModeInfo.Buffer.DeviceCache := MFG_CV_ID_BIT_7_EQUALS_ONE; // Set up to Verify a 1 in Bit 7 of CV 8 - Next := STATE_SERVICEMODE_DIRECT_MODE_BIT_TEST; - end else - begin - ServiceModeInfo.Buffer.DeviceCache := MFG_CV_ID; // Set up to Verify CV 8 - Next := STATE_SERVICEMODE_DIRECT_MODE_BYTE_TEST; + case ServiceModeInfo.iStateMachine of + STATE_SERVICEMODE_POWER_ON_CYCLE : PowerOnCycle(BufferPtr); + STATE_SERVICEMODE_RESET_CYCLE : ResetCycle(BufferPtr); + STATE_SERVICEMODE_DIRECT_BYTE : + begin + if ServiceModeInfo.Flags.PROGRAMMING_ACK_DETECTED_BIT = 1 then + begin // ACK detected and we are done + ServiceModeInfo.Value := ServiceModeInfo.ReadIndex; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE_READ; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; + end else + if ServiceModeInfo.Flags.PROGRAMMING_ACK_FAILED_TO_DETECT_TRAILINGEDGE_BIT = 1 then + FailedToDetectCorrectAckWidth(BufferPtr) + else + if ServiceModeInfo.Flags.PROGRAMMING_ACK_TIMER_DETECTED_LEADINGEDGE_BIT = 1 then + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) // Ack start detected so drop into Reset Packets are either success or failure handled above after 5ms + else begin + if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_DIRECT_INSTRUCTION_COUNT then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00000100, ServiceModeInfo.ReadIndex); + end else + begin + Inc(ServiceModeInfo.ReadIndex); // Try the next Value + if ServiceModeInfo.Value = ServiceModeInfo.ReadIndex then // Have we run all the way around the horn once + begin + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_DATA_NOT_FOUND; // Run all possible values and an ACK was not found + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY + end else + begin + ServiceModeInfo.iInstructionCountSent := 1; // Run the next possible Value cycle + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESET_CYCLE; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); + end + end + end + end; + STATE_SERVICEMODE_DIRECT_BIT_ONE : + begin + if ServiceModeInfo.Flags.PROGRAMMING_ACK_DETECTED_BIT = 1 then + begin + BitOffset := ServiceModeInfo.ReadIndex; + ServiceModeInfo.Value.BitOffset := 1; // Set the offset to 1 (default is 0) + NextBitAndTestForCompletion(BufferPtr); + end else + if ServiceModeInfo.Flags.PROGRAMMING_ACK_FAILED_TO_DETECT_TRAILINGEDGE_BIT = 1 then + FailedToDetectCorrectAckWidth(BufferPtr) + else + if ServiceModeInfo.Flags.PROGRAMMING_ACK_TIMER_DETECTED_LEADINGEDGE_BIT = 1 then + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) // Ack start detected so drop into Reset Packets are either success or failure handled above after 5ms + else + if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_DIRECT_INSTRUCTION_COUNT then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00001000, %11101000 or ServiceModeInfo.ReadIndex); + end else + NextBitAndTestForCompletion(BufferPtr); + end; + STATE_SERVICEMODE_RESULTS_READY : + begin + // Spin here until the application calls ServiceMode_ReadResults to grab the Result and move to Done + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 // Don't come out of Service Mode + end; + STATE_SERVICEMODE_DONE : + begin + end; + end end; - NextStateAndLoadResetPacket(Next, BufferPtr); end; // *************************************************************************** -// procedure Direct_ResetAndDispatchNextStateFunc; +// procedure DirectServiceMode_StateMachineWrite // -// Called in response after the decoder responded to tests to see if it implements -// Direct Bit and/or Byte Mode. If Bit Mode is implemented it is assumed Byte -// Mode is also implemented. -// *************************************************************************** -procedure Direct_ResetAndDispatchNextStateFunc(BufferPtr: PDCCBufferInfo); -var - State: Byte; -begin - ServiceModeInfo.Buffer.DeviceCache := ServiceModeInfo.ScratchBuffer; // Restore the original request - - if ServiceModeInfo.Buffer.Mode and $0F = SERVICE_MODE_COMMMAND_WRITE_BYTE then - State := STATE_SERVICEMODE_DIRECT_BYTEMODE_WRITE - else - if ServiceModeInfo.Buffer.Mode and $0F = SERVICE_MODE_COMMMAND_VERIFY_BYTE then - begin - if ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_BITMODE_AVAILABLE = 1 then - begin - State := STATE_SERVICEMODE_DIRECT_BYTEMODE_BY_BITS_VERIFY; - ServiceModeInfo.Buffer.DeviceCache.Value := %11100111; // Bit Verify, Bit = 0, Bit Index = 7, count backwards - end else - State := STATE_SERVICEMODE_DIRECT_BYTEMODE_VERIFY - end else - State := STATE_SERVICEMODE_DIRECT_BITMODE; // The Buffer.Value is already in the correct format (including the Verify/Write Bit) - NextStateAndLoadResetPacket(State, BufferPtr); -end; - -// *************************************************************************** -// procedure Direct_ByteModeByBitsResetNextStateFunc; -// -// Called when the Byte by Bit Reset runs its course, it much load the last -// Reset Packet -// *************************************************************************** -procedure Direct_ByteModeByBitsResetNextStateFunc(BufferPtr: PDCCBufferInfo); -begin - NextStateAndLoadResetPacket(STATE_SERVICEMODE_DIRECT_BYTEMODE_BY_BITS_VERIFY, BufferPtr); -end; - -// *************************************************************************** -// procedure Direct_RequestCurrentStateFunc; -// -// Called during a Direct Mode Request to send the actual request before it is -// acknowledged -// *************************************************************************** -procedure Direct_RequestCurrentStateFunc(BufferPtr: PDCCBufferInfo; Command: Byte); -var - i: Integer; -begin - BufferPtr^.TX_TransmittingPacket.PacketBytes[0] := Command or (Hi(ServiceModeInfo.Buffer.DeviceCache.Address) and %00000011); - BufferPtr^.TX_TransmittingPacket.PacketBytes[1] := Lo(ServiceModeInfo.Buffer.DeviceCache.Address); - BufferPtr^.TX_TransmittingPacket.PacketBytes[2] := ServiceModeInfo.Buffer.DeviceCache.Value; - if Command and %00001100 = %00001000 then // Is Bit Manipulation instruction? - BufferPtr^.TX_TransmittingPacket.PacketBytes[2] := %11100000 or BufferPtr^.TX_TransmittingPacket.PacketBytes[2]; // Buffer.Value must be in NMRA form xxxKDBBB where K = Read/Verify, D = Value to Read/Verify, BBB = the Bit Index to Read/Verify - BufferPtr^.TX_TransmittingPacket.Flags := 3; - BufferPtr^.TX_XOR_Byte := 0; - for i := 0 to 2 do - BufferPtr^.TX_XOR_Byte := BufferPtr^.TX_XOR_Byte xor BufferPtr^.TX_TransmittingPacket.PacketBytes[i]; - BufferPtr^.TX_PreambleBitCount := PREAMBLE_BIT_COUNT_SERVICEMODE; - Inc(ServiceModeInfo.TotalSent); -end; - -// *************************************************************************** -// procedure Direct_WriteRecoveryNextStateFunc; -// -// Called when the Write Recovery Reset Packets have completed -// *************************************************************************** -procedure Direct_WriteRecoveryNextStateFunc(BufferPtr: PDCCBufferInfo); -begin - NextStateAndLoadResetPacket(STATE_SERVICEMODE_SEQUENCE_COMPLETE, BufferPtr); -end; - -// *************************************************************************** -// procedure ServiceMode_Direct_Func -// // Parameters: None // // Result: None @@ -395,25 +242,70 @@ // StateMachine that handles a Direct CV Service Mode Programmming sequence // per the S9.2.3 spec // +// NOTE: Everytime this StateMachine is entered the Transmitter MUST BE LOADED // *************************************************************************** -procedure NMRA_DCC_DirectServiceModeStateMachine(BufferPtr: PDCCBufferInfo); +procedure DirectServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); begin - case ServiceModeInfo.iStateMachine of - STATE_SERVICEMODE_POWER_ON_CYCLE : ServiceModePowerOn(BufferPtr, @Direct_PowerOnNextStateFunc); - STATE_SERVICEMODE_RESET_CYCLE : ServiceModeReset(BufferPtr, @Direct_ResetAndTestNextStateFunc, SERVICEMODE_POWER_ON_CYCLE_RESET_COUNT, True); - STATE_SERVICEMODE_DIRECT_MODE_BIT_TEST : ServiceModeRequest(BufferPtr, @Direct_TestBitNextStateFunc, @Direct_RequestCurrentStateFunc, @Direct_AckDetectedSupportedTestFunc, %01111000, SERVICEMODE_INSTRUCTION_COUNT); - STATE_SERVICEMODE_DIRECT_MODE_BYTE_TEST : ServiceModeRequest(BufferPtr, @Direct_TestByteNextStateFunc, @Direct_RequestCurrentStateFunc, @Direct_AckDetectedSupportedTestFunc, %01110100, SERVICEMODE_INSTRUCTION_COUNT); - STATE_SERVICEMODE_DIRECT_RESET_CYCLE : ServiceModeReset(BufferPtr, @Direct_ResetAndDispatchNextStateFunc, SERVICEMODE_POWER_ON_CYCLE_RESET_COUNT, True); - STATE_SERVICEMODE_DIRECT_BITMODE : ServiceModeRequest(BufferPtr, @Direct_RequestNextStateFunc, @Direct_RequestCurrentStateFunc, @Direct_AckDetectedFunc, %01111000, SERVICEMODE_INSTRUCTION_COUNT); - STATE_SERVICEMODE_DIRECT_BYTEMODE_VERIFY : ServiceModeRequest(BufferPtr, @Direct_ByteVerifyNextStateFunc, @Direct_RequestCurrentStateFunc, @Direct_AckDetectedFunc, %01110100, SERVICEMODE_INSTRUCTION_COUNT); - STATE_SERVICEMODE_DIRECT_BYTEMODE_WRITE : ServiceModeRequest(BufferPtr, @Direct_RequestNextStateFunc, @Direct_RequestCurrentStateFunc, @Direct_AckDetectedFunc, %01111100, SERVICEMODE_INSTRUCTION_COUNT); - STATE_SERVICEMODE_DIRECT_BYTEMODE_BY_BITS_RESET : ServiceModeReset(BufferPtr, @Direct_ByteModeByBitsResetNextStateFunc, SERVICEMODE_POWER_ON_CYCLE_RESET_COUNT, True); - STATE_SERVICEMODE_DIRECT_BYTEMODE_BY_BITS_VERIFY : ServiceModeRequest(BufferPtr, @Direct_ByteByBitNextStateFunc, @Direct_RequestCurrentStateFunc, @Direct_AckDetectedByteByBitFunc, %01111000, SERVICEMODE_INSTRUCTION_COUNT); - STATE_SERVICEMODE_DIRECT_WRITE_RECOVER_CYCLE : ServiceModeReset(BufferPtr, @Direct_WriteRecoveryNextStateFunc, SERVICEMODE_WRITE_RECOVER_COUNT, False); - STATE_SERVICEMODE_SEQUENCE_COMPLETE : ServiceModeSequenceComplete(BufferPtr); - STATE_SERVICEMODE_SEND_RESET_PACKETS : ServiceModeSendResetPackets(BufferPtr); - STATE_SERVICEMODE_NOT_SUPPORTED : ServiceModeNotSupported(BufferPtr); - end; + if BufferPtr^.TX_Flags.TRANSMITTING_FLAG_STOP_BIT = 1 then + begin + case ServiceModeInfo.iStateMachine of + STATE_SERVICEMODE_POWER_ON_CYCLE : PowerOnCycle(BufferPtr); + STATE_SERVICEMODE_RESET_CYCLE : ResetCycle(BufferPtr); + STATE_SERVICEMODE_DIRECT_BYTE : + begin + if ServiceModeInfo.Flags.PROGRAMMING_ACK_DETECTED_BIT = 1 then + begin // ACK detected and we are done + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE_WRITE_ACK; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; + end else + if ServiceModeInfo.Flags.PROGRAMMING_ACK_FAILED_TO_DETECT_TRAILINGEDGE_BIT = 1 then + FailedToDetectCorrectAckWidth(BufferPtr) + else + if ServiceModeInfo.Flags.PROGRAMMING_ACK_TIMER_DETECTED_LEADINGEDGE_BIT = 1 then + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) // Ack start detected so drop into Reset Packets are either success or failure handled above after 5ms + else + if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_DIRECT_INSTRUCTION_COUNT then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00001100, ServiceModeInfo.Value); + end else + begin + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE_WRITE_NO_ACK; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_DONE; + end + end; + STATE_SERVICEMODE_DIRECT_BIT_ONE : + begin + if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_DIRECT_INSTRUCTION_COUNT then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00001000, %11110000 or ServiceModeInfo.Value) // The passed value must be in the xxxxDBBB format where D = Data and BBB is the offset 0..7 + end else + begin + // If an ACK is detected it will jump us out of this state and this will never be called + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_DONE; + end + end; + STATE_SERVICEMODE_DIRECT_WRITE_RECOVERY : + begin + if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_RECOVER_CYCLE_RESET_COUNT then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); + end else + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; + end; + STATE_SERVICEMODE_RESULTS_READY : + begin + // Spin here until the application calls ServiceMode_ReadResults to grab the Result and move to Done + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 // Don't come out of Service Mode + end; + STATE_SERVICEMODE_DONE : + begin + end; + end + end; end; end. \ No newline at end of file Modified: trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetDCC.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetDCC.mpas 2013-02-10 08:03:37 UTC (rev 2991) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetDCC.mpas 2013-02-11 04:00:28 UTC (rev 2992) @@ -40,12 +40,25 @@ MESSAGE_IDLE_0 = $FF; // Idle message = 20+8+8+1 = 37 ones; 8+3 = 11 zeros (48) = 6.84ms MESSAGE_IDLE_1 = $00; MESSAGE_IDLE_XOR = $FF; + MESSAGE_PAGE_PRESET_0 = $7D; // %01111101; + MESSAGE_PAGE_PRESET_1 = $01; // %00000001; + MESSAGE_PAGE_PRESET_XOR = $7C; // %01111100 POM_MESSAGE_REPEAT_COUNT = $03; MAX_TRACK_BUFFER_DEPTH = 16; // Max Number of Packets stored to send to the Track DCC Output MAX_TRACK_PRIORITY_BUFFER_DEPTH = 16; // Max Number of Priority Packets stored to send to the Track DCC Output + + // DCC Bit State Machine Constants + STATE_NMRA_DCC_BIT_0 = 0; + STATE_NMRA_DCC_BIT_7 = 7; + // DCC Pin State Machine Constants + STATE_NMRA_DCC_PIN_0 = 0; // First 56us + STATE_NMRA_DCC_PIN_1 = 1; // Second 56us (for a "0") + STATE_NMRA_DCC_PIN_2 = 2; // First 56us + STATE_NMRA_DCC_PIN_3 = 3; // Second 56us (for a "0") + type // *************************************************************************** // Implements the raw byte array that hold the NMRA DCC Message bytes @@ -65,8 +78,9 @@ MASK_DCC_PACKET_SPECIAL = $80; // Bit 7 = Address is special ($00 = Reset; $FF = Idle; $FE = ??? but defined in S-9.2); MASK_DCC_PACKET_ADDRESS_BITS = $F8; // Bits 3..7 All the Address Bits MASK_DCC_PACKET_INITIALIZE_FLAGS = $00; // - MASK_DCC_PACKET_IDLE_MESSAGE = $02 or MASK_DCC_PACKET_SPECIAL; - MASK_DCC_PACKET_RESET_MESSAGE = $02 or MASK_DCC_PACKET_SPECIAL; + MASK_DCC_PACKET_IDLE_MESSAGE = $02 or MASK_DCC_PACKET_SPECIAL; // 2 Bytes and it is special + MASK_DCC_PACKET_RESET_MESSAGE = $02 or MASK_DCC_PACKET_SPECIAL; // 2 Bytes and it is special + MASK_DCC_PACKET_PAGE_PRESET_MESSAGE = $02 or MASK_DCC_PACKET_SPECIAL; // 2 Bytes and it is special type TDCCPacket = record @@ -74,7 +88,7 @@ Flags: Byte; // See the QUEUE_MESSAGE_XXXXX Flags // Bit 0 1 2 = Number of Valid data bytes in the message. // Bit 3 = Address is a Multi-Function decoder with 7 bit address (short address) - // Bit 4 = Address is a Basic Accessory Decoder with 9 bit addres and Extended Accessory Decoder with 11 bit address + // Bit 4 = Address is a Basic Accessory Decoder with 9 bit address and Extended Accessory Decoder with 11 bit address // Bit 5 = Address is a Multi-Function decoder with a 14 bit address (extended address) // Bit 6 = Address is in the NMRA Reserved range // Bit 7 = Address is special ($00 = Reset; $FF = Idle; $FE = ??? but defined in S-9.2); @@ -115,7 +129,7 @@ Main: TDCCPacketList; // Main Queue Priority: TDCCPacketList; // Priorty Queue - TX_TransmittingPacket: TDCCPacket; // Message that is being currently transmitted + TX_TransmittingPacket: TDCCPacket; // Message that is being currently transmitted TX_PreambleBitCount: Byte; // Number of Preamble Bits to send, the value is destroyed when the state machine is run TX_iStateMachine: Byte; // Main State machine TX_iBit: Byte; // Index of the current Bit being sent @@ -137,6 +151,7 @@ var Track: TDCCBufferInfo; + Programming: TDCCBufferInfo; // Call once on start up procedure NMRA_DCC_Initialize; forward; @@ -152,9 +167,12 @@ procedure NMRA_DCC_LoadPacketIntoTransmitterStateMachine(ABuffer: PDCCBufferInfo; PreambleCount: Byte); // Fires the 20 Idle Packets per the NMRA Spec procedure NMRA_DCC_Packet_Init; forward; +// +procedure NMRA_DCC_ResetTransmitter(Buffer: PDCCBufferInfo); procedure NMRA_DCC_LoadIdlePacketIntoTransmitter(Buffer: PDCCBufferInfo; PreambleCount: Byte); procedure NMRA_DCC_LoadResetPacketIntoTransmitter(Buffer: PDCCBufferInfo; PreambleCount: Byte); +procedure NMRA_DCC_LoadPagePresetPacketIntoTransmitter(Buffer: PDCCBufferInfo; PreambleCount: Byte); @@ -177,26 +195,14 @@ STATE_NMRA_DCC_XOR_BYTE = 12; STATE_NMRA_DCC_STOP_BIT = 13; - // DCC Bit State Machine Constants - STATE_NMRA_DCC_BIT_0 = 0; - STATE_NMRA_DCC_BIT_7 = 7; - - // DCC Pin State Machine Constants - STATE_NMRA_DCC_PIN_0 = 0; // First 56us - STATE_NMRA_DCC_PIN_1 = 1; // Second 56us (for a "0") - STATE_NMRA_DCC_PIN_2 = 2; // First 56us - STATE_NMRA_DCC_PIN_3 = 3; // Second 56us (for a "0") - type TTrackMessageQueue = array[0..MAX_TRACK_BUFFER_DEPTH-1] of TDCCPacket; TTrackMessageQueuePriority = array[0..MAX_TRACK_PRIORITY_BUFFER_DEPTH-1] of TDCCPacket; var - TrackQueueInfo: TDCCPacketList; TrackQueue: TTrackMessageQueue; TrackQueuePriority: TTrackMessageQueuePriority; - TrackPriorityQueueInfo: TDCCPacketList; procedure InitializeBuffer(ABuffer: PDCCBufferInfo; SlotQueue, PrioritySlotQueue: PDCCPacketArray; QueueSize, QueuePrioritySize: Byte); forward; @@ -219,6 +225,7 @@ procedure NMRA_DCC_Initialize; begin InitializeBuffer(@Track, @TrackQueue, @TrackQueuePriority, MAX_TRACK_BUFFER_DEPTH, MAX_TRACK_PRIORITY_BUFFER_DEPTH); + InitializeBuffer(@Programming, nil, nil, 0, 0); end; // **************************************************************************** @@ -491,6 +498,28 @@ end; // *************************************************************************** +// procedure NMRA_DCC_LoadPagePresetPacketIntoTransmitter +// +// Parameters: +// Buffer - The buffer to load the Transmitter with +// PreambleCount - The number of preamble bits to send with the packet +// +// Result: None +// +// Description: +// Local helper function +// +// *************************************************************************** +procedure NMRA_DCC_LoadPagePresetPacketIntoTransmitter(Buffer: PDCCBufferInfo; PreambleCount: Byte); +begin + Buffer^.TX_TransmittingPacket.PacketBytes[0] := MESSAGE_PAGE_PRESET_0; + Buffer^.TX_TransmittingPacket.PacketBytes[1] := MESSAGE_PAGE_PRESET_1; + Buffer^.TX_XOR_Byte := MESSAGE_PAGE_PRESET_XOR; + Buffer^.TX_TransmittingPacket.Flags := MASK_DCC_PACKET_PAGE_PRESET_MESSAGE; // 2 Bytes and Address Is Special + Buffer^.TX_PreambleBitCount := PreambleCount; +end; + +// *************************************************************************** // procedure NMRA_DCC_LoadResetPacketIntoTransmitter // // Parameters: @@ -777,7 +806,10 @@ else ABuffer^.TX_iDCC_Pin_StateMachine := STATE_NMRA_DCC_PIN_2 // If is a one then we jump right to the back edge of the pulse width at 56us end; - STATE_NMRA_DCC_PIN_1 : Inc(ABuffer^.TX_iDCC_Pin_StateMachine); // Pin State 1 is the second "positive" 56us of a new "0" bit being sent on the DCC line, if the bit was a 1 in Pin State 0 then this state is skipped + STATE_NMRA_DCC_PIN_1 : + begin + Inc(ABuffer^.TX_iDCC_Pin_StateMachine); // Pin State 1 is the second "positive" 56us of a new "0" bit being sent on the DCC line, if the bit was a 1 in Pin State 0 then this state is skipped + end; STATE_NMRA_DCC_PIN_2 : // Pin State 2 is the first "negative" 56us of a new bit being sent on the DCC line begin ABuffer^.TX_Flags.TRANSMITTING_FLAG_DCC_PIN_BIT := 0; // Set the I/O Pin Low (negative half of the DCC cycle) @@ -794,7 +826,10 @@ end end; end; - STATE_NMRA_DCC_PIN_3 : ABuffer^.TX_iDCC_Pin_StateMachine := STATE_NMRA_DCC_PIN_0; // Pin State 3 is the second "negative" 56us of a new "0" bit being sent on the DCC line, if the bit was a 1 in Pin State 2 then this state is skipped + STATE_NMRA_DCC_PIN_3 : + begin + ABuffer^.TX_iDCC_Pin_StateMachine := STATE_NMRA_DCC_PIN_0; // Pin State 3 is the second "negative" 56us of a new "0" bit being sent on the DCC line, if the bit was a 1 in Pin State 2 then this state is skipped + end; end; end; Modified: trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetServiceMode.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetServiceMode.mpas 2013-02-10 08:03:37 UTC (rev 2991) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetServiceMode.mpas 2013-02-11 04:00:28 UTC (rev 2992) @@ -17,335 +17,94 @@ unit NMRAnetServiceMode; -const - PROGRAMMING_ACK_STATE_SCAN_FOR_ACK_BIT = 0; // Start looking for the Acknowledge bit - PROGRAMMING_ACK_STATE_DETECTED_BIT = 1; // A valid Acknowledge was detected - PROGRAMMING_ACK_STATE_RESPONSE_READY_BIT = 2; // The Service Mode ready to respond to the device - PROGRAMMING_ACK_STATE_IN_SERVICEMODE_BIT = 3; // Service Mode is enabled as far as devices are concerned (sent the Enter Service Mode Request to the device(//s) - PROGRAMMING_ACK_STATE_IDLE_BIT = 4; // Ready for the next Service Mode Request in the Queue - PROGRAMMING_ACK_STATE_MACHINE_ENABLED = 5; // Allows the StateMachine to run (the Power On Cycle will just send "1"s when not enabled) - PROGRAMMING_ACK_STATE_BITMODE_AVAILABLE = 6; // Bit mode is available +uses + NMRAnetDCC, + DirectServiceMode, + RegisterServiceMode, + PagedServiceMode, + ServiceModeDefines; - SERVICE_MODE_RESULT_SHORTCIRCUIT = 1; // System had too much current draw - SERVICE_MODE_RESULT_DATA_NOT_FOUND = 2; // No Acknowledgement was detected - SERVICE_MODE_RESULT_STATION_BUSY = 3; // Not supported in XpressNet yet - SERVICE_MODE_RESULT_STATION_READY = 4; // Not supported in XpressNet yet - SERVICE_MODE_RESULT_RESPONSE_PAGE_MODE = 5; // Response was achieved in Register or Paged mode - SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE = 6; // Response was achieved in Direct CV mode - - // The order here matters, Verifies must be lower than Writes - SERVICE_MODE_COMMMAND_VERIFY_BYTE = $01; // Service Mode to Read a decoder - SERVICE_MODE_COMMMAND_VERIFY_BIT = $02; // Service Mode to Read a decoder - SERVICE_MODE_COMMMAND_WRITE_BYTE = $03; // Service Mode to Write to a decoder - SERVICE_MODE_COMMMAND_WRITE_BIT = $04; // Service Mode to Write to a decoder - SERVICE_MODE_COMMAND_MAX_VERIFY = SERVICE_MODE_COMMMAND_VERIFY_BIT; - - SERVICE_MODE_DIRECT = $10; // Direct Service Mode - SERVICE_MODE_ADDRESS = $20; // Address Only Service Mode - SERVICE_MODE_REGISTER = $30; // Register Service Mode - SERVICE_MODE_PAGE = $40; // Page Service Mode - - SERVICE_MODE_DIRECT_TEST_BIT_ZERO_MODE = $01; // Service Mode State testing for Bit mode sending a zero - SERVICE_MODE_DIRECT_TEST_BIT_ONE_MODE = $02; // Service Mode State testing for Bit mode sending a one - SERVICE_MODE_DIRECT_TEST_BYTE_MODE = $03; // Service Mode State testing for Byte mode - - SERVICEMODE_POWER_ON_CYCLE_IDLE_COUNT = 20; // Per RP-9.2.3 - SERVICEMODE_POWER_ON_CYCLE_RESET_COUNT = 3; // Per RP-9.2.3 - SERVICEMODE_RECOVER_CYCLE_RESET_COUNT = 6; // Per RP-9.2.3 - - SERVICEMODE_INSTRUCTION_COUNT = 5; // Per RP-9.2.3 - SERVICEMODE_WRITE_RECOVER_COUNT = 6; // Per RP-9.2.3; Write Recover packets - SERVICEMODE_PAGE_PRESET_COUNT = 5; // Per RP-9.2.3; Page-Preset-packets Address-Only=5, Register=5, Page=5, Direct=N/A - SERVICEMODE_PAGE_PRESET_RECOVER = 6; // Per RP-9.2.3; Write Recovery after Page-Preset Write AddressOnly=6, Register=6, Page=6, Direct=N/A - - STATE_SERVICEMODE_POWER_ON_CYCLE = 01; - STATE_SERVICEMODE_RESET_CYCLE = 02; - STATE_SERVICEMODE_SEND_RESET_PACKETS = 03; - STATE_SERVICEMODE_NOT_SUPPORTED = 100; - STATE_SERVICEMODE_SEQUENCE_COMPLETE = 101; - - // Direct Mode - STATE_SERVICEMODE_DIRECT_MODE_BIT_TEST = 10; - STATE_SERVICEMODE_DIRECT_MODE_BYTE_TEST = 11; - STATE_SERVICEMODE_DIRECT_RESET_CYCLE = 12; - STATE_SERVICEMODE_DIRECT_BITMODE = 13; - STATE_SERVICEMODE_DIRECT_BYTEMODE_VERIFY = 14; - STATE_SERVICEMODE_DIRECT_BYTEMODE_WRITE = 15; - STATE_SERVICEMODE_DIRECT_BYTEMODE_BY_BITS_RESET = 16; - STATE_SERVICEMODE_DIRECT_BYTEMODE_BY_BITS_VERIFY = 17; - STATE_SERVICEMODE_DIRECT_WRITE_RECOVER_CYCLE = 19; - - - // Address/Register/Page - STATE_SERVICEMODE_WRITE_PAGE_PRESET = 10; - - // Paged Mode - STATE_SERVICEMODE_PAGED_WRITE_PAGE_REG_RECOVER = 11; - STATE_SERVICEMODE_PAGED_RESETCYCLE = 12; - STATE_SERVICEMODE_PAGED_VERIFY = 13; - STATE_SERVICEMODE_PAGED_WRITE = 14; - STATE_SERVICEMODE_PAGED_WRITE_RECOVER_CYCLE = 15; - - - MAX_SERVICEMODE_QUEUE_MESSAGES = 2; - - HUNG_BUS_TIMEOUT = 10; // 10 * 840ms = 8.4 seconds - -type - TServiceModeRegisterCache = record - Address: Word; // CV Address or Bit index to work on - Value: Byte; // The value of the CV or Bit value to read/write, if it is the Bit Value it MUST BE IN NMRA FORMAT "xxxKDBBB" - end; - PServiceModeRegisterCache = ^TServiceModeRegisterCache; - - TServiceModeRegisterInfo = record - DeviceCache: TServiceModeRegisterCache; // The request and the result from/to the device -// iDevice: Integer; // Device that invoked Service Mode - Mode: Byte; // High Nibble is the Service Mode type (Direct/Address/Register/Page) See SERVICE_MODE_DIRECT_XXXX and the Lo Nibble is the command type (Read/Write/ReadBit/WriteBit) See SERVICE_MODE_COMMMAND_XXXXX constants - iStateMachine: Byte; // The StateMachine State to start from after Service Mode Initialization (Power On Cycle) has been completed - end; - PServiceModeRegisterInfo = ^TServiceModeRegisterInfo; - - TServiceModeRegisterInfoArray = array[0..MAX_SERVICEMODE_QUEUE_MESSAGES-1] of TServiceModeRegisterInfo; - - TServiceModeMessageQueue = record - Messages: TServiceModeRegisterInfoArray; - Count, // Number of messages in the queue - ResultRequestCount, // Number of times the ServiceMode Results request has been sent - iHead, // Head (next empty) buffer index - iTail: Byte; // Tail (next to use/currently being used) buffer index - end; - - TServiceModeInfo = record - Queue : TServiceModeMessageQueue; // Waiting Service Mode Requests - Flags : Byte; // See PROGRAMMING_ACK_STATE_XXXXX constants - Buffer : TServiceModeRegisterInfo; // Buffer of the request being worked on - ScratchBuffer : TServiceModeRegisterCache; // Buffer to use for - DirectSupportTest : Byte; // Tracks the different tests needed to understand if Direct Mode is supported and how fully it is supported (Bit mode) - iStateMachine : Byte; // Current State of the Service Mode State Machine - iInstructionCountSent : Byte; // State Machine uses to count the number of Packets for different states of a Service Mode call - ServiceModeResult : Byte; // [OUT] The result of executing the Service Mode SEE SERVICE_MODE_RESULT_XXXXX constant - TotalSent : Word; // Total packets sent for the call - HungBusTimer : Byte; // Number of 840ms timer ticks have occured - end; - PServiceModeInfo = ^TServiceModeInfo; - // Call once on start up procedure ServiceMode_Initialize; forward; -// Stops the Service Mode Engine -procedure ServiceMode_End; forward; -// Resets the Engine and prepares it to run Service Mode Commands -procedure ServiceMode_LoadBufferFromNextInQueue(PowerOnCycle: Boolean); forward; +//procedure ServiceMode_LoadBufferFromNextInQueue(PowerOnCycle: Boolean); forward; +procedure ServiceMode_EngageServiceMode(BufferPtr: PDCCBufferInfo; PowerOnCycle: Boolean; AReadWrite, AServiceModeType: Byte; ACV: Word; Value: Byte); // Called by a timer that ticks every 56us or so procedure ServiceMode_56us_TimeTick; forward; // Called by a timer that ticks every 5ms procedure ServiceMode_5ms_TimeTick; forward; // Called by a timer that ticks every 5ms -procedure ServiceMode_840ms_TimeTick; forward; -// Places the Service Mode Message in the Queue -function ServiceMode_QueueRequest(AnAddress: Word; AValue: Byte; iDevice: Integer; Mode, iStateMachine: Byte): Boolean; -// Clears necessary Flags and Variables to start a new Service Mode Ack run -procedure ServiceMode_ResetForNewAck; -// Flushes (clears) the Request Queue -procedure ClearRequestQueue; +procedure ServiceMode_100ms_TimeTick; forward; +// Runs the statemachine from the Stop Bit of the DCC Transmitter Statemachine +procedure ServiceMode_StateMachine(BufferPtr: PDCCBufferInfo); +// Tests if the statemachine is in a mode where it is waiting to have the results of the operation read +function ServiceMode_ReadResults: Boolean; +// Ends the Statemachine (after a completed read/write cycle) +procedure ServiceMode_Quit; -const - MFG_CV_ID_BIT_7_EQUALS_ZERO: TServiceModeRegisterCache = (7, %11100111); // CV 8 = Manufactures ID, Set up to Verify a 0 in Bit 7 of CV 8 - MFG_CV_ID_BIT_7_EQUALS_ONE: TServiceModeRegisterCache = (7, %11101111); // CV 8 = Manufactures ID, Set up to Verify a 1 in Bit 7 of CV 8 - MFG_CV_ID: TServiceModeRegisterCache = (7, 0); // CV 8 = Manufactures ID, Set up to Verify starting at a value of 1 - var - ServiceModeInfo: TServiceModeInfo; - DCC_Programming_ACK_Pin : sbit; sfr; external; DCC_Programming_ACK_Direction : sbit; sfr; external; + Ack_TimerEnabled_Bit : sbit; sfr; external; implementation + procedure ServiceMode_Initialize; var i: Integer; - Buffer: PServiceModeRegisterInfo; begin - for i := 0 to MAX_SERVICEMODE_QUEUE_MESSAGES - 1 do - begin - Buffer := @ServiceModeInfo.Queue.Messages[i]; - Buffer^.Mode := 0; - Buffer^.DeviceCache.Value := 0; - Buffer^.DeviceCache.Address := 0; - Buffer^.iStateMachine := STATE_SERVICEMODE_RESET_CYCLE; // Default - // Buffer^.iDevice := ID_NO_DEVICE; - end; - ServiceModeInfo.Queue.Count := 0; - ServiceModeInfo.Queue.iHead := 0; - ServiceModeInfo.Queue.iTail := 0; - ServiceModeInfo.Queue.ResultRequestCount := 0; - - ServiceModeInfo.Buffer.DeviceCache.Address := 0; - ServiceModeInfo.Buffer.DeviceCache.Value := 0; - // ServiceModeInfo.Buffer.iDevice := ID_NO_DEVICE; - ServiceModeInfo.Buffer.Mode := 0; - - ServiceModeInfo.ScratchBuffer.Address := 0; - ServiceModeInfo.ScratchBuffer.Value := 0; ServiceModeInfo.Flags := 0; - ServiceModeInfo.Flags.PROGRAMMING_ACK_STATE_IDLE_BIT := 1; ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_DATA_NOT_FOUND; ServiceModeInfo.iInstructionCountSent :... [truncated message content] |