# -*- 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
# 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
}
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)
[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()