diff --git a/examples/pinproctest/drivers.cpp b/examples/pinproctest/drivers.cpp index dff8e8e..ed6a4b2 100644 --- a/examples/pinproctest/drivers.cpp +++ b/examples/pinproctest/drivers.cpp @@ -24,136 +24,3 @@ */ #include "pinproctest.h" - - -void ConfigureDrivers(PRHandle proc, PRMachineType machineType, YAML::Node& yamlDoc) -{ - int i; - - const int WPCDriverLoopTime = 4; // milliseconds - const int SternDriverLoopTime = 2; // milliseconds - - const int mappedWPCDriverGroupEnableIndex[] = {0, 0, 0, 0, 0, 2, 4, 3, 1, 5, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0}; - const int mappedSternDriverGroupEnableIndex[] = {0, 0, 0, 0, 1, 0, 2, 3, 0, 0, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9}; - const int mappedWPCDriverGroupSlowTime[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 400, 400, 400, 400, 400, 400, 400, 400, 0, 0, 0, 0, 0, 0, 0, 0}; - const int mappedSternDriverGroupSlowTime[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200}; - const int mappedWPCDriverGroupActivateIndex[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}; - const int mappedSternDriverGroupActivateIndex[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; - - const int watchdogResetTime = 1000; // milliseconds - - int mappedDriverGroupEnableIndex[kPRDriverGroupsMax]; - int mappedDriverGroupSlowTime[kPRDriverGroupsMax]; - int mappedDriverGroupActivateIndex[kPRDriverGroupsMax]; - int rowEnableIndex1; - int rowEnableIndex0; - bool tickleSternWatchdog; - bool globalPolarity; - bool activeLowMatrixRows; - int driverLoopTime; - int slowGroupTime; - int numMatrixGroups; - bool encodeEnables; - int rowEnableSelect; - - switch (machineType) - { - case kPRMachineWPC: - { - memcpy(mappedDriverGroupEnableIndex,mappedWPCDriverGroupEnableIndex, - sizeof(mappedDriverGroupEnableIndex)); - rowEnableIndex1 = 6; // Unused in WPC - rowEnableIndex0 = 6; - tickleSternWatchdog = false; - globalPolarity = false; - activeLowMatrixRows = true; - driverLoopTime = 4; // milliseconds - memcpy(mappedDriverGroupSlowTime,mappedWPCDriverGroupSlowTime, - sizeof(mappedDriverGroupSlowTime)); - memcpy(mappedDriverGroupActivateIndex,mappedWPCDriverGroupActivateIndex, - sizeof(mappedDriverGroupActivateIndex)); - numMatrixGroups = 8; - encodeEnables = false; - rowEnableSelect = 0; - break; - } - - case kPRMachineStern: - { - memcpy(mappedDriverGroupEnableIndex,mappedSternDriverGroupEnableIndex, - sizeof(mappedDriverGroupEnableIndex)); - rowEnableIndex1 = 6; // Unused in Stern - rowEnableIndex0 = 10; - tickleSternWatchdog = true; - globalPolarity = true; - activeLowMatrixRows = false; - driverLoopTime = 2; // milliseconds - memcpy(mappedDriverGroupSlowTime,mappedSternDriverGroupSlowTime, - sizeof(mappedDriverGroupSlowTime)); - memcpy(mappedDriverGroupActivateIndex,mappedSternDriverGroupActivateIndex, - sizeof(mappedDriverGroupActivateIndex)); - numMatrixGroups = 16; - encodeEnables = true; - rowEnableSelect = 0; - break; - } - } - - PRDriverGlobalConfig globals; - globals.enableOutputs = false; - globals.globalPolarity = globalPolarity; - globals.useClear = false; - globals.strobeStartSelect = false; - globals.startStrobeTime = driverLoopTime; // milliseconds per output loop - globals.matrixRowEnableIndex1 = rowEnableIndex1; - globals.matrixRowEnableIndex0 = rowEnableIndex0; - globals.activeLowMatrixRows = activeLowMatrixRows; - globals.tickleSternWatchdog = tickleSternWatchdog; - globals.encodeEnables = encodeEnables; - globals.watchdogExpired = false; - globals.watchdogEnable = true; - globals.watchdogResetTime = watchdogResetTime; - - // We want to start up safely, so we'll update the global driver config twice. - // When we toggle enableOutputs like this P-ROC will reset the polarity: - - // Enable now without the outputs enabled: - PRDriverUpdateGlobalConfig(proc, &globals); - - // Now enable the outputs: (TODO: Why?) - globals.enableOutputs = true; - PRDriverUpdateGlobalConfig(proc, &globals); - - // Configure the groups. Each group corresponds to 8 consecutive drivers, starting - // with driver #32. The following 6 groups are configured for coils/flashlamps. - - PRDriverGroupConfig group; - for (i = 4; i < 10; i++) - { - PRDriverGetGroupConfig(proc, i, &group); - group.slowTime = 0; - group.enableIndex = mappedDriverGroupEnableIndex[i]; - group.rowActivateIndex = 0; - group.rowEnableSelect = 0; - group.matrixed = false; - group.polarity = globalPolarity; - group.active = 1; - group.disableStrobeAfter = false; - - PRDriverUpdateGroupConfig(proc, &group); - } - - // The following 8 groups are configured for the feature lamp matrix. - for (i = 10; i < 10 + numMatrixGroups; i++) { - PRDriverGetGroupConfig(proc, i, &group); - group.slowTime = mappedDriverGroupSlowTime[i]; - group.enableIndex = mappedDriverGroupEnableIndex[i]; - group.rowActivateIndex = mappedDriverGroupActivateIndex[i]; - group.rowEnableSelect = rowEnableSelect; - group.matrixed = 1; - group.polarity = globalPolarity; - group.active = 1; - group.disableStrobeAfter = mappedDriverGroupSlowTime[i] != 0; - PRDriverUpdateGroupConfig(proc, &group); - } -} diff --git a/examples/pinproctest/pinproctest.cpp b/examples/pinproctest/pinproctest.cpp index c1957a5..55721a5 100644 --- a/examples/pinproctest/pinproctest.cpp +++ b/examples/pinproctest/pinproctest.cpp @@ -174,24 +174,22 @@ int main(int argc, const char **argv) ConfigureSwitches(proc, yamlDoc); // Notify host for all debounced switch events. ConfigureSwitchRules(proc, yamlDoc); // Flippers, slingshots - // Make Drivers the last thing to configure so watchdog doesn't expire - // before the RunLoop begins. - ConfigureDrivers(proc, machineType, yamlDoc); - - printf("Running. Hit Ctrl-C to exit.\n"); - // Pulse a coil for testing purposes. //PRDriverPulse(proc, 53, 100); // Schedule a feature lamp for testing purposes. PRDriverSchedule(proc, 80, 0xFF00FF00, 0, 0); // Pitter-patter a feature lamp for testing purposes. //PRDriverPatter(proc, 84, 127, 127, 0); + PRFlushWriteData(proc); + printf("Running. Hit Ctrl-C to exit.\n"); + RunLoop(proc); // Clean up P-ROC. printf("Disabling P-ROC drivers and switch rules...\n"); PRReset(proc, kPRResetFlagUpdateDevice); // Reset the device structs and write them into the device. + PRFlushWriteData(proc); // Destroy the P-ROC device handle: PRDelete(proc); diff --git a/include/pinproc.h b/include/pinproc.h index b8cfa02..9fc5076 100644 --- a/include/pinproc.h +++ b/include/pinproc.h @@ -178,6 +178,13 @@ PR_EXPORT PRResult PRDriverGetState(PRHandle handle, uint8_t driverNum, PRDriver * @brief Sets the state of the given driver (lamp or coil). */ PR_EXPORT PRResult PRDriverUpdateState(PRHandle handle, PRDriverState *driverState); +/** + * @brief Loads the driver defaults for the given machine type. + * + * PRReset() calls this function internally; this function is useful for basing custom driver settings off of the defaults for a particular machine. + * @note This function does not update the P-ROC hardware, only the internal data structures. Use PRDriverGetGlobalConfig() and PRDriverGetGroupConfig() to retrieve the settings. + */ +PR_EXPORT PRResult PRDriverLoadMachineTypeDefaults(PRHandle handle, PRMachineType machineType); // Driver Helper functions: diff --git a/libpinproc.xcodeproj/project.pbxproj b/libpinproc.xcodeproj/project.pbxproj index 55dbc47..bd5ec84 100644 --- a/libpinproc.xcodeproj/project.pbxproj +++ b/libpinproc.xcodeproj/project.pbxproj @@ -234,6 +234,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_ENABLE_FIX_AND_CONTINUE = YES; @@ -241,7 +242,10 @@ GCC_OPTIMIZATION_LEVEL = 0; HEADER_SEARCH_PATHS = /usr/local/include; INSTALL_PATH = /usr/local/lib; + OBJROOT = build; + ONLY_ACTIVE_ARCH = NO; PRODUCT_NAME = pinproc; + SYMROOT = bin; }; name = Debug; }; @@ -249,11 +253,14 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; GCC_MODEL_TUNING = G5; HEADER_SEARCH_PATHS = /usr/local/include; INSTALL_PATH = /usr/local/lib; + OBJROOT = build; PRODUCT_NAME = pinproc; + SYMROOT = bin; }; name = Release; }; @@ -295,6 +302,7 @@ HEADER_SEARCH_PATHS = /usr/local/include; INSTALL_PATH = /usr/local/bin; OTHER_LDFLAGS = ( + "-Lbin", "-lyaml-cpp", "-lftdi", ); diff --git a/src/PRDevice.cpp b/src/PRDevice.cpp index 95d3efe..b67c4e2 100644 --- a/src/PRDevice.cpp +++ b/src/PRDevice.cpp @@ -63,24 +63,15 @@ PRDevice* PRDevice::Create(PRMachineType machineType) PRResult PRDevice::Reset(uint32_t resetFlags) { - bool defaultPolarity = machineType != kPRMachineWPC; int i; - memset(&driverGlobalConfig, 0x00, sizeof(PRDriverGlobalConfig)); - for (i = 0; i < kPRDriverCount; i++) - { - PRDriverState *driver = &drivers[i]; - memset(driver, 0x00, sizeof(PRDriverState)); - driver->driverNum = i; - driver->polarity = defaultPolarity; - if (resetFlags & kPRResetFlagUpdateDevice) DriverUpdateState(driver); - } - for (i = 0; i < kPRDriverGroupsMax; i++) - { - PRDriverGroupConfig *group = &driverGroups[i]; - memset(group, 0x00, sizeof(PRDriverGroupConfig)); - group->groupNum = i; - group->polarity = defaultPolarity; - } + + // Make sure the data queues are empty. + while (!unrequestedDataQueue.empty()) unrequestedDataQueue.pop(); + while (!requestedDataQueue.empty()) requestedDataQueue.pop(); + num_collected_bytes = 0; + numPreparedWriteWords = 0; + + DriverLoadMachineTypeDefaults(machineType, resetFlags); // Make sure the free list is empty. while (!freeSwitchRuleIndexes.empty()) freeSwitchRuleIndexes.pop(); @@ -92,7 +83,7 @@ PRResult PRDevice::Reset(uint32_t resetFlags) uint16_t ruleIndex = i; ParseSwitchRuleIndex(ruleIndex, &switchRule->switchNum, &switchRule->eventType); - switchRule->driver.polarity = defaultPolarity; + switchRule->driver.polarity = driverGlobalConfig.globalPolarity; if (switchRule->switchNum >= kPRSwitchVirtualFirst) // Disabled for compiler warning (always true due to data type): && switchRule->switchNum <= kPRSwitchVirtualLast) freeSwitchRuleIndexes.push(ruleIndex); } @@ -113,13 +104,6 @@ PRResult PRDevice::Reset(uint32_t resetFlags) } } - // Make sure the data queues are empty. - while (!unrequestedDataQueue.empty()) unrequestedDataQueue.pop(); - while (!requestedDataQueue.empty()) requestedDataQueue.pop(); - num_collected_bytes = 0; - numPreparedWriteWords = 0; - - // TODO: Assign defaults based on machineType. Some may have already been done above. return kPRSuccess; } @@ -213,6 +197,170 @@ PRResult PRDevice::DriverUpdateState(PRDriverState *driverState) return PrepareWriteData(burst, burstWords); } +PRResult PRDevice::DriverLoadMachineTypeDefaults(PRMachineType machineType, uint32_t resetFlags) +{ + int i; + PRResult res = kPRSuccess; + + //const int WPCDriverLoopTime = 4; // milliseconds + //const int SternDriverLoopTime = 2; // milliseconds + + const int mappedWPCDriverGroupEnableIndex[] = {0, 0, 0, 0, 0, 2, 4, 3, 1, 5, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 0, 0, 0, 0, 0, 0}; + const int mappedSternDriverGroupEnableIndex[] = {0, 0, 0, 0, 1, 0, 2, 3, 0, 0, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9, 8, 9}; + const int mappedWPCDriverGroupSlowTime[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 400, 400, 400, 400, 400, 400, 400, 400, 0, 0, 0, 0, 0, 0, 0, 0}; + const int mappedSternDriverGroupSlowTime[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200, 0, 200}; + const int mappedWPCDriverGroupActivateIndex[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0}; + const int mappedSternDriverGroupActivateIndex[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; + + const int watchdogResetTime = 1000; // milliseconds + + int mappedDriverGroupEnableIndex[kPRDriverGroupsMax]; + int mappedDriverGroupSlowTime[kPRDriverGroupsMax]; + int mappedDriverGroupActivateIndex[kPRDriverGroupsMax]; + int rowEnableIndex1; + int rowEnableIndex0; + bool tickleSternWatchdog; + bool globalPolarity; + bool activeLowMatrixRows; + int driverLoopTime; + //int slowGroupTime; + int numMatrixGroups; + bool encodeEnables; + int rowEnableSelect; + + switch (machineType) + { + case kPRMachineWPC: + { + memcpy(mappedDriverGroupEnableIndex,mappedWPCDriverGroupEnableIndex, + sizeof(mappedDriverGroupEnableIndex)); + rowEnableIndex1 = 6; // Unused in WPC + rowEnableIndex0 = 6; + tickleSternWatchdog = false; + globalPolarity = false; + activeLowMatrixRows = true; + driverLoopTime = 4; // milliseconds + memcpy(mappedDriverGroupSlowTime,mappedWPCDriverGroupSlowTime, + sizeof(mappedDriverGroupSlowTime)); + memcpy(mappedDriverGroupActivateIndex,mappedWPCDriverGroupActivateIndex, + sizeof(mappedDriverGroupActivateIndex)); + numMatrixGroups = 8; + encodeEnables = false; + rowEnableSelect = 0; + break; + } + + case kPRMachineStern: + { + memcpy(mappedDriverGroupEnableIndex,mappedSternDriverGroupEnableIndex, + sizeof(mappedDriverGroupEnableIndex)); + rowEnableIndex1 = 6; // Unused in Stern + rowEnableIndex0 = 10; + tickleSternWatchdog = true; + globalPolarity = true; + activeLowMatrixRows = false; + driverLoopTime = 2; // milliseconds + memcpy(mappedDriverGroupSlowTime,mappedSternDriverGroupSlowTime, + sizeof(mappedDriverGroupSlowTime)); + memcpy(mappedDriverGroupActivateIndex,mappedSternDriverGroupActivateIndex, + sizeof(mappedDriverGroupActivateIndex)); + numMatrixGroups = 16; + encodeEnables = true; + rowEnableSelect = 0; + break; + } + } + + memset(&driverGlobalConfig, 0x00, sizeof(PRDriverGlobalConfig)); + for (i = 0; i < kPRDriverCount; i++) + { + PRDriverState *driver = &drivers[i]; + memset(driver, 0x00, sizeof(PRDriverState)); + driver->driverNum = i; + driver->polarity = globalPolarity; + if (resetFlags & kPRResetFlagUpdateDevice) + res = DriverUpdateState(driver); + } + for (i = 0; i < kPRDriverGroupsMax; i++) + { + PRDriverGroupConfig *group = &driverGroups[i]; + memset(group, 0x00, sizeof(PRDriverGroupConfig)); + group->groupNum = i; + group->polarity = globalPolarity; + } + + PRDriverGlobalConfig globals; + globals.enableOutputs = false; + globals.globalPolarity = globalPolarity; + globals.useClear = false; + globals.strobeStartSelect = false; + globals.startStrobeTime = driverLoopTime; // milliseconds per output loop + globals.matrixRowEnableIndex1 = rowEnableIndex1; + globals.matrixRowEnableIndex0 = rowEnableIndex0; + globals.activeLowMatrixRows = activeLowMatrixRows; + globals.tickleSternWatchdog = tickleSternWatchdog; + globals.encodeEnables = encodeEnables; + globals.watchdogExpired = false; + globals.watchdogEnable = true; + globals.watchdogResetTime = watchdogResetTime; + + // We want to start up safely, so we'll update the global driver config twice. + // When we toggle enableOutputs like this P-ROC will reset the polarity: + + // Enable now without the outputs enabled: + if (resetFlags & kPRResetFlagUpdateDevice) + res = DriverUpdateGlobalConfig(&globals); + else + driverGlobalConfig = globals; + + // Now enable the outputs to protect against the polarity being driven incorrectly: + globals.enableOutputs = true; + if (resetFlags & kPRResetFlagUpdateDevice) + res = DriverUpdateGlobalConfig(&globals); + else + driverGlobalConfig = globals; + + // Configure the groups. Each group corresponds to 8 consecutive drivers, starting + // with driver #32. The following 6 groups are configured for coils/flashlamps. + + PRDriverGroupConfig group; + for (i = 4; i < 10; i++) + { + DriverGetGroupConfig(i, &group); + group.slowTime = 0; + group.enableIndex = mappedDriverGroupEnableIndex[i]; + group.rowActivateIndex = 0; + group.rowEnableSelect = 0; + group.matrixed = false; + group.polarity = globalPolarity; + group.active = 1; + group.disableStrobeAfter = false; + + if (resetFlags & kPRResetFlagUpdateDevice) + res = DriverUpdateGroupConfig(&group); + else + driverGroups[i] = group; + } + + // The following 8 groups are configured for the feature lamp matrix. + for (i = 10; i < 10 + numMatrixGroups; i++) { + DriverGetGroupConfig(i, &group); + group.slowTime = mappedDriverGroupSlowTime[i]; + group.enableIndex = mappedDriverGroupEnableIndex[i]; + group.rowActivateIndex = mappedDriverGroupActivateIndex[i]; + group.rowEnableSelect = rowEnableSelect; + group.matrixed = 1; + group.polarity = globalPolarity; + group.active = 1; + group.disableStrobeAfter = mappedDriverGroupSlowTime[i] != 0; + + if (resetFlags & kPRResetFlagUpdateDevice) + res = DriverUpdateGroupConfig(&group); + else + driverGroups[i] = group; + } + return res; +} PRResult PRDevice::DriverWatchdogTickle() { diff --git a/src/PRDevice.h b/src/PRDevice.h index 034dc8b..3c0737a 100644 --- a/src/PRDevice.h +++ b/src/PRDevice.h @@ -60,6 +60,7 @@ public: PRResult DriverUpdateGroupConfig(PRDriverGroupConfig *driverGroupConfig); PRResult DriverGetState(uint8_t driverNum, PRDriverState *driverState); PRResult DriverUpdateState(PRDriverState *driverState); + PRResult DriverLoadMachineTypeDefaults(PRMachineType machineType, uint32_t resetFlags = kPRResetFlagDefault); PRResult SwitchUpdateConfig(PRSwitchConfig *switchConfig); PRResult SwitchUpdateRule(uint8_t switchNum, PREventType eventType, PRSwitchRule *rule, PRDriverState *linkedDrivers, int numDrivers); diff --git a/src/pinproc.cpp b/src/pinproc.cpp index b25894f..671eea0 100644 --- a/src/pinproc.cpp +++ b/src/pinproc.cpp @@ -139,6 +139,10 @@ PR_EXPORT PRResult PRDriverUpdateState(PRHandle handle, PRDriverState *driverSta { return handleAsDevice->DriverUpdateState(driverState); } +PR_EXPORT PRResult PRDriverLoadMachineTypeDefaults(PRHandle handle, PRMachineType machineType) +{ + return handleAsDevice->DriverLoadMachineTypeDefaults(machineType); +} // Driver Helper functions: PR_EXPORT PRResult PRDriverDisable(PRHandle handle, uint16_t driverNum)