From 426325ea2b66658b8062525db78a9b50d79ce507 Mon Sep 17 00:00:00 2001 From: fenugrec Date: Thu, 26 Apr 2018 18:35:39 -0400 Subject: [PATCH] Add new decoder: Intel MCS-48 Decodes addresses and data read from an external ROM. The MCS-48 processors (8048, 8049, 8039, etc.) have an 8-bit data bus that latches first the address then the data. --- decoders/mcs48/__init__.py | 31 +++++++++++ decoders/mcs48/pd.py | 104 +++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 decoders/mcs48/__init__.py create mode 100644 decoders/mcs48/pd.py diff --git a/decoders/mcs48/__init__.py b/decoders/mcs48/__init__.py new file mode 100644 index 0000000..424c6b4 --- /dev/null +++ b/decoders/mcs48/__init__.py @@ -0,0 +1,31 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2018 fenugrec +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see . +## + +''' +This protocol decoder de-multiplexes Intel MCS-48 (8039, 8048, etc.) external +program memory accesses. This requires 14 channels: 8 for D0-D7 (data and +lower 8 bits of address), 4 for A8-A11 (output on port P2), ALE and PSEN. +An optional A12 is supported, which may be an arbitrary I/O pin driven by +software (use case is dumping ROM of an HP 3478A). + +The two groups D0-D7 and A8-A12 must be on consecutive channels, for +example CH8..CH15 and CH0..CH4. +''' + +from .pd import Decoder diff --git a/decoders/mcs48/pd.py b/decoders/mcs48/pd.py new file mode 100644 index 0000000..2c331d1 --- /dev/null +++ b/decoders/mcs48/pd.py @@ -0,0 +1,104 @@ +## +## This file is part of the libsigrokdecode project. +## +## Copyright (C) 2018 fenugrec +## +## This program is free software; you can redistribute it and/or modify +## it under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 2 of the License, or +## (at your option) any later version. +## +## This program is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program; if not, see . +## + +# TODO: Make A12 optional; it's here because of an instrument (HP3478A) that +# drives a generic I/O pin to access 8kB of ROM; the MCS-48 only has a 4kB +# address space. + +import sigrokdecode as srd + +class ChannelError(Exception): + pass + +class Decoder(srd.Decoder): + api_version = 3 + id = 'mcs48' + name = 'MCS-48' + longname = 'Intel MCS-48' + desc = 'Intel MCS-48 external memory access protocol.' + license = 'gplv2+' + inputs = ['logic'] + outputs = ['mcs48'] + channels = \ + tuple({ + 'id': 'd%d' % i, + 'name': 'D%d' % i, + 'desc': 'CPU data line %d' % i + } for i in range(8) + ) + tuple({ + 'id': 'a%d' % i, + 'name': 'A%d' % i, + 'desc': 'CPU address line %d' % i + } for i in range(8, 13) + ) + ( + {'id': 'ale', 'name': 'ALE', 'desc': 'Address latch enable'}, + {'id': 'psen', 'name': '/PSEN', 'desc': 'Program store enable'}, + ) + annotations = ( + ('romdata', 'Address:Data'), + ) + binary = ( + ('romdata', 'AAAA:DD'), + ) + + def __init__(self): + self.addr = 0 + self.addr_s = 0 + self.data = 0 + self.data_s = 0 + + # Flag to make sure we get an ALE pulse first. + self.started = 0 + + def start(self): + self.out_ann = self.register(srd.OUTPUT_ANN) + self.out_bin = self.register(srd.OUTPUT_BINARY) + + def newaddr(self, pins): + # Falling edge on ALE: reconstruct address. + self.started = 1 + tempaddr = 0 + for i in range(13): + tempaddr |= pins[i] << i + self.addr = tempaddr + self.addr_s = self.samplenum + + def newdata(self, pins): + # Edge on PSEN: get data. + tempdata = 0 + for i in range(8): + tempdata |= pins[i] << i + self.data = tempdata + self.data_s = self.samplenum + if self.started: + self.put(self.addr_s, self.samplenum, self.out_ann, + [0, ['%04X:' % self.addr + '%02X' % self.data]]) + self.put(self.addr_s, self.samplenum, self.out_bin, + [0, bytes([(self.addr >> 8) & 0xFF, self.addr & 0xFF, self.data])]) + + def decode(self): + # Sample address on the falling ALE edge. + # Save data on falling edge of PSEN. + while True: + pins = self.wait([{13: 'f'}, {14: 'r'}]) + # Handle those conditions (one or more) that matched this time. + if self.matched[0]: + self.newaddr(pins[0:]) + if self.matched[1]: + self.newdata(pins[0:]) -- 2.30.2