ap--/python-seabreeze

Read gpio with raw_usb_bus_access?

mabaquero opened this issue · 2 comments

spectrometer and system information

  • model: HR4000CG-UV-NIR
  • operating system: Windows 10 64bit

current problem

Dear experts,
I want to read one of the digital GPIO pins in my spectrometer, but unfortunately the gpio feature does not seem to be available for my device.

From what I can tell, the only feature that is available is "raw_usb_bus_access".

Does anyone know how to use this feature to configure GPIO pin 0 as an input, and then read it?
If so, could you please share with me a couple of lines of code that I can use as a reference?

Thanks!

Hello @mabaquero
Here are my method use to access FPGA and configure GPIO:

import struct 
import seabreeze
seabreeze.use('cseabreeze')
from seabreeze.spectrometers import list_devices, Spectrometer
  
# FPGA commnd bytes
FPGA_WRITE = 0x6A
FPGA_READ = 0x6B

# FPGA address for GPIO 
MUX_TYPE = 0x48 # GPIO Mux Register  (0 = pin is GPIO pin, 1 = pin is alternate function)
DIR_TYPE = 0x50 # GPIO Output Enable (1 = pin is output, 0=pin is input)
VAL_TYPE = 0x54 # GPIO Data Register (For Ouput = Write value of signal, For Input = Read current GPIO state)

def write_fpga_register(spec: Spectrometer, address: int, val: int):  
    b0 = FPGA_WRITE
    b1 = address.to_bytes(1, byteorder='little')[0]
    b2, b3 = val.to_bytes(2, byteorder='little') 
    request = struct.pack("BBBB", b0, b1, b2, b3) 
    spec.f.raw_usb_bus_access.raw_usb_write(data=request, endpoint='primary_out')
 
def read_fpga_register(spec: Spectrometer, address: int): 
    b0 = FPGA_READ
    b1 = address.to_bytes(1, byteorder='little')[0]  
    request = struct.pack("BB", b0, b1) 
    spec.f.raw_usb_bus_access.raw_usb_write(data=request, endpoint='primary_out') 
    response = spec.f.raw_usb_bus_access.raw_usb_read(endpoint='primary_in', buffer_length=3) 
    return (response[2] << 8) + response[1]

def fpga_major_version(spec: Spectrometer):
    data = read_fpga_register(spec, 0x04) 
    major = (data >> 12) & 0x0f
    minor = (data >> 4) & 0xff
    path = (data >> 0) & 0x0f 
    return major
 
def get_gpio_bit(spec: Spectrometer, type: bytes, pin: int):
    data = read_fpga_register(spec, type)
    return (data & (1 << pin)) 

def set_gpio_bit(spec: Spectrometer,type: bytes, pin: int, val: int):
    data = read_fpga_register(spec, type) 
    mask = (1 << pin)
    data &= ~mask 
    if val == 1:
        data |= mask 
    write_fpga_register(spec, type, data)

# Define variables
GPIO_PIN = 0 
 
spec = Spectrometer.from_first_available()

set_gpio_bit(spec, MUX_TYPE, GPIO_PIN, 0)   # GPIO pin
set_gpio_bit(spec, DIR_TYPE, GPIO_PIN, 1)   # Output signal
set_gpio_bit(spec, VAL_TYPE, GPIO_PIN, 1)   # Signal goes HIGH at GPIO pin
 
#Check signal value of GPIO pin
pin0_status = get_gpio_bit(spec, VAL_TYPE, GPIO_PIN)
print(pin0_status )

spec.close()

Result: Spectrometer pulse HIGH digital signal to GPIO PIN 0
342331949_3245068009139037_5663111713827760130_n

Cheer!!!

Thank you very much @anpjam459 ! I will give it a try :)