├── .gitignore ├── CMakeLists.txt ├── Doxyfile ├── Makefile ├── README.markdown ├── examples └── pinproctest │ ├── Makefile │ ├── alphanumeric.cpp │ ├── dmd.cpp │ ├── drivers.cpp │ ├── pinproctest.cpp │ ├── pinproctest.h │ └── switches.cpp ├── include └── pinproc.h ├── installers └── Win │ ├── DPInst32.exe │ ├── DPInst64.exe │ ├── README.txt │ └── nsis_install_script.nsi ├── libpinproc.xcodeproj └── project.pbxproj ├── pinproc.pc.cmake ├── src ├── PRCommon.h ├── PRDevice.cpp ├── PRDevice.h ├── PRHardware.cpp ├── PRHardware.h ├── pinproc.cpp └── pinproc.def └── utils └── pinprocfw ├── Makefile ├── lenval.cpp ├── lenval.h ├── pinprocfw.cpp └── pinprocfw.h /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | build/ 3 | */*.pbxuser 4 | */*.perspectivev3 5 | *.o 6 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | ### 2 | ### CMake settings 3 | ### 4 | # Version 2.8.1 was released 2010-03-16 and is a reasonable minimum. 5 | cmake_minimum_required(VERSION 2.8.1) 6 | 7 | # allow relative paths in link_directories() 8 | # see https://cmake.org/cmake/help/v3.18/policy/CMP0081.html 9 | if(POLICY CMP0081) 10 | cmake_policy(SET CMP0081 OLD) 11 | endif() 12 | 13 | ### 14 | ### Project settings 15 | ### 16 | project(PINPROC) 17 | 18 | set(PINPROC_VERSION_MAJOR "2") 19 | set(PINPROC_VERSION_MINOR "1") 20 | set(PINPROC_VERSION "${PINPROC_VERSION_MAJOR}.${PINPROC_VERSION_MINOR}") 21 | 22 | 23 | ### 24 | ### Project options 25 | ### 26 | ## Project stuff 27 | option(PINPROC_BUILD_TOOLS "Enable testing and firmware tools" ON) 28 | 29 | ## Build options 30 | # --> General 31 | # see http://www.cmake.org/cmake/help/cmake2.6docs.html#variable:BUILD_SHARED_LIBS 32 | # http://www.cmake.org/cmake/help/cmake2.6docs.html#command:add_library 33 | option(BUILD_SHARED_LIBS "Build Shared Libraries" OFF) 34 | 35 | # --> Apple 36 | option(APPLE_UNIVERSAL_BIN "Apple: Build universal binary" OFF) 37 | 38 | # --> Microsoft Visual C++ 39 | # see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx 40 | # http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx 41 | option(MSVC_SHARED_RT "MSVC: Build with shared runtime libs (/MD)" ON) 42 | option(MSVC_STHREADED_RT "MSVC: Build with single-threaded static runtime libs (/ML until VS .NET 2003)" OFF) 43 | 44 | option(CROSS_ROOT "Cross-compilation root path" OFF) 45 | 46 | ### 47 | ### Sources, headers, directories and libs 48 | ### 49 | file(GLOB sources "src/[a-zA-Z]*.cpp") 50 | file(GLOB public_headers "include/[a-zA-Z]*.h") 51 | file(GLOB private_headers "src/[a-zA-Z]*.h") 52 | 53 | if(WIN32) 54 | if(BUILD_SHARED_LIBS) 55 | set(defs 56 | src/pinproc.def 57 | ) 58 | endif() 59 | endif() 60 | 61 | if(VERBOSE) 62 | message(STATUS "sources: ${sources}") 63 | message(STATUS "public_headers: ${public_headers}") 64 | message(STATUS "private_headers: ${private_headers}") 65 | message(STATUS "defs: ${defs}") 66 | endif() 67 | 68 | # use -DEXTRA_INC=";" and -DEXTRA_LINK=";" 69 | set(EXTRA_INC "" CACHE STRING "Extra include directories separated by ;") 70 | set(EXTRA_LINK "" CACHE STRING "Extra link directories separated by ;") 71 | if(CROSS_ROOT) 72 | include_directories(${PINPROC_SOURCE_DIR}/include ${EXTRA_INC} ${CROSS_ROOT}/usr/local/include) 73 | link_directories(${EXTRA_LINK} ${CROSS_ROOT}/usr/local/lib) 74 | else() 75 | include_directories(${PINPROC_SOURCE_DIR}/include ${EXTRA_INC} /usr/local/include) 76 | link_directories(${EXTRA_LINK} /usr/local/lib) 77 | endif() 78 | 79 | 80 | ### 81 | ### General compilation settings 82 | ### 83 | if(BUILD_SHARED_LIBS) 84 | set(LABEL_SUFFIX "shared") 85 | else() 86 | set(LABEL_SUFFIX "static") 87 | endif() 88 | 89 | if(APPLE) 90 | if(APPLE_UNIVERSAL_BIN) 91 | set(CMAKE_OSX_ARCHITECTURES ppc;i386) 92 | endif() 93 | endif() 94 | 95 | if(WIN32) 96 | set(lib_ftdi_usb ftd2xx) 97 | if(BUILD_SHARED_LIBS) 98 | add_definitions(-D${PROJECT_NAME}_DLL) # use or build Windows DLL 99 | endif() 100 | if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) 101 | set(CMAKE_INSTALL_PREFIX "C:/") 102 | endif() 103 | else() 104 | set(lib_ftdi_usb usb-1.0 ftdi1) 105 | endif() 106 | 107 | # GCC specialities 108 | if(CMAKE_COMPILER_IS_GNUCC) 109 | if(WIN32) 110 | set(CMAKE_SHARED_LIBRARY_PREFIX "") # DLLs do not have a "lib" prefix 111 | set(CMAKE_IMPORT_LIBRARY_PREFIX "") # same for DLL import libs 112 | set(CMAKE_LINK_DEF_FILE_FLAG "") # CMake workaround (2.8.3) 113 | endif() 114 | endif() 115 | 116 | # Microsoft VisualC++ specialities 117 | if(MSVC) 118 | ### General stuff 119 | # a) Change MSVC runtime library settings (/MD[d], /MT[d], /ML[d] (single-threaded until VS 2003)) 120 | # plus set lib suffix for later use and project label accordingly 121 | # see http://msdn.microsoft.com/en-us/library/aa278396(v=VS.60).aspx 122 | # http://msdn.microsoft.com/en-us/library/2kzt1wy3(v=VS.71).aspx 123 | set(LIB_RT_SUFFIX "md") # CMake defaults to /MD for MSVC 124 | set(LIB_RT_OPTION "/MD") 125 | # 126 | if(NOT MSVC_SHARED_RT) # User wants to have static runtime libraries (/MT, /ML) 127 | if(MSVC_STHREADED_RT) # User wants to have old single-threaded static runtime libraries 128 | set(LIB_RT_SUFFIX "ml") 129 | set(LIB_RT_OPTION "/ML") 130 | if(NOT ${MSVC_VERSION} LESS 1400) 131 | message(FATAL_ERROR "Single-threaded static runtime libraries (/ML) only available until VS .NET 2003 (7.1).") 132 | endif() 133 | else() 134 | set(LIB_RT_SUFFIX "mt") 135 | set(LIB_RT_OPTION "/MT") 136 | endif() 137 | 138 | # correct linker options 139 | foreach(flag_var CMAKE_C_FLAGS CMAKE_CXX_FLAGS) 140 | foreach(config_name "" DEBUG RELEASE MINSIZEREL RELWITHDEBINFO) 141 | set(var_name "${flag_var}") 142 | if(NOT "${config_name}" STREQUAL "") 143 | set(var_name "${var_name}_${config_name}") 144 | endif() 145 | string(REPLACE "/MD" "${LIB_RT_OPTION}" ${var_name} "${${var_name}}") 146 | endforeach() 147 | endforeach() 148 | endif() 149 | # 150 | set(LABEL_SUFFIX "${LABEL_SUFFIX} ${LIB_RT_SUFFIX}") 151 | 152 | # b) Change prefix for static libraries 153 | set(CMAKE_STATIC_LIBRARY_PREFIX "lib") # to distinguish static libraries from DLL import libs 154 | 155 | # c) Correct suffixes for static libraries 156 | if(NOT BUILD_SHARED_LIBS) 157 | set(LIB_TARGET_SUFFIX "${LIB_SUFFIX}${LIB_RT_SUFFIX}") 158 | endif() 159 | endif() 160 | 161 | 162 | ### 163 | ### General install settings 164 | ### 165 | if(WIN32) 166 | set(_library_dir bin) # .dll are in PATH, like executables 167 | else() 168 | set(_library_dir lib) 169 | endif() 170 | 171 | set(INCLUDE_INSTALL_DIR include/p-roc) 172 | set(LIB_INSTALL_DIR "${_library_dir}${LIB_SUFFIX}") 173 | 174 | set(_INSTALL_DESTINATIONS 175 | RUNTIME DESTINATION bin 176 | LIBRARY DESTINATION ${LIB_INSTALL_DIR} 177 | ARCHIVE DESTINATION "lib${LIB_SUFFIX}" 178 | ) 179 | 180 | 181 | ### 182 | ### Library 183 | ### 184 | add_library(pinproc 185 | ${sources} 186 | ${public_headers} 187 | ${private_headers} 188 | ${defs} 189 | ) 190 | 191 | set_target_properties(pinproc PROPERTIES 192 | VERSION "${PINPROC_VERSION}" 193 | SOVERSION "${PINPROC_VERSION_MAJOR}.${PINPROC_VERSION_MINOR}" 194 | PROJECT_LABEL "pinproc ${LABEL_SUFFIX}" 195 | ) 196 | 197 | target_link_libraries(pinproc 198 | ${lib_ftdi_usb} 199 | ) 200 | 201 | if(MSVC) 202 | if(NOT BUILD_SHARED_LIBS) 203 | # correct library names 204 | set_target_properties(pinproc PROPERTIES 205 | DEBUG_POSTFIX "${LIB_TARGET_SUFFIX}d" 206 | RELEASE_POSTFIX "${LIB_TARGET_SUFFIX}" 207 | MINSIZEREL_POSTFIX "${LIB_TARGET_SUFFIX}" 208 | RELWITHDEBINFO_POSTFIX "${LIB_TARGET_SUFFIX}" 209 | ) 210 | endif() 211 | endif() 212 | 213 | install(TARGETS pinproc ${_INSTALL_DESTINATIONS}) 214 | install( 215 | FILES ${public_headers} 216 | DESTINATION ${INCLUDE_INSTALL_DIR} 217 | ) 218 | 219 | if(UNIX) 220 | set(PC_FILE ${CMAKE_BINARY_DIR}/pinproc.pc) 221 | configure_file("pinproc.pc.cmake" ${PC_FILE} @ONLY) 222 | install(FILES ${PC_FILE} DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) 223 | endif() 224 | 225 | 226 | ### 227 | ### Extras 228 | ### 229 | if(PINPROC_BUILD_TOOLS) 230 | # Create a target for the test tool 231 | #TODO: use add_subdirectory() and separate CMakeLists.txt (like yaml-cpp) 232 | # see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_subdirectory 233 | add_executable(pinproctest 234 | examples/pinproctest/pinproctest.cpp 235 | examples/pinproctest/drivers.cpp 236 | examples/pinproctest/dmd.cpp 237 | examples/pinproctest/switches.cpp 238 | examples/pinproctest/alphanumeric.cpp 239 | ) 240 | target_link_libraries(pinproctest 241 | pinproc 242 | ) 243 | 244 | # Create a target for the firmware tool 245 | #TODO: use add_subdirectory() and separate CMakeLists.txt (like yaml-cpp) 246 | # see http://www.cmake.org/cmake/help/cmake-2-8-docs.html#command:add_subdirectory 247 | add_executable(pinprocfw 248 | utils/pinprocfw/pinprocfw.cpp 249 | utils/pinprocfw/lenval.cpp 250 | ) 251 | target_link_libraries(pinprocfw 252 | pinproc 253 | ) 254 | endif() 255 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | AR = ar 3 | ARFLAGS = rc 4 | RANLIB = ranlib 5 | RM = rm -f 6 | LIBPINPROC_CFLAGS=-c -Wall -Iinclude 7 | 8 | LIBPINPROC = bin/libpinproc.a 9 | LIBPINPROC_DYLIB = bin/libpinproc.dylib 10 | SRCS = src/pinproc.cpp src/PRDevice.cpp src/PRHardware.cpp 11 | OBJS := $(SRCS:.cpp=.o) 12 | INCLUDES = include/pinproc.h src/PRCommon.h src/PRDevice.h src/PRHardware.h 13 | 14 | .PHONY: libpinproc 15 | libpinproc: $(LIBPINPROC) $(LIBPINPROC_DYLIB) 16 | 17 | $(LIBPINPROC): $(OBJS) 18 | $(AR) $(ARFLAGS) $@ $(OBJS) 19 | $(RANLIB) $@ 20 | 21 | $(LIBPINPROC_DYLIB): $(OBJS) 22 | g++ -dynamiclib -o $@ `pkg-config --libs libftdi1` $(LDFLAGS) $(OBJS) 23 | 24 | .cpp.o: 25 | $(CC) $(LIBPINPROC_CFLAGS) $(CFLAGS) -o $@ $< 26 | 27 | clean: 28 | $(RM) $(OBJS) 29 | 30 | .PHONY: clean 31 | 32 | depend: $(SRCS) 33 | makedepend $(INCLUDES) $^ 34 | 35 | # DO NOT DELETE THIS LINE -- make depend needs it 36 | 37 | src/PRDevice.o: include/pinproc.h src/PRCommon.h src/PRHardware.h 38 | src/PRHardware.o: include/pinproc.h 39 | src/pinproc.o: include/pinproc.h src/PRDevice.h 40 | src/pinproc.o: src/PRCommon.h src/PRHardware.h 41 | src/PRDevice.o: src/PRDevice.h include/pinproc.h 42 | src/PRDevice.o: src/PRCommon.h src/PRHardware.h 43 | src/PRHardware.o: src/PRHardware.h include/pinproc.h 44 | src/PRHardware.o: src/PRCommon.h 45 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | ## libpinproc 2 | 3 | Library for [Multimorphic, Inc.'s](https://www.multimorphic.com/) P-ROC and P3-ROC pinball controller boards. 4 | 5 | ### Compiling 6 | 7 | #### Prerequisites 8 | 9 | libpinproc requires: 10 | 11 | - [libusb](https://github.com/libusb/libusb): Install with the default /usr/local prefix. Current builds of libftdi and libpinproc use libusb-1.0. 12 | 13 | - [libftdi](https://www.intra2net.com/en/developer/libftdi/): Install with the default /usr/local prefix. 14 | 15 | #### Building with CMake (Linux and macOS) 16 | 17 | Download and install [CMake](https://cmake.org/download/). Then: 18 | 19 | cd libpinproc 20 | mkdir bin; cd bin 21 | cmake .. 22 | make 23 | 24 | The CMakeLists.txt file is presently designed to be run from a directory inside the libpinproc directory. This will build both libpinproc and pinproctest. Binaries will be placed in the directory that make was run from. We recommend 'bin', as it is the path expected by pypinproc. 25 | 26 | Note: On some systems, it may be necessary to build libpinproc with the '-fPIC' option. To do this with cmake, instead of running 'cmake ..', run 'cmake .. -DCMAKE_CXX_FLAGS="-fPIC"'. Compiling without '-fPIC' may cause problems when building the Python extensions on some 64-bit Linux machines. 27 | 28 | Mac users may need to install [D2xxHelper](http://www.ftdichip.com/Drivers/D2XX.htm) to keep the Mac from claiming the P-ROC/P3-ROC and creating a `/dev/tty.usbserial` device for it. It may be necessary to install a second time, if you're asked to allowing the installation via the Security & Privacy System Preference. You will also need to reboot after installing D2xxHelper. Run a `ls /dev/tty.usbserial*` before and after connecting the P-ROC/P3-ROC. If you see a new entry, libpinproc will not be able to connect. 29 | 30 | #### Building in Windows with MinGW/CMake 31 | 32 | (Note that these instructions are outdated with the advent of of MSYS2/MinGW64. Recent attempts at building with these instructions result in builds with dependencies on DLLs from MinGW64. For users with MSYS/MinGW32 installations they should still be valid.) 33 | 34 | Download and unzip [ftd2xx for Windows zip file](http://www.ftdichip.com/Drivers/D2XX.htm). Plug in a powered-up P-ROC and point the driver install wizard to the unzipped driver. Note, this is a two-step process. It will ask you to install a driver twice (once for USB and again for the FTDI specific stuff). 35 | 36 | Download and install [CMake](https://cmake.org/download/). 37 | 38 | Download and install [MinGW](http://sourceforge.net/projects/mingw/files/). (Tested with MinGW 5.1.4) 39 | 40 | Follow directions above for Building with CMake with the following exception: 41 | - Add `-G "MinGW Makefiles"` to the cmake command line. 42 | - Use `-DEXTRA_INC=""` and `-DEXTRA_LINK=""` to add include/library paths for `ftd2xx.h` and `ftd2xx.sys`. 43 | - Use mingw32-make instead of make. 44 | 45 | #### Building in Windows with CMake and Visual Studio 2019 46 | 47 | Follow directions above for Building with CMake with the following exception: 48 | - Add `-A Win32` to the cmake command line. 49 | - Use `-DEXTRA_INC=""` and `-DEXTRA_LINK=""` to add include/library paths for `ftd2xx.h` and `ftd2xx.sys`. 50 | - Open PINPROC.sln in Visual Studio, switch to the Debug or Release configuration and perform ALL_BUILD. It will place the libary and sample programs in `build/Debug` and `build/Release`. 51 | 52 | Example: 53 | 54 | cd libpinproc 55 | mkdir bin; cd bin 56 | cmake .. -A Win32 57 | # configure paths for ftd2xxx; use `cmake .. -L` to list configured options 58 | cmake .. -D EXTRA_INC="../ftd2xx" 59 | cmake .. -D EXTRA_LINK="../ftd2xx/i386" 60 | # Can now open PINPROC.sln in Visual Studio and build Debug and Release targets. 61 | 62 | ### Testing 63 | 64 | Once built, run the `pinproctest` program with the appropriate "machine type" passed in (e.g., "wpc"). Run `pinproctest` without any parameters for a list of valid types. 65 | 66 | ### License 67 | 68 | Copyright (c) 2009 Gerry Stellenberg, Adam Preble 69 | 70 | Copyright (c) 2020 Multimorphic, Inc. 71 | 72 | Contributors: 73 | - Adam Preble 74 | - Gerry Stellenberg 75 | - Jan Kantert 76 | - Jimmy Lipham 77 | - Koen Heltzel 78 | - Roy Eltham 79 | - Tom Collins 80 | 81 | Permission is hereby granted, free of charge, to any person 82 | obtaining a copy of this software and associated documentation 83 | files (the "Software"), to deal in the Software without 84 | restriction, including without limitation the rights to use, 85 | copy, modify, merge, publish, distribute, sublicense, and/or sell 86 | copies of the Software, and to permit persons to whom the 87 | Software is furnished to do so, subject to the following 88 | conditions: 89 | 90 | The above copyright notice and this permission notice shall be 91 | included in all copies or substantial portions of the Software. 92 | 93 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 94 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 95 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 96 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 97 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 98 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 99 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 100 | OTHER DEALINGS IN THE SOFTWARE. 101 | -------------------------------------------------------------------------------- /examples/pinproctest/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | RM = rm -f 3 | CFLAGS = $(ARCH) -c -Wall -I../../include 4 | LDFLAGS = $(ARCH) -L../../bin 5 | 6 | uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') 7 | 8 | PINPROCTEST = ../../bin/pinproctest 9 | LIBPINPROC = ../../bin/libpinproc.a 10 | SRCS = pinproctest.cpp drivers.cpp dmd.cpp switches.cpp 11 | OBJS := $(SRCS:.cpp=.o) 12 | INCLUDES = ../../include/pinproc.h 13 | 14 | LIBS = usb pinproc 15 | ifneq ($(uname_s),Windows) # not Windows 16 | LIBS += ftdi 17 | endif 18 | ifeq ($(uname_s),Windows) 19 | LIBS = ftd2xx 20 | endif 21 | 22 | pinproctest: $(PINPROCTEST) 23 | 24 | $(PINPROCTEST): $(OBJS) $(LIBPINPROC) 25 | $(CC) $(LDFLAGS) $(OBJS) $(addprefix -l,$(LIBS)) -o $@ 26 | 27 | .cpp.o: 28 | $(CC) $(CFLAGS) -o $@ $< 29 | 30 | clean: 31 | $(RM) $(OBJS) 32 | 33 | .PHONY: clean pinproctest 34 | 35 | depend: $(SRCS) 36 | makedepend $(INCLUDES) $^ 37 | 38 | # DO NOT DELETE THIS LINE -- make depend needs it 39 | 40 | pinproctest.o: pinproctest.h ../../include/pinproc.h 41 | drivers.o: pinproctest.h ../../include/pinproc.h 42 | dmd.o: pinproctest.h ../../include/pinproc.h 43 | switches.o: pinproctest.h ../../include/pinproc.h 44 | -------------------------------------------------------------------------------- /examples/pinproctest/alphanumeric.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #include "pinproctest.h" 26 | 27 | void display(PRHandle proc, char * string_1, char * string_2) 28 | { 29 | // Start at ASCII table offset 32: ' ' 30 | const int asciiSegments[] = {0x0000, // ' ' 31 | 0x0000, // '!' 32 | 0x0000, // '"' 33 | 0x0000, // '#' 34 | 0x0000, // '$' 35 | 0x0000, // '%' 36 | 0x0000, // '&' 37 | 0x0200, // ''' 38 | 0x1400, // '(' 39 | 0x4100, // ')' 40 | 0x7f40, // '*' 41 | 0x2a40, // '+' 42 | 0x8080, // ',' 43 | 0x0840, // '-' 44 | 0x8000, // '.' 45 | 0x4400, // '/' 46 | 47 | 0x003f, // '0' 48 | 0x0006, // '1' 49 | 0x085b, // '2' 50 | 0x084f, // '3' 51 | 0x0866, // '4' 52 | 0x086d, // '5' 53 | 0x087d, // '6' 54 | 0x0007, // '7' 55 | 0x087f, // '8' 56 | 0x086f, // '9' 57 | 58 | 0x0000, // '1' 59 | 0x0000, // '1' 60 | 0x0000, // '1' 61 | 0x0000, // '1' 62 | 0x0000, // '1' 63 | 0x0000, // '1' 64 | 0x0000, // '1' 65 | 66 | 0x0877, // 'A' 67 | 0x2a4f, // 'B' 68 | 0x0039, // 'C' 69 | 0x220f, // 'D' 70 | 0x0879, // 'E' 71 | 0x0871, // 'F' 72 | 0x083d, // 'G' 73 | 0x0876, // 'H' 74 | 0x2209, // 'I' 75 | 0x001e, // 'J' 76 | 0x1470, // 'K' 77 | 0x0038, // 'L' 78 | 0x0536, // 'M' 79 | 0x1136, // 'N' 80 | 0x003f, // 'O' 81 | 0x0873, // 'P' 82 | 0x103f, // 'Q' 83 | 0x1873, // 'R' 84 | 0x086d, // 'S' 85 | 0x2201, // 'T' 86 | 0x003e, // 'U' 87 | 0x4430, // 'V' 88 | 0x5036, // 'W' 89 | 0x5500, // 'X' 90 | 0x2500, // 'Y' 91 | 0x4409 // 'Z' 92 | }; 93 | 94 | const int DIS_STB = 8; 95 | const int STB_1 = 9; 96 | const int STB_2 = 10; 97 | const int STB_3 = 11; 98 | const int STB_4 = 12; 99 | 100 | int i, cmd_index=0; 101 | char char_a, char_b; 102 | int segs_a, segs_b; 103 | 104 | PRDriverAuxCommand auxCommands[256]; 105 | 106 | // Disable the first entry so the Aux logic won't begin immediately. 107 | PRDriverAuxPrepareDisable(&auxCommands[cmd_index++]); 108 | 109 | for (i=0; i<16; i++) { 110 | // Assert the STB line 111 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), i, 0, DIS_STB, false, 0); 112 | 113 | char_a = string_1[i]; 114 | char_b = string_2[i]; 115 | 116 | segs_a = asciiSegments[char_a - 32]; 117 | segs_b = asciiSegments[char_b - 32]; 118 | 119 | printf("ASCII Chars and associated segment values: %d\n", i); 120 | printf("char_a: %x, segs_a: %x\n", char_a, segs_a); 121 | printf("char_b: %x, segs_b: %x\n", char_b, segs_b); 122 | 123 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), segs_a & 0xff, 0, STB_1, false, 0); 124 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), (segs_a >> 8) & 0xff, 0, STB_2, false, 0); 125 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), segs_b & 0xff, 0, STB_3, false, 0); 126 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), (segs_b >> 8) & 0xff, 0, STB_4, false, 0); 127 | 128 | PRDriverAuxPrepareDelay(&auxCommands[cmd_index++],350); 129 | 130 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), 0, 0, STB_1, false, 0); 131 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), 0, 0, STB_2, false, 0); 132 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), 0, 0, STB_3, false, 0); 133 | PRDriverAuxPrepareOutput(&(auxCommands[cmd_index++]), 0, 0, STB_4, false, 0); 134 | 135 | PRDriverAuxPrepareDelay(&auxCommands[cmd_index++],40); 136 | } 137 | 138 | PRDriverAuxPrepareJump(&auxCommands[cmd_index++],1); 139 | 140 | printf("Aux commands being sent:\n"); 141 | for (i=0; i= 0; row--) 81 | { 82 | // Map the color index to the DMD's physical color map 83 | int mappedColors[] = {0, 2, 8, 10, 1, 3, 9, 11, 4, 6, 12, 14, 5, 7, 13, 15}; 84 | mappedColor = mappedColors[color]; 85 | 86 | // Loop through each of 16 bytes in a row 87 | for (col = 0; col < kDMDColumns / 8; col++) 88 | { 89 | // Loop through each subframe 90 | for (subFrame = 0; subFrame < kDMDSubFrames; subFrame++) 91 | { 92 | // Turn on the byte in each sub-frame that's enabled 93 | // active for the color code. 94 | if (((mappedColor >> subFrame) & 1) == 1) 95 | dots[subFrame*(kDMDColumns*kDMDRows/8)+((row%kDMDRows)*(kDMDColumns / 8))+col] = byte_shifter; 96 | } 97 | } 98 | // Determine where to change the color in order to progress from row 0 = color 0 99 | // to the last row being the last color. 100 | if (row % (int)((kDMDRows/(1 << kDMDSubFrames))) == 0) color--; 101 | if (byte_shifter == 1) byte_shifter = 0x80; 102 | else byte_shifter = byte_shifter >> 1; 103 | } 104 | } 105 | } 106 | 107 | -------------------------------------------------------------------------------- /examples/pinproctest/drivers.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 3009 Gerry Stellenberg, Adam Preble 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #include "pinproctest.h" 26 | 27 | // This is an example configuration for a custom machine showing 28 | // the steps to configure drivers. 29 | // Custom machine devs will almost certainly need to use different settings 30 | // tailored to their hardware setup. 31 | 32 | // For this example, we're using the following driver group configuration: 33 | // Group 0 (Drivers 0-7) : Unused 34 | // Group 1 (Drivers 8-15) : Unused 35 | // Group 2 (Drivers 16-23) : Unused 36 | // Group 3 (Drivers 24-31) : Unused 37 | // Group 4 (Drivers 32-39) : Coils 0-7 38 | // Group 5 (Drivers 40-47) : Coils 8-15 39 | // Group 6 (Drivers 48-55) : Coils 16-23 40 | // Group 7 (Drivers 56-63) : Coils 24-31 41 | // Group 8 (Drivers 64-71) : Coils 32-39 42 | // Group 9 (Drivers 72-79) : Coils 40-47 43 | // Group 10 (Drivers 80-87) : Matrix 0 0-7 44 | // Group 11 (Drivers 88-95) : Matrix 0 8-15 45 | // Group 12 (Drivers 96-103) : Matrix 0 16-23 46 | // Group 13 (Drivers 104-111) : Matrix 0 24-31 47 | // Group 14 (Drivers 112-119) : Matrix 0 32-39 48 | // Group 15 (Drivers 120-127) : Matrix 0 40-47 49 | // Group 16 (Drivers 128-135) : Matrix 0 48-55 50 | // Group 17 (Drivers 136-143) : Matrix 0 56-63 51 | // Group 18 (Drivers 144-151) : Matrix 1 0-7 52 | // Group 19 (Drivers 152-159) : Matrix 1 8-15 53 | // Group 20 (Drivers 160-167) : Matrix 1 16-23 54 | // Group 21 (Drivers 168-175) : Matrix 1 24-31 55 | // Group 22 (Drivers 176-183) : Matrix 1 32-39 56 | // Group 23 (Drivers 184-191) : Matrix 1 40-47 57 | // Group 24 (Drivers 192-199) : Matrix 1 48-55 58 | // Group 25 (Drivers 300-207) : Matrix 1 56-63 59 | 60 | // The Driver Board setup is the following: 61 | // Address 0 : Sink-16 62 | // Address 1 : Sink-16 63 | // Address 2 : Sink-16 64 | // Address 3 : Source-sink-8 65 | // Address 4 : Source-sink-8 66 | 67 | 68 | // First create individual driver records for each driver, and reset them to 69 | // zero except for the polarity, which is set according to driverPolarity from 70 | // above. 71 | void InitializeDrivers(PRHandle proc, bool driverPolarity) 72 | { 73 | int i; 74 | for (i = 0; i < kPRDriverCount; i++) 75 | { 76 | PRDriverState driver; 77 | memset(&driver, 0x00, sizeof(PRDriverState)); 78 | driver.driverNum = i; 79 | driver.polarity = driverPolarity; 80 | PRDriverUpdateState(proc, &driver); 81 | } 82 | } 83 | 84 | void ConfigureDriverGroups(PRHandle proc, bool driverPolarity) 85 | { 86 | int i; 87 | 88 | // Each entry in the mappedDriverGroupEnableIndex is the enable line that 89 | // will be asserted when the data belonging to the group is serviced. 90 | // The enable line maps to a Driver Board and bank. 91 | // Bits [3:1] of the index represent the Driver 92 | // Board address, and bit [0] represents the bank (A vs B). For example, 93 | // Enable 0 maps to Board 0, Bank A. Enable 1 maps to Board 0, Bank B. 94 | // Enable 2 maps to Board 1, Bank A. Etc, etc. 95 | 96 | // The groups being serviced correspond directly to the P-ROC's drivers. 97 | // Group 0 is for drivers 0-7 group 1 is for drivers 15-8, and so on. 98 | // Groups 0-3 correspond to the P-ROC's direct driver outputs. 99 | // The remaining groups correspond to the P-ROC's multiplexed drivers, 100 | // and are therefore the drivers used on existing P/D boards and now 101 | // on the new Driver Boards. These start at group 4 (drivers 32-39). 102 | // Therefore, the enable indexes given to groups 0-3 are all 0 in 103 | // this case and don't matter. Group 4 is also 0, meaning drivers 104 | // 32-39 map to Driver Board 0, Bank A. 105 | 106 | // Notice groups 10-17 all use index 7, which maps to Driver Board 3, 107 | // Bank B. This means that drivers 80-143 all use Driver Board 3, 108 | // Bank B. In the example setup, this is a Source-Sink-8 Board where 109 | // Bank B is the row outputs. Similarly, groups 18-25, or drivers 110 | // 144-207, go to index 9 or Board 4, Bank B. Board 4 is also a 111 | // source-sink-8 board. 112 | 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}; 113 | 114 | // Slow times are used to allow matrix groups to turn on the matrix lamp or led. 115 | // They're in microseconds. Here, all matrixed groups turn on for 300us. 116 | 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}; 117 | 118 | // GroupActivateIndexes indicate which column to strobe while a matrix group 119 | // is being serviced. For instance, group 10 is 0, so data bit [0] is asserted 120 | // for the matrix column when drivers 80-87 are driven onto the rows of the 121 | // matrix. Next, group 11 is 1, so data bit [1] represents the active column 122 | // when drivers 88-95 are driven onto the Rows. How these columns map to the 123 | // Driver Boards is determined by the matrixRowEnableIndex below. 124 | 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}; 125 | 126 | // There are 2 matrixRowEnableIndexes because the P-ROC can control 2 separate 127 | // matrixes, and in fact this example uses 2 matrixes. This next 128 | // variable mappedDriverGroupRowEnableSelect specifies which of the 2 indexes 129 | // to use when the groups are serviced. Groups 10-17 use index 0, and 130 | // groups 18-25 use index 1. The value of indexes 0 and 1 is defined below 131 | // in the matrixRowEnableIndex variables. 132 | 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}; 133 | 134 | for (i = 0; i < kPRDriverGroupsMax; i++) 135 | { 136 | PRDriverGroupConfig group; 137 | //memset(&group, 0x00, sizeof(PRDriverGroupConfig)); 138 | 139 | group.groupNum = i; 140 | 141 | group.slowTime = mappedDriverGroupSlowTime[i]; 142 | group.enableIndex = mappedDriverGroupEnableIndex[i]; 143 | group.rowActivateIndex = mappedDriverGroupActivateIndex[i]; 144 | group.rowEnableSelect = mappedDriverGroupRowEnableSelect[i]; 145 | 146 | // All of the groups with slow times are in matrixes. 147 | group.matrixed = mappedDriverGroupSlowTime[i] != 0; 148 | 149 | group.polarity = driverPolarity; 150 | 151 | // Not using groups 0-3 in this example because we're not using the direct 152 | // drivers (drivers 0-31). So, start activating the groups at group 4. 153 | group.active = i >= 4; 154 | 155 | // Matrix rows should be disabled after they are driven so they don't 156 | // overlap into the next row. 157 | group.disableStrobeAfter = mappedDriverGroupSlowTime[i] != 0; 158 | 159 | PRDriverUpdateGroupConfig(proc, &group); 160 | } 161 | } 162 | 163 | void ConfigureDriverGlobals(PRHandle proc, bool driverPolarity) 164 | { 165 | PRDriverGlobalConfig globals; 166 | 167 | // Set up the watchdog time for when the global settings are programmed. 1000 168 | // means the drivers will disable automatically if the watchdog isn't updated 169 | // for 1 second (1000ms). This could happen if software crashes or if the USB 170 | // cable is unplugged. 171 | const int watchdogResetTime = 1000; // milliseconds 172 | 173 | // Start with outputs disabled so the P-ROC can initialize all of its 174 | // logic without actually driving anything. 175 | globals.enableOutputs = false; 176 | globals.globalPolarity = driverPolarity; 177 | globals.useClear = false; 178 | globals.strobeStartSelect = false; 179 | 180 | // startStrobeTime is obselete. It used to mean cycle through the drivers 181 | // every x ms. Now the logic loops as fast as it can, which is as fast 182 | // as the combination of all of the slowTime combined. 183 | globals.startStrobeTime = 1; 184 | 185 | // Here's where the enable lines are set for the matrix columns. 186 | // All of the groups in Matrix 0 were configured to use index 0, which 187 | // is set to 6 here. 6 maps to Driver Board 3, Bank A, which is the 188 | // source bank on the source-sink-8 board. 189 | // All of the groups in Matrix 1 were configured to use index 1, which 190 | // is set to 8 here. 8 maps to Driver Board 4, Bank A, which is the 191 | // source bank on the source-sink-8 board. 192 | globals.matrixRowEnableIndex0 = 6; 193 | globals.matrixRowEnableIndex1 = 8; 194 | 195 | // Choose the polarity for the Column strobes. PDBs are active high. 196 | // So rows should NOT be active low. 197 | globals.activeLowMatrixRows = false; 198 | 199 | // Not using the Stern P/D board. So disable the Stern tickle logic. 200 | globals.tickleSternWatchdog = false; 201 | 202 | // Encoding enables isn't entirely necessary since we're not using 203 | // the multiplexed data/enables bus, but it seems nice that the encoded 204 | // enables map to the Driver Board addresses/banks. 205 | globals.encodeEnables = true; 206 | 207 | // Enable and reset the watchdog logic. 208 | globals.watchdogExpired = false; 209 | globals.watchdogEnable = true; 210 | globals.watchdogResetTime = watchdogResetTime; 211 | 212 | // Send these globals to the P-ROC. Remember, we aren't enabling the outputs 213 | // yet. As soon as this command goes through, the P-ROC will initialize its 214 | // driver logic. 215 | PRDriverUpdateGlobalConfig(proc, &globals); 216 | 217 | // Now that the P-ROC driver logic is initialized, enable the outputs and 218 | // resend the command. 219 | globals.enableOutputs = true; 220 | PRDriverUpdateGlobalConfig(proc, &globals); 221 | } 222 | 223 | void ConfigureDrivers(PRHandle proc) 224 | { 225 | // First set up a bunch of constants to use later: 226 | 227 | // The driverPolarity determines when the drivers go high or low when 228 | // they are supposed to be active. PDBs are active high. So 229 | // this should be true. 230 | const bool driverPolarity = true; 231 | 232 | // Now start actually programming thing in the P-ROC. 233 | 234 | // First reset each individual driver. 235 | InitializeDrivers(proc, driverPolarity); 236 | 237 | // Now configure all of the groups. 238 | ConfigureDriverGroups(proc, driverPolarity); 239 | 240 | // Now take care of the globals. 241 | ConfigureDriverGlobals(proc, driverPolarity); 242 | 243 | // The P-ROC should now be configured to use our chain of Driver Boards. 244 | // You can now change the outputs by issuing the normal PRDriver commands, 245 | // like: 246 | 247 | // Pulse driver 40 for 30ms. Driver 40 is in group 5, which we 248 | // configured to go to enableIndex 1, which is Board 0, bank B. 249 | // PRDriverPulse(proc, 40, 30); Pulse driver 40 for 30ms. 250 | 251 | // Disable driver 32, which we configured to be on Board 0, Bank A. 252 | // PRDriverDisable(proc, 32); 253 | 254 | // Other commands like PRDriverSchedule, PRDriverPatter, 255 | // PRDriverPulsedPatter, etc will all work too. 256 | 257 | // Note - Another way to control Driver Board outputs is to write 258 | // to them directly. Using this scheme, configuring the individual 259 | // drivers and groups, as shown above, is unnecessary. 260 | // Here's how to write directly to the Driver Boards: 261 | 262 | // uint8_t command = 0x1; // Command 1 is Write 263 | // uint8_t brd_addr = 0x2; 264 | // uint8_t reg_addr = 0x0; // 0 for Bank A, 1 for Bank B 265 | // uint8_t reg_data = 0xa5; // Turn on every other driver. 266 | // uint32_t data= (command << 24) | (brd_addr << 16) | 267 | // (reg_addr << 8) | reg_data; 268 | 269 | // Now issue the write to Module 3, address 0xc00. These 270 | // hardcoded values map to the P-ROC's serial bus output. So 271 | // don't change them. 272 | // PRWriteData(proc, 3, 0xc00, 1, &data); 273 | } 274 | 275 | -------------------------------------------------------------------------------- /examples/pinproctest/pinproctest.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | /* 26 | * pinproctest.cpp 27 | * libpinproc 28 | */ 29 | #include "pinproctest.h" 30 | uint32_t board_id = 0; 31 | 32 | PRMachineType machineType = kPRMachineInvalid; 33 | 34 | /** Demonstration of the custom logging callback. */ 35 | void TestLogger(PRLogLevel level, const char *text) 36 | { 37 | printf("TEST: %s", text); 38 | } 39 | 40 | void ConfigureAccelerometerMotion(PRHandle proc) 41 | { 42 | uint32_t readData[5]; 43 | 44 | // Only the P3-ROC has an accelerometer. 45 | if (board_id != P3_ROC_CHIP_ID) { 46 | return; 47 | } 48 | 49 | PRReadData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x10D, 1, readData); 50 | printf("Accel chip id: %x\n", readData[0]); 51 | 52 | // Set FF_MT_COUNT (0x18) 53 | readData[0] = 1; 54 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x118, 1, readData); 55 | 56 | // Set FF_MT_THRESH (0x17) 57 | readData[0] = 1; 58 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x117, 1, readData); 59 | 60 | // Set FF_MT_CONFIG (0x15) 61 | readData[0] = 0xD8; 62 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x115, 1, readData); 63 | 64 | // Enable Motion interrupts 65 | readData[0] = 0x04; 66 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12D, 1, readData); 67 | 68 | // Direct motion interrupt to int0 pin (default) 69 | readData[0] = 0x04; 70 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12E, 1, readData); 71 | 72 | readData[0] = 0x3D; 73 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12A, 1, readData); 74 | 75 | readData[0] = 0x02; 76 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12B, 1, readData); 77 | 78 | 79 | // Enable auto-polling of accelerometer every 128 ms (8 times a sec). 80 | //readData[0] = 0x0F; // Enable polling, 8 times a second. 81 | readData[0] = 0x00; // Disable polling 82 | readData[0] = readData[0] | 0x1600; // Set IRQ status addr (FF_MT_SRC) 83 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x000, 1, readData); 84 | PRFlushWriteData(proc); 85 | } 86 | 87 | void ConfigureAccelerometerTransient(PRHandle proc) 88 | { 89 | uint32_t readData[5]; 90 | 91 | // Only the P3-ROC has an accelerometer. 92 | if (board_id != P3_ROC_CHIP_ID) { 93 | return; 94 | } 95 | 96 | PRReadData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x10D, 1, readData); 97 | printf("Accel chip id: %x\n", readData[0]); 98 | 99 | // Set to standby so register changes will take. 100 | readData[0] = 0x0; 101 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12A, 1, readData); 102 | 103 | // Set HPF_OUT bit in XYZ_DATA_CFG (0x0E) 104 | //readData[0] = 0x10; 105 | //PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x10E, 1, readData); 106 | 107 | 108 | // Set HP_FILTER_CUTOFF (0x0F) 109 | readData[0] = 0x03; 110 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x10F, 1, readData); 111 | 112 | // Set FF_TRANSIENT_COUNT (0x20) 113 | readData[0] = 1; 114 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x120, 1, readData); 115 | 116 | // Set FF_TRANSIENT_THRESH (0x1F) 117 | readData[0] = 1; 118 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x11F, 1, readData); 119 | 120 | // Set FF_TRANSIENT_CONFIG (0x1D) 121 | readData[0] = 0x1E; 122 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x11D, 1, readData); 123 | 124 | // Enable Motion interrupts 125 | readData[0] = 0x20; 126 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12D, 1, readData); 127 | 128 | // Direct motion interrupt to int0 pin (default) 129 | readData[0] = 0x20; 130 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12E, 1, readData); 131 | 132 | //readData[0] = 0x3D; 133 | readData[0] = 0x05; 134 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12A, 1, readData); 135 | 136 | readData[0] = 0x02; 137 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x12B, 1, readData); 138 | 139 | 140 | // Enable auto-polling of accelerometer every 128 ms (8 times a sec). 141 | //readData[0] = 0x0F; // Enable polling, 8 times a second. 142 | readData[0] = 0x00; // Disable polling 143 | readData[0] = readData[0] | 0x1E00; // Set IRQ status addr (FF_MT_SRC) 144 | PRWriteData(proc, P3_ROC_BUS_ACCELEROMETER_SELECT, 0x000, 1, readData); 145 | PRFlushWriteData(proc); 146 | } 147 | 148 | time_t startTime; 149 | bool runLoopRun = true; 150 | 151 | void RunLoop(PRHandle proc) 152 | { 153 | const int maxEvents = 16; 154 | int i; 155 | PREvent events[maxEvents]; 156 | uint32_t readData[5]; 157 | // Create dot array using an array of bytes. Each byte holds 8 dots. Need 158 | // space for 4 sub-frames of 128/32 dots. 159 | unsigned char dots[4*((128*32)/8)]; 160 | unsigned int dotOffset = 0; 161 | 162 | // Retrieve and store initial switch states. 163 | LoadSwitchStates(proc); 164 | 165 | if (machineType != kPRMachineWPCAlphanumeric) { 166 | // Send 3 frames 167 | for (i=0; i<3; i++) 168 | { 169 | // Create a dot pattern to test the DMD 170 | UpdateDots(dots,dotOffset++); 171 | PRDMDDraw(proc,dots); 172 | } 173 | } 174 | 175 | //ConfigureAccelerometerMotion(proc); 176 | ConfigureAccelerometerTransient(proc); 177 | 178 | int p = 0; 179 | 180 | while (runLoopRun) 181 | { 182 | PRDriverWatchdogTickle(proc); 183 | 184 | int numEvents = PRGetEvents(proc, events, maxEvents); 185 | for (int i = 0; i < numEvents; i++) 186 | { 187 | PREvent *event = &events[i]; 188 | const char *stateText; 189 | switch (event->type) { 190 | case kPREventTypeSwitchOpenDebounced: 191 | stateText = "open"; 192 | break; 193 | case kPREventTypeSwitchClosedDebounced: 194 | stateText = "closed"; 195 | break; 196 | case kPREventTypeSwitchOpenNondebounced: 197 | stateText = "open(ndb)"; 198 | break; 199 | case kPREventTypeSwitchClosedNondebounced: 200 | stateText = "closed(ndb)"; 201 | break; 202 | default: 203 | stateText = "Unknown"; 204 | } 205 | #ifdef _MSC_VER 206 | struct _timeb tv; 207 | _ftime_s(&tv); 208 | #else 209 | struct timeval tv; 210 | gettimeofday(&tv, NULL); 211 | #endif 212 | switch (event->type) 213 | { 214 | case kPREventTypeSwitchOpenDebounced: 215 | case kPREventTypeSwitchClosedDebounced: 216 | case kPREventTypeSwitchOpenNondebounced: 217 | case kPREventTypeSwitchClosedNondebounced: 218 | #ifdef _MSC_VER 219 | printf("%d.%03d switch %3d: %s\n", (int)(tv.time-startTime), tv.millitm, event->value, stateText); 220 | #else 221 | printf("%d.%03d switch %3d: %s\n", (int)(tv.tv_sec-startTime), (int)tv.tv_usec/1000, event->value, stateText); 222 | #endif 223 | UpdateSwitchState( event ); 224 | break; 225 | case kPREventTypeDMDFrameDisplayed: 226 | if (machineType == kPRMachineWPCAlphanumeric) { 227 | //UpdateAlphaDisplay(proc, dotOffset++); 228 | } 229 | else { 230 | UpdateDots(dots,dotOffset++); 231 | PRDMDDraw(proc,dots); 232 | } 233 | break; 234 | case kPREventTypeAccelerometerX: 235 | //readData[0] = event->value & 0x3FFF; 236 | readData[0] = event->value; 237 | break; 238 | case kPREventTypeAccelerometerY: 239 | //readData[1] = event->value & 0x3FFF; 240 | readData[1] = event->value; 241 | break; 242 | case kPREventTypeAccelerometerZ: 243 | //readData[2] = event->value & 0x3FFF; 244 | readData[2] = event->value; 245 | printf("Accel: X: %x, Y: %x, Z: %x\n", readData[0], readData[1],readData[2]); 246 | break; 247 | case kPREventTypeAccelerometerIRQ: 248 | //readData[2] = event->value & 0x3FFF; 249 | readData[3] = event->value; 250 | printf("Accel IRQ: %x\n", readData[3]); 251 | break; 252 | default: 253 | printf("Unknown event: %x:%x\n", event->type, event->value); 254 | } 255 | } 256 | PRFlushWriteData(proc); 257 | #ifdef _MSC_VER 258 | Sleep(10); 259 | #else 260 | usleep(10*1000); // Sleep for 10ms so we aren't pegging the CPU. 261 | #endif 262 | } 263 | } 264 | 265 | void sigint(int) 266 | { 267 | runLoopRun = false; 268 | signal(SIGINT, SIG_DFL); // Re-install the default signal handler. 269 | printf("Exiting...\n"); 270 | } 271 | 272 | const struct { 273 | PRMachineType type; 274 | const char *name; 275 | } machine_types[] = { 276 | { kPRMachineCustom, "custom" }, 277 | { kPRMachineWPCAlphanumeric, "wpcAlphanumeric" }, 278 | { kPRMachineWPC, "wpc" }, 279 | { kPRMachineWPC95, "wpc95" }, 280 | { kPRMachineSternWhitestar, "sternWhitestar" }, 281 | { kPRMachineSternSAM, "sternSAM" }, 282 | { kPRMachinePDB, "pdb" }, 283 | }; 284 | #define MACHINE_TYPES (sizeof(machine_types) / sizeof(machine_types[0])) 285 | 286 | int main(int argc, const char **argv) 287 | { 288 | int i; 289 | 290 | // Set stdout unbuffered to eliminate need to fflush() 291 | setbuf(stdout, NULL); 292 | 293 | // Set a signal handler so that we can exit gracefully on Ctrl-C: 294 | signal(SIGINT, sigint); 295 | startTime = time(NULL); 296 | 297 | if (argc < 2) { 298 | printf("Usage: %s \n\nWhere machine_type is one of:\n ", argv[0]); 299 | for (i = 0; i < MACHINE_TYPES; i++) { 300 | printf("%s %s", i ? "," : "", machine_types[i].name); 301 | } 302 | return 1; 303 | } 304 | 305 | // Assign a custom logging callback to demonstrate capturing log information from P-ROC: 306 | PRLogSetCallback(TestLogger); 307 | 308 | for (i = 0; i < MACHINE_TYPES; i++) { 309 | if (strcmp(argv[1], machine_types[i].name) == 0) { 310 | machineType = machine_types[i].type; 311 | break; 312 | } 313 | } 314 | 315 | if (machineType == kPRMachineInvalid) { 316 | printf("Unknown machine type: %s\n", argv[1]); 317 | return 1; 318 | } 319 | 320 | // Finally instantiate the P-ROC device: 321 | PRHandle proc = PRCreate(machineType); 322 | if (proc == kPRHandleInvalid) { 323 | printf("Error during PRCreate: %s\n", PRGetLastErrorText()); 324 | return 1; 325 | } 326 | PRReadData(proc, P_ROC_MANAGER_SELECT, P_ROC_REG_CHIP_ID_ADDR, 1, &board_id); 327 | if (board_id == P_ROC_CHIP_ID) { 328 | printf("Connected to P-ROC\n"); 329 | } 330 | else if (board_id == P3_ROC_CHIP_ID) { 331 | printf("Connected to P3-ROC\n"); 332 | } 333 | else { 334 | printf("Warning: unrecognized board ID 0x%08X\n", board_id); 335 | } 336 | 337 | PRLogSetLevel(kPRLogInfo); 338 | PRReset(proc, kPRResetFlagUpdateDevice); // Reset the device structs and write them into the device. 339 | 340 | // Even if WPCAlphanumeric, configure the DMD at least to get frame events for 341 | // timing purposes. 342 | ConfigureDMD(proc); 343 | if (machineType == kPRMachineCustom) { 344 | ConfigureDrivers(proc); 345 | } 346 | ConfigureSwitches(proc); // Notify host for all debounced switch events. 347 | 348 | if (machineType == kPRMachineWPCAlphanumeric) { 349 | UpdateAlphaDisplay(proc, 0); 350 | } 351 | 352 | // Pulse a coil for testing purposes. 353 | PRDriverPulse(proc, 47, 30); 354 | // Schedule a feature lamp for testing purposes. 355 | for (i=0; i<8; i++) { 356 | PRDriverSchedule(proc, 80+i, 0xFF00FF00, 0, 0); 357 | } 358 | 359 | //PRDriverSchedule(proc, 80, 0xFF00FF00, 0, 0); 360 | //PRDriverSchedule(proc, 0, 0xFF00AAAA, 1, 1); 361 | 362 | // Pitter-patter lamp 84: on 127ms, off 127ms, forever. 363 | //PRDriverPatter(proc, 84, 127, 127, 0); 364 | 365 | //Pulsed Patter for coil 48: on 5ms, off 10ms, repeat for 45ms. 366 | //PRDriverPulsedPatter(proc, 48, 5, 10, 45); // Coil 48: on 5ms, off 10ms, repeat for 45ms. 367 | 368 | /* 369 | PRDriverAuxCommand auxCommands[256]; 370 | 371 | // Disable the first entry so the Aux logic won't begin immediately. 372 | PRDriverAuxPrepareDisable(&auxCommands[0]); 373 | // Set up a sequence of outputs. 374 | for (i=0; i<16; i++) { 375 | PRDriverAuxPrepareOutput(&(auxCommands[i+1]), i, 0, 8, false); 376 | } 377 | // Disable the last command so the sequence stops. 378 | // PRDriverAuxPrepareDisable(&auxCommands[17]); 379 | // Jump from addr 17 to 1 to repeat. 380 | PRDriverAuxPrepareDelay(&auxCommands[17],1000); 381 | PRDriverAuxPrepareJump(&auxCommands[18],1); 382 | 383 | // Send the commands. 384 | PRDriverAuxSendCommands(proc, auxCommands, 19, 0); 385 | 386 | // Jump from addr 0 to 1 to begin. 387 | PRDriverAuxPrepareJump(&auxCommands[0],1); 388 | PRDriverAuxSendCommands(proc, auxCommands, 1, 0); 389 | */ 390 | PRFlushWriteData(proc); 391 | 392 | printf("Running. Hit Ctrl-C to exit.\n"); 393 | 394 | RunLoop(proc); 395 | 396 | // Clean up P-ROC. 397 | printf("Disabling P-ROC drivers and switch rules...\n"); 398 | 399 | PRReset(proc, kPRResetFlagUpdateDevice); // Reset the device structs and write them into the device. 400 | PRFlushWriteData(proc); 401 | 402 | // Destroy the P-ROC device handle: 403 | PRDelete(proc); 404 | proc = kPRHandleInvalid; 405 | return 0; 406 | } 407 | -------------------------------------------------------------------------------- /examples/pinproctest/pinproctest.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following 12 | * conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | * OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | /* 27 | * pinproctest.cpp 28 | * libpinproc 29 | */ 30 | #ifndef PINPROCTEST_PINPROCTEST_H 31 | #define PINPROCTEST_PINPROCTEST_H 32 | #if !defined(__GNUC__) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4) // GCC supports "pragma once" correctly since 3.4 33 | #pragma once 34 | #endif 35 | 36 | #include 37 | #include 38 | #include 39 | 40 | #ifndef _MSC_VER 41 | #include 42 | #endif 43 | 44 | #include 45 | #include "pinproc.h" // Include libpinproc's header. 46 | #include 47 | 48 | #ifdef _MSC_VER 49 | #include 50 | #include 51 | #include 52 | #else 53 | #include 54 | #endif 55 | 56 | #define kFlippersSection "PRFlippers" 57 | #define kBumpersSection "PRBumpers" 58 | #define kCoilsSection "PRCoils" 59 | #define kSwitchesSection "PRSwitches" 60 | #define kNumberField "number" 61 | 62 | #define kFlipperPulseTime (34) // 34 ms 63 | #define kFlipperPatterOnTime (2) // 2 ms 64 | #define kFlipperPatterOffTime (18) // 2 ms 65 | #define kBumperPulseTime (25) // 25 ms 66 | 67 | #define kDMDColumns (128) 68 | #define kDMDRows (32) 69 | #define kDMDSubFrames (4) // For color depth of 16 70 | #define kDMDFrameBuffers (3) // 3 is the max 71 | 72 | void ConfigureDrivers(PRHandle proc); 73 | 74 | void ConfigureSwitches(PRHandle proc); 75 | void UpdateSwitchState (PREvent * event); 76 | void LoadSwitchStates (PRHandle proc); 77 | 78 | void ConfigureDMD(PRHandle proc); 79 | void UpdateDots(unsigned char * dots, unsigned int dotOffset); 80 | 81 | void UpdateAlphaDisplay(PRHandle, int); 82 | 83 | #endif /* PINPROCTEST_PINPROCTEST_H */ 84 | -------------------------------------------------------------------------------- /examples/pinproctest/switches.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #include "pinproctest.h" 26 | 27 | extern PRMachineType machineType; 28 | 29 | typedef struct SwitchStatus { 30 | PREventType state; 31 | uint32_t lastEventTime; 32 | } SwitchStatus; 33 | 34 | static SwitchStatus switches[kPRSwitchPhysicalLast + 1]; 35 | 36 | void ConfigureSwitches(PRHandle proc) 37 | { 38 | // Configure switch controller registers (if the defaults aren't acceptable) 39 | PRSwitchConfig switchConfig; 40 | switchConfig.clear = false; 41 | switchConfig.use_column_8 = machineType == kPRMachineWPC; 42 | switchConfig.use_column_9 = false; // No WPC machines actually use this. 43 | switchConfig.hostEventsEnable = true; 44 | switchConfig.directMatrixScanLoopTime = 2; // milliseconds 45 | switchConfig.pulsesBeforeCheckingRX = 10; 46 | switchConfig.inactivePulsesAfterBurst = 12; 47 | switchConfig.pulsesPerBurst = 6; 48 | switchConfig.pulseHalfPeriodTime = 13; // milliseconds 49 | PRSwitchUpdateConfig(proc, &switchConfig); 50 | 51 | // Go through the switches array and reset the current status of each switch 52 | for (int i = 0; i <= kPRSwitchPhysicalLast; i++) 53 | { 54 | switches[i].state = kPREventTypeInvalid; 55 | switches[i].lastEventTime = 0; 56 | 57 | PRSwitchRule sw; 58 | sw.notifyHost = true; 59 | sw.reloadActive = false; 60 | PRSwitchUpdateRule(proc, i, kPREventTypeSwitchClosedDebounced, &sw, NULL, 0, false); 61 | PRSwitchUpdateRule(proc, i, kPREventTypeSwitchOpenDebounced, &sw, NULL, 0, false); 62 | } 63 | } 64 | 65 | void ConfigureWPCFlipperSwitchRule (PRHandle proc, int swNum, int mainCoilNum, int holdCoilNum, int pulseTime) 66 | { 67 | const int numDriverRules = 2; 68 | PRDriverState drivers[numDriverRules]; 69 | PRSwitchRule sw; 70 | 71 | // Flipper on rules 72 | PRDriverGetState(proc, mainCoilNum, &drivers[0]); 73 | PRDriverStatePulse(&drivers[0],pulseTime); // Pulse coil for 34ms. 74 | PRDriverGetState(proc, holdCoilNum, &drivers[1]); 75 | PRDriverStatePulse(&drivers[1],0); // Turn on indefintely (set pulse for 0ms) 76 | sw.notifyHost = false; 77 | sw.reloadActive = false; 78 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchClosedNondebounced, &sw, drivers, numDriverRules, true); 79 | sw.notifyHost = true; 80 | sw.reloadActive = false; 81 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchClosedDebounced, &sw, NULL, 0, false); 82 | 83 | // Flipper off rules 84 | PRDriverGetState(proc, mainCoilNum, &drivers[0]); 85 | PRDriverStateDisable(&drivers[0]); // Disable main coil 86 | PRDriverGetState(proc, holdCoilNum, &drivers[1]); 87 | PRDriverStateDisable(&drivers[1]); // Disable hold coil 88 | sw.notifyHost = false; 89 | sw.reloadActive = false; 90 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchOpenNondebounced, &sw, drivers, numDriverRules, true); 91 | sw.notifyHost = true; 92 | sw.reloadActive = false; 93 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchOpenDebounced, &sw, NULL, 0, false); 94 | } 95 | 96 | void ConfigureSternFlipperSwitchRule (PRHandle proc, int swNum, int mainCoilNum, int pulseTime, int patterOnTime, int patterOffTime) 97 | { 98 | printf("swNum: %d', coilnum: %d, pulseTime: %d, pon: %d, poff: %d\n", swNum,mainCoilNum,pulseTime,patterOnTime,patterOffTime); 99 | const int numDriverRules = 1; 100 | PRDriverState drivers[numDriverRules]; 101 | PRSwitchRule sw; 102 | 103 | // Flipper on rules 104 | PRDriverGetState(proc, mainCoilNum, &drivers[0]); 105 | PRDriverStatePatter(&drivers[0],patterOnTime,patterOffTime,pulseTime,true); // Pulse coil for 34ms. 106 | sw.notifyHost = false; 107 | sw.reloadActive = false; 108 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchClosedNondebounced, &sw, drivers, numDriverRules, true); 109 | sw.notifyHost = true; 110 | sw.reloadActive = false; 111 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchClosedDebounced, &sw, NULL, 0, false); 112 | 113 | // Flipper off rules 114 | PRDriverGetState(proc, mainCoilNum, &drivers[0]); 115 | PRDriverStateDisable(&drivers[0]); // Disable main coil 116 | sw.notifyHost = false; 117 | sw.reloadActive = false; 118 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchOpenNondebounced, &sw, drivers, numDriverRules, true); 119 | sw.notifyHost = true; 120 | sw.reloadActive = false; 121 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchOpenDebounced, &sw, NULL, 0, false); 122 | } 123 | 124 | void ConfigureBumperRule (PRHandle proc, int swNum, int coilNum, int pulseTime) 125 | { 126 | const int numDriverRules = 1; 127 | PRDriverState drivers[numDriverRules]; 128 | PRSwitchRule sw; 129 | 130 | PRDriverGetState(proc, coilNum, &drivers[0]); 131 | PRDriverStatePulse(&drivers[0],pulseTime); // Pulse coil for 34ms. 132 | sw.reloadActive = true; 133 | sw.notifyHost = false; 134 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchClosedNondebounced, &sw, drivers, numDriverRules, true); 135 | sw.notifyHost = true; 136 | sw.reloadActive = false; 137 | PRSwitchUpdateRule(proc, swNum, kPREventTypeSwitchClosedDebounced, &sw, NULL, 0, false); 138 | } 139 | 140 | void UpdateSwitchState( PREvent * event ) 141 | { 142 | switches[event->value].state = event->type; 143 | switches[event->value].lastEventTime = event->time; 144 | } 145 | 146 | void LoadSwitchStates( PRHandle proc ) 147 | { 148 | int i; 149 | PREventType procSwitchStates[kPRSwitchPhysicalLast + 1]; 150 | 151 | // Get all of the switch states from the P-ROC. 152 | if (PRSwitchGetStates( proc, procSwitchStates, kPRSwitchPhysicalLast + 1 ) == kPRFailure) 153 | { 154 | printf("Error: Unable to retrieve switch states\n"); 155 | } 156 | else 157 | { 158 | // Copy the returning states into the local switches array. 159 | for (i = 0; i <= kPRSwitchPhysicalLast; i++) 160 | { 161 | switches[i].state = procSwitchStates[i]; 162 | } 163 | 164 | int zero = 0; 165 | for (i = 0; i < kPRSwitchPhysicalLast + 1; i++) 166 | { 167 | if (i % 32 == 0) { 168 | printf("\n"); 169 | if (i != kPRSwitchPhysicalLast) 170 | printf("Current Switch States: %3d: ", i); 171 | } 172 | printf("%d", switches[i].state); 173 | } 174 | printf("\n"); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /include/pinproc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following 12 | * conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | * OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | /** @file pinproc.h 27 | * @brief libpinproc, P-ROC Layer 1 API (Preliminary) 28 | * 29 | */ 30 | #ifndef PINPROC_PINPROC_H 31 | #define PINPROC_PINPROC_H 32 | #if !defined(__GNUC__) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4) // GCC supports "pragma once" correctly since 3.4 33 | #pragma once 34 | #endif 35 | 36 | /* 37 | * 3rd party "stdint.h" replacement available for Visual C++ before version 2010. 38 | * http://en.wikipedia.org/wiki/Stdint.h#External_links 39 | * -> http://msinttypes.googlecode.com/svn/trunk/stdint.h 40 | * Place inside the major include dir (e.g. %ProgramFiles%\Microsoft Visual Studio\VC98\INCLUDE) 41 | */ 42 | #include 43 | 44 | /** @cond */ 45 | // The following ifdef block is the standard way of creating macros which make exporting 46 | // from a DLL simpler. All files within this DLL are compiled with the pinproc_EXPORTS 47 | // symbol defined on the command line. This symbol should not be defined on any project 48 | // that uses this DLL. This way any other project whose source files include this file see 49 | // PINPROC_API functions as being imported from a DLL, whereas this DLL sees symbols 50 | // defined with this macro as being exported. 51 | #undef PINPROC_API 52 | 53 | #ifdef PINPROC_DLL // Using or Building PinPROC DLL (definition defined manually) 54 | #ifdef pinproc_EXPORTS // Building PinPROC DLL (definition created by CMake or defined manually) 55 | #define PINPROC_API __declspec(dllexport) 56 | #else 57 | #define PINPROC_API __declspec(dllimport) 58 | #endif 59 | #endif 60 | // fallback for non-DLL usage and builds 61 | #ifndef PINPROC_API 62 | #define PINPROC_API 63 | #endif 64 | 65 | #if defined(__cplusplus) 66 | #define PINPROC_EXTERN_C_BEGIN extern "C" { 67 | #define PINPROC_EXTERN_C_END } 68 | #else 69 | #define PINPROC_EXTERN_C_BEGIN 70 | #define PINPROC_EXTERN_C_END 71 | #endif 72 | 73 | PINPROC_EXTERN_C_BEGIN 74 | /** @endcond */ 75 | 76 | // Types 77 | 78 | typedef int32_t bool_t; // FIXME: This needs better platform independence. 79 | 80 | typedef int32_t PRResult; /**< See: #kPRSuccess and #kPRFailure. */ 81 | #define kPRSuccess (1) /**< Success value for #PRResult. */ 82 | #define kPRFailure (0) /**< Failure value for #PRResult. */ 83 | 84 | typedef void * PRHandle; /**< Opaque type used to reference an individual P-ROC device. Created with PRCreate() and destroyed with PRDelete(). This value is used as the first parameter to all P-ROC API function calls. */ 85 | #define kPRHandleInvalid (0) /**< Value returned by PRCreate() on failure. Indicates an invalid #PRHandle. */ 86 | 87 | #define P_ROC_INIT_PATTERN_A 0x801F1122 88 | #define P_ROC_INIT_PATTERN_B 0x345678AB 89 | #define P_ROC_CHIP_ID 0xfeedbeef 90 | #define P3_ROC_CHIP_ID 0xf33db33f 91 | 92 | #define P_ROC_VER_REV_FIXED_SWITCH_STATE_READS 0x10013 // 1.19 93 | 94 | #define P_ROC_AUTO_STERN_DETECT_SHIFT 8 95 | #define P_ROC_AUTO_STERN_DETECT_MASK 0x00000100 96 | #define P_ROC_AUTO_STERN_DETECT_VALUE 0x1 97 | #define P_ROC_MANUAL_STERN_DETECT_SHIFT 0 98 | #define P_ROC_MANUAL_STERN_DETECT_MASK 0x00000001 99 | #define P_ROC_MANUAL_STERN_DETECT_VALUE 0x00000000 100 | #define P_ROC_BOARD_VERSION_SHIFT 7 101 | #define P_ROC_BOARD_VERSION_MASK 0x00000080 102 | 103 | #define P_ROC_ADDR_MASK 0x000FFFFF 104 | #define P_ROC_HEADER_LENGTH_MASK 0x7FF00000 105 | #define P_ROC_COMMAND_MASK 0x80000000 106 | 107 | #define P_ROC_ADDR_SHIFT 0 108 | #define P_ROC_HEADER_LENGTH_SHIFT 20 109 | #define P_ROC_COMMAND_SHIFT 31 110 | 111 | #define P_ROC_READ 0 112 | #define P_ROC_WRITE 1 113 | #define P_ROC_REQUESTED_DATA 0 114 | #define P_ROC_UNREQUESTED_DATA 1 115 | 116 | #define P_ROC_REG_ADDR_MASK 0x0000FFFF 117 | #define P_ROC_MODULE_SELECT_MASK 0x000F0000 118 | 119 | #define P_ROC_REG_ADDR_SHIFT 0 120 | #define P_ROC_MODULE_SELECT_SHIFT 16 121 | 122 | #define P_ROC_MANAGER_SELECT 0 123 | #define P_ROC_BUS_JTAG_SELECT 1 124 | #define P_ROC_BUS_SWITCH_CTRL_SELECT 2 125 | #define P_ROC_BUS_DRIVER_CTRL_SELECT 3 126 | #define P_ROC_BUS_STATE_CHANGE_PROC_SELECT 4 127 | #define P_ROC_BUS_DMD_SELECT 5 128 | #define P_ROC_BUS_UNASSOCIATED_SELECT 15 129 | 130 | #define P3_ROC_MANAGER_SELECT 0 131 | #define P3_ROC_BUS_SPI_SELECT 1 132 | #define P3_ROC_BUS_SWITCH_CTRL_SELECT 2 133 | #define P3_ROC_BUS_DRIVER_CTRL_SELECT 3 134 | #define P3_ROC_BUS_STATE_CHANGE_PROC_SELECT 4 135 | #define P3_ROC_BUS_AUX_CTRL_SELECT 5 136 | #define P3_ROC_BUS_ACCELEROMETER_SELECT 6 137 | #define P3_ROC_BUS_I2C_SELECT 7 138 | #define P3_ROC_BUS_UNASSOCIATED_SELECT 15 139 | 140 | #define P_ROC_REG_CHIP_ID_ADDR 0 141 | #define P_ROC_REG_VERSION_ADDR 1 142 | #define P_ROC_REG_WATCHDOG_ADDR 2 143 | #define P_ROC_REG_DIPSWITCH_ADDR 3 144 | 145 | #define P_ROC_MANAGER_WATCHDOG_EXPIRED_SHIFT 30 146 | #define P_ROC_MANAGER_WATCHDOG_ENABLE_SHIFT 14 147 | #define P_ROC_MANAGER_WATCHDOG_RESET_TIME_SHIFT 0 148 | #define P_ROC_MANAGER_REUSE_DMD_DATA_FOR_AUX_SHIFT 10 149 | #define P_ROC_MANAGER_INVERT_DIPSWITCH_1_SHIFT 9 150 | 151 | #define P3_ROC_SPI_OPCODE_SHIFT 24 152 | 153 | #define P3_ROC_SPI_OPCODE_WR_ENABLE 0 154 | #define P3_ROC_SPI_OPCODE_WR_DISABLE 1 155 | #define P3_ROC_SPI_OPCODE_RD_ID 2 156 | #define P3_ROC_SPI_OPCODE_RD_STATUS 3 157 | #define P3_ROC_SPI_OPCODE_WR_STATUS 4 158 | #define P3_ROC_SPI_OPCODE_RD_DATA 5 159 | #define P3_ROC_SPI_OPCODE_FRD_DATA 6 160 | #define P3_ROC_SPI_OPCODE_PP 7 161 | #define P3_ROC_SPI_OPCODE_SECTOR_ERASE 8 162 | #define P3_ROC_SPI_OPCODE_BULK_ERASE 9 163 | #define P3_ROC_SPI_OPCODE_DEEP_POWERDN 10 164 | #define P3_ROC_SPI_OPCODE_RELEASE 11 165 | 166 | #define P_ROC_JTAG_SHIFT_EXIT_SHIFT 16 167 | #define P_ROC_JTAG_SHIFT_NUM_BITS_SHIFT 0 168 | 169 | #define P_ROC_JTAG_CMD_CHANGE_STATE 0 170 | #define P_ROC_JTAG_CMD_SHIFT 1 171 | #define P_ROC_JTAG_CMD_TRANSITION 2 172 | #define P_ROC_JTAG_CMD_SET_PORTS 3 173 | 174 | #define P_ROC_JTAG_CMD_START_SHIFT 31 175 | #define P_ROC_JTAG_CMD_OE_SHIFT 30 176 | #define P_ROC_JTAG_CMD_CMD_SHIFT 24 177 | 178 | #define P_ROC_JTAG_TRANSITION_TCK_MASK_SHIFT 6 179 | #define P_ROC_JTAG_TRANSITION_TDO_MASK_SHIFT 5 180 | #define P_ROC_JTAG_TRANSITION_TMS_MASK_SHIFT 4 181 | #define P_ROC_JTAG_TRANSITION_TCK_SHIFT 2 182 | #define P_ROC_JTAG_TRANSITION_TDO_SHIFT 1 183 | #define P_ROC_JTAG_TRANSITION_TMS_SHIFT 0 184 | 185 | #define P_ROC_JTAG_STATUS_DONE_SHIFT 31 186 | #define P_ROC_JTAG_STATUS_TDI_SHIFT 16 187 | 188 | #define P_ROC_JTAG_COMMAND_REG_BASE_ADDR 0x0 189 | #define P_ROC_JTAG_STATUS_REG_BASE_ADDR 0x1 190 | #define P_ROC_JTAG_TDO_MEMORY_BASE_ADDR 0x400 191 | #define P_ROC_JTAG_TDI_MEMORY_BASE_ADDR 0x800 192 | 193 | #define P_ROC_SWITCH_CTRL_STATE_BASE_ADDR 4 194 | #define P_ROC_SWITCH_CTRL_OLD_DEBOUNCE_BASE_ADDR 11 195 | #define P_ROC_SWITCH_CTRL_DEBOUNCE_BASE_ADDR 12 196 | #define P3_ROC_SWITCH_CTRL_STATE_BASE_ADDR 16 197 | #define P3_ROC_SWITCH_CTRL_DEBOUNCE_BASE_ADDR 32 198 | 199 | #define P_ROC_EVENT_TYPE_SWITCH 0 200 | #define P_ROC_EVENT_TYPE_DMD 1 201 | #define P_ROC_EVENT_TYPE_BURST_SWITCH 2 202 | #define P_ROC_EVENT_TYPE_ACCELEROMETER 3 203 | 204 | #define P_ROC_V1_EVENT_TYPE_MASK 0xC00 205 | #define P_ROC_V1_EVENT_TYPE_SHIFT 10 206 | #define P_ROC_V2_EVENT_TYPE_MASK 0xC000 207 | #define P_ROC_V2_EVENT_TYPE_SHIFT 14 208 | 209 | #define P_ROC_V1_EVENT_SWITCH_NUM_MASK 0xFF 210 | #define P_ROC_V2_EVENT_SWITCH_NUM_MASK 0x7FF 211 | #define P_ROC_V1_EVENT_SWITCH_STATE_MASK 0x100 212 | #define P_ROC_V2_EVENT_SWITCH_STATE_MASK 0x1000 213 | #define P_ROC_V1_EVENT_SWITCH_STATE_SHIFT 8 214 | #define P_ROC_V2_EVENT_SWITCH_STATE_SHIFT 12 215 | #define P_ROC_V1_EVENT_SWITCH_DEBOUNCED_MASK 0x200 216 | #define P_ROC_V2_EVENT_SWITCH_DEBOUNCED_MASK 0x2000 217 | #define P_ROC_V1_EVENT_SWITCH_DEBOUNCED_SHIFT 9 218 | #define P_ROC_V2_EVENT_SWITCH_DEBOUNCED_SHIFT 13 219 | #define P_ROC_V1_EVENT_SWITCH_TIMESTAMP_MASK 0xFFFFF000 220 | #define P_ROC_V1_EVENT_SWITCH_TIMESTAMP_SHIFT 12 221 | #define P_ROC_V2_EVENT_SWITCH_TIMESTAMP_MASK 0xFFFF0000 222 | #define P_ROC_V2_EVENT_SWITCH_TIMESTAMP_SHIFT 16 223 | #define P_ROC_V2_EVENT_ACCEL_TIMESTAMP_MASK 0xFFFC0000 224 | #define P_ROC_V2_EVENT_ACCEL_TIMESTAMP_SHIFT 18 225 | 226 | 227 | #define P_ROC_DRIVER_CTRL_DECODE_SHIFT 10 228 | #define P_ROC_DRIVER_CTRL_REG_DECODE 0 229 | #define P_ROC_DRIVER_CONFIG_TABLE_DECODE 1 230 | #define P_ROC_DRIVER_AUX_MEM_DECODE 2 231 | #define P_ROC_DRIVER_CATCHALL_DECODE 3 232 | 233 | #define P_ROC_DRIVER_GLOBAL_ENABLE_DIRECT_OUTPUTS_SHIFT 31 234 | #define P_ROC_DRIVER_GLOBAL_GLOBAL_POLARITY_SHIFT 30 235 | #define P_ROC_DRIVER_GLOBAL_USE_CLEAR_SHIFT 28 236 | #define P_ROC_DRIVER_GLOBAL_STROBE_START_SELECT_SHIFT 27 237 | #define P_ROC_DRIVER_GLOBAL_START_STROBE_TIME_SHIFT 20 238 | #define P_ROC_DRIVER_GLOBAL_START_STROBE_TIME_MASK 0x07F00000 239 | #define P_ROC_DRIVER_GLOBAL_MATRIX_ROW_ENABLE_INDEX_1_SHIFT 16 240 | #define P_ROC_DRIVER_GLOBAL_MATRIX_ROW_ENABLE_INDEX_1_MASK 0x000F0000 241 | #define P_ROC_DRIVER_GLOBAL_MATRIX_ROW_ENABLE_INDEX_0_SHIFT 12 242 | #define P_ROC_DRIVER_GLOBAL_MATRIX_ROW_ENABLE_INDEX_0_MASK 0x0000F000 243 | #define P_ROC_DRIVER_GLOBAL_ACTIVE_LOW_MATRIX_ROWS_SHIFT 11 244 | #define P_ROC_DRIVER_GLOBAL_ENCODE_ENABLES_SHIFT 10 245 | #define P_ROC_DRIVER_GLOBAL_TICKLE_WATCHDOG_SHIFT 9 246 | 247 | #define P_ROC_DRIVER_GROUP_SLOW_TIME_SHIFT 12 248 | #define P_ROC_DRIVER_GROUP_DISABLE_STROBE_AFTER_SHIFT 11 249 | #define P_ROC_DRIVER_GROUP_ENABLE_INDEX_SHIFT 7 250 | #define P_ROC_DRIVER_GROUP_ROW_ACTIVATE_INDEX_SHIFT 4 251 | #define P_ROC_DRIVER_GROUP_ROW_ENABLE_SELECT_SHIFT 3 252 | #define P_ROC_DRIVER_GROUP_MATRIXED_SHIFT 2 253 | #define P_ROC_DRIVER_GROUP_POLARITY_SHIFT 1 254 | #define P_ROC_DRIVER_GROUP_ACTIVE_SHIFT 0 255 | 256 | #define P_ROC_DRIVER_CONFIG_OUTPUT_DRIVE_TIME_SHIFT 0 257 | #define P_ROC_DRIVER_CONFIG_POLARITY_SHIFT 8 258 | #define P_ROC_DRIVER_CONFIG_STATE_SHIFT 9 259 | #define P_ROC_DRIVER_CONFIG_UPDATE_SHIFT 10 260 | #define P_ROC_DRIVER_CONFIG_WAIT_4_1ST_SLOT_SHIFT 11 261 | #define P_ROC_DRIVER_CONFIG_TIMESLOT_SHIFT 16 262 | #define P_ROC_DRIVER_CONFIG_PATTER_ON_TIME_SHIFT 16 263 | #define P_ROC_DRIVER_CONFIG_PATTER_OFF_TIME_SHIFT 23 264 | #define P_ROC_DRIVER_CONFIG_PATTER_ENABLE_SHIFT 30 265 | #define P_ROC_DRIVER_CONFIG_FUTURE_ENABLE_SHIFT 31 266 | 267 | #define P_ROC_DRIVER_CONFIG_TABLE_DRIVER_NUM_SHIFT 1 268 | 269 | #define P_ROC_DRIVER_AUX_ENTRY_ACTIVE_SHIFT 31 270 | #define P_ROC_DRIVER_AUX_OUTPUT_DELAY_SHIFT 20 271 | #define P_ROC_DRIVER_AUX_OUTPUT_DELAY_MASK 0x7ff 272 | #define P_ROC_DRIVER_AUX_MUX_ENABLES_SHIFT 19 273 | #define P_ROC_DRIVER_AUX_COMMAND_SHIFT 16 274 | #define P_ROC_DRIVER_AUX_COMMAND_MASK 0x3 275 | #define P_ROC_DRIVER_AUX_ENABLES_SHIFT 12 276 | #define P_ROC_DRIVER_AUX_ENABLES_MASK 0xF 277 | #define P_ROC_DRIVER_AUX_EXTRA_DATA_SHIFT 8 278 | #define P_ROC_DRIVER_AUX_EXTRA_DATA_MASK 0xF 279 | #define P_ROC_DRIVER_AUX_DATA_SHIFT 0 280 | #define P_ROC_DRIVER_AUX_DATA_MASK 0xFF 281 | #define P_ROC_DRIVER_AUX_DELAY_TIME_SHIFT 0 282 | #define P_ROC_DRIVER_AUX_DELAY_TIME_MASK 0x3FFF 283 | #define P_ROC_DRIVER_AUX_JUMP_ADDR_SHIFT 0 284 | #define P_ROC_DRIVER_AUX_JUMP_ADDR_MASK 0xFF 285 | 286 | #define P_ROC_DRIVER_AUX_CMD_OUTPUT 2 287 | #define P_ROC_DRIVER_AUX_CMD_DELAY 1 288 | #define P_ROC_DRIVER_AUX_CMD_JUMP 0 289 | 290 | #define P_ROC_SWITCH_CONFIG_CLEAR_SHIFT 31 291 | #define P_ROC_SWITCH_CONFIG_USE_COLUMN_9 30 292 | #define P_ROC_SWITCH_CONFIG_USE_COLUMN_8 29 293 | #define P_ROC_SWITCH_CONFIG_MS_PER_DM_SCAN_LOOP_SHIFT 24 294 | #define P_ROC_SWITCH_CONFIG_PULSES_BEFORE_CHECKING_RX_SHIFT 18 295 | #define P_ROC_SWITCH_CONFIG_INACTIVE_PULSES_AFTER_BURST_SHIFT 12 296 | #define P_ROC_SWITCH_CONFIG_PULSES_PER_BURST_SHIFT 6 297 | #define P_ROC_SWITCH_CONFIG_MS_PER_PULSE_HALF_PERIOD_SHIFT 0 298 | 299 | #define P_ROC_SWITCH_RULE_DRIVE_OUTPUTS_NOW 13 300 | #define P_ROC_SWITCH_RULE_NUM_DEBOUNCE_SHIFT 9 301 | #define P_ROC_SWITCH_RULE_NUM_STATE_SHIFT 8 302 | #define P_ROC_SWITCH_RULE_NUM_SWITCH_NUM_SHIFT 0 303 | #define P_ROC_SWITCH_RULE_NUM_TO_ADDR_SHIFT 2 304 | 305 | #define P_ROC_SWITCH_RULE_RELOAD_ACTIVE_SHIFT 31 306 | #define P_ROC_SWITCH_RULE_NOTIFY_HOST_SHIFT 23 307 | #define P_ROC_SWITCH_RULE_LINK_ACTIVE_SHIFT 10 308 | #define P_ROC_SWITCH_RULE_LINK_ADDRESS_SHIFT 11 309 | #define P_ROC_SWITCH_RULE_CHANGE_OUTPUT_SHIFT 9 310 | #define P_ROC_SWITCH_RULE_DRIVER_NUM_SHIFT 0 311 | 312 | #define P_ROC_STATE_CHANGE_CONFIG_ADDR 0x1000 313 | 314 | #define P_ROC_DMD_NUM_COLUMNS_SHIFT 0 315 | #define P_ROC_DMD_NUM_ROWS_SHIFT 8 316 | #define P_ROC_DMD_NUM_SUB_FRAMES_SHIFT 16 317 | #define P_ROC_DMD_NUM_FRAME_BUFFERS_SHIFT 24 318 | #define P_ROC_DMD_AUTO_INC_WR_POINTER_SHIFT 29 319 | #define P_ROC_DMD_ENABLE_FRAME_EVENTS_SHIFT 30 320 | #define P_ROC_DMD_ENABLE_SHIFT 31 321 | 322 | #define P_ROC_DMD_DOTCLK_HALF_PERIOD_SHIFT 0 323 | #define P_ROC_DMD_DE_HIGH_CYCLES_SHIFT 6 324 | #define P_ROC_DMD_LATCH_HIGH_CYCLES_SHIFT 16 325 | #define P_ROC_DMD_RCLK_LOW_CYCLES_SHIFT 24 326 | 327 | #define P_ROC_DMD_DOT_TABLE_BASE_ADDR 0x1000 328 | 329 | #define P_ROC_DRIVER_PDB_ADDR 0xC00 330 | #define P_ROC_DRIVER_PDB_COMMAND_SHIFT 24 331 | #define P_ROC_DRIVER_PDB_BOARD_ADDR_SHIFT 16 332 | #define P_ROC_DRIVER_PDB_REGISTER_SHIFT 8 333 | #define P_ROC_DRIVER_PDB_DATA_SHIFT 0 334 | #define P_ROC_DRIVER_PDB_READ_COMMAND 0x00 335 | #define P_ROC_DRIVER_PDB_WRITE_COMMAND 0x01 336 | #define P_ROC_DRIVER_PDB_CLEAR_ALL_COMMAND 0x07 337 | #define P_ROC_DRIVER_PDB_BROADCAST_ADDR 0x3F 338 | 339 | #define p_ROC_DRIVER_PDB_REGISTER_BANK_A 0 340 | #define p_ROC_DRIVER_PDB_REGISTER_BANK_B 1 341 | 342 | typedef enum PRLogLevel { 343 | kPRLogVerbose, 344 | kPRLogInfo, 345 | kPRLogWarning, 346 | kPRLogError 347 | } PRLogLevel; 348 | 349 | typedef void (*PRLogCallback)(PRLogLevel level, const char *text); /**< Function pointer type for a custom logging callback. See: PRLogSetCallback(). */ 350 | PINPROC_API void PRLogSetCallback(PRLogCallback callback); /**< Replaces the default logging handler with the given callback function. */ 351 | 352 | PINPROC_API void PRLogSetLevel(PRLogLevel level); 353 | 354 | PINPROC_API const char *PRGetLastErrorText(void); 355 | 356 | /** 357 | * @defgroup device Device Creation & Deletion 358 | * @{ 359 | */ 360 | 361 | typedef enum PRMachineType { 362 | kPRMachineInvalid = 0, 363 | kPRMachineCustom = 1, 364 | kPRMachineWPCAlphanumeric = 2, 365 | kPRMachineWPC = 3, 366 | kPRMachineWPC95 = 4, 367 | kPRMachineSternWhitestar = 5, 368 | kPRMachineSternSAM = 6, 369 | kPRMachinePDB = 7, // PinballControllers.com Driver Boards 370 | } PRMachineType; 371 | 372 | // PRHandle Creation and Deletion 373 | 374 | PINPROC_API PRHandle PRCreate(PRMachineType machineType); /**< Create a new P-ROC device handle. Only one handle per device may be created. This handle must be destroyed with PRDelete() when it is no longer needed. Returns #kPRHandleInvalid if an error occurred. */ 375 | PINPROC_API void PRDelete(PRHandle handle); /**< Destroys an existing P-ROC device handle. */ 376 | 377 | #define kPRResetFlagDefault (0) /**< Only resets state in memory and does not write changes to the device. */ 378 | #define kPRResetFlagUpdateDevice (1) /**< Instructs PRReset() to update the device once it has reset the configuration to its defaults. */ 379 | 380 | /** 381 | * @brief Resets internally maintained driver and switch rule structures. 382 | * @param resetFlags Specify #kPRResetFlagDefault to only reset the configuration in host memory. #kPRResetFlagUpdateDevice will write the default configuration to the device, effectively disabling all drivers and switch rules. 383 | */ 384 | PINPROC_API PRResult PRReset(PRHandle handle, uint32_t resetFlags); 385 | 386 | /** @} */ // End of Device Creation & Deletion 387 | 388 | // I/O 389 | 390 | /** Flush all pending write data out to the P-ROC. */ 391 | PINPROC_API PRResult PRFlushWriteData(PRHandle handle); 392 | 393 | /** Write data out to the P-ROC immediately (does not require a call to PRFlushWriteData). */ 394 | PINPROC_API PRResult PRWriteData(PRHandle handle, uint32_t moduleSelect, uint32_t startingAddr, int32_t numWriteWords, uint32_t * writeBuffer); 395 | 396 | /** Write data buffered to P-ROC (does require a call to PRFlushWriteData). */ 397 | PINPROC_API PRResult PRWriteDataUnbuffered(PRHandle handle, uint32_t moduleSelect, uint32_t startingAddr, int32_t numWriteWords, uint32_t * writeBuffer); 398 | 399 | /** Read data from the P-ROC. */ 400 | PINPROC_API PRResult PRReadData(PRHandle handle, uint32_t moduleSelect, uint32_t startingAddr, int32_t numReadWords, uint32_t * readBuffer); 401 | 402 | // Manager 403 | /** @defgroup Manager 404 | * @{ 405 | */ 406 | 407 | typedef struct PRManagerConfig { 408 | bool_t reuse_dmd_data_for_aux; 409 | bool_t invert_dipswitch_1; 410 | } PRManagerConfig; 411 | 412 | /** Update Manager configuration */ 413 | PINPROC_API PRResult PRManagerUpdateConfig(PRHandle handle, PRManagerConfig *managerConfig); 414 | 415 | // Drivers 416 | /** @defgroup drivers Driver Manipulation 417 | * @{ 418 | */ 419 | 420 | #define kPRDriverGroupsMax (26) /**< Number of available driver groups. */ 421 | #define kPRDriverCount (256) /**< Total number of drivers */ 422 | 423 | #define kPRDriverAuxCmdOutput (2) 424 | #define kPRDriverAuxCmdDelay (1) 425 | #define kPRDriverAuxCmdJump (0) 426 | 427 | typedef struct PRDriverGlobalConfig { 428 | bool_t enableOutputs; // Formerly enable_direct_outputs 429 | bool_t globalPolarity; 430 | bool_t useClear; 431 | bool_t strobeStartSelect; 432 | uint8_t startStrobeTime; 433 | uint8_t matrixRowEnableIndex1; 434 | uint8_t matrixRowEnableIndex0; 435 | bool_t activeLowMatrixRows; 436 | bool_t encodeEnables; 437 | bool_t tickleSternWatchdog; 438 | bool_t watchdogExpired; 439 | bool_t watchdogEnable; 440 | uint16_t watchdogResetTime; 441 | } PRDriverGlobalConfig; 442 | 443 | typedef struct PRDriverGroupConfig { 444 | uint8_t groupNum; 445 | uint16_t slowTime; 446 | uint8_t enableIndex; 447 | uint8_t rowActivateIndex; 448 | uint8_t rowEnableSelect; 449 | bool_t matrixed; 450 | bool_t polarity; 451 | bool_t active; 452 | bool_t disableStrobeAfter; 453 | } PRDriverGroupConfig; 454 | 455 | typedef struct PRDriverState { 456 | uint16_t driverNum; 457 | uint8_t outputDriveTime; 458 | bool_t polarity; 459 | bool_t state; 460 | bool_t waitForFirstTimeSlot; 461 | uint32_t timeslots; 462 | uint8_t patterOnTime; 463 | uint8_t patterOffTime; 464 | bool_t patterEnable; 465 | bool_t futureEnable; 466 | } PRDriverState; 467 | 468 | typedef struct PRDriverAuxCommand { 469 | bool_t active; 470 | bool_t muxEnables; 471 | uint8_t command; 472 | uint8_t enables; 473 | uint8_t extraData; 474 | uint8_t data; 475 | uint16_t delayTime; 476 | uint8_t jumpAddr; 477 | } PRDriverAuxCommand; 478 | 479 | /** Update registers for the global driver configuration. */ 480 | PINPROC_API PRResult PRDriverUpdateGlobalConfig(PRHandle handle, PRDriverGlobalConfig *driverGlobalConfig); 481 | 482 | PINPROC_API PRResult PRDriverGetGroupConfig(PRHandle handle, uint8_t groupNum, PRDriverGroupConfig *driverGroupConfig); 483 | /** Update registers for the given driver group configuration. */ 484 | PINPROC_API PRResult PRDriverUpdateGroupConfig(PRHandle handle, PRDriverGroupConfig *driverGroupConfig); 485 | 486 | PINPROC_API PRResult PRDriverGetState(PRHandle handle, uint8_t driverNum, PRDriverState *driverState); 487 | /** 488 | * @brief Sets the state of the given driver (lamp or coil). 489 | */ 490 | PINPROC_API PRResult PRDriverUpdateState(PRHandle handle, PRDriverState *driverState); 491 | /** 492 | * @brief Loads the driver defaults for the given machine type. 493 | * 494 | * PRReset() calls this function internally; this function is useful for basing custom driver settings off of the defaults for a particular machine. 495 | * @note This function does not update the P-ROC hardware, only the internal data structures. Use PRDriverGetGlobalConfig() and PRDriverGetGroupConfig() to retrieve the settings. 496 | */ 497 | PINPROC_API PRResult PRDriverLoadMachineTypeDefaults(PRHandle handle, PRMachineType machineType); 498 | 499 | // Driver Group Helper functions: 500 | 501 | /** 502 | * Disables (turns off) the given driver group. 503 | * This function is provided for convenience. See PRDriverGroupDisable() for a full description. 504 | */ 505 | PINPROC_API PRResult PRDriverGroupDisable(PRHandle handle, uint8_t groupNum); 506 | // Driver Helper functions: 507 | 508 | /** 509 | * Disables (turns off) the given driver. 510 | * This function is provided for convenience. See PRDriverStateDisable() for a full description. 511 | */ 512 | PINPROC_API PRResult PRDriverDisable(PRHandle handle, uint8_t driverNum); 513 | /** 514 | * Pulses the given driver for a number of milliseconds. 515 | * This function is provided for convenience. See PRDriverStatePulse() for a full description. 516 | */ 517 | PINPROC_API PRResult PRDriverPulse(PRHandle handle, uint8_t driverNum, uint8_t milliseconds); 518 | /** 519 | * Pulses the given driver for a number of milliseconds when the hardware reaches a specific timestamp. 520 | * This function is provided for convenience. See PRDriverStatePulse() for a full description. 521 | */ 522 | PINPROC_API PRResult PRDriverFuturePulse(PRHandle handle, uint8_t driverNum, uint8_t milliseconds, uint32_t futureTime); 523 | /** 524 | * Assigns a repeating schedule to the given driver. 525 | * This function is provided for convenience. See PRDriverStateSchedule() for a full description. 526 | */ 527 | PINPROC_API PRResult PRDriverSchedule(PRHandle handle, uint8_t driverNum, uint32_t schedule, uint8_t cycleSeconds, bool_t now); 528 | /** 529 | * Assigns a pitter-patter schedule (repeating on/off) to the given driver. 530 | * This function is provided for convenience. See PRDriverStatePatter() for a full description. 531 | */ 532 | PINPROC_API PRResult PRDriverPatter(PRHandle handle, uint8_t driverNum, uint8_t millisecondsOn, uint8_t millisecondsOff, uint8_t originalOnTime, bool_t now); 533 | /** 534 | * Assigns a pitter-patter schedule (repeating on/off) to the given driver on for the given duration. 535 | * This function is provided for convenience. See PRDriverStatePulsedPatter() for a full description. 536 | */ 537 | PINPROC_API PRResult PRDriverPulsedPatter(PRHandle handle, uint8_t driverNum, uint8_t millisecondsOn, uint8_t millisecondsOff, uint8_t originalOnTime, bool_t now); 538 | /** 539 | * Prepares an Aux Command to drive the Aux bus. 540 | * This function is provided for convenience. 541 | */ 542 | PINPROC_API void PRDriverAuxPrepareOutput(PRDriverAuxCommand *auxCommand, uint8_t data, uint8_t extraData, uint8_t enables, bool_t muxEnables, uint16_t delayTime); 543 | /** 544 | * Prepares an Aux Command to delay the Aux logic. 545 | * This function is provided for convenience. 546 | */ 547 | PINPROC_API void PRDriverAuxPrepareDelay(PRDriverAuxCommand *auxCommand, uint16_t delayTime); 548 | /** 549 | * Prepares an Aux Command to have the Aux memory pointer jump to a new address. 550 | * This function is provided for convenience. 551 | */ 552 | PINPROC_API void PRDriverAuxPrepareJump(PRDriverAuxCommand *auxCommand, uint8_t jumpAddr); 553 | /** 554 | * Prepares a disabled Aux Command. 555 | * This function is provided for convenience. 556 | */ 557 | PINPROC_API void PRDriverAuxPrepareDisable(PRDriverAuxCommand *auxCommand); 558 | 559 | /** Tickle the watchdog timer. */ 560 | PINPROC_API PRResult PRDriverWatchdogTickle(PRHandle handle); 561 | 562 | /** 563 | * Changes the given #PRDriverGroupConfig to reflect a disabled group. 564 | * @note The driver group config structure must be applied using PRDriverUpdateGroupConfig() to have any effect. 565 | */ 566 | PINPROC_API void PRDriverGroupStateDisable(PRDriverGroupConfig *driverGroup); 567 | /** 568 | * Changes the given #PRDriverState to reflect a disabled state. 569 | * @note The driver state structure must be applied using PRDriverUpdateState() or linked to a switch rule using PRSwitchUpdateRule() to have any effect. 570 | */ 571 | PINPROC_API void PRDriverStateDisable(PRDriverState *driverState); 572 | /** 573 | * Changes the given #PRDriverState to reflect a pulse state. 574 | * @param milliseconds Number of milliseconds to pulse the driver for. 575 | * @note The driver state structure must be applied using PRDriverUpdateState() or linked to a switch rule using PRSwitchUpdateRule() to have any effect. 576 | */ 577 | PINPROC_API void PRDriverStatePulse(PRDriverState *driverState, uint8_t milliseconds); 578 | /** 579 | * Changes the given #PRDriverState to reflect a future scheduled pulse state. 580 | * @param milliseconds Number of milliseconds to pulse the driver for. 581 | * @param futureTime Value indicating at which HW timestamp the pulse should occur. Currently only the low 10-bits are used. 582 | * @note The driver state structure must be applied using PRDriverUpdateState() or linked to a switch rule using PRSwitchUpdateRule() to have any effect. 583 | */ 584 | PINPROC_API void PRDriverStateFuturePulse(PRDriverState *driverState, uint8_t milliseconds, uint32_t futureTime); 585 | /** 586 | * Changes the given #PRDriverState to reflect a scheduled state. 587 | * Assigns a repeating schedule to the given driver. 588 | * @note The driver state structure must be applied using PRDriverUpdateState() or linked to a switch rule using PRSwitchUpdateRule() to have any effect. 589 | */ 590 | PINPROC_API void PRDriverStateSchedule(PRDriverState *driverState, uint32_t schedule, uint8_t cycleSeconds, bool_t now); 591 | /** 592 | * @brief Changes the given #PRDriverState to reflect a pitter-patter schedule state. 593 | * Assigns a pitter-patter schedule (repeating on/off) to the given driver. 594 | * @note The driver state structure must be applied using PRDriverUpdateState() or linked to a switch rule using PRSwitchUpdateRule() to have any effect. 595 | * 596 | * Use originalOnTime to pulse the driver for a number of milliseconds before the pitter-patter schedule begins. 597 | */ 598 | PINPROC_API void PRDriverStatePatter(PRDriverState *driverState, uint8_t millisecondsOn, uint8_t millisecondsOff, uint8_t originalOnTime, bool_t now); 599 | 600 | /** 601 | * @brief Changes the given #PRDriverState to reflect a pitter-patter schedule state. 602 | * Just like the regular Patter above, but PulsePatter only drives the patter 603 | * scheduled for the given number of milliseconds before disabling the driver. 604 | */ 605 | PINPROC_API void PRDriverStatePulsedPatter(PRDriverState *driverState, uint8_t millisecondsOn, uint8_t millisecondsOff, uint8_t patterTime, bool_t now); 606 | 607 | /** 608 | * Write Aux Port commands into the Aux Port command memory. 609 | */ 610 | 611 | PINPROC_API PRResult PRDriverAuxSendCommands(PRHandle handle, PRDriverAuxCommand * commands, uint8_t numCommands, uint8_t startingAddr); 612 | 613 | /** 614 | * @brief Converts a coil, lamp, switch, or GI string into a P-ROC driver number. 615 | * The following formats are accepted: Cxx (coil), Lxx (lamp), Sxx (matrix switch), SFx (flipper grounded switch), or SDx (dedicated grounded switch). 616 | * If the string does not match this format it will be converted into an integer using atoi(). 617 | */ 618 | PINPROC_API uint16_t PRDecode(PRMachineType machineType, const char *str); 619 | 620 | /** @} */ // End of Drivers 621 | 622 | // Switches 623 | 624 | /** @defgroup switches Switches and Events 625 | * @{ 626 | */ 627 | 628 | // Events 629 | // Closed == 0, Open == 1 630 | typedef enum PREventType { 631 | kPREventTypeInvalid = 0, 632 | kPREventTypeSwitchClosedDebounced = 1, /**< The switch has gone from open to closed and the signal has been debounced. */ 633 | kPREventTypeSwitchOpenDebounced = 2, /**< The switch has gone from closed to open and the signal has been debounced. */ 634 | kPREventTypeSwitchClosedNondebounced = 3, /**< The switch has gone from open to closed and the signal has not been debounced. */ 635 | kPREventTypeSwitchOpenNondebounced = 4, /**< The switch has gone from closed to open and the signal has not been debounced. */ 636 | kPREventTypeDMDFrameDisplayed = 5, /**< A DMD frame has been displayed. */ 637 | kPREventTypeBurstSwitchOpen = 6, /**< A burst switch has gone from closed to open. */ 638 | kPREventTypeBurstSwitchClosed = 7, /**< A burst switch has gone from open to closed. */ 639 | kPREventTypeAccelerometerX = 8, /**< New value from the accelerometer - X plane. */ 640 | kPREventTypeAccelerometerY = 9, /**< New value from the accelerometer - Y plane. */ 641 | kPREventTypeAccelerometerZ = 10, /**< New value from the accelerometer - Z plane. */ 642 | kPREventTypeAccelerometerIRQ = 11, /**< New interrupt from the accelerometer */ 643 | kPREventTypetLast = kPREventTypeSwitchOpenNondebounced 644 | } PREventType; 645 | 646 | typedef struct PREvent { 647 | PREventType type; /**< The type of event that has occurred. Usually a switch event at this point. */ 648 | uint32_t value; /**< For switch events, the switch number that has changed. For DMD events, the frame buffer that was just displayed. */ 649 | uint32_t time; /**< Time (in milliseconds) that this event occurred. */ 650 | } PREvent; 651 | 652 | /** Get all of the available events that have been received. 653 | * \return Number of events returned; -1 if an error occurred. 654 | */ 655 | PINPROC_API int PRGetEvents(PRHandle handle, PREvent *eventsOut, int maxEvents); 656 | 657 | 658 | #define kPRSwitchPhysicalFirst (0) /**< Switch number of the first physical switch. */ 659 | #define kPRSwitchPhysicalLast (255) /**< Switch number of the last physical switch. */ 660 | #define kPRSwitchNeverDebounceFirst (192) /**< Switch number of the first switch that doesn't need to debounced. */ 661 | #define kPRSwitchNeverDebounceLast (255) /**< Switch number of the last switch that doesn't need to be debounce. */ 662 | #define kPRSwitchCount (256) 663 | #define kPRSwitchRulesCount (kPRSwitchCount << 2) /**< Total number of available switch rules. */ 664 | 665 | typedef struct PRSwitchConfig { 666 | bool_t clear; // Drive the clear output 667 | bool_t hostEventsEnable; // Drive the clear output 668 | bool_t use_column_9; // Use switch matrix column 9 669 | bool_t use_column_8; // Use switch matrix column 8 670 | uint8_t directMatrixScanLoopTime; // milliseconds 671 | uint8_t pulsesBeforeCheckingRX; 672 | uint8_t inactivePulsesAfterBurst; 673 | uint8_t pulsesPerBurst; 674 | uint8_t pulseHalfPeriodTime; // milliseconds 675 | } PRSwitchConfig; 676 | 677 | typedef struct PRSwitchRule { 678 | bool_t reloadActive; /**< If true, any associated driver changes resulting from this rule will only happen at most once every 256ms. */ 679 | bool_t notifyHost; /**< If true this switch change event will provided to the user via PRGetEvents(). */ 680 | } PRSwitchRule; 681 | 682 | /** Update the switch controller configurion registers */ 683 | PINPROC_API PRResult PRSwitchUpdateConfig(PRHandle handle, PRSwitchConfig *switchConfig); 684 | 685 | /** 686 | * @brief Configures the handling of switch rules within P-ROC. 687 | * 688 | * P-ROC's switch rule system allows the user to decide which switch events are returned to software, 689 | * as well as optionally linking one or more driver state changes to rules to create immediate feedback (such as in pop bumpers). 690 | * 691 | * For instance, P-ROC can provide debounced switch events for a flipper button so software can apply lange change behavior. 692 | * This is accomplished by configuring the P-ROC with a switch rule for the flipper button and then receiving the events via the PRGetEvents() call. 693 | * The same switch can also be configured with a non-debounced rule to fire a flipper coil. 694 | * Multiple driver changes can be tied to a single switch state transition to create more complicated effects: a slingshot 695 | * switch that fires the slingshot coil, a flash lamp, and a score event. 696 | * 697 | * P-ROC holds four different switch rules for each switch: closed to open and open to closed, each with a debounced and non-debounced versions: 698 | * - #kPREventTypeSwitchOpenDebounced 699 | * - #kPREventTypeSwitchClosedDebounced 700 | * - #kPREventTypeSwitchOpenNondebounced 701 | * - #kPREventTypeSwitchClosedNondebounced 702 | * 703 | * @section Examples 704 | * 705 | * Configuring a basic switch rule to simply notify software via PRGetEvents() without affecting any coil/lamp drivers: 706 | * @code 707 | * PRSwitchRule rule; 708 | * rule.notifyHost = true; 709 | * PRSwitchUpdateRule(handle, switchNum, kPREventTypeSwitchOpenDebounced, &rule, NULL, 0); 710 | * @endcode 711 | * 712 | * Configuring a pop bumper switch to pulse the coil and a flash lamp for 50ms each: 713 | * @code 714 | * // Configure a switch rule to fire the coil and flash lamp: 715 | * PRSwitchRule rule; 716 | * rule.notifyHost = false; 717 | * PRDriverState drivers[2]; 718 | * PRDriverGetState(handle, drvCoilPopBumper1, &drivers[0]); 719 | * PRDriverGetState(handle, drvFlashLamp1, &drivers[1]); 720 | * PRDriverStatePulse(&drivers[0], 50); 721 | * PRDriverStatePulse(&drivers[1], 50); 722 | * PRSwitchUpdateRule(handle, swPopBumper1, kPREventTypeSwitchClosedNondebounced, 723 | * &rule, drivers, 2); 724 | * // Now configure a switch rule to process scoring in software: 725 | * rule.notifyHost = true; 726 | * PRSwitchUpdateRule(handle, swPopBumper1, kPREventTypeSwitchClosedDebounced, 727 | * &rule, NULL, 0); 728 | * @endcode 729 | * 730 | * @param handle The P-ROC device handle. 731 | * @param switchNum The index of the switch this configuration affects. 732 | * @param eventType The switch rule for the specified switchNum to be configured. 733 | * @param rule A pointer to the #PRSwitchRule structure describing how this state change should be handled. May not be NULL. 734 | * @param linkedDrivers An array of #PRDriverState structures describing the driver state changes to be made when this switch rule is triggered. May be NULL if numDrivers is 0. 735 | * @param numDrivers Number of elements in the linkedDrivers array. May be zero or more. 736 | */ 737 | PINPROC_API PRResult PRSwitchUpdateRule(PRHandle handle, uint8_t switchNum, PREventType eventType, PRSwitchRule *rule, PRDriverState *linkedDrivers, int numDrivers, bool_t drive_outputs_now); 738 | 739 | /** Returns a list of PREventTypes describing the states of the requested number of switches */ 740 | PINPROC_API PRResult PRSwitchGetStates(PRHandle handle, PREventType * switchStates, uint16_t numSwitches); 741 | 742 | /** @} */ // End of Switches & Events 743 | 744 | // DMD 745 | 746 | /** 747 | * @defgroup dmd DMD Control 748 | * @{ 749 | */ 750 | typedef struct PRDMDConfig { 751 | uint8_t numRows; 752 | uint16_t numColumns; 753 | uint8_t numSubFrames; 754 | uint8_t numFrameBuffers; 755 | bool_t autoIncBufferWrPtr; 756 | bool_t enableFrameEvents; 757 | bool_t enable; 758 | uint8_t rclkLowCycles[8]; 759 | uint8_t latchHighCycles[8]; 760 | uint16_t deHighCycles[8]; 761 | uint8_t dotclkHalfPeriod[8]; 762 | } PRDMDConfig; 763 | 764 | /** Sets the configuration registers for the DMD driver. */ 765 | PINPROC_API int32_t PRDMDUpdateConfig(PRHandle handle, PRDMDConfig *dmdConfig); 766 | /** Updates the DMD frame buffer with the given data. */ 767 | PINPROC_API PRResult PRDMDDraw(PRHandle handle, uint8_t * dots); 768 | 769 | /** @} */ // End of DMD 770 | 771 | 772 | // JTAG 773 | 774 | /** 775 | * @defgroup jtag JTAG interface control 776 | * @{ 777 | */ 778 | 779 | typedef struct PRJTAGStatus { 780 | bool_t commandComplete; 781 | bool_t tdi; 782 | } PRJTAGStatus; 783 | 784 | typedef struct PRJTAGOutputs { 785 | bool_t tckMask; 786 | bool_t tmsMask; 787 | bool_t tdoMask; 788 | bool_t tck; 789 | bool_t tms; 790 | bool_t tdo; 791 | } PRJTAGOutputs; 792 | 793 | /** Force JTAG outputs (TCK, TDO, TMS) to specific values. Optionally toggle the clock when driving only TDO and/or TMS.*/ 794 | PINPROC_API PRResult PRJTAGDriveOutputs(PRHandle handle, PRJTAGOutputs * jtagOutputs, bool_t toggleClk); 795 | /** Store data to be shifted out on TDO */ 796 | PINPROC_API PRResult PRJTAGWriteTDOMemory(PRHandle handle, uint16_t tableOffset, uint16_t numWords, uint32_t * tdoData); 797 | /** Shift stored TDO data onto the TDO pin, toggling TCK on every bit. */ 798 | PINPROC_API PRResult PRJTAGShiftTDOData(PRHandle handle, uint16_t numBits, bool_t dataBlockComplete); 799 | /** Get the contents of the TDI memory. */ 800 | PINPROC_API PRResult PRJTAGReadTDIMemory(PRHandle handle, uint16_t tableOffset, uint16_t numWords, uint32_t * tdiData); 801 | /** Read the JTAG status register for the command complete bit and JTAG pin states. */ 802 | PINPROC_API PRResult PRJTAGGetStatus(PRHandle handle, PRJTAGStatus * status); 803 | 804 | /** @} */ // End of JTAG 805 | 806 | // PD-LED 807 | 808 | /** 809 | * @defgroup pdled PD-LED Control 810 | * @{ 811 | */ 812 | 813 | 814 | typedef struct PRLED { 815 | uint8_t boardAddr; 816 | uint8_t LEDIndex; 817 | } PRLED; 818 | 819 | typedef struct PRLEDRGB { 820 | PRLED* pRedLED; 821 | PRLED* pGreenLED; 822 | PRLED* pBlueLED; 823 | } PRLEDRGB; 824 | 825 | /** Sets the color of a given PRLED. */ 826 | PINPROC_API PRResult PRLEDColor(PRHandle handle, PRLED * pLED, uint8_t color); 827 | /** Sets the fade color on a given PRLED. */ 828 | PINPROC_API PRResult PRLEDFadeColor(PRHandle handle, PRLED * pLED, uint8_t fadeColor); 829 | /** Sets the fade color and rate on a given PRLED. Note: The rate will apply to any future PRLEDFadeColor or PRLEDRGBFadeColor calls on the same PD-LED board. */ 830 | PINPROC_API PRResult PRLEDFade(PRHandle handle, PRLED * pLED, uint8_t fadeColor, uint16_t fadeRate); 831 | 832 | /** Sets the fade rate on a given board. Note: The rate will apply to any future PRLEDFadeColor or PRLEDRGBFadeColor calls on the same PD-LED board. */ 833 | PINPROC_API PRResult PRLEDFadeRate(PRHandle handle, uint8_t boardAddr, uint16_t fadeRate); 834 | 835 | /** Sets the color of a given PRLEDRGB. */ 836 | PINPROC_API PRResult PRLEDRGBColor(PRHandle handle, PRLEDRGB * pLED, uint32_t color); 837 | /** Sets the fade color and rate on a given PRLEDRGB. Note: The rate will apply to any future PRLEDFadeColor or PRLEDRGBFadeColor calls on any of the referenced PD-LED boards. */ 838 | PINPROC_API PRResult PRLEDRGBFade(PRHandle handle, PRLEDRGB * pLED, uint32_t fadeColor, uint16_t fadeRate); 839 | /** Sets the fade color on a given PRLEDRGB. */ 840 | PINPROC_API PRResult PRLEDRGBFadeColor(PRHandle handle, PRLEDRGB * pLED, uint32_t fadeColor); 841 | 842 | 843 | /** @} */ // End of PD-LED 844 | 845 | 846 | /** @cond */ 847 | PINPROC_EXTERN_C_END 848 | /** @endcond */ 849 | 850 | /** 851 | * @mainpage libpinproc API Documentation 852 | * 853 | * This is the documentation for libpinproc, the P-ROC Layer 1 API. 854 | */ 855 | 856 | #endif /* PINPROC_PINPROC_H */ 857 | -------------------------------------------------------------------------------- /installers/Win/DPInst32.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/preble/libpinproc/286c56694dae9f068e6ba14f8f625026f15e54c7/installers/Win/DPInst32.exe -------------------------------------------------------------------------------- /installers/Win/DPInst64.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/preble/libpinproc/286c56694dae9f068e6ba14f8f625026f15e54c7/installers/Win/DPInst64.exe -------------------------------------------------------------------------------- /installers/Win/README.txt: -------------------------------------------------------------------------------- 1 | libpinproc installation notes: 2 | 3 | The install process should have created the following subdirectories: 4 | .\FTDI_2.xx.yy (includes the USB driver) 5 | .\bin (includes pinprocfw.exe) 6 | .\ext\python (includes a setup file for the pinproc python extension) 7 | 8 | *** USB Driver *** 9 | The FTDI driver should have been installed automatically during the libpinproc installation. If it did not, manually run .\FTDI_2.xx.yy\DPInst.exe. This is necessary to communicate with the P-ROC over USB. 10 | 11 | *** pinprocfw.exe *** 12 | This application can be used to update the P-ROC's firmware when updates are made 13 | available on www.pinballcontrollers.com as follows: 14 | .\bin\pinprocfw.exe 15 | 16 | *** pinproc python extension *** 17 | If you're planning on writing or using Python scripts to communicate with your P-ROC, and 18 | you already have Python 2.6 installed, execute this setup file to install the pinproc python 19 | extension. Note - this extension has only been tested with Python 2.6. 20 | -------------------------------------------------------------------------------- /installers/Win/nsis_install_script.nsi: -------------------------------------------------------------------------------- 1 | ; Script generated by the HM NIS Edit Script Wizard. 2 | 3 | ; HM NIS Edit Wizard helper defines 4 | !define PRODUCT_NAME "libpinproc" 5 | !define PRODUCT_VERSION "2.0" 6 | !define PRODUCT_PUBLISHER "Gerry Stellenberg" 7 | !define PRODUCT_WEB_SITE "http://www.pinballcontrollers.com" 8 | !define PRODUCT_DIR_REGKEY "Software\Microsoft\Windows\CurrentVersion\App Paths\DPInst.exe" 9 | !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" 10 | !define PRODUCT_UNINST_ROOT_KEY "HKLM" 11 | 12 | ; MUI 1.67 compatible ------ 13 | !include "MUI.nsh" 14 | 15 | ; MUI Settings 16 | !define MUI_ABORTWARNING 17 | !define MUI_ICON "${NSISDIR}\Contrib\Graphics\Icons\modern-install.ico" 18 | !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" 19 | 20 | ; Welcome page 21 | !insertmacro MUI_PAGE_WELCOME 22 | ; Directory page 23 | !insertmacro MUI_PAGE_DIRECTORY 24 | ; Instfiles page 25 | !insertmacro MUI_PAGE_INSTFILES 26 | ; Finish page 27 | !insertmacro MUI_PAGE_FINISH 28 | 29 | ; Uninstaller pages 30 | !insertmacro MUI_UNPAGE_INSTFILES 31 | 32 | ; Language files 33 | !insertmacro MUI_LANGUAGE "English" 34 | 35 | ; MUI end ------ 36 | 37 | Name "${PRODUCT_NAME} ${PRODUCT_VERSION}" 38 | OutFile "libpinproc_2.0_install.exe" 39 | InstallDir "$PROGRAMFILES\P-ROC\libpinproc" 40 | ShowInstDetails show 41 | ShowUnInstDetails show 42 | 43 | Function InstallFTDI 44 | 45 | IfFileExists $WINDIR\SYSWOW64\*.* Is64bit Is32bit 46 | Is32bit: 47 | CopyFiles "$INSTDIR\FTDI_2.08.14\DPInst32.exe" "$INSTDIR\FTDI_2.08.14\DPInst.exe" 48 | GOTO End32Bitvs64BitCheck 49 | 50 | Is64bit: 51 | CopyFiles "$INSTDIR\FTDI_2.08.14\DPInst64.exe" "$INSTDIR\FTDI_2.08.14\DPInst.exe" 52 | End32Bitvs64BitCheck: 53 | 54 | ExecWait '"$INSTDIR\FTDI_2.08.14\DPInst.exe"' 55 | 56 | FunctionEnd 57 | 58 | Section "MainSection" SEC01 59 | SetOutPath "$INSTDIR\FTDI_2.08.14\amd64" 60 | SetOverwrite try 61 | File "C:\P-ROC\Install\FTDI_2.08.14\amd64\ftbusui.dll" 62 | File "C:\P-ROC\Install\FTDI_2.08.14\amd64\ftcserco.dll" 63 | File "C:\P-ROC\Install\FTDI_2.08.14\amd64\ftd2xx.lib" 64 | File "C:\P-ROC\Install\FTDI_2.08.14\amd64\ftd2xx64.dll" 65 | File "C:\P-ROC\Install\FTDI_2.08.14\amd64\ftdibus.sys" 66 | File "C:\P-ROC\Install\FTDI_2.08.14\amd64\ftlang.dll" 67 | File "C:\P-ROC\Install\FTDI_2.08.14\amd64\ftser2k.sys" 68 | File "C:\P-ROC\Install\FTDI_2.08.14\amd64\ftserui2.dll" 69 | SetOutPath "$INSTDIR\FTDI_2.08.14" 70 | File "C:\P-ROC\Install\FTDI_2.08.14\DPInst32.exe" 71 | File "C:\P-ROC\Install\FTDI_2.08.14\DPInst64.exe" 72 | File "C:\P-ROC\Install\FTDI_2.08.14\DPInst.xml" 73 | File "C:\P-ROC\Install\FTDI_2.08.14\ftd2xx.h" 74 | File "C:\P-ROC\Install\FTDI_2.08.14\ftdibus.cat" 75 | File "C:\P-ROC\Install\FTDI_2.08.14\ftdibus.inf" 76 | File "C:\P-ROC\Install\FTDI_2.08.14\ftdiport.cat" 77 | File "C:\P-ROC\Install\FTDI_2.08.14\ftdiport.inf" 78 | SetOutPath "$INSTDIR\FTDI_2.08.14\i386" 79 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftbusui.dll" 80 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftcserco.dll" 81 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftd2xx.dll" 82 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftd2xx.lib" 83 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftdibus.sys" 84 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftlang.dll" 85 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftser2k.sys" 86 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftserui2.dll" 87 | SetOutPath "$INSTDIR\bin" 88 | SetOverwrite ifnewer 89 | File "C:\P-ROC\libpinproc\bin\pinprocfw.exe" 90 | File "C:\P-ROC\Install\FTDI_2.08.14\i386\ftd2xx.dll" 91 | File "C:\MinGW\bin\libgcc_s_dw2-1.dll" 92 | File "C:\MinGW\bin\libstdc++-6.dll" 93 | SetOutPath "$INSTDIR\ext\python" 94 | SetOverwrite ifnewer 95 | File "C:\P-ROC\pypinproc\dist\pinproc-1.2.win32-py2.6.exe" 96 | SetOutPath "$INSTDIR" 97 | SetOverwrite ifnewer 98 | File "C:\P-ROC\libpinproc\installers\Win\README.txt" 99 | Call InstallFTDI 100 | SectionEnd 101 | 102 | Section -Post 103 | WriteUninstaller "$INSTDIR\uninst.exe" 104 | WriteRegStr HKLM "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\FTDI_2.08.14\DPInst.exe" 105 | WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" 106 | WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" 107 | WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\FTDI_2.08.14\DPInst.exe" 108 | WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}" 109 | WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" 110 | WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" 111 | SectionEnd 112 | 113 | 114 | Function un.onUninstSuccess 115 | HideWindow 116 | MessageBox MB_ICONINFORMATION|MB_OK "$(^Name) was successfully removed from your computer." 117 | FunctionEnd 118 | 119 | Function un.onInit 120 | MessageBox MB_ICONQUESTION|MB_YESNO|MB_DEFBUTTON2 "Are you sure you want to completely remove $(^Name) and all of its components?" IDYES +2 121 | Abort 122 | FunctionEnd 123 | 124 | Section Uninstall 125 | Delete "$INSTDIR\uninst.exe" 126 | Delete "$INSTDIR\bin\ftd2xx.dll" 127 | Delete "$INSTDIR\bin\pinprocfw.exe" 128 | Delete "$INSTDIR\FTDI_2.08.14\i386\ftserui2.dll" 129 | Delete "$INSTDIR\FTDI_2.08.14\i386\ftser2k.sys" 130 | Delete "$INSTDIR\FTDI_2.08.14\i386\ftlang.dll" 131 | Delete "$INSTDIR\FTDI_2.08.14\i386\ftdibus.sys" 132 | Delete "$INSTDIR\FTDI_2.08.14\i386\ftd2xx.lib" 133 | Delete "$INSTDIR\FTDI_2.08.14\i386\ftd2xx.dll" 134 | Delete "$INSTDIR\FTDI_2.08.14\i386\ftcserco.dll" 135 | Delete "$INSTDIR\FTDI_2.08.14\i386\ftbusui.dll" 136 | Delete "$INSTDIR\FTDI_2.08.14\ftdiport.inf" 137 | Delete "$INSTDIR\FTDI_2.08.14\ftdiport.cat" 138 | Delete "$INSTDIR\FTDI_2.08.14\ftdibus.inf" 139 | Delete "$INSTDIR\FTDI_2.08.14\ftdibus.cat" 140 | Delete "$INSTDIR\FTDI_2.08.14\ftd2xx.h" 141 | Delete "$INSTDIR\FTDI_2.08.14\DPInst.xml" 142 | Delete "$INSTDIR\FTDI_2.08.14\DPInst.exe" 143 | Delete "$INSTDIR\FTDI_2.08.14\DPInst32.exe" 144 | Delete "$INSTDIR\FTDI_2.08.14\DPInst64.exe" 145 | Delete "$INSTDIR\FTDI_2.08.14\CDM 2 04 16 Release Info.doc" 146 | Delete "$INSTDIR\FTDI_2.08.14\amd64\ftserui2.dll" 147 | Delete "$INSTDIR\FTDI_2.08.14\amd64\ftser2k.sys" 148 | Delete "$INSTDIR\FTDI_2.08.14\amd64\ftlang.dll" 149 | Delete "$INSTDIR\FTDI_2.08.14\amd64\ftdibus.sys" 150 | Delete "$INSTDIR\FTDI_2.08.14\amd64\ftd2xx64.dll" 151 | Delete "$INSTDIR\FTDI_2.08.14\amd64\ftd2xx.lib" 152 | Delete "$INSTDIR\FTDI_2.08.14\amd64\ftcserco.dll" 153 | Delete "$INSTDIR\FTDI_2.08.14\amd64\ftbusui.dll" 154 | 155 | RMDir "$INSTDIR\FTDI_2.08.14\i386" 156 | RMDir "$INSTDIR\FTDI_2.08.14\amd64" 157 | RMDir "$INSTDIR\FTDI_2.08.14" 158 | RMDir "$INSTDIR\bin" 159 | 160 | DeleteRegKey ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" 161 | DeleteRegKey HKLM "${PRODUCT_DIR_REGKEY}" 162 | SetAutoClose true 163 | SectionEnd 164 | -------------------------------------------------------------------------------- /libpinproc.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 45; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 66640E5E0FD1CFB6003135D8 /* dmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 66640E5B0FD1CFB6003135D8 /* dmd.cpp */; }; 11 | 66640E5F0FD1CFB6003135D8 /* drivers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 66640E5C0FD1CFB6003135D8 /* drivers.cpp */; }; 12 | 66640E600FD1CFB6003135D8 /* switches.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 66640E5D0FD1CFB6003135D8 /* switches.cpp */; }; 13 | 6682492C0FC079050051560E /* pinproc.h in Headers */ = {isa = PBXBuildFile; fileRef = 6682492B0FC079050051560E /* pinproc.h */; }; 14 | 6682493A0FC07B2A0051560E /* pinproc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 668249390FC07B2A0051560E /* pinproc.cpp */; }; 15 | 668249420FC07D900051560E /* PRDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 668249400FC07D900051560E /* PRDevice.h */; }; 16 | 668249430FC07D900051560E /* PRDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 668249410FC07D900051560E /* PRDevice.cpp */; }; 17 | 6682494B0FC0870B0051560E /* PRHardware.h in Headers */ = {isa = PBXBuildFile; fileRef = 6682494A0FC0870B0051560E /* PRHardware.h */; }; 18 | 668249E30FC0A3960051560E /* pinproctest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 668249E20FC0A3960051560E /* pinproctest.cpp */; }; 19 | 668249EA0FC0A4280051560E /* libpinproc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libpinproc.a */; }; 20 | 668249ED0FC0A4CD0051560E /* PRHardware.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 668249EC0FC0A4CD0051560E /* PRHardware.cpp */; }; 21 | 66824E7B0FCCBAFF0051560E /* PRCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 66824E7A0FCCBAFF0051560E /* PRCommon.h */; }; 22 | 66C3CCBB111DDBA700FE329E /* lenval.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 66C3CCB7111DDBA700FE329E /* lenval.cpp */; }; 23 | 66C3CCBC111DDBA700FE329E /* pinprocfw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 66C3CCB9111DDBA700FE329E /* pinprocfw.cpp */; }; 24 | /* End PBXBuildFile section */ 25 | 26 | /* Begin PBXContainerItemProxy section */ 27 | 668249E40FC0A3C40051560E /* PBXContainerItemProxy */ = { 28 | isa = PBXContainerItemProxy; 29 | containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; 30 | proxyType = 1; 31 | remoteGlobalIDString = D2AAC045055464E500DB518D; 32 | remoteInfo = libpinproc; 33 | }; 34 | 66C3CCD8111DDD6F00FE329E /* PBXContainerItemProxy */ = { 35 | isa = PBXContainerItemProxy; 36 | containerPortal = 08FB7793FE84155DC02AAC07 /* Project object */; 37 | proxyType = 1; 38 | remoteGlobalIDString = D2AAC045055464E500DB518D /* libpinproc */; 39 | remoteInfo = libpinproc; 40 | }; 41 | /* End PBXContainerItemProxy section */ 42 | 43 | /* Begin PBXFileReference section */ 44 | 66640E5B0FD1CFB6003135D8 /* dmd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dmd.cpp; path = examples/pinproctest/dmd.cpp; sourceTree = ""; }; 45 | 66640E5C0FD1CFB6003135D8 /* drivers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = drivers.cpp; path = examples/pinproctest/drivers.cpp; sourceTree = ""; }; 46 | 66640E5D0FD1CFB6003135D8 /* switches.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = switches.cpp; path = examples/pinproctest/switches.cpp; sourceTree = ""; }; 47 | 66640E610FD1D010003135D8 /* pinproctest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pinproctest.h; path = examples/pinproctest/pinproctest.h; sourceTree = ""; }; 48 | 6682492B0FC079050051560E /* pinproc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pinproc.h; path = include/pinproc.h; sourceTree = ""; }; 49 | 668249390FC07B2A0051560E /* pinproc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pinproc.cpp; path = src/pinproc.cpp; sourceTree = ""; }; 50 | 668249400FC07D900051560E /* PRDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PRDevice.h; path = src/PRDevice.h; sourceTree = ""; }; 51 | 668249410FC07D900051560E /* PRDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PRDevice.cpp; path = src/PRDevice.cpp; sourceTree = ""; }; 52 | 6682494A0FC0870B0051560E /* PRHardware.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PRHardware.h; path = src/PRHardware.h; sourceTree = ""; }; 53 | 668249D90FC0A30A0051560E /* pinproctest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pinproctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 668249E20FC0A3960051560E /* pinproctest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pinproctest.cpp; path = examples/pinproctest/pinproctest.cpp; sourceTree = ""; }; 55 | 668249EC0FC0A4CD0051560E /* PRHardware.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PRHardware.cpp; path = src/PRHardware.cpp; sourceTree = ""; }; 56 | 66824E7A0FCCBAFF0051560E /* PRCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PRCommon.h; path = src/PRCommon.h; sourceTree = ""; }; 57 | 66C3CCB0111DDB8200FE329E /* pinprocfw */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pinprocfw; sourceTree = BUILT_PRODUCTS_DIR; }; 58 | 66C3CCB7111DDBA700FE329E /* lenval.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lenval.cpp; path = utils/pinprocfw/lenval.cpp; sourceTree = ""; }; 59 | 66C3CCB8111DDBA700FE329E /* lenval.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lenval.h; path = utils/pinprocfw/lenval.h; sourceTree = ""; }; 60 | 66C3CCB9111DDBA700FE329E /* pinprocfw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pinprocfw.cpp; path = utils/pinprocfw/pinprocfw.cpp; sourceTree = ""; }; 61 | 66C3CCBA111DDBA700FE329E /* pinprocfw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = pinprocfw.h; path = utils/pinprocfw/pinprocfw.h; sourceTree = ""; }; 62 | D2AAC046055464E500DB518D /* libpinproc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpinproc.a; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | /* End PBXFileReference section */ 64 | 65 | /* Begin PBXFrameworksBuildPhase section */ 66 | 668249D70FC0A30A0051560E /* Frameworks */ = { 67 | isa = PBXFrameworksBuildPhase; 68 | buildActionMask = 2147483647; 69 | files = ( 70 | 668249EA0FC0A4280051560E /* libpinproc.a in Frameworks */, 71 | ); 72 | runOnlyForDeploymentPostprocessing = 0; 73 | }; 74 | 66C3CCAE111DDB8200FE329E /* Frameworks */ = { 75 | isa = PBXFrameworksBuildPhase; 76 | buildActionMask = 2147483647; 77 | files = ( 78 | ); 79 | runOnlyForDeploymentPostprocessing = 0; 80 | }; 81 | D289987405E68DCB004EDB86 /* Frameworks */ = { 82 | isa = PBXFrameworksBuildPhase; 83 | buildActionMask = 2147483647; 84 | files = ( 85 | ); 86 | runOnlyForDeploymentPostprocessing = 0; 87 | }; 88 | /* End PBXFrameworksBuildPhase section */ 89 | 90 | /* Begin PBXGroup section */ 91 | 08FB7794FE84155DC02AAC07 /* libpinproc */ = { 92 | isa = PBXGroup; 93 | children = ( 94 | 08FB7795FE84155DC02AAC07 /* Source */, 95 | C6A0FF2B0290797F04C91782 /* Documentation */, 96 | 1AB674ADFE9D54B511CA2CBB /* Products */, 97 | ); 98 | name = libpinproc; 99 | sourceTree = ""; 100 | }; 101 | 08FB7795FE84155DC02AAC07 /* Source */ = { 102 | isa = PBXGroup; 103 | children = ( 104 | 66C3CCB5111DDB9000FE329E /* pinprocfw */, 105 | 668249D30FC0A2C10051560E /* pinproctest */, 106 | 668249D20FC0A29E0051560E /* libpinproc */, 107 | ); 108 | name = Source; 109 | sourceTree = ""; 110 | }; 111 | 1AB674ADFE9D54B511CA2CBB /* Products */ = { 112 | isa = PBXGroup; 113 | children = ( 114 | D2AAC046055464E500DB518D /* libpinproc.a */, 115 | 668249D90FC0A30A0051560E /* pinproctest */, 116 | 66C3CCB0111DDB8200FE329E /* pinprocfw */, 117 | ); 118 | name = Products; 119 | sourceTree = ""; 120 | }; 121 | 668249D20FC0A29E0051560E /* libpinproc */ = { 122 | isa = PBXGroup; 123 | children = ( 124 | 6682492B0FC079050051560E /* pinproc.h */, 125 | 668249390FC07B2A0051560E /* pinproc.cpp */, 126 | 668249400FC07D900051560E /* PRDevice.h */, 127 | 668249410FC07D900051560E /* PRDevice.cpp */, 128 | 6682494A0FC0870B0051560E /* PRHardware.h */, 129 | 668249EC0FC0A4CD0051560E /* PRHardware.cpp */, 130 | 66824E7A0FCCBAFF0051560E /* PRCommon.h */, 131 | ); 132 | name = libpinproc; 133 | sourceTree = ""; 134 | }; 135 | 668249D30FC0A2C10051560E /* pinproctest */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 66640E610FD1D010003135D8 /* pinproctest.h */, 139 | 668249E20FC0A3960051560E /* pinproctest.cpp */, 140 | 66640E5B0FD1CFB6003135D8 /* dmd.cpp */, 141 | 66640E5C0FD1CFB6003135D8 /* drivers.cpp */, 142 | 66640E5D0FD1CFB6003135D8 /* switches.cpp */, 143 | ); 144 | name = pinproctest; 145 | sourceTree = ""; 146 | }; 147 | 66C3CCB5111DDB9000FE329E /* pinprocfw */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 66C3CCB7111DDBA700FE329E /* lenval.cpp */, 151 | 66C3CCB8111DDBA700FE329E /* lenval.h */, 152 | 66C3CCB9111DDBA700FE329E /* pinprocfw.cpp */, 153 | 66C3CCBA111DDBA700FE329E /* pinprocfw.h */, 154 | ); 155 | name = pinprocfw; 156 | sourceTree = ""; 157 | }; 158 | C6A0FF2B0290797F04C91782 /* Documentation */ = { 159 | isa = PBXGroup; 160 | children = ( 161 | ); 162 | name = Documentation; 163 | sourceTree = ""; 164 | }; 165 | /* End PBXGroup section */ 166 | 167 | /* Begin PBXHeadersBuildPhase section */ 168 | D2AAC043055464E500DB518D /* Headers */ = { 169 | isa = PBXHeadersBuildPhase; 170 | buildActionMask = 2147483647; 171 | files = ( 172 | 6682492C0FC079050051560E /* pinproc.h in Headers */, 173 | 668249420FC07D900051560E /* PRDevice.h in Headers */, 174 | 6682494B0FC0870B0051560E /* PRHardware.h in Headers */, 175 | 66824E7B0FCCBAFF0051560E /* PRCommon.h in Headers */, 176 | ); 177 | runOnlyForDeploymentPostprocessing = 0; 178 | }; 179 | /* End PBXHeadersBuildPhase section */ 180 | 181 | /* Begin PBXNativeTarget section */ 182 | 668249D80FC0A30A0051560E /* pinproctest */ = { 183 | isa = PBXNativeTarget; 184 | buildConfigurationList = 668249DD0FC0A32A0051560E /* Build configuration list for PBXNativeTarget "pinproctest" */; 185 | buildPhases = ( 186 | 668249D60FC0A30A0051560E /* Sources */, 187 | 668249D70FC0A30A0051560E /* Frameworks */, 188 | ); 189 | buildRules = ( 190 | ); 191 | dependencies = ( 192 | 668249E50FC0A3C40051560E /* PBXTargetDependency */, 193 | ); 194 | name = pinproctest; 195 | productName = pinproctest; 196 | productReference = 668249D90FC0A30A0051560E /* pinproctest */; 197 | productType = "com.apple.product-type.tool"; 198 | }; 199 | 66C3CCAF111DDB8200FE329E /* pinprocfw */ = { 200 | isa = PBXNativeTarget; 201 | buildConfigurationList = 66C3CCB6111DDB9000FE329E /* Build configuration list for PBXNativeTarget "pinprocfw" */; 202 | buildPhases = ( 203 | 66C3CCAD111DDB8200FE329E /* Sources */, 204 | 66C3CCAE111DDB8200FE329E /* Frameworks */, 205 | ); 206 | buildRules = ( 207 | ); 208 | dependencies = ( 209 | 66C3CCD9111DDD6F00FE329E /* PBXTargetDependency */, 210 | ); 211 | name = pinprocfw; 212 | productName = pinprocfw; 213 | productReference = 66C3CCB0111DDB8200FE329E /* pinprocfw */; 214 | productType = "com.apple.product-type.tool"; 215 | }; 216 | D2AAC045055464E500DB518D /* libpinproc */ = { 217 | isa = PBXNativeTarget; 218 | buildConfigurationList = 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libpinproc" */; 219 | buildPhases = ( 220 | D2AAC043055464E500DB518D /* Headers */, 221 | D2AAC044055464E500DB518D /* Sources */, 222 | D289987405E68DCB004EDB86 /* Frameworks */, 223 | ); 224 | buildRules = ( 225 | ); 226 | dependencies = ( 227 | ); 228 | name = libpinproc; 229 | productName = libpinproc; 230 | productReference = D2AAC046055464E500DB518D /* libpinproc.a */; 231 | productType = "com.apple.product-type.library.static"; 232 | }; 233 | /* End PBXNativeTarget section */ 234 | 235 | /* Begin PBXProject section */ 236 | 08FB7793FE84155DC02AAC07 /* Project object */ = { 237 | isa = PBXProject; 238 | buildConfigurationList = 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libpinproc" */; 239 | compatibilityVersion = "Xcode 3.1"; 240 | hasScannedForEncodings = 1; 241 | mainGroup = 08FB7794FE84155DC02AAC07 /* libpinproc */; 242 | projectDirPath = ""; 243 | projectRoot = ""; 244 | targets = ( 245 | D2AAC045055464E500DB518D /* libpinproc */, 246 | 668249D80FC0A30A0051560E /* pinproctest */, 247 | 66C3CCAF111DDB8200FE329E /* pinprocfw */, 248 | ); 249 | }; 250 | /* End PBXProject section */ 251 | 252 | /* Begin PBXSourcesBuildPhase section */ 253 | 668249D60FC0A30A0051560E /* Sources */ = { 254 | isa = PBXSourcesBuildPhase; 255 | buildActionMask = 2147483647; 256 | files = ( 257 | 668249E30FC0A3960051560E /* pinproctest.cpp in Sources */, 258 | 66640E5E0FD1CFB6003135D8 /* dmd.cpp in Sources */, 259 | 66640E5F0FD1CFB6003135D8 /* drivers.cpp in Sources */, 260 | 66640E600FD1CFB6003135D8 /* switches.cpp in Sources */, 261 | ); 262 | runOnlyForDeploymentPostprocessing = 0; 263 | }; 264 | 66C3CCAD111DDB8200FE329E /* Sources */ = { 265 | isa = PBXSourcesBuildPhase; 266 | buildActionMask = 2147483647; 267 | files = ( 268 | 66C3CCBB111DDBA700FE329E /* lenval.cpp in Sources */, 269 | 66C3CCBC111DDBA700FE329E /* pinprocfw.cpp in Sources */, 270 | ); 271 | runOnlyForDeploymentPostprocessing = 0; 272 | }; 273 | D2AAC044055464E500DB518D /* Sources */ = { 274 | isa = PBXSourcesBuildPhase; 275 | buildActionMask = 2147483647; 276 | files = ( 277 | 6682493A0FC07B2A0051560E /* pinproc.cpp in Sources */, 278 | 668249430FC07D900051560E /* PRDevice.cpp in Sources */, 279 | 668249ED0FC0A4CD0051560E /* PRHardware.cpp in Sources */, 280 | ); 281 | runOnlyForDeploymentPostprocessing = 0; 282 | }; 283 | /* End PBXSourcesBuildPhase section */ 284 | 285 | /* Begin PBXTargetDependency section */ 286 | 668249E50FC0A3C40051560E /* PBXTargetDependency */ = { 287 | isa = PBXTargetDependency; 288 | target = D2AAC045055464E500DB518D /* libpinproc */; 289 | targetProxy = 668249E40FC0A3C40051560E /* PBXContainerItemProxy */; 290 | }; 291 | 66C3CCD9111DDD6F00FE329E /* PBXTargetDependency */ = { 292 | isa = PBXTargetDependency; 293 | target = D2AAC045055464E500DB518D /* libpinproc */; 294 | targetProxy = 66C3CCD8111DDD6F00FE329E /* PBXContainerItemProxy */; 295 | }; 296 | /* End PBXTargetDependency section */ 297 | 298 | /* Begin XCBuildConfiguration section */ 299 | 1DEB91EC08733DB70010E9CD /* Debug */ = { 300 | isa = XCBuildConfiguration; 301 | buildSettings = { 302 | ALWAYS_SEARCH_USER_PATHS = NO; 303 | CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; 304 | COPY_PHASE_STRIP = NO; 305 | GCC_DYNAMIC_NO_PIC = NO; 306 | GCC_ENABLE_FIX_AND_CONTINUE = YES; 307 | GCC_MODEL_TUNING = G5; 308 | GCC_OPTIMIZATION_LEVEL = 0; 309 | HEADER_SEARCH_PATHS = /usr/local/include; 310 | INSTALL_PATH = /usr/local/lib; 311 | OBJROOT = build; 312 | ONLY_ACTIVE_ARCH = NO; 313 | PRODUCT_NAME = pinproc; 314 | SYMROOT = bin; 315 | }; 316 | name = Debug; 317 | }; 318 | 1DEB91ED08733DB70010E9CD /* Release */ = { 319 | isa = XCBuildConfiguration; 320 | buildSettings = { 321 | ALWAYS_SEARCH_USER_PATHS = NO; 322 | CONFIGURATION_BUILD_DIR = "$(BUILD_DIR)"; 323 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 324 | GCC_MODEL_TUNING = G5; 325 | HEADER_SEARCH_PATHS = /usr/local/include; 326 | INSTALL_PATH = /usr/local/lib; 327 | OBJROOT = build; 328 | PRODUCT_NAME = pinproc; 329 | SYMROOT = bin; 330 | }; 331 | name = Release; 332 | }; 333 | 1DEB91F008733DB70010E9CD /* Debug */ = { 334 | isa = XCBuildConfiguration; 335 | buildSettings = { 336 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 337 | GCC_C_LANGUAGE_STANDARD = c99; 338 | GCC_OPTIMIZATION_LEVEL = 0; 339 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 340 | GCC_WARN_UNUSED_VARIABLE = YES; 341 | ONLY_ACTIVE_ARCH = YES; 342 | PREBINDING = NO; 343 | SDKROOT = macosx10.5; 344 | }; 345 | name = Debug; 346 | }; 347 | 1DEB91F108733DB70010E9CD /* Release */ = { 348 | isa = XCBuildConfiguration; 349 | buildSettings = { 350 | ARCHS = "$(ARCHS_STANDARD_32_BIT)"; 351 | GCC_C_LANGUAGE_STANDARD = c99; 352 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 353 | GCC_WARN_UNUSED_VARIABLE = YES; 354 | PREBINDING = NO; 355 | SDKROOT = macosx10.5; 356 | }; 357 | name = Release; 358 | }; 359 | 668249DB0FC0A30A0051560E /* Debug */ = { 360 | isa = XCBuildConfiguration; 361 | buildSettings = { 362 | ALWAYS_SEARCH_USER_PATHS = NO; 363 | COPY_PHASE_STRIP = NO; 364 | GCC_DYNAMIC_NO_PIC = NO; 365 | GCC_ENABLE_FIX_AND_CONTINUE = YES; 366 | GCC_MODEL_TUNING = G5; 367 | GCC_OPTIMIZATION_LEVEL = 0; 368 | HEADER_SEARCH_PATHS = /usr/local/include; 369 | INSTALL_PATH = /usr/local/bin; 370 | OTHER_LDFLAGS = ( 371 | "-Lbin", 372 | "-lftdi", 373 | ); 374 | PREBINDING = NO; 375 | PRODUCT_NAME = pinproctest; 376 | }; 377 | name = Debug; 378 | }; 379 | 668249DC0FC0A30A0051560E /* Release */ = { 380 | isa = XCBuildConfiguration; 381 | buildSettings = { 382 | ALWAYS_SEARCH_USER_PATHS = NO; 383 | COPY_PHASE_STRIP = YES; 384 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 385 | GCC_ENABLE_FIX_AND_CONTINUE = NO; 386 | GCC_MODEL_TUNING = G5; 387 | HEADER_SEARCH_PATHS = /usr/local/include; 388 | INSTALL_PATH = /usr/local/bin; 389 | OTHER_LDFLAGS = ( 390 | "-lftdi", 391 | ); 392 | PREBINDING = NO; 393 | PRODUCT_NAME = pinproctest; 394 | ZERO_LINK = NO; 395 | }; 396 | name = Release; 397 | }; 398 | 66C3CCB2111DDB8400FE329E /* Debug */ = { 399 | isa = XCBuildConfiguration; 400 | buildSettings = { 401 | ALWAYS_SEARCH_USER_PATHS = NO; 402 | CONFIGURATION_BUILD_DIR = bin; 403 | COPY_PHASE_STRIP = NO; 404 | GCC_DYNAMIC_NO_PIC = NO; 405 | GCC_ENABLE_FIX_AND_CONTINUE = YES; 406 | GCC_MODEL_TUNING = G5; 407 | GCC_OPTIMIZATION_LEVEL = 0; 408 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 409 | INSTALL_PATH = /usr/local/bin; 410 | OBJROOT = "$(PROJECT_DIR)/build"; 411 | OTHER_LDFLAGS = ( 412 | "-Lbin", 413 | "-lftdi", 414 | "-lpinproc", 415 | ); 416 | PREBINDING = NO; 417 | PRODUCT_NAME = pinprocfw; 418 | SYMROOT = bin; 419 | }; 420 | name = Debug; 421 | }; 422 | 66C3CCB3111DDB8400FE329E /* Release */ = { 423 | isa = XCBuildConfiguration; 424 | buildSettings = { 425 | ALWAYS_SEARCH_USER_PATHS = NO; 426 | CONFIGURATION_BUILD_DIR = bin; 427 | COPY_PHASE_STRIP = YES; 428 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 429 | GCC_ENABLE_FIX_AND_CONTINUE = NO; 430 | GCC_MODEL_TUNING = G5; 431 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 432 | INSTALL_PATH = /usr/local/bin; 433 | OBJROOT = "$(PROJECT_DIR)/build"; 434 | OTHER_LDFLAGS = ( 435 | "-Lbin", 436 | "-lftdi", 437 | "-lpinproc", 438 | ); 439 | PREBINDING = NO; 440 | PRODUCT_NAME = pinprocfw; 441 | SYMROOT = bin; 442 | ZERO_LINK = NO; 443 | }; 444 | name = Release; 445 | }; 446 | /* End XCBuildConfiguration section */ 447 | 448 | /* Begin XCConfigurationList section */ 449 | 1DEB91EB08733DB70010E9CD /* Build configuration list for PBXNativeTarget "libpinproc" */ = { 450 | isa = XCConfigurationList; 451 | buildConfigurations = ( 452 | 1DEB91EC08733DB70010E9CD /* Debug */, 453 | 1DEB91ED08733DB70010E9CD /* Release */, 454 | ); 455 | defaultConfigurationIsVisible = 0; 456 | defaultConfigurationName = Release; 457 | }; 458 | 1DEB91EF08733DB70010E9CD /* Build configuration list for PBXProject "libpinproc" */ = { 459 | isa = XCConfigurationList; 460 | buildConfigurations = ( 461 | 1DEB91F008733DB70010E9CD /* Debug */, 462 | 1DEB91F108733DB70010E9CD /* Release */, 463 | ); 464 | defaultConfigurationIsVisible = 0; 465 | defaultConfigurationName = Release; 466 | }; 467 | 668249DD0FC0A32A0051560E /* Build configuration list for PBXNativeTarget "pinproctest" */ = { 468 | isa = XCConfigurationList; 469 | buildConfigurations = ( 470 | 668249DB0FC0A30A0051560E /* Debug */, 471 | 668249DC0FC0A30A0051560E /* Release */, 472 | ); 473 | defaultConfigurationIsVisible = 0; 474 | defaultConfigurationName = Release; 475 | }; 476 | 66C3CCB6111DDB9000FE329E /* Build configuration list for PBXNativeTarget "pinprocfw" */ = { 477 | isa = XCConfigurationList; 478 | buildConfigurations = ( 479 | 66C3CCB2111DDB8400FE329E /* Debug */, 480 | 66C3CCB3111DDB8400FE329E /* Release */, 481 | ); 482 | defaultConfigurationIsVisible = 0; 483 | defaultConfigurationName = Release; 484 | }; 485 | /* End XCConfigurationList section */ 486 | }; 487 | rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; 488 | } 489 | -------------------------------------------------------------------------------- /pinproc.pc.cmake: -------------------------------------------------------------------------------- 1 | prefix=@CMAKE_INSTALL_PREFIX@ 2 | exec_prefix=@CMAKE_INSTALL_PREFIX@ 3 | libdir=${prefix}/@LIB_INSTALL_DIR@ 4 | includedir=${prefix}/@INCLUDE_INSTALL_DIR@ 5 | 6 | Name: Pinproc 7 | Description: P-ROC interface library 8 | Version: @PINPROC_VERSION@ 9 | Requires: 10 | Libs: -L${libdir} -lpinproc 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /src/PRCommon.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 3 | * 4 | * Permission is hereby granted, free of charge, to any person 5 | * obtaining a copy of this software and associated documentation 6 | * files (the "Software"), to deal in the Software without 7 | * restriction, including without limitation the rights to use, 8 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following 11 | * conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be 14 | * included in all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 18 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 20 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 21 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23 | * OTHER DEALINGS IN THE SOFTWARE. 24 | */ 25 | #ifndef PINPROC_PRCOMMON_H 26 | #define PINPROC_PRCOMMON_H 27 | #if !defined(__GNUC__) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4) // GCC supports "pragma once" correctly since 3.4 28 | #pragma once 29 | #endif 30 | 31 | #ifdef NDEBUG 32 | # define DEBUG(block) 33 | #else 34 | # define DEBUG(block) block 35 | #endif 36 | 37 | void PRLog(PRLogLevel level, const char *format, ...); 38 | void PRSetLastErrorText(const char *format, ...); 39 | 40 | #endif /* PINPROC_PRCOMMON_H */ 41 | -------------------------------------------------------------------------------- /src/PRDevice.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following 12 | * conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | * OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | /* 27 | * PRDevice.h 28 | * libpinproc 29 | */ 30 | #ifndef PINPROC_PRDEVICE_H 31 | #define PINPROC_PRDEVICE_H 32 | #if !defined(__GNUC__) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4) // GCC supports "pragma once" correctly since 3.4 33 | #pragma once 34 | #endif 35 | 36 | #include "pinproc.h" 37 | #include "PRCommon.h" 38 | #include "PRHardware.h" 39 | #include 40 | 41 | using namespace std; 42 | 43 | #define maxDriverGroups (26) 44 | #define maxDrivers (256) 45 | #define maxSwitchRules (256<<2) // 8 bits of switchNum indicies plus bits for debounced and state. 46 | #define maxWriteWords (1536) // Hardware supports 2048 word bursts, but restrict to 1536 for margin. 47 | 48 | class PRDevice 49 | { 50 | public: 51 | static PRDevice *Create(PRMachineType machineType); 52 | ~PRDevice(); 53 | PRResult Reset(uint32_t resetFlags); 54 | protected: 55 | PRDevice(PRMachineType machineType); 56 | 57 | public: 58 | // public libpinproc API: 59 | int GetEvents(PREvent *events, int maxEvents); 60 | 61 | PRResult FlushWriteData(); 62 | PRResult WriteDataRaw(uint32_t moduleSelect, uint32_t startingAddr, int32_t numWriteWords, uint32_t * buffer); 63 | PRResult WriteDataRawUnbuffered(uint32_t moduleSelect, uint32_t startingAddr, int32_t numWriteWords, uint32_t * buffer); 64 | PRResult ReadDataRaw(uint32_t moduleSelect, uint32_t startingAddr, int32_t numReadWords, uint32_t * readBuffer); 65 | 66 | PRResult ManagerUpdateConfig(PRManagerConfig *managerConfig); 67 | 68 | PRResult DriverUpdateGlobalConfig(PRDriverGlobalConfig *driverGlobalConfig); 69 | PRResult DriverGetGroupConfig(uint8_t groupNum, PRDriverGroupConfig *driverGroupConfig); 70 | PRResult DriverUpdateGroupConfig(PRDriverGroupConfig *driverGroupConfig); 71 | PRResult DriverGetState(uint8_t driverNum, PRDriverState *driverState); 72 | PRResult DriverUpdateState(PRDriverState *driverState); 73 | PRResult DriverLoadMachineTypeDefaults(PRMachineType machineType, uint32_t resetFlags = kPRResetFlagDefault); 74 | PRResult DriverAuxSendCommands( PRDriverAuxCommand *commands, uint8_t numCommands, uint8_t startingAddr); 75 | PRResult DriverWatchdogTickle(); 76 | 77 | PRResult SwitchUpdateConfig(PRSwitchConfig *switchConfig); 78 | PRResult SwitchUpdateRule(uint8_t switchNum, PREventType eventType, PRSwitchRule *rule, PRDriverState *linkedDrivers, int numDrivers, bool_t drive_outputs_now); 79 | PRResult SwitchGetStates(PREventType * switchStates, uint16_t numSwitches); 80 | 81 | PRResult DMDUpdateConfig(PRDMDConfig *dmdConfig); 82 | PRResult DMDDraw(uint8_t * dots); 83 | 84 | PRResult PRJTAGDriveOutputs(PRJTAGOutputs * jtagOutputs, bool_t toggleClk); 85 | PRResult PRJTAGWriteTDOMemory(uint16_t tableOffset, uint16_t numWords, uint32_t * tdoData); 86 | PRResult PRJTAGShiftTDOData(uint16_t numBits, bool_t dataBlockComplete); 87 | PRResult PRJTAGReadTDIMemory(uint16_t tableOffset, uint16_t numWords, uint32_t * tdiData); 88 | PRResult PRJTAGGetStatus(PRJTAGStatus * status); 89 | 90 | PRResult PRLEDColor(PRLED * pLED, uint8_t color); 91 | PRResult PRLEDFade(PRLED * pLED, uint8_t fadeColor, uint16_t fadeRate); 92 | PRResult PRLEDFadeColor(PRLED * pLED, uint8_t fadeColor); 93 | PRResult PRLEDFadeRate(uint8_t boardAddr, uint16_t fadeRate); 94 | PRResult PRLEDRGBColor(PRLEDRGB * pLED, uint32_t color); 95 | PRResult PRLEDRGBFade(PRLEDRGB * pLED, uint32_t fadeColor, uint16_t fadeRate); 96 | PRResult PRLEDRGBFadeColor(PRLEDRGB * pLED, uint32_t fadeColor); 97 | 98 | int GetVersionInfo(uint16_t *verPtr, uint16_t *revPtr, uint32_t *combinedPtr); 99 | 100 | protected: 101 | 102 | // Device I/O 103 | 104 | PRResult Open(); 105 | PRResult Close(); 106 | 107 | PRResult VerifyChipID(); 108 | PRMachineType GetReadMachineType(); 109 | 110 | // Raw write and read methods 111 | // 112 | 113 | /** Schedules data to be written to the P-ROC. */ 114 | PRResult PrepareWriteData(uint32_t * buffer, int32_t numWords); 115 | 116 | /** Writes data to the P-ROC immediately. */ 117 | PRResult WriteData(uint32_t * buffer, int32_t numWords); 118 | 119 | /** 120 | * Reads data from the buffer that was previously collected by CollectReadData(). 121 | * Returns the number of bytes read. 122 | */ 123 | int32_t ReadData(uint32_t *buffer, int32_t maxWords); 124 | 125 | // Collection of methods to get data returning from the P-ROC 126 | /** 127 | * Request a block of data from the P-ROC. 128 | */ 129 | PRResult RequestData(uint32_t module_select, uint32_t start_addr, int32_t num_words); 130 | /** 131 | * Actually reads the data off of the FTDI chip. 132 | * This is called by SortReturningData() in order to get some data to process. 133 | */ 134 | int32_t CollectReadData(); 135 | /** 136 | * Processes data into unrequestedDataQueue and requestedDataQueue. 137 | * Calls CollectReadData() to obtain the data and then uses ReadData() to read it out. 138 | */ 139 | PRResult SortReturningData(); 140 | /** 141 | * Empties out the read buffer. 142 | * Calls CollectReadData() and then ReadData() until it's empty. 143 | */ 144 | PRResult FlushReadBuffer(); 145 | 146 | queue unrequestedDataQueue; /**< Queue of words received from the device that were not requested via RequestData(). Usually switch events. */ 147 | queue requestedDataQueue; /**< Queue of words received from the device as the result of a call to RequestData(). */ 148 | 149 | uint16_t version; 150 | uint16_t revision; 151 | uint32_t chip_id; 152 | uint32_t combinedVersionRevision; 153 | /** 154 | * Calculated combined Version/Revision number. 155 | */ 156 | int CalcCombinedVerRevision(); 157 | 158 | uint32_t preparedWriteWords[maxWriteWords]; 159 | int32_t numPreparedWriteWords; 160 | 161 | uint8_t collected_bytes_fifo[FTDI_BUFFER_SIZE]; 162 | int32_t collected_bytes_rd_addr; 163 | int32_t collected_bytes_wr_addr; 164 | int32_t num_collected_bytes; 165 | 166 | uint8_t wr_buffer[16384]; 167 | uint8_t collect_buffer[FTDI_BUFFER_SIZE]; 168 | PRMachineType readMachineType; 169 | 170 | 171 | // Local Device State 172 | PRMachineType machineType; 173 | PRManagerConfig managerConfig; 174 | PRDriverGlobalConfig driverGlobalConfig; 175 | PRDriverGroupConfig driverGroups[maxDriverGroups]; 176 | PRDriverState drivers[maxDrivers]; 177 | PRDMDConfig dmdConfig; 178 | 179 | PRSwitchConfig switchConfig; 180 | PRSwitchRuleInternal switchRules[maxSwitchRules]; 181 | queue freeSwitchRuleIndexes; /**< Indexes of available switch rules. */ 182 | PRSwitchRuleInternal *GetSwitchRuleByIndex(uint16_t index); 183 | }; 184 | 185 | #endif /* PINPROC_PRDEVICE_H */ 186 | -------------------------------------------------------------------------------- /src/PRHardware.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following 12 | * conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | * OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | /* 27 | * PRHardware.cpp 28 | * libpinproc 29 | */ 30 | 31 | #include 32 | #include "PRHardware.h" 33 | #include "PRCommon.h" 34 | 35 | bool_t IsStern (uint32_t hardware_data) { 36 | // if ( ((hardware_data & P_ROC_BOARD_VERSION_MASK) >> P_ROC_BOARD_VERSION_SHIFT) == 0x1) 37 | // return ( ((hardware_data & P_ROC_AUTO_STERN_DETECT_MASK) >> P_ROC_AUTO_STERN_DETECT_SHIFT) == P_ROC_AUTO_STERN_DETECT_VALUE); 38 | // else 39 | return ( ((hardware_data & P_ROC_MANUAL_STERN_DETECT_MASK) >> P_ROC_MANUAL_STERN_DETECT_SHIFT) == P_ROC_MANUAL_STERN_DETECT_VALUE); 40 | } 41 | 42 | uint32_t CreateRegRequestWord( uint32_t select, uint32_t addr, uint32_t num_words ) { 43 | return ( (P_ROC_READ << P_ROC_COMMAND_SHIFT) | 44 | (num_words << P_ROC_HEADER_LENGTH_SHIFT) | 45 | (select << P_ROC_MODULE_SELECT_SHIFT) | 46 | (addr << P_ROC_ADDR_SHIFT) ); 47 | }; 48 | 49 | 50 | uint32_t CreateBurstCommand ( uint32_t select, uint32_t addr, uint32_t num_words ) { 51 | return ( (P_ROC_WRITE << P_ROC_COMMAND_SHIFT) | 52 | (num_words << P_ROC_HEADER_LENGTH_SHIFT) | 53 | (select << P_ROC_MODULE_SELECT_SHIFT) | 54 | (addr << P_ROC_ADDR_SHIFT) ); 55 | } 56 | 57 | int32_t CreateManagerUpdateConfigBurst ( uint32_t * burst, PRManagerConfig *manager_config) { 58 | uint32_t addr; 59 | 60 | addr = P_ROC_REG_DIPSWITCH_ADDR; 61 | burst[0] = CreateBurstCommand (P_ROC_MANAGER_SELECT, addr, 1 ); 62 | burst[1] = ( (manager_config->reuse_dmd_data_for_aux << 63 | P_ROC_MANAGER_REUSE_DMD_DATA_FOR_AUX_SHIFT) | 64 | (manager_config->invert_dipswitch_1 << 65 | P_ROC_MANAGER_INVERT_DIPSWITCH_1_SHIFT) ); 66 | 67 | return kPRSuccess; 68 | } 69 | 70 | int32_t CreateDriverUpdateGlobalConfigBurst ( uint32_t * burst, PRDriverGlobalConfig *driver_globals) { 71 | uint32_t addr; 72 | 73 | addr = 0; 74 | addr = (P_ROC_DRIVER_CTRL_REG_DECODE << P_ROC_DRIVER_CTRL_DECODE_SHIFT); 75 | 76 | burst[0] = CreateBurstCommand (P_ROC_BUS_DRIVER_CTRL_SELECT, addr, 1 ); 77 | burst[1] = ( (driver_globals->enableOutputs << 78 | P_ROC_DRIVER_GLOBAL_ENABLE_DIRECT_OUTPUTS_SHIFT) | 79 | (driver_globals->globalPolarity << 80 | P_ROC_DRIVER_GLOBAL_GLOBAL_POLARITY_SHIFT) | 81 | (driver_globals->useClear << 82 | P_ROC_DRIVER_GLOBAL_USE_CLEAR_SHIFT) | 83 | (driver_globals->strobeStartSelect << 84 | P_ROC_DRIVER_GLOBAL_STROBE_START_SELECT_SHIFT) | 85 | (driver_globals->startStrobeTime << 86 | P_ROC_DRIVER_GLOBAL_START_STROBE_TIME_SHIFT) | 87 | (driver_globals->matrixRowEnableIndex1 << 88 | P_ROC_DRIVER_GLOBAL_MATRIX_ROW_ENABLE_INDEX_1_SHIFT) | 89 | (driver_globals->matrixRowEnableIndex0 << 90 | P_ROC_DRIVER_GLOBAL_MATRIX_ROW_ENABLE_INDEX_0_SHIFT) | 91 | (driver_globals->activeLowMatrixRows << 92 | P_ROC_DRIVER_GLOBAL_ACTIVE_LOW_MATRIX_ROWS_SHIFT) | 93 | (driver_globals->encodeEnables << 94 | P_ROC_DRIVER_GLOBAL_ENCODE_ENABLES_SHIFT) | 95 | (driver_globals->tickleSternWatchdog << 96 | P_ROC_DRIVER_GLOBAL_TICKLE_WATCHDOG_SHIFT) ); 97 | 98 | return kPRSuccess; 99 | } 100 | 101 | int32_t CreateDriverUpdateGroupConfigBurst ( uint32_t * burst, PRDriverGroupConfig *driver_group) { 102 | uint32_t addr; 103 | 104 | addr = 0; 105 | addr = (P_ROC_DRIVER_CTRL_REG_DECODE << P_ROC_DRIVER_CTRL_DECODE_SHIFT) | 106 | driver_group->groupNum; 107 | 108 | burst[0] = CreateBurstCommand (P_ROC_BUS_DRIVER_CTRL_SELECT, addr, 1 ); 109 | burst[1] = ( (driver_group->slowTime << 110 | P_ROC_DRIVER_GROUP_SLOW_TIME_SHIFT) | 111 | (driver_group->disableStrobeAfter << 112 | P_ROC_DRIVER_GROUP_DISABLE_STROBE_AFTER_SHIFT) | 113 | (driver_group->enableIndex << 114 | P_ROC_DRIVER_GROUP_ENABLE_INDEX_SHIFT) | 115 | (driver_group->rowActivateIndex << 116 | P_ROC_DRIVER_GROUP_ROW_ACTIVATE_INDEX_SHIFT) | 117 | (driver_group->rowEnableSelect << 118 | P_ROC_DRIVER_GROUP_ROW_ENABLE_SELECT_SHIFT) | 119 | (driver_group->matrixed << 120 | P_ROC_DRIVER_GROUP_MATRIXED_SHIFT) | 121 | (driver_group->polarity << 122 | P_ROC_DRIVER_GROUP_POLARITY_SHIFT) | 123 | (driver_group->active << 124 | P_ROC_DRIVER_GROUP_ACTIVE_SHIFT) ); 125 | return kPRSuccess; 126 | } 127 | 128 | int32_t CreateDriverUpdateBurst ( uint32_t * burst, PRDriverState *driver) { 129 | uint32_t addr; 130 | 131 | addr = 0; 132 | addr = (P_ROC_DRIVER_CONFIG_TABLE_DECODE << P_ROC_DRIVER_CTRL_DECODE_SHIFT) | 133 | (driver->driverNum << P_ROC_DRIVER_CONFIG_TABLE_DRIVER_NUM_SHIFT); 134 | 135 | burst[0] = CreateBurstCommand (P_ROC_BUS_DRIVER_CTRL_SELECT, addr, 2 ); 136 | burst[1] = ( (driver->outputDriveTime << P_ROC_DRIVER_CONFIG_OUTPUT_DRIVE_TIME_SHIFT) | 137 | (driver->polarity << P_ROC_DRIVER_CONFIG_POLARITY_SHIFT) | 138 | (driver->state << P_ROC_DRIVER_CONFIG_STATE_SHIFT) | 139 | (1 << P_ROC_DRIVER_CONFIG_UPDATE_SHIFT) | 140 | (driver->waitForFirstTimeSlot << P_ROC_DRIVER_CONFIG_WAIT_4_1ST_SLOT_SHIFT) | 141 | (driver->timeslots << P_ROC_DRIVER_CONFIG_TIMESLOT_SHIFT) ); 142 | burst[2] = (driver->timeslots >> P_ROC_DRIVER_CONFIG_TIMESLOT_SHIFT) | 143 | (driver->patterOnTime << P_ROC_DRIVER_CONFIG_PATTER_ON_TIME_SHIFT) | 144 | (driver->patterOffTime << P_ROC_DRIVER_CONFIG_PATTER_OFF_TIME_SHIFT) | 145 | (driver->patterEnable << P_ROC_DRIVER_CONFIG_PATTER_ENABLE_SHIFT) | 146 | (driver->futureEnable << P_ROC_DRIVER_CONFIG_FUTURE_ENABLE_SHIFT); 147 | return kPRSuccess; 148 | } 149 | 150 | uint32_t CreateDriverAuxCommand ( PRDriverAuxCommand command) { 151 | switch (command.command) { 152 | case (kPRDriverAuxCmdOutput) : { 153 | return ((command.active & 1) << P_ROC_DRIVER_AUX_ENTRY_ACTIVE_SHIFT) | 154 | ((command.delayTime & P_ROC_DRIVER_AUX_OUTPUT_DELAY_MASK) << 155 | P_ROC_DRIVER_AUX_OUTPUT_DELAY_SHIFT) | 156 | ((command.muxEnables & 1) << P_ROC_DRIVER_AUX_MUX_ENABLES_SHIFT) | 157 | ((command.command & P_ROC_DRIVER_AUX_COMMAND_MASK) << 158 | P_ROC_DRIVER_AUX_COMMAND_SHIFT) | 159 | ((command.enables & P_ROC_DRIVER_AUX_ENABLES_MASK) << 160 | P_ROC_DRIVER_AUX_ENABLES_SHIFT) | 161 | ((command.extraData & P_ROC_DRIVER_AUX_EXTRA_DATA_MASK) << 162 | P_ROC_DRIVER_AUX_EXTRA_DATA_SHIFT) | 163 | ((command.data & P_ROC_DRIVER_AUX_DATA_MASK) << 164 | P_ROC_DRIVER_AUX_DATA_SHIFT); 165 | } 166 | break; 167 | case (kPRDriverAuxCmdDelay) : { 168 | return (command.active << P_ROC_DRIVER_AUX_ENTRY_ACTIVE_SHIFT) | 169 | ((command.command & P_ROC_DRIVER_AUX_COMMAND_MASK) << 170 | P_ROC_DRIVER_AUX_COMMAND_SHIFT) | 171 | ((command.delayTime & P_ROC_DRIVER_AUX_DELAY_TIME_MASK) << 172 | P_ROC_DRIVER_AUX_DELAY_TIME_SHIFT); 173 | } 174 | break; 175 | case (kPRDriverAuxCmdJump) : { 176 | return (command.active << P_ROC_DRIVER_AUX_ENTRY_ACTIVE_SHIFT) | 177 | ((command.command & P_ROC_DRIVER_AUX_COMMAND_MASK) << 178 | P_ROC_DRIVER_AUX_COMMAND_SHIFT) | 179 | ((command.jumpAddr & P_ROC_DRIVER_AUX_JUMP_ADDR_MASK) << 180 | P_ROC_DRIVER_AUX_JUMP_ADDR_SHIFT); 181 | } 182 | break; 183 | default : { 184 | return (false << P_ROC_DRIVER_AUX_ENTRY_ACTIVE_SHIFT); 185 | } 186 | } 187 | } 188 | 189 | int32_t CreateWatchdogConfigBurst ( uint32_t * burst, bool_t watchdogExpired, 190 | bool_t watchdogEnable, uint16_t watchdogResetTime) { 191 | uint32_t addr; 192 | 193 | addr = P_ROC_REG_WATCHDOG_ADDR; 194 | burst[0] = CreateBurstCommand (P_ROC_MANAGER_SELECT, addr, 1 ); 195 | burst[1] = ( (watchdogExpired << P_ROC_MANAGER_WATCHDOG_EXPIRED_SHIFT) | 196 | (watchdogEnable << P_ROC_MANAGER_WATCHDOG_ENABLE_SHIFT) | 197 | (watchdogResetTime << P_ROC_MANAGER_WATCHDOG_RESET_TIME_SHIFT) ); 198 | 199 | return kPRSuccess; 200 | } 201 | 202 | int32_t CreateSwitchUpdateConfigBurst ( uint32_t * burst, PRSwitchConfig *switchConfig) 203 | { 204 | uint32_t addr; 205 | 206 | addr = 0; 207 | burst[0] = CreateBurstCommand (P_ROC_BUS_SWITCH_CTRL_SELECT, addr, 1 ); 208 | burst[1] = (switchConfig->clear << P_ROC_SWITCH_CONFIG_CLEAR_SHIFT) | 209 | (switchConfig->directMatrixScanLoopTime << 210 | P_ROC_SWITCH_CONFIG_MS_PER_DM_SCAN_LOOP_SHIFT) | 211 | (switchConfig->pulsesBeforeCheckingRX << 212 | P_ROC_SWITCH_CONFIG_PULSES_BEFORE_CHECKING_RX_SHIFT) | 213 | (switchConfig->inactivePulsesAfterBurst << 214 | P_ROC_SWITCH_CONFIG_INACTIVE_PULSES_AFTER_BURST_SHIFT) | 215 | (switchConfig->pulsesPerBurst << 216 | P_ROC_SWITCH_CONFIG_PULSES_PER_BURST_SHIFT) | 217 | (switchConfig->pulseHalfPeriodTime << 218 | P_ROC_SWITCH_CONFIG_MS_PER_PULSE_HALF_PERIOD_SHIFT) | 219 | (switchConfig->use_column_8 << 220 | P_ROC_SWITCH_CONFIG_USE_COLUMN_8) | 221 | (switchConfig->use_column_9 << 222 | P_ROC_SWITCH_CONFIG_USE_COLUMN_9); 223 | burst[2] = CreateBurstCommand (P_ROC_BUS_STATE_CHANGE_PROC_SELECT, 224 | P_ROC_STATE_CHANGE_CONFIG_ADDR, 1 ); 225 | burst[3] = switchConfig->hostEventsEnable; 226 | 227 | return kPRSuccess; 228 | } 229 | 230 | int16_t CreateSwitchRuleIndex(uint8_t switchNum, PREventType eventType) 231 | { 232 | uint32_t debounce = (eventType == kPREventTypeSwitchOpenDebounced) || (eventType == kPREventTypeSwitchClosedDebounced) ? 1 : 0; 233 | uint32_t state = (eventType == kPREventTypeSwitchOpenDebounced) || (eventType == kPREventTypeSwitchOpenNondebounced) ? 1 : 0; 234 | 235 | uint32_t index = ((debounce << P_ROC_SWITCH_RULE_NUM_DEBOUNCE_SHIFT) | 236 | (state << P_ROC_SWITCH_RULE_NUM_STATE_SHIFT) | 237 | (switchNum << P_ROC_SWITCH_RULE_NUM_SWITCH_NUM_SHIFT) ); 238 | return index; 239 | } 240 | 241 | int32_t CreateSwitchRuleAddr(uint8_t switchNum, PREventType eventType, bool_t drive_outputs_now) 242 | { 243 | uint16_t number = CreateSwitchRuleIndex( switchNum, eventType ); 244 | uint32_t addr = (number << P_ROC_SWITCH_RULE_NUM_TO_ADDR_SHIFT) | 245 | (drive_outputs_now << P_ROC_SWITCH_RULE_DRIVE_OUTPUTS_NOW); 246 | return addr; 247 | } 248 | 249 | void ParseSwitchRuleIndex(uint16_t index, uint8_t *switchNum, PREventType *eventType) 250 | { 251 | *switchNum = (index >> P_ROC_SWITCH_RULE_NUM_SWITCH_NUM_SHIFT) & 0xff; 252 | 253 | bool open = ((index >> P_ROC_SWITCH_RULE_NUM_STATE_SHIFT) & 0x1) == 0x1; 254 | bool debounce = ((index >> P_ROC_SWITCH_RULE_NUM_DEBOUNCE_SHIFT) & 0x1) == 0x1; 255 | if (open) 256 | *eventType = debounce ? kPREventTypeSwitchOpenDebounced : kPREventTypeSwitchOpenNondebounced; 257 | else 258 | *eventType = debounce ? kPREventTypeSwitchClosedDebounced : kPREventTypeSwitchClosedNondebounced; 259 | } 260 | 261 | int32_t CreateSwitchUpdateRulesBurst ( uint32_t * burst, PRSwitchRuleInternal *rule_record, bool_t drive_outputs_now) { 262 | uint32_t addr = CreateSwitchRuleAddr(rule_record->switchNum, rule_record->eventType, drive_outputs_now); 263 | uint32_t driver_command[3]; 264 | 265 | CreateDriverUpdateBurst ( driver_command, &(rule_record->driver)); 266 | 267 | burst[0] = CreateBurstCommand (P_ROC_BUS_STATE_CHANGE_PROC_SELECT, addr, 3 ); 268 | burst[1] = driver_command[1]; 269 | burst[2] = driver_command[2]; 270 | 271 | burst[3] = (rule_record->changeOutput << P_ROC_SWITCH_RULE_CHANGE_OUTPUT_SHIFT) | 272 | (rule_record->driver.driverNum << P_ROC_SWITCH_RULE_DRIVER_NUM_SHIFT) | 273 | (rule_record->linkActive << P_ROC_SWITCH_RULE_LINK_ACTIVE_SHIFT) | 274 | (rule_record->linkIndex << P_ROC_SWITCH_RULE_LINK_ADDRESS_SHIFT) | 275 | (rule_record->notifyHost << P_ROC_SWITCH_RULE_NOTIFY_HOST_SHIFT) | 276 | (rule_record->reloadActive << P_ROC_SWITCH_RULE_RELOAD_ACTIVE_SHIFT); 277 | return kPRSuccess; 278 | 279 | } 280 | 281 | int32_t CreateDMDUpdateConfigBurst ( uint32_t * burst, PRDMDConfig *dmd_config) 282 | { 283 | uint32_t addr; 284 | uint32_t i; 285 | 286 | addr = 0; 287 | burst[0] = CreateBurstCommand (P_ROC_BUS_DMD_SELECT, addr, 1 ); 288 | burst[1] = (1 << P_ROC_DMD_ENABLE_SHIFT) | 289 | (dmd_config->enableFrameEvents << P_ROC_DMD_ENABLE_FRAME_EVENTS_SHIFT) | 290 | (dmd_config->autoIncBufferWrPtr << P_ROC_DMD_AUTO_INC_WR_POINTER_SHIFT) | 291 | (dmd_config->numFrameBuffers << P_ROC_DMD_NUM_FRAME_BUFFERS_SHIFT) | 292 | (dmd_config->numSubFrames << P_ROC_DMD_NUM_SUB_FRAMES_SHIFT) | 293 | (dmd_config->numRows << P_ROC_DMD_NUM_ROWS_SHIFT) | 294 | (dmd_config->numColumns << P_ROC_DMD_NUM_COLUMNS_SHIFT); 295 | 296 | addr = 8; 297 | burst[2] = CreateBurstCommand (P_ROC_BUS_DMD_SELECT, addr, 4 ); 298 | 299 | for (i=0; i<4; i++) { 300 | burst[i+3] = (dmd_config->rclkLowCycles[i] << P_ROC_DMD_RCLK_LOW_CYCLES_SHIFT) | 301 | (dmd_config->latchHighCycles[i] << P_ROC_DMD_LATCH_HIGH_CYCLES_SHIFT) | 302 | (dmd_config->deHighCycles[i] << P_ROC_DMD_DE_HIGH_CYCLES_SHIFT) | 303 | (dmd_config->dotclkHalfPeriod[i] << P_ROC_DMD_DOTCLK_HALF_PERIOD_SHIFT); 304 | } 305 | return kPRSuccess; 306 | } 307 | 308 | int32_t CreateJTAGForceOutputsBurst ( uint32_t * burst, PRJTAGOutputs *jtagOutputs) { 309 | burst[0] = CreateBurstCommand (P_ROC_BUS_JTAG_SELECT, P_ROC_JTAG_COMMAND_REG_BASE_ADDR, 1 ); 310 | burst[1] = 0; 311 | burst[1] = 1 << P_ROC_JTAG_CMD_START_SHIFT | 312 | 1 << P_ROC_JTAG_CMD_OE_SHIFT | 313 | P_ROC_JTAG_CMD_SET_PORTS << P_ROC_JTAG_CMD_CMD_SHIFT | 314 | jtagOutputs->tckMask << P_ROC_JTAG_TRANSITION_TCK_MASK_SHIFT | 315 | jtagOutputs->tdoMask << P_ROC_JTAG_TRANSITION_TDO_MASK_SHIFT | 316 | jtagOutputs->tmsMask << P_ROC_JTAG_TRANSITION_TMS_MASK_SHIFT | 317 | jtagOutputs->tck << P_ROC_JTAG_TRANSITION_TCK_SHIFT | 318 | jtagOutputs->tdo << P_ROC_JTAG_TRANSITION_TCK_SHIFT | 319 | jtagOutputs->tms << P_ROC_JTAG_TRANSITION_TCK_SHIFT; 320 | return kPRSuccess; 321 | 322 | } 323 | int32_t CreateJTAGLatchOutputsBurst ( uint32_t * burst, PRJTAGOutputs *jtagOutputs) { 324 | burst[0] = CreateBurstCommand (P_ROC_BUS_JTAG_SELECT, P_ROC_JTAG_COMMAND_REG_BASE_ADDR, 1 ); 325 | burst[1] = 0; 326 | burst[1] = 1 << P_ROC_JTAG_CMD_START_SHIFT | 327 | 1 << P_ROC_JTAG_CMD_OE_SHIFT | 328 | P_ROC_JTAG_CMD_TRANSITION << P_ROC_JTAG_CMD_CMD_SHIFT | 329 | jtagOutputs->tdoMask << P_ROC_JTAG_TRANSITION_TDO_MASK_SHIFT | 330 | jtagOutputs->tmsMask << P_ROC_JTAG_TRANSITION_TMS_MASK_SHIFT | 331 | jtagOutputs->tdo << P_ROC_JTAG_TRANSITION_TCK_SHIFT | 332 | jtagOutputs->tms << P_ROC_JTAG_TRANSITION_TMS_SHIFT; 333 | return kPRSuccess; 334 | 335 | } 336 | int32_t CreateJTAGShiftTDODataBurst ( uint32_t * burst, uint16_t numBits, bool_t dataBlockComplete) { 337 | burst[0] = CreateBurstCommand (P_ROC_BUS_JTAG_SELECT, P_ROC_JTAG_COMMAND_REG_BASE_ADDR, 1 ); 338 | burst[1] = 0; 339 | burst[1] = 1 << P_ROC_JTAG_CMD_START_SHIFT | 340 | 1 << P_ROC_JTAG_CMD_OE_SHIFT | 341 | P_ROC_JTAG_CMD_SHIFT << P_ROC_JTAG_CMD_CMD_SHIFT | 342 | dataBlockComplete << P_ROC_JTAG_SHIFT_EXIT_SHIFT | 343 | numBits << P_ROC_JTAG_SHIFT_NUM_BITS_SHIFT; 344 | return kPRSuccess; 345 | } 346 | 347 | void FillPDBCommand(uint8_t command, uint8_t boardAddr, PRLEDRegisterType reg, uint8_t data, uint32_t * buffer) 348 | { 349 | buffer[0] = CreateBurstCommand (P_ROC_BUS_DRIVER_CTRL_SELECT, P_ROC_DRIVER_PDB_ADDR, 1 ); 350 | buffer[1] = (command << P_ROC_DRIVER_PDB_COMMAND_SHIFT) | 351 | (boardAddr << P_ROC_DRIVER_PDB_BOARD_ADDR_SHIFT) | 352 | (reg << P_ROC_DRIVER_PDB_REGISTER_SHIFT) | 353 | (data << P_ROC_DRIVER_PDB_DATA_SHIFT); 354 | } 355 | 356 | 357 | 358 | /** 359 | * This is where all FTDI driver-specific code should go. 360 | * As we add support for other drivers (such as D2xx on Windows), we will add more implementations of the PRHardware*() functions here. 361 | */ 362 | 363 | #if defined(__WIN32__) || defined(_WIN32) 364 | #include "ftd2xx.h" 365 | 366 | #define BUF_SIZE 16 367 | #define MAX_DEVICES 1 368 | 369 | // Globals 370 | static FT_HANDLE ftHandles[MAX_DEVICES]; 371 | static FT_HANDLE ftHandle; 372 | 373 | PRResult PRHardwareOpen() 374 | { 375 | char cBufWrite[BUF_SIZE]; 376 | char * pcBufLD[MAX_DEVICES + 1]; 377 | char cBufLD[MAX_DEVICES][64]; 378 | FT_STATUS ftStatus; 379 | int iNumDevs = 0; 380 | int i, j; 381 | int iDevicesOpen = 0; 382 | 383 | for(i = 0; i < MAX_DEVICES; i++) { 384 | pcBufLD[i] = cBufLD[i]; 385 | ftHandles[i] = NULL; 386 | } 387 | pcBufLD[MAX_DEVICES] = NULL; 388 | 389 | ftStatus = FT_ListDevices(pcBufLD, &iNumDevs, FT_LIST_ALL | FT_OPEN_BY_SERIAL_NUMBER); 390 | 391 | if(ftStatus != FT_OK) { 392 | PRSetLastErrorText("FT_ListDevices(%d)\n", ftStatus); 393 | DEBUG(PRLog(kPRLogInfo,"Error: FT_ListDevices(%d)\n", ftStatus)); 394 | return kPRFailure; 395 | } 396 | 397 | for(j = 0; j < BUF_SIZE; j++) { 398 | cBufWrite[j] = j; 399 | } 400 | 401 | for(i = 0; ( (i 0) 429 | { 430 | FT_ResetDevice(ftHandle); 431 | DEBUG(PRLog(kPRLogInfo,"FTDI Device Opened\n")); 432 | return kPRSuccess; 433 | } 434 | else 435 | { 436 | PRSetLastErrorText("No FTDI device found."); 437 | return kPRFailure; 438 | } 439 | } 440 | 441 | void PRHardwareClose() 442 | { 443 | int i; 444 | 445 | for(i = 0; i < MAX_DEVICES; i++) { 446 | if(ftHandles[i] != NULL) { 447 | FT_Close(ftHandles[i]); 448 | ftHandles[i] = NULL; 449 | DEBUG(PRLog(kPRLogInfo,"Closed device\n")); 450 | } 451 | } 452 | } 453 | 454 | int PRHardwareRead(uint8_t *buffer, int maxBytes) 455 | { 456 | FT_STATUS ftStatus; 457 | DWORD bytesToRead; 458 | DWORD bytesRead; 459 | int i; 460 | 461 | ftStatus = FT_GetQueueStatus(ftHandle,&bytesToRead); 462 | if (ftStatus != FT_OK) return 0; 463 | 464 | if ((DWORD)maxBytes < bytesToRead) bytesToRead = maxBytes; 465 | ftStatus = FT_Read(ftHandle, buffer, bytesToRead, &bytesRead); 466 | if (ftStatus == FT_OK) { 467 | DEBUG(PRLog(kPRLogVerbose,"Read %d bytes:\n",bytesRead)); 468 | for (i=0; (DWORD)i 501 | 502 | static bool ftdiInitialized; 503 | static ftdi_context ftdic; 504 | 505 | 506 | PRResult PRHardwareOpen() 507 | { 508 | int32_t i=0; 509 | PRResult rc; 510 | struct ftdi_device_list *devlist, *curdev; 511 | char manufacturer[128], description[128]; 512 | 513 | ftdiInitialized = false; 514 | 515 | // Open the FTDI device 516 | if (ftdi_init(&ftdic) != 0) 517 | { 518 | PRSetLastErrorText("Failed to initialize FTDI."); 519 | return kPRFailure; 520 | } 521 | 522 | // Find all FTDI devices 523 | // This is very basic and really only expects to see 1 device. It needs to be 524 | // smarter. At the very least, it should check some register on the P-ROC versus 525 | // an input parameter to ensure the software is set up for the same architecture as 526 | // the P-ROC (Stern vs WPC). Otherwise, it's possible to drive the coils the wrong 527 | // polarity and blow fuses or fry transistors and all other sorts of badness. 528 | 529 | // We first enumerate all of the devices: 530 | int numDevices = ftdi_usb_find_all(&ftdic, &devlist, FTDI_VENDOR_ID, FTDI_FT245RL_PRODUCT_ID); 531 | if (numDevices <=0) numDevices = ftdi_usb_find_all(&ftdic, &devlist, FTDI_VENDOR_ID, FTDI_FT240X_PRODUCT_ID); 532 | if (numDevices < 0) { 533 | PRSetLastErrorText("ftdi_usb_find_all failed: %d: %s", numDevices, ftdi_get_error_string(&ftdic)); 534 | ftdi_deinit(&ftdic); 535 | return kPRFailure; 536 | } 537 | else { 538 | DEBUG(PRLog(kPRLogInfo, "Number of FTDI devices found: %d\n", numDevices)); 539 | 540 | for (curdev = devlist; curdev != NULL; i++) { 541 | DEBUG(PRLog(kPRLogInfo, "Checking device %d\n", i)); 542 | if ((rc = (int32_t)ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) { 543 | DEBUG(PRLog(kPRLogInfo, " ftdi_usb_get_strings failed: %d: %s\n", rc, ftdi_get_error_string(&ftdic))); 544 | } 545 | else { 546 | DEBUG(PRLog(kPRLogInfo, " Device #%d:\n", i)); 547 | DEBUG(PRLog(kPRLogInfo, " Manufacturer: %s\n", manufacturer)); 548 | DEBUG(PRLog(kPRLogInfo, " Description: %s\n", description)); 549 | } 550 | curdev = curdev->next; 551 | } 552 | 553 | } 554 | 555 | // Don't need the device list anymore 556 | ftdi_list_free (&devlist); 557 | 558 | if (((rc = (int32_t)ftdi_usb_open(&ftdic, FTDI_VENDOR_ID, FTDI_FT245RL_PRODUCT_ID)) < 0) && ((rc = (int32_t)ftdi_usb_open(&ftdic, FTDI_VENDOR_ID, FTDI_FT240X_PRODUCT_ID)) < 0)) 559 | { 560 | PRSetLastErrorText("Unable to open ftdi device: %d: %s", rc, ftdi_get_error_string(&ftdic)); 561 | return kPRFailure; 562 | } 563 | else 564 | { 565 | rc = kPRSuccess; 566 | //if (ftdic.type == TYPE_R) { 567 | if (1) { 568 | uint32_t chipid; 569 | ftdi_read_chipid(&ftdic,&chipid); 570 | DEBUG(PRLog(kPRLogInfo, "FTDI chip_id = 0x%x\n", chipid)); 571 | // Set some defaults: 572 | ftdi_read_data_set_chunksize(&ftdic, 4096); 573 | ftdi_set_latency_timer(&ftdic, 2); // This helps make reads much faster. 16 appeared to be the default. 574 | ftdiInitialized = true; 575 | return kPRSuccess; 576 | } 577 | else 578 | { 579 | PRSetLastErrorText("FTDI type != TYPE_R: 0x%x", ftdic.type); 580 | return kPRFailure; 581 | } 582 | } 583 | } 584 | void PRHardwareClose() 585 | { 586 | if (ftdiInitialized) 587 | { 588 | ftdi_usb_close(&ftdic); 589 | ftdi_deinit(&ftdic); 590 | } 591 | } 592 | int PRHardwareRead(uint8_t *buffer, int maxBytes) 593 | { 594 | //return 0; 595 | return ftdi_read_data(&ftdic, buffer, maxBytes); 596 | } 597 | int PRHardwareWrite(uint8_t *buffer, int bytes) 598 | { 599 | //return 0; 600 | return ftdi_write_data(&ftdic, buffer, bytes); 601 | } 602 | 603 | #endif 604 | -------------------------------------------------------------------------------- /src/PRHardware.h: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following 12 | * conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | * OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | #ifndef PINPROC_PRHARDWARE_H 27 | #define PINPROC_PRHARDWARE_H 28 | #if !defined(__GNUC__) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4) // GCC supports "pragma once" correctly since 3.4 29 | #pragma once 30 | #endif 31 | 32 | #include 33 | #include "pinproc.h" 34 | 35 | #if defined(__WIN32__) || defined(_WIN32) 36 | #include 37 | #define PRSleep(milliseconds) Sleep(milliseconds) 38 | #else 39 | #define PRSleep(milliseconds) usleep(milliseconds*1000) 40 | #endif 41 | 42 | const int32_t FTDI_VENDOR_ID = 0x0403; 43 | const int32_t FTDI_FT245RL_PRODUCT_ID = 0x6001; 44 | const int32_t FTDI_FT240X_PRODUCT_ID = 0x6015; 45 | 46 | //const int32_t FTDI_BUFFER_SIZE = 2048; 47 | const int32_t FTDI_BUFFER_SIZE = 8192; 48 | 49 | 50 | typedef enum PRLEDRegisterType { 51 | kPRLEDRegisterTypeLEDIndex = 0, 52 | kPRLEDRegisterTypeColor = 1, 53 | kPRLEDRegisterTypeFadeColor = 2, 54 | kPRLEDRegisterTypeFadeRateLow = 3, 55 | kPRLEDRegisterTypeFadeRateHigh = 4 56 | } PRPDLEDRegisterType; 57 | 58 | typedef struct PRSwitchRuleInternal { 59 | uint8_t switchNum; /**< Number of the physical switch, or for linked driver changes the virtual switch number (224 and up). */ 60 | PREventType eventType; /**< The event type that this rule generates. Determines closed/open, debounced/non-debounced. */ 61 | bool_t reloadActive; 62 | bool_t notifyHost; 63 | bool_t changeOutput; /**< True if this switch rule should affect a driver output change. */ 64 | bool_t linkActive; /**< True if this switch rule has additional linked driver updates. */ 65 | uint16_t linkIndex; /**< Switch rule index ({debounce,state,switchNum}) of the linked driver update rule. */ 66 | PRDriverState driver; /**< Driver state change to affect once this rule is triggered. */ 67 | } PRSwitchRuleInternal; 68 | 69 | 70 | bool_t IsStern (uint32_t hardware_data); 71 | uint32_t CreateRegRequestWord( uint32_t select, uint32_t addr, uint32_t num_words); 72 | uint32_t CreateBurstCommand ( uint32_t select, uint32_t addr, uint32_t num_words); 73 | int32_t CreateManagerUpdateConfigBurst ( uint32_t * burst, PRManagerConfig *manager_config); 74 | int32_t CreateDriverUpdateGlobalConfigBurst ( uint32_t * burst, PRDriverGlobalConfig *driver_globals); 75 | int32_t CreateDriverUpdateGroupConfigBurst ( uint32_t * burst, PRDriverGroupConfig *driver_group); 76 | int32_t CreateDriverUpdateBurst ( uint32_t * burst, PRDriverState *driver); 77 | uint32_t CreateDriverAuxCommand ( PRDriverAuxCommand command); 78 | 79 | int32_t CreateWatchdogConfigBurst ( uint32_t * burst, bool_t watchdogExpired, 80 | bool_t watchdogEnable, uint16_t watchdogResetTime); 81 | 82 | int32_t CreateDMDUpdateConfigBurst ( uint32_t * burst, PRDMDConfig *dmd_config); 83 | 84 | int32_t CreateSwitchUpdateConfigBurst ( uint32_t * burst, PRSwitchConfig *switchConfig); 85 | int32_t CreateSwitchUpdateRulesBurst ( uint32_t * burst, PRSwitchRuleInternal *rule_record, bool_t drive_outputs_now); 86 | 87 | void ParseSwitchRuleIndex(uint16_t index, uint8_t *switchNum, PREventType *eventType); 88 | int16_t CreateSwitchRuleIndex(uint8_t switchNum, PREventType eventType); 89 | int32_t CreateSwitchRuleAddr(uint8_t switchNum, PREventType eventType, bool_t drive_outputs_now); 90 | 91 | int32_t CreateJTAGLatchOutputsBurst ( uint32_t * burst, PRJTAGOutputs *jtagOutputs); 92 | int32_t CreateJTAGForceOutputsBurst ( uint32_t * burst, PRJTAGOutputs *jtagOutputs); 93 | int32_t CreateJTAGShiftTDODataBurst ( uint32_t * burst, uint16_t numBits, bool_t dataBlockComplete); 94 | 95 | void FillPDBCommand(uint8_t command, uint8_t boardAddr, PRLEDRegisterType reg, uint8_t value, uint32_t * pData); 96 | 97 | PRResult PRHardwareOpen(); 98 | void PRHardwareClose(); 99 | int PRHardwareRead(uint8_t *buffer, int maxBytes); 100 | int PRHardwareWrite(uint8_t *buffer, int bytes); 101 | 102 | #endif /* PINPROC_PRHARDWARE_H */ 103 | -------------------------------------------------------------------------------- /src/pinproc.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * The MIT License 3 | * Copyright (c) 2009 Gerry Stellenberg, Adam Preble 4 | * 5 | * Permission is hereby granted, free of charge, to any person 6 | * obtaining a copy of this software and associated documentation 7 | * files (the "Software"), to deal in the Software without 8 | * restriction, including without limitation the rights to use, 9 | * copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following 12 | * conditions: 13 | * 14 | * The above copyright notice and this permission notice shall be 15 | * included in all copies or substantial portions of the Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 18 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 19 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 20 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 21 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 22 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 23 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 | * OTHER DEALINGS IN THE SOFTWARE. 25 | */ 26 | /* 27 | * pinproc.cpp 28 | * libpinproc 29 | */ 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "PRDevice.h" 37 | 38 | #if defined(_MSC_VER) && (_MSC_VER < 1400) 39 | #define vsnprintf _vsnprintf 40 | #endif 41 | 42 | #define MAX_TEXT (1024) 43 | 44 | typedef void (*PRLogCallback)(PRLogLevel level, const char *text); 45 | 46 | PRLogCallback logCallback = NULL; 47 | //PRLogLevel logLevel = kPRLogError; 48 | PRLogLevel logLevel = kPRLogError; 49 | 50 | void PRLog(PRLogLevel level, const char *format, ...) 51 | { 52 | if (level < logLevel) 53 | return; 54 | 55 | char line[MAX_TEXT]; 56 | va_list ap; 57 | va_start(ap, format); 58 | vsnprintf(line, MAX_TEXT, format, ap); 59 | if (logCallback) 60 | logCallback(level, line); 61 | else 62 | fprintf(stderr, "%s", line); 63 | } 64 | 65 | void PRLogSetCallback(PRLogCallback callback) 66 | { 67 | logCallback = callback; 68 | } 69 | 70 | void PRLogSetLevel(PRLogLevel level) 71 | { 72 | logLevel = level; 73 | } 74 | 75 | char lastErrorText[MAX_TEXT]; 76 | 77 | void PRSetLastErrorText(const char *format, ...) 78 | { 79 | va_list ap; 80 | va_start(ap, format); 81 | vsnprintf(lastErrorText, MAX_TEXT, format, ap); 82 | PRLog(kPRLogError, "%s\n", lastErrorText); 83 | } 84 | 85 | const char *PRGetLastErrorText(void) 86 | { 87 | return lastErrorText; 88 | } 89 | 90 | #define handleAsDevice ((PRDevice*)handle) 91 | 92 | /** Create a new P-ROC device handle. Only one handle per device may be created. This handle must be destroyed with PRDelete() when it is no longer needed. */ 93 | PRHandle PRCreate(PRMachineType machineType) 94 | { 95 | PRDevice *device = PRDevice::Create(machineType); 96 | if (device == NULL) 97 | return kPRHandleInvalid; 98 | else 99 | return device; 100 | } 101 | /** Destroys an existing P-ROC device handle. */ 102 | void PRDelete(PRHandle handle) 103 | { 104 | if (handle != kPRHandleInvalid) 105 | delete (PRDevice*)handle; 106 | } 107 | 108 | /** Resets internally maintained driver and switch rule structures and optionally writes those to the P-ROC device. */ 109 | PRResult PRReset(PRHandle handle, uint32_t resetFlags) 110 | { 111 | return handleAsDevice->Reset(resetFlags); 112 | } 113 | 114 | // I/O 115 | 116 | /** Flush all pending write data out to the P-ROC */ 117 | PRResult PRFlushWriteData(PRHandle handle) 118 | { 119 | return handleAsDevice->FlushWriteData(); 120 | } 121 | 122 | /** Write data out to the P-ROC immediately (does not require a call to PRFlushWriteData). */ 123 | PRResult PRWriteData(PRHandle handle, uint32_t moduleSelect, uint32_t startingAddr, int32_t numWriteWords, uint32_t * writeBuffer) 124 | { 125 | return handleAsDevice->WriteDataRaw(moduleSelect, startingAddr, numWriteWords, writeBuffer); 126 | } 127 | 128 | /** Write data buffered to P-ROC (does require a call to PRFlushWriteData). */ 129 | PRResult PRWriteDataUnbuffered(PRHandle handle, uint32_t moduleSelect, uint32_t startingAddr, int32_t numWriteWords, uint32_t * writeBuffer) 130 | { 131 | return handleAsDevice->WriteDataRawUnbuffered(moduleSelect, startingAddr, numWriteWords, writeBuffer); 132 | } 133 | 134 | /** Read data from the P-ROC. */ 135 | PRResult PRReadData(PRHandle handle, uint32_t moduleSelect, uint32_t startingAddr, int32_t numReadWords, uint32_t * readBuffer) 136 | { 137 | return handleAsDevice->ReadDataRaw(moduleSelect, startingAddr, numReadWords, readBuffer); 138 | } 139 | 140 | // Events 141 | 142 | /** Get all of the available events that have been received. */ 143 | int PRGetEvents(PRHandle handle, PREvent *eventsOut, int maxEvents) 144 | { 145 | return handleAsDevice->GetEvents(eventsOut, maxEvents); 146 | } 147 | 148 | // Manager 149 | PRResult PRManagerUpdateConfig(PRHandle handle, PRManagerConfig *managerConfig) 150 | { 151 | return handleAsDevice->ManagerUpdateConfig(managerConfig); 152 | } 153 | 154 | // Drivers 155 | PRResult PRDriverUpdateGlobalConfig(PRHandle handle, PRDriverGlobalConfig *driverGlobalConfig) 156 | { 157 | return handleAsDevice->DriverUpdateGlobalConfig(driverGlobalConfig); 158 | } 159 | PRResult PRDriverGetGroupConfig(PRHandle handle, uint8_t groupNum, PRDriverGroupConfig *driverGroupConfig) 160 | { 161 | return handleAsDevice->DriverGetGroupConfig(groupNum, driverGroupConfig); 162 | } 163 | PRResult PRDriverUpdateGroupConfig(PRHandle handle, PRDriverGroupConfig *driverGroupConfig) 164 | { 165 | return handleAsDevice->DriverUpdateGroupConfig(driverGroupConfig); 166 | } 167 | PRResult PRDriverGetState(PRHandle handle, uint8_t driverNum, PRDriverState *driverState) 168 | { 169 | return handleAsDevice->DriverGetState(driverNum, driverState); 170 | } 171 | PRResult PRDriverUpdateState(PRHandle handle, PRDriverState *driverState) 172 | { 173 | return handleAsDevice->DriverUpdateState(driverState); 174 | } 175 | PRResult PRDriverLoadMachineTypeDefaults(PRHandle handle, PRMachineType machineType) 176 | { 177 | return handleAsDevice->DriverLoadMachineTypeDefaults(machineType); 178 | } 179 | 180 | // Driver Group Helper functions: 181 | PRResult PRDriverGroupDisable(PRHandle handle, uint8_t groupNum) 182 | { 183 | PRDriverGroupConfig driverGroup; 184 | handleAsDevice->DriverGetGroupConfig(groupNum, &driverGroup); 185 | PRDriverGroupStateDisable(&driverGroup); 186 | return handleAsDevice->DriverUpdateGroupConfig(&driverGroup); 187 | } 188 | // Driver Helper functions: 189 | PRResult PRDriverDisable(PRHandle handle, uint8_t driverNum) 190 | { 191 | PRDriverState driver; 192 | handleAsDevice->DriverGetState(driverNum, &driver); 193 | PRDriverStateDisable(&driver); 194 | return handleAsDevice->DriverUpdateState(&driver); 195 | } 196 | PRResult PRDriverPulse(PRHandle handle, uint8_t driverNum, uint8_t milliseconds) 197 | { 198 | PRDriverState driver; 199 | handleAsDevice->DriverGetState(driverNum, &driver); 200 | PRDriverStatePulse(&driver, milliseconds); 201 | return handleAsDevice->DriverUpdateState(&driver); 202 | } 203 | PRResult PRDriverFuturePulse(PRHandle handle, uint8_t driverNum, uint8_t milliseconds, uint32_t futureTime) 204 | { 205 | PRDriverState driver; 206 | handleAsDevice->DriverGetState(driverNum, &driver); 207 | PRDriverStateFuturePulse(&driver, milliseconds, futureTime); 208 | return handleAsDevice->DriverUpdateState(&driver); 209 | } 210 | PRResult PRDriverSchedule(PRHandle handle, uint8_t driverNum, uint32_t schedule, uint8_t cycleSeconds, bool_t now) 211 | { 212 | PRDriverState driver; 213 | handleAsDevice->DriverGetState(driverNum, &driver); 214 | PRDriverStateSchedule(&driver, schedule, cycleSeconds, now); 215 | return handleAsDevice->DriverUpdateState(&driver); 216 | } 217 | PRResult PRDriverPatter(PRHandle handle, uint8_t driverNum, uint8_t millisecondsOn, uint8_t millisecondsOff, uint8_t originalOnTime, bool_t now) 218 | { 219 | PRDriverState driver; 220 | handleAsDevice->DriverGetState(driverNum, &driver); 221 | PRDriverStatePatter(&driver, millisecondsOn, millisecondsOff, originalOnTime, now); 222 | return handleAsDevice->DriverUpdateState(&driver); 223 | } 224 | PRResult PRDriverPulsedPatter(PRHandle handle, uint8_t driverNum, uint8_t millisecondsOn, uint8_t millisecondsOff, uint8_t duration, bool_t now) 225 | { 226 | PRDriverState driver; 227 | handleAsDevice->DriverGetState(driverNum, &driver); 228 | PRDriverStatePulsedPatter(&driver, millisecondsOn, millisecondsOff, duration, now); 229 | return handleAsDevice->DriverUpdateState(&driver); 230 | } 231 | PRResult PRDriverAuxSendCommands(PRHandle handle, PRDriverAuxCommand * commands, uint8_t numCommands, uint8_t startingAddr) 232 | { 233 | return handleAsDevice->DriverAuxSendCommands(commands, numCommands, startingAddr); 234 | } 235 | 236 | void PRDriverAuxPrepareOutput(PRDriverAuxCommand *auxCommand, uint8_t data, uint8_t extraData, uint8_t enables, bool_t muxEnables, uint16_t delayTime) 237 | { 238 | auxCommand->active = true; 239 | auxCommand->data = data; 240 | auxCommand->extraData = extraData; 241 | auxCommand->enables = enables; 242 | auxCommand->muxEnables = muxEnables; 243 | auxCommand->command = kPRDriverAuxCmdOutput; 244 | auxCommand->delayTime = delayTime; 245 | } 246 | 247 | void PRDriverAuxPrepareDelay(PRDriverAuxCommand *auxCommand, uint16_t delayTime) 248 | { 249 | auxCommand->active = true; 250 | auxCommand->delayTime = delayTime; 251 | auxCommand->command = kPRDriverAuxCmdDelay; 252 | auxCommand->data = 0; 253 | auxCommand->extraData = 0; 254 | auxCommand->enables = 0; 255 | auxCommand->muxEnables = false; 256 | } 257 | 258 | void PRDriverAuxPrepareJump(PRDriverAuxCommand *auxCommand, uint8_t jumpAddr) 259 | { 260 | auxCommand->active = true; 261 | auxCommand->jumpAddr = jumpAddr; 262 | auxCommand->command = kPRDriverAuxCmdJump; 263 | auxCommand->data = 0; 264 | auxCommand->extraData = 0; 265 | auxCommand->enables = 0; 266 | auxCommand->muxEnables = false; 267 | } 268 | 269 | void PRDriverAuxPrepareDisable(PRDriverAuxCommand *auxCommand) 270 | { 271 | auxCommand->active = false; 272 | auxCommand->data = 0; 273 | auxCommand->extraData = 0; 274 | auxCommand->enables = 0; 275 | auxCommand->muxEnables = false; 276 | } 277 | 278 | PRResult PRDriverWatchdogTickle(PRHandle handle) 279 | { 280 | return handleAsDevice->DriverWatchdogTickle(); 281 | } 282 | 283 | void PRDriverGroupStateDisable(PRDriverGroupConfig *driverGroup) 284 | { 285 | driverGroup->active = false; 286 | } 287 | void PRDriverStateDisable(PRDriverState *driver) 288 | { 289 | driver->state = 0; 290 | driver->timeslots = 0; 291 | driver->waitForFirstTimeSlot = false; 292 | driver->outputDriveTime = 0; 293 | driver->patterOnTime = 0; 294 | driver->patterOffTime = 0; 295 | driver->patterEnable = false; 296 | driver->futureEnable = false; 297 | } 298 | void PRDriverStatePulse(PRDriverState *driver, uint8_t milliseconds) 299 | { 300 | driver->state = 1; 301 | driver->timeslots = 0; 302 | driver->waitForFirstTimeSlot = false; 303 | driver->outputDriveTime = milliseconds; 304 | driver->patterOnTime = 0; 305 | driver->patterOffTime = 0; 306 | driver->patterEnable = false; 307 | driver->futureEnable = false; 308 | } 309 | void PRDriverStateFuturePulse(PRDriverState *driver, uint8_t milliseconds, uint32_t futureTime) 310 | { 311 | driver->state = 1; 312 | driver->timeslots = futureTime; 313 | driver->waitForFirstTimeSlot = false; 314 | driver->outputDriveTime = milliseconds; 315 | driver->patterOnTime = 0; 316 | driver->patterOffTime = 0; 317 | driver->patterEnable = false; 318 | driver->futureEnable = true; 319 | } 320 | void PRDriverStateSchedule(PRDriverState *driver, uint32_t schedule, uint8_t cycleSeconds, bool_t now) 321 | { 322 | driver->state = schedule != 0; 323 | driver->timeslots = schedule; 324 | driver->waitForFirstTimeSlot = !now; 325 | driver->outputDriveTime = cycleSeconds; 326 | driver->patterOnTime = 0; 327 | driver->patterOffTime = 0; 328 | driver->patterEnable = false; 329 | driver->futureEnable = false; 330 | } 331 | void PRDriverStatePatter(PRDriverState *driver, uint8_t millisecondsOn, uint8_t millisecondsOff, uint8_t originalOnTime, bool_t now) 332 | { 333 | driver->state = true; 334 | driver->timeslots = 0; 335 | driver->waitForFirstTimeSlot = !now; 336 | driver->outputDriveTime = originalOnTime; 337 | driver->patterOnTime = millisecondsOn; 338 | driver->patterOffTime = millisecondsOff; 339 | driver->patterEnable = true; 340 | driver->futureEnable = false; 341 | } 342 | 343 | void PRDriverStatePulsedPatter(PRDriverState *driver, uint8_t millisecondsOn, uint8_t millisecondsOff, uint8_t patterTime, bool_t now) 344 | { 345 | driver->state = false; 346 | driver->timeslots = 0; 347 | driver->waitForFirstTimeSlot = !now; 348 | driver->outputDriveTime = patterTime; 349 | driver->patterOnTime = millisecondsOn; 350 | driver->patterOffTime = millisecondsOff; 351 | driver->patterEnable = true; 352 | driver->futureEnable = false; 353 | } 354 | 355 | uint16_t PRDecode(PRMachineType machineType, const char *str) 356 | { 357 | uint16_t x; 358 | 359 | if (str == NULL) 360 | return 0; 361 | 362 | if ( strlen(str) == 3 ) 363 | x = (str[1]-'0') * 10 + (str[2]-'0'); 364 | else if ( strlen(str) == 4) 365 | x = (str[2]-'0') * 10 + (str[3]-'0'); 366 | else return atoi(str); 367 | 368 | if ((machineType == kPRMachineWPC) || 369 | (machineType == kPRMachineWPC95) || 370 | (machineType == kPRMachineWPCAlphanumeric)) 371 | { 372 | switch (str[0]) 373 | { 374 | case 'F': 375 | case 'f': 376 | switch (str[1]) 377 | { 378 | case 'L': 379 | case 'l': 380 | switch (str[2]) 381 | { 382 | case 'R': 383 | case 'r': 384 | switch (str[3]) 385 | { 386 | case 'M': 387 | case 'm': 388 | return 32; 389 | default: 390 | return 33; 391 | } 392 | default: 393 | switch (str[3]) 394 | { 395 | case 'M': 396 | case 'm': 397 | return 34; 398 | default: 399 | return 35; 400 | } 401 | } 402 | default: 403 | switch (str[2]) 404 | { 405 | case 'R': 406 | case 'r': 407 | switch (str[3]) 408 | { 409 | case 'M': 410 | case 'm': 411 | return 36; 412 | default: 413 | return 37; 414 | } 415 | default: 416 | switch (str[3]) 417 | { 418 | case 'M': 419 | case 'm': 420 | return 38; 421 | default: 422 | return 39; 423 | } 424 | } 425 | } 426 | 427 | case 'L': 428 | case 'l': 429 | return 80 + 8 * ((x / 10) - 1) + ((x % 10) -1); 430 | case 'C': 431 | case 'c': 432 | if (x <= 28) 433 | return x + 39; 434 | else if (x <= 36) 435 | return x + 3; 436 | else if (x <= 44) 437 | { 438 | if (machineType == kPRMachineWPC95) 439 | //return x + 7; 440 | return x + 31; 441 | else 442 | return x + 107; // WPC 37-44 use 8-driver board (mapped to drivers 144-151) 443 | } 444 | else return x + 108; 445 | case 'G': 446 | case 'g': 447 | return x + 71; 448 | case 'S': 449 | case 's': 450 | { 451 | switch (str[1]) 452 | { 453 | case 'D': 454 | case 'd': 455 | return 8 + ((str[2]-'0') - 1); 456 | case 'F': 457 | case 'f': 458 | return (str[2]-'0') - 1; 459 | default: 460 | return 32 + 16 * ((x / 10) - 1) + ((x % 10) - 1); 461 | } 462 | } 463 | } 464 | } 465 | else if (machineType == kPRMachineSternSAM) 466 | { 467 | switch (str[0]) 468 | { 469 | case 'L': 470 | case 'l': 471 | return 80 + 16 * (7 - ((x - 1) % 8)) + (x - 1) / 8; 472 | case 'C': 473 | case 'c': 474 | return x + 31; 475 | case 'S': 476 | case 's': 477 | { 478 | switch (str[1]) 479 | { 480 | case 'D': 481 | case 'd': 482 | if (strlen(str) == 3) 483 | return (str[2]-'0') + 7; 484 | else return x + 7; 485 | default: 486 | if ((x - 1) % 16 < 8) 487 | return 32 + 8 * ((x - 1) / 8) + (7 - ((x - 1) % 8)); 488 | else 489 | return 32 + (x - 1); 490 | } 491 | } 492 | } 493 | } 494 | else if (machineType == kPRMachineSternWhitestar) 495 | { 496 | switch (str[0]) 497 | { 498 | case 'L': 499 | case 'l': 500 | return 80 + 16 * (7 - ((x - 1) % 8)) + (x - 1) / 8; 501 | case 'C': 502 | case 'c': 503 | return x + 31; 504 | case 'S': 505 | case 's': 506 | { 507 | switch (str[1]) 508 | { 509 | case 'D': 510 | case 'd': 511 | if (strlen(str) == 3) 512 | return (str[2]-'0') + 7; 513 | else return x + 7; 514 | default: 515 | return 32 + 16 * (((x-1) / 8)) + (7-((x-1) % 8)); 516 | } 517 | } 518 | } 519 | } 520 | return atoi(str); 521 | } 522 | 523 | // Switches 524 | 525 | PRResult PRSwitchUpdateConfig(PRHandle handle, PRSwitchConfig *switchConfig) 526 | { 527 | return handleAsDevice->SwitchUpdateConfig(switchConfig); 528 | } 529 | 530 | PRResult PRSwitchUpdateRule(PRHandle handle, uint8_t switchNum, PREventType eventType, PRSwitchRule *rule, PRDriverState *linkedDrivers, int numDrivers, bool_t drive_outputs_now) 531 | { 532 | return handleAsDevice->SwitchUpdateRule(switchNum, eventType, rule, linkedDrivers, numDrivers, drive_outputs_now); 533 | } 534 | 535 | PRResult PRSwitchGetStates(PRHandle handle, PREventType * switchStates, uint16_t numSwitches) 536 | { 537 | return handleAsDevice->SwitchGetStates(switchStates, numSwitches); 538 | } 539 | 540 | // DMD 541 | 542 | int32_t PRDMDUpdateConfig(PRHandle handle, PRDMDConfig *dmdConfig) 543 | { 544 | return handleAsDevice->DMDUpdateConfig(dmdConfig); 545 | } 546 | PRResult PRDMDDraw(PRHandle handle, uint8_t * dots) 547 | { 548 | return handleAsDevice->DMDDraw(dots); 549 | } 550 | 551 | // JTAG 552 | 553 | PRResult PRJTAGDriveOutputs(PRHandle handle, PRJTAGOutputs * jtagOutputs, bool_t toggleClk) 554 | { 555 | return handleAsDevice->PRJTAGDriveOutputs(jtagOutputs, toggleClk); 556 | } 557 | 558 | PRResult PRJTAGWriteTDOMemory(PRHandle handle, uint16_t tableOffset, uint16_t numWords, uint32_t * tdoData) 559 | { 560 | return handleAsDevice->PRJTAGWriteTDOMemory(tableOffset, numWords, tdoData); 561 | } 562 | 563 | PRResult PRJTAGShiftTDOData(PRHandle handle, uint16_t numBits, bool_t dataBlockComplete) 564 | { 565 | return handleAsDevice->PRJTAGShiftTDOData(numBits, dataBlockComplete); 566 | } 567 | 568 | PRResult PRJTAGReadTDIMemory(PRHandle handle, uint16_t tableOffset, uint16_t numWords, uint32_t * tdiData) 569 | { 570 | return handleAsDevice->PRJTAGReadTDIMemory(tableOffset, numWords, tdiData); 571 | } 572 | 573 | PRResult PRJTAGGetStatus(PRHandle handle, PRJTAGStatus * status) 574 | { 575 | return handleAsDevice->PRJTAGGetStatus(status); 576 | } 577 | 578 | PRResult PRLEDColor(PRHandle handle, PRLED * pLED, uint8_t color) 579 | { 580 | return handleAsDevice->PRLEDColor(pLED, color); 581 | } 582 | 583 | PRResult PRLEDFade(PRHandle handle, PRLED * pLED, uint8_t fadeColor, uint16_t fadeRate) 584 | { 585 | return handleAsDevice->PRLEDFade(pLED, fadeColor, fadeRate); 586 | } 587 | 588 | PRResult PRLEDFadeColor(PRHandle handle, PRLED * pLED, uint8_t fadeColor) 589 | { 590 | return handleAsDevice->PRLEDFadeColor(pLED, fadeColor); 591 | } 592 | 593 | PRResult PRLEDFadeRate(PRHandle handle, uint8_t boardAddr, uint16_t fadeRate) 594 | { 595 | return handleAsDevice->PRLEDFadeRate(boardAddr, fadeRate); 596 | } 597 | 598 | PRResult PRLEDRGBColor(PRHandle handle, PRLEDRGB * pLED, uint32_t color) 599 | { 600 | return handleAsDevice->PRLEDRGBColor(pLED, color); 601 | } 602 | 603 | PRResult PRLEDRGBFade(PRHandle handle, PRLEDRGB * pLED, uint32_t fadeColor, uint16_t fadeRate) 604 | { 605 | return handleAsDevice->PRLEDRGBFade(pLED, fadeColor, fadeRate); 606 | } 607 | 608 | PRResult PRLEDRGBFadeColor(PRHandle handle, PRLEDRGB * pLED, uint32_t fadeColor) 609 | { 610 | return handleAsDevice->PRLEDRGBFadeColor(pLED, fadeColor); 611 | } 612 | -------------------------------------------------------------------------------- /src/pinproc.def: -------------------------------------------------------------------------------- 1 | LIBRARY "pinproc.dll" 2 | 3 | DESCRIPTION "PinPROC library. See http://www.pinballcontrollers.com/" 4 | 5 | EXPORTS 6 | ; since API/SO version 0.9 7 | PRCreate @1 8 | PRDMDDraw @2 9 | PRDMDUpdateConfig @3 10 | PRDecode @4 11 | PRDelete @5 12 | PRDriverAuxPrepareDelay @6 13 | PRDriverAuxPrepareDisable @7 14 | PRDriverAuxPrepareJump @8 15 | PRDriverAuxPrepareOutput @9 16 | PRDriverAuxSendCommands @10 17 | PRDriverDisable @11 18 | PRDriverGetGroupConfig @12 19 | PRDriverGetState @13 20 | PRDriverGroupDisable @14 21 | PRDriverGroupStateDisable @15 22 | PRDriverLoadMachineTypeDefaults @16 23 | PRDriverPatter @17 24 | PRDriverPulse @18 25 | PRDriverPulsedPatter @19 26 | PRDriverSchedule @20 27 | PRDriverStateDisable @21 28 | PRDriverStatePatter @22 29 | PRDriverStatePulse @23 30 | PRDriverStatePulsedPatter @24 31 | PRDriverStateSchedule @25 32 | PRDriverUpdateGlobalConfig @26 33 | PRDriverUpdateGroupConfig @27 34 | PRDriverUpdateState @28 35 | PRDriverWatchdogTickle @29 36 | PRFlushWriteData @30 37 | PRGetEvents @31 38 | PRGetLastErrorText @32 39 | PRJTAGDriveOutputs @33 40 | PRJTAGGetStatus @34 41 | PRJTAGReadTDIMemory @35 42 | PRJTAGShiftTDOData @36 43 | PRJTAGWriteTDOMemory @37 44 | PRLogSetCallback @38 45 | PRLogSetLevel @39 46 | PRManagerUpdateConfig @40 47 | PRReadData @41 48 | PRReset @42 49 | PRSwitchGetStates @43 50 | PRSwitchUpdateConfig @44 51 | PRSwitchUpdateRule @45 52 | PRWriteData @46 53 | -------------------------------------------------------------------------------- /utils/pinprocfw/Makefile: -------------------------------------------------------------------------------- 1 | CC = g++ 2 | RM = rm -f 3 | CFLAGS = $(ARCH) -c -Wall -I../../include 4 | LDFLAGS = $(ARCH) -L../../bin 5 | 6 | uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') 7 | 8 | PINPROCFW = ../../bin/pinprocfw 9 | LIBPINPROC = ../../bin/libpinproc.a 10 | SRCS = pinprocfw.cpp lenval.cpp 11 | OBJS := $(SRCS:.cpp=.o) 12 | INCLUDES = ../../include/pinproc.h 13 | 14 | LIBS = usb pinproc 15 | ifneq ($(uname_s),Windows) # not Windows 16 | LIBS += ftdi 17 | endif 18 | ifeq ($(uname_s),Windows) 19 | LIBS = ftd2xx 20 | endif 21 | 22 | pinprocfw: $(PINPROCFW) 23 | 24 | $(PINPROCFW): $(OBJS) $(LIBPINPROC) 25 | $(CC) $(LDFLAGS) $(OBJS) $(addprefix -l,$(LIBS)) -o $@ 26 | 27 | .cpp.o: 28 | $(CC) $(CFLAGS) -o $@ $< 29 | 30 | clean: 31 | $(RM) $(OBJS) 32 | 33 | .PHONY: clean pinprocfw 34 | 35 | depend: $(SRCS) 36 | makedepend $(INCLUDES) $^ 37 | 38 | # DO NOT DELETE THIS LINE -- make depend needs it 39 | 40 | pinprocfw.o: lenval.h ../../include/pinproc.h 41 | lenval.o: lenval.h pinprocfw.h 42 | -------------------------------------------------------------------------------- /utils/pinprocfw/lenval.cpp: -------------------------------------------------------------------------------- 1 | /*******************************************************/ 2 | /* file: lenval.c */ 3 | /* abstract: This file contains routines for using */ 4 | /* the lenVal data structure. */ 5 | /*******************************************************/ 6 | #include "lenval.h" 7 | #include "pinprocfw.h" 8 | 9 | /***************************************************************************** 10 | * Function: value 11 | * Description: Extract the long value from the lenval array. 12 | * Parameters: plvValue - ptr to lenval. 13 | * Returns: long - the extracted value. 14 | *****************************************************************************/ 15 | long value( lenVal* plvValue ) 16 | { 17 | long lValue; /* result to hold the accumulated result */ 18 | short sIndex; 19 | 20 | lValue = 0; 21 | for ( sIndex = 0; sIndex < plvValue->len ; ++sIndex ) 22 | { 23 | lValue <<= 8; /* shift the accumulated result */ 24 | lValue |= plvValue->val[ sIndex]; /* get the last byte first */ 25 | } 26 | 27 | return( lValue ); 28 | } 29 | 30 | /***************************************************************************** 31 | * Function: initLenVal 32 | * Description: Initialize the lenval array with the given value. 33 | * Assumes lValue is less than 256. 34 | * Parameters: plv - ptr to lenval. 35 | * lValue - the value to set. 36 | * Returns: void. 37 | *****************************************************************************/ 38 | void initLenVal( lenVal* plv, 39 | long lValue ) 40 | { 41 | plv->len = 1; 42 | plv->val[0] = (unsigned char)lValue; 43 | } 44 | 45 | /***************************************************************************** 46 | * Function: EqualLenVal 47 | * Description: Compare two lenval arrays with an optional mask. 48 | * Parameters: plvTdoExpected - ptr to lenval #1. 49 | * plvTdoCaptured - ptr to lenval #2. 50 | * plvTdoMask - optional ptr to mask (=0 if no mask). 51 | * Returns: short - 0 = mismatch; 1 = equal. 52 | *****************************************************************************/ 53 | short EqualLenVal( lenVal* plvTdoExpected, 54 | lenVal* plvTdoCaptured, 55 | lenVal* plvTdoMask ) 56 | { 57 | short sEqual; 58 | short sIndex; 59 | unsigned char ucByteVal1; 60 | unsigned char ucByteVal2; 61 | unsigned char ucByteMask; 62 | 63 | sEqual = 1; 64 | sIndex = plvTdoExpected->len; 65 | 66 | while ( sEqual && sIndex-- ) 67 | { 68 | ucByteVal1 = plvTdoExpected->val[ sIndex ]; 69 | ucByteVal2 = plvTdoCaptured->val[ sIndex ]; 70 | if ( plvTdoMask ) 71 | { 72 | ucByteMask = plvTdoMask->val[ sIndex ]; 73 | ucByteVal1 &= ucByteMask; 74 | ucByteVal2 &= ucByteMask; 75 | } 76 | if ( ucByteVal1 != ucByteVal2 ) 77 | { 78 | sEqual = 0; 79 | } 80 | } 81 | 82 | return( sEqual ); 83 | } 84 | 85 | 86 | /***************************************************************************** 87 | * Function: RetBit 88 | * Description: return the (byte, bit) of lv (reading from left to right). 89 | * Parameters: plv - ptr to lenval. 90 | * iByte - the byte to get the bit from. 91 | * iBit - the bit number (0=msb) 92 | * Returns: short - the bit value. 93 | *****************************************************************************/ 94 | short RetBit( lenVal* plv, 95 | int iByte, 96 | int iBit ) 97 | { 98 | /* assert( ( iByte >= 0 ) && ( iByte < plv->len ) ); */ 99 | /* assert( ( iBit >= 0 ) && ( iBit < 8 ) ); */ 100 | return( (short)( ( plv->val[ iByte ] >> ( 7 - iBit ) ) & 0x1 ) ); 101 | } 102 | 103 | /***************************************************************************** 104 | * Function: SetBit 105 | * Description: set the (byte, bit) of lv equal to val 106 | * Example: SetBit("00000000",byte, 1) equals "01000000". 107 | * Parameters: plv - ptr to lenval. 108 | * iByte - the byte to get the bit from. 109 | * iBit - the bit number (0=msb). 110 | * sVal - the bit value to set. 111 | * Returns: void. 112 | *****************************************************************************/ 113 | void SetBit( lenVal* plv, 114 | int iByte, 115 | int iBit, 116 | short sVal ) 117 | { 118 | unsigned char ucByteVal; 119 | unsigned char ucBitMask; 120 | 121 | ucBitMask = (unsigned char)(1 << ( 7 - iBit )); 122 | ucByteVal = (unsigned char)(plv->val[ iByte ] & (~ucBitMask)); 123 | 124 | if ( sVal ) 125 | { 126 | ucByteVal |= ucBitMask; 127 | } 128 | plv->val[ iByte ] = ucByteVal; 129 | } 130 | 131 | /***************************************************************************** 132 | * Function: AddVal 133 | * Description: add val1 to val2 and store in resVal; 134 | * assumes val1 and val2 are of equal length. 135 | * Parameters: plvResVal - ptr to result. 136 | * plvVal1 - ptr of addendum. 137 | * plvVal2 - ptr of addendum. 138 | * Returns: void. 139 | *****************************************************************************/ 140 | void addVal( lenVal* plvResVal, 141 | lenVal* plvVal1, 142 | lenVal* plvVal2 ) 143 | { 144 | unsigned char ucCarry; 145 | unsigned short usSum; 146 | unsigned short usVal1; 147 | unsigned short usVal2; 148 | short sIndex; 149 | 150 | plvResVal->len = plvVal1->len; /* set up length of result */ 151 | 152 | /* start at least significant bit and add bytes */ 153 | ucCarry = 0; 154 | sIndex = plvVal1->len; 155 | while ( sIndex-- ) 156 | { 157 | usVal1 = plvVal1->val[ sIndex ]; /* i'th byte of val1 */ 158 | usVal2 = plvVal2->val[ sIndex ]; /* i'th byte of val2 */ 159 | 160 | /* add the two bytes plus carry from previous addition */ 161 | usSum = (unsigned short)( usVal1 + usVal2 + ucCarry ); 162 | 163 | /* set up carry for next byte */ 164 | ucCarry = (unsigned char)( ( usSum > 255 ) ? 1 : 0 ); 165 | 166 | /* set the i'th byte of the result */ 167 | plvResVal->val[ sIndex ] = (unsigned char)usSum; 168 | } 169 | } 170 | 171 | /***************************************************************************** 172 | * Function: readVal 173 | * Description: read from XSVF numBytes bytes of data into x. 174 | * Parameters: plv - ptr to lenval in which to put the bytes read. 175 | * sNumBytes - the number of bytes to read. 176 | * Returns: void. 177 | *****************************************************************************/ 178 | void readVal( lenVal* plv, 179 | short sNumBytes ) 180 | { 181 | unsigned char* pucVal; 182 | 183 | plv->len = sNumBytes; /* set the length of the lenVal */ 184 | for ( pucVal = plv->val; sNumBytes; --sNumBytes, ++pucVal ) 185 | { 186 | /* read a byte of data into the lenVal */ 187 | readByte( pucVal ); 188 | } 189 | } 190 | 191 | -------------------------------------------------------------------------------- /utils/pinprocfw/lenval.h: -------------------------------------------------------------------------------- 1 | /*******************************************************/ 2 | /* file: lenval.h */ 3 | /* abstract: This file contains a description of the */ 4 | /* data structure "lenval". */ 5 | /*******************************************************/ 6 | #ifndef PINPROCFW_LENVAL_H 7 | #define PINPROCFW_LENVAL_H 8 | #if !defined(__GNUC__) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4) // GCC supports "pragma once" correctly since 3.4 9 | #pragma once 10 | #endif 11 | 12 | /* the lenVal structure is a byte oriented type used to store an */ 13 | /* arbitrary length binary value. As an example, the hex value */ 14 | /* 0x0e3d is represented as a lenVal with len=2 (since 2 bytes */ 15 | /* and val[0]=0e and val[1]=3d. val[2-MAX_LEN] are undefined */ 16 | 17 | /* maximum length (in bytes) of value to read in */ 18 | /* this needs to be at least 4, and longer than the */ 19 | /* length of the longest SDR instruction. If there is, */ 20 | /* only 1 device in the chain, MAX_LEN must be at least */ 21 | /* ceil(27/8) == 4. For 6 devices in a chain, MAX_LEN */ 22 | /* must be 5, for 14 devices MAX_LEN must be 6, for 20 */ 23 | /* devices MAX_LEN must be 7, etc.. */ 24 | /* You can safely set MAX_LEN to a smaller number if you*/ 25 | /* know how many devices will be in your chain. */ 26 | /* #define MAX_LEN (Actual #define is below this comment block) 27 | This #define defines the maximum length (in bytes) of predefined 28 | buffers in which the XSVF player stores the current shift data. 29 | This length must be greater than the longest shift length (in bytes) 30 | in the XSVF files that will be processed. 7000 is a very conservative 31 | number. The buffers are stored on the stack and if you have limited 32 | stack space, you may decrease the MAX_LEN value. 33 | 34 | How to find the "shift length" in bits? 35 | Look at the ASCII version of the XSVF (generated with the -a option 36 | for the SVF2XSVF translator) and search for the XSDRSIZE command 37 | with the biggest parameter. XSDRSIZE is equivalent to the SVF's 38 | SDR length plus the lengths of applicable HDR and TDR commands. 39 | Remember that the MAX_LEN is defined in bytes. Therefore, the 40 | minimum MAX_LEN = ceil( max( XSDRSIZE ) / 8 ); 41 | 42 | The following MAX_LEN values have been tested and provide relatively 43 | good margin for the corresponding devices: 44 | 45 | DEVICE MAX_LEN Resulting Shift Length Max (in bits) 46 | --------- ------- ---------------------------------------------- 47 | XC9500/XL/XV 32 256 48 | 49 | CoolRunner/II 256 2048 - actual max 1 device = 1035 bits 50 | 51 | FPGA 128 1024 - svf2xsvf -rlen 1024 52 | 53 | XC18V00/XCF00 54 | 1100 8800 - no blank check performed (default) 55 | - actual max 1 device = 8192 bits verify 56 | - max 1 device = 4096 bits program-only 57 | 58 | XC18V00/XCF00 when using the optional Blank Check operation 59 | 2500 20000 - required for blank check 60 | - blank check max 1 device = 16384 bits 61 | */ 62 | //#define MAX_LEN 7000 63 | #define MAX_LEN 1100 64 | 65 | 66 | typedef struct var_len_byte 67 | { 68 | short len; /* number of chars in this value */ 69 | unsigned char val[MAX_LEN+1]; /* bytes of data */ 70 | } lenVal; 71 | 72 | 73 | /* return the long representation of a lenVal */ 74 | extern long value(lenVal *x); 75 | 76 | /* set lenVal equal to value */ 77 | extern void initLenVal(lenVal *x, long value); 78 | 79 | /* check if expected equals actual (taking the mask into account) */ 80 | extern short EqualLenVal(lenVal *expected, lenVal *actual, lenVal *mask); 81 | 82 | /* add val1+val2 and put the result in resVal */ 83 | extern void addVal(lenVal *resVal, lenVal *val1, lenVal *val2); 84 | 85 | /* return the (byte, bit) of lv (reading from left to right) */ 86 | extern short RetBit(lenVal *lv, int byte, int bit); 87 | 88 | /* set the (byte, bit) of lv equal to val (e.g. SetBit("00000000",byte, 1) 89 | equals "01000000" */ 90 | extern void SetBit(lenVal *lv, int byte, int bit, short val); 91 | 92 | /* read from XSVF numBytes bytes of data into x */ 93 | extern void readVal(lenVal *x, short numBytes); 94 | 95 | #endif /* PINPROCFW_LENVAL_H */ 96 | -------------------------------------------------------------------------------- /utils/pinprocfw/pinprocfw.h: -------------------------------------------------------------------------------- 1 | /***************************************************************************** 2 | * File: micro.h 3 | * Description: This header file contains the function prototype to the 4 | * primary interface function for the XSVF player. 5 | * Usage: FIRST - PORTS.C 6 | * Customize the ports.c function implementations to establish 7 | * the correct protocol for communicating with your JTAG ports 8 | * (setPort() and readTDOBit()) and tune the waitTime() delay 9 | * function. Also, establish access to the XSVF data source 10 | * in the readByte() function. 11 | * FINALLY - Call xsvfExecute(). 12 | *****************************************************************************/ 13 | #ifndef PINPROCFW_PINPROCFW_H 14 | #define PINPROCFW_PINPROCFW_H 15 | #if !defined(__GNUC__) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || (__GNUC__ >= 4) // GCC supports "pragma once" correctly since 3.4 16 | #pragma once 17 | #endif 18 | 19 | //#if defined(__WIN32__) || defined(_WIN32) 20 | // #include 21 | // #define PRSleep(milliseconds) Sleep(milliseconds) 22 | //#else 23 | // #define PRSleep(milliseconds) sleep(milliseconds/1000) 24 | //#endif 25 | 26 | /* Legacy error codes for xsvfExecute from original XSVF player v2.0 */ 27 | #define XSVF_LEGACY_SUCCESS 1 28 | #define XSVF_LEGACY_ERROR 0 29 | 30 | /* 4.04 [NEW] Error codes for xsvfExecute. */ 31 | /* Must #define XSVF_SUPPORT_ERRORCODES in micro.c to get these codes */ 32 | #define XSVF_ERROR_NONE 0 33 | #define XSVF_ERROR_UNKNOWN 1 34 | #define XSVF_ERROR_TDOMISMATCH 2 35 | #define XSVF_ERROR_MAXRETRIES 3 /* TDO mismatch after max retries */ 36 | #define XSVF_ERROR_ILLEGALCMD 4 37 | #define XSVF_ERROR_ILLEGALSTATE 5 38 | #define XSVF_ERROR_DATAOVERFLOW 6 /* Data > lenVal MAX_LEN buffer size*/ 39 | /* Insert new errors here */ 40 | #define XSVF_ERROR_LAST 7 41 | 42 | /***************************************************************************** 43 | * Function: xsvfExecute 44 | * Description: Process, interpret, and apply the XSVF commands. 45 | * See port.c:readByte for source of XSVF data. 46 | * Parameters: none. 47 | * Returns: int - For error codes see above. 48 | *****************************************************************************/ 49 | extern int xsvfExecute(); 50 | 51 | /* these constants are used to send the appropriate ports to setPort */ 52 | /* they should be enumerated types, but some of the microcontroller */ 53 | /* compilers don't like enumerated types */ 54 | #define TCK (short) 0 55 | #define TMS (short) 1 56 | #define TDI (short) 2 57 | 58 | //#define P_ROC_ID 0xfeedbeef 59 | //#define P3_ROC_ID 0xf33db33f 60 | 61 | /* set the port "p" (TCK, TMS, or TDI) to val (0 or 1) */ 62 | void setPort(short p, short val); 63 | 64 | /* read the TDO bit and store it in val */ 65 | unsigned char readTDOBit(); 66 | 67 | /* make clock go down->up->down*/ 68 | void pulseClock(); 69 | 70 | /* read the next byte of data from the xsvf file */ 71 | void readByte(unsigned char *data); 72 | 73 | void waitTime(long microsec); 74 | 75 | 76 | #endif /* PINPROCFW_PINPROCFW_H */ 77 | --------------------------------------------------------------------------------