Classes/PsGadgetSpi.ps1
|
#Requires -Version 5.1 # Classes/PsGadgetSpi.ps1 # SPI device handle returned by PsGadgetFtdi.GetSpi(). # Wraps an FTDI connection for MPSSE SPI transactions and exposes # Write(), Read(), and Transfer() methods backed by Ftdi.Spi.ps1. # # Obtain via: # $spi = $dev.GetSpi() # 1 MHz, Mode 0, CS=ADBUS3 # $spi = $dev.GetSpi(10000000) # 10 MHz, Mode 0, CS=ADBUS3 # $spi = $dev.GetSpi(5000000, 3, 3) # 5 MHz, Mode 3, CS=ADBUS3 class PsGadgetSpi { [PsGadgetLogger]$Logger [System.Object]$FtdiDevice [int]$ClockHz [int]$SpiMode # 0-3 (CPOL/CPHA) [int]$CsPin # ADBUS pin number for CS (3-7) [bool]$IsInitialized PsGadgetSpi([System.Object]$ftdiConnection, [int]$clockHz, [int]$spiMode, [int]$csPin) { $this.Logger = Get-PsGadgetModuleLogger $this.FtdiDevice = $ftdiConnection $this.ClockHz = $clockHz $this.SpiMode = $spiMode $this.CsPin = $csPin $this.IsInitialized = $false $this.Logger.WriteInfo("PsGadgetSpi created: clock=${clockHz}Hz mode=${spiMode} CS=ADBUS${csPin}") } [bool] Initialize() { return $this.Initialize($false) } [bool] Initialize([bool]$force) { if ($this.IsInitialized -and -not $force) { $this.Logger.WriteInfo("SPI already initialized") return $true } if (-not $this.FtdiDevice) { $this.Logger.WriteError("No FTDI device assigned to SPI instance") return $false } $result = Initialize-MpsseSpi ` -DeviceHandle $this.FtdiDevice ` -ClockFrequency $this.ClockHz ` -SpiMode $this.SpiMode ` -CsPin $this.CsPin if ($result) { $this.IsInitialized = $true $this.Logger.WriteInfo("SPI initialized: clock=$($this.ClockHz)Hz mode=$($this.SpiMode) CS=ADBUS$($this.CsPin)") } else { $this.Logger.WriteError("SPI initialization failed") } return $result } # Write bytes to SPI device. CS is asserted for the entire payload. [bool] Write([byte[]]$data) { if (-not $this.IsInitialized) { $this.Logger.WriteError("SPI not initialized. Call Initialize() first.") return $false } return (Invoke-MpsseSpiWrite ` -DeviceHandle $this.FtdiDevice ` -Data $data ` -SpiMode $this.SpiMode ` -CsPin $this.CsPin) } # Read N bytes from SPI device. MOSI stays LOW during the read. [byte[]] Read([int]$count) { if (-not $this.IsInitialized) { $this.Logger.WriteError("SPI not initialized. Call Initialize() first.") return [byte[]]@() } return (Invoke-MpsseSpiRead ` -DeviceHandle $this.FtdiDevice ` -Count $count ` -SpiMode $this.SpiMode ` -CsPin $this.CsPin) } # Full-duplex transfer: write Data bytes while simultaneously clocking in the same count. # Returns the bytes received from MISO. Use this for ADC reads, register reads with dummy # write, and any device that requires MOSI activity during readback. [byte[]] Transfer([byte[]]$data) { if (-not $this.IsInitialized) { $this.Logger.WriteError("SPI not initialized. Call Initialize() first.") return [byte[]]@() } return (Invoke-MpsseSpiTransfer ` -DeviceHandle $this.FtdiDevice ` -Data $data ` -SpiMode $this.SpiMode ` -CsPin $this.CsPin) } } |