diff --git a/CVReader.ino b/CVReader.ino index 194b447..5ab4a43 100644 --- a/CVReader.ino +++ b/CVReader.ino @@ -2,36 +2,29 @@ #include "DIAG.h" #include "DCCEXParser.h" -/* this code is here to test the waveforwe generator and reveal the issues involved in programming track operations. +/* this code is here to test the waveform generator and reveal the issues involved in programming track operations. It tests the Waveform genartor and demonstrates how a DCC API function can be simply written to transmit and receive DCC data on the programming track. - Once soem CVs have been listed, it then drops into JMRI input moce so you can play. - + Once started, it continues to operate as a DCC++ compaitible command parser Important... Config.h contains hardware specific confioguration settings that you will need to check. - - */ - - -const int cvnums[] = {1, 2, 3, 4, 5, 8, 17, 18, 19, 21, 22, 29}; +void myCallback(int result) { + DIAG(F("\n Reading CV 1 callback result=%d"),result); +} void setup() { Serial.begin(115200); DCC::begin(); -// DIAG(F("\n===== CVReader begin ==============================\n")); -// -// for (byte x = 0; x < sizeof(cvnums) / sizeof(cvnums[0]); x++) { -// int value = DCC::readCV(cvnums[x]); -// DIAG(F("\nCV %d = %d 0x%x %s\n"), cvnums[x], value, value, value >= 0 ? " VERIFIED OK" : "FAILED VERIFICATION"); -// } -// DIAG(F("\n===== CVReader done ==============================\n")); - DIAG(F("\nReady for JMRI commands\n")); + DIAG(F("\n===== CVReader demonstrating DCC::readCV call ==========\n")); + DCC::readCV(1,myCallback); // myCallback will be called with the result + DIAG(F("\n===== DCC::readCV has returned, but wont be executed until we are in loop() ======\n")); + DIAG(F("\nReady for JMRI commands\n")); } void loop() { diff --git a/DCC.cpp b/DCC.cpp index d0b6c58..9f7966f 100644 --- a/DCC.cpp +++ b/DCC.cpp @@ -108,14 +108,14 @@ void DCC::writeCVBitMain(int cab, int cv, byte bNum, bool bValue) { -const ackOp WRITE_BIT0_PROG[] = { +const ackOp PROGMEM WRITE_BIT0_PROG[] = { BASELINE, W0,WACK, V0, WACK, // validate bit is 0 ITC1, // if acked, callback(1) FAIL // callback (-1) }; -const ackOp WRITE_BIT1_PROG[] = { +const ackOp PROGMEM WRITE_BIT1_PROG[] = { BASELINE, W1,WACK, V1, WACK, // validate bit is 1 @@ -124,7 +124,7 @@ const ackOp WRITE_BIT1_PROG[] = { }; -const ackOp READ_BIT_PROG[] = { +const ackOp PROGMEM READ_BIT_PROG[] = { BASELINE, V1, WACK, // validate bit is 1 ITC1, // if acked, callback(1) @@ -133,7 +133,7 @@ const ackOp READ_BIT_PROG[] = { FAIL // bit not readable }; -const ackOp WRITE_BYTE_PROG[] = { +const ackOp PROGMEM WRITE_BYTE_PROG[] = { BASELINE, WB,WACK, // Write VB,WACK, // validate byte @@ -142,9 +142,9 @@ const ackOp WRITE_BYTE_PROG[] = { }; -const ackOp READ_CV_PROG[] = { +const ackOp PROGMEM READ_CV_PROG[] = { BASELINE, - ZERO, //clear bit and byte values + STARTMERGE, //clear bit and byte values ready for merge pass // each bit is validated against 1 (no need for zero validation as entire byte is validated at the end) V1, WACK, MERGE, // read and merge bit 0 V1, WACK, MERGE, // read and merge bit 1 etc @@ -277,19 +277,27 @@ void DCC::ackManagerSetup(int cv, byte byteValueOrBitnum, ackOp const program[] } -#define RESET_MIN 8 +const byte RESET_MIN=8; // tuning of reset counter before sending message + void DCC::ackManagerLoop() { while (ackManagerProg) { // breaks from this switch will step to next prog entry // returns from this switch will stay on same entry (typically WACK waiting and when all finished.) - byte opcode=*ackManagerProg; + byte opcode=pgm_read_byte_near(ackManagerProg); + // DIAG(F("apAck %d\n"),opcode); int resets=DCCWaveform::progTrack.sentResetsSincePacket; - - // DIAG(F("\nopAck %d"),opcode); + int current; + switch (opcode) { - case W0: // write bit - case W1: // write bit + case BASELINE: + if (resets 6) { - DIAG(F("\nWACK fail %d\n"), resets); + if (resets > 6) { //ACK timeout + // DIAG(F("\nWACK fail %d\n"), resets); ackReceived = false; break; // move on to next prog step } - int current=Hardware::getCurrentMilliamps(false); + current=Hardware::getCurrentMilliamps(false); - if (current > ackTriggerMilliamps) { - DIAG(F("\nWACK ok %dmA, after %d resets\n"), current,resets); + if (current > ackTriggerMilliamps) { //ACK detected + // DIAG(F("\nACK %dmA, after %d resets\n"), current,resets); ackReceived = true; DCCWaveform::progTrack.killRemainingRepeats(); break; // move on tho next step } - } - return; // maintain place for next poll cycle. + + return; // check again on next loop cycle. case ITC0: case ITC1: // If True Callback(0 or 1) (if prevous WACK got an ACK) if (ackReceived) { - ackManagerProg = NULL; + ackManagerProg = NULL; // all done now (ackManagerCallback)(opcode==ITC0?0:1); return; } break; + case ITCB: // If True callback(byte) if (ackReceived) { - ackManagerProg = NULL; + ackManagerProg = NULL; // all done now (ackManagerCallback)(ackManagerByte); return; } break; - case MERGE: // Merge previous wack response with byte value and increment bit number (use for reading CV bytes) - ackManagerByte <<= 1; - if (ackReceived) ackManagerByte |= 1; - ackManagerBitNum--; - break; + case FAIL: // callback(-1) ackManagerProg = NULL; (ackManagerCallback)(-1); return; - case ZERO: + + case STARTMERGE: ackManagerBitNum=7; ackManagerByte=0; break; - case BASELINE: - if (resets