前回は古いハードを掘り起こし、M5StackのI2Cバス(3.3V)の先に5Vの外部電源動作のIOExpander MCP23017を2個接続OKなことまで確認しました。今回はMCP23017を制御して古代の8ビット8085風味のバスサイクルを作り出してみます。MicroPython制御のDMAコントローラ一丁あがり?
※「MicroPython的午睡」投稿順 Indexはこちら
※M5Stack Grayに書き込んだUIFlow2.0 (Alpha-27)対応のMicroPython処理系とWindowsパソコン上で動作しているThonny 4.0.1で動作確認しています。
今回動作確認の実機回路図
前回、回路図を掲げましたが、今回は「DMAC単体」での動作確認ということもありプルアップ抵抗など追加したので回路図を再掲載いたします。こんな感じ。
8085風のバスサイクルを作りだすMicroPythonコード
とりあえず8085の「メモリリード」と「メモリライト」サイクルのみかけられるようにMicroPythonをプログラムしてみましたぞ。遥か以前にZ80に接続しているROMをダンプするのに使ったコードをかなり流用してます。
# softDMA8085.py from machine import I2C, Pin import M5 import time IOEX0 = 0x20 IOEX1 = 0x21 IOCONA = 0x0A IOCONB = 0x0B IODIRA = 0x00 IODIRB = 0x01 GPIOA = 0x12 GPIOB = 0x13 OLATA = 0x14 OLATB = 0x15 i2c = I2C(0, scl=Pin(22), sda=Pin(21), 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 bufW = bytes([regADR]) ackW = i2c.writeto(i2cADR, bufW) bufR = bytearray(1) ackR = i2c.readfrom_into(i2cADR, bufR) return int.from_bytes(bufR, 'little') def writeByte(i2cADR, regADR, dat): global i2c bufW = bytes([regADR, dat]) ackW = i2c.writeto(i2cADR, bufW) 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(): writeByte(IOEX0, OLATB, 0x1E) # NO RESET, NO HOLD writeByte(IOEX0, IODIRB, 0xCF) # RESET# HOLD : output def assertALE(): writeByte(IOEX0, OLATB, 0x3F) # NO RESET, HOLD, ALE def assertMEMRD(): writeByte(IOEX0, OLATB, 0x38) # NO RESET, HOLD, IO/M#, RD# def assertMEMWR(): writeByte(IOEX0, OLATB, 0x34) # NO RESET, HOLD, IO/M#, WR# def assertRST(): writeByte(IOEX0, OLATB, 0x0E) def negateCNT(): writeByte(IOEX0, OLATB, 0x3E) # NO RESET, HOLD 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): enableCONTSIG() while isHLDA() == 0: pass letADRbusOutput() outputADRbus(adr) assertALE() negateCNT() outputDATAbus(dat) assertMEMWR() negateCNT() letADRbusInput() disableCONTSIG() def rdMEM(adr): enableCONTSIG() while isHLDA() == 0: pass letADRbusOutput() outputADRbus(adr) assertALE() negateCNT() assertMEMRD() letDATAbusInput() dat = inputDATAbus() negateCNT() disableCONTSIG() return dat def main(): global i2c M5.begin() print("8085 SoftDMA") print("IO Expander is ", end="") if not isIOEXavailable(): print("not available.") else: print("available.") initDevices() addrW = 0x12 datW = 0xA5 addrR = 0x13 while True: wrMEM(addrW, datW) rdMEM(addrR) time.sleep(1) if __name__ == "__main__": main()
テストプログラムで生成したバスサイクルを観察
上記はダラダラとライトとリードを繰り返すので、その様子をAnalog Discovery2のロジアナ機能で観察してみました。メンドイのでアドレス・データバスの下4ビットしか見てません。
左の赤い方がライト・サイクルで、右の青い方がリード・サイクルです。
次は8085のバスに接続可能なSRAMモジュールをこしらえて、上記のバスサイクルで読み書きだな。さっさとやれよ。