diff options
Diffstat (limited to 'decoders')
-rw-r--r-- | decoders/mcs48/__init__.py | 3 | ||||
-rw-r--r-- | decoders/mcs48/pd.py | 73 |
2 files changed, 45 insertions, 31 deletions
diff --git a/decoders/mcs48/__init__.py b/decoders/mcs48/__init__.py index 424c6b4..54c01cc 100644 --- a/decoders/mcs48/__init__.py +++ b/decoders/mcs48/__init__.py @@ -23,9 +23,6 @@ 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 index 2c331d1..185fd89 100644 --- a/decoders/mcs48/pd.py +++ b/decoders/mcs48/pd.py @@ -17,10 +17,6 @@ ## along with this program; if not, see <http://www.gnu.org/licenses/>. ## -# 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): @@ -35,20 +31,25 @@ class Decoder(srd.Decoder): license = 'gplv2+' inputs = ['logic'] outputs = ['mcs48'] - channels = \ - tuple({ + channels = ( + {'id': 'ale', 'name': 'ALE', 'desc': 'Address latch enable'}, + {'id': 'psen', 'name': '/PSEN', 'desc': 'Program store enable'}, + ) + tuple({ 'id': 'd%d' % i, 'name': 'D%d' % i, 'desc': 'CPU data line %d' % i - } for i in range(8) + } for i in range(0, 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'}, + } for i in range(8, 12) + ) + optional_channels = tuple({ + 'id': 'a%d' % i, + 'name': 'A%d' % i, + 'desc': 'CPU address line %d' % i + } for i in range(12, 13) ) annotations = ( ('romdata', 'Address:Data'), @@ -56,8 +57,15 @@ class Decoder(srd.Decoder): binary = ( ('romdata', 'AAAA:DD'), ) + OFF_ALE, OFF_PSEN = 0, 1 + OFF_DATA_BOT, OFF_DATA_TOP = 2, 10 + OFF_ADDR_BOT, OFF_ADDR_TOP = 10, 14 + OFF_BANK_BOT, OFF_BANK_TOP = 14, 15 def __init__(self): + self.reset() + + def reset(self): self.addr = 0 self.addr_s = 0 self.data = 0 @@ -70,35 +78,44 @@ class Decoder(srd.Decoder): self.out_ann = self.register(srd.OUTPUT_ANN) self.out_bin = self.register(srd.OUTPUT_BINARY) - def newaddr(self, pins): + def newaddr(self, addr, data): # Falling edge on ALE: reconstruct address. self.started = 1 - tempaddr = 0 - for i in range(13): - tempaddr |= pins[i] << i - self.addr = tempaddr + addr = sum([bit << i for i, bit in enumerate(addr)]) + addr <<= len(data) + addr |= sum([bit << i for i, bit in enumerate(data)]) + self.addr = addr self.addr_s = self.samplenum - def newdata(self, pins): + def newdata(self, data): # Edge on PSEN: get data. - tempdata = 0 - for i in range(8): - tempdata |= pins[i] << i - self.data = tempdata + data = sum([bit << i for i, bit in enumerate(data)]) + self.data = data 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])]) + anntext = '{:04X}:{:02X}'.format(self.addr, self.data) + self.put(self.addr_s, self.data_s, self.out_ann, [0, [anntext]]) + bindata = self.addr.to_bytes(2, byteorder='big') + bindata += self.data.to_bytes(1, byteorder='big') + self.put(self.addr_s, self.data_s, self.out_bin, [0, bindata]) def decode(self): + # Address bits above A11 are optional, and are considered to be A12+. + # This logic needs more adjustment when more bank address pins are + # to get supported. For now, having just A12 is considered sufficient. + has_bank = self.has_channel(self.OFF_BANK_BOT) + bank_pin_count = 1 if has_bank else 0 # Sample address on the falling ALE edge. # Save data on falling edge of PSEN. while True: - pins = self.wait([{13: 'f'}, {14: 'r'}]) + pins = self.wait([{self.OFF_ALE: 'f'}, {self.OFF_PSEN: 'r'}]) + data = pins[self.OFF_DATA_BOT:self.OFF_DATA_TOP] + addr = pins[self.OFF_ADDR_BOT:self.OFF_ADDR_TOP] + bank = pins[self.OFF_BANK_BOT:self.OFF_BANK_TOP] + if has_bank: + addr += bank[:bank_pin_count] # Handle those conditions (one or more) that matched this time. if self.matched[0]: - self.newaddr(pins[0:]) + self.newaddr(addr, data) if self.matched[1]: - self.newdata(pins[0:]) + self.newdata(data) |