1
0
mirror of https://github.com/preble/libpinproc synced 2026-02-24 18:25:23 +01:00

Moved libftdi-specific code to PRHardware.cpp and added abstract PRHardware*() functions.

Added PRCommon.h.
This commit is contained in:
Adam Preble
2009-05-26 20:18:36 -04:00
parent 179125367b
commit 511d5d49c4
6 changed files with 184 additions and 110 deletions

View File

@@ -15,6 +15,7 @@
668249E30FC0A3960051560E /* pinproctest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 668249E20FC0A3960051560E /* pinproctest.cpp */; }; 668249E30FC0A3960051560E /* pinproctest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 668249E20FC0A3960051560E /* pinproctest.cpp */; };
668249EA0FC0A4280051560E /* libpinproc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libpinproc.a */; }; 668249EA0FC0A4280051560E /* libpinproc.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D2AAC046055464E500DB518D /* libpinproc.a */; };
668249ED0FC0A4CD0051560E /* PRHardware.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 668249EC0FC0A4CD0051560E /* PRHardware.cpp */; }; 668249ED0FC0A4CD0051560E /* PRHardware.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 668249EC0FC0A4CD0051560E /* PRHardware.cpp */; };
66824E7B0FCCBAFF0051560E /* PRCommon.h in Headers */ = {isa = PBXBuildFile; fileRef = 66824E7A0FCCBAFF0051560E /* PRCommon.h */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -36,6 +37,7 @@
668249D90FC0A30A0051560E /* pinproctest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pinproctest; sourceTree = BUILT_PRODUCTS_DIR; }; 668249D90FC0A30A0051560E /* pinproctest */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = pinproctest; sourceTree = BUILT_PRODUCTS_DIR; };
668249E20FC0A3960051560E /* pinproctest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pinproctest.cpp; path = examples/pinproctest/pinproctest.cpp; sourceTree = "<group>"; }; 668249E20FC0A3960051560E /* pinproctest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = pinproctest.cpp; path = examples/pinproctest/pinproctest.cpp; sourceTree = "<group>"; };
668249EC0FC0A4CD0051560E /* PRHardware.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PRHardware.cpp; path = src/PRHardware.cpp; sourceTree = "<group>"; }; 668249EC0FC0A4CD0051560E /* PRHardware.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PRHardware.cpp; path = src/PRHardware.cpp; sourceTree = "<group>"; };
66824E7A0FCCBAFF0051560E /* PRCommon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PRCommon.h; path = src/PRCommon.h; sourceTree = "<group>"; };
D2AAC046055464E500DB518D /* libpinproc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpinproc.a; sourceTree = BUILT_PRODUCTS_DIR; }; D2AAC046055464E500DB518D /* libpinproc.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libpinproc.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@@ -95,6 +97,7 @@
668249410FC07D900051560E /* PRDevice.cpp */, 668249410FC07D900051560E /* PRDevice.cpp */,
6682494A0FC0870B0051560E /* PRHardware.h */, 6682494A0FC0870B0051560E /* PRHardware.h */,
668249EC0FC0A4CD0051560E /* PRHardware.cpp */, 668249EC0FC0A4CD0051560E /* PRHardware.cpp */,
66824E7A0FCCBAFF0051560E /* PRCommon.h */,
); );
name = libpinproc; name = libpinproc;
sourceTree = "<group>"; sourceTree = "<group>";
@@ -124,6 +127,7 @@
6682492C0FC079050051560E /* pinproc.h in Headers */, 6682492C0FC079050051560E /* pinproc.h in Headers */,
668249420FC07D900051560E /* PRDevice.h in Headers */, 668249420FC07D900051560E /* PRDevice.h in Headers */,
6682494B0FC0870B0051560E /* PRHardware.h in Headers */, 6682494B0FC0870B0051560E /* PRHardware.h in Headers */,
66824E7B0FCCBAFF0051560E /* PRCommon.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };

36
src/PRCommon.h Normal file
View File

@@ -0,0 +1,36 @@
/*
* Copyright (c) 2009 Gerry Stellenberg, Adam Preble
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef _PRCOMMON_H_
#define _PRCOMMON_H_
#ifdef NDEBUG
# define DEBUG(block)
#else
# define DEBUG(block) block
#endif
extern void PRLog(const char *format, ...);
#endif // _PRCOMMON_H_

View File

@@ -30,7 +30,7 @@
#include "PRDevice.h" #include "PRDevice.h"
PRDevice::PRDevice(PRMachineType machineType) : machineType(machineType), ftdiInitialized(false) PRDevice::PRDevice(PRMachineType machineType) : machineType(machineType)
{ {
Reset(); Reset();
} }
@@ -375,112 +375,39 @@ PRResult PRDevice::DMDDraw(uint8_t * dots)
PRResult PRDevice::Open() PRResult PRDevice::Open()
{ {
int32_t i=0; PRResult res = PRHardwareOpen();
PRResult rc; if (res == kPRSuccess)
struct ftdi_device_list *devlist, *curdev;
char manufacturer[128], description[128];
uint32_t temp_word;
ftdiInitialized = false;
// Open the FTDI device
if (ftdi_init(&ftdic) != 0)
{ {
DEBUG(PRLog("Failed to initialize FTDI.\n")); // Try to verify the P-ROC IS in the FPGA before initializing the FPGA's FTDI interface
return kPRFailure; // just in case it was already initialized from a previous application execution.
} DEBUG(PRLog("Verifying P-ROC ID: \n"));
if (VerifyChipID() == kPRFailure) {
// Find all FTDI devices // Since the FPGA didn't appear to be responding properly, send the FPGA's FTDI
// This is very basic and really only expects to see 1 device. It needs to be // initialization sequence. This is a set of bytes the FPGA is waiting to receive
// smarter. At the very least, it should check some register on the P-ROC versus // before it allows access deeper into the chip. This keeps garbage from getting
// an input parameter to ensure the software is set up for the same architecture as // in and wreaking havoc before software is up and running.
// the P-ROC (Stern vs WPC). Otherwise, it's possible to drive the coils the wrong DEBUG(PRLog("Initializing P-ROC...\n"));
// polarity and blow fuses or fry transistors and all other sorts of badness. res = FlushReadBuffer();
uint32_t temp_word = P_ROC_INIT_PATTERN_A;
// We first enumerate all of the devices: res = WriteData(&temp_word, 1);
int numDevices = ftdi_usb_find_all(&ftdic, &devlist, FTDI_VENDOR_ID, FTDI_FT245RL_PRODUCT_ID); temp_word = P_ROC_INIT_PATTERN_B;
if (numDevices < 0) { res = WriteData(&temp_word, 1);
DEBUG(PRLog("ftdi_usb_find_all failed: %d: %s\n", numDevices, ftdi_get_error_string(&ftdic))); res = VerifyChipID();
ftdi_deinit(&ftdic);
return kPRFailure;
}
else {
DEBUG(PRLog("Number of FTDI devices found: %d\n", numDevices));
for (curdev = devlist; curdev != NULL; i++) {
DEBUG(PRLog("Checking device %d\n", i));
if ((rc = (int32_t)ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) {
DEBUG(PRLog(" ftdi_usb_get_strings failed: %d: %s\n", rc, ftdi_get_error_string(&ftdic)));
}
else {
DEBUG(PRLog(" Device #%d:\n", i));
DEBUG(PRLog(" Manufacturer: %s\n", manufacturer));
DEBUG(PRLog(" Description: %s\n", description));
}
curdev = curdev->next;
} }
else
} {
DEBUG(PRLog("Failed to verify chip ID."));
// Don't need the device list anymore res = kPRFailure;
ftdi_list_free (&devlist);
// Did previous logic leave ftdic clean? Probably
// Need to de-init and re-init before opening usb? Doubtful.
//ftdi_deinit(&ftdic);
//ftdi_init(&ftdic);
if ((rc = (int32_t)ftdi_usb_open(&ftdic, FTDI_VENDOR_ID, FTDI_FT245RL_PRODUCT_ID)) < 0)
{
DEBUG(PRLog("ERROR: Unable to open ftdi device: %d: %s\n", rc, ftdi_get_error_string(&ftdic)));
return kPRFailure;
}
else
{
rc = kPRSuccess;
if (ftdic.type == TYPE_R) {
uint32_t chipid;
ftdi_read_chipid(&ftdic,&chipid);
DEBUG(PRLog("FTDI chip_id = 0x%x\n", chipid));
// Try to verify the P-ROC IS in the FPGA before initializing the FPGA's FTDI interface
// just in case it was already initialized from a previous application execution.
DEBUG(PRLog("Verifying P-ROC ID: \n"));
if (VerifyChipID() == kPRFailure) {
// Since the FPGA didn't appear to be responding properly, send the FPGA's FTDI
// initialization sequence. This is a set of bytes the FPGA is waiting to receive
// before it allows access deeper into the chip. This keeps garbage from getting
// in and wreaking havoc before software is up and running.
DEBUG(PRLog("Initializing P-ROC...\n"));
rc = FlushReadBuffer();
temp_word = P_ROC_INIT_PATTERN_A;
rc = WriteData(&temp_word, 1);
temp_word = P_ROC_INIT_PATTERN_B;
rc = WriteData(&temp_word, 1);
rc = VerifyChipID();
}
else
{
DEBUG(PRLog("Failed to verify chip ID."));
rc = kPRFailure;
}
} }
} }
if (rc == kPRSuccess) return res;
ftdiInitialized = true;
return rc;
} }
PRResult PRDevice::Close() PRResult PRDevice::Close()
{ {
// TODO: Add protection against closing a not-open ftdic. // TODO: Add protection against closing a not-open ftdic.
if (ftdiInitialized) PRHardwareClose();
{
ftdi_usb_close(&ftdic);
ftdi_deinit(&ftdic);
}
return kPRSuccess; return kPRSuccess;
} }
@@ -561,7 +488,7 @@ PRResult PRDevice::WriteData(uint32_t * words, int32_t numWords)
} }
int bytesToWrite = numWords * 4; int bytesToWrite = numWords * 4;
int bytesWritten = (int32_t)ftdi_write_data(&ftdic, wr_buffer, bytesToWrite); int bytesWritten = PRHardwareWrite(wr_buffer, bytesToWrite);
if (bytesWritten != bytesToWrite) if (bytesWritten != bytesToWrite)
{ {
@@ -623,7 +550,7 @@ PRResult PRDevice::FlushReadBuffer()
int32_t PRDevice::CollectReadData() int32_t PRDevice::CollectReadData()
{ {
int32_t rc,i; int32_t rc,i;
rc = ftdi_read_data(&ftdic, collect_buffer, FTDI_BUFFER_SIZE-num_collected_bytes); rc = PRHardwareRead(collect_buffer, FTDI_BUFFER_SIZE-num_collected_bytes);
for (i=0; i<rc; i=i++) { for (i=0; i<rc; i=i++) {
collected_bytes_fifo[collected_bytes_wr_addr] = collect_buffer[i]; collected_bytes_fifo[collected_bytes_wr_addr] = collect_buffer[i];
if (collected_bytes_wr_addr == (FTDI_BUFFER_SIZE-1)) if (collected_bytes_wr_addr == (FTDI_BUFFER_SIZE-1))

View File

@@ -29,9 +29,9 @@
*/ */
#include "../include/pinproc.h" #include "../include/pinproc.h"
#include "PRCommon.h"
#include "PRHardware.h" #include "PRHardware.h"
#include <queue> #include <queue>
#include <ftdi.h>
using namespace std; using namespace std;
@@ -39,13 +39,6 @@ using namespace std;
#define maxDrivers (256) #define maxDrivers (256)
#define maxSwitchRules (256<<2) // 8 bits of switchNum indicies plus bits for debounced and state. #define maxSwitchRules (256<<2) // 8 bits of switchNum indicies plus bits for debounced and state.
#ifdef NDEBUG
# define DEBUG(block)
#else
# define DEBUG(block) block
#endif
extern void PRLog(const char *format, ...);
class PRDevice class PRDevice
{ {
public: public:
@@ -117,9 +110,6 @@ protected:
queue<uint32_t> unrequestedDataQueue; /**< Queue of words received from the device that were not requested via RequestData(). Usually switch events. */ queue<uint32_t> unrequestedDataQueue; /**< Queue of words received from the device that were not requested via RequestData(). Usually switch events. */
queue<uint32_t> requestedDataQueue; /**< Queue of words received from the device as the result of a call to RequestData(). */ queue<uint32_t> requestedDataQueue; /**< Queue of words received from the device as the result of a call to RequestData(). */
bool ftdiInitialized;
ftdi_context ftdic;
uint8_t collected_bytes_fifo[FTDI_BUFFER_SIZE]; uint8_t collected_bytes_fifo[FTDI_BUFFER_SIZE];
int32_t collected_bytes_rd_addr; int32_t collected_bytes_rd_addr;
int32_t collected_bytes_wr_addr; int32_t collected_bytes_wr_addr;

View File

@@ -30,6 +30,8 @@
#include "PRHardware.h" #include "PRHardware.h"
#include "PRCommon.h"
#include "pinproc.h"
uint32_t CreateRegRequestWord( uint32_t select, uint32_t addr, uint32_t num_words ) { uint32_t CreateRegRequestWord( uint32_t select, uint32_t addr, uint32_t num_words ) {
@@ -212,3 +214,112 @@ int32_t CreateDMDUpdateConfigBurst ( uint32_t * burst, PRDMDConfig *dmd_config)
return kPRSuccess; return kPRSuccess;
} }
/**
* This is where all FTDI driver-specific code should go.
* As we add support for other drivers (such as D2xx on Windows), we will add more implementations of the PRHardware*() functions here.
*/
#if !defined(USE_LIBFTDI)
#define USE_LIBFTDI 1
#endif
#if USE_LIBFTDI
#include <ftdi.h>
static bool ftdiInitialized;
static ftdi_context ftdic;
PRResult PRHardwareOpen()
{
int32_t i=0;
PRResult rc;
struct ftdi_device_list *devlist, *curdev;
char manufacturer[128], description[128];
ftdiInitialized = false;
// Open the FTDI device
if (ftdi_init(&ftdic) != 0)
{
DEBUG(PRLog("Failed to initialize FTDI.\n"));
return kPRFailure;
}
// Find all FTDI devices
// This is very basic and really only expects to see 1 device. It needs to be
// smarter. At the very least, it should check some register on the P-ROC versus
// an input parameter to ensure the software is set up for the same architecture as
// the P-ROC (Stern vs WPC). Otherwise, it's possible to drive the coils the wrong
// polarity and blow fuses or fry transistors and all other sorts of badness.
// We first enumerate all of the devices:
int numDevices = ftdi_usb_find_all(&ftdic, &devlist, FTDI_VENDOR_ID, FTDI_FT245RL_PRODUCT_ID);
if (numDevices < 0) {
DEBUG(PRLog("ftdi_usb_find_all failed: %d: %s\n", numDevices, ftdi_get_error_string(&ftdic)));
ftdi_deinit(&ftdic);
return kPRFailure;
}
else {
DEBUG(PRLog("Number of FTDI devices found: %d\n", numDevices));
for (curdev = devlist; curdev != NULL; i++) {
DEBUG(PRLog("Checking device %d\n", i));
if ((rc = (int32_t)ftdi_usb_get_strings(&ftdic, curdev->dev, manufacturer, 128, description, 128, NULL, 0)) < 0) {
DEBUG(PRLog(" ftdi_usb_get_strings failed: %d: %s\n", rc, ftdi_get_error_string(&ftdic)));
}
else {
DEBUG(PRLog(" Device #%d:\n", i));
DEBUG(PRLog(" Manufacturer: %s\n", manufacturer));
DEBUG(PRLog(" Description: %s\n", description));
}
curdev = curdev->next;
}
}
// Don't need the device list anymore
ftdi_list_free (&devlist);
if ((rc = (int32_t)ftdi_usb_open(&ftdic, FTDI_VENDOR_ID, FTDI_FT245RL_PRODUCT_ID)) < 0)
{
DEBUG(PRLog("ERROR: Unable to open ftdi device: %d: %s\n", rc, ftdi_get_error_string(&ftdic)));
return kPRFailure;
}
else
{
rc = kPRSuccess;
if (ftdic.type == TYPE_R) {
uint32_t chipid;
ftdi_read_chipid(&ftdic,&chipid);
DEBUG(PRLog("FTDI chip_id = 0x%x\n", chipid));
ftdiInitialized = true;
return kPRSuccess;
}
else
{
DEBUG(PRLog("FTDI type != TYPE_R: 0x%x\n", ftdic.type));
return kPRFailure;
}
}
}
void PRHardwareClose()
{
if (ftdiInitialized)
{
ftdi_usb_close(&ftdic);
ftdi_deinit(&ftdic);
}
}
int PRHardwareRead(uint8_t *buffer, int maxBytes)
{
return ftdi_read_data(&ftdic, buffer, maxBytes);
}
int PRHardwareWrite(uint8_t *buffer, int bytes)
{
return ftdi_write_data(&ftdic, buffer, bytes);
}
#endif // USE_LIBFTDI

View File

@@ -169,4 +169,10 @@ void ParseSwitchRuleIndex(uint16_t index, uint8_t *switchNum, PREventType *event
int16_t CreateSwitchRuleIndex(uint8_t switchNum, PREventType eventType); int16_t CreateSwitchRuleIndex(uint8_t switchNum, PREventType eventType);
int32_t CreateSwitchRuleAddr(uint8_t switchNum, PREventType eventType); int32_t CreateSwitchRuleAddr(uint8_t switchNum, PREventType eventType);
PRResult PRHardwareOpen();
void PRHardwareClose();
int PRHardwareRead(uint8_t *buffer, int maxBytes);
int PRHardwareWrite(uint8_t *buffer, int bytes);
#endif // _PROC_HARDWARE_H_ #endif // _PROC_HARDWARE_H_