Friday 01 2021

MCP3201 Programming Log - Part 1

MCP3201 Programming Log - Part 1

# Program:

#   adc_util01_v118.py tlfong01 2020aug17hkt1747
#
# Function:
#   Test (1) SPI loockback and repeat send byte
#        (2) test MCP3008, MCP3201, and MCP3208
#
# Contents
#  1. Program Config
#  2. System Utilities
#  3. Dictionaries
#  4. SPI Testing and Troubleshooting Functions
#  5. Test MCP3008, MCP3201, and MCP3208 ADC

from time     import sleep
import               spidev
import               inspect
from datetime import datetime
import spi_util_01_v117 as spiutil

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 1. Program Config ***

programTitle = 'adcutil_01_v117'

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 2. System Utilities ***

def printBeginProgram():
    print('     Begin program ' + programTitle + '  tlfong01  ' + timeNowStr)
    #print(' ')
    return

def printEndProgram():
    print('\n     End   program ' + programTitle + '  tlfong01  ' + timeNowStr)
    return    
        
def printTitle(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]))    
    return

def printTitleNoNewLine(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]), end = '')    
    return

def printTitleString(title, indentFormat, string):
    printTitleNoNewLine(title, indentFormat)
    print('=', string)
    return

def printStarLine():
    print('')
    printTitle(('*' * 80), indentFormat480)
    print('')
    return

def printBeginExecFunction():
    functionName = inspect.stack()[1][3] 
    title = 'Begin Execute Function ' + functionName + '  ' + timeNowStr
    printStarLine()
    printTitle(title, indentFormat480)
    print('')
    printTitleString('Function Name', indentFormat640, functionName)
    return
    
def printEndExecFunction():
    title = 'End   Execute Function ' + inspect.stack()[1][3] + '  ' + timeNowStr
    print('')
    printTitle(title, indentFormat480)
    printStarLine()
    return

def convertOneByteNumToFourCharStr(oneByteNum): 
    tempStr = ((hex(oneByteNum))[2:])
    if (len(tempStr) != 2):
        tempStr = '0' + tempStr
    fourCharStr = '0x' + tempStr
    return fourCharStr

def convertTwoByteNumToEightCharStr(twoByteNum): # new <<<<<<<<<<
    tempStr = ((hex(twoByteNum))[2:])
    tempStr = '0' * (4 - len(tempStr)) + tempStr
    tenCharStr = '0x' + tempStr
    return tenCharStr

def pauseSeconds(pauseSecondsName):
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    sleep(pauseSeconds)
    return

# *** Time Now String ***
 
timeNowStr = str(datetime.now())[0:16]

# *** Format string for print functions ***

indentFormat480 = [4, 80]
indentFormat608 = [6,  8]
indentFormat610 = [6, 10]
indentFormat615 = [6, 15]
indentFormat630 = [6, 30]
indentFormat640 = [6, 40]

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 3. Dictionaries ***

# *** Repeat Times and Pause Dict ***

repeatTimesDict = {
    '1 times'         :        1,
    '10 times'        :       10,
    '100 times'       :      100,
    '1000 times'      :     1000,
    '10000 times'     :    10000,
    '100000 times'    :   100000,
    '1000000 times'   :  1000000,
    '10000000 times'  : 10000000
    }

sampleSizeDict = {
    '1 sample'            :         1,
    '10 samples'          :        10,
    '100 samples'         :       100,
    '1000 samples'        :      1000,
    '10000 samples'       :     10000,
    '100000 samples'      :    100000,
    '1000000 samples'     :   1000000,
    '10000000 samples'    :  10000000,
    '10 million samples'  : 100000000,
    }
        
pauseSecondsDict = {
    '0.001 second'    : 0.001, 
    '0.002 second'    : 0.002,
    '0.01 second'     : 0.01,
    '0.1 second'      : 0.1,
    '10 ms'           : 0.01
    }

spiSpeedNameListDict = \
    {
    'Long SPI speeds list' : ['10 kHz', '50 kHz', '100 kHz', '400 kHz', '1 MHz', '2 MHz', '4 MHz', '5 MHz', '6 MHz', '8 MHz', '10 MHz'],
    'Short SPI speeds list' : ['100 kHz', '400 kHz', '1 MHz'],
    '1 MHz list' : ['1 MHz'],
    }

refVoltDict = \
    {
    '0.00V'        : 0.00,
    '1.68V'        : 1.68,
    '2.048V'       : 2.048,
    '3.30V'        : 3.30,
    '4.096V'       : 4.096
    }

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 4. SPI Utilities (for troubleshooting) ***

def testSpiUtil():
    
    print('       Begin testSpiUtil(), ...\n')
    
    # *** Test SPI Set Port Speed ***
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')
    #setSpiPortSpeedBySpiPortNameList(spiPortNameListAll, '100 kHz')  
        
    # *** Test SPI loopback ***
    #spiutil.testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')
    
    # *** Test SPI Repeat send one byte ***
    #spiutil.testRepeatSendOneByteSpiPortNameList(['SpiPort00'], '0x5b', '0.01 second', '100 times')   
    #spiutil.testRepeatSendOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b', '0.01 second', '100 times')   
   
    print('\n\n       End   testSpiUtil(), ...')
    return

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********  

# *** ADC Functions ***

def testAdc(spiPortName, adcName, spiSpeedName):
    
    # 1. *** Set SPI speed ***
    print('\n       # *** Set SPI Port Speed ***')
    spiutil.setSpiPortSpeedBySpiPortNameList([spiPortName], spiSpeedName)
    print('')
    
    # 2. *** Test SPI loopback (for troubleshooting only) ***
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')
    
    # 3. *** Test ADC ***
    if adcName == 'MCP3208':
        pass
        # / to continue, ...        
        print('       ADC 12 Bit Results =', hex(adc12BitResults))
    if adcName == 'MCP3008':
        pass
        # / to continue, ...
    if adcName == 'MCP3201':
        print('       *** Read', adcName, 'Conversion Results ***')
        #spiPort = spiutil.spiPortDict[spiPortName]
        #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
        #adcResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
        adc12BitResults = readMcp3201(spiPortName)
        adcVolts   = (adc12BitResults / 0xfff) * 3.3
        print('       MCP3201 Results in 12 bits binary (expect fff/2~= 0x0800) =', convertTwoByteNumToEightCharStr(adc12BitResults))
        print('                       in V (expect 3.3V /2 ~= 1.65V)            =', "%.2f" % adcVolts, 'V')
    return

def readMcp3201BinaryResults(spiPortName):
    spiPort = spiutil.spiPortDict[spiPortName]
    recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
    adcBinaryResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
    return adcBinaryResults

def readMcp3201DecimalResults(spiPortName):
    adc12BitResults = readMcp3201(spiPortName)
    adcVoltResults = (adc12BitResults / 0xfff) * 3.3
    return adcDecimalResults

def repeatReadMcp3201(spiPortName, PauseTimeName, repeatTimesName):
    spiPort = spiutil.spiPortDict[spiPortName]
    PauseTime = PauseTimeDict[PauseTimeName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    
    for count in range(repeatTimes):
        #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
        #adcResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
        adc12BitResults = readMcp3201(spiPortName)
        sleep(PauseTime)
    return adc12BitResults

def readAdcMultipleSpiSpeedsMultipleTimes(spiPortName, adcName, refVoltName, speedNameListName, sampleSizeName):
    spiPort = spiutil.spiPortDict[spiPortName]
    
    print('         Test Config: SPI Port =', spiPortName, ';', 'ADC =', adcName, ';', 'Speed List =',  speedNameListName, ';', \
          'Sample Size =', sampleSizeName) 
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))    
    print('        ', 'SPI Port'.rjust(10), 'Speed'.rjust(10), 'Mean 12bit'.rjust(10), 'Mean (V)'.rjust(10), \
          'Error (%)'.rjust(10), 'Max Volt'.rjust(10), 'Min Volt'.rjust(10), 'MaxMin Dif'.rjust(10), end = '')
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))     
  
    refVolt = refVoltDict[refVoltName]
    speedNameList = spiSpeedNameListDict[speedNameListName]
    sampleSize = sampleSizeDict[sampleSizeName]
    
    for speedName in speedNameList:
      # *** Set SPI speed ***
      spiutil.setSpiPortSpeedByName(spiPortName, speedName)
      
      # *** Results List *** 
      binResultList =  [0.0 for x in range(sampleSize)]
      decResultList =  [0.0 for x in range(sampleSize)]
      
      # *** Repeat ADC, and analyse readings ***
      for count in range(sampleSize): 
          if adcName == 'MCP3008':
              print('Not available')
          if adcName == 'MCP3208':
              print('Not available')
          if adcName == 'MCP3201':
              recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x5b, 0x5c)
              binResult = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
              decResult = (binResult / 0xfff) * refVolt
              error      = ((refVolt - decResult) / refVolt) * 100
              binResultList[count] = binResult
              decResultList[count] = decResult
      
      maxDecResult  = max(decResultList)
      minDecResult  = min(decResultList)
      meanDecResult = sum(decResultList) / sampleSize
      maxMinDiff    = maxDecResult - minDecResult
        
      print('        ', spiPortName.rjust(10), end = '')
      print('', speedName.rjust(10), end = '')
      print('', convertTwoByteNumToEightCharStr(binResult).rjust(10), end = '')  
      print('', ("%.3f" % decResult).rjust(10), end = '')
      print('', ("%.1f" % error).rjust(10), end = '')
      print('', ("%.3f" % maxDecResult).rjust(10), end = '')
      print('', ("%.3f" % minDecResult).rjust(10), end = '')
      print('', ("%.3f" % maxMinDiff).rjust(10), end = '')
      
      print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10),'----------'.rjust(10))        
    return


def readAdcMultipleSpiSpeedsMultipleTimesNoPrintStatements(spiPortName, adcName, refVoltName, speedNameListName, sampleSizeName):
    spiPort = spiutil.spiPortDict[spiPortName]
    
    print('\n         Test Config: SPI Port =', spiPortName, ';', 'ADC =', adcName, ';', 'Speed List =',  speedNameListName, ';', \
          'Sample Size =', sampleSizeName) 
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))    
    print('        ', 'SPI Port'.rjust(10), 'Speed'.rjust(10), 'Mean 12bit'.rjust(10), 'Mean (V)'.rjust(10), \
          'Error (%)'.rjust(10), 'Max Volt'.rjust(10), 'Min Volt'.rjust(10), 'MaxMin Dif'.rjust(10), end = '')
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))     
  
    refVolt = refVoltDict[refVoltName]
    speedNameList = spiSpeedNameListDict[speedNameListName]
    sampleSize = sampleSizeDict[sampleSizeName]
    
    for speedName in speedNameList:
      # *** Set SPI speed ***
      spiutil.setSpiPortSpeedByName(spiPortName, speedName)
      pauseSecondsName = '10 ms'
     
      
      # *** Results List *** 
      #binResultList =  [0.0 for x in range(sampleSize)]
      #decResultList =  [0.0 for x in range(sampleSize)]
      
      # *** Repeat ADC, and analyse readings ***
      for count in range(sampleSize): 
          #if adcName == 'MCP3008':
          #    print('Not available')
          #if adcName == 'MCP3208':
          #    print('Not available')
          #if adcName == 'MCP3201':
          #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
          recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x5b, 0x5c)
          #binResult = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
          #decResult = (binResult / 0xfff) * 3.3
          #error      = ((refVolt - decResult) / refVolt) * 100
          #binResultList[count] = binResult
          #decResultList[count] = decResult
          pauseSeconds(pauseSecondsName)
      
      #maxDecResult  = max(decResultList)
      #minDecResult  = min(decResultList)
      #meanDecResult = sum(decResultList) / sampleSize
      #maxMinDiff    = maxDecResult - minDecResult
        
      #print('        ', spiPortName.rjust(10), end = '')
      #print('', speedName.rjust(10), end = '')
      #print('', convertTwoByteNumToEightCharStr(binResult).rjust(10), end = '')  
      #print('', ("%.3f" % decResult).rjust(10), end = '')
      #print('', ("%.1f" % error).rjust(10), end = '')
      #print('', ("%.3f" % maxDecResult).rjust(10), end = '')
      #print('', ("%.3f" % minDecResult).rjust(10), end = '')
      #print('', ("%.3f" % maxMinDiff).rjust(10), end = '')
      
      print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10),'----------'.rjust(10))        
    return


# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** ********** 

# *** Old tests ***

    # *** Set SPI port speed ***
    #print('       # *** Set SPI Port Speed ***')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    
    #print('       # *** Repeat read MCP3201 ***') # <<< Not tested >>>
    #repeatReadMcp3201('SpiPort00', '10 ms', '100 times') 
    
    # *** Loopback 1/2 bytes ***
    #spiutil.testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')

    # *** Read MCP3201 ADC result at 100kHz ***
    #print('       # *** Test MCP3201 ADC ***')
    #testAdc('SpiPort00', 'MCP3201', '100 kHz')
    
    #print('\n       # *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    # readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', 'Long SPI speeds list', '10 samples')   # Long SPI speeds list
    #readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', 'Short SPI speeds list', '100 samples')  # Short SPI speeds list 
    #readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', '1 MHz list', '100000 samples')  # 1 MHz speed list
    
    #print('\n       *** Set SpiPort00 1 MHz ***')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz')
    
    #print('\n       *** Loopback SpiPort00 two bytes 0x5b, 0x5c (short MOSI and MISO ***')    
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')    
    
    #print('\n       *** Repeat send two bytes 0x5b, 0x5c (can keep MOSI, MISO shorted) ***')
    #spiutil.testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '5 us', '10000000 times')

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** ********** 

# *** Main ***

def main():
    printBeginProgram()
    
# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** ********** 
   
    # 1. Set SPI Speed 1 MHz  <<< SpiPort00 <<<
    print('\n       *** Set SpiPort00 1 MHz ***')
    spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz') # <<< SpiPort00 <<<
    
    # 2. Loop back two bytes 0x5b, 0x5c <<< SpiPort 00
    print('\n       *** Loopback SpiPort00 two bytes 0x5b, 0x5c (short MOSI and MISO ***')    
    spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c') # <<< SpiPort00 <<<
    
    # 1. Set SPI Speed 1 MHz <<< SpiPort10 <<< 
    print('\n       *** Set SpiPort10 1 MHz ***')
    spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort10'], '1 MHz') # <<< SpiPort10 <<<
    
    # 2. Loop back two bytes 0x5b, 0x5c *** <<< SpiPort 10
    print('\n       *** Loopback SpiPort10 two bytes 0x5b, 0x5c (short MOSI and MISO ***')    
    spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort10'], '0x5b', '0x5c') # <<< SpiPort10 <<<   

    # ********** ********** ********** ********** ********** ********** ********** 
    # ********** ********** ********** ********** ********** ********** **********   
 
    # 4. Read MCP3201 10 Million Times (To display SPI signals using a scope) #<<< SpiPort10 <<<
    #print('\n       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    #readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', '1 MHz list', '10 million samples') 
 
    # ********** ********** ********** ********** ********** ********** ********** 
    # ********** ********** ********** ********** ********** ********** **********  
 
    # 3. Read MCP3201 10 Times (To read 10 samples to get (1) ~= 2.82V if MSOI shorted MISO, (2) 1.65V if MCP3201
    print('\n       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', '1 MHz list', '10 samples') # <<< SpiPort00 <<<
    
    # 3. Read MCP3201 10 Times (To read 10 samples to get (1) ~= 2.82V if MSOI shorted MISO, (2) 1.65V if MCP3201
    print('\n       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    readAdcMultipleSpiSpeedsMultipleTimes('SpiPort10', 'MCP3201', '1.68V', '1 MHz list', '10 samples') # <<< SpiPort10
    
    printEndProgram()
    return

if __name__ == '__main__':
    main()

# End of program

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** Sample Output ***

'''
>>> %Run adc_util_01_v117.py
     Begin program adcutil_01_v117  tlfong01  2020-08-15 17:45

       *** Set SpiPort00 1 MHz ***
       spiPortName   = SpiPort00
       spiSpeedName  = 1 MHz

       *** Loopback SpiPort00 two bytes 0x5b, 0x5c (short MOSI and MISO ***
       sendBytes                               = 0x5b 0x5c
       recvBytes                               = 0x1f 0xfa

       *** Set SpiPort10 1 MHz ***
       spiPortName   = SpiPort10
       spiSpeedName  = 1 MHz

       *** Loopback SpiPort10 two bytes 0x5b, 0x5c (short MOSI and MISO ***
       sendBytes                               = 0x5b 0x5c
       recvBytes                               = 0x1f 0xe2

       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***
         Test Config: SPI Port = SpiPort00 ; ADC = MCP3201 ; Speed List = 1 MHz list ; Sample Size = 10 samples

         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
           SPI Port      Speed Mean 12bit   Mean (V)  Error (%)   Max Volt   Min Volt MaxMin Dif
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00      1 MHz     0x0ff1      1.674        0.3      1.678      1.668      0.010
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------

       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***
         Test Config: SPI Port = SpiPort10 ; ADC = MCP3201 ; Speed List = 1 MHz list ; Sample Size = 10 samples

         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
           SPI Port      Speed Mean 12bit   Mean (V)  Error (%)   Max Volt   Min Volt MaxMin Dif
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort10      1 MHz     0x0fed      1.673        0.4      1.680      1.667      0.013
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------

     End   program adcutil_01_v117  tlfong01  2020-08-15 17:45
>>> 
'''
 # *** End of program ***




# Program:
#  
spi_util_01_v117.py tlfong01 2020aug14hkt2117
# Function:

#   1. SPI one byte loopback
#   2. SPI repeatedly send one byte
#
# System Config: 
#   Rpi4B buster, python 3.7.3, thonny v3.2.7
#   pi@raspberrypi:~ $ date = Sat 08 Aug 2020 04:16:17 PM HKT
#   pi@raspberrypi:~ $ uname -a = Linux raspberrypi 4.19.118-v7l+ #1311 SMP Mon Apr 27 14:26:42 BST 2020 armv7l GNU/Linux

# Test Function Definitions:
#
# Test 1 - loopBackTest() - SPI port send and receive one byte.
#   Function - Send one byte to MOSI and read it back from MISO.
#     Setup - Connet MOSI pin to MISO pin to form a loop.
#
# Test 2 - repeatSendByte() - SPI port repeatedly send one bytes. 
#   Function - Repeat many times sending a byte, pause after each byte.

# Notes
#   1. SPI ports setup notes
#      To enable SPI and setup SPI 10, 11, 12 ports, add these two lines to /boot/config.txt
#        dtparam=spi=on
#        dtoverlay=spi1-3cs
#      To list SPI devices
#        pi@raspberrypi:~ $ ls /dev/spi*
#        /dev/spidev0.0  /dev/spidev0.1  /dev/spidev1.0  /dev/spidev1.1  /dev/spidev1.2

#   2. Notes of loopback function
#     Call example - testLoopbackOneByte(spiPort00)
#     Function     - send byte 0x5b to SPI MOSI and read byte from MISO
#     Setup        - must connect MOSI pin to MISO pin to loop back
#     Note         - 1. Only checks if MISO echoes MOSI, CS0, CS1, CS2 is not checked
#                    2. To check if SPI 0, CS0, CS1, or SPI1 CS0, CS1, CS2, need a scope to display repeat send bytes 

from time     import sleep
import               spidev
import               inspect
from datetime import datetime

# *** Program Config ***

programTitle = 'spituil_v95'

# *** SPI Port Setup/Config ***

spiPort00 = spidev.SpiDev()
spiPort00.open(0,0)

spiPort01 = spidev.SpiDev()
spiPort01.open(0,1)

spiPort10 = spidev.SpiDev()
spiPort10.open(1,0)

spiPort11 = spidev.SpiDev()
spiPort11.open(1,1)

spiPort12 = spidev.SpiDev()
spiPort12.open(1,2)


# *** SPI Port Name List and Dict ***

spiPortNameList00  = ['SpiPort00']
spiPortNameList01  = ['SpiPort01']
spiPortNameListAll = ['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12']

spiPortDict = {
    'SpiPort00'       : spiPort00,
    'SpiPort01'       : spiPort01,
    'SpiPort10'       : spiPort10,
    'SpiPort11'       : spiPort11,
    'SpiPort12'       : spiPort12,
    }

spiSpeedDict = {
    '10 MHz'       : 10000000,
    '8 MHz'        :  8000000,
    '6 MHz'        :  6000000,
    '5 MHz'        :  5000000,
    '4 MHz'        :  4000000,
    '2 MHz'        :  2000000,
    '1 MHz'        :  1000000,
    '400 kHz'      :   400000,
    '100 kHz'      :   100000,
    '50 kHz'       :    50000,
    '10 kHz'       :    10000,
    '1 kHz'        :     1000,
    '500 Hz'       :      500,
    }

dataByteDict = {
    '0x00'            :     0x00,
    '0x5a'            :     0x5a,
    '0x5b'            :     0x5b,
    '0x5c'            :     0x5c,
    '0x5d'            :     0x5d,
    '0x5e'            :     0x5e,
    '0x5f'            :     0x5f,
    '0x55'            :     0x55,
    '0x66'            :     0x66,
    '0x77'            :     0x77,
    }
    
repeatTimesDict = {
    '100 times'       :      100,
    '1000 times'      :     1000,
    '10000 times'     :    10000,
    '100000 times'    :   100000,
    '1000000 times'   :  1000000,
    '10000000 times'  : 10000000
    }
        
pauseSecondsDict = {
    '0.000001 second' : 0.000001,
    '0.00005 second'  : 0.00005,
    '0.0001 second'   : 0.0001,
    '0.001 second'    : 0.001, 
    '0.002 second'    : 0.002,
    '0.01 second'     : 0.01,
    '0.1 second'      : 0.1,
    '10 us'           : 0.000001,
    '5 us'            : 0.0000005,
    }

# *** Set SPI Port Speed Functions ***

def setSpiPortSpeedByName(spiPortName, spiSpeedName):
    spiPort = spiPortDict[spiPortName]
    spiSpeed = spiSpeedDict[spiSpeedName]
    spiPort.max_speed_hz = spiSpeed
    return

def setSpiPortSpeedBySpiPortNameList(spiPortNameList, spiSpeedName):
    for spiPortName in spiPortNameList:
        setSpiPortSpeedByName(spiPortName, spiSpeedName)
        print('       spiPortName   =', spiPortName)
        print('       spiSpeedName  =', spiSpeedName)
    return

# *** Example Calls ***

#setSpiPortSpeedBySpiPortNameList('SpiPortNameListAll, '100 kHz')  
#setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')  

# *** Print Functions ***

def printBeginProgram():
    print('     Begin program ' + programTitle + '  tlfong01  ' + timeNowStr)
    print(' ')
    return

def printEndProgram():
    print('\n     End   program ' + programTitle + '  tlfong01  ' + timeNowStr)
    return    
        
def printTitle(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]))    
    return

def printTitleNoNewLine(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]), end = '')    
    return

def printTitleString(title, indentFormat, string):
    printTitleNoNewLine(title, indentFormat)
    print('=', string)
    return

def printStarLine():
    print('')
    printTitle(('*' * 100), indentFormat480)
    print('')
    return

def printBeginExecFunction():
    functionName = inspect.stack()[1][3] 
    title = 'Begin Execute Function ' + functionName + '  ' + timeNowStr
    printStarLine()
    printTitle(title, indentFormat480)
    print('')
    printTitleString('Function Name', indentFormat640, functionName)
    return
    
def printEndExecFunction():
    title = 'End   Execute Function ' + inspect.stack()[1][3] + '  ' + timeNowStr
    print('')
    printTitle(title, indentFormat480)
    printStarLine()
    return

def convertOneByteNumToFourCharStr(oneByteNum): 
    tempStr = ((hex(oneByteNum))[2:])
    if (len(tempStr) != 2):
        tempStr = '0' + tempStr
    fourCharStr = '0x' + tempStr
    return fourCharStr

# *** Time Now String ***
 
timeNowStr = str(datetime.now())[0:16]

# *** Format string for print functions ***

indentFormat480 = [4, 80]
indentFormat608 = [6,  8]
indentFormat610 = [6, 10]
indentFormat615 = [6, 15]
indentFormat630 = [6, 30]
indentFormat640 = [6, 40]

# *** SPI Send/Receive/Loopback/RepeatSend Byte Functions ***

# *** Send/Receive 1/2/3 bytes functions called by SPI ports spiPort00, spiPort01, spiPort10, spiPort11, spiPort12 ***

def spiSendRecvOneByte(spiPort, sendByte):
  sendByteArray = [sendByte]
  recvByteArray = spiPort.xfer(sendByteArray)  
  return recvByteArray

def spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2):
    sendByteArray = [sendByte1, sendByte2]
    recvByteArray = spiPort.xfer2(sendByteArray)    
    return recvByteArray

def spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
    sendByteArray = [sendByte1, sendByte2, sendByte3]
    recvByteArray = spiPort.xfer2(sendByteArray)    
    return recvByteArray

# *** Send/Receive 1/2/3 bytefunctions called by SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def spiSendRecvOneByteByName(spiPortName, sendByteName):
  spiPort  = spiPortDict[spiPortName]
  sendByte = dataByteDict[sendByteName]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte)  
  return recvByteArray

def spiSendRecvTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name):
  print(sendByte1Name)
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte1. sendByte2)  
  return recvByteArray

def spiSendRecvThreeBytesByName(spiPortName, sendByte1Name, sendByte2Name, sendByte3Name):
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  sendByte3 = dataByteDict[sendByte3Name]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte1. sendByte2, sendByte3)  
  return recvByteArray

# *** Loopback 1/2/3 byte functions called by SPI ports spiPort00, spiPort01, spiPort10, spiPort11, spiPort12 ***

def loopBackOneByte(spiPort, sendByte):
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte)
  recvByte      = recvByteArray[0]

  print('\n       Begin testLoopbackOneByte(),....')
  #print('')
  print('          sendByte                                = ', hex(sendByte))
  print('          recvByte                                = ', hex(recvByte))
  #print('')
  print('       End testLoopbackOneByte(),....\n')
  return

def loopbackTwoBytes(spiPort, sendByte1, sendByte2):
    #fprint.printBeginExecFunction()
    recvByteArray      = spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
    recvByte1          = recvByteArray[0]
    recvByte2          = recvByteArray[1]
    sendBytes = convertOneByteNumToFourCharStr(sendByte1) + ' ' + convertOneByteNumToFourCharStr(sendByte2)
    printTitleString('sendBytes', indentFormat640, sendBytes)  
    recvBytes = convertOneByteNumToFourCharStr(recvByte1) + ' ' + convertOneByteNumToFourCharStr(recvByte2)
    printTitleString('recvBytes', indentFormat640, recvBytes)
    #printEndExecFunction()
    return

def loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
    #fprint.printBeginExecFunction()    
    recvByteArray      = spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
    recvByte1          = recvByteArray[0]
    recvByte2          = recvByteArray[1]
    recvByte3          = recvByteArray[2]
    sendBytes = convertOneByteNumToFourCharStr(sendByte1) + ' ' + convertOneByteNumToFourCharStr(sendByte2) + ' ' + \
                convertOneByteNumToFourCharStr(sendByte3)
    printTitleString('sendBytes', indentFormat640, sendBytes)
    recvBytes = convertOneByteNumToFourCharStr(recvByte1) + ' ' + convertOneByteNumToFourCharStr(recvByte2) + ' ' + \
                convertOneByteNumToFourCharStr(recvByte3)
    printTitleString('sendBytes', indentFormat640, recvBytes)
    #printEndExecFunction()
    return

# *** Loopback 1/2/3 byte functions called bycalled SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def loopbackOneByteByName(spiPortName, sendByteName):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte = dataByteDict[sendByteName]
  loopBackOneByte(spiPort, sendByte)
  #printEndExecFunction() 
  return

def loopbackTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  
  loopbackTwoBytes(spiPort, sendByte1, sendByte2)
  #printEndExecFunction() 
  return

def loopbackThreeBytesByName(spiPortName, sendByte1Name, sendByte2Name, sendByte3Name):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  sendByte3 = dataByteDict[sendByte3Name]
  
  loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
  #printEndExecFunction() 
  return

# *** Test loopback one byte function call by SPI port ***

def testLoopbackOneByte(spiPort, dataByte):
  loopackOneByte(spiPort, dataByte)
  return

# *** Test loopback one byte function called by SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def testLoopbackOneByteByName(spiPortName, dataByteName):
  loopackOneByteByName(spiPortName, dataByteName)
  return

def testLoopbackTwoBytesByName(spiPortName, dataByte1Name, dataByte2Name):
    spiPort = spiPortDict[spiPortName]
    dataByte1 = dataByteDict[dataByte1Name]
    dataByte2 = dataByteDict[testByte2Name]
    loopbackTwoBytes(spiPort, datatByte1, dataByte2)
    return

def testLoopbackThreeBytesByName(spiPortName, dataByte1Name, dataByte2Name, dataByte3Name):
    spiPort = spiPortDict[spiBusName]
    dataByte1 = dataByteDict[dataByte1Name]
    dataByte2 = dataByteDict[dataByte2Name]
    dataByte3 = dataByteDict[testByte3Name]
    loopbackThreeBytes(spiPort, dataByte1, dataByte2, datatByte3)
    return

# *** Test Example Loopback 1/2/3 bytes called by name ***

def testLoopbackOneByteByNameSpiPort00x5b():
    printBeginExecFunction()  
    loopBackOneByteByName('SpiPort00', '0x5b')
    printEndExecFunction()  
    return

def testLoopbackTwoBytesByNameSpiPort00x5bx5c():
    printBeginExecFunction()  
    loopBackTwoBytesByName('SpiPort00', '0x5b', '0x5c')
    printEndExecFunction()  
    return

def testLoopbackThreeBytesByNameSpiPort00x5bx5cx5d():
    printBeginExecFunction()  
    loopBackThreeBytesByName('SpiPort00', '0x5b', '0x5c', '0x5d')
    printEndExecFunction()  
    return

# *** Example Loopback 1 byte calling all SPI ports 00, 01, 10, 11, 12 ***

def testLoopbackSpiPortsAll():
    print('\n*** testLoopbackOneByte(spiPort00, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort00, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort01, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort01, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort10, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort10, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort11, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort11, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort12, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort12, 0x5b)

    print('\n*** testLoopbackOneByteByName("spiPort00", "0x5b") ***', end = '')
    testLoopbackOneByteByName('SpiPort00', '0x5b')
    return

# *** Example Loopback 1/2/3 byte calling SPI port names ***

def testLoopbackOneTwoThreeBytesSpiPorts00ByName():
    testLoopbackOneByteByNameSpiPort00x5b()
    testLoopbackTwoBytesByNameSpiPort00x5bx5c()
    testLoopbackThreeBytesByNameSpiPort00x5bx5cx5d()
    return

# *** Example Loopback 1/2/3 byte calling SPI port name list ***

def testLoopbackOneByteSpiPortNameList(spiPortNameList, dataByteName):
    #print('       testLoopbackOneByteSpiPortNameList(),....')
    for spiPortName in spiPortNameList:
        loopbackOneByteByName(spiPortName, dataByteName)
    #print('       End   testLoopbackOneByteSpiPortNameList().\n')
    return

def testLoopbackTwoBytesSpiPortNameList(spiPortNameList, dataByte1Name, dataByte2Name):
    for spiPortName in spiPortNameList:
        loopbackTwoBytesByName(spiPortName, dataByte1Name, dataByte2Name)
    return

def testLoopbackThreeBytesSpiPortNameList(spiPortNameList, dataByte1Name, dataByte2Name, dataByte3Name):
    for spiPortName in spiPortNameList:
        loopbackThreeBytesByName(spiPortName, dataByte1Name, dataByte2Name, dataByte3Name)
    return

# *** Repeat send byte functions ***

def repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes):
    print('       Begin repeatSendByte(),....')
    print('           Now use a scope to display the SPI signals, MOSI, MISO, CSn, ...')
    for i in range(repeatTimes):
      spiSendRecvOneByte(spiPort, sendByte)
      sleep(pauseSeconds)
    print('       End   repeatSendByte().', end = '')
    return

def repeatSendTwoBytes(spiPort, sendByte1, sendByte2, pauseSeconds, repeatTimes):
    print('       Begin repeatSendByte(),....')
    print('           Now use a scope to display the SPI signals, CLK, MOSI, MISO, CS0.  <ctrl>C to abort')
    for i in range(repeatTimes):
      spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
      sleep(pauseSeconds)
    print('       End   repeatSendByte().', end = '')
    return

def repeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName):
    spiPort  = spiPortDict[spiPortName]
    sendByte = dataByteDict[sendByteName]
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes)  
    return

def repeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName):
    spiPort  = spiPortDict[spiPortName]
    sendByte1 = dataByteDict[sendByte1Name]
    sendByte2 = dataByteDict[sendByte2Name]    
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    repeatSendTwoBytes(spiPort, sendByte1, sendByte2, pauseSeconds, repeatTimes)  
    return

# *** Test repeat send one byte functions ***

def testRepeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes):
    repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes)
    return

def testRepeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName):
    repeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName)
    return

def testRepeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName):
    repeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName)
    return

# *** Test Examples ***

def testRepeatSendOneByteByNameSpiPort000x5b0001Seconds100Times():
    testRepeatSendOneByteByName('SpiPort00', '0x5b', '0.001 second', '100 times')    
    return

def testRepeatSendOneByteSpiPortsAll():
    print('\n*** testRepeatSendOneByte(spiPort00, 0x5b, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort00, 0x5b, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort01, 0x5b, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort01, 0x5b, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort10, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort10, 0xb5, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort11, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort11, 0xb5, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort12, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort12, 0xb5, 0.001, 200)
    
    return
    
def testRepeatSendOneByteSpiPortsAllByName():
    printBeginExecFunction()  
    testRepeatSendOneByteByName('SpiPort00', '0x5b', '0.001 second', '100 times')
    printEndExecFunction()  
    return

def testRepeatSendOneByteSpiPortNameList(spiPortNameList, sendByteName, pauseSeconds, repeatTimes):
    for spiPortName in spiPortNameList:
        testRepeatSendOneByteByName(spiPortName, sendByteName, pauseSeconds, repeatTimes)
    return

def testRepeatSendTwoBytesSpiPortNameList(spiPortNameList, sendByte1Name, sendByte2Name, pauseSeconds, repeatTimes):
    for spiPortName in spiPortNameList:
        testRepeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSeconds, repeatTimes)
    return

# *** Old Tests ***

    # *** Test loopback functions ***
    #testLoopbackSpiPortsAll()
    #testLoopbackOneTwoThreeBytesSpiPorts00ByName()
    #testLoopbackSpiPortNameListAll()  
    #testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')    
    #testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')
    #testLoopbackThreeBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '0x5d')

# *** Main ***

def main():

    # *** Print program title ***    
    printBeginProgram()
        
    # *** Set SPI Port Speed ***
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz') 
    #setSpiPortSpeedBySpiPortNameList(spiPortNameListAll, '100 kHz')  
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')     
  
    # *** Loopback Tests ***
    #testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')
    
    # *** Repeat Send Byte Tests ***
    #testRepeatSendOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b', '0.01 second', '100 times')
    
    # *** Repeat Send Two Bytes Tests ***
    testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '5 us', '1000000 times')
        
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz')         
    #testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '0.01 second', '1000000 times')

    printEndProgram()

# ********************************************************************************

if __name__ == '__main__':
    main()

# End of program

# *** Sample Output *** 

# *** End ***




4:22pm Sun. 8/16/2020

5:28pm Fri. 8/14/2020

MCP3201 Testing Program V1.2


https://penzu.com/p/f9966699


5:28pm Fri. 8/14/2020


# Program:
#  
adc_util01_v116.py tlfong01 2020aug13hkt1639
#

# Function:
#   Test (1) SPI loockback and repeat send byte
#        (2) test MCP3008, MCP3201, and MCP3208
#
# Contents
#  1. Program Config
#  2. System Utilities
#  3. Dictionaries
#  4. SPI Testing and Troubleshooting Functions
#  5. Test MCP3008, MCP3201, and MCP3208 ADC

from time     import sleep
import               spidev
import               inspect
from datetime import datetime
import spi_util_01_v113 as spiutil

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 1. Program Config ***

programTitle = 'adcutil_01_v116'

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 2. System Utilities ***

def printBeginProgram():
    print('     Begin program ' + programTitle + '  tlfong01  ' + timeNowStr)
    #print(' ')
    return

def printEndProgram():
    print('\n     End   program ' + programTitle + '  tlfong01  ' + timeNowStr)
    return    
        
def printTitle(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]))    
    return

def printTitleNoNewLine(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]), end = '')    
    return

def printTitleString(title, indentFormat, string):
    printTitleNoNewLine(title, indentFormat)
    print('=', string)
    return

def printStarLine():
    print('')
    printTitle(('*' * 80), indentFormat480)
    print('')
    return

def printBeginExecFunction():
    functionName = inspect.stack()[1][3] 
    title = 'Begin Execute Function ' + functionName + '  ' + timeNowStr
    printStarLine()
    printTitle(title, indentFormat480)
    print('')
    printTitleString('Function Name', indentFormat640, functionName)
    return
    
def printEndExecFunction():
    title = 'End   Execute Function ' + inspect.stack()[1][3] + '  ' + timeNowStr
    print('')
    printTitle(title, indentFormat480)
    printStarLine()
    return

def convertOneByteNumToFourCharStr(oneByteNum): 
    tempStr = ((hex(oneByteNum))[2:])
    if (len(tempStr) != 2):
        tempStr = '0' + tempStr
    fourCharStr = '0x' + tempStr
    return fourCharStr

def convertTwoByteNumToEightCharStr(twoByteNum): # new <<<<<<<<<<
    tempStr = ((hex(twoByteNum))[2:])
    tempStr = '0' * (4 - len(tempStr)) + tempStr
    tenCharStr = '0x' + tempStr
    return tenCharStr

def pauseSeconds(pauseSecondsName):
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    sleep(pauseSeconds)
    return

# *** Time Now String ***
 
timeNowStr = str(datetime.now())[0:16]

# *** Format string for print functions ***

indentFormat480 = [4, 80]
indentFormat608 = [6,  8]
indentFormat610 = [6, 10]
indentFormat615 = [6, 15]
indentFormat630 = [6, 30]
indentFormat640 = [6, 40]

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 3. Dictionaries ***

# *** Repeat Times and Pause Dict ***

repeatTimesDict = {
    '1 times'         :        1,
    '10 times'        :       10,
    '100 times'       :      100,
    '1000 times'      :     1000,
    '10000 times'     :    10000,
    '100000 times'    :   100000,
    '1000000 times'   :  1000000,
    '10000000 times'  : 10000000
    }

sampleSizeDict = {
    '1 sample'            :         1,
    '10 samples'          :        10,
    '100 samples'         :       100,
    '1000 samples'        :      1000,
    '10000 samples'       :     10000,
    '100000 samples'      :    100000,
    '1000000 samples'     :   1000000,
    '10000000 samples'    :  10000000,
    '10 million samples'  : 100000000,
    }
        
pauseSecondsDict = {
    '0.001 second'    : 0.001, 
    '0.002 second'    : 0.002,
    '0.01 second'     : 0.01,
    '0.1 second'      : 0.1,
    '10 ms'           : 0.01
    }

spiSpeedNameListDict = \
    {
    'Long SPI speeds list' : ['10 kHz', '50 kHz', '100 kHz', '400 kHz', '1 MHz', '2 MHz', '4 MHz', '5 MHz', '6 MHz', '8 MHz', '10 MHz'],
    'Short SPI speeds list' : ['100 kHz', '400 kHz', '1 MHz'],
    '1 MHz list' : ['1 MHz'],
    }

refVoltDict = \
    {
    '0.00V'        : 0.00,
    '1.68V'        : 1.68,
    '2.048V'       : 2.048,
    '3.30V'        : 3.30,
    '4.096V'       : 4.096
    }

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 4. SPI Utilities (for troubleshooting) ***

def testSpiUtil():
    
    print('       Begin testSpiUtil(), ...\n')
    
    # *** Test SPI Set Port Speed ***
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')
    #setSpiPortSpeedBySpiPortNameList(spiPortNameListAll, '100 kHz')  
        
    # *** Test SPI loopback ***
    #spiutil.testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')
    
    # *** Test SPI Repeat send one byte ***
    #spiutil.testRepeatSendOneByteSpiPortNameList(['SpiPort00'], '0x5b', '0.01 second', '100 times')   
    #spiutil.testRepeatSendOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b', '0.01 second', '100 times')   
   
    print('\n\n       End   testSpiUtil(), ...')
    return

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********  

# *** ADC Functions ***

def testAdc(spiPortName, adcName, spiSpeedName):
    
    # 1. *** Set SPI speed ***
    print('\n       # *** Set SPI Port Speed ***')
    spiutil.setSpiPortSpeedBySpiPortNameList([spiPortName], spiSpeedName)
    print('')
    
    # 2. *** Test SPI loopback (for troubleshooting only) ***
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')
    
    # 3. *** Test ADC ***
    if adcName == 'MCP3208':
        pass
        # / to continue, ...        
        print('       ADC 12 Bit Results =', hex(adc12BitResults))
    if adcName == 'MCP3008':
        pass
        # / to continue, ...
    if adcName == 'MCP3201':
        print('       *** Read', adcName, 'Conversion Results ***')
        #spiPort = spiutil.spiPortDict[spiPortName]
        #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
        #adcResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
        adc12BitResults = readMcp3201(spiPortName)
        adcVolts   = (adc12BitResults / 0xfff) * 3.3
        print('       MCP3201 Results in 12 bits binary (expect fff/2~= 0x0800) =', convertTwoByteNumToEightCharStr(adc12BitResults))
        print('                       in V (expect 3.3V /2 ~= 1.65V)            =', "%.2f" % adcVolts, 'V')
    return

def readMcp3201BinaryResults(spiPortName):
    spiPort = spiutil.spiPortDict[spiPortName]
    recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
    adcBinaryResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
    return adcBinaryResults

def readMcp3201DecimalResults(spiPortName):
    adc12BitResults = readMcp3201(spiPortName)
    adcVoltResults = (adc12BitResults / 0xfff) * 3.3
    return adcDecimalResults

def repeatReadMcp3201(spiPortName, PauseTimeName, repeatTimesName):
    spiPort = spiutil.spiPortDict[spiPortName]
    PauseTime = PauseTimeDict[PauseTimeName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    
    for count in range(repeatTimes):
        #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
        #adcResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
        adc12BitResults = readMcp3201(spiPortName)
        sleep(PauseTime)
    return adc12BitResults

def readAdcMultipleSpiSpeedsMultipleTimes(spiPortName, adcName, refVoltName, speedNameListName, sampleSizeName):
    spiPort = spiutil.spiPortDict[spiPortName]
    
    print('         Test Config: SPI Port =', spiPortName, ';', 'ADC =', adcName, ';', 'Speed List =',  speedNameListName, ';', \
          'Sample Size =', sampleSizeName) 
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))    
    print('        ', 'SPI Port'.rjust(10), 'Speed'.rjust(10), 'Mean 12bit'.rjust(10), 'Mean (V)'.rjust(10), \
          'Error (%)'.rjust(10), 'Max Volt'.rjust(10), 'Min Volt'.rjust(10), 'MaxMin Dif'.rjust(10), end = '')
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))     
  
    refVolt = refVoltDict[refVoltName]
    speedNameList = spiSpeedNameListDict[speedNameListName]
    sampleSize = sampleSizeDict[sampleSizeName]
    
    for speedName in speedNameList:
      # *** Set SPI speed ***
      spiutil.setSpiPortSpeedByName(spiPortName, speedName)
      
      # *** Results List *** 
      binResultList =  [0.0 for x in range(sampleSize)]
      decResultList =  [0.0 for x in range(sampleSize)]
      
      # *** Repeat ADC, and analyse readings ***
      for count in range(sampleSize): 
          if adcName == 'MCP3008':
              print('Not available')
          if adcName == 'MCP3208':
              print('Not available')
          if adcName == 'MCP3201':
              recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x5b, 0x5c)
              binResult = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
              decResult = (binResult / 0xfff) * 3.3
              error      = ((refVolt - decResult) / refVolt) * 100
              binResultList[count] = binResult
              decResultList[count] = decResult
      
      maxDecResult  = max(decResultList)
      minDecResult  = min(decResultList)
      meanDecResult = sum(decResultList) / sampleSize
      maxMinDiff    = maxDecResult - minDecResult
        
      print('        ', spiPortName.rjust(10), end = '')
      print('', speedName.rjust(10), end = '')
      print('', convertTwoByteNumToEightCharStr(binResult).rjust(10), end = '')  
      print('', ("%.3f" % decResult).rjust(10), end = '')
      print('', ("%.1f" % error).rjust(10), end = '')
      print('', ("%.3f" % maxDecResult).rjust(10), end = '')
      print('', ("%.3f" % minDecResult).rjust(10), end = '')
      print('', ("%.3f" % maxMinDiff).rjust(10), end = '')
      
      print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10),'----------'.rjust(10))        
    return


def readAdcMultipleSpiSpeedsMultipleTimesNoPrintStatements(spiPortName, adcName, refVoltName, speedNameListName, sampleSizeName):
    spiPort = spiutil.spiPortDict[spiPortName]
    
    print('\n         Test Config: SPI Port =', spiPortName, ';', 'ADC =', adcName, ';', 'Speed List =',  speedNameListName, ';', \
          'Sample Size =', sampleSizeName) 
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))    
    print('        ', 'SPI Port'.rjust(10), 'Speed'.rjust(10), 'Mean 12bit'.rjust(10), 'Mean (V)'.rjust(10), \
          'Error (%)'.rjust(10), 'Max Volt'.rjust(10), 'Min Volt'.rjust(10), 'MaxMin Dif'.rjust(10), end = '')
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))     
  
    refVolt = refVoltDict[refVoltName]
    speedNameList = spiSpeedNameListDict[speedNameListName]
    sampleSize = sampleSizeDict[sampleSizeName]
    
    for speedName in speedNameList:
      # *** Set SPI speed ***
      spiutil.setSpiPortSpeedByName(spiPortName, speedName)
      pauseSecondsName = '10 ms'
     
      
      # *** Results List *** 
      #binResultList =  [0.0 for x in range(sampleSize)]
      #decResultList =  [0.0 for x in range(sampleSize)]
      
      # *** Repeat ADC, and analyse readings ***
      for count in range(sampleSize): 
          #if adcName == 'MCP3008':
          #    print('Not available')
          #if adcName == 'MCP3208':
          #    print('Not available')
          #if adcName == 'MCP3201':
          #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
          recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x5b, 0x5c)
          #binResult = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
          #decResult = (binResult / 0xfff) * 3.3
          #error      = ((refVolt - decResult) / refVolt) * 100
          #binResultList[count] = binResult
          #decResultList[count] = decResult
          pauseSeconds(pauseSecondsName)
      
      #maxDecResult  = max(decResultList)
      #minDecResult  = min(decResultList)
      #meanDecResult = sum(decResultList) / sampleSize
      #maxMinDiff    = maxDecResult - minDecResult
        
      #print('        ', spiPortName.rjust(10), end = '')
      #print('', speedName.rjust(10), end = '')
      #print('', convertTwoByteNumToEightCharStr(binResult).rjust(10), end = '')  
      #print('', ("%.3f" % decResult).rjust(10), end = '')
      #print('', ("%.1f" % error).rjust(10), end = '')
      #print('', ("%.3f" % maxDecResult).rjust(10), end = '')
      #print('', ("%.3f" % minDecResult).rjust(10), end = '')
      #print('', ("%.3f" % maxMinDiff).rjust(10), end = '')
      
      print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10),'----------'.rjust(10))        
    return


# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** ********** 

# *** Old tests ***

    # *** Set SPI port speed ***
    #print('       # *** Set SPI Port Speed ***')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    
    #print('       # *** Repeat read MCP3201 ***') # <<< Not tested >>>
    #repeatReadMcp3201('SpiPort00', '10 ms', '100 times') 
    
    # *** Loopback 1/2 bytes ***
    #spiutil.testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')

    # *** Read MCP3201 ADC result at 100kHz ***
    #print('       # *** Test MCP3201 ADC ***')
    #testAdc('SpiPort00', 'MCP3201', '100 kHz')
    
    #print('\n       # *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    # readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', 'Long SPI speeds list', '10 samples')   # Long SPI speeds list
    #readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', 'Short SPI speeds list', '100 samples')  # Short SPI speeds list 
    #readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', '1 MHz list', '100000 samples')  # 1 MHz speed list
    
    #print('\n       *** Set SpiPort00 1 MHz ***')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz')
    
    #print('\n       *** Loopback SpiPort00 two bytes 0x5b, 0x5c (short MOSI and MISO ***')    
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')    
    
    #print('\n       *** Repeat send two bytes 0x5b, 0x5c (can keep MOSI, MISO shorted) ***')
    #spiutil.testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '5 us', '10000000 times')

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** ********** 

# *** Main ***

def main():
    printBeginProgram()
   
    # 1. Set SPI Speed 1 MHz  
    print('\n       *** Set SpiPort00 1 MHz ***')
    spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz')
    
    # 2. Loop back two bytes 0x5b, 0x5c ***
    print('\n       *** Loopback SpiPort00 two bytes 0x5b, 0x5c (short MOSI and MISO ***')    
    spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')  
    
    # 3. Read MCP3201 10 Times (To read 10 samples to get (1) ~= 2.82V if MSOI shorted MISO, (2) 1.65V if MCP3201
    print('\n       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', '1 MHz list', '10 samples')  

    # 4. Read MCP3201 10 Million Times (To display SPI signals using a scope) 
    print('\n       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', '1 MHz list', '10 million samples') 
    
    printEndProgram()
    return

if __name__ == '__main__':
    main()

# End of program

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** Sample Output ***

'''
>>> %Run adc_util_01_v116.py
     Begin program adcutil_01_v116  tlfong01  2020-08-14 11:53

       *** Set SpiPort00 1 MHz ***
       spiPortName   = SpiPort00
       spiSpeedName  = 1 MHz

       *** Loopback SpiPort00 two bytes 0x5b, 0x5c (short MOSI and MISO ***
       sendBytes                               = 0x5b 0x5c
       recvBytes                               = 0x0f 0xe5

       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***
         Test Config: SPI Port = SpiPort00 ; ADC = MCP3201 ; Speed List = 1 MHz list ; Sample Size = 10 samples

         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
           SPI Port      Speed Mean 12bit   Mean (V)  Error (%)   Max Volt   Min Volt MaxMin Dif
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00      1 MHz     0x07f6      1.642        2.2      1.647      1.638      0.009
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------

       *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***
         Test Config: SPI Port = SpiPort00 ; ADC = MCP3201 ; Speed List = 1 MHz list ; Sample Size = 10 million samples

         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
           SPI Port      Speed Mean 12bit   Mean (V)  Error (%)   Max Volt   Min Volt MaxMin Dif
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
Traceback (most recent call last):
  File "/home/pi/Programs/programs/adc_util_01_v116.py", line 430, in <module>
    main()
  File "/home/pi/Programs/programs/adc_util_01_v116.py", line 424, in main
    readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', '1 MHz list', '10 million samples')
  File "/home/pi/Programs/programs/adc_util_01_v116.py", line 267, in readAdcMultipleSpiSpeedsMultipleTimes
    binResultList =  [0.0 for x in range(sampleSize)]
  File "/home/pi/Programs/programs/adc_util_01_v116.py", line 267, in <listcomp>
    binResultList =  [0.0 for x in range(sampleSize)]
KeyboardInterrupt: Execution interrupted
>>> 
'''
 # *** End of program ***



# Program:
#  
spi_util_01_v113.py tlfong01 2020aug13hkt1430# Function:
#   1. SPI one byte loopback
#   2. SPI repeatedly send one byte
#
# System Config: 
#   Rpi4B buster, python 3.7.3, thonny v3.2.7
#   pi@raspberrypi:~ $ date = Sat 08 Aug 2020 04:16:17 PM HKT
#   pi@raspberrypi:~ $ uname -a = Linux raspberrypi 4.19.118-v7l+ #1311 SMP Mon Apr 27 14:26:42 BST 2020 armv7l GNU/Linux

# Test Function Definitions:
#
# Test 1 - loopBackTest() - SPI port send and receive one byte.
#   Function - Send one byte to MOSI and read it back from MISO.
#     Setup - Connet MOSI pin to MISO pin to form a loop.
#
# Test 2 - repeatSendByte() - SPI port repeatedly send one bytes. 
#   Function - Repeat many times sending a byte, pause after each byte.

# Notes
#   1. SPI ports setup notes
#      To enable SPI and setup SPI 10, 11, 12 ports, add these two lines to /boot/config.txt
#        dtparam=spi=on
#        dtoverlay=spi1-3cs
#      To list SPI devices
#        pi@raspberrypi:~ $ ls /dev/spi*
#        /dev/spidev0.0  /dev/spidev0.1  /dev/spidev1.0  /dev/spidev1.1  /dev/spidev1.2

#   2. Notes of loopback function
#     Call example - testLoopbackOneByte(spiPort00)
#     Function     - send byte 0x5b to SPI MOSI and read byte from MISO
#     Setup        - must connect MOSI pin to MISO pin to loop back
#     Note         - 1. Only checks if MISO echoes MOSI, CS0, CS1, CS2 is not checked
#                    2. To check if SPI 0, CS0, CS1, or SPI1 CS0, CS1, CS2, need a scope to display repeat send bytes 

from time     import sleep
import               spidev
import               inspect
from datetime import datetime

# *** Program Config ***

programTitle = 'spituil_v95'

# *** SPI Port Setup/Config ***

spiPort00 = spidev.SpiDev()
spiPort00.open(0,0)

spiPort01 = spidev.SpiDev()
spiPort01.open(0,1)

spiPort10 = spidev.SpiDev()
spiPort10.open(1,0)

spiPort11 = spidev.SpiDev()
spiPort11.open(1,1)

spiPort12 = spidev.SpiDev()
spiPort12.open(1,2)


# *** SPI Port Name List and Dict ***

spiPortNameList00  = ['SpiPort00']
spiPortNameList01  = ['SpiPort01']
spiPortNameListAll = ['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12']

spiPortDict = {
    'SpiPort00'       : spiPort00,
    'SpiPort01'       : spiPort01,
    'SpiPort10'       : spiPort10,
    'SpiPort11'       : spiPort11,
    'SpiPort12'       : spiPort12,
    }

spiSpeedDict = {
    '10 MHz'       : 10000000,
    '8 MHz'        :  8000000,
    '6 MHz'        :  6000000,
    '5 MHz'        :  5000000,
    '4 MHz'        :  4000000,
    '2 MHz'        :  2000000,
    '1 MHz'        :  1000000,
    '400 kHz'      :   400000,
    '100 kHz'      :   100000,
    '50 kHz'       :    50000,
    '10 kHz'       :    10000,
    '1 kHz'        :     1000,
    '500 Hz'       :      500,
    }

dataByteDict = {
    '0x00'            :     0x00,
    '0x5a'            :     0x5a,
    '0x5b'            :     0x5b,
    '0x5c'            :     0x5c,
    '0x5d'            :     0x5d,
    '0x5e'            :     0x5e,
    '0x5f'            :     0x5f,
    '0x55'            :     0x55,
    '0x66'            :     0x66,
    '0x77'            :     0x77,
    }
    
repeatTimesDict = {
    '100 times'       :      100,
    '1000 times'      :     1000,
    '10000 times'     :    10000,
    '100000 times'    :   100000,
    '1000000 times'   :  1000000,
    '10000000 times'  : 10000000
    }
        
pauseSecondsDict = {
    '0.000001 second' : 0.000001,
    '0.00005 second'  : 0.00005,
    '0.0001 second'   : 0.0001,
    '0.001 second'    : 0.001, 
    '0.002 second'    : 0.002,
    '0.01 second'     : 0.01,
    '0.1 second'      : 0.1,
    '10 us'           : 0.000001,
    '5 us'            : 0.0000005,
    }

# *** Set SPI Port Speed Functions ***

def setSpiPortSpeedByName(spiPortName, spiSpeedName):
    spiPort = spiPortDict[spiPortName]
    spiSpeed = spiSpeedDict[spiSpeedName]
    spiPort.max_speed_hz = spiSpeed
    return

def setSpiPortSpeedBySpiPortNameList(spiPortNameList, spiSpeedName):
    for spiPortName in spiPortNameList:
        setSpiPortSpeedByName(spiPortName, spiSpeedName)
        print('       spiPortName   =', spiPortName)
        print('       spiSpeedName  =', spiSpeedName)
    return

# *** Example Calls ***

#setSpiPortSpeedBySpiPortNameList('SpiPortNameListAll, '100 kHz')  
#setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')  

# *** Print Functions ***

def printBeginProgram():
    print('     Begin program ' + programTitle + '  tlfong01  ' + timeNowStr)
    print(' ')
    return

def printEndProgram():
    print('\n     End   program ' + programTitle + '  tlfong01  ' + timeNowStr)
    return    
        
def printTitle(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]))    
    return

def printTitleNoNewLine(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]), end = '')    
    return

def printTitleString(title, indentFormat, string):
    printTitleNoNewLine(title, indentFormat)
    print('=', string)
    return

def printStarLine():
    print('')
    printTitle(('*' * 100), indentFormat480)
    print('')
    return

def printBeginExecFunction():
    functionName = inspect.stack()[1][3] 
    title = 'Begin Execute Function ' + functionName + '  ' + timeNowStr
    printStarLine()
    printTitle(title, indentFormat480)
    print('')
    printTitleString('Function Name', indentFormat640, functionName)
    return
    
def printEndExecFunction():
    title = 'End   Execute Function ' + inspect.stack()[1][3] + '  ' + timeNowStr
    print('')
    printTitle(title, indentFormat480)
    printStarLine()
    return

def convertOneByteNumToFourCharStr(oneByteNum): 
    tempStr = ((hex(oneByteNum))[2:])
    if (len(tempStr) != 2):
        tempStr = '0' + tempStr
    fourCharStr = '0x' + tempStr
    return fourCharStr

# *** Time Now String ***
 
timeNowStr = str(datetime.now())[0:16]

# *** Format string for print functions ***

indentFormat480 = [4, 80]
indentFormat608 = [6,  8]
indentFormat610 = [6, 10]
indentFormat615 = [6, 15]
indentFormat630 = [6, 30]
indentFormat640 = [6, 40]

# *** SPI Send/Receive/Loopback/RepeatSend Byte Functions ***

# *** Send/Receive 1/2/3 bytes functions called by SPI ports spiPort00, spiPort01, spiPort10, spiPort11, spiPort12 ***

def spiSendRecvOneByte(spiPort, sendByte):
  sendByteArray = [sendByte]
  recvByteArray = spiPort.xfer(sendByteArray)  
  return recvByteArray

def spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2):
    sendByteArray = [sendByte1, sendByte2]
    recvByteArray = spiPort.xfer2(sendByteArray)    
    return recvByteArray

def spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
    sendByteArray = [sendByte1, sendByte2, sendByte3]
    recvByteArray = spiPort.xfer2(sendByteArray)    
    return recvByteArray

# *** Send/Receive 1/2/3 bytefunctions called by SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def spiSendRecvOneByteByName(spiPortName, sendByteName):
  spiPort  = spiPortDict[spiPortName]
  sendByte = dataByteDict[sendByteName]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte)  
  return recvByteArray

def spiSendRecvTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name):
  print(sendByte1Name)
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte1. sendByte2)  
  return recvByteArray

def spiSendRecvThreeBytesByName(spiPortName, sendByte1Name, sendByte2Name, sendByte3Name):
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  sendByte3 = dataByteDict[sendByte3Name]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte1. sendByte2, sendByte3)  
  return recvByteArray

# *** Loopback 1/2/3 byte functions called by SPI ports spiPort00, spiPort01, spiPort10, spiPort11, spiPort12 ***

def loopBackOneByte(spiPort, sendByte):
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte)
  recvByte      = recvByteArray[0]

  print('\n       Begin testLoopbackOneByte(),....')
  #print('')
  print('          sendByte                                = ', hex(sendByte))
  print('          recvByte                                = ', hex(recvByte))
  #print('')
  print('       End testLoopbackOneByte(),....\n')
  return

def loopbackTwoBytes(spiPort, sendByte1, sendByte2):
    #fprint.printBeginExecFunction()
    recvByteArray      = spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
    recvByte1          = recvByteArray[0]
    recvByte2          = recvByteArray[1]
    sendBytes = convertOneByteNumToFourCharStr(sendByte1) + ' ' + convertOneByteNumToFourCharStr(sendByte2)
    printTitleString('sendBytes', indentFormat640, sendBytes)  
    recvBytes = convertOneByteNumToFourCharStr(recvByte1) + ' ' + convertOneByteNumToFourCharStr(recvByte2)
    printTitleString('recvBytes', indentFormat640, recvBytes)
    #printEndExecFunction()
    return

def loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
    #fprint.printBeginExecFunction()    
    recvByteArray      = spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
    recvByte1          = recvByteArray[0]
    recvByte2          = recvByteArray[1]
    recvByte3          = recvByteArray[2]
    sendBytes = convertOneByteNumToFourCharStr(sendByte1) + ' ' + convertOneByteNumToFourCharStr(sendByte2) + ' ' + \
                convertOneByteNumToFourCharStr(sendByte3)
    printTitleString('sendBytes', indentFormat640, sendBytes)
    recvBytes = convertOneByteNumToFourCharStr(recvByte1) + ' ' + convertOneByteNumToFourCharStr(recvByte2) + ' ' + \
                convertOneByteNumToFourCharStr(recvByte3)
    printTitleString('sendBytes', indentFormat640, recvBytes)
    #printEndExecFunction()
    return

# *** Loopback 1/2/3 byte functions called bycalled SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def loopbackOneByteByName(spiPortName, sendByteName):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte = dataByteDict[sendByteName]
  loopBackOneByte(spiPort, sendByte)
  #printEndExecFunction() 
  return

def loopbackTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  
  loopbackTwoBytes(spiPort, sendByte1, sendByte2)
  #printEndExecFunction() 
  return

def loopbackThreeBytesByName(spiPortName, sendByte1Name, sendByte2Name, sendByte3Name):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  sendByte3 = dataByteDict[sendByte3Name]
  
  loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
  #printEndExecFunction() 
  return

# *** Test loopback one byte function call by SPI port ***

def testLoopbackOneByte(spiPort, dataByte):
  loopackOneByte(spiPort, dataByte)
  return

# *** Test loopback one byte function called by SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def testLoopbackOneByteByName(spiPortName, dataByteName):
  loopackOneByteByName(spiPortName, dataByteName)
  return

def testLoopbackTwoBytesByName(spiPortName, dataByte1Name, dataByte2Name):
    spiPort = spiPortDict[spiPortName]
    dataByte1 = dataByteDict[dataByte1Name]
    dataByte2 = dataByteDict[testByte2Name]
    loopbackTwoBytes(spiPort, datatByte1, dataByte2)
    return

def testLoopbackThreeBytesByName(spiPortName, dataByte1Name, dataByte2Name, dataByte3Name):
    spiPort = spiPortDict[spiBusName]
    dataByte1 = dataByteDict[dataByte1Name]
    dataByte2 = dataByteDict[dataByte2Name]
    dataByte3 = dataByteDict[testByte3Name]
    loopbackThreeBytes(spiPort, dataByte1, dataByte2, datatByte3)
    return

# *** Test Example Loopback 1/2/3 bytes called by name ***

def testLoopbackOneByteByNameSpiPort00x5b():
    printBeginExecFunction()  
    loopBackOneByteByName('SpiPort00', '0x5b')
    printEndExecFunction()  
    return

def testLoopbackTwoBytesByNameSpiPort00x5bx5c():
    printBeginExecFunction()  
    loopBackTwoBytesByName('SpiPort00', '0x5b', '0x5c')
    printEndExecFunction()  
    return

def testLoopbackThreeBytesByNameSpiPort00x5bx5cx5d():
    printBeginExecFunction()  
    loopBackThreeBytesByName('SpiPort00', '0x5b', '0x5c', '0x5d')
    printEndExecFunction()  
    return

# *** Example Loopback 1 byte calling all SPI ports 00, 01, 10, 11, 12 ***

def testLoopbackSpiPortsAll():
    print('\n*** testLoopbackOneByte(spiPort00, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort00, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort01, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort01, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort10, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort10, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort11, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort11, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort12, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort12, 0x5b)

    print('\n*** testLoopbackOneByteByName("spiPort00", "0x5b") ***', end = '')
    testLoopbackOneByteByName('SpiPort00', '0x5b')
    return

# *** Example Loopback 1/2/3 byte calling SPI port names ***

def testLoopbackOneTwoThreeBytesSpiPorts00ByName():
    testLoopbackOneByteByNameSpiPort00x5b()
    testLoopbackTwoBytesByNameSpiPort00x5bx5c()
    testLoopbackThreeBytesByNameSpiPort00x5bx5cx5d()
    return

# *** Example Loopback 1/2/3 byte calling SPI port name list ***

def testLoopbackOneByteSpiPortNameList(spiPortNameList, dataByteName):
    #print('       testLoopbackOneByteSpiPortNameList(),....')
    for spiPortName in spiPortNameList:
        loopbackOneByteByName(spiPortName, dataByteName)
    #print('       End   testLoopbackOneByteSpiPortNameList().\n')
    return

def testLoopbackTwoBytesSpiPortNameList(spiPortNameList, dataByte1Name, dataByte2Name):
    for spiPortName in spiPortNameList:
        loopbackTwoBytesByName(spiPortName, dataByte1Name, dataByte2Name)
    return

def testLoopbackThreeBytesSpiPortNameList(spiPortNameList, dataByte1Name, dataByte2Name, dataByte3Name):
    for spiPortName in spiPortNameList:
        loopbackThreeBytesByName(spiPortName, dataByte1Name, dataByte2Name, dataByte3Name)
    return

# *** Repeat send byte functions ***

def repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes):
    print('       Begin repeatSendByte(),....')
    print('           Now use a scope to display the SPI signals, MOSI, MISO, CSn, ...')
    for i in range(repeatTimes):
      spiSendRecvOneByte(spiPort, sendByte)
      sleep(pauseSeconds)
    print('       End   repeatSendByte().', end = '')
    return

def repeatSendTwoBytes(spiPort, sendByte1, sendByte2, pauseSeconds, repeatTimes):
    print('       Begin repeatSendByte(),....')
    print('           Now use a scope to display the SPI signals, CLK, MOSI, MISO, CS0.  <ctrl>C to abort')
    for i in range(repeatTimes):
      spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
      sleep(pauseSeconds)
    print('       End   repeatSendByte().', end = '')
    return

def repeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName):
    spiPort  = spiPortDict[spiPortName]
    sendByte = dataByteDict[sendByteName]
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes)  
    return

def repeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName):
    spiPort  = spiPortDict[spiPortName]
    sendByte1 = dataByteDict[sendByte1Name]
    sendByte2 = dataByteDict[sendByte2Name]    
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    repeatSendTwoBytes(spiPort, sendByte1, sendByte2, pauseSeconds, repeatTimes)  
    return

# *** Test repeat send one byte functions ***

def testRepeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes):
    repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes)
    return

def testRepeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName):
    repeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName)
    return

def testRepeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName):
    repeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName)
    return

# *** Test Examples ***

def testRepeatSendOneByteByNameSpiPort000x5b0001Seconds100Times():
    testRepeatSendOneByteByName('SpiPort00', '0x5b', '0.001 second', '100 times')    
    return

def testRepeatSendOneByteSpiPortsAll():
    print('\n*** testRepeatSendOneByte(spiPort00, 0x5b, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort00, 0x5b, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort01, 0x5b, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort01, 0x5b, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort10, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort10, 0xb5, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort11, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort11, 0xb5, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort12, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort12, 0xb5, 0.001, 200)
    
    return
    
def testRepeatSendOneByteSpiPortsAllByName():
    printBeginExecFunction()  
    testRepeatSendOneByteByName('SpiPort00', '0x5b', '0.001 second', '100 times')
    printEndExecFunction()  
    return

def testRepeatSendOneByteSpiPortNameList(spiPortNameList, sendByteName, pauseSeconds, repeatTimes):
    for spiPortName in spiPortNameList:
        testRepeatSendOneByteByName(spiPortName, sendByteName, pauseSeconds, repeatTimes)
    return

def testRepeatSendTwoBytesSpiPortNameList(spiPortNameList, sendByte1Name, sendByte2Name, pauseSeconds, repeatTimes):
    for spiPortName in spiPortNameList:
        testRepeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSeconds, repeatTimes)
    return

# *** Old Tests ***

    # *** Test loopback functions ***
    #testLoopbackSpiPortsAll()
    #testLoopbackOneTwoThreeBytesSpiPorts00ByName()
    #testLoopbackSpiPortNameListAll()  
    #testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')    
    #testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')
    #testLoopbackThreeBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '0x5d')

# *** Main ***

def main():

    # *** Print program title ***    
    printBeginProgram()
        
    # *** Set SPI Port Speed ***
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz') 
    #setSpiPortSpeedBySpiPortNameList(spiPortNameListAll, '100 kHz')  
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')     
  
    # *** Loopback Tests ***
    #testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')
    
    # *** Repeat Send Byte Tests ***
    #testRepeatSendOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b', '0.01 second', '100 times')
    
    # *** Repeat Send Two Bytes Tests ***
    testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '5 us', '1000000 times')
        
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz')         
    #testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '0.01 second', '1000000 times')

    printEndProgram()

# ********************************************************************************

if __name__ == '__main__':
    main()

# End of program

# *** Sample Output *** 

# *** End ***



4:19pm Thu. 8/13/2020


MCP3201 Testing Program V1.1


https://penzu.com/p/730dde02


# Program:
#   adc_util01_v114.py tlfong01 2020aug13hkt1426
#
# Function:
#   Test (1) SPI loockback and repeat send byte
#        (2) test MCP3008, MCP3201, and MCP3208
#
# Contents
#  1. Program Config
#  2. System Utilities
#  3. Dictionaries
#  4. SPI Testing and Troubleshooting Functions
#  5. Test MCP3008, MCP3201, and MCP3208 ADC

from time     import sleep
import               spidev
import               inspect
from datetime import datetime
import spi_util_01_v113 as spiutil

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 1. Program Config ***

programTitle = 'adcutil_01_v113'

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 2. System Utilities ***

def printBeginProgram():
    print('     Begin program ' + programTitle + '  tlfong01  ' + timeNowStr)
    #print(' ')
    return

def printEndProgram():
    print('\n     End   program ' + programTitle + '  tlfong01  ' + timeNowStr)
    return    
        
def printTitle(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]))    
    return

def printTitleNoNewLine(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]), end = '')    
    return

def printTitleString(title, indentFormat, string):
    printTitleNoNewLine(title, indentFormat)
    print('=', string)
    return

def printStarLine():
    print('')
    printTitle(('*' * 80), indentFormat480)
    print('')
    return

def printBeginExecFunction():
    functionName = inspect.stack()[1][3] 
    title = 'Begin Execute Function ' + functionName + '  ' + timeNowStr
    printStarLine()
    printTitle(title, indentFormat480)
    print('')
    printTitleString('Function Name', indentFormat640, functionName)
    return
    
def printEndExecFunction():
    title = 'End   Execute Function ' + inspect.stack()[1][3] + '  ' + timeNowStr
    print('')
    printTitle(title, indentFormat480)
    printStarLine()
    return

def convertOneByteNumToFourCharStr(oneByteNum): 
    tempStr = ((hex(oneByteNum))[2:])
    if (len(tempStr) != 2):
        tempStr = '0' + tempStr
    fourCharStr = '0x' + tempStr
    return fourCharStr

def convertTwoByteNumToEightCharStr(twoByteNum): # new <<<<<<<<<<
    tempStr = ((hex(twoByteNum))[2:])
    tempStr = '0' * (4 - len(tempStr)) + tempStr
    tenCharStr = '0x' + tempStr
    return tenCharStr

def pauseSeconds(pauseSecondsName):
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    sleep(pauseSeconds)
    return

# *** Time Now String ***
 
timeNowStr = str(datetime.now())[0:16]

# *** Format string for print functions ***

indentFormat480 = [4, 80]
indentFormat608 = [6,  8]
indentFormat610 = [6, 10]
indentFormat615 = [6, 15]
indentFormat630 = [6, 30]
indentFormat640 = [6, 40]

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 3. Dictionaries ***

# *** Repeat Times and Pause Dict ***

repeatTimesDict = {
    '1 times'         :        1,
    '10 times'        :       10,
    '100 times'       :      100,
    '1000 times'      :     1000,
    '10000 times'     :    10000,
    '100000 times'    :   100000,
    '1000000 times'   :  1000000,
    '10000000 times'  : 10000000
    }

sampleSizeDict = {
    '1 sample'          :        1,
    '10 samples'        :       10,
    '100 samples'       :      100,
    '1000 samples'      :     1000,
    '10000 samples'     :    10000,
    '100000 samples'    :   100000,
    '1000000 samples'   :  1000000,
    '10000000 samples'  : 10000000
    }
        
pauseSecondsDict = {
    '0.001 second'    : 0.001, 
    '0.002 second'    : 0.002,
    '0.01 second'     : 0.01,
    '0.1 second'      : 0.1,
    '10 ms'           : 0.01
    }

spiSpeedNameListDict = \
    {
    'Long SPI speeds list' : ['10 kHz', '50 kHz', '100 kHz', '400 kHz', '1 MHz', '2 MHz', '4 MHz', '5 MHz', '6 MHz', '8 MHz', '10 MHz'],
    'Short SPI speeds list' : ['100 kHz', '400 kHz', '1 MHz'],
    '1 MHz list' : ['1 MHz'],
    }

refVoltDict = \
    {
    '0.00V'        : 0.00,
    '1.68V'        : 1.68,
    '2.048V'       : 2.048,
    '3.30V'        : 3.30,
    '4.096V'       : 4.096
    }

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** 4. SPI Utilities (for troubleshooting) ***

def testSpiUtil():
    
    print('       Begin testSpiUtil(), ...\n')
    
    # *** Test SPI Set Port Speed ***
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')
    #setSpiPortSpeedBySpiPortNameList(spiPortNameListAll, '100 kHz')  
        
    # *** Test SPI loopback ***
    #spiutil.testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')
    
    # *** Test SPI Repeat send one byte ***
    #spiutil.testRepeatSendOneByteSpiPortNameList(['SpiPort00'], '0x5b', '0.01 second', '100 times')   
    #spiutil.testRepeatSendOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b', '0.01 second', '100 times')   
   
    print('\n\n       End   testSpiUtil(), ...')
    return

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********  

# *** ADC Functions ***

def testAdc(spiPortName, adcName, spiSpeedName):
    
    # 1. *** Set SPI speed ***
    print('\n       # *** Set SPI Port Speed ***')
    spiutil.setSpiPortSpeedBySpiPortNameList([spiPortName], spiSpeedName)
    print('')
    
    # 2. *** Test SPI loopback (for troubleshooting only) ***
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')
    
    # 3. *** Test ADC ***
    if adcName == 'MCP3208':
        pass
        # / to continue, ...        
        print('       ADC 12 Bit Results =', hex(adc12BitResults))
    if adcName == 'MCP3008':
        pass
        # / to continue, ...
    if adcName == 'MCP3201':
        print('       *** Read', adcName, 'Conversion Results ***')
        #spiPort = spiutil.spiPortDict[spiPortName]
        #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
        #adcResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
        adc12BitResults = readMcp3201(spiPortName)
        adcVolts   = (adc12BitResults / 0xfff) * 3.3
        print('       MCP3201 Results in 12 bits binary (expect fff/2~= 0x0800) =', convertTwoByteNumToEightCharStr(adc12BitResults))
        print('                       in V (expect 3.3V /2 ~= 1.65V)            =', "%.2f" % adcVolts, 'V')
    return

def readMcp3201BinaryResults(spiPortName):
    spiPort = spiutil.spiPortDict[spiPortName]
    recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
    adcBinaryResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
    return adcBinaryResults

def readMcp3201DecimalResults(spiPortName):
    adc12BitResults = readMcp3201(spiPortName)
    adcVoltResults = (adc12BitResults / 0xfff) * 3.3
    return adcDecimalResults

def repeatReadMcp3201(spiPortName, PauseTimeName, repeatTimesName):
    spiPort = spiutil.spiPortDict[spiPortName]
    PauseTime = PauseTimeDict[PauseTimeName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    
    for count in range(repeatTimes):
        #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
        #adcResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
        adc12BitResults = readMcp3201(spiPortName)
        sleep(PauseTime)
    return adc12BitResults

def readAdcMultipleSpiSpeedsMultipleTimes(spiPortName, adcName, refVoltName, speedNameListName, sampleSizeName):
    spiPort = spiutil.spiPortDict[spiPortName]
    
    print('         Test Config: SPI Port =', spiPortName, ';', 'ADC =', adcName, ';', 'Speed List =',  speedNameListName, ';', \
          'Sample Size =', sampleSizeName) 
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))    
    print('        ', 'SPI Port'.rjust(10), 'Speed'.rjust(10), 'Mean 12bit'.rjust(10), 'Mean (V)'.rjust(10), \
          'Error (%)'.rjust(10), 'Max Volt'.rjust(10), 'Min Volt'.rjust(10), 'MaxMin Dif'.rjust(10), end = '')
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                        '----------'.rjust(10),'----------'.rjust(10))     
  
    refVolt = refVoltDict[refVoltName]
    speedNameList = spiSpeedNameListDict[speedNameListName]
    sampleSize = sampleSizeDict[sampleSizeName]
    
    for speedName in speedNameList:
      # *** Set SPI speed ***
      spiutil.setSpiPortSpeedByName(spiPortName, speedName)
      pauseSecondsName = '10 ms'
      
      # *** Results List *** 
      binResultList =  [0.0 for x in range(sampleSize)]
      decResultList =  [0.0 for x in range(sampleSize)]
      
      # *** Repeat ADC, and analyse readings ***
      for count in range(sampleSize): 
          if adcName == 'MCP3008':
              print('Not available')
          if adcName == 'MCP3208':
              print('Not available')
          if adcName == 'MCP3201':
              recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
              binResult = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
              decResult = (binResult / 0xfff) * 3.3
              error      = ((refVolt - decResult) / refVolt) * 100
              binResultList[count] = binResult
              decResultList[count] = decResult
          pauseSeconds(pauseSecondsName)
      
      maxDecResult  = max(decResultList)
      minDecResult  = min(decResultList)
      meanDecResult = sum(decResultList) / sampleSize
      maxMinDiff    = maxDecResult - minDecResult
        
      print('        ', spiPortName.rjust(10), end = '')
      print('', speedName.rjust(10), end = '')
      print('', convertTwoByteNumToEightCharStr(binResult).rjust(10), end = '')  
      print('', ("%.3f" % decResult).rjust(10), end = '')
      print('', ("%.1f" % error).rjust(10), end = '')
      print('', ("%.3f" % maxDecResult).rjust(10), end = '')
      print('', ("%.3f" % minDecResult).rjust(10), end = '')
      print('', ("%.3f" % maxMinDiff).rjust(10), end = '')
      
      print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), \
                          '----------'.rjust(10),'----------'.rjust(10))        
    return

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** ********** 

# *** Old tests ***

    # *** Set SPI port speed ***
    #print('       # *** Set SPI Port Speed ***')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    
    #print('       # *** Repeat read MCP3201 ***') # <<< Not tested >>>
    #repeatReadMcp3201('SpiPort00', '10 ms', '100 times') 
    
    # *** Loopback 1/2 bytes ***
    #spiutil.testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')

    # *** Read MCP3201 ADC result at 100kHz ***
    #print('       # *** Test MCP3201 ADC ***')
    #testAdc('SpiPort00', 'MCP3201', '100 kHz')
    
    #print('\n       # *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    # readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', 'Long SPI speeds list', '10 samples')   # Long SPI speeds list
    #readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', 'Short SPI speeds list', '100 samples')  # Short SPI speeds list 
    #readAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', '1 MHz list', '100000 samples')  # 1 MHz speed list

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** ********** 

# *** Main ***

def main():
    printBeginProgram()
    
    print('\n       *** Set SpiPort00 1 MHz ***')
    spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz')
    
    print('\n       *** Loopback SpiPort00 two bytes 0x5b, 0x5c (short MOSI and MISO ***')    
    spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')    
    
    print('\n       *** Repeat send two bytes 0x5b, 0x5c (can keep MOSI, MISO shorted) ***')
    spiutil.testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '5 us', '10000000 times')
    
    printEndProgram()
    return

if __name__ == '__main__':
    main()

# End of program

# ********** ********** ********** ********** ********** ********** ********** 
# ********** ********** ********** ********** ********** ********** **********

# *** Sample Output ***
'''
>>> %Run adc_util_01_v113.py
     Begin program adcutil_01_v113  tlfong01  2020-08-13 15:29

       *** Set SpiPort00 1 MHz ***
       spiPortName   = SpiPort00
       spiSpeedName  = 1 MHz

       *** Loopback SpiPort00 two bytes 0x5b, 0x5c (short MOSI and MISO ***
       sendBytes                               = 0x5b 0x5c
       recvBytes                               = 0x5b 0x5c

       *** Repeat send two bytes 0x5b, 0x5c (can keep MOSI, MISO shorted) ***
       Begin repeatSendByte(),....
           Now use a scope to display the SPI signals, CLK, MOSI, MISO, CS0.  <ctrl>C to abort

Traceback (most recent call last):
...
KeyboardInterrupt: Execution interrupted
>>> 

'''

# *** End ***




# Program:
#   spi_util_01_v113.py tlfong01 2020aug13hkt1430# Function:
#   1. SPI one byte loopback
#   2. SPI repeatedly send one byte
#
# System Config: 
#   Rpi4B buster, python 3.7.3, thonny v3.2.7
#   pi@raspberrypi:~ $ date = Sat 08 Aug 2020 04:16:17 PM HKT
#   pi@raspberrypi:~ $ uname -a = Linux raspberrypi 4.19.118-v7l+ #1311 SMP Mon Apr 27 14:26:42 BST 2020 armv7l GNU/Linux

# Test Function Definitions:
#
# Test 1 - loopBackTest() - SPI port send and receive one byte.
#   Function - Send one byte to MOSI and read it back from MISO.
#     Setup - Connet MOSI pin to MISO pin to form a loop.
#
# Test 2 - repeatSendByte() - SPI port repeatedly send one bytes. 
#   Function - Repeat many times sending a byte, pause after each byte.

# Notes
#   1. SPI ports setup notes
#      To enable SPI and setup SPI 10, 11, 12 ports, add these two lines to /boot/config.txt
#        dtparam=spi=on
#        dtoverlay=spi1-3cs
#      To list SPI devices
#        pi@raspberrypi:~ $ ls /dev/spi*
#        /dev/spidev0.0  /dev/spidev0.1  /dev/spidev1.0  /dev/spidev1.1  /dev/spidev1.2

#   2. Notes of loopback function
#     Call example - testLoopbackOneByte(spiPort00)
#     Function     - send byte 0x5b to SPI MOSI and read byte from MISO
#     Setup        - must connect MOSI pin to MISO pin to loop back
#     Note         - 1. Only checks if MISO echoes MOSI, CS0, CS1, CS2 is not checked
#                    2. To check if SPI 0, CS0, CS1, or SPI1 CS0, CS1, CS2, need a scope to display repeat send bytes 

from time     import sleep
import               spidev
import               inspect
from datetime import datetime

# *** Program Config ***

programTitle = 'spituil_v95'

# *** SPI Port Setup/Config ***

spiPort00 = spidev.SpiDev()
spiPort00.open(0,0)

spiPort01 = spidev.SpiDev()
spiPort01.open(0,1)

spiPort10 = spidev.SpiDev()
spiPort10.open(1,0)

spiPort11 = spidev.SpiDev()
spiPort11.open(1,1)

spiPort12 = spidev.SpiDev()
spiPort12.open(1,2)


# *** SPI Port Name List and Dict ***

spiPortNameList00  = ['SpiPort00']
spiPortNameList01  = ['SpiPort01']
spiPortNameListAll = ['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12']

spiPortDict = {
    'SpiPort00'       : spiPort00,
    'SpiPort01'       : spiPort01,
    'SpiPort10'       : spiPort10,
    'SpiPort11'       : spiPort11,
    'SpiPort12'       : spiPort12,
    }

spiSpeedDict = {
    '10 MHz'       : 10000000,
    '8 MHz'        :  8000000,
    '6 MHz'        :  6000000,
    '5 MHz'        :  5000000,
    '4 MHz'        :  4000000,
    '2 MHz'        :  2000000,
    '1 MHz'        :  1000000,
    '400 kHz'      :   400000,
    '100 kHz'      :   100000,
    '50 kHz'       :    50000,
    '10 kHz'       :    10000,
    '1 kHz'        :     1000,
    '500 Hz'       :      500,
    }

dataByteDict = {
    '0x00'            :     0x00,
    '0x5a'            :     0x5a,
    '0x5b'            :     0x5b,
    '0x5c'            :     0x5c,
    '0x5d'            :     0x5d,
    '0x5e'            :     0x5e,
    '0x5f'            :     0x5f,
    '0x55'            :     0x55,
    '0x66'            :     0x66,
    '0x77'            :     0x77,
    }
    
repeatTimesDict = {
    '100 times'       :      100,
    '1000 times'      :     1000,
    '10000 times'     :    10000,
    '100000 times'    :   100000,
    '1000000 times'   :  1000000,
    '10000000 times'  : 10000000
    }
        
pauseSecondsDict = {
    '0.000001 second' : 0.000001,
    '0.00005 second'  : 0.00005,
    '0.0001 second'   : 0.0001,
    '0.001 second'    : 0.001, 
    '0.002 second'    : 0.002,
    '0.01 second'     : 0.01,
    '0.1 second'      : 0.1,
    '10 us'           : 0.000001,
    '5 us'            : 0.0000005,
    }

# *** Set SPI Port Speed Functions ***

def setSpiPortSpeedByName(spiPortName, spiSpeedName):
    spiPort = spiPortDict[spiPortName]
    spiSpeed = spiSpeedDict[spiSpeedName]
    spiPort.max_speed_hz = spiSpeed
    return

def setSpiPortSpeedBySpiPortNameList(spiPortNameList, spiSpeedName):
    for spiPortName in spiPortNameList:
        setSpiPortSpeedByName(spiPortName, spiSpeedName)
        print('       spiPortName   =', spiPortName)
        print('       spiSpeedName  =', spiSpeedName)
    return

# *** Example Calls ***

#setSpiPortSpeedBySpiPortNameList('SpiPortNameListAll, '100 kHz')  
#setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')  

# *** Print Functions ***

def printBeginProgram():
    print('     Begin program ' + programTitle + '  tlfong01  ' + timeNowStr)
    print(' ')
    return

def printEndProgram():
    print('\n     End   program ' + programTitle + '  tlfong01  ' + timeNowStr)
    return    
        
def printTitle(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]))    
    return

def printTitleNoNewLine(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]), end = '')    
    return

def printTitleString(title, indentFormat, string):
    printTitleNoNewLine(title, indentFormat)
    print('=', string)
    return

def printStarLine():
    print('')
    printTitle(('*' * 100), indentFormat480)
    print('')
    return

def printBeginExecFunction():
    functionName = inspect.stack()[1][3] 
    title = 'Begin Execute Function ' + functionName + '  ' + timeNowStr
    printStarLine()
    printTitle(title, indentFormat480)
    print('')
    printTitleString('Function Name', indentFormat640, functionName)
    return
    
def printEndExecFunction():
    title = 'End   Execute Function ' + inspect.stack()[1][3] + '  ' + timeNowStr
    print('')
    printTitle(title, indentFormat480)
    printStarLine()
    return

def convertOneByteNumToFourCharStr(oneByteNum): 
    tempStr = ((hex(oneByteNum))[2:])
    if (len(tempStr) != 2):
        tempStr = '0' + tempStr
    fourCharStr = '0x' + tempStr
    return fourCharStr

# *** Time Now String ***
 
timeNowStr = str(datetime.now())[0:16]

# *** Format string for print functions ***

indentFormat480 = [4, 80]
indentFormat608 = [6,  8]
indentFormat610 = [6, 10]
indentFormat615 = [6, 15]
indentFormat630 = [6, 30]
indentFormat640 = [6, 40]

# *** SPI Send/Receive/Loopback/RepeatSend Byte Functions ***

# *** Send/Receive 1/2/3 bytes functions called by SPI ports spiPort00, spiPort01, spiPort10, spiPort11, spiPort12 ***

def spiSendRecvOneByte(spiPort, sendByte):
  sendByteArray = [sendByte]
  recvByteArray = spiPort.xfer(sendByteArray)  
  return recvByteArray

def spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2):
    sendByteArray = [sendByte1, sendByte2]
    recvByteArray = spiPort.xfer2(sendByteArray)    
    return recvByteArray

def spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
    sendByteArray = [sendByte1, sendByte2, sendByte3]
    recvByteArray = spiPort.xfer2(sendByteArray)    
    return recvByteArray

# *** Send/Receive 1/2/3 bytefunctions called by SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def spiSendRecvOneByteByName(spiPortName, sendByteName):
  spiPort  = spiPortDict[spiPortName]
  sendByte = dataByteDict[sendByteName]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte)  
  return recvByteArray

def spiSendRecvTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name):
  print(sendByte1Name)
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte1. sendByte2)  
  return recvByteArray

def spiSendRecvThreeBytesByName(spiPortName, sendByte1Name, sendByte2Name, sendByte3Name):
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  sendByte3 = dataByteDict[sendByte3Name]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte1. sendByte2, sendByte3)  
  return recvByteArray

# *** Loopback 1/2/3 byte functions called by SPI ports spiPort00, spiPort01, spiPort10, spiPort11, spiPort12 ***

def loopBackOneByte(spiPort, sendByte):
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte)
  recvByte      = recvByteArray[0]

  print('\n       Begin testLoopbackOneByte(),....')
  #print('')
  print('          sendByte                                = ', hex(sendByte))
  print('          recvByte                                = ', hex(recvByte))
  #print('')
  print('       End testLoopbackOneByte(),....\n')
  return

def loopbackTwoBytes(spiPort, sendByte1, sendByte2):
    #fprint.printBeginExecFunction()
    recvByteArray      = spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
    recvByte1          = recvByteArray[0]
    recvByte2          = recvByteArray[1]
    sendBytes = convertOneByteNumToFourCharStr(sendByte1) + ' ' + convertOneByteNumToFourCharStr(sendByte2)
    printTitleString('sendBytes', indentFormat640, sendBytes)  
    recvBytes = convertOneByteNumToFourCharStr(recvByte1) + ' ' + convertOneByteNumToFourCharStr(recvByte2)
    printTitleString('recvBytes', indentFormat640, recvBytes)
    #printEndExecFunction()
    return

def loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
    #fprint.printBeginExecFunction()    
    recvByteArray      = spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
    recvByte1          = recvByteArray[0]
    recvByte2          = recvByteArray[1]
    recvByte3          = recvByteArray[2]
    sendBytes = convertOneByteNumToFourCharStr(sendByte1) + ' ' + convertOneByteNumToFourCharStr(sendByte2) + ' ' + \
                convertOneByteNumToFourCharStr(sendByte3)
    printTitleString('sendBytes', indentFormat640, sendBytes)
    recvBytes = convertOneByteNumToFourCharStr(recvByte1) + ' ' + convertOneByteNumToFourCharStr(recvByte2) + ' ' + \
                convertOneByteNumToFourCharStr(recvByte3)
    printTitleString('sendBytes', indentFormat640, recvBytes)
    #printEndExecFunction()
    return

# *** Loopback 1/2/3 byte functions called bycalled SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def loopbackOneByteByName(spiPortName, sendByteName):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte = dataByteDict[sendByteName]
  loopBackOneByte(spiPort, sendByte)
  #printEndExecFunction() 
  return

def loopbackTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  
  loopbackTwoBytes(spiPort, sendByte1, sendByte2)
  #printEndExecFunction() 
  return

def loopbackThreeBytesByName(spiPortName, sendByte1Name, sendByte2Name, sendByte3Name):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  sendByte3 = dataByteDict[sendByte3Name]
  
  loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
  #printEndExecFunction() 
  return

# *** Test loopback one byte function call by SPI port ***

def testLoopbackOneByte(spiPort, dataByte):
  loopackOneByte(spiPort, dataByte)
  return

# *** Test loopback one byte function called by SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def testLoopbackOneByteByName(spiPortName, dataByteName):
  loopackOneByteByName(spiPortName, dataByteName)
  return

def testLoopbackTwoBytesByName(spiPortName, dataByte1Name, dataByte2Name):
    spiPort = spiPortDict[spiPortName]
    dataByte1 = dataByteDict[dataByte1Name]
    dataByte2 = dataByteDict[testByte2Name]
    loopbackTwoBytes(spiPort, datatByte1, dataByte2)
    return

def testLoopbackThreeBytesByName(spiPortName, dataByte1Name, dataByte2Name, dataByte3Name):
    spiPort = spiPortDict[spiBusName]
    dataByte1 = dataByteDict[dataByte1Name]
    dataByte2 = dataByteDict[dataByte2Name]
    dataByte3 = dataByteDict[testByte3Name]
    loopbackThreeBytes(spiPort, dataByte1, dataByte2, datatByte3)
    return

# *** Test Example Loopback 1/2/3 bytes called by name ***

def testLoopbackOneByteByNameSpiPort00x5b():
    printBeginExecFunction()  
    loopBackOneByteByName('SpiPort00', '0x5b')
    printEndExecFunction()  
    return

def testLoopbackTwoBytesByNameSpiPort00x5bx5c():
    printBeginExecFunction()  
    loopBackTwoBytesByName('SpiPort00', '0x5b', '0x5c')
    printEndExecFunction()  
    return

def testLoopbackThreeBytesByNameSpiPort00x5bx5cx5d():
    printBeginExecFunction()  
    loopBackThreeBytesByName('SpiPort00', '0x5b', '0x5c', '0x5d')
    printEndExecFunction()  
    return

# *** Example Loopback 1 byte calling all SPI ports 00, 01, 10, 11, 12 ***

def testLoopbackSpiPortsAll():
    print('\n*** testLoopbackOneByte(spiPort00, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort00, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort01, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort01, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort10, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort10, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort11, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort11, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort12, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort12, 0x5b)

    print('\n*** testLoopbackOneByteByName("spiPort00", "0x5b") ***', end = '')
    testLoopbackOneByteByName('SpiPort00', '0x5b')
    return

# *** Example Loopback 1/2/3 byte calling SPI port names ***

def testLoopbackOneTwoThreeBytesSpiPorts00ByName():
    testLoopbackOneByteByNameSpiPort00x5b()
    testLoopbackTwoBytesByNameSpiPort00x5bx5c()
    testLoopbackThreeBytesByNameSpiPort00x5bx5cx5d()
    return

# *** Example Loopback 1/2/3 byte calling SPI port name list ***

def testLoopbackOneByteSpiPortNameList(spiPortNameList, dataByteName):
    #print('       testLoopbackOneByteSpiPortNameList(),....')
    for spiPortName in spiPortNameList:
        loopbackOneByteByName(spiPortName, dataByteName)
    #print('       End   testLoopbackOneByteSpiPortNameList().\n')
    return

def testLoopbackTwoBytesSpiPortNameList(spiPortNameList, dataByte1Name, dataByte2Name):
    for spiPortName in spiPortNameList:
        loopbackTwoBytesByName(spiPortName, dataByte1Name, dataByte2Name)
    return

def testLoopbackThreeBytesSpiPortNameList(spiPortNameList, dataByte1Name, dataByte2Name, dataByte3Name):
    for spiPortName in spiPortNameList:
        loopbackThreeBytesByName(spiPortName, dataByte1Name, dataByte2Name, dataByte3Name)
    return

# *** Repeat send byte functions ***

def repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes):
    print('       Begin repeatSendByte(),....')
    print('           Now use a scope to display the SPI signals, MOSI, MISO, CSn, ...')
    for i in range(repeatTimes):
      spiSendRecvOneByte(spiPort, sendByte)
      sleep(pauseSeconds)
    print('       End   repeatSendByte().', end = '')
    return

def repeatSendTwoBytes(spiPort, sendByte1, sendByte2, pauseSeconds, repeatTimes):
    print('       Begin repeatSendByte(),....')
    print('           Now use a scope to display the SPI signals, CLK, MOSI, MISO, CS0.  <ctrl>C to abort')
    for i in range(repeatTimes):
      spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
      sleep(pauseSeconds)
    print('       End   repeatSendByte().', end = '')
    return

def repeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName):
    spiPort  = spiPortDict[spiPortName]
    sendByte = dataByteDict[sendByteName]
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes)  
    return

def repeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName):
    spiPort  = spiPortDict[spiPortName]
    sendByte1 = dataByteDict[sendByte1Name]
    sendByte2 = dataByteDict[sendByte2Name]    
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    repeatSendTwoBytes(spiPort, sendByte1, sendByte2, pauseSeconds, repeatTimes)  
    return

# *** Test repeat send one byte functions ***

def testRepeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes):
    repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes)
    return

def testRepeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName):
    repeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName)
    return

def testRepeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName):
    repeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSecondsName, repeatTimesName)
    return

# *** Test Examples ***

def testRepeatSendOneByteByNameSpiPort000x5b0001Seconds100Times():
    testRepeatSendOneByteByName('SpiPort00', '0x5b', '0.001 second', '100 times')    
    return

def testRepeatSendOneByteSpiPortsAll():
    print('\n*** testRepeatSendOneByte(spiPort00, 0x5b, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort00, 0x5b, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort01, 0x5b, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort01, 0x5b, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort10, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort10, 0xb5, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort11, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort11, 0xb5, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort12, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort12, 0xb5, 0.001, 200)
    
    return
    
def testRepeatSendOneByteSpiPortsAllByName():
    printBeginExecFunction()  
    testRepeatSendOneByteByName('SpiPort00', '0x5b', '0.001 second', '100 times')
    printEndExecFunction()  
    return

def testRepeatSendOneByteSpiPortNameList(spiPortNameList, sendByteName, pauseSeconds, repeatTimes):
    for spiPortName in spiPortNameList:
        testRepeatSendOneByteByName(spiPortName, sendByteName, pauseSeconds, repeatTimes)
    return

def testRepeatSendTwoBytesSpiPortNameList(spiPortNameList, sendByte1Name, sendByte2Name, pauseSeconds, repeatTimes):
    for spiPortName in spiPortNameList:
        testRepeatSendTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name, pauseSeconds, repeatTimes)
    return

# *** Old Tests ***

    # *** Test loopback functions ***
    #testLoopbackSpiPortsAll()
    #testLoopbackOneTwoThreeBytesSpiPorts00ByName()
    #testLoopbackSpiPortNameListAll()  
    #testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')    
    #testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')
    #testLoopbackThreeBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '0x5d')

# *** Main ***

def main():

    # *** Print program title ***    
    printBeginProgram()
        
    # *** Set SPI Port Speed ***
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz') 
    #setSpiPortSpeedBySpiPortNameList(spiPortNameListAll, '100 kHz')  
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')     
  
    # *** Loopback Tests ***
    #testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')
    
    # *** Repeat Send Byte Tests ***
    #testRepeatSendOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b', '0.01 second', '100 times')
    
    # *** Repeat Send Two Bytes Tests ***
    testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '5 us', '1000000 times')
        
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '1 MHz')         
    #testRepeatSendTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '0.01 second', '1000000 times')

    printEndProgram()

# ********************************************************************************

if __name__ == '__main__':
    main()

# End of program

# *** Sample Output *** 

# *** End ***



4:19pm Thu. 8/13/2020





2:32pm Wed. 8/12/2020


MCP3201 Testing Program V1.0


https://penzu.com/p/f20e9949



Contents


adc_util01_v111.py tlfong01 2020aug12hkt1314


spi_util_01_v106.py tlfong01 2020aug11hkt1206



# Program:
#   adc_util01_v111.py tlfong01 2020aug12hkt1314
#
# Function:
#   Test (1) SPI loockback and repeat send byte
#        (2) test MCP3008, MCP3201, and MCP3208
#
# Contents
#  1. Program Config
#  2. System Utilities
#  3. SPI Utilities
#  4. Write/Read Device Reg Functions
#  5. Test MCP3008, MCP3201, and MCP3208 ADC

from time     import sleep
import               spidev
import               inspect
from datetime import datetime
import spi_util_01_v108 as spiutil

# *** 1. Program Config ***

programTitle = 'adcutil_01_v111'

# *** 2. System Utilities ***

def printBeginProgram():
    print('     Begin program ' + programTitle + '  tlfong01  ' + timeNowStr)
    #print(' ')
    return

def printEndProgram():
    print('\n     End   program ' + programTitle + '  tlfong01  ' + timeNowStr)
    return    
        
def printTitle(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]))    
    return

def printTitleNoNewLine(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]), end = '')    
    return

def printTitleString(title, indentFormat, string):
    printTitleNoNewLine(title, indentFormat)
    print('=', string)
    return

def printStarLine():
    print('')
    printTitle(('*' * 100), indentFormat480)
    print('')
    return

def printBeginExecFunction():
    functionName = inspect.stack()[1][3] 
    title = 'Begin Execute Function ' + functionName + '  ' + timeNowStr
    printStarLine()
    printTitle(title, indentFormat480)
    print('')
    printTitleString('Function Name', indentFormat640, functionName)
    return
    
def printEndExecFunction():
    title = 'End   Execute Function ' + inspect.stack()[1][3] + '  ' + timeNowStr
    print('')
    printTitle(title, indentFormat480)
    printStarLine()
    return

def convertOneByteNumToFourCharStr(oneByteNum): 
    tempStr = ((hex(oneByteNum))[2:])
    if (len(tempStr) != 2):
        tempStr = '0' + tempStr
    fourCharStr = '0x' + tempStr
    return fourCharStr

def convertTwoByteNumToEightCharStr(twoByteNum): # new <<<<<<<<<<
    tempStr = ((hex(twoByteNum))[2:])
    tempStr = '0' * (4 - len(tempStr)) + tempStr
    tenCharStr = '0x' + tempStr
    return tenCharStr

# *** Time Now String ***
 
timeNowStr = str(datetime.now())[0:16]

# *** Format string for print functions ***

indentFormat480 = [4, 80]
indentFormat608 = [6,  8]
indentFormat610 = [6, 10]
indentFormat615 = [6, 15]
indentFormat630 = [6, 30]
indentFormat640 = [6, 40]

# *** Repeat Times and Pause Dict ***

repeatTimesDict = {
    '1 times'         :        1,
    '10 times'        :       10,
    '100 times'       :      100,
    '1000 times'      :     1000,
    '10000 times'     :    10000,
    '100000 times'    :   100000,
    '1000000 times'   :  1000000,
    '10000000 times'  : 10000000
    }

sampleSizeDict = {
    '1 sample'          :        1,
    '10 samples'        :       10,
    '100 samples'       :      100,
    '1000 samples'      :     1000,
    '10000 samples'     :    10000,
    '100000 samples'    :   100000,
    '1000000 samples'   :  1000000,
    '10000000 samples'  : 10000000
    }
        
pauseSecondsDict = {
    '0.001 second'    : 0.001, 
    '0.002 second'    : 0.002,
    '0.01 second'     : 0.01,
    '0.1 second'      : 0.1,
    '10 ms'           : 0.01
    }

# *** 3. SPI Utilities ***

def testSpiUtil():
    
    print('       Begin testSpiUtil(), ...\n')
    
    # *** Test SPI Set Port Speed ***
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')
    #setSpiPortSpeedBySpiPortNameList(spiPortNameListAll, '100 kHz')  
        
    # *** Test SPI loopback ***
    #spiutil.testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')
    
    # *** Test SPI Repeat send one byte ***
    #spiutil.testRepeatSendOneByteSpiPortNameList(['SpiPort00'], '0x5b', '0.01 second', '100 times')   
    #spiutil.testRepeatSendOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b', '0.01 second', '100 times')   
   
    print('\n\n       End   testSpiUtil(), ...')
    return

# *********************************************************************************************************************
# *********************************************************************************************************************
# *********************************************************************************************************************

# *** Write/Read Device Register Functions ***

# *** 4. MCP23S17 Utilities ***

# *** Mcp23s17 Config ***

regAddrByteDict = \
    {   
    'IODIRA'    : 0x00, 
    'IODIRB'    : 0x01, 
    'IPOLA'     : 0x02,
    'IPOLB'     : 0x03, 
    'GPINTENA'  : 0x04, 
    'GPINTENB'  : 0x05, 
    'DEFVALA'   : 0x06, 
    'DEFVALB'   : 0x07, 
    'INTCONA'   : 0x08, 
    'INTCONB'   : 0x09, 
    'IOCON'     : 0x0b, 
    'IOCON'     : 0x0a, 
    'GPPUA'     : 0x0c, 
    'GPPUB'     : 0x0d, 
    'INTFA'     : 0x0e, 
    'INTFB'     : 0x0f, 
    'INTCAPA'   : 0x10, 
    'INTCAPB'   : 0x11,
    'GPIOA'     : 0x12,
    'GPIOB'     : 0x13,
    'OLATA'     : 0x14,
    'OLATB'     : 0x15,
    'PortA'     : \
            {
                'Direction'         : 0x00,
                'OutLatch'          : 0x14,
                'GpioPort'          : 0x12,
                'IntPinsEnable'     : 0x04,
                'IntPinsDefault'    : 0x06,
                'IntPinsCompare'    : 0x08,
                'InterruptFlagByte' : 0x0e,
                'IntCap'            : 0x10,
                'PullUp'            : 0x0c
            },
    'PortB'      : \
            {
                'Direction'         : 0x01,
                'OutLatch'          : 0x15,
                'GpioPort'          : 0x13,
                'IntPinsEnable'     : 0x05,
                'IntPinsDefault'    : 0x07,
                'IntPinsCompare'    : 0x09,
                'InterruptFlagByte' : 0x0f,
                'IntCap'            : 0x11,
                'PullUp'            : 0x0d
            },
        }
        
controlByteDict = \
     {
        'WriteRegBaseByte'                          : 0x40,
        'ReadRegBaseByte'                           : 0x41,
        'EnableAddressPins'                         : 0x08,
        'AllPinsOutput'                             : 0x00,
        'AllPinsInput'                              : 0xff,
        'Pin0OutputOtherPinsInput'                  : 0xfe,
        'LowNibblePinsOutputHighNibblePinsInput'    : 0xf0,
        'IntAllPinsEnable'                          : 0xff,
        'IntPinsEnable'                             : 0xff,
        'IntAllPinsCompareDefault'                  : 0xff,
        'AllPinsPullUp'                             : 0xff,
        'AllHigh'                                   : 0xff,
        'AllLow'                                    : 0x00,
        'AllPinsHigh'                               : 0xff,
        'AllPinsLow'                                : 0x00,
        'IntAllPinsHigh'                            : 0xff,
        'IntAllPinsLow'                             : 0x00,
        'IntLowNibblePinsEnable'                    : 0x0f,
        'IntLowNibblePinsComparePrevious'           : 0x00, 
    }


dataByteDict = \
    {
        '0x01'                                      : 0x01,
        '0x55'                                      : 0x55,
        '0x5b'                                      : 0x5b,
        '0x66'                                      : 0x66,
        '0xaa'                                      : 0xaa,
        '0x0f'                                      : 0x0f,
        '0xf0'                                      : 0xf0,
    }
 
# *** Mcp23s17 Functions ***

'''
def readDevRegOneByte(spiPortName, devRegAddrDict, devRegName):
    spiPort        = spiutil.spiPortDict[spiPortName]
    devRegAddr     = devRegAddrDict[devRegName]
    readDevRegAddr = (devRegaddr << 1) | 0x01  
    dummyByte      = 0x00
    recvByteArray  = spiutil.spiSendRecvTwoBytes(spiPort, readDevRegAddr, dummyByte)
    readByte       = recvByteArray[1]
    return readByte
'''
''' to rewrite
def writedDevRegOneByte(spiBusName, devRegAddrDict, devRegName, controlByteDict, writeByteName):
    spiBus         = spiBusDict[spiBusName]
    devRegAddr     = devRegAddrDict[devRegName]
    writeDevRegAddr = devRegAddr << 1
    writeByte = controlByteDict[writeByteName]
    spiSendRecvTwoBytes(spiBus, writeDevRegAddr, writeByte)
    return 
'''
'''
def testWriteReadPrintIoDirRegA(testDataByte):
    printDvRegOneByte(i2cCh1, dvAddrByte, ioDirRegAddrByteA, 'Old Byte =')
    writeDvRegOneByte(i2cCh1, dvAddrByte, ioDirRegAddrByteA, testDataByte)    
    printDvRegOneByte(i2cCh1, dvAddrByte, ioDirRegAddrByteA, 'New Byte =')
    return

def testMcp23s17():
    print('      Begin testMcp23s17(), ...')
    testWriteReadPrintIoDirRegA(dataByte0x55)
    print('      End   testMcp23s17(), ...')
    return


 # *** mcp23s17 Write/Read Functions ***
 
def mcp23s17WritedDevRegOneByte(spiPortName, devRegName, writeByteName, devRegAddrDict, dataByteDict):
    spiPort         = spiutil.spiPortDict[spiPortName]
    devRegAddr      = devRegAddrDict[devRegName]
    writeDevRegAddr = devRegAddr << 1
    writeByte       = dataByteDict[writeByteName]
    spiutil.spiSendRecvTwoBytes(spiBus, writeDevRegAddr, writeByte)
    return 

def mcp23s17ReadDevRegOneByte(spiBusName, devRegAddrDict, devRegName):
    spiBus         = spiBusDict[spiBusName]
    devRegAddr     = devRegAddrDict[devRegName]
    readDevRegAddr = (devRegaddr << 1) | 0x01  
    dummyByte      = 0x00
    recvByteArray  = spiSendRecvTwoBytes(spiBus, readDevRegAddr, dummyByte)
    readByte       = recvByteArray[1]
    return readByte
'''

def mcp23s17ReadRegOneByte(spiPortName, regAddrByteDict, regName):
    spiPort            = spiutil.spiPortDict[spiPortName]
    regAddrByte     = regAddrByteDict[regName]
    readRegAddrByte = (regAddrByte << 1) | 0x01  
    dummyByte          = 0x00
    recvByteArray      = spiutil.spiSendRecvTwoBytes(spiPort, readRegAddrByte, dummyByte)
    readByte           = recvByteArray[1]
    print('           spiPortName        =', spiPortName)
    print('           regName            =', regName)
    print('           regAddress         =', convertOneByteNumToFourCharStr(regAddrByte))
    print('           readByte           =', convertOneByteNumToFourCharStr(readByte))
    return readByte

def readIoDirA(spiPortName):
    print('         Read IODIRA')
    readByte = mcp23s17ReadRegOneByte(spiPortName, regAddrByteDict, 'IODIRA')
    print('         IODIRA contents =', convertOneByteNumToFourCharStr(readByte))
    return

def mcp23s17WritedRegOneByte(spiPortName, regAddrByteDict, regName, writeByteName):
    spiPort          = spiutil.spiPortDict[spiPortName]
    regAddrByte      = regAddrByteDict[regName]
    writeRegAddrByte = regAddrByte << 1
    writeByte        = dataByteDict[writeByteName]
    spiutil.spiSendRecvTwoBytes(spiPort, writeRegAddrByte, writeByte)
    print('           spiPortName        =', spiPortName)
    print('           regName            =', regName)
    print('           regAddress         =', convertOneByteNumToFourCharStr(regAddrByte))
    print('           writeByteName      =', writeByteName)
    print('           writeByte          =', convertOneByteNumToFourCharStr(writeByte))
    return

def writeIoDirA(spiPortName, writeByteName):
    print('         Write IODIRA', writeByteName)
    mcp23s17WritedRegOneByte(spiPortName, regAddrByteDict, 'IODIRA', writeByteName)
    return

# *** MCP23S17 Test Functions ***

def testMcp23s17(spiPortName):
    print('       Begin testMcp23s17(), ...')
    readIoDirA(spiPortName)
    writeIoDirA(spiPortName, '0x5b')
    readIoDirA(spiPortName)
    print('       End   testMcp23s17().')
    return

def testAdc(spiPortName, adcName, spiSpeedName):
    
    # 1. *** Set SPI speed ***
    print('\n       # *** Set SPI Port Speed ***')
    spiutil.setSpiPortSpeedBySpiPortNameList([spiPortName], spiSpeedName)
    print('')
    
    # 2. *** Test SPI loopback (for troubleshooting only) ***
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')
    
    # 3. *** Test ADC ***
    if adcName == 'MCP3208':
        pass
        # / to continue, ...        
        print('       ADC 12 Bit Results =', hex(adc12BitResults))
    if adcName == 'MCP3008':
        pass
        # / to continue, ...
    if adcName == 'MCP3201':
        print('       *** Read', adcName, 'Conversion Results ***')
        #spiPort = spiutil.spiPortDict[spiPortName]
        #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
        #adcResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
        adc12BitResults = readMcp3201(spiPortName)
        adcVolts   = (adc12BitResults / 0xfff) * 3.3
        print('       MCP3201 Results in 12 bits binary (expect fff/2~= 0x0800) =', convertTwoByteNumToEightCharStr(adc12BitResults))
        print('                       in V (expect 3.3V /2 ~= 1.65V)            =', "%.2f" % adcVolts, 'V')
    return

def readMcp3201BinaryResults(spiPortName):
    spiPort = spiutil.spiPortDict[spiPortName]
    recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
    adcBinaryResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
    return adcBinaryResults

def readMcp3201DecimalResults(spiPortName):
    adc12BitResults = readMcp3201(spiPortName)
    adcVoltResults = (adc12BitResults / 0xfff) * 3.3
    return adcDecimalResults

def repeatReadMcp3201(spiPortName, pauseSecondsName, repeatTimesName):
    spiPort = spiutil.spiPortDict[spiPortName]
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    
    for count in range(repeatTimes):
        #recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
        #adcResults = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
        adc12BitResults = readMcp3201(spiPortName)
        sleep(pauseSeconds)
    return adc12BitResults

refVoltDict = \
    {
    '0.00V'        : 0.00,
    '1.68V'        : 1.68,
    '2.048V'       : 2.048,
    '3.30V'        : 3.30,
    '4.096V'       : 4.096
    }

spiSpeedNameListDict = \
    {
    'All speeds name list' : ['10 kHz', '50 kHz', '100 kHz', '400 kHz', '1 MHz', '2 MHz', '4 MHz', '5 MHz', '6 MHz', '8 MHz', '10 MHz']
    }

def testAdcMultipleSpiSpeedsMultipleTimes(spiPortName, adcName, refVoltName, speedNameListName, sampleSizeName):
    spiPort = spiutil.spiPortDict[spiPortName]
    
    print('         Test Config: SPI Port =', spiPortName, ';', 'ADC =', adcName, ';', 'Speed List =',  speedNameListName, ';', 'Sample Size =', sampleSizeName) 
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10),'----------'.rjust(10),
                        '----------'.rjust(10), '----------'.rjust(10),'----------'.rjust(10))    
    print('        ', 'SPI Port'.rjust(10), 'Speed'.rjust(10), 'Mean Raw'.rjust(10), 'Mean Volt'.rjust(10), 'Error (%)'.rjust(10), \
                      'Max Volt'.rjust(10), 'Min Volt'.rjust(10), 'MaxMin Dif'.rjust(10), end = '')
    print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10),'----------'.rjust(10),
                        '----------'.rjust(10), '----------'.rjust(10),'----------'.rjust(10))    
  
    
    refVolt = refVoltDict[refVoltName]
    speedNameList = spiSpeedNameListDict[speedNameListName]
    sampleSize = sampleSizeDict[sampleSizeName]
    
    for speedName in speedNameList:
      # *** Set SPI speed ***
      spiutil.setSpiPortSpeedByName(spiPortName, speedName)
      
      # *** Read ADC Multiple Times***
 
      # repeatTimes = 1
      
      binResultList =  [0.0 for x in range(sampleSize)]
      decResultList =  [0.0 for x in range(sampleSize)]
      
      for count in range(sampleSize): 
          if adcName == 'MCP3008':
              print('Not available')
          if adcName == 'MCP3208':
              print('Not available')
          if adcName == 'MCP3201':
              recvArray = spiutil.spiSendRecvTwoBytes(spiPort, 0x00, 0x00)
              binResult = (((recvArray[0] & 0x3f) << 8) + recvArray[1]) >> 1
              decResult = (binResult / 0xfff) * 3.3
              error      = ((refVolt - decResult) / refVolt) * 100
              binResultList[count] = binResult
              decResultList[count] = decResult
      
      maxDecResult  = max(decResultList)
      minDecResult  = min(decResultList)
      meanDecResult = sum(decResultList) / sampleSize
      maxMinDiff    = maxDecResult - minDecResult

      #print('MaxDecResult  =', maxDecResult)
      #print('MinDecResult  =', minDecResult)
      #print('MeanDecResult =', meanDecResult)
      #print('MaxMinDiff    =', maxMinDiff)
         
      print('        ', spiPortName.rjust(10), end = '')
      print('', speedName.rjust(10), end = '')
      print('', convertTwoByteNumToEightCharStr(binResult).rjust(10), end = '')  
      print('', ("%.3f" % decResult).rjust(10), end = '')
      print('', ("%.1f" % error).rjust(10), end = '')
      print('', ("%.3f" % maxDecResult).rjust(10), end = '')
      print('', ("%.3f" % minDecResult).rjust(10), end = '')
      print('', ("%.3f" % maxMinDiff).rjust(10), end = '')
      
      print('\n        ', '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10), '----------'.rjust(10),'----------'.rjust(10),
                        '----------'.rjust(10), '----------'.rjust(10),'----------'.rjust(10))  
      
    return

# *** Main ***

def main():
    printBeginProgram()
    
    # *** Set SPI port speed ***
    #print('       # *** Set SPI Port Speed ***')
    #spiutil.setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz')
    
    #print('       # *** Repeat read MCP3201 ***') # <<< Not tested >>>
    #repeatReadMcp3201('SpiPort00', '10 ms', '100 times') 
    
    # *** Loopback 1/2 bytes ***
    #spiutil.testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #spiutil.testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')

    # *** Read MCP3201 ADC result at 100kHz ***
    #print('       # *** Test MCP3201 ADC ***')
    #testAdc('SpiPort00', 'MCP3201', '100 kHz')
    
    # *** Read MCP3201 ADC result with list of SPI speds ***
    print('\n       # *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***')
    testAdcMultipleSpiSpeedsMultipleTimes('SpiPort00', 'MCP3201', '1.68V', 'All speeds name list', '10 samples')   

    printEndProgram()
    return

if __name__ == '__main__':
    main()

# End of program

# *** Sample Output ***
'''
>>> %Run adc_util_01_v111.py
     Begin program adcutil_01_v111  tlfong01  2020-08-12 13:40

       # *** Test MCP3201 ADC with Ref Voltage = 1.68V, and a range of SPI speeds ***
         Test Config: SPI Port = SpiPort00 ; ADC = MCP3201 ; Speed List = All speeds name list ; Sample Size = 10 samples

         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
           SPI Port      Speed   Mean Raw  Mean Volt  Error (%)   Max Volt   Min Volt MaxMin Dif
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00     10 kHz     0x07ff      1.650        1.8      1.652      1.646      0.006
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00     50 kHz     0x0802      1.652        1.7      1.652      1.646      0.006
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00    100 kHz     0x07ff      1.650        1.8      1.650      1.647      0.003
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00    400 kHz     0x07fe      1.649        1.9      1.651      1.649      0.002
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00      1 MHz     0x0803      1.653        1.6      1.655      1.650      0.005
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00      2 MHz     0x07cc      1.608        4.3      1.608      1.604      0.005
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00      4 MHz     0x06ce      1.404       16.4      1.406      1.404      0.002
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00      5 MHz     0x0773      1.537        8.5      1.539      1.535      0.004
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00      6 MHz     0x02ff      0.618       63.2      0.618      0.618      0.000
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00      8 MHz     0x02ff      0.618       63.2      0.618      0.618      0.000
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------
          SpiPort00     10 MHz     0x02e0      0.593       64.7      0.593      0.593      0.000
         ---------- ---------- ---------- ---------- ---------- ---------- ---------- ----------

     End   program adcutil_01_v111  tlfong01  2020-08-12 13:40
>>> 
'''

# *** End ***



# Program:
#   spi_util_01_v106.py tlfong01 2020aug11hkt1206
# Function:
#   1. SPI one byte loopback
#   2. SPI repeatedly send one byte
#
# System Config: 
#   Rpi4B buster, python 3.7.3, thonny v3.2.7
#   pi@raspberrypi:~ $ date = Sat 08 Aug 2020 04:16:17 PM HKT
#   pi@raspberrypi:~ $ uname -a = Linux raspberrypi 4.19.118-v7l+ #1311 SMP Mon Apr 27 14:26:42 BST 2020 armv7l GNU/Linux

# Test Function Definitions:
#
# Test 1 - loopBackTest() - SPI port send and receive one byte.
#   Function - Send one byte to MOSI and read it back from MISO.
#     Setup - Connet MOSI pin to MISO pin to form a loop.
#
# Test 2 - repeatSendByte() - SPI port repeatedly send one bytes. 
#   Function - Repeat many times sending a byte, pause after each byte.

# Notes
#   1. SPI ports setup notes
#      To enable SPI and setup SPI 10, 11, 12 ports, add these two lines to /boot/config.txt
#        dtparam=spi=on
#        dtoverlay=spi1-3cs
#      To list SPI devices
#        pi@raspberrypi:~ $ ls /dev/spi*
#        /dev/spidev0.0  /dev/spidev0.1  /dev/spidev1.0  /dev/spidev1.1  /dev/spidev1.2

#   2. Notes of loopback function
#     Call example - testLoopbackOneByte(spiPort00)
#     Function     - send byte 0x5b to SPI MOSI and read byte from MISO
#     Setup        - must connect MOSI pin to MISO pin to loop back
#     Note         - 1. Only checks if MISO echoes MOSI, CS0, CS1, CS2 is not checked
#                    2. To check if SPI 0, CS0, CS1, or SPI1 CS0, CS1, CS2, need a scope to display repeat send bytes 

from time     import sleep
import               spidev
import               inspect
from datetime import datetime

# *** Program Config ***

programTitle = 'spituil_v95'

# *** SPI Port Setup/Config ***

spiPort00 = spidev.SpiDev()
spiPort00.open(0,0)

spiPort01 = spidev.SpiDev()
spiPort01.open(0,1)

spiPort10 = spidev.SpiDev()
spiPort10.open(1,0)

spiPort11 = spidev.SpiDev()
spiPort11.open(1,1)

spiPort12 = spidev.SpiDev()
spiPort12.open(1,2)


# *** SPI Port Name List and Dict ***

spiPortNameList00  = ['SpiPort00']
spiPortNameList01  = ['SpiPort01']
spiPortNameListAll = ['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12']

spiPortDict = {
    'SpiPort00'       : spiPort00,
    'SpiPort01'       : spiPort01,
    'SpiPort10'       : spiPort10,
    'SpiPort11'       : spiPort11,
    'SpiPort12'       : spiPort12,
    }

spiSpeedDict = {
    '10 MHz'       : 10000000,
    '8 MHz'        :  8000000,
    '6 MHz'        :  6000000,
    '5 MHz'        :  5000000,
    '4 MHz'        :  4000000,
    '2 MHz'        :  2000000,
    '1 MHz'        :  1000000,
    '400 kHz'      :   400000,
    '100 kHz'      :   100000,
    '50 kHz'       :    50000,
    '10 kHz'       :    10000,
    '1 kHz'        :     1000,
    '500 Hz'       :      500,
    }

dataByteDict = {
    '0x00'            :     0x00,
    '0x5a'            :     0x5a,
    '0x5b'            :     0x5b,
    '0x5c'            :     0x5c,
    '0x5d'            :     0x5d,
    '0x5e'            :     0x5e,
    '0x5f'            :     0x5f,
    '0x55'            :     0x55,
    '0x66'            :     0x66,
    '0x77'            :     0x77,
    }
    
repeatTimesDict = {
    '100 times'       :      100,
    '1000 times'      :     1000,
    '10000 times'     :    10000,
    '100000 times'    :   100000,
    '1000000 times'   :  1000000,
    '10000000 times'  : 10000000
    }
        
pauseSecondsDict = {
    '0.001 second'    : 0.001, 
    '0.002 second'    : 0.002,
    '0.01 second'     : 0.01,
    '0.1 second'      : 0.1
    }

# *** Set SPI Port Speed Functions ***

def setSpiPortSpeedByName(spiPortName, spiSpeedName):
    spiPort = spiPortDict[spiPortName]
    spiSpeed = spiSpeedDict[spiSpeedName]
    spiPort.max_speed_hz = spiSpeed
    return

def setSpiPortSpeedBySpiPortNameList(spiPortNameList, spiSpeedName):
    for spiPortName in spiPortNameList:
        setSpiPortSpeedByName(spiPortName, spiSpeedName)
        print('       spiPortName   =', spiPortName)
        print('       spiSpeedName  =', spiSpeedName)
    return

# *** Example Calls ***

#setSpiPortSpeedBySpiPortNameList('SpiPortNameListAll, '100 kHz')  
#setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')  

# *** Print Functions ***

def printBeginProgram():
    print('     Begin program ' + programTitle + '  tlfong01  ' + timeNowStr)
    print(' ')
    return

def printEndProgram():
    print('\n     End   program ' + programTitle + '  tlfong01  ' + timeNowStr)
    return    
        
def printTitle(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]))    
    return

def printTitleNoNewLine(title, indentFormat):
    print((' ' * (indentFormat[0])), title.ljust(indentFormat[1]), end = '')    
    return

def printTitleString(title, indentFormat, string):
    printTitleNoNewLine(title, indentFormat)
    print('=', string)
    return

def printStarLine():
    print('')
    printTitle(('*' * 100), indentFormat480)
    print('')
    return

def printBeginExecFunction():
    functionName = inspect.stack()[1][3] 
    title = 'Begin Execute Function ' + functionName + '  ' + timeNowStr
    printStarLine()
    printTitle(title, indentFormat480)
    print('')
    printTitleString('Function Name', indentFormat640, functionName)
    return
    
def printEndExecFunction():
    title = 'End   Execute Function ' + inspect.stack()[1][3] + '  ' + timeNowStr
    print('')
    printTitle(title, indentFormat480)
    printStarLine()
    return

def convertOneByteNumToFourCharStr(oneByteNum): 
    tempStr = ((hex(oneByteNum))[2:])
    if (len(tempStr) != 2):
        tempStr = '0' + tempStr
    fourCharStr = '0x' + tempStr
    return fourCharStr

# *** Time Now String ***
 
timeNowStr = str(datetime.now())[0:16]

# *** Format string for print functions ***

indentFormat480 = [4, 80]
indentFormat608 = [6,  8]
indentFormat610 = [6, 10]
indentFormat615 = [6, 15]
indentFormat630 = [6, 30]
indentFormat640 = [6, 40]

# *** SPI Send/Receive/Loopback/RepeatSend Byte Functions ***

# *** Send/Receive 1/2/3 bytes functions called by SPI ports spiPort00, spiPort01, spiPort10, spiPort11, spiPort12 ***

def spiSendRecvOneByte(spiPort, sendByte):
  sendByteArray = [sendByte]
  recvByteArray = spiPort.xfer(sendByteArray)  
  return recvByteArray

def spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2):
    sendByteArray = [sendByte1, sendByte2]
    recvByteArray = spiPort.xfer2(sendByteArray)    
    return recvByteArray

def spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
    sendByteArray = [sendByte1, sendByte2, sendByte3]
    recvByteArray = spiPort.xfer2(sendByteArray)    
    return recvByteArray

# *** Send/Receive 1/2/3 bytefunctions called by SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def spiSendRecvOneByteByName(spiPortName, sendByteName):
  spiPort  = spiPortDict[spiPortName]
  sendByte = dataByteDict[sendByteName]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte)  
  return recvByteArray

def spiSendRecvTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name):
  print(sendByte1Name)
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte1. sendByte2)  
  return recvByteArray

def spiSendRecvThreeBytesByName(spiPortName, sendByte1Name, sendByte2Name, sendByte3Name):
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  sendByte3 = dataByteDict[sendByte3Name]
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte1. sendByte2, sendByte3)  
  return recvByteArray

# *** Loopback 1/2/3 byte functions called by SPI ports spiPort00, spiPort01, spiPort10, spiPort11, spiPort12 ***

def loopBackOneByte(spiPort, sendByte):
  recvByteArray = spiSendRecvOneByte(spiPort, sendByte)
  recvByte      = recvByteArray[0]

  print('\n       Begin testLoopbackOneByte(),....')
  #print('')
  print('          sendByte                                = ', hex(sendByte))
  print('          recvByte                                = ', hex(recvByte))
  #print('')
  print('       End testLoopbackOneByte(),....\n')
  return

def loopbackTwoBytes(spiPort, sendByte1, sendByte2):
    #fprint.printBeginExecFunction()
    recvByteArray      = spiSendRecvTwoBytes(spiPort, sendByte1, sendByte2)
    recvByte1          = recvByteArray[0]
    recvByte2          = recvByteArray[1]
    sendBytes = convertOneByteNumToFourCharStr(sendByte1) + ' ' + convertOneByteNumToFourCharStr(sendByte2)
    printTitleString('sendBytes', indentFormat640, sendBytes)  
    recvBytes = convertOneByteNumToFourCharStr(recvByte1) + ' ' + convertOneByteNumToFourCharStr(recvByte2)
    printTitleString('recvBytes', indentFormat640, recvBytes)
    #printEndExecFunction()
    return

def loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3):
    #fprint.printBeginExecFunction()    
    recvByteArray      = spiSendRecvThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
    recvByte1          = recvByteArray[0]
    recvByte2          = recvByteArray[1]
    recvByte3          = recvByteArray[2]
    sendBytes = convertOneByteNumToFourCharStr(sendByte1) + ' ' + convertOneByteNumToFourCharStr(sendByte2) + ' ' + \
                convertOneByteNumToFourCharStr(sendByte3)
    printTitleString('sendBytes', indentFormat640, sendBytes)
    recvBytes = convertOneByteNumToFourCharStr(recvByte1) + ' ' + convertOneByteNumToFourCharStr(recvByte2) + ' ' + \
                convertOneByteNumToFourCharStr(recvByte3)
    printTitleString('sendBytes', indentFormat640, recvBytes)
    #printEndExecFunction()
    return

# *** Loopback 1/2/3 byte functions called bycalled SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def loopbackOneByteByName(spiPortName, sendByteName):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte = dataByteDict[sendByteName]
  loopBackOneByte(spiPort, sendByte)
  #printEndExecFunction() 
  return

def loopbackTwoBytesByName(spiPortName, sendByte1Name, sendByte2Name):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  
  loopbackTwoBytes(spiPort, sendByte1, sendByte2)
  #printEndExecFunction() 
  return

def loopbackThreeBytesByName(spiPortName, sendByte1Name, sendByte2Name, sendByte3Name):
  #printBeginExecFunction()  
  spiPort  = spiPortDict[spiPortName]
  sendByte1 = dataByteDict[sendByte1Name]
  sendByte2 = dataByteDict[sendByte2Name]
  sendByte3 = dataByteDict[sendByte3Name]
  
  loopbackThreeBytes(spiPort, sendByte1, sendByte2, sendByte3)
  #printEndExecFunction() 
  return

# *** Test loopback one byte function call by SPI port ***

def testLoopbackOneByte(spiPort, dataByte):
  loopackOneByte(spiPort, dataByte)
  return

# *** Test loopback one byte function called by SPI port names 'SpiPort00','SpiPort01','SpiPort10','SpiPort11','SpiPort12' ***

def testLoopbackOneByteByName(spiPortName, dataByteName):
  loopackOneByteByName(spiPortName, dataByteName)
  return

def testLoopbackTwoBytesByName(spiPortName, dataByte1Name, dataByte2Name):
    spiPort = spiPortDict[spiPortName]
    dataByte1 = dataByteDict[dataByte1Name]
    dataByte2 = dataByteDict[testByte2Name]
    loopbackTwoBytes(spiPort, datatByte1, dataByte2)
    return

def testLoopbackThreeBytesByName(spiPortName, dataByte1Name, dataByte2Name, dataByte3Name):
    spiPort = spiPortDict[spiBusName]
    dataByte1 = dataByteDict[dataByte1Name]
    dataByte2 = dataByteDict[dataByte2Name]
    dataByte3 = dataByteDict[testByte3Name]
    loopbackThreeBytes(spiPort, dataByte1, dataByte2, datatByte3)
    return

# *** Test Example Loopback 1/2/3 bytes called by name ***

def testLoopbackOneByteByNameSpiPort00x5b():
    printBeginExecFunction()  
    loopBackOneByteByName('SpiPort00', '0x5b')
    printEndExecFunction()  
    return

def testLoopbackTwoBytesByNameSpiPort00x5bx5c():
    printBeginExecFunction()  
    loopBackTwoBytesByName('SpiPort00', '0x5b', '0x5c')
    printEndExecFunction()  
    return

def testLoopbackThreeBytesByNameSpiPort00x5bx5cx5d():
    printBeginExecFunction()  
    loopBackThreeBytesByName('SpiPort00', '0x5b', '0x5c', '0x5d')
    printEndExecFunction()  
    return

# *** Example Loopback 1 byte calling all SPI ports 00, 01, 10, 11, 12 ***

def testLoopbackSpiPortsAll():
    print('\n*** testLoopbackOneByte(spiPort00, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort00, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort01, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort01, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort10, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort10, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort11, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort11, 0x5b)

    print('\n*** testLoopbackOneByte(spiPort12, 0x5b) ***', end = '')
    testLoopbackOneByte(spiPort12, 0x5b)

    print('\n*** testLoopbackOneByteByName("spiPort00", "0x5b") ***', end = '')
    testLoopbackOneByteByName('SpiPort00', '0x5b')
    return

# *** Example Loopback 1/2/3 byte calling SPI port names ***

def testLoopbackOneTwoThreeBytesSpiPorts00ByName():
    testLoopbackOneByteByNameSpiPort00x5b()
    testLoopbackTwoBytesByNameSpiPort00x5bx5c()
    testLoopbackThreeBytesByNameSpiPort00x5bx5cx5d()
    return

# *** Example Loopback 1/2/3 byte calling SPI port name list ***

def testLoopbackOneByteSpiPortNameList(spiPortNameList, dataByteName):
    #print('       testLoopbackOneByteSpiPortNameList(),....')
    for spiPortName in spiPortNameList:
        loopbackOneByteByName(spiPortName, dataByteName)
    #print('       End   testLoopbackOneByteSpiPortNameList().\n')
    return

def testLoopbackTwoBytesSpiPortNameList(spiPortNameList, dataByte1Name, dataByte2Name):
    for spiPortName in spiPortNameList:
        loopbackTwoBytesByName(spiPortName, dataByte1Name, dataByte2Name)
    return

def testLoopbackThreeBytesSpiPortNameList(spiPortNameList, dataByte1Name, dataByte2Name, dataByte3Name):
    for spiPortName in spiPortNameList:
        loopbackThreeBytesByName(spiPortName, dataByte1Name, dataByte2Name, dataByte3Name)
    return

# *** Repeat send byte functions ***

def repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes):
    print('       Begin repeatSendByte(),....')
    print('           Now use a scope to display the SPI signals, MOSI, MISO, CSn, ...')
    for i in range(repeatTimes):
      spiSendRecvOneByte(spiPort, sendByte)
      sleep(pauseSeconds)
    print('       End   repeatSendByte().', end = '')
    return

def repeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName):
    spiPort  = spiPortDict[spiPortName]
    sendByte = dataByteDict[sendByteName]
    pauseSeconds = pauseSecondsDict[pauseSecondsName]
    repeatTimes = repeatTimesDict[repeatTimesName]
    repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes)  
    return

# *** Test repeat send one byte functions ***

def testRepeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes):
    repeatSendOneByte(spiPort, sendByte, pauseSeconds, repeatTimes)
    return

def testRepeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName):
    repeatSendOneByteByName(spiPortName, sendByteName, pauseSecondsName, repeatTimesName)
    return

# *** Test Examples ***

def testRepeatSendOneByteByNameSpiPort000x5b0001Seconds100Times():
    testRepeatSendOneByteByName('SpiPort00', '0x5b', '0.001 second', '100 times')    
    return

def testRepeatSendOneByteSpiPortsAll():
    print('\n*** testRepeatSendOneByte(spiPort00, 0x5b, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort00, 0x5b, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort01, 0x5b, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort01, 0x5b, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort10, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort10, 0xb5, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort11, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort11, 0xb5, 0.001, 200)

    print('\n*** testRepeatSendOneByte(spiPort12, 0xb5, 0.001, 2x) ***', end = '')
    testRepeatSendOneByte(spiPort12, 0xb5, 0.001, 200)
    
    return
    
def testRepeatSendOneByteSpiPortsAllByName():
    printBeginExecFunction()  
    testRepeatSendOneByteByName('SpiPort00', '0x5b', '0.001 second', '100 times')
    printEndExecFunction()  
    return

def testRepeatSendOneByteSpiPortNameList(spiPortNameList, sendByteName, pauseSeconds, repeatTimes):
    for spiPortName in spiPortNameList:
        testRepeatSendOneByteByName(spiPortName, sendByteName, pauseSeconds, repeatTimes)
    return

# *** Old Tests ***

    # *** Test loopback functions ***
    #testLoopbackSpiPortsAll()
    #testLoopbackOneTwoThreeBytesSpiPorts00ByName()
    #testLoopbackSpiPortNameListAll()  
    #testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')    
    #testLoopbackTwoBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c')
    #testLoopbackThreeBytesSpiPortNameList(['SpiPort00'], '0x5b', '0x5c', '0x5d')

# *** Main ***

def main():

    # *** Print program title ***    
    printBeginProgram()
        
    # *** Set SPI Port Speed ***
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00'], '100 kHz') 
    setSpiPortSpeedBySpiPortNameList(spiPortNameListAll, '100 kHz')  
    #setSpiPortSpeedBySpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '100 kHz')     
  
    # *** Loopback Tests ***
    testLoopbackOneByteSpiPortNameList(['SpiPort00'], '0x5b')
    #testLoopbackOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b')
    
    # *** Repeat Send Byte Tests ***
    #testRepeatSendOneByteSpiPortNameList(['SpiPort00', 'SpiPort01', 'SpiPort10', 'SpiPort11', 'SpiPort12'], '0x5b', '0.01 second', '100 times')
        
    printEndProgram()

# ********************************************************************************

if __name__ == '__main__':
    main()

# End of program

# *** Sample Output *** 

# *** End ***

2:32pm Wed. 8/12/202



Joe Biden

RCA Tunnel Diode Manual - RCA 1966

 RCA Tunnel Diode Manual - RCA 1966 https://www.yumpu.com/en/document/read/23901571/rca-tunnel-diode-manual