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:
36
src/PRCommon.h
Normal file
36
src/PRCommon.h
Normal 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_
|
||||
125
src/PRDevice.cpp
125
src/PRDevice.cpp
@@ -30,7 +30,7 @@
|
||||
|
||||
#include "PRDevice.h"
|
||||
|
||||
PRDevice::PRDevice(PRMachineType machineType) : machineType(machineType), ftdiInitialized(false)
|
||||
PRDevice::PRDevice(PRMachineType machineType) : machineType(machineType)
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
@@ -375,112 +375,39 @@ PRResult PRDevice::DMDDraw(uint8_t * dots)
|
||||
|
||||
PRResult PRDevice::Open()
|
||||
{
|
||||
int32_t i=0;
|
||||
PRResult rc;
|
||||
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)
|
||||
PRResult res = PRHardwareOpen();
|
||||
if (res == kPRSuccess)
|
||||
{
|
||||
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;
|
||||
// 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"));
|
||||
res = FlushReadBuffer();
|
||||
uint32_t temp_word = P_ROC_INIT_PATTERN_A;
|
||||
res = WriteData(&temp_word, 1);
|
||||
temp_word = P_ROC_INIT_PATTERN_B;
|
||||
res = WriteData(&temp_word, 1);
|
||||
res = VerifyChipID();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Don't need the device list anymore
|
||||
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;
|
||||
}
|
||||
else
|
||||
{
|
||||
DEBUG(PRLog("Failed to verify chip ID."));
|
||||
res = kPRFailure;
|
||||
}
|
||||
}
|
||||
|
||||
if (rc == kPRSuccess)
|
||||
ftdiInitialized = true;
|
||||
|
||||
return rc;
|
||||
return res;
|
||||
}
|
||||
|
||||
PRResult PRDevice::Close()
|
||||
{
|
||||
// TODO: Add protection against closing a not-open ftdic.
|
||||
if (ftdiInitialized)
|
||||
{
|
||||
ftdi_usb_close(&ftdic);
|
||||
ftdi_deinit(&ftdic);
|
||||
}
|
||||
PRHardwareClose();
|
||||
return kPRSuccess;
|
||||
}
|
||||
|
||||
@@ -561,7 +488,7 @@ PRResult PRDevice::WriteData(uint32_t * words, int32_t numWords)
|
||||
}
|
||||
|
||||
int bytesToWrite = numWords * 4;
|
||||
int bytesWritten = (int32_t)ftdi_write_data(&ftdic, wr_buffer, bytesToWrite);
|
||||
int bytesWritten = PRHardwareWrite(wr_buffer, bytesToWrite);
|
||||
|
||||
if (bytesWritten != bytesToWrite)
|
||||
{
|
||||
@@ -623,7 +550,7 @@ PRResult PRDevice::FlushReadBuffer()
|
||||
int32_t PRDevice::CollectReadData()
|
||||
{
|
||||
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++) {
|
||||
collected_bytes_fifo[collected_bytes_wr_addr] = collect_buffer[i];
|
||||
if (collected_bytes_wr_addr == (FTDI_BUFFER_SIZE-1))
|
||||
|
||||
@@ -29,9 +29,9 @@
|
||||
*/
|
||||
|
||||
#include "../include/pinproc.h"
|
||||
#include "PRCommon.h"
|
||||
#include "PRHardware.h"
|
||||
#include <queue>
|
||||
#include <ftdi.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -39,13 +39,6 @@ using namespace std;
|
||||
#define maxDrivers (256)
|
||||
#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
|
||||
{
|
||||
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> 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];
|
||||
int32_t collected_bytes_rd_addr;
|
||||
int32_t collected_bytes_wr_addr;
|
||||
|
||||
@@ -30,6 +30,8 @@
|
||||
|
||||
|
||||
#include "PRHardware.h"
|
||||
#include "PRCommon.h"
|
||||
#include "pinproc.h"
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
@@ -169,4 +169,10 @@ void ParseSwitchRuleIndex(uint16_t index, uint8_t *switchNum, PREventType *event
|
||||
int16_t CreateSwitchRuleIndex(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_
|
||||
|
||||
Reference in New Issue
Block a user