blob: eeeb49e85e53b9179e4b711e319d5b520e422184 [file] [log] [blame]
/*
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;
const char* description;
};
struct mpsse_context {
const 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_ */