added i80 decoder draft
This commit is contained in:
22
i80/__init__.py
Normal file
22
i80/__init__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
##
|
||||
## Copyright (C) 2024 Timo Schneider
|
||||
##
|
||||
## 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 <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
'''
|
||||
This protocol decoder can decode an i80 bus.
|
||||
'''
|
||||
|
||||
from .pd import Decoder
|
||||
211
i80/pd.py
Normal file
211
i80/pd.py
Normal file
@@ -0,0 +1,211 @@
|
||||
##
|
||||
## This file is part of the libsigrokdecode project.
|
||||
##
|
||||
## Copyright (C) 2013-2016 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## 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 <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
import sigrokdecode as srd
|
||||
from common.srdhelper import bitpack
|
||||
|
||||
|
||||
class ChannelError(Exception):
|
||||
pass
|
||||
|
||||
NUM_CHANNELS = 32
|
||||
|
||||
class Decoder(srd.Decoder):
|
||||
api_version = 3
|
||||
id = 'i80'
|
||||
name = 'Intel 8080'
|
||||
longname = 'Intel 8080 like bus'
|
||||
desc = 'Parallel asynchronous 8/16 bit bus.'
|
||||
license = 'gplv2+'
|
||||
inputs = ['logic']
|
||||
outputs = ['i80']
|
||||
tags = ['Util']
|
||||
channels = (
|
||||
{'id': 'cs', 'name': 'CS', 'desc': 'Chip select line', 'idn':'dec_i80_chan_cs'},
|
||||
{'id': 'cmd', 'name': 'CMD', 'desc': 'Command line', 'idn':'dec_i80_chan_cmd'},
|
||||
{'id': 'rst', 'name': 'RST', 'desc': 'Reset line', 'idn':'dec_i80_chan_rst'},
|
||||
{'id': 'hrdy', 'name': 'HRDY', 'desc': 'Ready line', 'idn':'dec_i80_chan_hrdy'},
|
||||
{'id': 'd0', 'name': 'D0', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d0'},
|
||||
{'id': 'd1', 'name': 'D1', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d1'},
|
||||
{'id': 'd2', 'name': 'D2', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d2'},
|
||||
{'id': 'd3', 'name': 'D3', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d3'},
|
||||
{'id': 'd4', 'name': 'D4', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d4'},
|
||||
{'id': 'd5', 'name': 'D5', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d5'},
|
||||
{'id': 'd6', 'name': 'D6', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d6'},
|
||||
{'id': 'd7', 'name': 'D7', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d7'},
|
||||
)
|
||||
optional_channels = (
|
||||
{'id': 'd8', 'name': 'D8', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d8'},
|
||||
{'id': 'd9', 'name': 'D9', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d9'},
|
||||
{'id': 'd10', 'name': 'D10', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d10'},
|
||||
{'id': 'd11', 'name': 'D11', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d11'},
|
||||
{'id': 'd12', 'name': 'D12', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d12'},
|
||||
{'id': 'd13', 'name': 'D13', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d13'},
|
||||
{'id': 'd14', 'name': 'D14', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d14'},
|
||||
{'id': 'd15', 'name': 'D15', 'desc': 'Serial data line', 'idn':'dec_i80_chan_d15'},
|
||||
{'id': 'hwe', 'name': 'HWE', 'desc': 'Write enable line', 'idn':'dec_i80_chan_hwe'},
|
||||
{'id': 'hre', 'name': 'HRE', 'desc': 'Read enable line', 'idn':'dec_i80_chan_hre'},
|
||||
)
|
||||
options = (
|
||||
{'id': 'cs_polarity', 'desc': 'Chip select active state',
|
||||
'default': 'low', 'values': ('low', 'high'), 'idn':'dec_i80_opt_cs_polarity'},
|
||||
{'id': 'cmd_polarity', 'desc': 'Command active state',
|
||||
'default': 'low', 'values': ('low', 'high'), 'idn':'dec_i80_opt_cmd_polarity'},
|
||||
{'id': 'hwe_polarity', 'desc': 'Write enable active state',
|
||||
'default': 'low', 'values': ('low', 'high'), 'idn':'dec_i80_opt_hwe_polarity'},
|
||||
{'id': 'hre_polarity', 'desc': 'Read enable active state',
|
||||
'default': 'low', 'values': ('low', 'high'), 'idn':'dec_i80_opt_hre_polarity'},
|
||||
{'id': 'rst_polarity', 'desc': 'Reset polarity',
|
||||
'default': 'low', 'values': ('low', 'high'), 'idn':'dec_i80_opt_rst_polarity'},
|
||||
{'id': 'hrdy_polarity', 'desc': 'HRDY polarity',
|
||||
'default': 'high', 'values': ('low', 'high'), 'idn':'dec_i80_opt_cs_polarity'},
|
||||
{'id': 'endianness', 'desc': 'Data endianness',
|
||||
'default': 'little', 'values': ('little', 'big'), 'idn':'dec_i80_opt_endianess'},
|
||||
)
|
||||
annotations = (
|
||||
('command', 'Command'),
|
||||
('write_data', 'Write'),
|
||||
('read_data', 'Read'),
|
||||
('reset', 'Reset'),
|
||||
('warnings', 'Warnings'),
|
||||
)
|
||||
annotation_rows = (
|
||||
('data', 'Data', (0,1,2)),
|
||||
('events', 'Events', (3,)),
|
||||
('warnings', 'Warnings', (4,)),
|
||||
)
|
||||
|
||||
def __init__(self):
|
||||
self.reset()
|
||||
|
||||
def reset(self):
|
||||
self.items = []
|
||||
self.saved_item = None
|
||||
self.saved_word = None
|
||||
self.ss_word = self.es_word = None
|
||||
self.first = True
|
||||
self.have_clock = True
|
||||
self.prv_dex = 0
|
||||
self.num_item_bits = None
|
||||
|
||||
def start(self):
|
||||
self.out_python = self.register(srd.OUTPUT_PYTHON)
|
||||
self.out_ann = self.register(srd.OUTPUT_ANN)
|
||||
|
||||
def putd(self, s, e, data):
|
||||
self.put(s, e, self.out_ann, data)
|
||||
|
||||
|
||||
def end(self):
|
||||
#the last annotation
|
||||
#self.put_py(self._data_begin, self.samplenum, ['ITEM', self._data])
|
||||
#self.put_ann(self._data_begin, self.samplenum, [0, [self.format.format(self._data)]])
|
||||
...
|
||||
|
||||
def decode(self):
|
||||
# Determine which (optional) channels have input data. Insist in
|
||||
# a non-empty input data set. Cope with sparse connection maps.
|
||||
# Store enough state to later "compress" sampled input data.
|
||||
bus_width_8_bit = all(not self.has_channel(chan) for chan in range(12, 20))
|
||||
bus_width_16_bit = all(self.has_channel(chan) for chan in range(12, 20))
|
||||
|
||||
if not bus_width_8_bit and not bus_width_16_bit:
|
||||
raise ChannelError('Can\'t determine bus width. Define only 8 or 16 bits!')
|
||||
|
||||
self.format = "@{{:0{}X}}".format(2 if bus_width_8_bit else 4)
|
||||
|
||||
have_hwe = self.has_channel(20)
|
||||
hwe_active_low = self.options['hwe_polarity'] == 'low'
|
||||
|
||||
have_hre = self.has_channel(21)
|
||||
hre_active_low = self.options['hre_polarity'] == 'low'
|
||||
|
||||
cs_active_low = self.options['cs_polarity'] == 'low'
|
||||
cmd_active_low = self.options['cmd_polarity'] == 'low'
|
||||
rst_active_low = self.options['rst_polarity'] == 'low'
|
||||
|
||||
trigger_conds = [
|
||||
{0: 'e'}, # CS
|
||||
{2: 'e'}, # RST
|
||||
{20: 'r' if hwe_active_low else 'f'}, # HWE
|
||||
{21: 'r' if hre_active_low else 'f'}, # HRE
|
||||
]
|
||||
|
||||
# Keep processing the input stream. Assume "always zero" for
|
||||
# not-connected input lines.
|
||||
|
||||
is_first = True
|
||||
self._last_samplenum = 0
|
||||
|
||||
while True:
|
||||
|
||||
(cs, cmd, rst, hrdy, d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10 ,d11 ,d12 ,d13 ,d14 ,d15, hwe, hre) = self.wait(trigger_conds)
|
||||
|
||||
operation = (cs, cmd, hwe, hre, rst, hrdy)
|
||||
if bus_width_8_bit:
|
||||
data = bitpack([d0, d1, d2, d3, d4, d5, d6, d7])
|
||||
elif bus_width_16_bit:
|
||||
data = bitpack([d0, d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, d13, d14, d15])
|
||||
|
||||
if is_first:
|
||||
is_first = False
|
||||
self._last_operation = operation
|
||||
self._data_begin = 0
|
||||
self._rst_begin = 0
|
||||
self._data = data
|
||||
self._data_is_cmd = operation[1]
|
||||
self._data_dir = 1
|
||||
self._last_samplenum = self.samplenum
|
||||
continue
|
||||
|
||||
# check edge on hwe
|
||||
if have_hwe and ((not self._last_operation[2] and operation[2] and hwe_active_low) or (self._last_operation[2] and not operation[2] and not hwe_active_low)):
|
||||
self._data = data
|
||||
self._data_is_cmd = operation[1] if cmd_active_low else not operation[1]
|
||||
self._data_dir = 1
|
||||
|
||||
# check edge on hre
|
||||
elif have_hre and ((not self._last_operation[3] and operation[3] and hre_active_low) or (self._last_operation[3] and not operation[3] and not hre_active_low)):
|
||||
self._data = data
|
||||
self._data_is_cmd = operation[1] if cmd_active_low else not operation[1]
|
||||
self._data_dir = 0
|
||||
|
||||
# check cs switch
|
||||
if operation[0] != self._last_operation[0]:
|
||||
# cs on
|
||||
if cs_active_low != operation[0]:
|
||||
self._data_begin = self.samplenum
|
||||
|
||||
#cs off
|
||||
elif self._data_is_cmd:
|
||||
#self.putd(self._data_begin, self.samplenum, [0, [self.format.format(self._data)]])
|
||||
self.putd(self._data_begin, self.samplenum, [1, [self.format.format(data)]])
|
||||
else:
|
||||
#self.putd(self._data_begin, self.samplenum, [1 if self._data_dir else 2, [self.format.format(self._data)]])
|
||||
self.putd(self._data_begin, self.samplenum, [0, [self.format.format(data)]])
|
||||
|
||||
# check rst switch
|
||||
if operation[4] != self._last_operation[4]:
|
||||
if rst_active_low != operation[4]:
|
||||
self._rst_begin = self.samplenum
|
||||
else:
|
||||
self.putd(self._rst_begin, self.samplenum, [3, ['Reset']])
|
||||
|
||||
self._last_operation = operation
|
||||
self._last_samplenum = self.samplenum
|
||||
Reference in New Issue
Block a user