# -*- coding: utf-8 -*-
# Copyright (c) 2017 RS Components Ltd
# SPDX-License-Identifier: MIT License
"""
Manages Pmod HAT port resources, enforcing correct usage and
avoiding conflicts.
"""
from __future__ import absolute_import
from DesignSpark.Pmod import TC1
from DesignSpark.Pmod import AD1
from DesignSpark.Pmod import MIC3
from DesignSpark.Pmod import HB3
from DesignSpark.Pmod import ISNS20
from DesignSpark.Pmod import OLEDrgb
from DesignSpark.Pmod import Error
from DesignSpark.Pmod import SWT
from DesignSpark.Pmod import ACL2
from DesignSpark.Pmod import GPS
from DesignSpark.Pmod import LS1
from DesignSpark.Pmod import KYPD
# Physical pin map of Pmod to BCM I/O
JA1 = 8 #SPI_CE0
JA2 = 10 #SPI0_MOSI
JA3 = 9 #SPI0_MISO
JA4 = 11 #SPI0_CLK
# Gnd JA5
# Vcc JA6
JA7 = 19 #PCM_FS/PWM1
JA8 = 21 #PCM_DOUT/GPCLK1
JA9 = 20 #PCM_DIN/GPCLK0
JA10 = 18 #PCM_CLK/PWM0
# Gnd JA11
# Vcc JA12
JB1 = 7 #SPI_CE1
JB2 = 10 #SPI0_MOSI
JB3 = 9 #SPI0_MISO
JB4 = 11 #SPI_CLK
# Gnd JB5
# Vcc JB6
JB7 = 26
JB8 = 13 #PWM1
JB9 = 3 #SCL1
JB10 = 2 #SDA1
# Gnd JB11
# Vcc JB12
JC1 = 16 #CTS0
JC2 = 14 #TXD0
JC3 = 15 #RXD0
JC4 = 17 #RTS0
# Gnd JB5
# Vcc JB6
JC7 = 4 #GPCLK0
JC8 = 12 #PWM0
JC9 = 5 #GPCLK1
JC10 = 6 #GPCLK2
# Gnd JB11
# Vcc JB12
moduleDict = {
'TC1': TC1,
'AD1': AD1,
'MIC3': MIC3,
'HB3': HB3,
'ISNS20': ISNS20,
'OLEDrgb': OLEDrgb,
'SWT': SWT,
'ACL2': ACL2,
'GPS': GPS,
'LS1': LS1,
'KYPD': KYPD
}
capabilityDict = {
'JAA': [JA1,JA2,JA3,JA4,True,False,False],
'JAB': [JA7,JA8,JA9,JA10,False,False,False],
'JBA': [JB1,JB2,JB3,JB4,True,False,False],
'JBB': [JB7,JB8,JB9,JB10,False,True,False],
'JCA': [JC1,JC2,JC3,JC4,False,False,True], # UART pins are active by default
'JCB': [JC7,JC8,JC9,JC10,False,False,False]
}
portUseDict = {}
def __checkPhysical(module, port):
return module.PHY == port.phy
def __checkCapability(module, port):
if module.CAP == 'SPI' and port._spi == True:
return True
if module.CAP == 'I2C' and port._i2c == True:
return True
if module.CAP == 'UART' and port._uart == True:
return True
if module.CAP == 'GPIO':
return True
# No capability match found
return False
[docs]def createPmod(moduleName, portName):
if moduleName in moduleDict:
module = moduleDict[moduleName]
else:
erma = moduleName+' is not a recognised module identifier'
raise Error.incorrectModuleName(erma)
if portName == 'JA' or portName == 'JB' or portName == 'JC':
port = DSPMod12(portName)
else:
if portName in capabilityDict:
port = DSPMod6(portName)
else:
erma = portName+' is not a recognised port identifier'
raise Error.incorrectPortName(erma)
if __checkPhysical(module,port) == False:
erma = 'chosen port '+portName+' is the wrong size'+moduleName+' is a Pmod'+module.PHY+' module'
raise Error.portCapabilitySupport(erma)
if __checkCapability(module,port) == False:
erma = 'chosen port '+portName+' does not support '+module.CAP
raise Error.portCapabilitySupport(erma)
if port.inUse():
erma = 'chosen port '+portName+' is already in use with '+portUseDict[portName]
raise Error.portInUse(erma)
## Usage conflicts
"""
If SPI is used on JAA or JBB allow only other SPI modules to init
If a non-SPI module is used on JAA or JBB do not allow any other module
"""
if 'JAA' in portUseDict:
cap = moduleDict[portUseDict['JAA']].CAP
if cap == 'SPI':
if portName == 'JBA' or portName == 'JB':
if moduleDict[moduleName].CAP != 'SPI':
erma = 'when port JAA is using an SPI module, port '+portName+' must also only use SPI'
raise Error.portCapabilityConflict(erma)
else:
if portName == 'JBA' or portName == 'JB':
erma = 'when port JAA is not using an SPI module, port JBA is unavailable'
raise Error.portCapabilityConflict(erma)
if 'JBA' in portUseDict:
cap = moduleDict[portUseDict['JBA']].CAP
if cap == 'SPI':
if portName == 'JAA' or portName == 'JA':
if moduleDict[moduleName].CAP != 'SPI':
erma = 'when port JBA is using an SPI module port '+portName+' must also only use SPI'
raise Error.portCapabilityConflict(erma)
else:
if portName == 'JAA' or portName == 'JA':
erma = 'when port JBA is not using an SPI module, port JAA is unavailable'
raise Error.portCapabilityConflict(erma)
## All qualifiers passed
port.setUseModule(moduleName)
if moduleName == 'HB3':
return HB3.PmodHB3(port)
if moduleName == 'AD1':
return AD1.PmodAD1(port)
if moduleName == 'ISNS20':
return ISNS20.PmodISNS20(port)
if moduleName == 'MIC3':
return MIC3.PmodMIC3(port)
if moduleName == 'TC1':
return TC1.PmodTC1(port)
if moduleName == 'OLEDrgb':
return OLEDrgb.PmodOLEDrgb(port)
if moduleName == 'SWT':
return SWT.PmodSWT(port)
if moduleName == 'ACL2':
return ACL2.PmodACL2(port)
if moduleName == 'GPS':
return GPS.PmodGPS(port)
if moduleName == 'LS1':
return LS1.PmodLS1(port)
if moduleName == 'KYPD':
return KYPD.PmodKYPD(port)
[docs]class DSPMod6:
def __init__(self, _portName):
self.portName = _portName
cap = capabilityDict[self.portName]
self.pin1 = cap[0]
self.pin2 = cap[1]
self.pin3 = cap[2]
self.pin4 = cap[3]
self._spi = cap[4]
self._i2c = cap[5]
self._uart = cap[6]
self.phy = '1x6'
[docs] def setUseModule(self,moduleName):
portUseDict[self.portName] = moduleName
[docs] def inUse(self):
return self.portName in portUseDict
[docs]class DSPMod12:
def __init__ (self, _portName):
self.dspMod6A = DSPMod6(_portName + 'A')
self.dspMod6B = DSPMod6(_portName + 'B')
self.pin1 = self.dspMod6A.pin1
self.pin2 = self.dspMod6A.pin2
self.pin3 = self.dspMod6A.pin3
self.pin4 = self.dspMod6A.pin4
self.pin7 = self.dspMod6B.pin1
self.pin8 = self.dspMod6B.pin2
self.pin9 = self.dspMod6B.pin3
self.pin10 = self.dspMod6B.pin4
self._spi = self.dspMod6A._spi # All SPI is on the upper 'a' Pmod port
self._i2c = self.dspMod6B._i2c # Only I2C is on the lower 'b' Pmod port
self._uart = self.dspMod6A._uart # Only UART is on the upper 'a' Pmod port
self.phy = '2x6'
[docs] def setUseModule(self, moduleName):
self.dspMod6A.setUseModule(moduleName)
self.dspMod6B.setUseModule(moduleName)
[docs] def inUse(self):
return self.dspMod6A.inUse() and self.dspMod6B.inUse()