
前回は古いハードを掘り起こし、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モジュールをこしらえて、上記のバスサイクルで読み書きだな。さっさとやれよ。