From a488ad7ae72f306ae85299462bf8aa1a187e6061 Mon Sep 17 00:00:00 2001 From: Gerry Stellenberg Date: Sat, 11 Jun 2011 20:48:49 -0500 Subject: [PATCH] Added example code to configure custom Driver Boards if the YAML's machineType field is 'custom'. --- examples/pinproctest/drivers.cpp | 239 ++++++++++++++++++++++++++- examples/pinproctest/pinproctest.cpp | 3 + examples/pinproctest/pinproctest.h | 2 +- 3 files changed, 242 insertions(+), 2 deletions(-) diff --git a/examples/pinproctest/drivers.cpp b/examples/pinproctest/drivers.cpp index ed6a4b2..5cb09ae 100644 --- a/examples/pinproctest/drivers.cpp +++ b/examples/pinproctest/drivers.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Gerry Stellenberg, Adam Preble + * Copyright (c) 3009 Gerry Stellenberg, Adam Preble * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation @@ -24,3 +24,240 @@ */ #include "pinproctest.h" +// This is an example configuration for a custom machine showing +// the steps to configure drivers. +// Custom machine devs will almost certainly need to use different settings +// tailored to their hardware setup. + +// For this example, we're using the following driver group configuration: +// Group 0 (Drivers 0-7) : Unused +// Group 1 (Drivers 8-15) : Unused +// Group 2 (Drivers 16-23) : Unused +// Group 3 (Drivers 24-31) : Unused +// Group 4 (Drivers 32-39) : Coils 0-7 +// Group 5 (Drivers 40-47) : Coils 8-15 +// Group 6 (Drivers 48-55) : Coils 16-23 +// Group 7 (Drivers 56-63) : Coils 24-31 +// Group 8 (Drivers 64-71) : Coils 32-39 +// Group 9 (Drivers 72-79) : Coils 40-47 +// Group 10 (Drivers 80-87) : Matrix 0 0-7 +// Group 11 (Drivers 88-95) : Matrix 0 8-15 +// Group 12 (Drivers 96-103) : Matrix 0 16-23 +// Group 13 (Drivers 104-111) : Matrix 0 24-31 +// Group 14 (Drivers 112-119) : Matrix 0 32-39 +// Group 15 (Drivers 120-127) : Matrix 0 40-47 +// Group 16 (Drivers 128-135) : Matrix 0 48-55 +// Group 17 (Drivers 136-143) : Matrix 0 56-63 +// Group 18 (Drivers 144-151) : Matrix 1 0-7 +// Group 19 (Drivers 152-159) : Matrix 1 8-15 +// Group 20 (Drivers 160-167) : Matrix 1 16-23 +// Group 21 (Drivers 168-175) : Matrix 1 24-31 +// Group 22 (Drivers 176-183) : Matrix 1 32-39 +// Group 23 (Drivers 184-191) : Matrix 1 40-47 +// Group 24 (Drivers 192-199) : Matrix 1 48-55 +// Group 25 (Drivers 300-207) : Matrix 1 56-63 + +// The Driver Board setup is the following: +// Address 0 : Sink-16 +// Address 1 : Sink-16 +// Address 2 : Sink-16 +// Address 3 : Source-sink-8 +// Address 4 : Source-sink-8 + +void ConfigureDrivers(PRHandle proc) +{ + int i; + + + // First set up a bunch of constants to use later: + + // The driverPolarity determines when the drivers go high or low when + // they are supposed to be active. For the Driver Boards, this doesn't + // really matter, since they auto-detect polarity. True seems to make + // more logical sense though. + const bool driverPolarity = true; + + //const int WPCDriverLoopTime = 4; // milliseconds + //const int SternDriverLoopTime = 2; // milliseconds + + // Each entry in the mappedDriverGroupEnableIndex is the enable line that + // will be asserted when the data belonging to the group is serviced. + // The enable line maps to a Driver Board and bank. + // Bits [3:1] of the index represent the Driver + // Board address, and bit [0] represents the bank (A vs B). For example, + // Enable 0 maps to Board 0, Bank A. Enable 1 maps to Board 0, Bank B. + // Enable 2 maps to Board 1, Bank A. Etc, etc. + + // The groups being serviced correspond directly to the P-ROC's drivers. + // Group 0 is for drivers 0-7 group 1 is for drivers 15-8, and so on. + // Groups 0-3 correspond to the P-ROC's direct driver outputs. + // The remaining groups correspond to the P-ROC's multiplexed drivers, + // and are therefore the drivers used on existing P/D boards and now + // on the new Driver Boards. These start at group 4 (drivers 32-39). + // Therefore, the enable indexes given to groups 0-3 are all 0 in + // this case and don't matter. Group 4 is also 0, meaning drivers + // 32-39 map to Driver Board 0, Bank A. + + // Notice groups 10-17 all use index 7, which maps to Driver Board 3, + // Bank B. This means that drivers 80-143 all use Driver Board 3, + // Bank B. In the example setup, this is a Source-Sink-8 Board where + // Bank B is the row outputs. Similarly, groups 18-25, or drivers + // 144-207, go to index 9 or Board 4, Bank B. Board 4 is also a + // source-sink-8 board. + const int mappedDriverGroupEnableIndex[] = {0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 7, 7, 7, 7, 7, 7, 7, 7, 9, 9, 9, 9, 9, 9, 9, 9}; + + // Slow times are used to allow matrix groups to turn on the matrix lamp or led. + // They're in microseconds. Here, all matrixed groups turn on for 300us. + const int mappedDriverGroupSlowTime[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300, 300}; + + // GroupActivateIndexes indicate which column to strobe while a matrix group + // is being serviced. For instance, group 10 is 0, so data bit [0] is asserted + // for the matrix column when drivers 80-87 are driven onto the rows of the + // matrix. Next, group 11 is 1, so data bit [1] represents the active column + // when drivers 88-95 are driven onto the Rows. How these columns map to the + // Driver Boards is determined by the matrixRowEnableIndex below. + const int mappedDriverGroupActivateIndex[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 2, 3, 4, 5, 6, 7}; + + // There are 2 matrixRowEnableIndexes because the P-ROC can control 2 separate + // matrixes, and in fact this example uses 2 matrixes. This next + // variable mappedDriverGroupRowEnableSelect specifies which of the 2 indexes + // to use when the groups are serviced. Groups 10-17 use index 0, and + // groups 18-25 use index 1. The value of indexes 0 and 1 is defined below + // in the matrixRowEnableIndex variables. + const int mappedDriverGroupRowEnableSelect[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1}; + + // Set up the watchdog time for when the global settings are programmed. 1000 + // means the drivers will disable automatically if the watchdog isn't updated + // for 1 second (1000ms). This could happen if software crashes or if the USB + // cable is unplugged. + const int watchdogResetTime = 1000; // milliseconds + + // Now start actually programming thing in the P-ROC. + + // First create individual driver records for each driver, and reset them to + // zero except for the polarity, which is set according to driverPolarity from + // above. + for (i = 0; i < kPRDriverCount; i++) + { + PRDriverState driver; + memset(&driver, 0x00, sizeof(PRDriverState)); + driver.driverNum = i; + driver.polarity = driverPolarity; + PRDriverUpdateState(proc, &driver); + } + + // Now configure all of the groups. + for (i = 0; i <= kPRDriverGroupsMax; i++) + { + PRDriverGroupConfig group; + //memset(&group, 0x00, sizeof(PRDriverGroupConfig)); + + group.groupNum = i; + + group.slowTime = mappedDriverGroupSlowTime[i]; + group.enableIndex = mappedDriverGroupEnableIndex[i]; + group.rowActivateIndex = mappedDriverGroupActivateIndex[i]; + group.rowEnableSelect = mappedDriverGroupRowEnableSelect[i]; + + // All of the groups with slow times are in matrixes. + group.matrixed = mappedDriverGroupSlowTime[i] != 0; + + group.polarity = driverPolarity; + + // Not using groups 0-3 in this example because we're not using the direct + // drivers (drivers 0-31). So, start activating the groups at group 4. + group.active = i >= 4; + + // Matrix rows should be disabled after they are driven so they don't + // overlap into the next row. + group.disableStrobeAfter = mappedDriverGroupSlowTime[i] != 0; + + PRDriverUpdateGroupConfig(proc, &group); + } + + + // Now set up the global driver parameters. + + PRDriverGlobalConfig globals; + + // Start with outputs disabled so the P-ROC can initialize all of its + // logic without actually driving anything. + globals.enableOutputs = false; + globals.globalPolarity = driverPolarity; + globals.useClear = false; + globals.strobeStartSelect = false; + + // startStrobeTime is obselete. It used to mean cycle through the drivers + // every x ms. Now the logic loops as fast as it can, which is as fast + // as the combination of all of the slowTime combined. + globals.startStrobeTime = 1; + + // Here's where the enable lines are set for the matrix columns. + // All of the groups in Matrix 0 were configured to use index 0, which + // is set to 6 here. 6 maps to Driver Board 3, Bank A, which is the + // source bank on the source-sink-8 board. + // All of the groups in Matrix 1 were configured to use index 1, which + // is set to 8 here. 8 maps to Driver Board 4, Bank A, which is the + // source bank on the source-sink-8 board. + globals.matrixRowEnableIndex0 = 6; + globals.matrixRowEnableIndex1 = 8; + + // Choose the polarity for the Column strobes. Again, this doesn't really + // matter since the Driver Boards auto-detect polarity. + globals.activeLowMatrixRows = false; + + // Not using the Stern P/D board. So disable the Stern tickle logic. + globals.tickleSternWatchdog = false; + + // Encoding enables isn't entirely necessary since we're not using + // the multiplexed data/enables bus, but it seems nice that the encoded + // enables map to the Driver Board addresses/banks. + globals.encodeEnables = true; + + // Enable and reset the watchdog logic. + globals.watchdogExpired = false; + globals.watchdogEnable = true; + globals.watchdogResetTime = watchdogResetTime; + + // Send these globals to the P-ROC. Remember, we aren't enabling the outputs + // yet. As soon as this command goes through, the P-ROC will initialize its + // driver logic. + PRDriverUpdateGlobalConfig(proc, &globals); + + // Now that the P-ROC driver logic is initialized, enable the outputs and + // resend the command. + globals.enableOutputs = true; + PRDriverUpdateGlobalConfig(proc, &globals); + + // The P-ROC should now be configured to use our chain of Driver Boards. + // You can now change the outputs by issuing the normal PRDriver commands, + // like: + + // Pulse driver 40 for 30ms. Driver 40 is in group 5, which we + // configured to go to enableIndex 1, which is Board 0, bank B. + // PRDriverPulse(proc, 40, 30); Pulse driver 40 for 30ms. + + // Disable driver 32, which we configured to be on Board 0, Bank A. + // PRDriverDisable(proc, 32); + + // Other commands like PRDriverSchedule, PRDriverPatter, + // PRDriverPulsedPatter, etc will all work too. + + // Note - Another way to control Driver Board outputs is to write + // to them directly. Using this scheme, configuring the individual + // drivers and groups, as shown above, is unnecessary. + // Here's how to write directly to the Driver Boards: + + // uint8_t command = 0x1; // Command 1 is Write + // uint8_t brd_addr = 0x2; + // uint8_t reg_addr = 0x0; // 0 for Bank A, 1 for Bank B + // uint8_t reg_data = 0xa5; // Turn on every other driver. + // uint32_t data= (command << 24) | (brd_addr << 16) | + // (reg_addr << 8) | reg_data; + + // Now issue the write to Module 3, address 0xc00. These + // hardcoded values map to the P-ROC's serial bus output. So + // don't change them. + // PRWriteData(proc, 3, 0xc00, 1, &data); +} + diff --git a/examples/pinproctest/pinproctest.cpp b/examples/pinproctest/pinproctest.cpp index ab75ac2..754cd8e 100644 --- a/examples/pinproctest/pinproctest.cpp +++ b/examples/pinproctest/pinproctest.cpp @@ -204,6 +204,8 @@ int main(int argc, const char **argv) machineType = kPRMachineSternWhitestar; else if(machineTypeString == "sternSAM") machineType = kPRMachineSternSAM; + else if(machineTypeString == "custom") + machineType = kPRMachineCustom; else { fprintf(stderr, "Unknown machine type: %s\n", machineTypeString.c_str()); @@ -224,6 +226,7 @@ int main(int argc, const char **argv) // Even if WPCAlphanumeric, configure the DMD at least to get frame events for // timing purposes. ConfigureDMD(proc); + if (machineType == kPRMachineCustom) ConfigureDrivers(proc); ConfigureSwitches(proc, yamlDoc); // Notify host for all debounced switch events. ConfigureSwitchRules(proc, yamlDoc); // Flippers, slingshots diff --git a/examples/pinproctest/pinproctest.h b/examples/pinproctest/pinproctest.h index d5434eb..9a8f4f9 100644 --- a/examples/pinproctest/pinproctest.h +++ b/examples/pinproctest/pinproctest.h @@ -70,7 +70,7 @@ #define kDMDSubFrames (4) // For color depth of 16 #define kDMDFrameBuffers (3) // 3 is the max -void ConfigureDrivers(PRHandle proc, PRMachineType machineType, YAML::Node& yamlDoc); +void ConfigureDrivers(PRHandle proc); void ConfigureSwitches(PRHandle proc, YAML::Node& yamlDoc); void ConfigureSwitchRules(PRHandle proc, YAML::Node& yamlDoc);