blob: 06af65f3c59b50099249729cb961daa3ecc8440c [file] [log] [blame]
#!/usr/bin/env python3
#
# Copyright (c) 2019 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
#
# Author: Sathish Kuttan <sathish.k.kuttan@intel.com>
# This file defines device class that contains functions to
# setup/cconfigure SPI master device and GPIO pins required
# to communicate with the target.
# Member functions are provided to send and receive messages
# over the SPI bus
import yaml
import time
import periphery
import sys
import os
class Device:
"""
Device class containing the interface methods for communicating
with the target using SPI bus and GPIOs
"""
def __init__(self):
"""
Read config file and determine the SPI device, speed, mode
GPIO pin assignments, etc.
Initialize data structures accordingly.
"""
config_file = os.path.dirname(__file__)
config_file += '/config.yml'
with open(config_file, 'r') as ymlfile:
config = yaml.safe_load(ymlfile)
self.name = config['general']['name']
self.spi_device = config['spi']['device']
self.spi_speed = config['spi']['max_speed']
self.spi_mode = None
self.gpio_reset = config['gpio']['reset']
self.gpio_wake = config['gpio']['wake']
self.gpio_irq = config['gpio']['irq']
self.spi = None
self.reset_pin = None
self.wake_pin = None
self.irq_pin = None
def print_config(self):
"""
Print configuration information that was read from config file
"""
print('%s Device on %s' %(self.name, self.spi_device))
print('Max SPI Frequency: %2.1f MHz' % self.spi_speed)
print('Reset GPIO: %d' % self.gpio_reset)
print('Wake GPIO : %d' % self.gpio_wake)
print('IRQ GPIO : %d' % self.gpio_irq)
def configure_device(self, spi_mode, order, bits):
"""
Configure the SPI device and GPIOs for communication with target
"""
self.reset_pin = periphery.GPIO(self.gpio_reset, 'out')
self.wake_pin = periphery.GPIO(self.gpio_wake, 'out')
self.irq_pin = periphery.GPIO(self.gpio_irq, 'in')
self.spi = periphery.SPI(self.spi_device, spi_mode,
self.spi_speed * 1e6)
self.spi.bit_order = order
self.spi.bits_per_word = bits
print('Configured SPI %s for %s.' % (self.spi_device, self.name))
print('Configured GPIO %d for %s Reset.' % (self.gpio_reset, self.name))
print('Configured GPIO %d for %s Wake.' % (self.gpio_wake, self.name))
print('Configured GPIO %d for %s IRQ.' % (self.gpio_irq, self.name))
def check_device_ready(self):
"""
Check whether the target is ready to accept a command as follows:
Wait a minimum time and check whether IRQ is asserted by the target
If IRQ is not asserted, wait maximum time and check again.
Device is ready if IRQ is asserted
"""
min_wait = 0.001 # 1 ms
max_wait = 0.1 # 100 ms
time.sleep(min_wait)
ready = self.irq_pin.read()
if not ready:
time.sleep(max_wait)
ready = self.irq_pin.read()
if not ready:
print('Error: Device not ready', file=sys.stderr)
return ready
def reset_device(self):
"""
Assert the GPIO and deassert after a short duration to reset
the target.
"""
print('Resetting %s ...' % self.name)
self.reset_pin.write(False)
time.sleep(0.1)
self.reset_pin.write(True)
self.check_device_ready()
def send_receive(self, data, wait=True):
"""
Transmit and receive full duplex data over SPI
If requested to wait, wait for device to become ready
before return.
"""
rx_data = self.spi.transfer(data)
if wait:
self.check_device_ready()
return rx_data
def send_bulk(self, data):
"""
Send a byte stream of data without checking for device readiness.
"""
self.spi.transfer(data)
def close(self):
"""
Close the device handle
"""
self.spi.close()