From 2fc0732908694cff6278fbc923de4baae0b08c82 Mon Sep 17 00:00:00 2001 From: gstellenberg Date: Sun, 31 May 2009 11:25:09 -0500 Subject: [PATCH 1/4] Implemented PRSwitchGetStates to retrieve the current state of each switch --- examples/pinproctest/dmd.cpp | 3 +- examples/pinproctest/pinproctest.cpp | 4 ++ examples/pinproctest/pinproctest.h | 2 + examples/pinproctest/switches.cpp | 54 ++++++++++++++++- include/pinproc.h | 3 + src/PRDevice.cpp | 87 +++++++++++++++++++++++++--- src/PRDevice.h | 1 + src/PRHardware.h | 3 + src/pinproc.cpp | 5 ++ 9 files changed, 153 insertions(+), 9 deletions(-) diff --git a/examples/pinproctest/dmd.cpp b/examples/pinproctest/dmd.cpp index 568ba9d..536685a 100644 --- a/examples/pinproctest/dmd.cpp +++ b/examples/pinproctest/dmd.cpp @@ -99,4 +99,5 @@ void UpdateDots( unsigned char * dots, unsigned int dotOffset ) else byte_shifter = byte_shifter >> 1; } } -} \ No newline at end of file +} + diff --git a/examples/pinproctest/pinproctest.cpp b/examples/pinproctest/pinproctest.cpp index 257b2e7..87bcba6 100644 --- a/examples/pinproctest/pinproctest.cpp +++ b/examples/pinproctest/pinproctest.cpp @@ -84,6 +84,9 @@ void RunLoop(PRHandle proc) unsigned char dots[4*((128*32)/8)]; unsigned int dotOffset = 0; + // Retrieve and store initial switch states. + LoadSwitchStates(proc); + while (runLoopRun) { PRDriverWatchdogTickle(proc); @@ -107,6 +110,7 @@ void RunLoop(PRHandle proc) struct timeval tv; gettimeofday(&tv, NULL); printf("%d.%03d switch % 3d: %s\n", tv.tv_sec-startTime, tv.tv_usec/1000, event->value, stateText); + UpdateSwitchState( event ); } PRFlushWriteData(proc); usleep(10*1000); // Sleep for 10ms so we aren't pegging the CPU. diff --git a/examples/pinproctest/pinproctest.h b/examples/pinproctest/pinproctest.h index c4e339e..4916fc6 100644 --- a/examples/pinproctest/pinproctest.h +++ b/examples/pinproctest/pinproctest.h @@ -54,6 +54,8 @@ void ConfigureDrivers(PRHandle proc, PRMachineType machineType, YAML::Node& yaml void ConfigureSwitches(PRHandle proc, YAML::Node& yamlDoc); void ConfigureSwitchRules(PRHandle proc, YAML::Node& yamlDoc); +void UpdateSwitchState (PREvent * event); +void LoadSwitchStates (PRHandle proc); void ConfigureDMD(PRHandle proc); void UpdateDots(unsigned char * dots, unsigned int dotOffset); diff --git a/examples/pinproctest/switches.cpp b/examples/pinproctest/switches.cpp index 8ab1d52..8f966fd 100644 --- a/examples/pinproctest/switches.cpp +++ b/examples/pinproctest/switches.cpp @@ -24,6 +24,12 @@ */ #include "pinproctest.h" +typedef struct SwitchStatus { + PREventType state; + uint32_t lastEventTime; +} SwitchStatus; + +static SwitchStatus switches[kPRSwitchPhysicalLast + 1]; void ConfigureSwitches(PRHandle proc, YAML::Node& yamlDoc) { @@ -36,6 +42,13 @@ void ConfigureSwitches(PRHandle proc, YAML::Node& yamlDoc) switchConfig.pulsesPerBurst = 6; switchConfig.pulseHalfPeriodTime = 13; // milliseconds PRSwitchUpdateConfig(proc, &switchConfig); + + // Go through the switches array and reset the current status of each switch + for (int i = 0; i <= kPRSwitchPhysicalLast; i++) + { + switches[i].state = kPREventTypeInvalid; + switches[i].lastEventTime = 0; + } } void ConfigureWPCFlipperSwitchRule (PRHandle proc, int swNum, int mainCoilNum, int holdCoilNum, int pulseTime) @@ -106,4 +119,43 @@ void ConfigureSwitchRules(PRHandle proc, YAML::Node& yamlDoc) yamlDoc[kCoilsSection][bumperName][kNumberField] >> coilNum; ConfigureBumperRule (proc, swNum, coilNum, kBumperPulseTime); } -} \ No newline at end of file +} + +void UpdateSwitchState( PREvent * event ) +{ + switches[event->value].state = event->type; + switches[event->value].lastEventTime = event->time; +} + +void LoadSwitchStates( PRHandle proc ) +{ + int i; + PREventType procSwitchStates[kPRSwitchPhysicalLast + 1]; + + // Get all of the switch states from the P-ROC. + if (PRSwitchGetStates( proc, procSwitchStates, kPRSwitchPhysicalLast + 1 ) == kPRFailure) + { + fprintf(stderr, "Error: Unable to retrieve switch states\n"); + } + else + { + // Copy the returning states into the local switches array. + for (i = 0; i <= kPRSwitchPhysicalLast; i++) + { + switches[i].state = procSwitchStates[i]; + } + + fprintf(stderr, "\nCurrent Switch States: 0 : "); + for (i = 0; i < kPRSwitchPhysicalLast + 1; i++) + { + fprintf(stderr, "%d ", switches[i].state); + if ((i + 1) % 32 == 0) + { + printf("\n"); + if (i != kPRSwitchPhysicalLast) + fprintf(stderr, "Current Switch States: %d : ", i); + } + } + fprintf(stderr, "\n"); + } +} diff --git a/include/pinproc.h b/include/pinproc.h index 8f8c3e0..d586e1b 100644 --- a/include/pinproc.h +++ b/include/pinproc.h @@ -334,6 +334,9 @@ PR_EXPORT PRResult PRSwitchUpdateConfig(PRHandle handle, PRSwitchConfig *switchC */ PR_EXPORT PRResult PRSwitchUpdateRule(PRHandle handle, uint8_t switchNum, PREventType eventType, PRSwitchRule *rule, PRDriverState *linkedDrivers, int numDrivers); +/** Returns a list of PREventTypes describing the states of the requested number of switches */ +PR_EXPORT PRResult PRSwitchGetStates(PRHandle handle, PREventType * switchStates, uint16_t numSwitches); + /** @} */ // End of Switches & Events // DMD diff --git a/src/PRDevice.cpp b/src/PRDevice.cpp index cf13cc2..dfc8eff 100644 --- a/src/PRDevice.cpp +++ b/src/PRDevice.cpp @@ -82,7 +82,8 @@ PRResult PRDevice::Reset(uint32_t resetFlags) group->polarity = defaultPolarity; } - freeSwitchRuleIndexes.empty(); + // Make sure the free list is empty. + while (!freeSwitchRuleIndexes.empty()) freeSwitchRuleIndexes.pop(); for (i = 0; i < kPRSwitchRulesCount; i++) { @@ -112,8 +113,9 @@ PRResult PRDevice::Reset(uint32_t resetFlags) } } - unrequestedDataQueue.empty(); - requestedDataQueue.empty(); + // Make sure the data queues are empty. + while (!unrequestedDataQueue.empty()) unrequestedDataQueue.pop(); + while (!requestedDataQueue.empty()) requestedDataQueue.pop(); num_collected_bytes = 0; numPreparedWriteWords = 0; @@ -346,6 +348,74 @@ PRResult PRDevice::SwitchUpdateRule(uint8_t switchNum, PREventType eventType, PR return res; } +PRResult PRDevice::SwitchGetStates( PREventType * switchStates, uint16_t numSwitches ) +{ + uint32_t rc; + uint32_t stateWord, debounceWord; + uint8_t i, j; + PREventType eventType; + + // Request one state word and one debounce word at a time. Could make more efficient + // use of the USB bus by requesting a burst of state words and then a burst of debounce + // words, but doing one word at a time makes it easier to process each switch when the + // data returns. Also, this function shouldn't be called during timing sensitive + // situations; so the inefficiencies are acceptable. + for (i = 0; i < numSwitches / 32; i++) + { + rc = RequestData(P_ROC_BUS_SWITCH_CTRL_SELECT, + P_ROC_SWITCH_CTRL_STATE_BASE_ADDR + i, 1); + rc = RequestData(P_ROC_BUS_SWITCH_CTRL_SELECT, + P_ROC_SWITCH_CTRL_DEBOUNCE_BASE_ADDR + i, 1); + } + + // Expect 4 words for each 32 switches. The state and debounce words, + // and the address words for both. + uint16_t numWords = 4 * (numSwitches / 32); + + i = 0; // Reset i so it can be used to prevent an infinite loop below + + // Wait for data to return. Give it 10 loops before giving up. + while (requestedDataQueue.size() < numWords && i++ < 10) + { + sleep (.01); // 10 milliseconds should be plenty of time. + SortReturningData(); + } + + // Make sure all of the requested words are available before processing them. + // Too many words is just as bad as not enough words. + // If too many come back, can they be trusted? + if (requestedDataQueue.size() == numWords) + { + // Process the returning words. + for (i = 0; i < numSwitches / 32; i++) + { + requestedDataQueue.pop(); // Ignore address word. TODO: Verify this address word. + stateWord = requestedDataQueue.front(); // This is the switch state word. + requestedDataQueue.pop(); + requestedDataQueue.pop(); // Ignore address word. TODO: Verify this address word. + debounceWord = requestedDataQueue.front(); // This is the debounce word. + requestedDataQueue.pop(); + + // Loop through each bit of the words, combining them into an eventType + for (j = 0; j < 32; j++) + { + // Only process the number of switches requested via numSwitches + if ((i * 32) + j < numSwitches) + { + if (stateWord >> j & 1) + if (debounceWord >> j & 1) eventType = kPREventTypeSwitchOpenDebounced; + else eventType = kPREventTypeSwitchOpenNondebounced; + else if (debounceWord >> j & 1) eventType = kPREventTypeSwitchClosedDebounced; + else eventType = kPREventTypeSwitchClosedNondebounced; + switchStates[(i * 32) + j] = eventType; + } + } + } + return kPRSuccess; + } + else return kPRFailure; +} + int32_t PRDevice::DMDUpdateConfig(PRDMDConfig *dmdConfig) { uint32_t rc; @@ -645,14 +715,17 @@ PRResult PRDevice::SortReturningData() switch ( (rd_buffer[0] & P_ROC_COMMAND_MASK) >> P_ROC_COMMAND_SHIFT) { - // Must be a bug in the P-ROC. Unrequested packets are returning looking - // like requested packets. Commenting out requested packets for now. case P_ROC_REQUESTED_DATA: { - int bytesRead = ReadData(rd_buffer, + // Push the address word so it can be used to identify the subsequent data. + requestedDataQueue.push(rd_buffer[0]); + int wordsRead = ReadData(rd_buffer, (rd_buffer[0] & P_ROC_HEADER_LENGTH_MASK) >> P_ROC_HEADER_LENGTH_SHIFT); - for (int i = 0; i < bytesRead; i++) + for (int i = 0; i < wordsRead; i++) + { + DEBUG(PRLog(kPRLogVerbose, "Pushing onto unreq Q 0x%x\n", rd_buffer[i])); requestedDataQueue.push(rd_buffer[i]); + } break; } case P_ROC_UNREQUESTED_DATA: { diff --git a/src/PRDevice.h b/src/PRDevice.h index d6cfb0a..034dc8b 100644 --- a/src/PRDevice.h +++ b/src/PRDevice.h @@ -63,6 +63,7 @@ public: PRResult SwitchUpdateConfig(PRSwitchConfig *switchConfig); PRResult SwitchUpdateRule(uint8_t switchNum, PREventType eventType, PRSwitchRule *rule, PRDriverState *linkedDrivers, int numDrivers); + PRResult SwitchGetStates(PREventType * switchStates, uint16_t numSwitches); PRResult DriverWatchdogTickle(); diff --git a/src/PRHardware.h b/src/PRHardware.h index 2072eb3..bbcee7d 100644 --- a/src/PRHardware.h +++ b/src/PRHardware.h @@ -73,6 +73,9 @@ const uint32_t P_ROC_MANAGER_WATCHDOG_EXPIRED_SHIFT = 30; const uint32_t P_ROC_MANAGER_WATCHDOG_ENABLE_SHIFT = 14; const uint32_t P_ROC_MANAGER_WATCHDOG_RESET_TIME_SHIFT = 0; +const uint32_t P_ROC_SWITCH_CTRL_STATE_BASE_ADDR = 4; +const uint32_t P_ROC_SWITCH_CTRL_DEBOUNCE_BASE_ADDR = 11; + const uint32_t P_ROC_EVENT_SWITCH_NUM_MASK = 0xFF; const uint32_t P_ROC_EVENT_SWITCH_STATE_MASK = 0x100; const uint32_t P_ROC_EVENT_SWITCH_STATE_SHIFT = 8; diff --git a/src/pinproc.cpp b/src/pinproc.cpp index 9c2e39d..cb05d4f 100644 --- a/src/pinproc.cpp +++ b/src/pinproc.cpp @@ -212,6 +212,11 @@ PR_EXPORT PRResult PRSwitchUpdateRule(PRHandle handle, uint8_t switchNum, PREven return handleAsDevice->SwitchUpdateRule(switchNum, eventType, rule, linkedDrivers, numDrivers); } +PR_EXPORT PRResult PRSwitchGetStates(PRHandle handle, PREventType * switchStates, uint16_t numSwitches) +{ + return handleAsDevice->SwitchGetStates(switchStates, numSwitches); +} + PR_EXPORT int32_t PRDMDUpdateConfig(PRHandle handle, PRDMDConfig *dmdConfig) { return handleAsDevice->DMDUpdateConfig(dmdConfig); From 63053bd097645b4837a29f03f6a194b50585a14f Mon Sep 17 00:00:00 2001 From: gstellenberg Date: Sun, 31 May 2009 11:46:40 -0500 Subject: [PATCH 2/4] Updated current switch states display --- examples/pinproctest/switches.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/pinproctest/switches.cpp b/examples/pinproctest/switches.cpp index 8f966fd..9fb7c5e 100644 --- a/examples/pinproctest/switches.cpp +++ b/examples/pinproctest/switches.cpp @@ -145,7 +145,8 @@ void LoadSwitchStates( PRHandle proc ) switches[i].state = procSwitchStates[i]; } - fprintf(stderr, "\nCurrent Switch States: 0 : "); + int zero = 0; + fprintf(stderr, "\nCurrent Switch States: %3d : ", zero); for (i = 0; i < kPRSwitchPhysicalLast + 1; i++) { fprintf(stderr, "%d ", switches[i].state); @@ -153,7 +154,7 @@ void LoadSwitchStates( PRHandle proc ) { printf("\n"); if (i != kPRSwitchPhysicalLast) - fprintf(stderr, "Current Switch States: %d : ", i); + fprintf(stderr, "Current Switch States: %3d : ", i+1); } } fprintf(stderr, "\n"); From c91d32dc3f9bd9252ef9c7114851ddd3d34388b3 Mon Sep 17 00:00:00 2001 From: Adam Preble Date: Sun, 31 May 2009 17:23:09 -0400 Subject: [PATCH 3/4] Added PRDecode(), updated TZ.yaml to reflect it. --- examples/pinproctest/TZ.yaml | 26 ++++++++++++------ examples/pinproctest/pinproctest.cpp | 2 +- examples/pinproctest/switches.cpp | 13 +++++---- include/pinproc.h | 7 +++++ src/pinproc.cpp | 41 ++++++++++++++++++++++++++++ 5 files changed, 74 insertions(+), 15 deletions(-) diff --git a/examples/pinproctest/TZ.yaml b/examples/pinproctest/TZ.yaml index 455ea82..196c9e1 100644 --- a/examples/pinproctest/TZ.yaml +++ b/examples/pinproctest/TZ.yaml @@ -11,17 +11,17 @@ PRBumpers: - slingR PRSwitches: flipperLwR: - number: 1 + number: SF2 flipperLwL: - number: 3 + number: SF4 flipperUpR: - number: 5 + number: SF6 flipperUpL: - number: 7 + number: SF8 slingL: - number: 96 + number: S34 slingR: - number: 97 + number: S35 PRCoils: flipperLwRMain: number: 32 @@ -40,9 +40,17 @@ PRCoils: flipperUpLHold: number: 39 slingL: - number: 54 + number: C11 slingR: - number: 55 + number: C10 + slotKickout: + number: C01 + rocketKickout: + number: C02 + outhole: + number: C08 + ballRelease: + number: C09 PRLamps: doorTheCamera: - number: 80 \ No newline at end of file + number: L11 \ No newline at end of file diff --git a/examples/pinproctest/pinproctest.cpp b/examples/pinproctest/pinproctest.cpp index 55721a5..3d4d826 100644 --- a/examples/pinproctest/pinproctest.cpp +++ b/examples/pinproctest/pinproctest.cpp @@ -28,6 +28,7 @@ */ #include "pinproctest.h" +PRMachineType machineType = kPRMachineInvalid; /** Demonstration of the custom logging callback. */ void TestLogger(PRLogLevel level, const char *text) @@ -147,7 +148,6 @@ int main(int argc, const char **argv) return 1; } - PRMachineType machineType = kPRMachineInvalid; std::string machineTypeString; yamlDoc["PRGame"]["machineType"] >> machineTypeString; if (machineTypeString == "wpc") diff --git a/examples/pinproctest/switches.cpp b/examples/pinproctest/switches.cpp index 9fb7c5e..03feefb 100644 --- a/examples/pinproctest/switches.cpp +++ b/examples/pinproctest/switches.cpp @@ -24,6 +24,8 @@ */ #include "pinproctest.h" +extern PRMachineType machineType; + typedef struct SwitchStatus { PREventType state; uint32_t lastEventTime; @@ -96,15 +98,16 @@ void ConfigureBumperRule (PRHandle proc, int swNum, int coilNum, int pulseTime) void ConfigureSwitchRules(PRHandle proc, YAML::Node& yamlDoc) { // WPC Flippers + std::string numStr; const YAML::Node& flippers = yamlDoc[kFlippersSection]; for (YAML::Iterator flippersIt = flippers.begin(); flippersIt != flippers.end(); ++flippersIt) { int swNum, coilMain, coilHold; std::string flipperName; *flippersIt >> flipperName; - yamlDoc[kSwitchesSection][flipperName][kNumberField] >> swNum; - yamlDoc[kCoilsSection][flipperName + "Main"][kNumberField] >> coilMain; - yamlDoc[kCoilsSection][flipperName + "Hold"][kNumberField] >> coilHold; + yamlDoc[kSwitchesSection][flipperName][kNumberField] >> numStr; swNum = PRDecode(machineType, numStr.c_str()); + yamlDoc[kCoilsSection][flipperName + "Main"][kNumberField] >> numStr; coilMain = PRDecode(machineType, numStr.c_str()); + yamlDoc[kCoilsSection][flipperName + "Hold"][kNumberField] >> numStr; coilHold = PRDecode(machineType, numStr.c_str()); ConfigureWPCFlipperSwitchRule (proc, swNum, coilMain, coilHold, kFlipperPulseTime); } @@ -115,8 +118,8 @@ void ConfigureSwitchRules(PRHandle proc, YAML::Node& yamlDoc) // WPC Slingshots std::string bumperName; *bumpersIt >> bumperName; - yamlDoc[kSwitchesSection][bumperName][kNumberField] >> swNum; - yamlDoc[kCoilsSection][bumperName][kNumberField] >> coilNum; + yamlDoc[kSwitchesSection][bumperName][kNumberField] >> numStr; swNum = PRDecode(machineType, numStr.c_str()); + yamlDoc[kCoilsSection][bumperName][kNumberField] >> numStr; coilNum = PRDecode(machineType, numStr.c_str()); ConfigureBumperRule (proc, swNum, coilNum, kBumperPulseTime); } } diff --git a/include/pinproc.h b/include/pinproc.h index 9fc5076..f2ddabe 100644 --- a/include/pinproc.h +++ b/include/pinproc.h @@ -237,6 +237,13 @@ PR_EXPORT void PRDriverStateSchedule(PRDriverState *driverState, uint32_t schedu */ PR_EXPORT void PRDriverStatePatter(PRDriverState *driverState, uint16_t millisecondsOn, uint16_t millisecondsOff, uint16_t originalOnTime); +/** + * @brief Converts a coil, lamp, switch, or GI string into a P-ROC driver number. + * The following formats are accepted: Cxx (coil), Lxx (lamp), Sxx (matrix switch), SFx (flipper grounded switch), or SDx (dedicated grounded switch). + * If the string does not match this format it will be converted into an integer using atoi(). + */ +PR_EXPORT uint16_t PRDecode(PRMachineType machineType, const char *str); + /** @} */ // End of Drivers // Switches diff --git a/src/pinproc.cpp b/src/pinproc.cpp index 671eea0..59c2fd1 100644 --- a/src/pinproc.cpp +++ b/src/pinproc.cpp @@ -219,6 +219,47 @@ PR_EXPORT void PRDriverStatePatter(PRDriverState *driver, uint16_t millisecondsO driver->patterEnable = true; } +PR_EXPORT uint16_t PRDecode(PRMachineType machineType, const char *str) +{ + if (str == NULL) + return 0; + if (strlen(str) != 3) + return atoi(str); + uint16_t x = (str[1]-'0') * 10 + (str[2]-'0'); + + if (machineType == kPRMachineWPC) + { + switch (str[0]) + { + case 'L': + case 'l': + return 80 + 8 * ((x / 10) - 1) + ((x % 10) -1); + case 'C': + case 'c': + if (x <= 28) + return x + 39; + else + return x + 7; + case 'G': + case 'g': + return x + 71; + case 'S': + case 's': + { + switch (str[1]) + { + case 'D': + case 'd': + return 8 + ((str[2]-'0') - 1); + case 'F': + case 'f': + return (str[2]-'0') - 1; + } + } + } + } + return atoi(str); +} // Switches From cd1d74db81235f854a4c1945d25520eaeb07283f Mon Sep 17 00:00:00 2001 From: Adam Preble Date: Sun, 31 May 2009 17:29:03 -0400 Subject: [PATCH 4/4] Added missing switch matrix formula for PRDecode(). --- src/pinproc.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pinproc.cpp b/src/pinproc.cpp index 59c2fd1..3fe7359 100644 --- a/src/pinproc.cpp +++ b/src/pinproc.cpp @@ -254,6 +254,8 @@ PR_EXPORT uint16_t PRDecode(PRMachineType machineType, const char *str) case 'F': case 'f': return (str[2]-'0') - 1; + default: + return 32 + 16 * ((x / 10) - 1) + ((x % 10) - 1); } } }