From: <jim...@us...> - 2013-03-31 01:18:41
|
Revision: 3113 http://sourceforge.net/p/openlcb/svn/3113 Author: jimkueneman626 Date: 2013-03-31 01:18:34 +0000 (Sun, 31 Mar 2013) Log Message: ----------- reworked OLCB CS code for service mode Modified Paths: -------------- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/DirectServiceMode.mpas trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetServiceMode.mpas trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/PagedServiceMode.mpas trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/RegisterServiceMode.mpas trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/ServiceModeDefines.mpas trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/NMRAnetAppCallbacks.mpas trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/dsPIC33EP_NMRABusCommandStation.hex trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/dsPIC33EP_NMRABusCommandStation.mppds trunk/prototypes/mikroPascal/dsPIC33EP256_CommandStation/dsPIC33EP_NMRAnetCommandStation.mpas Added Paths: ----------- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/CommonServiceMode.mpas Added: trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/CommonServiceMode.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/CommonServiceMode.mpas (rev 0) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/CommonServiceMode.mpas 2013-03-31 01:18:34 UTC (rev 3113) @@ -0,0 +1,142 @@ +// ****************************************************************************** +// +// Copyright: +// (c) Mustangpeak, 2013. +// +// The contents of this file are subject to the GNU GPL v3 licence/ you maynot use +// this file except in compliance with the License. You may obtain a copy of the +// License at http://www.gnu.org/licenses/gpl.html +// +// * Revision History: +// 2013-03-29: Created +// +// * Description: +// Common Service Mode functions +// +// ****************************************************************************** + +unit CommonServiceMode; + +uses + NMRAnetDCC, + ServiceModeDefines, + NMRAnetDefinesShared; + +type + TServiceModePtr = procedure(BufferPtr: PDCCBufferInfo); + PServiceModePtr = ^TServiceModePtr; + + + procedure PowerOnCycle(BufferPtr: PDCCBufferInfo; InstructionCount, NextState: Word); + procedure ResetCycle(BufferPtr: PDCCBufferInfo; InstructionPtr: PServiceModePtr; PacketCount: Word; NextState: Word; PrepareForAck: Boolean); + procedure SendInstructions(BufferPtr: PDCCBufferInfo; SendInstruction, AckHandler, NoAckHandler: PServiceModePtr; InstructionCount: Word); + procedure ResultReady(BufferPtr: PDCCBufferInfo); + +implementation + +procedure ResetACK; +begin + ServiceModeInfo.Flags.PROGRAMMING_ACK_SCANNING_FOR_ACK_BIT := 1; // Start Looking + 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; +end; + +// *************************************************************************** +// procedure PowerOnCycle +// +// Parameters: None +// +// Result: None +// +// Description: +// *************************************************************************** +procedure PowerOnCycle(BufferPtr: PDCCBufferInfo; InstructionCount, NextState: Word); +begin + if ServiceModeInfo.iInstructionCountSent < InstructionCount then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + NMRA_DCC_LoadIdlePacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) + end else + begin + ServiceModeInfo.iInstructionCountSent := 1; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Next State is always a Reset Packet for all Modes + ServiceModeInfo.iStateMachine := NextState + end +end; + +// *************************************************************************** +// procedure ResetCycle +// +// Parameters: None +// +// Result: None +// +// Description: +// *************************************************************************** +procedure ResetCycle(BufferPtr: PDCCBufferInfo; InstructionPtr: PServiceModePtr; PacketCount: Word; NextState: Word; PrepareForAck: Boolean); +begin + if ServiceModeInfo.iInstructionCountSent < PacketCount then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) + end else + begin + ServiceModeInfo.iInstructionCountSent := 1; + InstructionPtr(BufferPtr); + ServiceModeInfo.iStateMachine := NextState; + if PrepareForAck then + ResetACK; + end; +end; + +// *************************************************************************** +// procedure SendInstructions +// +// Parameters: None +// +// Result: None +// +// Description: +// *************************************************************************** +procedure SendInstructions(BufferPtr: PDCCBufferInfo; SendInstruction, AckHandler, NoAckHandler: PServiceModePtr; InstructionCount: Word); +begin + if ServiceModeInfo.Flags.PROGRAMMING_ACK_DETECTED_BIT = 1 then + begin // ACK detected and we are done + AckHandler(BufferPtr); + end else + if ServiceModeInfo.Flags.PROGRAMMING_ACK_FAILED_TO_DETECT_TRAILINGEDGE_BIT = 1 then + begin + ServiceModeInfo.Value := 0; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_SHORT_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_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 < InstructionCount then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + SendInstruction(BufferPtr); + end else + NoAckHandler(BufferPtr) + end +end; + +// *************************************************************************** +// procedure ResultReady +// +// Parameters: None +// +// Result: None +// +// Description: +// *************************************************************************** +procedure ResultReady(BufferPtr: PDCCBufferInfo); +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; + +end. \ No newline at end of file Modified: trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/DirectServiceMode.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/DirectServiceMode.mpas 2013-03-30 03:56:19 UTC (rev 3112) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/DirectServiceMode.mpas 2013-03-31 01:18:34 UTC (rev 3113) @@ -2,12 +2,13 @@ uses NMRAnetDCC, + CommonServiceMode, NMRAnetDefinesShared, ServiceModeDefines; - procedure DirectServiceMode_StateMachineRead(BufferPtr: PDCCBufferInfo); - procedure DirectServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); + procedure DirectBitServiceMode_StateMachine(BufferPtr: PDCCBufferInfo); + procedure DirectByteServiceMode_StateMachine(BufferPtr: PDCCBufferInfo); implementation @@ -35,7 +36,7 @@ end; // *************************************************************************** -// procedure PowerOnCycle +// procedure NextBitAndTestForCompletion // // Parameters: None // @@ -43,22 +44,23 @@ // // Description: // *************************************************************************** -procedure PowerOnCycle(BufferPtr: PDCCBufferInfo); +procedure NextBitAndTestForCompletion(BufferPtr: PDCCBufferInfo); begin - if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_POWER_ON_CYCLE_IDLE_COUNT then + Inc(ServiceModeInfo.ReadIndex); // Try the next Bit + if ServiceModeInfo.ReadIndex < 8 then // Have we run all the bits? begin - Inc(ServiceModeInfo.iInstructionCountSent); - NMRA_DCC_LoadIdlePacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) + ServiceModeInfo.iInstructionCountSent := 1; // Run the next bit cycle + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESET_CYCLE; end else begin - ServiceModeInfo.iInstructionCountSent := 1; - NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESET_CYCLE - end + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_BIT_MODE; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY + end; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); end; // *************************************************************************** -// procedure ResetCycle +// procedure InstructionSendBit // // Parameters: None // @@ -66,43 +68,16 @@ // // Description: // *************************************************************************** -procedure ResetCycle(BufferPtr: PDCCBufferInfo); +procedure InstructionSendBit(BufferPtr: PDCCBufferInfo); begin - 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 + if ServiceModeInfo.ReadWrite = SERVICEMODE_WRITE then + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV-1, %00001000, %11110000 or ((ServiceModeInfo.Value) shl 3) or ServiceModeInfo.ReadIndex) // The passed value must be in the xxxxDBBB format where D = Data and BBB is the offset 0..7 + else + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV-1, %00001000, %11101000 or ServiceModeInfo.ReadIndex); // Always trying to read ones and assuming zeros if no response end; // *************************************************************************** -// procedure NextBitAndTestForCompletion +// procedure AckHandlerBit // // Parameters: None // @@ -110,23 +85,17 @@ // // Description: // *************************************************************************** -procedure NextBitAndTestForCompletion(BufferPtr: PDCCBufferInfo); +procedure AckHandlerBit(BufferPtr: PDCCBufferInfo); +var + BitOffset: Byte; begin - 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 - ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE_READ; - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY - end; - NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); + BitOffset := ServiceModeInfo.ReadIndex; + ServiceModeInfo.Value.BitOffset := 1; // Set the offset to 1 (default is 0) + NextBitAndTestForCompletion(BufferPtr); end; // *************************************************************************** -// procedure FailedToDetectCorrectAckWidth +// procedure NoAckHandlerBit // // Parameters: None // @@ -134,118 +103,115 @@ // // Description: // *************************************************************************** -procedure FailedToDetectCorrectAckWidth(BufferPtr: PDCCBufferInfo); +procedure NoAckHandlerBit(BufferPtr: PDCCBufferInfo); begin - ServiceModeInfo.Value := 0; - ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_MODE_SHORT_ACK; + NextBitAndTestForCompletion(BufferPtr); +end; + +// *************************************************************************** +// procedure InstructionSendByte +// +// Parameters: None +// +// Result: None +// +// Description: +// *************************************************************************** +procedure InstructionSendByte(BufferPtr: PDCCBufferInfo); +begin + if ServiceModeInfo.ReadWrite = SERVICEMODE_WRITE then + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV-1, %00001100, ServiceModeInfo.ReadIndex) + else + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV-1, %00000100, ServiceModeInfo.ReadIndex); +end; + +// *************************************************************************** +// procedure AckHandlerByte +// +// Parameters: None +// +// Result: None +// +// Description: +// *************************************************************************** +procedure AckHandlerByte(BufferPtr: PDCCBufferInfo); +begin + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_DIRECT_BYTE_MODE; NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; + + if ServiceModeInfo.ReadWrite = SERVICEMODE_WRITE then + begin // Write + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_DIRECT_WRITE_RECOVERY; + end else + begin // Read + ServiceModeInfo.Value := ServiceModeInfo.ReadIndex; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; + end; end; - + // *************************************************************************** -// procedure DirectServiceMode_StateMachineRead +// procedure NoAckHandlerByte // // Parameters: None // // Result: None // // Description: +// *************************************************************************** +procedure NoAckHandlerByte(BufferPtr: PDCCBufferInfo); +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; // Rurun it + end; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); +end; + +// *************************************************************************** +// procedure DirectByteServiceMode_StateMachine +// +// Parameters: None +// +// Result: None +// +// Description: // 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 DirectServiceMode_StateMachineRead(BufferPtr: PDCCBufferInfo); -const - QUICK_LOOK_COUNT = 5; - QUICK_LOOK_ARRAY: array[0..QUICK_LOOK_COUNT -1] of byte = (255, 128, 32, 64, 192); -var - BitOffset: Byte; +procedure DirectByteServiceMode_StateMachine(BufferPtr: PDCCBufferInfo); begin // Only update when we see the stop bit and need to update for the next packet sent 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.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 - // if ServicModeInfo.QuickLookIndex < QUICK_LOOK_COUNT then - // begin - // Inc(ServicModeInfo.QuickLookIndex); - // ServiceModeInfo.iInstructionCountSent := 1; // Run the next possible Value cycle - // NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); - // 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 - 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; + if ServiceModeInfo.CV <= SERVICE_MODE_DIRECT_MODE_MAX_CV then + begin + case ServiceModeInfo.iStateMachine of + STATE_SERVICEMODE_POWER_ON_CYCLE : PowerOnCycle(BufferPtr, SERVICEMODE_POWER_ON_CYCLE_IDLE_COUNT, STATE_SERVICEMODE_RESET_CYCLE); + STATE_SERVICEMODE_RESET_CYCLE : ResetCycle(BufferPtr, @InstructionSendByte, SERVICEMODE_POWER_ON_CYCLE_RESET_COUNT, STATE_SERVICEMODE_SEND_INSTRUCTION, True); + STATE_SERVICEMODE_SEND_INSTRUCTION : SendInstructions(BufferPtr, @InstructionSendByte, @AckHandlerByte, @NoAckHandlerByte, SERVICEMODE_DIRECT_INSTRUCTION_COUNT); + STATE_SERVICEMODE_DIRECT_WRITE_RECOVERY : ResetCycle(BufferPtr, @InstructionSendByte, SERVICEMODE_RECOVER_CYCLE_RESET_COUNT, STATE_SERVICEMODE_RESULTS_READY, True); + STATE_SERVICEMODE_RESULTS_READY : ResultReady(BufferPtr); + end + end else + begin + ServiceModeInfo.Value := 0; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_INVALID_CV; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; end end; end; // *************************************************************************** -// procedure DirectServiceMode_StateMachineWrite +// procedure DirectBitServiceMode_StateMachine // // Parameters: None // @@ -257,66 +223,28 @@ // // NOTE: Everytime this StateMachine is entered the Transmitter MUST BE LOADED // *************************************************************************** -procedure DirectServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); +procedure DirectBitServiceMode_StateMachine(BufferPtr: PDCCBufferInfo); +var + BitOffset: Byte; begin + // Only update when we see the stop bit and need to update for the next packet sent 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; + if ServiceModeInfo.CV <= SERVICE_MODE_DIRECT_MODE_MAX_CV then + begin + case ServiceModeInfo.iStateMachine of + STATE_SERVICEMODE_POWER_ON_CYCLE : PowerOnCycle(BufferPtr, SERVICEMODE_POWER_ON_CYCLE_IDLE_COUNT, STATE_SERVICEMODE_RESET_CYCLE); + STATE_SERVICEMODE_RESET_CYCLE : ResetCycle(BufferPtr, @InstructionSendBit, SERVICEMODE_POWER_ON_CYCLE_RESET_COUNT, STATE_SERVICEMODE_SEND_INSTRUCTION, True); + STATE_SERVICEMODE_SEND_INSTRUCTION : SendInstructions(BufferPtr, @InstructionSendBit, @AckHandlerBit, @NoAckHandlerBit, SERVICEMODE_DIRECT_INSTRUCTION_COUNT); + STATE_SERVICEMODE_DIRECT_WRITE_RECOVERY : ResetCycle(BufferPtr, @InstructionSendBit, SERVICEMODE_RECOVER_CYCLE_RESET_COUNT, STATE_SERVICEMODE_RESULTS_READY, True); + STATE_SERVICEMODE_RESULTS_READY : ResultReady(BufferPtr); + end + end else + begin + ServiceModeInfo.Value := 0; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_INVALID_CV; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; end end; end; Modified: trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetServiceMode.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetServiceMode.mpas 2013-03-30 03:56:19 UTC (rev 3112) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/NMRAnetServiceMode.mpas 2013-03-31 01:18:34 UTC (rev 3113) @@ -1,7 +1,7 @@ // ****************************************************************************** // // Copyright: -// (c) Mustangpeak, 2011. +// (c) Mustangpeak, 2013. // // The contents of this file are subject to the GNU GPL v3 licence/ you maynot use // this file except in compliance with the License. You may obtain a copy of the @@ -27,7 +27,7 @@ // Call once on start up procedure ServiceMode_Initialize; forward; //procedure ServiceMode_LoadBufferFromNextInQueue(PowerOnCycle: Boolean); forward; -procedure ServiceMode_EngageServiceMode(BufferPtr: PDCCBufferInfo; PowerOnCycle: Boolean; AReadWrite, AServiceModeType: Byte; ACV: Word; Value: Byte); +procedure ServiceMode_EngageServiceMode(BufferPtr: PDCCBufferInfo; PowerOnCycle: Boolean; AReadWrite, AServiceModeType: Byte; ACV: Word; Value, BitIndex: Byte); // Called by a timer that ticks every 56us or so procedure ServiceMode_56us_TimeTick; forward; // Called by a timer that ticks every 5ms @@ -56,7 +56,7 @@ ServiceModeInfo.Flags := 0; ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_DATA_NOT_FOUND; ServiceModeInfo.iInstructionCountSent := 0; - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_DONE; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_IDLE; DCC_Programming_ACK_Direction := 1; // Input end; @@ -65,13 +65,14 @@ // // Parameters: // AValue: If the state is Direct Mode Bit Write this contains the following: xxxxDBBB where BBB is the bit offset (0..7) and D is the Data to write +// ACV: Defined as 1..1024 per NMRA Spec // // Results: None // // Description: // // **************************************************************************** -procedure ServiceMode_EngageServiceMode(BufferPtr: PDCCBufferInfo; PowerOnCycle: Boolean; AReadWrite, AServiceModeType: Byte; ACV: Word; AValue: Byte); +procedure ServiceMode_EngageServiceMode(BufferPtr: PDCCBufferInfo; PowerOnCycle: Boolean; AReadWrite, AServiceModeType: Byte; ACV: Word; AValue, BitIndex: Byte); begin NMRA_DCC_ResetTransmitter(@Programming); ServiceModeInfo.ReadWrite := AReadWrite; // SERVCIE_MODE_READ or SERVCIE_MODE_WRITE @@ -85,12 +86,14 @@ ServiceModeInfo.ReadIndex := 0; // Redefined as the Index of bits into the Byte if AReadWrite = SERVICEMODE_READ then ServiceModeInfo.Value := 0 // Ready to receive data (we only look for "1" and default to "0" if "1" does not reply - else - ServiceModeInfo.Value := AValue; // Value to write to the decoder in Bit Mode + else begin + ServiceModeInfo.ReadIndex := BitIndex; // Setup the index of the Bit to write (0..7) + ServiceModeInfo.Value := AValue; // Value to write to the decoder in Bit Mode (must be 0 or 1) + end end else begin - ServiceModeInfo.ReadIndex := AValue; // Were to start looking if Reading - ServiceModeInfo.Value := AValue; + ServiceModeInfo.ReadIndex := AValue; // Were to start looking if Reading + ServiceModeInfo.Value := AValue; end; if PowerOnCycle then // Reset the StateMachine begin @@ -171,30 +174,16 @@ procedure ServiceMode_StateMachine(BufferPtr: PDCCBufferInfo); begin - case ServiceModeInfo.ReadWrite of - SERVICEMODE_READ : - begin - case ServiceModeInfo.ServiceModeType of - SERVICE_MODE_TYPE_DIRECT_BYTE, - SERVICE_MODE_TYPE_DIRECT_BIT : DirectServiceMode_StateMachineRead(BufferPtr); - SERVICE_MODE_TYPE_PHYSICAL_REGISTER, - SERVICE_MODE_TYPE_ADDRESS_ONLY : RegisterServiceMode_StateMachineRead(BufferPtr); - SERVICE_MODE_TYPE_PAGED : PagedServiceMode_StateMachineRead(BufferPtr); - end - end; - SERVICEMODE_WRITE : - begin - case ServiceModeInfo.ServiceModeType of - SERVICE_MODE_TYPE_DIRECT_BYTE, - SERVICE_MODE_TYPE_DIRECT_BIT : DirectServiceMode_StateMachineWrite(BufferPtr); - SERVICE_MODE_TYPE_PHYSICAL_REGISTER, - SERVICE_MODE_TYPE_ADDRESS_ONLY : RegisterServiceMode_StateMachineWrite(BufferPtr); - SERVICE_MODE_TYPE_PAGED : PagedServiceMode_StateMachineRead(BufferPtr); - end - end; - end; + case ServiceModeInfo.ServiceModeType of + SERVICE_MODE_TYPE_DIRECT_BYTE : DirectByteServiceMode_StateMachine(BufferPtr); + SERVICE_MODE_TYPE_DIRECT_BIT : DirectBitServiceMode_StateMachine(BufferPtr); + // SERVICE_MODE_TYPE_PHYSICAL_REGISTER, + // SERVICE_MODE_TYPE_ADDRESS_ONLY : RegisterServiceMode_StateMachineRead(BufferPtr); + // SERVICE_MODE_TYPE_PAGED : PagedServiceMode_StateMachineRead(BufferPtr); + end end; + function ServiceMode_ResultsReady: Boolean; begin Result := False; @@ -204,7 +193,7 @@ procedure ServiceMode_Quit; begin - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_DONE + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_IDLE end; end. \ No newline at end of file Modified: trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/PagedServiceMode.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/PagedServiceMode.mpas 2013-03-30 03:56:19 UTC (rev 3112) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/PagedServiceMode.mpas 2013-03-31 01:18:34 UTC (rev 3113) @@ -2,14 +2,16 @@ uses NMRAnetDCC, + CommonServiceMode, + NMRAnetDefinesShared, ServiceModeDefines; - procedure PagedServiceMode_StateMachineRead(BufferPtr: PDCCBufferInfo); - procedure PagedServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); + // procedure PagedServiceMode_StateMachineRead(BufferPtr: PDCCBufferInfo); + // procedure PagedServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); implementation - + { // *************************************************************************** // procedure DirectLoadTransmitter // @@ -66,20 +68,29 @@ // *************************************************************************** procedure PowerOnResetCycle(BufferPtr: PDCCBufferInfo); begin + if ServiceModeInfo.CV < SERVICE_MODE_PAGED_MODE_MAX_CV then + begin 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 + // Prepare to write to the Paging Register 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.Flags.PROGRAMMING_ACK_SCANNING_FOR_ACK_BIT := 1; // Start Looking since we are now sending the read instruction + ServiceModeInfo.Flags.PROGRAMMING_ACK_SCANNING_FOR_ACK_BIT := 1; // Start Looking since we are now sending the write instruction ServiceModeInfo.iInstructionCountSent := 1; - DirectLoadTransmitter(BufferPtr, 5, %00001000, ServiceModeInfo.ReadIndex div 4); // Page Register is Register 6 (RRR = 5) + DirectLoadTransmitter(BufferPtr, %00000101, %00001000, (ServiceModeInfo.CV-1) div 4); // Page Register is Register 6 (RRR = 5) ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_PAGED_WRITE_PAGE_REGISTER; + end else + begin + ServiceModeInfo.Value := 0; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_INVALID_CV; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; end end; @@ -94,14 +105,18 @@ // *************************************************************************** procedure PageRegisterWriteCycle(BufferPtr: PDCCBufferInfo); begin - if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_PAGED_PAGE_WRITE_COUNT then + if (ServiceModeInfo.iInstructionCountSent < SERVICEMODE_PAGED_PAGE_WRITE_COUNT) and (ServiceModeInfo.Flags.PROGRAMMING_ACK_DETECTED_BIT = 0) then begin Inc(ServiceModeInfo.iInstructionCountSent); - DirectLoadTransmitter(BufferPtr, 5, %00001000, ServiceModeInfo.ReadIndex div 4); // Page Register is Register 6 (RRR = 5) + DirectLoadTransmitter(BufferPtr, %00000101, %00001000, (ServiceModeInfo.CV-1) div 4); end else begin ServiceModeInfo.iInstructionCountSent := 1; NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); + 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.Flags.PROGRAMMING_ACK_SCANNING_FOR_ACK_BIT := 0; ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_PAGED_WRITE_PAGE_REGISTER_RECOVER; end end; @@ -128,11 +143,12 @@ NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); end else begin + ServiceModeInfo.Flags.PROGRAMMING_ACK_SCANNING_FOR_ACK_BIT := 1; // Start Looking ServiceModeInfo.iInstructionCountSent := 1; if ServiceModeInfo.ReadWrite = SERVICEMODE_WRITE then - DirectLoadTransmitter(BufferPtr, ServiceModeInfo.ReadIndex mod 4, %00001000, ServiceModeInfo.ReadIndex div 4) + DirectLoadTransmitter(BufferPtr, (ServiceModeInfo.CV-1) mod 4, %00001000, ServiceModeInfo.ReadIndex) else - DirectLoadTransmitter(BufferPtr, ServiceModeInfo.ReadIndex mod 4, %00000000, ServiceModeInfo.ReadIndex div 4); + DirectLoadTransmitter(BufferPtr, (ServiceModeInfo.CV-1) mod 4, %00000000, ServiceModeInfo.ReadIndex); ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_PAGED_REGISTER; end end; @@ -153,7 +169,7 @@ NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; end; - + // *************************************************************************** // procedure PagedServiceMode_StateMachineRead // @@ -177,14 +193,14 @@ STATE_SERVICEMODE_PAGED_WRITE_PAGE_REGISTER : PageRegisterWriteCycle(BufferPtr); STATE_SERVICEMODE_PAGED_WRITE_PAGE_REGISTER_RECOVER : PageRegisterWriteRecoverResetCycle(BufferPtr); STATE_SERVICEMODE_PAGED_INSTRUCTION_RESET : InstructionResetCycle(BufferPtr); - STATE_SERVICEMODE_PAGED_REGISTER : + STATE_SERVICEMODE_PAGED_REGISTER : begin if ServiceModeInfo.Flags.PROGRAMMING_ACK_DETECTED_BIT = 1 then - begin // ACK detected and we are done - ServiceModeInfo.Value := ServiceModeInfo.ReadIndex; + begin // ACK detected and we are done + ServiceModeInfo.Value := ServiceModeInfo.ReadIndex; ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_PAGED_MODE_READ; NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY end else if ServiceModeInfo.Flags.PROGRAMMING_ACK_FAILED_TO_DETECT_TRAILINGEDGE_BIT = 1 then FailedToDetectCorrectAckWidth(BufferPtr) @@ -195,7 +211,7 @@ if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_PAGED_INSTRUCTION_COUNT then begin Inc(ServiceModeInfo.iInstructionCountSent); - DirectLoadTransmitter(BufferPtr, ServiceModeInfo.ReadIndex mod 4, %00000000, ServiceModeInfo.ReadIndex div 4); + RegisterOperation(BufferPtr, (ServiceModeInfo.CV-1) mod 4, %00000000, ServiceModeInfo.ReadIndex); end else begin Inc(ServiceModeInfo.ReadIndex); // Try the next Value @@ -206,7 +222,7 @@ end else begin ServiceModeInfo.iInstructionCountSent := 1; // Run the next possible Value cycle - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_PAGED_INSTRUCTION_RESET; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESET_CYCLE; // NOTE: CAN GET 4 VALUE FROM 1 WRITE TO THE PAGE REGISTER BUT NEED TO BE CAREFUL WITH MOD 4 NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); end end; @@ -217,9 +233,6 @@ // 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; @@ -247,14 +260,14 @@ STATE_SERVICEMODE_PAGED_WRITE_PAGE_REGISTER : PageRegisterWriteCycle(BufferPtr); STATE_SERVICEMODE_PAGED_WRITE_PAGE_REGISTER_RECOVER : PageRegisterWriteRecoverResetCycle(BufferPtr); STATE_SERVICEMODE_PAGED_INSTRUCTION_RESET : InstructionResetCycle(BufferPtr); - STATE_SERVICEMODE_PAGED_REGISTER : - begin + STATE_SERVICEMODE_PAGED_REGISTER : + 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_PAGED_MODE_READ; + begin // ACK detected and we are done + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_PAGED_MODE_WRITE; NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; + ServiceModeInfo.iInstructionCountSent := 1; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_PAGED_WRITE_RECOVERY; end else if ServiceModeInfo.Flags.PROGRAMMING_ACK_FAILED_TO_DETECT_TRAILINGEDGE_BIT = 1 then FailedToDetectCorrectAckWidth(BufferPtr) @@ -265,24 +278,33 @@ if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_PAGED_INSTRUCTION_COUNT then begin Inc(ServiceModeInfo.iInstructionCountSent); - DirectLoadTransmitter(BufferPtr, ServiceModeInfo.ReadIndex mod 4, %00001000, ServiceModeInfo.ReadIndex div 4); + RegisterOperation(BufferPtr, (ServiceModeInfo.CV-1) mod 4, %00001000, ServiceModeInfo.ReadIndex); end else begin - ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_PAGED_MODE_WRITE_NO_ACK; - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_DONE; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_PAGED_MODE_WRITE_NO_ACK; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY end; end; - end; + end; + STATE_SERVICEMODE_PAGED_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 + begin + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_PAGED_MODE_WRITE; + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY + end; + 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/RegisterServiceMode.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/RegisterServiceMode.mpas 2013-03-30 03:56:19 UTC (rev 3112) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/RegisterServiceMode.mpas 2013-03-31 01:18:34 UTC (rev 3113) @@ -2,14 +2,16 @@ uses NMRAnetDCC, + CommonServiceMode, + NMRAnetDefinesShared, ServiceModeDefines; - procedure RegisterServiceMode_StateMachineRead(BufferPtr: PDCCBufferInfo); - procedure RegisterServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); +// procedure RegisterServiceMode_StateMachineRead(BufferPtr: PDCCBufferInfo); +// procedure RegisterServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); implementation - + { // *************************************************************************** // procedure DirectLoadTransmitter // @@ -19,16 +21,15 @@ // // Description: // *************************************************************************** -procedure DirectLoadTransmitter(BufferPtr: PDCCBufferInfo; CV_Address: Word; InstructionCode, DataByte: Byte); +procedure DirectLoadTransmitter(BufferPtr: PDCCBufferInfo; RegisterOffset, ReadWrite, DataByte: Byte); var i: Integer; begin - 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_TransmittingPacket.PacketBytes[0] := %01110000 or ReadWrite or RegisterOffset; + BufferPtr^.TX_TransmittingPacket.PacketBytes[1] := DataByte; + BufferPtr^.TX_TransmittingPacket.Flags := 2; BufferPtr^.TX_XOR_Byte := 0; - for i := 0 to 2 do + for i := 0 to 1 do BufferPtr^.TX_XOR_Byte := BufferPtr^.TX_XOR_Byte xor BufferPtr^.TX_TransmittingPacket.PacketBytes[i]; BufferPtr^.TX_PreambleBitCount := PREAMBLE_BIT_COUNT_SERVICEMODE; end; @@ -44,15 +45,24 @@ // *************************************************************************** procedure PowerOnCycle(BufferPtr: PDCCBufferInfo); begin - if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_POWER_ON_CYCLE_IDLE_COUNT then + if ServiceModeInfo.CV < SERVICE_MODE_REGISTER_MODE_MAX_CV then begin - Inc(ServiceModeInfo.iInstructionCountSent); - NMRA_DCC_LoadIdlePacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) + if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_POWER_ON_CYCLE_IDLE_COUNT then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + NMRA_DCC_LoadIdlePacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) + end else + begin + ServiceModeInfo.iInstructionCountSent := 1; + NMRA_DCC_LoadPagePresetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_REGISTER_PRESET_CYCLE + end end else begin - ServiceModeInfo.iInstructionCountSent := 1; - NMRA_DCC_LoadPagePresetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_REGISTER_PRESET_CYCLE + ServiceModeInfo.Value := 0; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_INVALID_CV; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; end end; @@ -65,25 +75,38 @@ // // Description: // *************************************************************************** -procedure ResetCycle(BufferPtr: PDCCBufferInfo); +procedure ResetCycle(BufferPtr: PDCCBufferInfo; PacketCount: Word; NextState: Word; PrepareForAck, SendInstruction: Boolean); begin - if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_POWER_ON_CYCLE_RESET_COUNT then + if ServiceModeInfo.iInstructionCountSent < PacketCount then begin Inc(ServiceModeInfo.iInstructionCountSent); NMRA_DCC_LoadPagePresetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) end else begin - ServiceModeInfo.Flags.PROGRAMMING_ACK_SCANNING_FOR_ACK_BIT := 1; // Start Looking????? + ServiceModeInfo.iInstructionCountSent := 1; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); + ServiceModeInfo.iStateMachine := NextState; + end; + + if PrepareForAck then + begin + ServiceModeInfo.Flags.PROGRAMMING_ACK_SCANNING_FOR_ACK_BIT := 1; // Start Looking 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; - + end; - ServiceModeInfo.iInstructionCountSent := 1; - NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); - ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_REGISTER_PRESET_CYCLE + if SendInstruction then + begin + ServiceModeInfo.iInstructionCountSent := 1; + if ServiceModeInfo.ReadWrite = SERVICEMODE_WRITE then + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV-1, %00001000, ServiceModeInfo.ReadIndex); + else + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV-1, %00000000, ServiceModeInfo.ReadIndex); + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_REGISTER; end end; + // *************************************************************************** // procedure FailedToDetectCorrectAckWidth // @@ -120,43 +143,18 @@ begin if BufferPtr^.TX_Flags.TRANSMITTING_FLAG_STOP_BIT = 1 then begin - { case ServiceModeInfo.iStateMachine of + case ServiceModeInfo.iStateMachine of STATE_SERVICEMODE_POWER_ON_CYCLE : PowerOnCycle(BufferPtr); - STATE_SERVICEMODE_RESET_CYCLE : ResetCycle(BufferPtr); - STATE_SERVICEMODE_REGISTER_PRESET_CYCLE : // Address Only and Physical Register Only - begin - if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_PAGE_PRESET_COUNT then - begin - Inc(ServiceModeInfo.iInstructionCountSent); - NMRA_DCC_LoadPagePresetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) - end else - begin - ServiceModeInfo.iInstructionCountSent := 1; - NMRA_DCC_LoadPagePresetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); - ServiceModeInfo.iStateMachine := SERVICEMODE_PAGE_PRESET_RECOVER - end - end; - SERVICEMODE_PAGE_PRESET_RECOVER : // Address Only and Physical Register Only - begin - if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_PAGE_PRESET_RECOVER then - begin - Inc(ServiceModeInfo.iInstructionCountSent); - NMRA_DCC_LoadPagePresetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE) - end else - begin - end - end; - - - STATE_SERVICEMODE_RESET_CYCLE : - begin - end; + STATE_SERVICEMODE_RESET_CYCLE : ResetCycle(BufferPtr, UGG_3, STATE_SERVICEMODE_REGISTER_PRESET_CYCLE , False, Fasle); + STATE_SERVICEMODE_REGISTER_PRESET_CYCLE : PagePresetCycle(BufferPtr); // Address Only and Physical Register Only + SERVICEMODE_PAGE_PRESET_RECOVER : ResetCycle(BufferPtr, SERVICEMODE_PAGE_PRESET_RECOVER , STATE_SERVICEMODE_RESET_CYCLE , False, False); + STATE_SERVICEMODE_RESET_CYCLE : ResetCycle(BufferPtr, UGG, STATE_SERVICEMODE_RESET_CYCLE , True, True); STATE_SERVICEMODE_REGISTER : 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; + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_REGISTER_MODE_READ; NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); // Per 9.2.3 ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESULTS_READY; end else @@ -169,7 +167,7 @@ if ServiceModeInfo.iInstructionCountSent < SERVICEMODE_INSTRUCTION_COUNT then begin Inc(ServiceModeInfo.iInstructionCountSent); - // DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV, %00000100, ServiceModeInfo.ReadIndex); + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV-1, %00000000, ServiceModeInfo.ReadIndex); end else begin Inc(ServiceModeInfo.ReadIndex); // Try the next Value @@ -180,8 +178,8 @@ 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); + ServiceModeInfo.iStateMachine := STATE_SERVICEMODE_RESET_CYCLE ; + NMRA_DCC_LoadResetPacketIntoTransmitter(BufferPtr, PREAMBLE_BIT_COUNT_SERVICEMODE); end end end @@ -191,10 +189,7 @@ // 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; @@ -213,11 +208,53 @@ // *************************************************************************** procedure RegisterServiceMode_StateMachineWrite(BufferPtr: PDCCBufferInfo); begin - 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, UGG_3, STATE_SERVICEMODE_REGISTER_PRESET_CYCLE , False, Fasle); + STATE_SERVICEMODE_REGISTER_PRESET_CYCLE : PagePresetCycle(BufferPtr); // Address Only and Physical Register Only + SERVICEMODE_PAGE_PRESET_RECOVER : ResetCycle(BufferPtr, SERVICEMODE_PAGE_PRESET_RECOVER , STATE_SERVICEMODE_RESET_CYCLE , False, False); + STATE_SERVICEMODE_RESET_CYCLE : ResetCycle(BufferPtr, UGG_10, STATE_SERVICEMODE_RESET_CYCLE , True, True); + STATE_SERVICEMODE_REGISTER : + begin + if ServiceModeInfo.Flags.PROGRAMMING_ACK_DETECTED_BIT = 1 then + begin // ACK detected and we are done + ServiceModeInfo.ServiceModeResult := SERVICE_MODE_RESULT_RESPONSE_REGISTER_MODE_WRITE; + 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_INSTRUCTION_COUNT then + begin + Inc(ServiceModeInfo.iInstructionCountSent); + DirectLoadTransmitter(BufferPtr, ServiceModeInfo.CV-1, %00001000, 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_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; + end end; -end; +end; } end. \ No newline at end of file Modified: trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/ServiceModeDefines.mpas =================================================================== --- trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/ServiceModeDefines.mpas 2013-03-30 03:56:19 UTC (rev 3112) +++ trunk/prototypes/mikroPascal/Library/NMRAnetDCCSystem/ServiceModeDefines.mpas 2013-03-31 01:18:34 UTC (rev 3113) @@ -8,19 +8,16 @@ 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_RESPONSE_REGISTER_MODE = 3; // Response was achieved in Register or Paged mode - SERVICE_MODE_RESULT_RESPONSE_REGISTER_MODE_SHORT_ACK = 4; - // SERVICE_MODE_RESULT_RESPONSE_REGISTER_MODE_WRITE_ACK = 5; // Write executed and decoder responded with an ACK - // SERVICE_MODE_RESULT_RESPONSE_REGISTER_MODE_WRITE_NO_ACK = 6; // Write executed and decoder did not respond with an ACK - S... [truncated message content] |