C++程序  |  250行  |  6.43 KB

/*
 *Copyright (C) 2015 The Android Open Source Project
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
 *
 * This file was copied from https://github.com/devttys0/libmpsse.git (sha1
 * f1a6744b), and modified to suite the Chromium OS project.
 */

#ifndef TRUNKS_FTDI_MPSSE_H_
#define TRUNKS_FTDI_MPSSE_H_

#include <libftdi1/ftdi.h>
#include <stdint.h>

#define MPSSE_OK 0
#define MPSSE_FAIL -1

#define MSB 0x00
#define LSB 0x08

#define CHUNK_SIZE 65535
#define SPI_RW_SIZE (63 * 1024)
#define SPI_TRANSFER_SIZE 512
#define I2C_TRANSFER_SIZE 64

#define LATENCY_MS 2
#define TIMEOUT_DIVISOR 1000000
#define USB_TIMEOUT 120000
#define SETUP_DELAY 25000

#define BITMODE_RESET 0
#define BITMODE_MPSSE 2

#define CMD_SIZE 3
#define MAX_SETUP_COMMANDS 10
#define SS_TX_COUNT 3

#define LOW 0
#define HIGH 1
#define NUM_GPIOL_PINS 4
#define NUM_GPIO_PINS 12

#define NULL_CONTEXT_ERROR_MSG "NULL MPSSE context pointer!"

#ifdef __cplusplus
extern "C" {
#endif

/* FTDI interfaces */
enum interface {
  IFACE_ANY = INTERFACE_ANY,
  IFACE_A = INTERFACE_A,
  IFACE_B = INTERFACE_B,
  IFACE_C = INTERFACE_C,
  IFACE_D = INTERFACE_D
};

/* Common clock rates */
enum clock_rates {
  ONE_HUNDRED_KHZ = 100000,
  FOUR_HUNDRED_KHZ = 400000,
  ONE_MHZ = 1000000,
  TWO_MHZ = 2000000,
  FIVE_MHZ = 5000000,
  SIX_MHZ = 6000000,
  TEN_MHZ = 10000000,
  TWELVE_MHZ = 12000000,
  FIFTEEN_MHZ = 15000000,
  THIRTY_MHZ = 30000000,
  SIXTY_MHZ = 60000000
};

/* Supported MPSSE modes */
enum modes {
  SPI0 = 1,
  SPI1 = 2,
  SPI2 = 3,
  SPI3 = 4,
  I2C = 5,
  GPIO = 6,
  BITBANG = 7,
};

enum pins {
  SK = 1,
  DO = 2,
  DI = 4,
  CS = 8,
  GPIO0 = 16,
  GPIO1 = 32,
  GPIO2 = 64,
  GPIO3 = 128
};

enum gpio_pins {
  GPIOL0 = 0,
  GPIOL1 = 1,
  GPIOL2 = 2,
  GPIOL3 = 3,
  GPIOH0 = 4,
  GPIOH1 = 5,
  GPIOH2 = 6,
  GPIOH3 = 7,
  GPIOH4 = 8,
  GPIOH5 = 9,
  GPIOH6 = 10,
  GPIOH7 = 11
};

enum i2c_ack { ACK = 0, NACK = 1 };

/* SK/DO/CS and GPIOs are outputs, DI is an input */
#define DEFAULT_TRIS (SK | DO | CS | GPIO0 | GPIO1 | GPIO2 | GPIO3)
#define DEFAULT_PORT (SK | CS) /* SK and CS are high, all others low */

enum mpsse_commands {
  INVALID_COMMAND = 0xAB,
  ENABLE_ADAPTIVE_CLOCK = 0x96,
  DISABLE_ADAPTIVE_CLOCK = 0x97,
  ENABLE_3_PHASE_CLOCK = 0x8C,
  DISABLE_3_PHASE_CLOCK = 0x8D,
  TCK_X5 = 0x8A,
  TCK_D5 = 0x8B,
  CLOCK_N_CYCLES = 0x8E,
  CLOCK_N8_CYCLES = 0x8F,
  PULSE_CLOCK_IO_HIGH = 0x94,
  PULSE_CLOCK_IO_LOW = 0x95,
  CLOCK_N8_CYCLES_IO_HIGH = 0x9C,
  CLOCK_N8_CYCLES_IO_LOW = 0x9D,
  TRISTATE_IO = 0x9E,
};

enum low_bits_status { STARTED, STOPPED };

struct vid_pid {
  int vid;
  int pid;
  char* description;
};

struct mpsse_context {
  char* description;
  struct ftdi_context ftdi;
  enum modes mode;
  enum low_bits_status status;
  int flush_after_read;
  int vid;
  int pid;
  int clock;
  int xsize;
  uint8_t endianess;
  uint8_t opened;
  uint8_t tris;
  uint8_t pstart;
  uint8_t pstop;
  uint8_t pidle;
  uint8_t gpioh;
  uint8_t trish;
  uint8_t bitbang;
  uint8_t tx;
  uint8_t rx;
  uint8_t txrx;
  uint8_t tack;
  uint8_t rack;
};

struct mpsse_context* MPSSE(enum modes mode, int freq, int endianess);
struct mpsse_context* Open(int vid,
                           int pid,
                           enum modes mode,
                           int freq,
                           int endianess,
                           int interface,
                           const char* description,
                           const char* serial);
struct mpsse_context* OpenIndex(int vid,
                                int pid,
                                enum modes mode,
                                int freq,
                                int endianess,
                                int interface,
                                const char* description,
                                const char* serial,
                                int index);
void Close(struct mpsse_context* mpsse);
const char* ErrorString(struct mpsse_context* mpsse);
int SetMode(struct mpsse_context* mpsse, int endianess);
void EnableBitmode(struct mpsse_context* mpsse, int tf);
int SetClock(struct mpsse_context* mpsse, uint32_t freq);
int GetClock(struct mpsse_context* mpsse);
int GetVid(struct mpsse_context* mpsse);
int GetPid(struct mpsse_context* mpsse);
const char* GetDescription(struct mpsse_context* mpsse);
int SetLoopback(struct mpsse_context* mpsse, int enable);
void SetCSIdle(struct mpsse_context* mpsse, int idle);
int Start(struct mpsse_context* mpsse);
int Write(struct mpsse_context* mpsse, const void* data, int size);
int Stop(struct mpsse_context* mpsse);
int GetAck(struct mpsse_context* mpsse);
void SetAck(struct mpsse_context* mpsse, int ack);
void SendAcks(struct mpsse_context* mpsse);
void SendNacks(struct mpsse_context* mpsse);
void FlushAfterRead(struct mpsse_context* mpsse, int tf);
int PinHigh(struct mpsse_context* mpsse, int pin);
int PinLow(struct mpsse_context* mpsse, int pin);
int SetDirection(struct mpsse_context* mpsse, uint8_t direction);
int WriteBits(struct mpsse_context* mpsse, char bits, size_t size);
char ReadBits(struct mpsse_context* mpsse, int size);
int WritePins(struct mpsse_context* mpsse, uint8_t data);
int ReadPins(struct mpsse_context* mpsse);
int PinState(struct mpsse_context* mpsse, int pin, int state);
int Tristate(struct mpsse_context* mpsse);
char Version(void);

#ifdef SWIGPYTHON
typedef struct swig_string_data {
  int size;
  char* data;
} swig_string_data;

swig_string_data Read(struct mpsse_context* mpsse, int size);
swig_string_data Transfer(struct mpsse_context* mpsse, char* data, int size);
#else
uint8_t* Read(struct mpsse_context* mpsse, int size);
uint8_t* Transfer(struct mpsse_context* mpsse,
                        uint8_t* data, int size);

int FastWrite(struct mpsse_context* mpsse, char* data, int size);
int FastRead(struct mpsse_context* mpsse, char* data, int size);
int FastTransfer(struct mpsse_context* mpsse,
                 char* wdata,
                 char* rdata,
                 int size);
#endif
#ifdef __cplusplus
}
#endif
#endif  /* TRUNKS_FTDI_MPSSE_H_ */