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



Wednesday 30 2020

KA431 Shunt Regulator Learning Notes - Part 1 (Datasheet)

KA431 Shunt Regulator Learning Notes - Part 1 (Datasheet)














KA431 Programmable Shun Regulator Datasheet

Description

The KA431A and KA431L are three−terminal adjustable regulators with a guaranteed thermal stability over the operating temperature range. The output voltage can be set to any value between VREF

(approximately 2.5 V) and 36 V with two external resistors. These devices have a typical dynamic output impedance of 0.2 . Active output circuitry provides a sharp turn−on characteristic, making these  devices excellent replacements for Zener diodes in many applications.

Features

Programmable Output Voltage to 36 V

Low Dynamic Output Impedance: 0.2  (Typical)

Sink Current Capability: 1.0 to 100 mA

Equivalent Full−Range Temperature Coefficient of 50 ppm/°C (Typical)

Temperature Compensated for Operation Over Full Rated Operating Temperature Range

Low Output Noise Voltage

Fast Turn−on Response


.END


MCP4725 DAC Learning Notes - Part 8 (Quad DAC Board Setup)

MCP4725 DAC Learning Notes - Part 8 (Quad DAC Board Setup)










Quad MCP4725 Blink LED



https://youtu.be/G6fMo1TroXw

Monday 28 2020

MCP4725 DAC Learning Notes - Part 7 (Calibration OK)

MCP4725 DAC Learning Notes - Part 7 (Calibration OK)


# mcp4725v259.py  tlfong01 2020dec28hkt1551


from datetime      import datetime

from time          import sleep

from signal        import pause

import             os

import             sys

import             smbus


# *** Config ***


i2cBus1 = smbus.SMBus(1) 


i2cBusDict = {'I2cBus1': i2cBus1,

             }


# *** System Functions ***


def pause(pauseTimeName):

    sleep(i2cControlByteDict[pauseTimeName])

    return


def convertTwoCompNumToDecNum(twoCompNum):

    twoCompNumStr = bin(twoCompNum)

    numBytes = 2

    val = int(twoCompNumStr, numBytes)

    b = val.to_bytes(numBytes, byteorder=sys.byteorder, signed = False)

    return int.from_bytes(b, byteorder = sys.byteorder, signed = True)


i2cControlByteDict = {

    'TenMilliSeconds'    : 0.01,

    'FourTimes'          : 4,

    'OneMillionTimes'    : 1000000,

    'TwentyMilliSeconds' : 0.02,

    }


timeNowLong  = str(datetime.now())

timeNowShort = str(datetime.now())[0:16]


# *** System Config Functions ***


def getSystemInfo():

    print('\n# *** System Info *****************************************************')

    

    print('\n>>>>> ', 'Date', '<<<<<')

    os.system('date')

    

    print('\n>>>>> ', 'linux version', 'buster version, Rpi4B model, Rpi4B memory', '<<<<<')

    os.system('cat /etc/issue.net')

    os.system('uname -a')

    os.system('grep Model /proc/cpuinfo')

    os.system('grep MemTotal /proc/meminfo')

    

    print('\n>>>>> ', 'i2c baudrate', '<<<<<')

    os.system('grep dtparam=i2c /boot/config.txt')

    

    print('\n>>>>> ', 'i2c dtoverlay', '<<<<<')

    os.system('grep dtoverlay=i2c /boot/config.txt')

    print('\n>>>>> ', 'ls /dev/i2c*', '<<<<<')    

    os.system('ls /dev/i2c*')

    i2cdetectCommand = 'i2cdetect -y 1'

    print('\n>>>>> ', i2cdetectCommand, '<<<<<')

    os.system(i2cdetectCommand)

    #i2cdetectCommand = 'i2cdetect -y 3'

    #print('\n>>>>> ', i2cdetectCommand, '<<<<<')

    #os.system(i2cdetectCommand)

    #i2cdetectCommand = 'i2cdetect -y 4'

    #print('\n>>>>> ', i2cdetectCommand, '<<<<<')

    #os.system(i2cdetectCommand) 

    return


def getUartConfigInfo():

    print('\n# *** UART BaudRate *****************************************************') 

    os.system('grep dtparam=i2c /boot/config.txt')

    return


# *** Write/Read Device One Byte ***


def quickWriteDevOneByte(i2cBus, devAddr, writeByte):

    i2cBus.write_byte(devAddr, writeByte)

    return    


def quickReadDevOneByte(i2cBus, devAddr):

    readByte = i2cBus.read_byte(devAddr)

    return readByte


# *** Write/Read/Print Device Two Bytes / Device Register One Byte ***


def writeDevTwoBytes(i2cBus, devAddr, writeByte1, writeByte2):

    i2cBus.write_byte_data(devAddr, writeByte1, writeByte2)

    return


def writeDevThreeBytes(i2cBus, devAddr, writeByte1, writeByte2, writeByte3): 

    i2cBus.write_block_data(devAddr, writeByte1, [writeByte2, writeByte3])

    return


def writeRegOneByte(i2cBus, devAddrDict, devAddrName, regAddrDict, regName, writeByte):

    devAddr = devAddrDict[devAddrName]

    regAddr = regAddrDict[regName]

    writeDevTwoBytes(i2cBus, devAddr, regAddr, writeByte)

    return


def readDevOneByte(i2cBus, devAddrAddr, readByteAddr):

    readByte = i2cBus.read_byte_data(devAddr, readByteAddr)

    return readByte


def readDevReadByteAddrByteOneByte(i2cBus, devAddrAddr, readByteAddr): # !!! Not Tested !!!

    readByte = readDevOneByte(i2cBus, devAddrAddr, readByteAddr)

    return readByte


def readDevControlByteOneByte(i2cBus, devAddr, controlByte):

    readByte = i2cBus.read_byte_data(devAddr, controlByte)

    return readByte


def readRegOneByte(i2cBus, devAddrDict, devName, regAddrDict, regName):

    devAddr = devAddrDict[devName]

    regAddr = regAddrDict[regName]

    readByte = i2cBus.read_byte_data(devAddr, regAddr)

    return readByte


def printRegOneByte(i2cBus, devAddrDict, devName, regAddrDict, regName):

    readByte = readRegOneByte(i2cBusName, devAddrDict, devName, regAddrDict, regName)

    print(printTitle, hex(readByte))

    return

  

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


def readRegister(busName, devAddrDict, devAddrName, regAddrDict, regAddrName):

   

    i2cBus = i2cBusDict[busName]

    readByte = readRegOneByte(i2cBus, devAddrDict, devAddrName, regAddrDict, regAddrName)

    

    return readByte


def readVerifyRegister(moduleType, moduleNickName, busName, devAddrDict, devAddrName, regAddrDict, regAddrName, controlByteDict, verifyByteName):

    

    i2cBus = i2cBusDict[busName]

    verifyByte = controlByteDict[verifyByteName]

    

    readByte = readRegOneByte(i2cBus, devAddrDict, devAddrName, regAddrDict, regAddrName) 

    

    if readByte == verifyByte:

        verifyResultsString = 'Success'

    else:

        verifyResultsString = 'Failure'


    devAddr = devAddrDict[devAddrName]

    

    fprint.printTitleString('Date Time',                           fprint.indentFormat640, str(datetime.now())[0:16])

    fprint.printTitleString('ModuleType',                          fprint.indentFormat640, moduleType)

    fprint.printTitleString('ModuleNickName',                      fprint.indentFormat640, moduleNickName)

    fprint.printTitleString('I2C Bus Name',                        fprint.indentFormat640, busName)

    fprint.printTitleString('Device Addr Name',                    fprint.indentFormat640, devAddrName)

    fprint.printTitleOneByteNum('Device Address',                  fprint.indentFormat640, devAddr)

    fprint.printTitleString('Register Name',                       fprint.indentFormat640, regAddrName)

    fprint.printTitleOneByteNum('VerifyByte',                      fprint.indentFormat640, verifyByte) 

    fprint.printTitleOneByteNum('Byte Read from Register',         fprint.indentFormat640, readByte)    

    fprint.printTitleString('Verify Results',                      fprint.indentFormat640, verifyResultsString)

 

    return verifyResultsString


def writeVerifyRegister(moduleType, moduleNickName, busName, devAddrDict, devAddrName, regAddrDict, regAddrName, controlByteDict, writeByteName):

    

    i2cBus = i2cBusDict[busName]

    writeByte = controlByteDict[writeByteName]

    

    writeRegOneByte(i2cBus, devAddrDict, devAddrName, regAddrDict, regAddrName, writeByte) 

    readByte = readRegOneByte(i2cBus, devAddrDict, devAddrName, regAddrDict, regAddrName) 

    

    if readByte == writeByte:

        resultsString = 'Success'

    else:

        resultsString = 'Failure'


    devAddr = devAddrDict[devAddrName]

    

    fprint.printTitleString('Date Time',                           fprint.indentFormat640, str(datetime.now())[0:16])

    fprint.printTitleString('ModuleType',                          fprint.indentFormat640, moduleType)

    fprint.printTitleString('ModuleNickName',                      fprint.indentFormat640, moduleNickName)

    fprint.printTitleString('I2C Bus Name',                        fprint.indentFormat640, busName)

    fprint.printTitleString('Device Addr Name',                    fprint.indentFormat640, devAddrName)

    fprint.printTitleOneByteNum('Device Address',                  fprint.indentFormat640, devAddr)

    fprint.printTitleString('Register Name',                       fprint.indentFormat640, regAddrName)

    fprint.printTitleOneByteNum('Byte Written   to   Register',    fprint.indentFormat640, writeByte) 

    fprint.printTitleOneByteNum('Byte Read back from Register',    fprint.indentFormat640, readByte)    

    fprint.printTitleString('Verify Results',                      fprint.indentFormat640, resultsString)

 

    return


def writeVerifyModuleRegister(moduleTypeName, moduleNickName, regAddrName, writeByteName):

    

    moduleDict = moduleDictDict[moduleTypeName]

    

    moduleType = moduleDict['ModuleType']    

    busName = moduleDict[moduleNickName]['I2cBusName']

    controlByteDict = moduleDict['ControlByteDict']

    

    devAddrDict = moduleDict['DevAddrDict']

    devAddrName = moduleDict[moduleNickName]['DevAddrName']

    

    regAddrDict = moduleDict['RegAddrDict']

    regAddr     = regAddrDict[regAddrName] 

    

    i2cBus = i2cBusDict[busName]

    writeByte = controlByteDict[writeByteName]

    

    writeRegOneByte(i2cBus, devAddrDict, devAddrName, regAddrDict, regAddrName, writeByte) 

    readByte = readRegOneByte(i2cBus, devAddrDict, devAddrName, regAddrDict, regAddrName) 

    

    if readByte == writeByte:

        writeVerifyResultsString = 'Success'

    else:

        writeVerifyResultsString = 'Failure'


    devAddr = devAddrDict[devAddrName]

    

    fprint.printTitleString('Date Time',                                fprint.indentFormat640, str(datetime.now())[0:16])

    fprint.printTitleString('ModuleType',                               fprint.indentFormat640, moduleType)

    fprint.printTitleString('ModuleNickName',                           fprint.indentFormat640, moduleNickName)

    fprint.printTitleString('I2C Bus Name',                             fprint.indentFormat640, busName)

    fprint.printTitleString('Device Addr Name',                         fprint.indentFormat640, devAddrName)

    fprint.printTitleOneByteNum('Device Address Byte',                  fprint.indentFormat640, devAddr)

    fprint.printTitleString('Register Name',                            fprint.indentFormat640, regAddrName)

    fprint.printTitleOneByteNum('Register Address Byte',                fprint.indentFormat640, regAddr)   

    fprint.printTitleString('WriteByteName',                            fprint.indentFormat640, writeByteName) 

    fprint.printTitleOneByteNum('WriteByte (Written to   Register)',    fprint.indentFormat640, writeByte) 

    fprint.printTitleOneByteNum('ReadByte  (Read    from Register)',    fprint.indentFormat640, readByte)    

    fprint.printTitleString('Write Verify Results',                     fprint.indentFormat640, writeVerifyResultsString)


    return writeVerifyResultsString


def pingModule(moduleTypeName, moduleNickName):

    

    moduleDict = moduleDictDict[moduleTypeName]

    

    moduleType = moduleDict['ModuleType']    

    busName = moduleDict[moduleNickName]['I2cBusName']

    controlByteDict = moduleDict['ControlByteDict']

    

    devAddrDict = moduleDict['DevAddrDict']

    devAddrName = moduleDict[moduleNickName]['DevAddrName']

    

    regAddrDict = moduleDict['RegAddrDict']

    regAddrName = moduleDict['PingRegAddrName']

    

    writeByteName = moduleDict['PingWriteByteName']    

  

    writeVerifyRegister(moduleType, moduleNickName, busName, devAddrDict, devAddrName, regAddrDict, regAddrName,

                          controlByteDict, writeByteName)

  

    return


def readModuleRegister(moduleTypeName, moduleNickName, regAddrName):

    

    moduleDict = moduleDictDict[moduleTypeName]

    

    moduleType = moduleDict['ModuleType']    

    busName = moduleDict[moduleNickName]['I2cBusName']

    controlByteDict = moduleDict['ControlByteDict']

    

    devAddrDict = moduleDict['DevAddrDict']

    devAddrName = moduleDict[moduleNickName]['DevAddrName']

    

    regAddrDict = moduleDict['RegAddrDict']

    

    readByte = readRegister(busName, devAddrDict, devAddrName, regAddrDict, regAddrName)

  

    return readByte


def readRegister(busName, devAddrDict, devAddrName, regAddrDict, regAddrName):

    

    i2cBus = i2cBusDict[busName]    

 

    readByte = readRegOneByte(i2cBus, devAddrDict, devAddrName, regAddrDict, regAddrName)

    

    return readByte

 

# ========== ========== ========== ========== ========== ========== ========== ==========  

# *** MCP4725 *** 

# ========== ========== ========== ========== ========== ========== ========== ==========


mcp4725I2cDevAddr = 0x60


mcp4725DevAddrDict = {

                'DevAddr0': 0x60,

                'DevAddr1': 0x61,

              }


mcp4725ControlByteDict = {

                    'ChannelNum0': 0x00,

                    'ChannelNum1': 0x01,

                }


mcp4725ModuleDict = {

                      'ModuleType'       : 'MCP4725',

                      'GreenTea': {'SignalName'     : 'GreenTea',

                                    'I2cBusName'     : 'I2cBus4',

                                    'DevAddrName'    : 'DevAddr0',

                                    'ChannelNumName' : 'ChannelNum0',

                            }, 

            }


# *** Digital and Analog Conversion Functions *


def digiAnaConvertV08(i2cBus, devAddr, writePowerMode, digiVal):

    writePowerModeDigiValMsb = (writePowerMode << 4) | ((digiVal & 0xf00) >> 8)

    #writePowerModeDigiValMsb = 0x0f

    digiValLsb               = digiVal & 0x0ff

    

    print('  I2cBusName     =', 'I2cBus1')      

    print('  devAddr        =', hex(0x60))

    print('  writePowerMode =', hex(writePowerMode))

    print('  digiVal        =', hex(digiVal))

    print('  writePowerModeDigiValMsb =', hex(writePowerModeDigiValMsb)) 

    print('  digiValLsb     =', hex(digiValLsb))

    

    writeDevTwoBytes(i2cBus, devAddr, writePowerModeDigiValMsb, digiValLsb)

    return


def testDigiAnaConvertV08():

    i2cBus         = i2cBus1

    devAddr        = 0x60

    writePowerMode = 0x0

    digiVal        = 0xfff

    pauseSeconds   = 1

    

    digiVal = 0x0ff

    for dacCount in range(15):

        digiAnaConvertV08(i2cBus, devAddr, writePowerMode, digiVal)

        sleep(0.25)

        digiVal = digiVal + 0x100

    return


# *** DC Sweep Functions ***


def daConvertV09(i2cBus, devAddr, writePowerMode, digiVal):

    #print('Begin daConvertV09(), ...')

    writePowerModeDigiValMsb = (writePowerMode << 4) | ((digiVal & 0xf00) >> 8)

    digiValLsb               = digiVal & 0x0ff

    

    #print('  I2cBusName     =', 'I2cBus1')      

    #print('  devAddr        =', hex(0x60))

    #print('  writePowerMode =', hex(writePowerMode))

    #print('  digiVal        =', hex(digiVal))

    #print('  writePowerModeDigiValMsb =', hex(writePowerModeDigiValMsb)) 

    #print('  digiValLsb     =', hex(digiValLsb))

    

    writeDevTwoBytes(i2cBus, devAddr, writePowerModeDigiValMsb, digiValLsb)

    #print('End   daConvertV09().')

    return


def dcSweepV01():

    #print('Begin testDaConvertV09(), ...')

    i2cBus          = i2cBus1

    devAddr         = 0x60

    writePowerMode  = 0b0000

    digiValBegin    = 0x000

    digiValEnd      = 0xfff

    TenMilliSeconds = 0.01

 

    digiVal = digiValBegin

    for convertCount in range(100):

        daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

        sleep(TenMilliSeconds)

        digiVal = digiVal + 0x50

        

    #print('End   testDaConvertV09().')

    return


def testDcSweepV01():

    print('Begin testDcSweepV01(), ...')    

    for testCount in range(100000):

        dcSweepV01()

    print('End   testDcSweepV01(), ...') 

    return



digiValDict = \

    {    'FullScale'    : 0xfff, # 3.29V (no load)

         'HalfScale'    : 0x800, # 1.65V

         'ZeroScale'    : 0x000, # 0.00V

         '3.00V'        : 0xe98,

         '1.50V'        : 0xe98 >> 1,

         '0.75V'        : 0xe98 >> 2,

         '0.77V'        : (0xe98 >> 2) + 0x020,

         '0.01V'        : 0x010,

         '0.02V'        : 0x020,

         '0.00V'        : 0x000,

    }


devAddrDict = \

    {

        'Mcp4725'       : 0x60

    }

    

def testCalibrate():

    print('Begin testCalibrate(), ...')

    i2cBusName      = 'I2cBus1'

    devAddrName     = 'Mcp4725'

    

    i2cBus          = i2cBusDict[i2cBusName]

    devAddr         = devAddrDict[devAddrName]

    

    writePowerMode  = 0b0000

    digiValBegin    = 0x000

    digiValEnd      = 0xfff


    '''

    digiVal = digiValDict['FullScale']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', 'FullScale')

    print('End   testCalibrate().')

    sleep(2)

    

    digiVal = digiValDict['HalfScale']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', 'HalfScale')

    print('End   testCalibrate().')

    sleep(2)

    

    digiVal = digiValDict['ZeroScale']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', 'ZeroScale')

    print('End   testCalibrate().')

    sleep(2)

    '''

    

    '''

    digiVal = digiValDict['3.00V']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', '3.00V')

    sleep(2)

    

    digiVal = digiValDict['1.50V']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', '1.50')

    sleep(2)

    

    digiVal = digiValDict['0.75V']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', '0.75V')

    sleep(2)

    '''

    

    digiVal = digiValDict['0.01V']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', '0.01V')

    sleep(2)

    

    digiVal = digiValDict['0.02V']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', '0.02V')

    sleep(2)


    digiVal = digiValDict['0.77V']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', '0.77V')

    sleep(2)

    

    '''

    digiVal = digiValDict['0.00V']

    daConvertV09(i2cBus, devAddr, writePowerMode, digiVal)

    print('DigiVal =', '0.00V')

    sleep(2)    

    '''

    

    print('End   testCalibrate().')

    return    


# *** Init/Main Function ***


def init():

    pass

    return


def main(): 

    #testDigiAnaConvertV08()

    #testDcSweepV01()

    testCalibrate()

    return


if __name__ == '__main__':

    main()


# *** End of Program ********************************************************************


# *** 11. Sample Outputs ***


'''


'''


# *** End of Sample Output ***



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