summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
inline | side by side (from parent 1:
426325e)
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.
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).
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
'''
from .pd import Decoder
## along with this program; if not, see <http://www.gnu.org/licenses/>.
##
## 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):
import sigrokdecode as srd
class ChannelError(Exception):
license = 'gplv2+'
inputs = ['logic']
outputs = ['mcs48']
license = 'gplv2+'
inputs = ['logic']
outputs = ['mcs48']
+ 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
'id': 'd%d' % i,
'name': 'D%d' % i,
'desc': 'CPU data line %d' % i
) + tuple({
'id': 'a%d' % i,
'name': 'A%d' % i,
'desc': 'CPU address line %d' % i
) + 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'),
)
annotations = (
('romdata', 'Address:Data'),
binary = (
('romdata', 'AAAA:DD'),
)
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
+ self.reset()
+
+ def reset(self):
self.addr = 0
self.addr_s = 0
self.data = 0
self.addr = 0
self.addr_s = 0
self.data = 0
self.out_ann = self.register(srd.OUTPUT_ANN)
self.out_bin = self.register(srd.OUTPUT_BINARY)
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
# 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
self.addr_s = self.samplenum
- def newdata(self, pins):
+ def newdata(self, data):
# Edge on PSEN: get 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.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])
+ # 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:
# 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]:
# Handle those conditions (one or more) that matched this time.
if self.matched[0]:
+ self.newaddr(addr, data)