diff options
author | Gerhard Sittig <gerhard.sittig@gmx.net> | 2018-05-12 22:21:39 +0200 |
---|---|---|
committer | Gerhard Sittig <gerhard.sittig@gmx.net> | 2018-05-12 23:35:15 +0200 |
commit | 52e8d8b7548f7fdc2fe56bc133fe60b8147fb3b8 (patch) | |
tree | 4268445b4db637631f60021577ff0a9beb95e584 /decoders/mcs48 | |
parent | 426325ea2b66658b8062525db78a9b50d79ce507 (diff) | |
download | libsigrokdecode-52e8d8b7548f7fdc2fe56bc133fe60b8147fb3b8.tar.gz libsigrokdecode-52e8d8b7548f7fdc2fe56bc133fe60b8147fb3b8.zip |
mcs48: add reset method, make A12 optional, unassorted adjustment
Add the reset() method which recently has become essential. Make the A12
"memory bank" address line optional. Use more Python idioms. Update
comments.
The control signals had to move, to avoid gaps between D7 and A8 as well
as between A11 and A12 in the GUI decoder properties dialog. With
dynamic assignment in the UI and with named references in the CLI this
shall not harm. Unmodified automated tests still pass.
The logic is prepared to handle data, address, and "bank" pin groups at
arbitrary locations, A[11:8] and D[7:0] need not be adjacent any longer.
Support for more than one memory bank pin is prepared, but the number of
bank pins needs to get determined at the start of decode(), when this
feature is to get added in the future.
Diffstat (limited to 'decoders/mcs48')
-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) |