Add new decoders

This commit is contained in:
DreamSourceLab 2017-06-06 20:36:18 +08:00
parent 337d3de3c4
commit 2e17f42187
17 changed files with 1459 additions and 0 deletions

View File

@ -0,0 +1,32 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2017 Karl Palsson <karlp@etactica.com>
##
## 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, write to the Free Software
## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
##
'''
This decoder stacks on top of the 'spi' PD and decodes Analog Devices
ADE77xx command/responses.
The ADE77xx is a "Poly Phase Multifunction Energy Metering IC with Per Phase
Information".
This PD has been tested with an ADE7758 so far, support for other devices
from the ADE77xx series can be added in the future.
'''
from .pd import Decoder

View File

@ -0,0 +1,102 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2017 Karl Palsson <karlp@etactica.com>
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included in all
## copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
from collections import OrderedDict
# Generated from datasheet rev E, using tabula.
regs = OrderedDict([
(0x1, ('AWATTHR', 'Watt-Hour Accumulation Register for Phase A. Active power is accumulated over time in this read-only register. The AWATTHR register can hold a maximum of 0.52 seconds of active energy information with full-scale analog inputs before it overflows (see the Active Energy Calculation section). Bit 0 and Bit 1 of the COMPMODE register determine how the active energy is processed from the six analog inputs.', 'R', 16, 'S', 0x0)),
(0x2, ('BWATTHR', 'Watt-Hour Accumulation Register for Phase B.', 'R', 16, 'S', 0x0)),
(0x3, ('CWATTHR', 'Watt-Hour Accumulation Register for Phase C.', 'R', 16, 'S', 0x0)),
(0x4, ('AVARHR', 'VAR-Hour Accumulation Register for Phase A. Reactive power is accumulated over time in this read-only register. The AVARHR register can hold a maximum of 0.52 seconds of reactive energy information with full-scale analog inputs before it overflows (see the Reactive Energy Calculation section). Bit 0 and Bit 1 of the COMPMODE register determine how the reactive energy is processed from the six analog inputs.', 'R', 16, 'S', 0x0)),
(0x5, ('BVARHR', 'VAR-Hour Accumulation Register for Phase B.', 'R', 16, 'S', 0x0)),
(0x6, ('CVARHR', 'VAR-Hour Accumulation Register for Phase C.', 'R', 16, 'S', 0x0)),
(0x7, ('AVAHR', 'VA-Hour Accumulation Register for Phase A. Apparent power is accumulated over time in this read-only register. The AVAHR register can hold a maximum of 1.15 seconds of apparent energy information with full-scale analog inputs before it overflows (see the Apparent Energy Calculation section). Bit 0 and Bit 1 of the COMPMODE register determine how the apparent energy is processed from the six analog inputs.', 'R', 16, 'S', 0x0)),
(0x8, ('BVAHR', 'VA-Hour Accumulation Register for Phase B.', 'R', 16, 'S', 0x0)),
(0x9, ('CVAHR', 'VA-Hour Accumulation Register for Phase C.', 'R', 16, 'S', 0x0)),
(0xa, ('AIRMS', 'Phase A Current Channel RMS Register. The register contains the rms component of the Phase A input of the current channel. The source is selected by data bits in the mode register.', 'R', 24, 'S', 0x0)),
(0xb, ('BIRMS', 'Phase B Current Channel RMS Register.', 'R', 24, 'S', 0x0)),
(0xc, ('CIRMS', 'Phase C Current Channel RMS Register.', 'R', 24, 'S', 0x0)),
(0xd, ('AVRMS', 'Phase A Voltage Channel RMS Register.', 'R', 24, 'S', 0x0)),
(0xe, ('BVRMS', 'Phase B Voltage Channel RMS Register.', 'R', 24, 'S', 0x0)),
(0xf, ('CVRMS', 'Phase C Voltage Channel RMS Register.', 'R', 24, 'S', 0x0)),
(0x10, ('FREQ', 'Frequency of the Line Input Estimated by the Zero-Crossing Processing. It can also display the period of the line input. Bit 7 of the LCYCMODE register determines if the reading is frequency or period. Default is frequency. Data Bit 0 and Bit 1 of the MMODE register determine the voltage channel used for the frequency or period calculation.', 'R', 12, 'U', 0x0)),
(0x11, ('TEMP', 'Temperature Register. This register contains the result of the latest temperature conversion. Refer to the Temperature Measurement section for details on how to interpret the content of this register.', 'R', 8, 'S', 0x0)),
(0x12, ('WFORM', 'Waveform Register. This register contains the digitized waveform of one of the six analog inputs or the digitized power waveform. The source is selected by Data Bit 0 to Bit 4 in the WAVMODE register.', 'R', 24, 'S', 0x0)),
(0x13, ('OPMODE', 'Operational Mode Register. This register defines the general configuration of the ADE7758 (see Table 18).', 'R/W', 8, 'U', 0x4)),
(0x14, ('MMODE', 'Measurement Mode Register. This register defines the channel used for period and peak detection measurements (see Table 19).', 'R/W', 8, 'U', 0xfc)),
(0x15, ('WAVMODE', 'Waveform Mode Register. This register defines the channel and sampling frequency used in the waveform sampling mode (see Table 20).', 'R/W', 8, 'U', 0x0)),
(0x16, ('COMPMODE', 'Computation Mode Register. This register configures the formula applied for the energy and line active energy measurements (see Table 22).', 'R/W', 8, 'U', 0x1c)),
(0x17, ('LCYCMODE', 'Line Cycle Mode Register. This register configures the line cycle accumulation mode for WATT-HR', 'R/W', 8, 'U', 0x78)),
(0x18, ('Mask', 'IRQ Mask Register. It determines if an interrupt event generates an active-low output at the IRQ pin (see the Interrupts section).', 'R/W', 24, 'U', 0x0)),
(0x19, ('Status', 'IRQ Status Register. This register contains information regarding the source of the ADE7758 interrupts (see the Interrupts section).', 'R', 24, 'U', 0x0)),
(0x1a, ('RSTATUS', 'IRQ Reset Status Register. Same as the STATUS register, except that its contents are reset to 0 (all flags cleared) after a read operation.', 'R', 24, 'U', 0x0)),
(0x1b, ('ZXTOUT', 'Zero-Cross Timeout Register. If no zero crossing is detected within the time period specified by this register', 'R/W', 16, 'U', 0xffff)),
(0x1c, ('LINECYC', 'Line Cycle Register. The content of this register sets the number of half-line cycles that the active', 'R/W', 16, 'U', 0xffff)),
(0x1d, ('SAGCYC', 'SAG Line Cycle Register. This register specifies the number of consecutive half-line cycles where voltage channel input may fall below a threshold level. This register is common to the three line voltage SAG detection. The detection threshold is specified by the SAGLVL register (see the Line Voltage SAG Detection section).', 'R/W', 8, 'U', 0xff)),
(0x1e, ('SAGLVL', 'SAG Voltage Level. This register specifies the detection threshold for the SAG event. This register is common to all three phases line voltage SAG detections. See the description of the SAGCYC register for details.', 'R/W', 8, 'U', 0x0)),
(0x1f, ('VPINTLVL', 'Voltage Peak Level Interrupt Threshold Register. This register sets the level of the voltage peak detection. Bit 5 to Bit 7 of the MMODE register determine which phases are to be monitored. If the selected voltage phase exceeds this level', 'R/W', 8, 'U', 0xff)),
(0x20, ('IPINTLVL', 'Current Peak Level Interrupt Threshold Register. This register sets the level of the current peak detection. Bit 5 to Bit 7 of the MMODE register determine which phases are to be monitored. If the selected current phase exceeds this level', 'R/W', 8, 'U', 0xff)),
(0x21, ('VPEAK', 'Voltage Peak Register. This register contains the value of the peak voltage waveform that has occurred within a fixed number of half-line cycles. The number of half-line cycles is set by the LINECYC register.', 'R', 8, 'U', 0x0)),
(0x22, ('IPEAK', 'Current Peak Register. This register holds the value of the peak current waveform that has occurred within a fixed number of half-line cycles. The number of half-line cycles is set by the LINECYC register.', 'R', 8, 'U', 0x0)),
(0x23, ('Gain', 'PGA Gain Register. This register is used to adjust the gain selection for the PGA in the current and voltage channels (see the Analog Inputs section).', 'R/W', 8, 'U', 0x0)),
(0x24, ('AVRMSGAIN', 'Phase A VRMS Gain Register. The range of the voltage rms calculation can be adjusted by writing to this register. It has an adjustment range of ±50% with a resolution of 0.0244%/LSB.', 'R/W', 12, 'S', 0x0)),
(0x25, ('BVRMSGAIN', 'Phase B VRMS Gain Register.', 'R/W', 12, 'S', 0x0)),
(0x26, ('CVRMSGAIN', 'Phase C VRMS Gain Register.', 'R/W', 12, 'S', 0x0)),
(0x27, ('AIGAIN', 'Phase A Current Gain Register. This register is not recommended to be used and it should be kept at 0', 'R/W', 12, 'S', 0x0)),
(0x28, ('BIGAIN', 'Phase B Current Gain Register. This register is not recommended to be used and it should be kept at 0', 'R/W', 12, 'S', 0x0)),
(0x29, ('CIGAIN', 'Phase C Current Gain Register. This register is not recommended to be used and it should be kept at 0', 'R/W', 12, 'S', 0x0)),
(0x2a, ('AWG', 'Phase A Watt Gain Register. The range of the watt calculation can be adjusted by writing to this register. It has an adjustment range of ±50% with a resolution of 0.0244%/LSB.', 'R/W', 12, 'S', 0x0)),
(0x2b, ('BWG', 'Phase B Watt Gain Register.', 'R/W', 12, 'S', 0x0)),
(0x2c, ('CWG', 'Phase C Watt Gain Register.', 'R/W', 12, 'S', 0x0)),
(0x2d, ('AVARG', 'Phase A VAR Gain Register. The range of the VAR calculation can be adjusted by writing to this register. It has an adjustment range of ±50% with a resolution of 0.0244%/LSB.', 'R/W', 12, 'S', 0x0)),
(0x2e, ('BVARG', 'Phase B VAR Gain Register.', 'R/W', 12, 'S', 0x0)),
(0x2f, ('CVARG', 'Phase C VAR Gain Register.', 'R/W', 12, 'S', 0x0)),
(0x30, ('AVAG', 'Phase A VA Gain Register. The range of the VA calculation can be adjusted by writing to this register. It has an adjustment range of ±50% with a resolution of 0.0244%/LSB.', 'R/W', 12, 'S', 0x0)),
(0x31, ('BVAG', 'Phase B VA Gain Register.', 'R/W', 12, 'S', 0x0)),
(0x32, ('CVAG', 'Phase C VA Gain Register.', 'R/W', 12, 'S', 0x0)),
(0x33, ('AVRMSOS', 'Phase A Voltage RMS Offset Correction Register.', 'R/W', 12, 'S', 0x0)),
(0x34, ('BVRMSOS', 'Phase B Voltage RMS Offset Correction Register.', 'R/W', 12, 'S', 0x0)),
(0x35, ('CVRMSOS', 'Phase C Voltage RMS Offset Correction Register.', 'R/W', 12, 'S', 0x0)),
(0x36, ('AIRMSOS', 'Phase A Current RMS Offset Correction Register.', 'R/W', 12, 'S', 0x0)),
(0x37, ('BIRMSOS', 'Phase B Current RMS Offset Correction Register.', 'R/W', 12, 'S', 0x0)),
(0x38, ('CIRMSOS', 'Phase C Current RMS Offset Correction Register.', 'R/W', 12, 'S', 0x0)),
(0x39, ('AWATTOS', 'Phase A Watt Offset Calibration Register.', 'R/W', 12, 'S', 0x0)),
(0x3a, ('BWATTOS', 'Phase B Watt Offset Calibration Register.', 'R/W', 12, 'S', 0x0)),
(0x3b, ('CWATTOS', 'Phase C Watt Offset Calibration Register.', 'R/W', 12, 'S', 0x0)),
(0x3c, ('AVAROS', 'Phase A VAR Offset Calibration Register.', 'R/W', 12, 'S', 0x0)),
(0x3d, ('BVAROS', 'Phase B VAR Offset Calibration Register.', 'R/W', 12, 'S', 0x0)),
(0x3e, ('CVAROS', 'Phase C VAR Offset Calibration Register.', 'R/W', 12, 'S', 0x0)),
(0x3f, ('APHCAL', 'Phase A Phase Calibration Register. The phase relationship between the current and voltage channel can be adjusted by writing to this signed 7-bit register (see the Phase Compensation section).', 'R/W', 7, 'S', 0x0)),
(0x40, ('BPHCAL', 'Phase B Phase Calibration Register.', 'R/W', 7, 'S', 0x0)),
(0x41, ('CPHCAL', 'Phase C Phase Calibration Register.', 'R/W', 7, 'S', 0x0)),
(0x42, ('WDIV', 'Active Energy Register Divider.', 'R/W', 8, 'U', 0x0)),
(0x43, ('VARDIV', 'Reactive Energy Register Divider.', 'R/W', 8, 'U', 0x0)),
(0x44, ('VADIV', 'Apparent Energy Register Divider.', 'R/W', 8, 'U', 0x0)),
(0x45, ('APCFNUM', 'Active Power CF Scaling Numerator Register. The content of this register is used in the numerator of the APCF output scaling calculation. Bits [15:13] indicate reverse polarity active power measurement for Phase A', 'R/W', 16, 'U', 0x0)),
(0x46, ('APCFDEN', 'Active Power CF Scaling Denominator Register. The content of this register is used in the denominator of the APCF output scaling.', 'R/W', 12, 'U', 0x3f)),
(0x47, ('VARCFNUM', 'Reactive Power CF Scaling Numerator Register. The content of this register is used in the numerator of the VARCF output scaling. Bits [15:13] indicate reverse polarity reactive power measurement for Phase A', 'R/W', 16, 'U', 0x0)),
(0x48, ('VARCFDEN', 'Reactive Power CF Scaling Denominator Register. The content of this register is used in the denominator of the VARCF output scaling.', 'R/W', 12, 'U', 0x3f)),
(0x7e, ('CHKSUM', 'Checksum Register. The content of this register represents the sum of all the ones in the last register read from the SPI port.', 'R', 8, 'U', None)),
(0x7f, ('Version', 'Version of the Die.', 'R', 8, 'U', None)),
])

View File

@ -0,0 +1,127 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2017 Karl Palsson <karlp@etactica.com>
##
## Permission is hereby granted, free of charge, to any person obtaining a copy
## of this software and associated documentation files (the "Software"), to deal
## in the Software without restriction, including without limitation the rights
## to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
## copies of the Software, and to permit persons to whom the Software is
## furnished to do so, subject to the following conditions:
##
## The above copyright notice and this permission notice shall be included in all
## copies or substantial portions of the Software.
##
## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
## SOFTWARE.
import math
import sigrokdecode as srd
from .lists import *
class Decoder(srd.Decoder):
api_version = 2
id = 'ade77xx'
name = 'ADE77xx'
longname = 'Analog Devices ADE77xx'
desc = 'Poly phase multifunction energy metering IC protocol.'
license = 'mit'
inputs = ['spi']
outputs = ['ade77xx']
annotations = (
('read', 'Register read commands'),
('write', 'Register write commands'),
('warning', 'Warnings'),
)
annotation_rows = (
('read', 'Read', (0,)),
('write', 'Write', (1,)),
('warnings', 'Warnings', (2,)),
)
def reset(self):
self.expected = 0
self.mosi_bytes, self.miso_bytes = [], []
def __init__(self):
self.ss_cmd, self.es_cmd = 0, 0
self.reset()
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
def putx(self, data):
self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
def put_warn(self, pos, msg):
self.put(pos[0], pos[1], self.out_ann, [2, [msg]])
def decode(self, ss, es, data):
ptype = data[0]
if ptype == 'CS-CHANGE':
# Bear in mind, that CS is optional according to the datasheet.
# If we transition high mid-stream, toss out our data and restart.
cs_old, cs_new = data[1:]
if cs_old is not None and cs_old == 0 and cs_new == 1:
if len(self.mosi_bytes) > 0 and len(self.mosi_bytes[1:]) < self.expected:
# Mark short read/write for reg at least!
self.es_cmd = es
write, reg = self.cmd & 0x80, self.cmd & 0x7f
rblob = regs.get(reg)
idx = 1 if write else 0
self.putx([idx, ['%s: %s' % (rblob[0], "SHORT")]])
self.put_warn([self.ss_cmd, es], "Short transfer!")
self.reset()
return
# Don't care about anything else.
if ptype != 'DATA':
return
mosi, miso = data[1:]
if len(self.mosi_bytes) == 0:
self.ss_cmd = ss
self.mosi_bytes.append(mosi)
self.miso_bytes.append(miso)
# A transfer is 2-4 bytes, (command + 1..3 byte reg).
if len(self.mosi_bytes) < 2:
return
self.cmd = self.mosi_bytes[0]
write, reg = self.cmd & 0x80, self.cmd & 0x7f
rblob = regs.get(reg)
if not rblob:
# If you don't have CS, this will _destroy_ comms!
self.put_warn([self.ss_cmd, es], 'Unknown register!')
return
self.expected = math.ceil(rblob[3] / 8)
if len(self.mosi_bytes[1:]) != self.expected:
return
valo, vali = None, None
self.es_cmd = es
if self.expected == 3:
valo = self.mosi_bytes[1] << 16 | self.mosi_bytes[2] << 8 | \
self.mosi_bytes[3]
vali = self.miso_bytes[1] << 16 | self.miso_bytes[2] << 8 | \
self.miso_bytes[3]
elif self.expected == 2:
valo = self.mosi_bytes[1] << 8 | self.mosi_bytes[2]
vali = self.miso_bytes[1] << 8 | self.miso_bytes[2]
elif self.expected == 1:
valo = self.mosi_bytes[1]
vali = self.miso_bytes[1]
if write:
self.putx([1, ['%s: %#x' % (rblob[0], valo)]])
else:
self.putx([0, ['%s: %#x' % (rblob[0], vali)]])
self.reset()

View File

@ -0,0 +1,29 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2017 Joel Holdsworth <joel@airwebreathe.org.uk>
##
## 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 decoder stacks on top of the 'spi' PD and decodes the protocol spoken
by the Analog Devices ADF4350 and ADF4351 RF synthesizer chips.
Details:
http://www.analog.com/media/en/technical-documentation/data-sheets/ADF4350.pdf
http://www.analog.com/media/en/technical-documentation/data-sheets/ADF4351.pdf
'''
from .pd import Decoder

View File

@ -0,0 +1,140 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2017 Joel Holdsworth <joel@airwebreathe.org.uk>
##
## 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 3 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
def disabled_enabled(v):
return ['Disabled', 'Enabled'][v]
def output_power(v):
return '%+ddBm' % [-4, -1, 2, 5][v]
regs = {
# reg: name offset width parser
0: [
('FRAC', 3, 12, None),
('INT', 15, 16, lambda v: 'Not Allowed' if v < 32 else v)
],
1: [
('MOD', 3, 12, None),
('Phase', 15, 12, None),
('Prescalar', 27, 1, lambda v: ['4/5', '8/9'][v]),
('Phase Adjust', 28, 1, lambda v: ['Off', 'On'][v]),
],
2: [
('Counter Reset', 3, 1, disabled_enabled),
('Charge Pump Three-State', 4, 1, disabled_enabled),
('Power-Down', 5, 1, disabled_enabled),
('PD Polarity', 6, 1, lambda v: ['Negative', 'Positive'][v]),
('LDP', 7, 1, lambda v: ['10ns', '6ns'][v]),
('LDF', 8, 1, lambda v: ['FRAC-N', 'INT-N'][v]),
('Charge Pump Current Setting', 9, 4, lambda v: '%0.2fmA @ 5.1kΩ' %
[0.31, 0.63, 0.94, 1.25, 1.56, 1.88, 2.19, 2.50,
2.81, 3.13, 3.44, 3.75, 4.06, 4.38, 4.69, 5.00][v]),
('Double Buffer', 13, 1, disabled_enabled),
('R Counter', 14, 10, None),
('RDIV2', 24, 1, disabled_enabled),
('Reference Doubler', 25, 1, disabled_enabled),
('MUXOUT', 26, 3, lambda v:
['Three-State Output', 'DVdd', 'DGND', 'R Counter Output', 'N Divider Output',
'Analog Lock Detect', 'Digital Lock Detect', 'Reserved'][v]),
('Low Noise and Low Spur Modes', 29, 2, lambda v:
['Low Noise Mode', 'Reserved', 'Reserved', 'Low Spur Mode'][v])
],
3: [
('Clock Divider', 3, 12, None),
('Clock Divider Mode', 15, 2, lambda v:
['Clock Divider Off', 'Fast Lock Enable', 'Resync Enable', 'Reserved'][v]),
('CSR Enable', 18, 1, disabled_enabled),
('Charge Cancellation', 21, 1, disabled_enabled),
('ABP', 22, 1, lambda v: ['6ns (FRAC-N)', '3ns (INT-N)'][v]),
('Band Select Clock Mode', 23, 1, lambda v: ['Low', 'High'][v])
],
4: [
('Output Power', 3, 2, output_power),
('Output Enable', 5, 1, disabled_enabled),
('AUX Output Power', 6, 2, output_power),
('AUX Output Select', 8, 1, lambda v: ['Divided Output', 'Fundamental'][v]),
('AUX Output Enable', 9, 1, disabled_enabled),
('MTLD', 10, 1, disabled_enabled),
('VCO Power-Down', 11, 1, lambda v:
'VCO Powered ' + ('Down' if v == 1 else 'Up')),
('Band Select Clock Divider', 12, 8, None),
('RF Divider Select', 20, 3, lambda v: '÷' + str(2**v)),
('Feedback Select', 23, 1, lambda v: ['Divided', 'Fundamental'][v]),
],
5: [
('LD Pin Mode', 22, 2, lambda v:
['Low', 'Digital Lock Detect', 'Low', 'High'][v])
]
}
ANN_REG = 0
class Decoder(srd.Decoder):
api_version = 2
id = 'adf435x'
name = 'ADF435x'
longname = 'Analog Devices ADF4350/1'
desc = 'Wideband synthesizer with integrated VCO.'
license = 'gplv3+'
inputs = ['spi']
outputs = ['adf435x']
annotations = (
# Sent from the host to the chip.
('register', 'Register written to the device'),
)
annotation_rows = (
('registers', 'Register writes', (ANN_REG,)),
)
def __init__(self):
self.bits = []
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
def decode_bits(self, offset, width):
return (sum([(1 << i) if self.bits[offset + i][0] else 0 for i in range(width)]),
(self.bits[offset + width - 1][1], self.bits[offset][2]))
def decode_field(self, name, offset, width, parser):
val, pos = self.decode_bits(offset, width)
self.put(pos[0], pos[1], self.out_ann, [ANN_REG,
['%s: %s' % (name, parser(val) if parser else str(val))]])
return val
def decode(self, ss, es, data):
ptype, data1, data2 = data
if ptype == 'CS-CHANGE':
if data1 == 1:
if len(self.bits) == 32:
reg_value, reg_pos = self.decode_bits(0, 3)
self.put(reg_pos[0], reg_pos[1], self.out_ann, [ANN_REG,
['Register: %d' % reg_value, 'Reg: %d' % reg_value,
'[%d]' % reg_value]])
if reg_value < len(regs):
field_descs = regs[reg_value]
for field_desc in field_descs:
field = self.decode_field(*field_desc)
self.bits = []
if ptype == 'BITS':
self.bits = data1 + self.bits

View File

@ -0,0 +1,25 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Fabian J. Stumpf <sigrok@fabianstumpf.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/>.
##
'''
DMX512 (Digital MultipleX 512) is a protocol based on RS485, used to control
professional lighting fixtures.
'''
from .pd import Decoder

View File

@ -0,0 +1,170 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Fabian J. Stumpf <sigrok@fabianstumpf.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
class Decoder(srd.Decoder):
api_version = 2
id = 'dmx512'
name = 'DMX512'
longname = 'Digital MultipleX 512'
desc = 'Professional lighting control protocol.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['dmx512']
channels = (
{'id': 'dmx', 'name': 'DMX data', 'desc': 'Any DMX data line'},
)
annotations = (
('bit', 'Bit'),
('break', 'Break'),
('mab', 'Mark after break'),
('startbit', 'Start bit'),
('stopbits', 'Stop bit'),
('startcode', 'Start code'),
('channel', 'Channel'),
('interframe', 'Interframe'),
('interpacket', 'Interpacket'),
('data', 'Data'),
('error', 'Error'),
)
annotation_rows = (
('name', 'Logical', (1, 2, 5, 6, 7, 8)),
('data', 'Data', (9,)),
('bits', 'Bits', (0, 3, 4)),
('errors', 'Errors', (10,)),
)
def __init__(self):
self.samplerate = None
self.sample_usec = None
self.samplenum = -1
self.run_start = -1
self.run_bit = 0
self.state = 'FIND BREAK'
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value
self.sample_usec = 1 / value * 1000000
self.skip_per_bit = int(4 / self.sample_usec)
def putr(self, data):
self.put(self.run_start, self.samplenum, self.out_ann, data)
def decode(self, ss, es, data):
if not self.samplerate:
raise SamplerateError('Cannot decode without samplerate.')
for (self.samplenum, pins) in data:
data.itercnt += 1
# Seek for an interval with no state change with a length between
# 88 and 1000000 us (BREAK).
if self.state == 'FIND BREAK':
if self.run_bit == pins[0]:
continue
runlen = (self.samplenum - self.run_start) * self.sample_usec
if runlen > 88 and runlen < 1000000:
self.putr([1, ['Break']])
self.bit_break = self.run_bit
self.state = 'MARK MAB'
self.channel = 0
elif runlen >= 1000000:
# Error condition.
self.putr([10, ['Invalid break length']])
self.run_bit = pins[0]
self.run_start = self.samplenum
# Directly following the BREAK is the MARK AFTER BREAK.
elif self.state == 'MARK MAB':
if self.run_bit == pins[0]:
continue
self.putr([2, ['MAB']])
self.state = 'READ BYTE'
self.channel = 0
self.bit = 0
self.aggreg = pins[0]
self.run_start = self.samplenum
# Mark and read a single transmitted byte
# (start bit, 8 data bits, 2 stop bits).
elif self.state == 'READ BYTE':
self.next_sample = self.run_start + (self.bit + 1) * self.skip_per_bit
self.aggreg += pins[0]
if self.samplenum != self.next_sample:
continue
bit_value = 0 if round(self.aggreg/self.skip_per_bit) == self.bit_break else 1
if self.bit == 0:
self.byte = 0
self.putr([3, ['Start bit']])
if bit_value != 0:
# (Possibly) invalid start bit, mark but don't fail.
self.put(self.samplenum, self.samplenum,
self.out_ann, [10, ['Invalid start bit']])
elif self.bit >= 9:
self.put(self.samplenum - self.skip_per_bit,
self.samplenum, self.out_ann, [4, ['Stop bit']])
if bit_value != 1:
# Invalid stop bit, mark.
self.put(self.samplenum, self.samplenum,
self.out_ann, [10, ['Invalid stop bit']])
if self.bit == 10:
# On invalid 2nd stop bit, search for new break.
self.run_bit = pins[0]
self.state = 'FIND BREAK'
else:
# Label and process one bit.
self.put(self.samplenum - self.skip_per_bit,
self.samplenum, self.out_ann, [0, [str(bit_value)]])
self.byte |= bit_value << (self.bit - 1)
# Label a complete byte.
if self.bit == 10:
if self.channel == 0:
d = [5, ['Start code']]
else:
d = [6, ['Channel ' + str(self.channel)]]
self.put(self.run_start, self.next_sample, self.out_ann, d)
self.put(self.run_start + self.skip_per_bit,
self.next_sample - 2 * self.skip_per_bit,
self.out_ann, [9, [str(self.byte) + ' / ' + \
str(hex(self.byte))]])
# Continue by scanning the IFT.
self.channel += 1
self.run_start = self.samplenum
self.run_bit = pins[0]
self.state = 'MARK IFT'
self.aggreg = pins[0]
self.bit += 1
# Mark the INTERFRAME-TIME between bytes / INTERPACKET-TIME between packets.
elif self.state == 'MARK IFT':
if self.run_bit == pins[0]:
continue
if self.channel > 512:
self.putr([8, ['Interpacket']])
self.state = 'FIND BREAK'
self.run_bit = pins[0]
self.run_start = self.samplenum
else:
self.putr([7, ['Interframe']])
self.state = 'READ BYTE'
self.bit = 0
self.run_start = self.samplenum

View File

@ -0,0 +1,25 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012 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/>.
##
'''
This decoder stacks on top of the 'onewire_network' PD and decodes the
Maxim DS28EA00 1-Wire digital thermometer protocol.
'''
from .pd import Decoder

View File

@ -0,0 +1,89 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2012 Iztok Jeras <iztok.jeras@gmail.com>
##
## 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
# Dictionary of FUNCTION commands and their names.
command = {
# Scratchpad
0x4e: 'Write scratchpad',
0xbe: 'Read scratchpad',
0x48: 'Copy scratchpad',
# Thermometer
0x44: 'Convert temperature',
0xb4: 'Read power mode',
0xb8: 'Recall EEPROM',
0xf5: 'PIO access read',
0xA5: 'PIO access write',
0x99: 'Chain',
}
class Decoder(srd.Decoder):
api_version = 2
id = 'ds28ea00'
name = 'DS28EA00'
longname = 'Maxim DS28EA00 1-Wire digital thermometer'
desc = '1-Wire digital thermometer with Sequence Detect and PIO.'
license = 'gplv2+'
inputs = ['onewire_network']
outputs = ['ds28ea00']
annotations = (
('text', 'Human-readable text'),
)
def __init__(self):
self.trn_beg = 0
self.trn_end = 0
self.state = 'ROM'
self.rom = 0x0000000000000000
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
def putx(self, data):
self.put(self.ss, self.es, self.out_ann, data)
def decode(self, ss, es, data):
code, val = data
self.ss, self.es = ss, es
# State machine.
if code == 'RESET/PRESENCE':
self.putx([0, ['Reset/presence: %s'
% ('true' if val else 'false')]])
self.state = 'ROM'
elif code == 'ROM':
self.rom = val
self.putx([0, ['ROM: 0x%016x' % (val)]])
self.state = 'COMMAND'
elif code == 'DATA':
if self.state == 'COMMAND':
if val not in command:
self.putx([0, ['Unrecognized command: 0x%02x' % val]])
return
self.putx([0, ['Function command: 0x%02x \'%s\''
% (val, command[val])]])
self.state = command[val].upper()
elif self.state == 'READ SCRATCHPAD':
self.putx([0, ['Scratchpad data: 0x%02x' % val]])
elif self.state == 'CONVERT TEMPERATURE':
self.putx([0, ['Temperature conversion status: 0x%02x' % val]])
elif self.state in [s.upper() for s in command.values()]:
self.putx([0, ['TODO \'%s\': 0x%02x' % (self.state, val)]])

View File

@ -0,0 +1,24 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2015 Jeremy Swanson <jeremy@rakocontrols.com>
##
## 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/>.
##
'''
DSI is a biphase/manchester based lighting control protocol.
'''
from .pd import Decoder

View File

@ -0,0 +1,164 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2015 Jeremy Swanson <jeremy@rakocontrols.com>
##
## 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
class SamplerateError(Exception):
pass
class Decoder(srd.Decoder):
api_version = 2
id = 'dsi'
name = 'DSI'
longname = 'Digital Serial Interface'
desc = 'DSI lighting control protocol.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['dsi']
channels = (
{'id': 'dsi', 'name': 'DSI', 'desc': 'DSI data line'},
)
options = (
{'id': 'polarity', 'desc': 'Polarity', 'default': 'active-high',
'values': ('active-low', 'active-high')},
)
annotations = (
('bit', 'Bit'),
('startbit', 'Startbit'),
('Level', 'Dimmer level'),
('raw', 'Raw data'),
)
annotation_rows = (
('bits', 'Bits', (0,)),
('raw', 'Raw Data',(3,)),
('fields', 'Fields', (1, 2,)),
)
def __init__(self):
self.samplerate = None
self.samplenum = None
self.edges, self.bits, self.ss_es_bits = [], [], []
self.state = 'IDLE'
self.nextSamplePoint = None
self.nextSample = None
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
self.old_dsi = 1 if self.options['polarity'] == 'active-low' else 0
def metadata(self, key, value):
if key == srd.SRD_CONF_SAMPLERATE:
self.samplerate = value
# One bit: 1666.7us (one half low, one half high).
# This is how many samples are in 1TE.
self.halfbit = int((self.samplerate * 0.0016667) / 2.0)
def putb(self, bit1, bit2, data):
ss, es = self.ss_es_bits[bit1][0], self.ss_es_bits[bit2][1]
self.put(ss, es, self.out_ann, data)
def handle_bits(self, length):
a, c, f, g, b = 0, 0, 0, 0, self.bits
# Individual raw bits.
for i in range(length):
if i == 0:
ss = max(0, self.bits[0][0])
else:
ss = self.ss_es_bits[i - 1][1]
es = self.bits[i][0] + (self.halfbit * 2)
self.ss_es_bits.append([ss, es])
self.putb(i, i, [0, ['%d' % self.bits[i][1]]])
# Bits[0:0]: Startbit
s = ['Startbit: %d' % b[0][1], 'ST: %d' % b[0][1], 'ST', 'S', 'S']
self.putb(0, 0, [1, s])
self.putb(0, 0, [3, s])
# Bits[1:8]
for i in range(8):
f |= (b[1 + i][1] << (7 - i))
g = f / 2.55
if length == 9: # BACKWARD Frame
s = ['Data: %02X' % f, 'Dat: %02X' % f,
'Dat: %02X' % f, 'D: %02X' % f, 'D']
self.putb(1, 8, [3, s])
s = ['Level: %d%%' % g, 'Lev: %d%%' % g,
'Lev: %d%%' % g, 'L: %d' % g, 'D']
self.putb(1, 8, [2, s])
return
def reset_decoder_state(self):
self.edges, self.bits, self.ss_es_bits = [], [], []
self.state = 'IDLE'
def decode(self, ss, es, data):
if not self.samplerate:
raise SamplerateError('Cannot decode without samplerate.')
bit = 0;
for (self.samplenum, pins) in data:
self.dsi = pins[0]
data.itercnt += 1
if self.options['polarity'] == 'active-high':
self.dsi ^= 1 # Invert.
# State machine.
if self.state == 'IDLE':
# Wait for any edge (rising or falling).
if self.old_dsi == self.dsi:
continue
# Add in the first half of the start bit.
self.edges.append(self.samplenum - int(self.halfbit))
self.edges.append(self.samplenum)
# Start bit is 0->1.
self.phase0 = self.dsi ^ 1
self.state = 'PHASE1'
self.old_dsi = self.dsi
# Get the next sample point.
# self.nextSamplePoint = self.samplenum + int(self.halfbit / 2)
self.old_dsi = self.dsi
# bit = self.dsi
continue
# if(self.samplenum == self.nextSamplePoint):
# bit = self.dsi
# continue
if self.old_dsi != self.dsi:
self.edges.append(self.samplenum)
elif self.samplenum == (self.edges[-1] + int(self.halfbit * 1.5)):
self.edges.append(self.samplenum - int(self.halfbit * 0.5))
else:
continue
bit = self.old_dsi
if self.state == 'PHASE0':
self.phase0 = bit
self.state = 'PHASE1'
elif self.state == 'PHASE1':
if (bit == 1) and (self.phase0 == 1): # Stop bit
if len(self.bits) == 17 or len(self.bits) == 9:
# Forward or Backward
self.handle_bits(len(self.bits))
self.reset_decoder_state() # Reset upon errors.
continue
else:
self.bits.append([self.edges[-3], bit])
self.state = 'PHASE0'
# self.nextSamplePoint = self.edges[-1] + int(self.halfbit / 2)
self.old_dsi = self.dsi

View File

@ -0,0 +1,32 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2017 Kevin Redon <kingkevin@cuvoodoo.info>
##
## 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 decoder stacks on top of the 'microwire' PD and decodes the 93Cxx EEPROM
specific instructions.
The implemented instructions come from the STMicroelectronics M93Cx6 EEPROM
datasheet. They are compatible with the Atmel AT93Cxx EEPROM with slightly
different names.
Warning: Other EEPROMs using Microwire might have different operation codes
and instructions.
'''
from .pd import Decoder

View File

@ -0,0 +1,137 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2017 Kevin Redon <kingkevin@cuvoodoo.info>
##
## 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
class Decoder(srd.Decoder):
api_version = 2
id = 'eeprom93cxx'
name = '93Cxx EEPROM'
longname = '93Cxx Microwire EEPROM'
desc = '93Cxx series Microwire EEPROM protocol.'
license = 'gplv2+'
inputs = ['microwire']
outputs = ['eeprom93cxx']
options = (
{'id': 'addresssize', 'desc': 'Address size', 'default': 8},
{'id': 'wordsize', 'desc': 'Word size', 'default': 16},
)
annotations = (
('si-data', 'SI data'),
('so-data', 'SO data'),
('warning', 'Warning'),
)
annotation_rows = (
('data', 'Data', (0, 1)),
('warnings', 'Warnings', (2,)),
)
def __init__(self):
self.frame = []
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
self.addresssize = self.options['addresssize']
self.wordsize = self.options['wordsize']
def put_address(self, data):
# Get address (MSb first).
a = 0
for b in range(len(data)):
a += (data[b].si << (len(data) - b - 1))
self.put(data[0].ss, data[-1].es, self.out_ann,
[0, ['Address: 0x%x' % a, 'Addr: 0x%x' % a, '0x%x' % a]])
def put_word(self, si, data):
# Decode word (MSb first).
word = 0
for b in range(len(data)):
d = data[b].si if si else data[b].so
word += (d << (len(data) - b - 1))
idx = 0 if si else 1
self.put(data[0].ss, data[-1].es,
self.out_ann, [idx, ['Data: 0x%x' % word, '0x%x' % word]])
def decode(self, ss, es, data):
if len(data) < (2 + self.addresssize):
self.put(ss, es, self.out_ann, [2, ['Not enough packet bits']])
return
opcode = (data[0].si << 1) + (data[1].si << 0)
if opcode == 2:
# READ instruction.
self.put(data[0].ss, data[1].es,
self.out_ann, [0, ['Read word', 'READ']])
self.put_address(data[2:2 + self.addresssize])
# Get all words.
word_start = 2 + self.addresssize
while len(data) - word_start > 0:
# Check if there are enough bits for a word.
if len(data) - word_start < self.wordsize:
self.put(data[word_start].ss, data[len(data) - 1].es,
self.out_ann, [2, ['Not enough word bits']])
break
self.put_word(False, data[word_start:word_start + self.wordsize])
# Go to next word.
word_start += self.wordsize
elif opcode == 1:
# WRITE instruction.
self.put(data[0].ss, data[1].es,
self.out_ann, [0, ['Write word', 'WRITE']])
self.put_address(data[2:2 + self.addresssize])
# Get word.
if len(data) < 2 + self.addresssize + self.wordsize:
self.put(data[2 + self.addresssize].ss,
data[len(data) - 1].ss,
self.out_ann, [2, ['Not enough word bits']])
else:
self.put_word(True, data[2 + self.addresssize:2 + self.addresssize + self.wordsize])
elif opcode == 3:
# ERASE instruction.
self.put(data[0].ss, data[1].es,
self.out_ann, [0, ['Erase word', 'ERASE']])
self.put_address(data[2:2 + self.addresssize])
elif opcode == 0:
if data[2].si == 1 and data[3].si == 1:
# WEN instruction.
self.put(data[0].ss, data[2 + self.addresssize - 1].es,
self.out_ann, [0, ['Write enable', 'WEN']])
elif data[2].si == 0 and data[3].si == 0:
# WDS instruction.
self.put(data[0].ss, data[2 + self.addresssize - 1].es,
self.out_ann, [0, ['Write disable', 'WDS']])
elif data[2].si == 1 and data[3].si == 0:
# ERAL instruction.
self.put(data[0].ss, data[2 + self.addresssize - 1].es,
self.out_ann, [0, ['Erase all memory',
'Erase all', 'ERAL']])
elif data[2].si == 0 and data[3].si == 1:
# WRAL instruction.
self.put(data[0].ss, data[2 + self.addresssize - 1].es,
self.out_ann, [0, ['Write all memory',
'Write all', 'WRAL']])
# Get word.
if len(data) < 2 + self.addresssize + self.wordsize:
self.put(data[2 + self.addresssize].ss,
data[len(data) - 1].ss,
self.out_ann, [2, ['Not enough word bits']])
else:
self.put_word(True, data[2 + self.addresssize:2 + self.addresssize + self.wordsize])

View File

@ -0,0 +1,24 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Rudolf Reuter <reuterru@arcor.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/>.
##
'''
This protocol decoder can decode the GPIB (IEEE-488) protocol.
'''
from .pd import Decoder

View File

@ -0,0 +1,188 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Rudolf Reuter <reuterru@arcor.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
class Decoder(srd.Decoder):
api_version = 2
id = 'gpib'
name = 'GPIB'
longname = 'General Purpose Interface Bus'
desc = 'IEEE-488 GPIB / HPIB protocol.'
license = 'gplv2+'
inputs = ['logic']
outputs = ['gpib']
channels = (
{'id': 'dio1' , 'name': 'DIO1', 'desc': 'Data I/O bit 1'},
{'id': 'dio2' , 'name': 'DIO2', 'desc': 'Data I/O bit 2'},
{'id': 'dio3' , 'name': 'DIO3', 'desc': 'Data I/O bit 3'},
{'id': 'dio4' , 'name': 'DIO4', 'desc': 'Data I/O bit 4'},
{'id': 'dio5' , 'name': 'DIO5', 'desc': 'Data I/O bit 5'},
{'id': 'dio6' , 'name': 'DIO6', 'desc': 'Data I/O bit 6'},
{'id': 'dio7' , 'name': 'DIO7', 'desc': 'Data I/O bit 7'},
{'id': 'dio8' , 'name': 'DIO8', 'desc': 'Data I/O bit 8'},
{'id': 'eoi', 'name': 'EOI', 'desc': 'End or identify'},
{'id': 'dav', 'name': 'DAV', 'desc': 'Data valid'},
{'id': 'nrfd', 'name': 'NRFD', 'desc': 'Not ready for data'},
{'id': 'ndac', 'name': 'NDAC', 'desc': 'Not data accepted'},
{'id': 'ifc', 'name': 'IFC', 'desc': 'Interface clear'},
{'id': 'srq', 'name': 'SRQ', 'desc': 'Service request'},
{'id': 'atn', 'name': 'ATN', 'desc': 'Attention'},
{'id': 'ren', 'name': 'REN', 'desc': 'Remote enable'},
)
options = (
{'id': 'sample_total', 'desc': 'Total number of samples', 'default': 0},
)
annotations = (
('items', 'Items'),
('gpib', 'DAT/CMD'),
('eoi', 'EOI'),
)
annotation_rows = (
('bytes', 'Bytes', (0,)),
('gpib', 'DAT/CMD', (1,)),
('eoi', 'EOI', (2,)),
)
def __init__(self):
self.olddav = None
self.items = []
self.itemcount = 0
self.saved_item = None
self.saved_ATN = False
self.saved_EOI = False
self.samplenum = 0
self.oldpins = None
self.ss_item = self.es_item = None
self.first = True
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
def putb(self, data):
self.put(self.ss_item, self.es_item, self.out_ann, data)
def handle_bits(self, datapins):
dbyte = 0x20
dATN = False
item2 = False
dEOI = False
item3 = False
# If this is the first item in a word, save its sample number.
if self.itemcount == 0:
self.ss_word = self.samplenum
# Get the bits for this item.
item = 0
for i in range(8):
item |= datapins[i] << i
item = item ^ 0xff # Invert data byte.
self.items.append(item)
self.itemcount += 1
if datapins[14] == 0:
item2 = True
if datapins[8] == 0:
item3 = True
if self.first:
# Save the start sample and item for later (no output yet).
self.ss_item = self.samplenum
self.first = False
self.saved_item = item
self.saved_ATN = item2
self.saved_EOI = item3
else:
# Output the saved item.
dbyte = self.saved_item
dATN = self.saved_ATN
dEOI = self.saved_EOI
self.es_item = self.samplenum
self.putb([0, ['%02X' % self.saved_item]])
# Encode item byte to GPIB convention.
self.strgpib = ' '
if dATN: # ATN, decode commands.
if dbyte == 0x01: self.strgpib = 'GTL'
if dbyte == 0x04: self.strgpib = 'SDC'
if dbyte == 0x05: self.strgpib = 'PPC'
if dbyte == 0x08: self.strgpib = 'GET'
if dbyte == 0x09: self.strgpib = 'TCT'
if dbyte == 0x11: self.strgpib = 'LLO'
if dbyte == 0x14: self.strgpib = 'DCL'
if dbyte == 0x15: self.strgpib = 'PPU'
if dbyte == 0x18: self.strgpib = 'SPE'
if dbyte == 0x19: self.strgpib = 'SPD'
if dbyte == 0x3f: self.strgpib = 'UNL'
if dbyte == 0x5f: self.strgpib = 'UNT'
if dbyte > 0x1f and dbyte < 0x3f: # Address Listener.
self.strgpib = 'L' + chr(dbyte + 0x10)
if dbyte > 0x3f and dbyte < 0x5f: # Address Talker
self.strgpib = 'T' + chr(dbyte - 0x10)
else:
if dbyte > 0x1f and dbyte < 0x7f:
self.strgpib = chr(dbyte)
if dbyte == 0x0a:
self.strgpib = 'LF'
if dbyte == 0x0d:
self.strgpib = 'CR'
self.putb([1, [self.strgpib]])
self.strEOI = ' '
if dEOI:
self.strEOI = 'EOI'
self.putb([2, [self.strEOI]])
self.ss_item = self.samplenum
self.saved_item = item
self.saved_ATN = item2
self.saved_EOI = item3
if self.itemcount < 16:
return
self.itemcount, self.items = 0, []
def find_falling_dav_edge(self, dav, datapins):
# Ignore sample if the DAV pin hasn't changed.
if dav == self.olddav:
return
self.olddav = dav
# Sample on falling DAV edge.
if dav == 1:
return
# Found the correct DAV edge, now get the bits.
self.handle_bits(datapins)
def decode(self, ss, es, data):
lsn = self.options['sample_total']
data.itercnt += 1
for (self.samplenum, pins) in data:
if lsn > 0:
if (lsn - self.samplenum) == 1: # Show the last data word.
self.handle_bits(pins)
# Ignore identical samples early on (for performance reasons).
if self.oldpins == pins:
continue
self.oldpins = pins
self.find_falling_dav_edge(pins[9], pins)

View File

@ -0,0 +1,28 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Robert Bosch Car Multimedia GmbH
## Authors: Oleksij Rempel
## <fixed-term.Oleksij.Rempel@de.bosch.com>
## <linux@rempel-privat.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/>.
##
'''
This decoder stacks on top of the 'spi' PD and decodes the Bosch
SSI32 protocol.
'''
from .pd import Decoder

View File

@ -0,0 +1,123 @@
##
## This file is part of the libsigrokdecode project.
##
## Copyright (C) 2016 Robert Bosch Car Multimedia GmbH
## Authors: Oleksij Rempel
## <fixed-term.Oleksij.Rempel@de.bosch.com>
## <linux@rempel-privat.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
class Decoder(srd.Decoder):
api_version = 2
id = 'ssi32'
name = 'SSI32'
longname = 'Synchronous Serial Interface (32bit)'
desc = 'Synchronous Serial Interface (32bit) protocol.'
license = 'gplv2+'
inputs = ['spi']
outputs = ['ssi32']
options = (
{'id': 'msgsize', 'desc': 'Message size', 'default': 64},
)
annotations = (
('ctrl-tx', 'CTRL TX'),
('ack-tx', 'ACK TX'),
('ctrl-rx', 'CTRL RX'),
('ack-rx', 'ACK RX'),
)
annotation_rows = (
('tx', 'TX', (0, 1)),
('rx', 'RX', (2, 3)),
)
def __init__(self):
self.ss_cmd, self.es_cmd = 0, 0
self.mosi_bytes = []
self.miso_bytes = []
self.es_array = []
self.rx_size = 0
self.tx_size = 0
def start(self):
self.out_ann = self.register(srd.OUTPUT_ANN)
def putx(self, data):
self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
def reset(self):
self.mosi_bytes = []
self.miso_bytes = []
self.es_array = []
def handle_ack(self):
# Only first byte should have ACK data, other 3 bytes are reserved.
self.es_cmd = self.es_array[0]
self.putx([1, ['> ACK:0x%02x' % (self.mosi_bytes[0])]])
self.putx([3, ['< ACK:0x%02x' % (self.miso_bytes[0])]])
def handle_ctrl(self):
mosi = miso = ''
self.tx_size = self.mosi_bytes[2]
self.rx_size = self.miso_bytes[2]
if self.tx_size > 0:
mosi = ', DATA:0x' + ''.join(format(x, '02x') for x in self.mosi_bytes[4:self.tx_size + 4])
if self.rx_size > 0:
miso = ', DATA:0x' + ''.join(format(x, '02x') for x in self.miso_bytes[4:self.rx_size + 4])
self.es_cmd = self.es_array[self.tx_size + 3]
self.putx([0, ['> CTRL:0x%02x, LUN:0x%02x, SIZE:0x%02x, CRC:0x%02x%s'
% (self.mosi_bytes[0], self.mosi_bytes[1],
self.mosi_bytes[2], self.mosi_bytes[3], mosi)]])
self.es_cmd = self.es_array[self.rx_size + 3]
self.putx([2, ['< CTRL:0x%02x, LUN:0x%02x, SIZE:0x%02x, CRC:0x%02x%s'
% (self.miso_bytes[0], self.miso_bytes[1],
self.miso_bytes[2], self.miso_bytes[3], miso)]])
def decode(self, ss, es, data):
ptype = data[0]
if ptype == 'CS-CHANGE':
self.reset()
return
# Don't care about anything else.
if ptype != 'DATA':
return
mosi, miso = data[1:]
self.ss, self.es = ss, es
if len(self.mosi_bytes) == 0:
self.ss_cmd = ss
self.mosi_bytes.append(mosi)
self.miso_bytes.append(miso)
self.es_array.append(es)
if self.mosi_bytes[0] & 0x80:
if len(self.mosi_bytes) < 4:
return
self.handle_ack()
self.reset()
else:
if len(self.mosi_bytes) < self.options['msgsize']:
return
self.handle_ctrl()
self.reset()