]> sigrok.org Git - libsigrokdecode.git/blame - decoders/mcs48/pd.py
Add new decoder: Intel MCS-48
[libsigrokdecode.git] / decoders / mcs48 / pd.py
CommitLineData
426325ea 1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2018 fenugrec <fenugrec@users.sourceforge.net>
5##
6## This program is free software; you can redistribute it and/or modify
7## it under the terms of the GNU General Public License as published by
8## the Free Software Foundation; either version 2 of the License, or
9## (at your option) any later version.
10##
11## This program is distributed in the hope that it will be useful,
12## but WITHOUT ANY WARRANTY; without even the implied warranty of
13## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14## GNU General Public License for more details.
15##
16## You should have received a copy of the GNU General Public License
17## along with this program; if not, see <http://www.gnu.org/licenses/>.
18##
19
20# TODO: Make A12 optional; it's here because of an instrument (HP3478A) that
21# drives a generic I/O pin to access 8kB of ROM; the MCS-48 only has a 4kB
22# address space.
23
24import sigrokdecode as srd
25
26class ChannelError(Exception):
27 pass
28
29class Decoder(srd.Decoder):
30 api_version = 3
31 id = 'mcs48'
32 name = 'MCS-48'
33 longname = 'Intel MCS-48'
34 desc = 'Intel MCS-48 external memory access protocol.'
35 license = 'gplv2+'
36 inputs = ['logic']
37 outputs = ['mcs48']
38 channels = \
39 tuple({
40 'id': 'd%d' % i,
41 'name': 'D%d' % i,
42 'desc': 'CPU data line %d' % i
43 } for i in range(8)
44 ) + tuple({
45 'id': 'a%d' % i,
46 'name': 'A%d' % i,
47 'desc': 'CPU address line %d' % i
48 } for i in range(8, 13)
49 ) + (
50 {'id': 'ale', 'name': 'ALE', 'desc': 'Address latch enable'},
51 {'id': 'psen', 'name': '/PSEN', 'desc': 'Program store enable'},
52 )
53 annotations = (
54 ('romdata', 'Address:Data'),
55 )
56 binary = (
57 ('romdata', 'AAAA:DD'),
58 )
59
60 def __init__(self):
61 self.addr = 0
62 self.addr_s = 0
63 self.data = 0
64 self.data_s = 0
65
66 # Flag to make sure we get an ALE pulse first.
67 self.started = 0
68
69 def start(self):
70 self.out_ann = self.register(srd.OUTPUT_ANN)
71 self.out_bin = self.register(srd.OUTPUT_BINARY)
72
73 def newaddr(self, pins):
74 # Falling edge on ALE: reconstruct address.
75 self.started = 1
76 tempaddr = 0
77 for i in range(13):
78 tempaddr |= pins[i] << i
79 self.addr = tempaddr
80 self.addr_s = self.samplenum
81
82 def newdata(self, pins):
83 # Edge on PSEN: get data.
84 tempdata = 0
85 for i in range(8):
86 tempdata |= pins[i] << i
87 self.data = tempdata
88 self.data_s = self.samplenum
89 if self.started:
90 self.put(self.addr_s, self.samplenum, self.out_ann,
91 [0, ['%04X:' % self.addr + '%02X' % self.data]])
92 self.put(self.addr_s, self.samplenum, self.out_bin,
93 [0, bytes([(self.addr >> 8) & 0xFF, self.addr & 0xFF, self.data])])
94
95 def decode(self):
96 # Sample address on the falling ALE edge.
97 # Save data on falling edge of PSEN.
98 while True:
99 pins = self.wait([{13: 'f'}, {14: 'r'}])
100 # Handle those conditions (one or more) that matched this time.
101 if self.matched[0]:
102 self.newaddr(pins[0:])
103 if self.matched[1]:
104 self.newdata(pins[0:])