MicroPython的午睡(143)RPi PicoでM5Stackを挿げ替える

Joseph Halfmoon

たまたまその上でMicroPythonやっていたというだけで「ソフトウエア制御DMAC」のシーケンサと化していたM5Stackです。折角のM5Stackを単なるシーケンサに使うのはモッタイナイ。そこで今回「シーケンサ」ホストを台数に余裕のあるRaspberry Pi Pico機に変更。M5Stackはお役目から解放。

※「MicroPython的午睡」投稿順 Indexはこちら

こういうホストを挿げ替えるような荒業を行うとき、C言語などで制御ソフトを書いていたらと思うと呆然としたでありましょうが、MicroPythonなら恐れるもなにもありません。ちょこちょこと端子名を書き変えたくらいで動作してしまいます。こういうときはMicroPythonサイコー。

でもまターゲットの回路は同じなので信号品質が悪い問題はまったく解決していないんだけれども。

まずは、ホスト挿げ替えの荒業を繰り出した後の回路が以下に。RPIPCO_SOFTDMA_SRAM_schematic

 

 

前回と比べ、どこが変わったの?という感じ。

MicroPythonスクリプトが以下に。これまた前回との変更点は、ファイルコンペアでもかけないと差には気づきずらいっす(前回はコードを貼り付けてなかったけど。)

# softDMA_REWRtest.py RpiPico
from machine import SoftI2C, Pin
import sys
import time

IOEX0 = 0x20
IOEX1 = 0x21
IOCONA = 0x0A
IOCONB = 0x0B
IODIRA = 0x00
IODIRB = 0x01
GPIOA = 0x12
GPIOB = 0x13
OLATA = 0x14
OLATB = 0x15

recount = 0
wecount = 0

i2c = SoftI2C(scl=Pin(1), sda=Pin(0), freq=100000)

def isIOEXavailable():
    global i2c
    lis = i2c.scan()
    if (IOEX0 in lis) and (IOEX1 in lis):
        return True
    return False

def readByte(i2cADR, regADR):
    global i2c, recount
    bufW = bytes([regADR])
    try:
        lim = 0
        while lim < 5:
            if i2c.writeto(i2cADR, bufW) != 1:
                lim += 1
                time.sleep_us(10) #$$$
            else:
                break
        if lim >= 5:
            return -2
        bufR = bytearray(1)
        ackR = i2c.readfrom_into(i2cADR, bufR)
    except OSError:
        recount += 1
        return -1       
    return int.from_bytes(bufR, 'little')  

def writeByte(i2cADR, regADR, dat):
    global i2c, wecount
    bufW = bytes([regADR, dat])
    try:
        lim = 0
        ackW = 0
        while (lim < 5) and (ackW < 2):
            ackW = i2c.writeto(i2cADR, bufW)
            lim += 1
            time.sleep_us(10) #$$$
        if lim >= 5:
            return -2
    except OSError:
        wecount += 1
        return -1
    return ackW  

def letPortsHz():
    writeByte(IOEX0, IODIRA, 0xFF)
    writeByte(IOEX0, IODIRB, 0xFF)
    writeByte(IOEX1, IODIRA, 0xFF)
    writeByte(IOEX1, IODIRB, 0xFF)

def letADRbusOutput():
    writeByte(IOEX1, OLATA, 0xFF) # initial value, A15-A8
    writeByte(IOEX1, OLATB, 0xFF) # initial value, A7-A0
    writeByte(IOEX1, IODIRA, 0x00) # DIR=ouput A15-A8
    writeByte(IOEX1, IODIRB, 0x00) # DIR=ouput AD7-AD0

def letADRbusInput():
    writeByte(IOEX1, IODIRA, 0xFF) # DIR=input A15-A8
    writeByte(IOEX1, IODIRB, 0xFF) # DIR=input AD7-AD0

def outputADRbus(adr):
    adrH = (adr >> 8) & 0xFF
    adrL = adr & 0xFF
    writeByte(IOEX1, OLATA, adrH) # output A15-A8
    writeByte(IOEX1, OLATB, adrL) # output AD7-AD0

def letDATAbusInput():
    writeByte(IOEX1, IODIRB, 0xFF) # AD7-AD0 input

def letDATAbusOutput():
    writeByte(IOEX1, OLATB, 0xFF) # initial value, AD7-AD0
    writeByte(IOEX1, IODIRB, 0x00) # DIR=ouput AD7-AD0

def outputDATAbus(dat):
    dat &= 0xFF
    writeByte(IOEX1, OLATB, dat) # output AD7-AD0

def inputDATAbus():
    return readByte(IOEX1, GPIOB) # input AD7-AD0

# B0: ALE, B1: IO/M#, B2:RD#, B3:WR#
# B4: RESET#, B5:HOLD, B6:HLDA, B7:---
def enableCONTSIG():
    writeByte(IOEX0, OLATB, 0x3E) # NO RESET, HOLD
    writeByte(IOEX0, IODIRB, 0xC0) # HLDA, B7: input

def disableCONTSIG(opt):
    if opt:
        writeByte(IOEX0, OLATB, 0x3E) # NO RESET, HOLD
    else:
        writeByte(IOEX0, OLATB, 0x1E) # NO RESET, NO HOLD        
    writeByte(IOEX0, IODIRB, 0xCF) # RESET# HOLD : output

def assertALE():
    # NO RESET, HOLD, ALE
    while writeByte(IOEX0, OLATB, 0x3F) < 0:
        print("ALE")

def assertMEMRD():
    # NO RESET, HOLD, IO/M#, RD#
    while writeByte(IOEX0, OLATB, 0x38) < 0:
        print("MEMRD")

def assertMEMWR():
    # NO RESET, HOLD, IO/M#, WR#
    while writeByte(IOEX0, OLATB, 0x34) < 0:
        print("MEMWR")

def assertRST():
    writeByte(IOEX0, OLATB, 0x0E)

def negateCNT(dbg):
    # NO RESET, HOLD
    while writeByte(IOEX0, OLATB, 0x3E) < 0:
        print("NEGCNT ", dbg)
        return -1
    return 0

def assertM():
    writeByte(IOEX0, OLATB, 0x3C) # NO RESET, HOLD, IO/M#=MEM

def isHLDA():
    temp = readByte(IOEX0, GPIOB)
    return (temp >> 6) & 1

def initDevices():
    writeByte(IOEX0, IOCONA, 0x20)
    writeByte(IOEX0, IODIRA, 0xFF)
    writeByte(IOEX0, IODIRB, 0xCF)
    writeByte(IOEX0, OLATA,  0xFF)
    writeByte(IOEX0, OLATB,  0x1E)
    writeByte(IOEX1, IOCONA, 0x20)
    writeByte(IOEX1, IODIRA, 0xFF)
    writeByte(IOEX1, IODIRB, 0xFF)
    writeByte(IOEX1, OLATA,  0xFF)
    writeByte(IOEX1, OLATB,  0xFF)

def wrMEM(adr, dat, opt):
    enableCONTSIG()
    while isHLDA() == 0:
        pass
    letADRbusOutput()
    outputADRbus(adr)
    assertALE()
    negateCNT("W1")
    outputDATAbus(dat)
    assertMEMWR()
    negateCNT("W2")   
    letADRbusInput()
    disableCONTSIG(opt)

def rdMEM(adr, opt):
    enableCONTSIG()
    while isHLDA() == 0:
        pass
    letADRbusOutput()
    outputADRbus(adr)
    assertALE()
    negateCNT("R1")
    letDATAbusInput()
    assertMEMRD()
    #time.sleep_us(100)
    dat = inputDATAbus()
    if negateCNT("R2") < 0:
        return -1
    disableCONTSIG(opt)
    return dat

def WrRdTest(startADDR, endADDR):
    global wecount, recount
    addr = startADDR
    dat = 0
    while addr < endADDR:
        wrMEM(addr, dat, True)
        rddat = rdMEM(addr, True)
        if rddat < 0:
            print("EXIT")
            sys.exit(999)
        if rddat == dat:
            if (addr % 0x100) == 0:
                print("VERIFIED ADDRESS: 0x{0:04x}".format(addr))
        else:
            wecount += 1
            #print("ERROR ADDRESS: 0x{0:04x} WR=0x{1:02x} RD=0x{2:02x} {3} {4}".format(addr, dat, rddat, type(dat), type(rddat)))
            continue            
        addr += 1
        dat += 1
        if dat > 0xFF:
            dat = 0
    rddat = rdMEM(addr, False)
    print("recount:{0} wecount:{1}".format(recount, wecount))       

def main():
    global i2c
    print("SRAM RD/WR test")
    print("IO Expander is ", end="")
    if not isIOEXavailable():
        print("not available.")
    else:
        print("available.")
        initDevices()
        WrRdTest(0x0, 0x1000)
 
if __name__ == "__main__":
    main()

まあお引越しできたので、次回こそ真のホスト8085との接続だな。MicroPythonじゃない、別シリーズでな。

MicroPython的午睡(142)M5Stack、SoftI2Cで無理やりSRAM初期化 へ戻る