or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-ftdi.mdeeprom.mdgpio.mdi2c.mdindex.mdjtag.mdserial.mdspi.mdusb-tools.md

spi.mddocs/

0

# SPI Master Communication

1

2

SPI master controller implementation enabling communication with SPI devices. Supports multiple chip selects, simultaneous GPIO access, variable clock speeds up to 30MHz, and advanced features like non-byte-aligned transfers.

3

4

## Capabilities

5

6

### SPI Controller Setup

7

8

Configure and manage SPI controller with multiple device support.

9

10

```python { .api }

11

class SpiController:

12

def configure(self, url, **kwargs):

13

"""

14

Configure SPI controller with FTDI device.

15

16

Parameters:

17

- url: FTDI device URL (e.g., 'ftdi:///1')

18

- frequency: Default SPI clock frequency in Hz (default: 6MHz)

19

- cs_count: Number of chip select lines (1-8)

20

- turbo: Enable turbo mode for higher performance

21

- debug: Enable debug output

22

23

Raises:

24

- SpiIOError: Configuration failed

25

- FtdiError: Device access error

26

"""

27

28

def terminate(self):

29

"""Terminate SPI controller and release device."""

30

31

def get_frequency(self) -> float:

32

"""Get actual configured frequency."""

33

34

def get_gpio(self):

35

"""

36

Get GPIO controller for unused pins.

37

38

Returns:

39

GpioMpsseController: GPIO controller for remaining pins

40

"""

41

```

42

43

### SPI Port Access

44

45

Get SPI port instances for communication with specific devices.

46

47

```python { .api }

48

def get_port(self, cs: int, freq: float = 6000000, mode: int = 0) -> 'SpiPort':

49

"""

50

Get SPI port for specific chip select.

51

52

Parameters:

53

- cs: Chip select number (0-7)

54

- freq: SPI clock frequency in Hz

55

- mode: SPI mode (0-3)

56

- Mode 0: CPOL=0, CPHA=0 (clock idle low, sample on rising edge)

57

- Mode 1: CPOL=0, CPHA=1 (clock idle low, sample on falling edge)

58

- Mode 2: CPOL=1, CPHA=0 (clock idle high, sample on falling edge)

59

- Mode 3: CPOL=1, CPHA=1 (clock idle high, sample on rising edge)

60

61

Returns:

62

SpiPort: Port instance for device communication

63

"""

64

```

65

66

### SPI Data Transfer

67

68

Perform SPI transactions with various transfer patterns.

69

70

```python { .api }

71

class SpiPort:

72

def exchange(self, out: bytes, readlen: int = 0, start: bool = True,

73

stop: bool = True, duplex: bool = False) -> bytes:

74

"""

75

Perform full-duplex SPI transaction.

76

77

Parameters:

78

- out: Data bytes to transmit

79

- readlen: Number of additional bytes to read after transmission

80

- start: Assert chip select at start

81

- stop: Deassert chip select at end

82

- duplex: True for simultaneous read/write, False for write-then-read

83

84

Returns:

85

bytes: Data received during transaction

86

"""

87

88

def read(self, readlen: int, start: bool = True, stop: bool = True) -> bytes:

89

"""

90

Read data from SPI device.

91

92

Parameters:

93

- readlen: Number of bytes to read

94

- start: Assert chip select at start

95

- stop: Deassert chip select at end

96

97

Returns:

98

bytes: Data read from device

99

"""

100

101

def write(self, out: bytes, start: bool = True, stop: bool = True):

102

"""

103

Write data to SPI device.

104

105

Parameters:

106

- out: Data bytes to write

107

- start: Assert chip select at start

108

- stop: Deassert chip select at end

109

"""

110

```

111

112

### Advanced SPI Features

113

114

Non-standard SPI operations and advanced transfer modes.

115

116

```python { .api }

117

def write_readinto(self, out: bytes, read_buf: bytearray, start: bool = True,

118

stop: bool = True):

119

"""Write data and read response into existing buffer."""

120

121

def flush(self):

122

"""Flush any pending SPI operations."""

123

124

def set_frequency(self, frequency: float) -> float:

125

"""

126

Set SPI clock frequency for this port.

127

128

Parameters:

129

- frequency: Desired frequency in Hz

130

131

Returns:

132

float: Actual configured frequency

133

"""

134

135

def get_frequency(self) -> float:

136

"""Get current SPI clock frequency."""

137

```

138

139

### SPI with GPIO Support

140

141

SPI port with additional GPIO control for device management.

142

143

```python { .api }

144

class SpiGpioPort(SpiPort):

145

"""SPI port with GPIO capabilities for control signals."""

146

147

def set_gpio_direction(self, pins: int, direction: int):

148

"""Set GPIO pin directions (0=input, 1=output)."""

149

150

def read_gpio(self) -> int:

151

"""Read current GPIO pin states."""

152

153

def write_gpio(self, value: int):

154

"""Write GPIO pin states."""

155

156

def exchange_gpio(self, out: bytes, readlen: int, gpio_dir: int,

157

gpio_out: int) -> tuple:

158

"""

159

Perform SPI exchange with simultaneous GPIO control.

160

161

Returns:

162

tuple: (spi_data, gpio_state)

163

"""

164

```

165

166

## Device Support

167

168

### Pin Assignments

169

170

Standard FTDI SPI pin assignments:

171

172

**FT232H (8 pins available):**

173

- SCK: AD0 (SPI Clock)

174

- MOSI: AD1 (Master Out, Slave In)

175

- MISO: AD2 (Master In, Slave Out)

176

- CS0: AD3 (Chip Select 0)

177

- CS1: AD4 (Chip Select 1)

178

- CS2-CS7: AD5-AD7, AC0-AC2 (Additional chip selects)

179

180

**FT2232H/FT4232H:**

181

- Similar pin assignments per interface

182

- Multiple interfaces allow independent SPI controllers

183

184

### Clock Speeds

185

186

Supported SPI clock frequencies:

187

- **FT232H**: Up to 30 MHz

188

- **FT2232H**: Up to 30 MHz

189

- **FT2232C/D**: Up to 6 MHz

190

- **Actual speeds**: Depend on FTDI device oscillator and divider limitations

191

192

## Usage Examples

193

194

### Basic SPI Communication

195

196

```python

197

from pyftdi.spi import SpiController

198

199

# Configure SPI controller

200

spi = SpiController()

201

spi.configure('ftdi:///1')

202

203

# Get SPI port for device on CS0

204

device = spi.get_port(cs=0, freq=1E6, mode=0)

205

206

# Read device ID (common SPI flash operation)

207

device_id = device.exchange([0x9F], 3) # JEDEC ID command

208

print(f"Device ID: {device_id.hex()}")

209

210

# Write enable command

211

device.write([0x06])

212

213

# Read status register

214

status = device.exchange([0x05], 1)[0]

215

print(f"Status: 0x{status:02x}")

216

217

# Clean up

218

spi.terminate()

219

```

220

221

### Multiple Device Management

222

223

```python

224

from pyftdi.spi import SpiController

225

226

spi = SpiController()

227

spi.configure('ftdi:///1', cs_count=3)

228

229

# Different devices on different chip selects

230

flash = spi.get_port(cs=0, freq=10E6, mode=0) # SPI Flash

231

adc = spi.get_port(cs=1, freq=1E6, mode=1) # ADC

232

dac = spi.get_port(cs=2, freq=5E6, mode=2) # DAC

233

234

# Independent communication with each device

235

flash_id = flash.exchange([0x9F], 3)

236

adc_value = adc.exchange([0x00, 0x00], 2)

237

dac.write([0x30, 0xFF, 0x00]) # Set DAC output

238

239

spi.terminate()

240

```

241

242

### SPI with GPIO Control

243

244

```python

245

from pyftdi.spi import SpiController

246

247

spi = SpiController()

248

spi.configure('ftdi:///1')

249

250

# Get SPI port and GPIO controller

251

device = spi.get_port(cs=0, freq=6E6, mode=0)

252

gpio = spi.get_gpio()

253

254

# Configure additional pins as GPIO

255

gpio.set_direction(0xF0, 0xF0) # Upper 4 bits as outputs

256

257

# Control reset line while doing SPI

258

gpio.write(0x10) # Assert reset

259

device.write([0x01, 0x02, 0x03]) # Send data

260

gpio.write(0x00) # Release reset

261

262

spi.terminate()

263

```

264

265

### High-Performance Transfers

266

267

```python

268

from pyftdi.spi import SpiController

269

270

spi = SpiController()

271

spi.configure('ftdi:///1', turbo=True) # Enable turbo mode

272

273

device = spi.get_port(cs=0, freq=30E6, mode=0) # Max speed

274

275

# Large data transfer

276

data_out = bytes(range(256)) # 256 bytes of test data

277

response = device.exchange(data_out, len(data_out), duplex=True)

278

279

# Continuous operations without CS toggling

280

device.write([0x02, 0x00, 0x00], start=True, stop=False) # Write command

281

device.write(data_out, start=False, stop=False) # Data

282

device.write([0x00], start=False, stop=True) # End transfer

283

284

spi.terminate()

285

```

286

287

## Exception Handling

288

289

```python

290

from pyftdi.spi import SpiController, SpiIOError

291

from pyftdi.ftdi import FtdiError

292

293

try:

294

spi = SpiController()

295

spi.configure('ftdi:///1')

296

297

device = spi.get_port(cs=0)

298

data = device.exchange([0x9F], 3)

299

300

except SpiIOError as e:

301

print(f"SPI communication error: {e}")

302

except FtdiError as e:

303

print(f"FTDI device error: {e}")

304

finally:

305

if 'spi' in locals():

306

spi.terminate()

307

```

308

309

## Types

310

311

```python { .api }

312

# Exception types

313

class SpiIOError(FtdiError):

314

"""SPI communication error"""

315

316

# SPI mode constants

317

SPI_MODE_0 = 0 # CPOL=0, CPHA=0

318

SPI_MODE_1 = 1 # CPOL=0, CPHA=1

319

SPI_MODE_2 = 2 # CPOL=1, CPHA=0

320

SPI_MODE_3 = 3 # CPOL=1, CPHA=1

321

```